Commit f21c52ae authored by tsergeant's avatar tsergeant Committed by Commit bot

Add connection info popup within Page Info on Android.

Partial revert of 00e86ade

This is a revived version of WebsiteSettingsPopupLegacy, which contains
detailed connection and certificate information, similar to the desktop
website settings popup. The popup is accessed through a 'Details' link
in the page info popup.

BUG=425158

Review URL: https://codereview.chromium.org/1100283002

Cr-Commit-Position: refs/heads/master@{#327429}
parent 462f20fa
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2015 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<solid android:color="#ebebeb" />
<stroke android:width="1dp" android:color="#cccccc" />
</shape>
</item>
<item>
<shape>
<solid android:color="#ffffff" />
<stroke android:width="1dp" android:color="#d9d9d9"/>
</shape>
</item>
</selector>
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2015 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/connection_info_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null" />
<LinearLayout
android:id="@+id/connection_info_text_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="@dimen/connection_info_padding_thin" >
<TextView
android:id="@+id/connection_info_headline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/connection_info_padding_thin"
android:textStyle="bold"
android:textColor="@color/connection_info_popup_text" />
<TextView
android:id="@+id/connection_info_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/connection_info_popup_text" />
</LinearLayout>
</LinearLayout>
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:lineSpacingExtra="3dp" android:lineSpacingExtra="3dp"
android:paddingTop="12dp" android:paddingTop="12dp"
android:textColor="#444444" android:textColor="@color/website_settings_popup_text"
android:textSize="14sp" /> android:textSize="14sp" />
<Button <Button
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_toEndOf="@id/website_settings_permission_icon" android:layout_toEndOf="@id/website_settings_permission_icon"
android:textColor="#444444" android:textColor="@color/website_settings_popup_text"
android:textSize="14sp" android:textSize="14sp"
android:textStyle="bold" /> android:textStyle="bold" />
......
...@@ -28,10 +28,16 @@ ...@@ -28,10 +28,16 @@
<!-- App banner colors --> <!-- App banner colors -->
<color name="app_banner_install_button_bg">#689f38</color> <color name="app_banner_install_button_bg">#689f38</color>
<!-- Website Settings Popup colors --> <!-- Connection Info Popup colors -->
<color name="connection_info_popup_reset_cert_decisions_button">#000000</color>
<color name="connection_info_popup_text">#444444</color>
<!-- Website Settings Popup colors -->
<color name="website_settings_popup_text">#444444</color>
<color name="website_settings_popup_button_text">#444444</color> <color name="website_settings_popup_button_text">#444444</color>
<color name="website_settings_connection_broken_leading_text">#db4437</color> <color name="website_settings_connection_broken_leading_text">#db4437</color>
<color name="website_settings_popup_permission_spinner_text">#646464</color> <color name="website_settings_popup_permission_spinner_text">#646464</color>
<color name="website_settings_popup_text_link">#4285f4</color>
<!-- URL Emphasizer colors --> <!-- URL Emphasizer colors -->
<color name="url_emphasis_start_scheme_security_warning">#ffb000</color> <color name="url_emphasis_start_scheme_security_warning">#ffb000</color>
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
found in the LICENSE file. --> found in the LICENSE file. -->
<resources> <resources>
<!-- Connection info popup dimensions -->
<dimen name="connection_info_padding_wide">24dp</dimen>
<dimen name="connection_info_padding_thin">16dp</dimen>
<!-- Website Settings Popup Dimensions --> <!-- Website Settings Popup Dimensions -->
<dimen name="website_settings_popup_padding_sides">16dp</dimen> <dimen name="website_settings_popup_padding_sides">16dp</dimen>
<dimen name="website_settings_popup_button_height">36dp</dimen> <dimen name="website_settings_popup_button_height">36dp</dimen>
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Typeface;
import android.net.http.SslCertificate;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.TextView;
import org.chromium.chrome.R;
import java.io.ByteArrayInputStream;
import java.security.MessageDigest;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
/**
* UI component for displaying certificate information.
*/
class CertificateViewer implements OnItemSelectedListener {
private static final String X_509 = "X.509";
private final Context mContext;
private final ArrayList<LinearLayout> mViews;
private final ArrayList<String> mTitles;
private final int mPadding;
private CertificateFactory mCertificateFactory;
/**
* Show a dialog with the provided certificate information.
*
* @param context The context this view should display in.
* @param derData DER-encoded data representing a X509 certificate chain.
*/
public static void showCertificateChain(Context context, byte[][] derData) {
CertificateViewer viewer = new CertificateViewer(context);
viewer.showCertificateChain(derData);
}
private CertificateViewer(Context context) {
mContext = context;
mViews = new ArrayList<LinearLayout>();
mTitles = new ArrayList<String>();
mPadding = (int) context.getResources().getDimension(
R.dimen.connection_info_padding_wide) / 2;
}
// Show information about an array of DER-encoded data representing a X509 certificate chain.
// A spinner will be displayed allowing the user to select which certificate to display.
private void showCertificateChain(byte[][] derData) {
for (int i = 0; i < derData.length; i++) {
addCertificate(derData[i]);
}
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(mContext,
android.R.layout.simple_spinner_item,
mTitles);
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
LinearLayout dialogContainer = new LinearLayout(mContext);
dialogContainer.setOrientation(LinearLayout.VERTICAL);
TextView title = new TextView(mContext);
title.setText(R.string.certtitle);
title.setTextAppearance(mContext, android.R.style.TextAppearance_Large);
title.setTypeface(title.getTypeface(), Typeface.BOLD);
title.setPadding(mPadding, mPadding, mPadding, mPadding / 2);
dialogContainer.addView(title);
Spinner spinner = new Spinner(mContext);
spinner.setAdapter(arrayAdapter);
spinner.setOnItemSelectedListener(this);
spinner.setPadding(0, 0, mPadding / 2, mPadding);
dialogContainer.addView(spinner);
LinearLayout certContainer = new LinearLayout(mContext);
certContainer.setOrientation(LinearLayout.VERTICAL);
for (int i = 0; i < mViews.size(); ++i) {
LinearLayout certificateView = mViews.get(i);
if (i != 0) {
certificateView.setVisibility(LinearLayout.GONE);
}
certContainer.addView(certificateView);
}
ScrollView scrollView = new ScrollView(mContext);
scrollView.addView(certContainer);
dialogContainer.addView(scrollView);
showDialogForView(dialogContainer);
}
// Displays a dialog with scrolling for the given view.
private void showDialogForView(View view) {
Dialog dialog = new Dialog(mContext);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.addContentView(view,
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
dialog.show();
}
private void addCertificate(byte[] derData) {
try {
if (mCertificateFactory == null) {
mCertificateFactory = CertificateFactory.getInstance(X_509);
}
Certificate cert = mCertificateFactory.generateCertificate(
new ByteArrayInputStream(derData));
addCertificateDetails(cert, getDigest(derData, "SHA-256"), getDigest(derData, "SHA-1"));
} catch (CertificateException e) {
Log.e("CertViewer", "Error parsing certificate" + e.toString());
}
}
private void addCertificateDetails(Certificate cert, byte[] sha256Digest, byte[] sha1Digest) {
LinearLayout certificateView = new LinearLayout(mContext);
mViews.add(certificateView);
certificateView.setOrientation(LinearLayout.VERTICAL);
X509Certificate x509 = (X509Certificate) cert;
SslCertificate sslCert = new SslCertificate(x509);
mTitles.add(sslCert.getIssuedTo().getCName());
addSectionTitle(certificateView, nativeGetCertIssuedToText());
addItem(certificateView, nativeGetCertInfoCommonNameText(),
sslCert.getIssuedTo().getCName());
addItem(certificateView, nativeGetCertInfoOrganizationText(),
sslCert.getIssuedTo().getOName());
addItem(certificateView, nativeGetCertInfoOrganizationUnitText(),
sslCert.getIssuedTo().getUName());
addItem(certificateView, nativeGetCertInfoSerialNumberText(),
formatBytes(x509.getSerialNumber().toByteArray(), ':'));
addSectionTitle(certificateView, nativeGetCertIssuedByText());
addItem(certificateView, nativeGetCertInfoCommonNameText(),
sslCert.getIssuedBy().getCName());
addItem(certificateView, nativeGetCertInfoOrganizationText(),
sslCert.getIssuedBy().getOName());
addItem(certificateView, nativeGetCertInfoOrganizationUnitText(),
sslCert.getIssuedBy().getUName());
addSectionTitle(certificateView, nativeGetCertValidityText());
java.text.DateFormat dateFormat = DateFormat.getDateFormat(mContext);
addItem(certificateView, nativeGetCertIssuedOnText(),
dateFormat.format(sslCert.getValidNotBeforeDate()));
addItem(certificateView, nativeGetCertExpiresOnText(),
dateFormat.format(sslCert.getValidNotAfterDate()));
addSectionTitle(certificateView, nativeGetCertFingerprintsText());
addItem(certificateView, nativeGetCertSHA256FingerprintText(),
formatBytes(sha256Digest, ' '));
addItem(certificateView, nativeGetCertSHA1FingerprintText(),
formatBytes(sha1Digest, ' '));
}
private void addSectionTitle(LinearLayout certificateView, String label) {
TextView title = addLabel(certificateView, label);
title.setAllCaps(true);
}
private void addItem(LinearLayout certificateView, String label, String value) {
if (value.isEmpty()) return;
addLabel(certificateView, label);
addValue(certificateView, value);
}
private TextView addLabel(LinearLayout certificateView, String label) {
TextView t = new TextView(mContext);
t.setPadding(mPadding, mPadding / 2, mPadding, 0);
t.setText(label);
t.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
t.setTextColor(mContext.getResources().getColor(R.color.connection_info_popup_text));
certificateView.addView(t);
return t;
}
private void addValue(LinearLayout certificateView, String value) {
TextView t = new TextView(mContext);
t.setText(value);
t.setPadding(mPadding, 0, mPadding, mPadding / 2);
t.setTextColor(mContext.getResources().getColor(R.color.connection_info_popup_text));
certificateView.addView(t);
}
private static String formatBytes(byte[] bytes, char separator) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
sb.append(String.format("%02X", bytes[i]));
if (i != bytes.length - 1) {
sb.append(separator);
}
}
return sb.toString();
}
private static byte[] getDigest(byte[] bytes, String algorithm) {
try {
MessageDigest md = MessageDigest.getInstance(algorithm);
md.update(bytes);
return md.digest();
} catch (java.security.NoSuchAlgorithmException e) {
return null;
}
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
for (int i = 0; i < mViews.size(); ++i) {
mViews.get(i).setVisibility(
i == position ? LinearLayout.VISIBLE : LinearLayout.GONE);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
private static native String nativeGetCertIssuedToText();
private static native String nativeGetCertInfoCommonNameText();
private static native String nativeGetCertInfoOrganizationText();
private static native String nativeGetCertInfoSerialNumberText();
private static native String nativeGetCertInfoOrganizationUnitText();
private static native String nativeGetCertIssuedByText();
private static native String nativeGetCertValidityText();
private static native String nativeGetCertIssuedOnText();
private static native String nativeGetCertExpiresOnText();
private static native String nativeGetCertFingerprintsText();
private static native String nativeGetCertSHA256FingerprintText();
private static native String nativeGetCertSHA1FingerprintText();
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.provider.Browser;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import org.chromium.base.CalledByNative;
import org.chromium.chrome.R;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsObserver;
import java.net.URISyntaxException;
/**
* Java side of Android implementation of the website settings UI.
*/
public class ConnectionInfoPopup implements OnClickListener {
private static final String HELP_URL =
"http://www.google.com/support/chrome/bin/answer.py?answer=95617";
private static final int DESCRIPTION_TEXT_SIZE_SP = 12;
private final Context mContext;
private final Dialog mDialog;
private final LinearLayout mContainer;
private final WebContents mWebContents;
private final int mPaddingWide, mPaddingThin;
private final long mNativeConnectionInfoPopup;
private TextView mCertificateViewer, mMoreInfoLink;
private ViewGroup mCertificateLayout, mDescriptionLayout;
private Button mResetCertDecisionsButton;
private String mLinkUrl;
private ConnectionInfoPopup(Context context, WebContents webContents) {
mContext = context;
mWebContents = webContents;
mContainer = new LinearLayout(mContext);
mContainer.setOrientation(LinearLayout.VERTICAL);
mContainer.setBackgroundColor(Color.WHITE);
mPaddingWide = (int) context.getResources().getDimension(
R.dimen.connection_info_padding_wide);
mPaddingThin = (int) context.getResources().getDimension(
R.dimen.connection_info_padding_thin);
mContainer.setPadding(mPaddingWide, mPaddingWide, mPaddingWide,
mPaddingWide - mPaddingThin);
mDialog = new Dialog(mContext);
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mDialog.setCanceledOnTouchOutside(true);
// This needs to come after other member initialization.
mNativeConnectionInfoPopup = nativeInit(this, webContents);
final WebContentsObserver webContentsObserver =
new WebContentsObserver(mWebContents) {
@Override
public void navigationEntryCommitted() {
// If a navigation is committed (e.g. from in-page redirect), the data we're
// showing is stale so dismiss the dialog.
mDialog.dismiss();
}
};
mDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
assert mNativeConnectionInfoPopup != 0;
webContentsObserver.destroy();
nativeDestroy(mNativeConnectionInfoPopup);
}
});
}
/**
* Adds certificate section, which contains an icon, a headline, a
* description and a label for certificate info link.
*/
@CalledByNative
private void addCertificateSection(int enumeratedIconId, String headline, String description,
String label) {
View section = addSection(enumeratedIconId, headline, description);
assert mCertificateLayout == null;
mCertificateLayout = (ViewGroup) section.findViewById(R.id.connection_info_text_layout);
if (label != null && !label.isEmpty()) {
setCertificateViewer(label);
}
}
/**
* Adds Description section, which contains an icon, a headline, and a
* description. Most likely headline for description is empty
*/
@CalledByNative
private void addDescriptionSection(int enumeratedIconId, String headline, String description) {
View section = addSection(enumeratedIconId, headline, description);
assert mDescriptionLayout == null;
mDescriptionLayout = (ViewGroup) section.findViewById(R.id.connection_info_text_layout);
}
private View addSection(int enumeratedIconId, String headline, String description) {
View section = LayoutInflater.from(mContext).inflate(R.layout.connection_info,
null);
ImageView i = (ImageView) section.findViewById(R.id.connection_info_icon);
int drawableId = ResourceId.mapToDrawableId(enumeratedIconId);
i.setImageResource(drawableId);
TextView h = (TextView) section.findViewById(R.id.connection_info_headline);
h.setText(headline);
if (TextUtils.isEmpty(headline)) h.setVisibility(View.GONE);
TextView d = (TextView) section.findViewById(R.id.connection_info_description);
d.setText(description);
d.setTextSize(DESCRIPTION_TEXT_SIZE_SP);
if (TextUtils.isEmpty(description)) d.setVisibility(View.GONE);
mContainer.addView(section);
return section;
}
private void setCertificateViewer(String label) {
assert mCertificateViewer == null;
mCertificateViewer = new TextView(mContext);
mCertificateViewer.setText(label);
mCertificateViewer.setTextColor(
mContext.getResources().getColor(R.color.website_settings_popup_text_link));
mCertificateViewer.setTextSize(DESCRIPTION_TEXT_SIZE_SP);
mCertificateViewer.setOnClickListener(this);
mCertificateViewer.setPadding(0, mPaddingThin, 0, mPaddingThin);
mCertificateLayout.addView(mCertificateViewer);
}
@CalledByNative
private void addResetCertDecisionsButton(String label) {
assert mNativeConnectionInfoPopup != 0;
assert mResetCertDecisionsButton == null;
mResetCertDecisionsButton = new Button(mContext);
mResetCertDecisionsButton.setText(label);
mResetCertDecisionsButton.setBackground(mContext.getResources().getDrawable(
R.drawable.connection_info_reset_cert_decisions));
mResetCertDecisionsButton.setTextColor(
mContext.getResources().getColor(
R.color.connection_info_popup_reset_cert_decisions_button));
mResetCertDecisionsButton.setTextSize(DESCRIPTION_TEXT_SIZE_SP);
mResetCertDecisionsButton.setOnClickListener(this);
LinearLayout container = new LinearLayout(mContext);
container.setOrientation(LinearLayout.VERTICAL);
container.addView(mResetCertDecisionsButton);
container.setPadding(0, 0, 0, mPaddingWide);
mContainer.addView(container);
}
@CalledByNative
private void addMoreInfoLink(String linkText) {
mMoreInfoLink = new TextView(mContext);
mLinkUrl = HELP_URL;
mMoreInfoLink.setText(linkText);
mMoreInfoLink.setTextColor(
mContext.getResources().getColor(R.color.website_settings_popup_text_link));
mMoreInfoLink.setTextSize(DESCRIPTION_TEXT_SIZE_SP);
mMoreInfoLink.setPadding(0, mPaddingThin, 0, mPaddingThin);
mMoreInfoLink.setOnClickListener(this);
mDescriptionLayout.addView(mMoreInfoLink);
}
/** Displays the ConnectionInfoPopup. */
@CalledByNative
private void showDialog() {
ScrollView scrollView = new ScrollView(mContext);
scrollView.addView(mContainer);
mDialog.addContentView(scrollView,
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
mDialog.getWindow().setLayout(
ViewGroup.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
mDialog.show();
}
@Override
public void onClick(View v) {
if (mResetCertDecisionsButton == v) {
nativeResetCertDecisions(mNativeConnectionInfoPopup, mWebContents);
mDialog.dismiss();
} else if (mCertificateViewer == v) {
byte[][] certChain = nativeGetCertificateChain(mWebContents);
if (certChain == null) {
// The WebContents may have been destroyed/invalidated. If so,
// ignore this request.
return;
}
CertificateViewer.showCertificateChain(mContext, certChain);
} else if (mMoreInfoLink == v) {
mDialog.dismiss();
try {
Intent i = Intent.parseUri(mLinkUrl, Intent.URI_INTENT_SCHEME);
i.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true);
i.putExtra(Browser.EXTRA_APPLICATION_ID, mContext.getPackageName());
mContext.startActivity(i);
} catch (URISyntaxException ex) {
// Do nothing intentionally.
}
}
}
/**
* Shows a connection info dialog for the provided WebContents.
*
* The popup adds itself to the view hierarchy which owns the reference while it's
* visible.
*
* @param context Context which is used for launching a dialog.
* @param webContents The WebContents for which to show Website information. This
* information is retrieved for the visible entry.
*/
public static void show(Context context, WebContents webContents) {
new ConnectionInfoPopup(context, webContents);
}
private static native long nativeInit(ConnectionInfoPopup popup,
WebContents webContents);
private native void nativeDestroy(long nativeConnectionInfoPopupAndroid);
private native void nativeResetCertDecisions(
long nativeConnectionInfoPopupAndroid, WebContents webContents);
private native byte[][] nativeGetCertificateChain(WebContents webContents);
}
...@@ -15,6 +15,7 @@ import android.graphics.Color; ...@@ -15,6 +15,7 @@ import android.graphics.Color;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.text.Layout; import android.text.Layout;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
...@@ -383,6 +384,7 @@ public class WebsiteSettingsPopup implements OnClickListener, OnItemSelectedList ...@@ -383,6 +384,7 @@ public class WebsiteSettingsPopup implements OnClickListener, OnItemSelectedList
// Set the URL connection message now, and the URL after layout (so it // Set the URL connection message now, and the URL after layout (so it
// can calculate its ideal height). // can calculate its ideal height).
mUrlConnectionMessage.setText(getUrlConnectionMessage()); mUrlConnectionMessage.setText(getUrlConnectionMessage());
if (isConnectionDetailsLinkVisible()) mUrlConnectionMessage.setOnClickListener(this);
} }
/** /**
...@@ -453,6 +455,14 @@ public class WebsiteSettingsPopup implements OnClickListener, OnItemSelectedList ...@@ -453,6 +455,14 @@ public class WebsiteSettingsPopup implements OnClickListener, OnItemSelectedList
} }
} }
/**
* Whether to show a 'Details' link to the connection info popup. The link is only shown for
* HTTPS connections.
*/
private boolean isConnectionDetailsLinkVisible() {
return !mIsInternalPage && mSecurityLevel != ToolbarModelSecurityLevel.NONE;
}
/** /**
* Gets the styled connection message to display below the URL. * Gets the styled connection message to display below the URL.
*/ */
...@@ -488,6 +498,18 @@ public class WebsiteSettingsPopup implements OnClickListener, OnItemSelectedList ...@@ -488,6 +498,18 @@ public class WebsiteSettingsPopup implements OnClickListener, OnItemSelectedList
messageBuilder.setSpan(boldSpan, 0, leadingText.length(), messageBuilder.setSpan(boldSpan, 0, leadingText.length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE); Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
} }
if (isConnectionDetailsLinkVisible()) {
messageBuilder.append(" ");
SpannableString detailsText = new SpannableString(
mContext.getResources().getString(R.string.page_info_details_link));
final ForegroundColorSpan blueSpan = new ForegroundColorSpan(
mContext.getResources().getColor(R.color.website_settings_popup_text_link));
detailsText.setSpan(
blueSpan, 0, detailsText.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
messageBuilder.append(detailsText);
}
return messageBuilder; return messageBuilder;
} }
...@@ -609,6 +631,19 @@ public class WebsiteSettingsPopup implements OnClickListener, OnItemSelectedList ...@@ -609,6 +631,19 @@ public class WebsiteSettingsPopup implements OnClickListener, OnItemSelectedList
} else if (view == mUrlTitle) { } else if (view == mUrlTitle) {
// Expand/collapse the displayed URL title. // Expand/collapse the displayed URL title.
mUrlTitle.toggleTruncation(); mUrlTitle.toggleTruncation();
} else if (view == mUrlConnectionMessage) {
if (DeviceFormFactor.isTablet(mContext)) {
ConnectionInfoPopup.show(mContext, mWebContents);
} else {
// Delay while the WebsiteSettingsPopup closes.
mContainer.postDelayed(new Runnable() {
@Override
public void run() {
ConnectionInfoPopup.show(mContext, mWebContents);
}
}, FADE_DURATION + CLOSE_CLEANUP_DELAY);
}
mDialog.dismiss();
} }
} }
......
...@@ -1297,6 +1297,9 @@ You are signing in with a managed account and giving its administrator control o ...@@ -1297,6 +1297,9 @@ You are signing in with a managed account and giving its administrator control o
<message name="IDS_PAGE_INFO_PERMISSION_BLOCK" desc="The label used in the permissions dropdowns in the Page Info dialog on mobile for the option that denies a permission."> <message name="IDS_PAGE_INFO_PERMISSION_BLOCK" desc="The label used in the permissions dropdowns in the Page Info dialog on mobile for the option that denies a permission.">
Block Block
</message> </message>
<message name="IDS_PAGE_INFO_DETAILS_LINK" desc="The label of the link to open the detailed connection information popup from the page info bubble.">
Details
</message>
<message name="IDS_PAGE_INFO_CONNECTION_HTTPS" desc="Message to display in the page info bubble when the connection is private (HTTPS)."> <message name="IDS_PAGE_INFO_CONNECTION_HTTPS" desc="Message to display in the page info bubble when the connection is private (HTTPS).">
Your connection to this site is private. Your connection to this site is private.
</message> </message>
......
...@@ -87,7 +87,9 @@ ...@@ -87,7 +87,9 @@
#include "chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.h" #include "chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.h"
#include "chrome/browser/ui/android/autofill/credit_card_scanner_view_android.h" #include "chrome/browser/ui/android/autofill/credit_card_scanner_view_android.h"
#include "chrome/browser/ui/android/autofill/password_generation_popup_view_android.h" #include "chrome/browser/ui/android/autofill/password_generation_popup_view_android.h"
#include "chrome/browser/ui/android/certificate_viewer_android.h"
#include "chrome/browser/ui/android/chrome_http_auth_handler.h" #include "chrome/browser/ui/android/chrome_http_auth_handler.h"
#include "chrome/browser/ui/android/connection_info_popup_android.h"
#include "chrome/browser/ui/android/context_menu_helper.h" #include "chrome/browser/ui/android/context_menu_helper.h"
#include "chrome/browser/ui/android/infobars/account_chooser_infobar.h" #include "chrome/browser/ui/android/infobars/account_chooser_infobar.h"
#include "chrome/browser/ui/android/infobars/app_banner_infobar.h" #include "chrome/browser/ui/android/infobars/app_banner_infobar.h"
...@@ -162,6 +164,7 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = { ...@@ -162,6 +164,7 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = {
{"AutofillProfileBridge", autofill::RegisterAutofillProfileBridge}, {"AutofillProfileBridge", autofill::RegisterAutofillProfileBridge},
{"BookmarksBridge", BookmarksBridge::RegisterBookmarksBridge}, {"BookmarksBridge", BookmarksBridge::RegisterBookmarksBridge},
{"CardUnmaskPrompt", autofill::CardUnmaskPromptViewAndroid::Register}, {"CardUnmaskPrompt", autofill::CardUnmaskPromptViewAndroid::Register},
{"CertificateViewer", RegisterCertificateViewer},
{"ChildAccountFeedbackReporter", RegisterChildAccountFeedbackReporter}, {"ChildAccountFeedbackReporter", RegisterChildAccountFeedbackReporter},
{"ChildAccountService", RegisterChildAccountService}, {"ChildAccountService", RegisterChildAccountService},
{"ChromeBrowserProvider", {"ChromeBrowserProvider",
...@@ -172,6 +175,8 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = { ...@@ -172,6 +175,8 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = {
RegisterChromeWebContentsDelegateAndroid}, RegisterChromeWebContentsDelegateAndroid},
{"ChromiumApplication", ChromiumApplication::RegisterBindings}, {"ChromiumApplication", ChromiumApplication::RegisterBindings},
{"ConfirmInfoBarDelegate", RegisterConfirmInfoBarDelegate}, {"ConfirmInfoBarDelegate", RegisterConfirmInfoBarDelegate},
{"ConnectionInfoPopupAndroid",
ConnectionInfoPopupAndroid::RegisterConnectionInfoPopupAndroid},
{"ContentViewUtil", RegisterContentViewUtil}, {"ContentViewUtil", RegisterContentViewUtil},
{"ContextMenuHelper", RegisterContextMenuHelper}, {"ContextMenuHelper", RegisterContextMenuHelper},
{"CookiesFetcher", RegisterCookiesFetcher}, {"CookiesFetcher", RegisterCookiesFetcher},
......
...@@ -34,6 +34,26 @@ DEFINE_RESOURCE_ID(IDR_INFOBAR_TRANSLATE, R.drawable.infobar_translate) ...@@ -34,6 +34,26 @@ DEFINE_RESOURCE_ID(IDR_INFOBAR_TRANSLATE, R.drawable.infobar_translate)
DEFINE_RESOURCE_ID(IDR_BLOCKED_POPUPS, R.drawable.infobar_blocked_popups) DEFINE_RESOURCE_ID(IDR_BLOCKED_POPUPS, R.drawable.infobar_blocked_popups)
DEFINE_RESOURCE_ID(IDR_INFOBAR_FULLSCREEN, R.drawable.infobar_fullscreen) DEFINE_RESOURCE_ID(IDR_INFOBAR_FULLSCREEN, R.drawable.infobar_fullscreen)
// WebsiteSettingsUI images, used in ConnectionInfoPopup
// Good:
DEFINE_RESOURCE_ID(IDR_PAGEINFO_GOOD, R.drawable.pageinfo_good)
// Warnings:
DEFINE_RESOURCE_ID(IDR_PAGEINFO_WARNING_MINOR,\
R.drawable.pageinfo_warning)
// Bad:
DEFINE_RESOURCE_ID(IDR_PAGEINFO_BAD, R.drawable.pageinfo_bad)
// Should never occur, use warning just in case:
// Enterprise managed: ChromeOS only.
DEFINE_RESOURCE_ID(IDR_PAGEINFO_ENTERPRISE_MANAGED,\
R.drawable.pageinfo_warning)
// Info: Only shown on chrome:// urls, which don't show the connection info
// popup.
DEFINE_RESOURCE_ID(IDR_PAGEINFO_INFO, R.drawable.pageinfo_warning)
// Major warning: Used on insecure pages, which don't show the connection info
// popup.
DEFINE_RESOURCE_ID(IDR_PAGEINFO_WARNING_MAJOR,\
R.drawable.pageinfo_warning)
// Autofill popup images. // Autofill popup images.
DEFINE_RESOURCE_ID(IDR_AUTOFILL_CC_AMEX, R.drawable.amex_card) DEFINE_RESOURCE_ID(IDR_AUTOFILL_CC_AMEX, R.drawable.amex_card)
DEFINE_RESOURCE_ID(IDR_AUTOFILL_CC_DISCOVER, R.drawable.discover_card) DEFINE_RESOURCE_ID(IDR_AUTOFILL_CC_DISCOVER, R.drawable.discover_card)
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/android/certificate_viewer_android.h"
#include "base/android/jni_string.h"
#include "base/logging.h"
#include "chrome/grit/generated_resources.h"
#include "jni/CertificateViewer_jni.h"
#include "net/cert/x509_certificate.h"
#include "ui/base/l10n/l10n_util.h"
using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaLocalRef;
void ShowCertificateViewer(content::WebContents* web_contents,
gfx::NativeWindow parent,
net::X509Certificate* cert) {
// For Android, showing the certificate is always handled in Java.
NOTREACHED();
}
static jstring GetCertIssuedToText(JNIEnv* env, jclass) {
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(IDS_CERT_INFO_SUBJECT_GROUP)).Release();
}
static jstring GetCertInfoCommonNameText(JNIEnv* env, jclass) {
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(IDS_CERT_INFO_COMMON_NAME_LABEL)).Release();
}
static jstring GetCertInfoOrganizationText(JNIEnv* env, jclass) {
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(
IDS_CERT_INFO_ORGANIZATION_LABEL)).Release();
}
static jstring GetCertInfoSerialNumberText(JNIEnv* env, jclass) {
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(
IDS_CERT_INFO_SERIAL_NUMBER_LABEL)).Release();
}
static jstring GetCertInfoOrganizationUnitText(JNIEnv* env, jclass) {
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(
IDS_CERT_INFO_ORGANIZATIONAL_UNIT_LABEL)).Release();
}
static jstring GetCertIssuedByText(JNIEnv* env, jclass) {
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(IDS_CERT_INFO_ISSUER_GROUP)).Release();
}
static jstring GetCertValidityText(JNIEnv* env, jclass) {
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(IDS_CERT_INFO_VALIDITY_GROUP)).Release();
}
static jstring GetCertIssuedOnText(JNIEnv* env, jclass) {
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(IDS_CERT_INFO_ISSUED_ON_LABEL)).Release();
}
static jstring GetCertExpiresOnText(JNIEnv* env, jclass) {
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(IDS_CERT_INFO_EXPIRES_ON_LABEL)).Release();
}
static jstring GetCertFingerprintsText(JNIEnv* env, jclass) {
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(
IDS_CERT_INFO_FINGERPRINTS_GROUP)).Release();
}
static jstring GetCertSHA256FingerprintText(JNIEnv* env, jclass) {
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(
IDS_CERT_INFO_SHA256_FINGERPRINT_LABEL)).Release();
}
static jstring GetCertSHA1FingerprintText(JNIEnv* env, jclass) {
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(
IDS_CERT_INFO_SHA1_FINGERPRINT_LABEL)).Release();
}
bool RegisterCertificateViewer(JNIEnv* env) {
return RegisterNativesImpl(env);
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_ANDROID_CERTIFICATE_VIEWER_ANDROID_H_
#define CHROME_BROWSER_UI_ANDROID_CERTIFICATE_VIEWER_ANDROID_H_
#include "chrome/browser/certificate_viewer.h"
#include <jni.h>
bool RegisterCertificateViewer(JNIEnv* env);
#endif // CHROME_BROWSER_UI_ANDROID_CERTIFICATE_VIEWER_ANDROID_H_
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/android/connection_info_popup_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "chrome/browser/android/resource_mapper.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/website_settings/website_settings.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/cert_store.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/ssl_status.h"
#include "jni/ConnectionInfoPopup_jni.h"
#include "net/cert/x509_certificate.h"
#include "ui/base/l10n/l10n_util.h"
using base::android::CheckException;
using base::android::ConvertUTF8ToJavaString;
using base::android::ConvertUTF16ToJavaString;
using base::android::GetClass;
using base::android::ScopedJavaLocalRef;
using content::CertStore;
using content::WebContents;
static jobjectArray GetCertificateChain(JNIEnv* env,
jobject obj,
jobject java_web_contents) {
content::WebContents* web_contents =
content::WebContents::FromJavaWebContents(java_web_contents);
if (!web_contents)
return NULL;
int cert_id =
web_contents->GetController().GetVisibleEntry()->GetSSL().cert_id;
scoped_refptr<net::X509Certificate> cert;
bool ok = CertStore::GetInstance()->RetrieveCert(cert_id, &cert);
CHECK(ok);
std::vector<std::string> cert_chain;
net::X509Certificate::OSCertHandles cert_handles =
cert->GetIntermediateCertificates();
// Make sure the peer's own cert is the first in the chain, if it's not
// already there.
if (cert_handles.empty() || cert_handles[0] != cert->os_cert_handle())
cert_handles.insert(cert_handles.begin(), cert->os_cert_handle());
cert_chain.reserve(cert_handles.size());
for (net::X509Certificate::OSCertHandles::const_iterator it =
cert_handles.begin();
it != cert_handles.end();
++it) {
std::string cert_bytes;
net::X509Certificate::GetDEREncoded(*it, &cert_bytes);
cert_chain.push_back(cert_bytes);
}
// OK to release, JNI binding.
return base::android::ToJavaArrayOfByteArray(env, cert_chain).Release();
}
// static
static jlong Init(JNIEnv* env,
jclass clazz,
jobject obj,
jobject java_web_contents) {
content::WebContents* web_contents =
content::WebContents::FromJavaWebContents(java_web_contents);
return reinterpret_cast<intptr_t>(
new ConnectionInfoPopupAndroid(env, obj, web_contents));
}
ConnectionInfoPopupAndroid::ConnectionInfoPopupAndroid(
JNIEnv* env,
jobject java_website_settings_pop,
WebContents* web_contents) {
// Important to use GetVisibleEntry to match what's showing in the omnibox.
content::NavigationEntry* nav_entry =
web_contents->GetController().GetVisibleEntry();
if (nav_entry == NULL)
return;
popup_jobject_.Reset(env, java_website_settings_pop);
presenter_.reset(new WebsiteSettings(
this,
Profile::FromBrowserContext(web_contents->GetBrowserContext()),
TabSpecificContentSettings::FromWebContents(web_contents),
InfoBarService::FromWebContents(web_contents),
nav_entry->GetURL(),
nav_entry->GetSSL(),
content::CertStore::GetInstance()));
}
ConnectionInfoPopupAndroid::~ConnectionInfoPopupAndroid() {
}
void ConnectionInfoPopupAndroid::Destroy(JNIEnv* env, jobject obj) {
delete this;
}
void ConnectionInfoPopupAndroid::ResetCertDecisions(
JNIEnv* env,
jobject obj,
jobject java_web_contents) {
presenter_->OnRevokeSSLErrorBypassButtonPressed();
}
void ConnectionInfoPopupAndroid::SetIdentityInfo(
const IdentityInfo& identity_info) {
JNIEnv* env = base::android::AttachCurrentThread();
{
int icon_id = ResourceMapper::MapFromChromiumId(
WebsiteSettingsUI::GetIdentityIconID(identity_info.identity_status));
// The headline and the certificate dialog link of the site's identity
// section is only displayed if the site's identity was verified. If the
// site's identity was verified, then the headline contains the organization
// name from the provided certificate. If the organization name is not
// available than the hostname of the site is used instead.
std::string headline;
if (identity_info.cert_id) {
headline = identity_info.site_identity;
}
ScopedJavaLocalRef<jstring> description =
ConvertUTF8ToJavaString(env, identity_info.identity_status_description);
base::string16 certificate_label =
l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON);
Java_ConnectionInfoPopup_addCertificateSection(
env,
popup_jobject_.obj(),
icon_id,
ConvertUTF8ToJavaString(env, headline).obj(),
description.obj(),
ConvertUTF16ToJavaString(env, certificate_label).obj());
if (identity_info.show_ssl_decision_revoke_button) {
base::string16 reset_button_label = l10n_util::GetStringUTF16(
IDS_PAGEINFO_RESET_INVALID_CERTIFICATE_DECISIONS_BUTTON);
Java_ConnectionInfoPopup_addResetCertDecisionsButton(
env,
popup_jobject_.obj(),
ConvertUTF16ToJavaString(env, reset_button_label).obj());
}
}
{
int icon_id = ResourceMapper::MapFromChromiumId(
WebsiteSettingsUI::GetConnectionIconID(
identity_info.connection_status));
ScopedJavaLocalRef<jstring> description = ConvertUTF8ToJavaString(
env, identity_info.connection_status_description);
Java_ConnectionInfoPopup_addDescriptionSection(
env, popup_jobject_.obj(), icon_id, NULL, description.obj());
}
Java_ConnectionInfoPopup_addMoreInfoLink(
env,
popup_jobject_.obj(),
ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(IDS_PAGE_INFO_HELP_CENTER_LINK)).obj());
Java_ConnectionInfoPopup_showDialog(env, popup_jobject_.obj());
}
void ConnectionInfoPopupAndroid::SetCookieInfo(
const CookieInfoList& cookie_info_list) {
NOTIMPLEMENTED();
}
void ConnectionInfoPopupAndroid::SetPermissionInfo(
const PermissionInfoList& permission_info_list) {
NOTIMPLEMENTED();
}
void ConnectionInfoPopupAndroid::SetSelectedTab(
WebsiteSettingsUI::TabId tab_id) {
// There's no tab UI on Android - only connection info is shown.
NOTIMPLEMENTED();
}
void ConnectionInfoPopupAndroid::SetFirstVisit(
const base::string16& first_visit) {
NOTIMPLEMENTED();
}
// static
bool
ConnectionInfoPopupAndroid::RegisterConnectionInfoPopupAndroid(
JNIEnv* env) {
return RegisterNativesImpl(env);
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_ANDROID_CONNECTION_INFO_POPUP_ANDROID_H_
#define CHROME_BROWSER_UI_ANDROID_CONNECTION_INFO_POPUP_ANDROID_H_
#include <jni.h>
#include "base/android/scoped_java_ref.h"
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/ui/website_settings/website_settings_ui.h"
namespace content {
class WebContents;
}
// Android implementation of the website settings UI which displays detailed
// connection and certificate information for the website.
class ConnectionInfoPopupAndroid : public WebsiteSettingsUI {
public:
ConnectionInfoPopupAndroid(JNIEnv* env,
jobject java_website_settings,
content::WebContents* web_contents);
~ConnectionInfoPopupAndroid() override;
void Destroy(JNIEnv* env, jobject obj);
// Revokes any current user exceptions for bypassing SSL error interstitials
// on this page.
void ResetCertDecisions(JNIEnv* env, jobject obj, jobject java_web_contents);
// WebsiteSettingsUI implementations.
void SetCookieInfo(const CookieInfoList& cookie_info_list) override;
void SetPermissionInfo(
const PermissionInfoList& permission_info_list) override;
void SetIdentityInfo(const IdentityInfo& identity_info) override;
void SetFirstVisit(const base::string16& first_visit) override;
void SetSelectedTab(WebsiteSettingsUI::TabId tab_id) override;
static bool RegisterConnectionInfoPopupAndroid(JNIEnv* env);
private:
// The presenter that controlls the Website Settings UI.
scoped_ptr<WebsiteSettings> presenter_;
// The java prompt implementation.
base::android::ScopedJavaGlobalRef<jobject> popup_jobject_;
DISALLOW_COPY_AND_ASSIGN(ConnectionInfoPopupAndroid);
};
#endif // CHROME_BROWSER_UI_ANDROID_CONNECTION_INFO_POPUP_ANDROID_H_
...@@ -1634,6 +1634,7 @@ ...@@ -1634,6 +1634,7 @@
'android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java', 'android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java',
'android/java/src/org/chromium/chrome/browser/BookmarksBridge.java', 'android/java/src/org/chromium/chrome/browser/BookmarksBridge.java',
'android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java', 'android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java',
'android/java/src/org/chromium/chrome/browser/CertificateViewer.java',
'android/java/src/org/chromium/chrome/browser/child_accounts/ChildAccountService.java', 'android/java/src/org/chromium/chrome/browser/child_accounts/ChildAccountService.java',
'android/java/src/org/chromium/chrome/browser/child_accounts/ChildAccountFeedbackReporter.java', 'android/java/src/org/chromium/chrome/browser/child_accounts/ChildAccountFeedbackReporter.java',
'android/java/src/org/chromium/chrome/browser/ChromiumApplication.java', 'android/java/src/org/chromium/chrome/browser/ChromiumApplication.java',
...@@ -1645,6 +1646,7 @@ ...@@ -1645,6 +1646,7 @@
'android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java', 'android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java',
'android/java/src/org/chromium/chrome/browser/compositor/scene_layer/SceneLayer.java', 'android/java/src/org/chromium/chrome/browser/compositor/scene_layer/SceneLayer.java',
'android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java', 'android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java',
'android/java/src/org/chromium/chrome/browser/ConnectionInfoPopup.java',
'android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java', 'android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java',
'android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java', 'android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java',
'android/java/src/org/chromium/chrome/browser/cookies/CookiesFetcher.java', 'android/java/src/org/chromium/chrome/browser/cookies/CookiesFetcher.java',
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
'browser/ui/android/chrome_http_auth_handler.cc', 'browser/ui/android/chrome_http_auth_handler.cc',
'browser/ui/android/chrome_http_auth_handler.h', 'browser/ui/android/chrome_http_auth_handler.h',
'browser/ui/android/color_chooser_dialog_android.cc', 'browser/ui/android/color_chooser_dialog_android.cc',
'browser/ui/android/connection_info_popup_android.cc',
'browser/ui/android/connection_info_popup_android.h',
'browser/ui/android/content_settings/popup_blocked_infobar_delegate.cc', 'browser/ui/android/content_settings/popup_blocked_infobar_delegate.cc',
'browser/ui/android/content_settings/popup_blocked_infobar_delegate.h', 'browser/ui/android/content_settings/popup_blocked_infobar_delegate.h',
'browser/ui/android/context_menu_helper.cc', 'browser/ui/android/context_menu_helper.cc',
...@@ -51,6 +53,8 @@ ...@@ -51,6 +53,8 @@
'browser/ui/android/infobars/save_password_infobar.h', 'browser/ui/android/infobars/save_password_infobar.h',
'browser/ui/android/infobars/translate_infobar.cc', 'browser/ui/android/infobars/translate_infobar.cc',
'browser/ui/android/infobars/translate_infobar.h', 'browser/ui/android/infobars/translate_infobar.h',
'browser/ui/android/certificate_viewer_android.cc',
'browser/ui/android/certificate_viewer_android.h',
'browser/ui/android/javascript_app_modal_dialog_android.cc', 'browser/ui/android/javascript_app_modal_dialog_android.cc',
'browser/ui/android/login_prompt_android.cc', 'browser/ui/android/login_prompt_android.cc',
'browser/ui/android/navigation_popup.cc', 'browser/ui/android/navigation_popup.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment