Commit 97894ce1 authored by sashab's avatar sashab Committed by Commit bot

Add Permissions to the PageInfo dialog on Android

Add permissions dropdowns to the PageInfo dialog on Android,
which alter the content setting for the website currently
being visited. Also add a 'Copy URL' button and a 'Done'
button.

BUG=365528

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

Cr-Commit-Position: refs/heads/master@{#300658}
parent 7b73f83a
......@@ -529,6 +529,26 @@ group("strings") {
if (is_android) {
# GYP: //chrome/chrome.gyp:content_setting_java
java_cpp_enum("content_setting_javagen") {
sources = [
"../components/content_settings/core/common/content_settings.h"
]
outputs = [
"org/chromium/chrome/browser/ContentSetting.java",
]
}
# GYP: //chrome/chrome.gyp:content_settings_type_java
java_cpp_enum("content_settings_type_javagen") {
sources = [
"../components/content_settings/core/common/content_settings_types.h"
]
outputs = [
"org/chromium/chrome/browser/ContentSettingsType.java",
]
}
# GYP: //chrome/chrome.gyp:page_info_connection_type_java
java_cpp_enum("page_info_connection_type_javagen") {
sources = [
......
......@@ -107,6 +107,8 @@ android_library("chrome_java") {
":tab_load_status_javagen",
":chrome_version_srcjar",
"//chrome:page_info_connection_type_javagen",
"//chrome:content_setting_javagen",
"//chrome:content_settings_type_javagen",
]
DEPRECATED_java_in_dir = "java/src"
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2014 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.
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:textColor="@color/website_settings_popup_permission_spinner_text"
android:textSize="@dimen/website_settings_popup_permission_spinner_text_size"
android:ellipsize="marquee" />
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2014 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.
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="32dp"
android:paddingRight="20dp"
android:background="@drawable/website_settings_permission_spinner_item_background"
android:ellipsize="marquee"
android:gravity="center_vertical"
android:singleLine="true"
android:textColor="@color/website_settings_popup_permission_spinner_text"
android:textSize="@dimen/website_settings_popup_permission_spinner_text_size" />
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2014 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.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- To achieve a single border along the bottom, draw a rectangle offset by
1dp in all dimensions but the bottom. -->
<item android:top="-1dp" android:right="-1dp" android:left="-1dp">
<shape android:shape="rectangle" >
<stroke android:width="1dip" android:color="#e5e5e5"/>
</shape>
</item>
<item><bitmap android:gravity="right" android:src="@drawable/page_info_arrow_down" /></item>
</layer-list>
......@@ -8,26 +8,111 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/website_settings_popup_background"
android:orientation="vertical"
android:paddingBottom="@dimen/website_settings_margin_bottom"
android:paddingEnd="@dimen/website_settings_margin_sides"
android:paddingStart="@dimen/website_settings_margin_sides"
android:paddingTop="@dimen/website_settings_margin_top" >
<TextView
android:id="@+id/website_settings_url"
android:background="#ffffff"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/website_settings_margin_below_url"
android:textColor="@color/website_settings_popup_url"
android:textSize="@dimen/website_settings_url_title_size" />
android:orientation="vertical"
android:paddingEnd="@dimen/website_settings_popup_padding_sides"
android:paddingStart="@dimen/website_settings_popup_padding_sides" >
<TextView
android:id="@+id/website_settings_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="4dp"
android:paddingTop="16dp"
android:textColor="@color/website_settings_popup_url"
android:textSize="16dp"/>
<TextView
android:id="@+id/website_settings_connection_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="3dp"
android:paddingTop="12dp"
android:textColor="#444444"
android:textSize="14dp" />
<Button
android:id="@+id/website_settings_copy_url_button"
style="?android:attr/borderlessButtonStyle"
android:layout_gravity="end"
android:layout_width="wrap_content"
android:layout_height="@dimen/website_settings_popup_button_height"
android:layout_marginEnd="@dimen/website_settings_popup_button_margin_sides"
android:layout_marginStart="@dimen/website_settings_popup_button_margin_sides"
android:layout_marginBottom="8dp"
android:layout_marginTop="24dp"
android:paddingEnd="@dimen/website_settings_popup_button_padding_sides"
android:paddingStart="@dimen/website_settings_popup_button_padding_sides"
android:text="@string/page_info_copy_url_button"
android:textAllCaps="true"
android:textColor="#4184f3"
android:textSize="@dimen/website_settings_popup_button_text_size"
android:textStyle="bold" />
</LinearLayout>
<!-- Horizontal separator -->
<View
android:layout_width="match_parent"
android:layout_height="1dip"
android:background="#e7e7e7" />
<TextView
android:id="@+id/website_settings_permission_message"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/website_settings_popup_text"
android:textSize="@dimen/website_settings_url_description_size" />
android:orientation="vertical"
android:paddingStart="@dimen/website_settings_popup_padding_sides"
android:paddingEnd="@dimen/website_settings_popup_padding_sides" >
<LinearLayout
android:id="@+id/website_settings_permissions_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:orientation="horizontal"
android:paddingTop="16dp"
android:paddingBottom="16dp" >
<Button
android:id="@+id/website_settings_site_settings_button"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="@dimen/website_settings_popup_button_height"
android:layout_marginEnd="@dimen/website_settings_popup_button_margin_sides"
android:layout_marginStart="@dimen/website_settings_popup_button_margin_sides"
android:paddingEnd="@dimen/website_settings_popup_button_padding_sides"
android:paddingStart="@dimen/website_settings_popup_button_padding_sides"
android:text="@string/page_info_site_settings_button"
android:textAllCaps="true"
android:textColor="@color/website_settings_popup_button_text"
android:textSize="@dimen/website_settings_popup_button_text_size"
android:textStyle="bold" />
<Button
android:id="@+id/website_settings_done_button"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="@dimen/website_settings_popup_button_height"
android:layout_marginEnd="@dimen/website_settings_popup_button_margin_sides"
android:layout_marginStart="@dimen/website_settings_popup_button_margin_sides"
android:paddingEnd="@dimen/website_settings_popup_button_padding_sides"
android:paddingStart="@dimen/website_settings_popup_button_padding_sides"
android:text="@string/page_info_done_button"
android:textAllCaps="true"
android:textColor="@color/website_settings_popup_button_text"
android:textSize="@dimen/website_settings_popup_button_text_size"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2014 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="wrap_content"
android:orientation="horizontal"
android:paddingTop="18dp" >
<ImageView
android:id="@+id/website_settings_permission_icon"
android:layout_width="@dimen/website_settings_popup_permission_icon_size"
android:layout_height="@dimen/website_settings_popup_permission_icon_size" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="16dp" >
<TextView
android:id="@+id/website_settings_permission_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#444444"
android:textSize="14dp"
android:textStyle="bold" />
<Spinner
android:id="@+id/website_settings_permission_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
......@@ -34,14 +34,14 @@
<color name="website_settings_popup_reset_cert_decisions_button">#000000</color>
<!-- Website Settings Popup colors -->
<color name="website_settings_popup_background">#f2f2f2</color>
<color name="website_settings_popup_text">#333333</color>
<color name="website_settings_popup_url">#666666</color>
<color name="website_settings_popup_url_domain">#333333</color>
<color name="website_settings_popup_button_text">#444444</color>
<color name="website_settings_popup_url">#848484</color>
<color name="website_settings_popup_url_domain">#444444</color>
<color name="website_settings_popup_url_scheme_http">#666666</color>
<color name="website_settings_popup_url_scheme_https">#1ac222</color>
<color name="website_settings_popup_url_scheme_mixed">#eba200</color>
<color name="website_settings_popup_url_scheme_mixed">#f2a600</color>
<color name="website_settings_popup_url_scheme_broken">#db4437</color>
<color name="website_settings_popup_permission_spinner_text">#646464</color>
<!-- Distilled Page Prefs colors -->
<color name="distilled_page_prefs_selected">#999999</color>
......
......@@ -10,12 +10,13 @@
<dimen name="certificate_viewer_padding_thin">16dp</dimen>
<!-- Website Settings Popup Dimensions -->
<dimen name="website_settings_margin_top">16dp</dimen>
<dimen name="website_settings_margin_sides">16dp</dimen>
<dimen name="website_settings_margin_bottom">18dp</dimen>
<dimen name="website_settings_margin_below_url">10dp</dimen>
<dimen name="website_settings_url_title_size">16dp</dimen>
<dimen name="website_settings_url_description_size">12dp</dimen>
<dimen name="website_settings_popup_padding_sides">16dp</dimen>
<dimen name="website_settings_popup_button_text_size">14dp</dimen>
<dimen name="website_settings_popup_button_height">36dp</dimen>
<dimen name="website_settings_popup_button_padding_sides">8dp</dimen>
<dimen name="website_settings_popup_button_margin_sides">4dp</dimen>
<dimen name="website_settings_popup_permission_icon_size">24dp</dimen>
<dimen name="website_settings_popup_permission_spinner_text_size">16dp</dimen>
<!-- Accessibility tab switcher -->
<dimen name="accessibility_tab_height">65dp</dimen>
......
......@@ -12,26 +12,66 @@ import android.graphics.drawable.ColorDrawable;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.TextView;
import org.chromium.base.CalledByNative;
import org.chromium.base.CommandLine;
import org.chromium.chrome.ChromeSwitches;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.toolbar.ToolbarModel;
import org.chromium.chrome.browser.ui.toolbar.ToolbarModelSecurityLevel;
import org.chromium.content.browser.WebContentsObserver;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.Clipboard;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
/**
* Java side of Android implementation of the website settings UI.
* TODO(sashab): Rename this, and all its resources, to PageInfo* and page_info_* instead of
* WebsiteSettings* and website_settings_*. Do this on the C++ side as well.
*/
public class WebsiteSettingsPopup {
public class WebsiteSettingsPopup implements OnClickListener, OnItemSelectedListener {
/**
* An entry in the settings dropdown for a given permission. There are two options for each
* permission: Allow and Block.
*/
private static final class PageInfoPermissionEntry {
public final String name;
public final int type;
public final int value;
PageInfoPermissionEntry(String name, int type, int value) {
this.name = name;
this.type = type;
this.value = value;
}
@Override
public String toString() {
return name;
}
}
private final Context mContext;
private final WebContents mWebContents;
......@@ -44,13 +84,26 @@ public class WebsiteSettingsPopup {
// UI elements in the dialog.
private final TextView mUrlTitle;
private final TextView mUrlConnectionMessage;
private final LinearLayout mPermissionsList;
private final Button mCopyUrlButton;
private final Button mSiteSettingsButton;
private final Button mDoneButton;
// The dialog the container is placed in.
private final Dialog mDialog;
// The full URL from the URL bar, which is copied to the user's clipboard when they select 'Copy
// URL'.
private String mFullUrl;
private URI mUrl;
/**
* Creates the WebsiteSettingsPopup, but does not display it. Also
* initializes the corresponding C++ object and saves a pointer to it.
* Creates the WebsiteSettingsPopup, but does not display it. Also initializes the corresponding
* C++ object and saves a pointer to it.
*
* @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.
*/
private WebsiteSettingsPopup(Context context, WebContents webContents) {
mContext = context;
......@@ -63,7 +116,22 @@ public class WebsiteSettingsPopup {
mUrlTitle = (TextView) mContainer
.findViewById(R.id.website_settings_url);
mUrlConnectionMessage = (TextView) mContainer
.findViewById(R.id.website_settings_permission_message);
.findViewById(R.id.website_settings_connection_message);
mPermissionsList = (LinearLayout) mContainer
.findViewById(R.id.website_settings_permissions_list);
mCopyUrlButton = (Button) mContainer.findViewById(R.id.website_settings_copy_url_button);
mCopyUrlButton.setOnClickListener(this);
mSiteSettingsButton = (Button) mContainer
.findViewById(R.id.website_settings_site_settings_button);
mSiteSettingsButton.setOnClickListener(this);
// Hide the Site Settings button until there's a link to take it to.
// TODO(sashab,finnur): Make this button visible once Site Settings is working.
mSiteSettingsButton.setVisibility(View.GONE);
mDoneButton = (Button) mContainer.findViewById(R.id.website_settings_done_button);
mDoneButton.setOnClickListener(this);
// Create the dialog.
mDialog = new Dialog(mContext);
......@@ -80,8 +148,8 @@ public class WebsiteSettingsPopup {
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.
// If a navigation is committed (e.g. from in-page redirect), the data we're showing
// is stale so dismiss the dialog.
mDialog.dismiss();
}
};
......@@ -96,72 +164,165 @@ public class WebsiteSettingsPopup {
}
/**
* Sets the URL in the title to: (scheme)://(domain)(path). Also colors
* different parts of the URL depending on connectionType.
* connectionType should be a valid PageInfoConnectionType.
* Finds the Image resource of the icon to use for the given permission.
*
* @param permission A valid ContentSettingsType that can be displayed in the PageInfo dialog to
* retrieve the image for.
* @return The resource ID of the icon to use for that permission.
*/
@CalledByNative
private void setURLTitle(String scheme, String domain, String path, int connectionType) {
boolean makeDomainBold = false;
int schemeColorId = R.color.website_settings_popup_url_scheme_broken;
switch (connectionType) {
case PageInfoConnectionType.CONNECTION_UNKNOWN:
schemeColorId = R.color.website_settings_popup_url_scheme_http;
makeDomainBold = true;
break;
case PageInfoConnectionType.CONNECTION_ENCRYPTED:
schemeColorId = R.color.website_settings_popup_url_scheme_https;
break;
case PageInfoConnectionType.CONNECTION_MIXED_CONTENT:
schemeColorId = R.color.website_settings_popup_url_scheme_mixed;
makeDomainBold = true;
break;
case PageInfoConnectionType.CONNECTION_UNENCRYPTED:
schemeColorId = R.color.website_settings_popup_url_scheme_http;
makeDomainBold = true;
break;
case PageInfoConnectionType.CONNECTION_ENCRYPTED_ERROR:
schemeColorId = R.color.website_settings_popup_url_scheme_broken;
makeDomainBold = true;
break;
case PageInfoConnectionType.CONNECTION_INTERNAL_PAGE:
schemeColorId = R.color.website_settings_popup_url_scheme_http;
break;
private int getImageResourceForPermission(int permission) {
switch (permission) {
case ContentSettingsType.CONTENT_SETTINGS_TYPE_IMAGES:
return R.drawable.page_info_image;
case ContentSettingsType.CONTENT_SETTINGS_TYPE_JAVASCRIPT:
return R.drawable.page_info_javascript;
case ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION:
return R.drawable.page_info_location;
case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM:
return R.drawable.page_info_media;
case ContentSettingsType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
return R.drawable.page_info_notification;
case ContentSettingsType.CONTENT_SETTINGS_TYPE_POPUPS:
return R.drawable.page_info_popups;
default:
assert false : "Unexpected connection type: " + connectionType;
assert false : "Icon requested for invalid permission: " + permission;
return -1;
}
}
@CalledByNative
private void updatePageDetails(boolean isInternalPage) {
mFullUrl = mWebContents.getVisibleUrl();
int securityLevel = ToolbarModel.getSecurityLevelForWebContents(mWebContents);
SpannableStringBuilder sb = new SpannableStringBuilder(scheme + "://" + domain + path);
try {
mUrl = new URI(mFullUrl);
} catch (URISyntaxException e) {
assert false : "Invalid URL specified: " + mFullUrl;
}
ForegroundColorSpan schemeColorSpan = new ForegroundColorSpan(
mContext.getResources().getColor(schemeColorId));
sb.setSpan(schemeColorSpan, 0, scheme.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
int schemeColorId = -1;
if (securityLevel == ToolbarModelSecurityLevel.SECURITY_ERROR) {
schemeColorId = R.color.website_settings_popup_url_scheme_broken;
int domainStartIndex = scheme.length() + 3;
ForegroundColorSpan domainColorSpan = new ForegroundColorSpan(
mContext.getResources().getColor(R.color.website_settings_popup_url_domain));
sb.setSpan(domainColorSpan, domainStartIndex, domainStartIndex + domain.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
String leadingText = mContext.getResources().getString(
R.string.page_info_connection_broken_leading_text);
String followingText = mContext.getResources().getString(
R.string.page_info_connection_broken_following_text,
UrlUtilities.getOriginForDisplay(mUrl, false));
SpannableStringBuilder sb = new SpannableStringBuilder(leadingText + " "
+ followingText);
final ForegroundColorSpan redSpan = new ForegroundColorSpan(mContext.getResources()
.getColor(R.color.website_settings_popup_url_scheme_broken));
final StyleSpan boldSpan = new StyleSpan(android.graphics.Typeface.BOLD);
sb.setSpan(redSpan, 0, leadingText.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
sb.setSpan(boldSpan, 0, leadingText.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
mUrlConnectionMessage.setText(sb);
} else {
int connectionMessageId = 0;
if (isInternalPage) {
schemeColorId = R.color.website_settings_popup_url_scheme_http;
connectionMessageId = R.string.page_info_connection_internal_page;
} else {
switch (securityLevel) {
case ToolbarModelSecurityLevel.NONE:
schemeColorId = R.color.website_settings_popup_url_scheme_http;
connectionMessageId = R.string.page_info_connection_http;
break;
case ToolbarModelSecurityLevel.SECURE:
case ToolbarModelSecurityLevel.EV_SECURE:
schemeColorId = R.color.website_settings_popup_url_scheme_https;
connectionMessageId = R.string.page_info_connection_https;
break;
case ToolbarModelSecurityLevel.SECURITY_WARNING:
case ToolbarModelSecurityLevel.SECURITY_POLICY_WARNING:
schemeColorId = R.color.website_settings_popup_url_scheme_mixed;
connectionMessageId = R.string.page_info_connection_mixed;
break;
default:
assert false : "Invalid security level specified: " + securityLevel;
schemeColorId = R.color.website_settings_popup_url_scheme_http;
connectionMessageId = R.string.page_info_connection_http;
}
}
mUrlConnectionMessage.setText(mContext.getResources().getString(connectionMessageId));
}
if (makeDomainBold) {
StyleSpan boldStyleSpan = new StyleSpan(android.graphics.Typeface.BOLD);
sb.setSpan(boldStyleSpan, domainStartIndex, domainStartIndex + domain.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
// Color the URI-parsed version of the URL.
SpannableStringBuilder sb = new SpannableStringBuilder(mUrl.toString());
final ForegroundColorSpan schemeColorSpan = new ForegroundColorSpan(mContext.getResources()
.getColor(schemeColorId));
sb.setSpan(schemeColorSpan, 0, mUrl.getScheme().length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
if (securityLevel == ToolbarModelSecurityLevel.SECURITY_ERROR) {
sb.setSpan(new StrikethroughSpan(), 0, mUrl.getScheme().length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
// The domain is everything after the scheme until the end of the
// origin.
final ForegroundColorSpan domainColorSpan = new ForegroundColorSpan(
mContext.getResources().getColor(R.color.website_settings_popup_url_domain));
sb.setSpan(domainColorSpan, mUrl.getScheme().length(),
UrlUtilities.getOriginForDisplay(mUrl, true).length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
mUrlTitle.setText(sb);
}
/**
* Sets the connection message displayed at the top of the dialog to
* connectionMessage (e.g. "Could not securely connect to this site").
* Adds a new row for the given permission.
*
* @param name The title of the permission to display to the user.
* @param type The ContentSettingsType of the permission.
* @param currentSetting The ContentSetting of the currently selected setting.
*/
@CalledByNative
private void setConnectionMessage(String connectionMessage) {
mUrlConnectionMessage.setText(connectionMessage);
private void addPermissionSection(String name, int type, int currentSetting) {
LinearLayout permissionRow = (LinearLayout) LayoutInflater.from(mContext).inflate(
R.layout.website_settings_permission_row, null);
ImageView permission_icon = (ImageView) permissionRow.findViewById(
R.id.website_settings_permission_icon);
permission_icon.setImageResource(getImageResourceForPermission(type));
TextView permission_name = (TextView) permissionRow.findViewById(
R.id.website_settings_permission_name);
permission_name.setText(name);
Spinner permission_spinner = (Spinner) permissionRow.findViewById(
R.id.website_settings_permission_spinner);
// Work out the index of the currently selected setting.
int selectedSettingIndex = -1;
switch (currentSetting) {
case ContentSetting.ALLOW:
selectedSettingIndex = 0;
break;
case ContentSetting.BLOCK:
selectedSettingIndex = 1;
break;
default:
assert false : "Invalid setting " + currentSetting + " for permission " + type;
}
List<PageInfoPermissionEntry> settingsChoices = Arrays.asList(
new PageInfoPermissionEntry(mContext.getResources().getString(
R.string.page_info_permission_allow), type, ContentSetting.ALLOW),
new PageInfoPermissionEntry(mContext.getResources().getString(
R.string.page_info_permission_block), type, ContentSetting.BLOCK));
ArrayAdapter<PageInfoPermissionEntry> adapter = new ArrayAdapter<PageInfoPermissionEntry>(
mContext, R.drawable.website_settings_permission_spinner_item, settingsChoices);
adapter.setDropDownViewResource(
R.drawable.website_settings_permission_spinner_dropdown_item);
permission_spinner.setAdapter(adapter);
permission_spinner.setSelection(selectedSettingIndex, false);
permission_spinner.setOnItemSelectedListener(this);
mPermissionsList.addView(permissionRow);
}
/** Displays the WebsiteSettingsPopup. */
/**
* Displays the WebsiteSettingsPopup.
*/
@CalledByNative
private void showDialog() {
// Wrap the dialog in a ScrollView in case the content is too long.
......@@ -171,8 +332,8 @@ public class WebsiteSettingsPopup {
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
// Make the dialog fill the width of the screen. This must be called
// after addContentView, or it won't fully fill to the edge.
// Make the dialog fill the width of the screen. This must be called after addContentView,
// or it won't fully fill to the edge.
Window window = mDialog.getWindow();
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
......@@ -180,14 +341,38 @@ public class WebsiteSettingsPopup {
mDialog.show();
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
PageInfoPermissionEntry entry = (PageInfoPermissionEntry) parent.getItemAtPosition(pos);
nativeOnPermissionSettingChanged(mNativeWebsiteSettingsPopup, entry.type, entry.value);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing intentionally.
}
@Override
public void onClick(View view) {
if (view == mCopyUrlButton) {
new Clipboard(mContext).setText(mFullUrl, mFullUrl);
mDialog.dismiss();
} else if (view == mSiteSettingsButton) {
// TODO(sashab,finnur): Make this open the Website Settings dialog.
assert false : "No Website Settings here!";
mDialog.dismiss();
} else if (view == mDoneButton) {
mDialog.dismiss();
}
}
/**
* Shows a WebsiteSettings dialog for the provided WebContents. The popup
* adds itself to the view hierarchy which owns the reference while it's
* visible.
* Shows a WebsiteSettings 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.
* @param webContents The WebContents for which to show Website information. This information is
* retrieved for the visible entry.
*/
@SuppressWarnings("unused")
public static void show(Context context, WebContents webContents) {
......@@ -198,8 +383,10 @@ public class WebsiteSettingsPopup {
}
}
private static native long nativeInit(WebsiteSettingsPopup popup,
WebContents webContents);
private static native long nativeInit(WebsiteSettingsPopup popup, WebContents webContents);
private native void nativeDestroy(long nativeWebsiteSettingsPopupAndroid);
private native void nativeOnPermissionSettingChanged(long nativeWebsiteSettingsPopupAndroid,
int type, int setting);
}
......@@ -411,6 +411,41 @@ You are signing in with a managed account and giving its administrator control o
Add to homescreen
</message>
<!-- WebsiteSettingsPopup (PageInfo dialog) -->
<message name="IDS_PAGE_INFO_COPY_URL_BUTTON" desc="Text in the button that copies the URL to the clipboard.">
Copy URL
</message>
<message name="IDS_PAGE_INFO_SITE_SETTINGS_BUTTON" desc="Text in the button that opens a website's Site Settings from the Page Info dialog.">
Site Settings
</message>
<message name="IDS_PAGE_INFO_DONE_BUTTON" desc="Text in the button that closes the Page Info dialog.">
Done
</message>
<message name="IDS_PAGE_INFO_PERMISSION_ALLOW" desc="The label used in the permissions dropdowns in the Page Info dialog on mobile for the option that grants a permission.">
Allow
</message>
<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
</message>
<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.
</message>
<message name="IDS_PAGE_INFO_CONNECTION_HTTP" desc="Message to display in the page info bubble when the connection is not private (HTTP).">
Your connection to this site is not private.
</message>
<message name="IDS_PAGE_INFO_CONNECTION_MIXED" desc="Message to display in the page info bubble when the main connection is private, but there is content on the page that is not private.">
Your connection to this site is private, but someone on the network might be able to change the look of the page.
</message>
<message name="IDS_PAGE_INFO_CONNECTION_BROKEN_LEADING_TEXT" desc="Message to display highlighted red in the page info bubble when the connection is insecure because the HTTPS certificate is invalid.">
Your connection to this site is not private.
</message>
<message name="IDS_PAGE_INFO_CONNECTION_BROKEN_FOLLOWING_TEXT" desc="Message to display after a 'Your connection to this site is not private' message' in the page info bubble when the connection is insecure because the HTTPS certificate is invalid.">
Attackers might be trying to steal your information (for example, photos, passwords, messages and credit cards) from <ph name="DOMAIN_NAME">%1$s<ex>google.com</ex></ph>.
</message>
<message name="IDS_PAGE_INFO_CONNECTION_INTERNAL_PAGE" desc="Message to display in the page info bubble when the page is an internal Chrome page (e.g. the bookmarks page, or about:blank).">
You are viewing a secure Google Chrome page.
</message>
<!-- Network prediction internal values -->
<message name="IDS_NEVER_PREFETCH_BANDWIDTH_ENTRY" desc="Option to always disable the prefetching of web pages. [CHAR-LIMIT=16]">
Never
......@@ -421,6 +456,7 @@ You are signing in with a managed account and giving its administrator control o
<message name="IDS_ALWAYS_PREFETCH_BANDWIDTH_ENTRY" desc="Option to always prefetch web pages regardless of connection. [CHAR-LIMIT=16]">
Always
</message>
</messages>
</release>
</grit>
......@@ -9431,17 +9431,6 @@ Keep your key file in a safe place. You will need it to create new versions of y
</message>
</if>
<!-- Page Info Bubble -->
<message name="IDS_PAGE_INFO_ENCRYPTED_CONNECTION_SUMMARY_TEXT" desc="Message to display in the page info bubble when the connection is private.">
Your connection to this site is private.
</message>
<message name="IDS_PAGE_INFO_UNENCRYPTED_CONNECTION_SUMMARY_TEXT" desc="Message to display in the page info bubble when the connection is not private.">
Your connection to this site is not private.
</message>
<message name="IDS_PAGE_INFO_MIXED_CONTENT_CONNECTION_SUMMARY_TEXT" desc="Message to display in the page info bubble when the connection is private, but someone on the network might be able to change the look of the page (there is content on the page that is not private).">
Your connection to this site is private (HTTPS), but someone on the network might be able to change the look of the page.
</message>
<!-- Critical Notification Bubble -->
<message name="IDS_CRITICAL_NOTIFICATION_HEADLINE" desc="The headline for the critical notification">
<ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will restart in <ph name="SECONDS">$2<ex>10</ex></ph> seconds.
......
......@@ -11,12 +11,14 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/website_settings/website_settings.h"
#include "chrome/browser/ui/website_settings/website_settings_ui.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.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 "grit/generated_resources.h"
#include "jni/WebsiteSettingsPopup_jni.h"
#include "ui/base/l10n/l10n_util.h"
......@@ -65,51 +67,25 @@ void WebsiteSettingsPopupAndroid::Destroy(JNIEnv* env, jobject obj) {
delete this;
}
void WebsiteSettingsPopupAndroid::OnPermissionSettingChanged(JNIEnv* env,
jobject obj,
jint type,
jint setting) {
ContentSettingsType content_setting_type =
static_cast<ContentSettingsType>(type);
ContentSetting content_setting = static_cast<ContentSetting>(setting);
presenter_->OnSitePermissionChanged(content_setting_type, content_setting);
}
void WebsiteSettingsPopupAndroid::SetIdentityInfo(
const IdentityInfo& identity_info) {
JNIEnv* env = base::android::AttachCurrentThread();
enum PageInfoConnectionType connection_type = CONNECTION_UNKNOWN;
switch (identity_info.connection_status) {
case WebsiteSettings::SITE_CONNECTION_STATUS_UNKNOWN:
connection_type = CONNECTION_UNKNOWN;
break;
case WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED:
connection_type = CONNECTION_ENCRYPTED;
break;
case WebsiteSettings::SITE_CONNECTION_STATUS_MIXED_CONTENT:
connection_type = CONNECTION_MIXED_CONTENT;
break;
case WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED:
connection_type = CONNECTION_UNENCRYPTED;
break;
case WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED_ERROR:
connection_type = CONNECTION_ENCRYPTED_ERROR;
break;
case WebsiteSettings::SITE_CONNECTION_STATUS_INTERNAL_PAGE:
connection_type = CONNECTION_INTERNAL_PAGE;
break;
default:
NOTREACHED();
break;
}
Java_WebsiteSettingsPopup_setURLTitle(
Java_WebsiteSettingsPopup_updatePageDetails(
env,
popup_jobject_.obj(),
ConvertUTF8ToJavaString(env, url_.scheme()).obj(),
ConvertUTF8ToJavaString(env, url_.host()).obj(),
ConvertUTF8ToJavaString(env, url_.path()).obj(),
static_cast<jint>(connection_type));
Java_WebsiteSettingsPopup_setConnectionMessage(
env,
popup_jobject_.obj(),
ConvertUTF16ToJavaString(
env,
l10n_util::GetStringUTF16(
WebsiteSettingsUI::GetConnectionSummaryMessageID(
identity_info.connection_status))).obj());
identity_info.connection_status ==
WebsiteSettings::SITE_CONNECTION_STATUS_INTERNAL_PAGE);
Java_WebsiteSettingsPopup_showDialog(env, popup_jobject_.obj());
}
......@@ -121,7 +97,43 @@ void WebsiteSettingsPopupAndroid::SetCookieInfo(
void WebsiteSettingsPopupAndroid::SetPermissionInfo(
const PermissionInfoList& permission_info_list) {
NOTIMPLEMENTED();
JNIEnv* env = base::android::AttachCurrentThread();
// On Android, we only want to display a subset of the available options in a
// particular order, but only if their value is different from the default.
std::vector<ContentSettingsType> permissions_to_display;
permissions_to_display.push_back(CONTENT_SETTINGS_TYPE_GEOLOCATION);
permissions_to_display.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM);
permissions_to_display.push_back(CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
permissions_to_display.push_back(CONTENT_SETTINGS_TYPE_IMAGES);
permissions_to_display.push_back(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
permissions_to_display.push_back(CONTENT_SETTINGS_TYPE_POPUPS);
std::map<ContentSettingsType, ContentSetting>
user_specified_settings_to_display;
for (const auto& permission : permission_info_list) {
if (std::find(permissions_to_display.begin(),
permissions_to_display.end(),
permission.type) != permissions_to_display.end() &&
permission.setting != CONTENT_SETTING_DEFAULT) {
user_specified_settings_to_display[permission.type] = permission.setting;
}
}
for (const auto& permission : permissions_to_display) {
if (ContainsKey(user_specified_settings_to_display, permission)) {
base::string16 setting_title =
WebsiteSettingsUI::PermissionTypeToUIString(permission);
Java_WebsiteSettingsPopup_addPermissionSection(
env,
popup_jobject_.obj(),
ConvertUTF16ToJavaString(env, setting_title).obj(),
static_cast<jint>(permission),
static_cast<jint>(user_specified_settings_to_display[permission]));
}
}
}
void WebsiteSettingsPopupAndroid::SetSelectedTab(
......
......@@ -35,6 +35,10 @@ class WebsiteSettingsPopupAndroid : public WebsiteSettingsUI {
content::WebContents* web_contents);
virtual ~WebsiteSettingsPopupAndroid();
void Destroy(JNIEnv* env, jobject obj);
void OnPermissionSettingChanged(JNIEnv* env,
jobject obj,
jint type,
jint setting);
// WebsiteSettingsUI implementations.
virtual void SetCookieInfo(const CookieInfoList& cookie_info_list) override;
......
......@@ -337,7 +337,13 @@ void WebsiteSettings::OnRevokeSSLErrorBypassButtonPressed() {
void WebsiteSettings::Init(Profile* profile,
const GURL& url,
const content::SSLStatus& ssl) {
if (url.SchemeIs(content::kChromeUIScheme)) {
bool isChromeUINativeScheme = false;
#if defined(OS_ANDROID)
isChromeUINativeScheme = url.SchemeIs(chrome::kChromeUINativeScheme);
#endif
if (url.SchemeIs(content::kChromeUIScheme) ||
url.SchemeIs(url::kAboutScheme) || isChromeUINativeScheme) {
site_identity_status_ = SITE_IDENTITY_STATUS_INTERNAL_PAGE;
site_identity_details_ =
l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE);
......
......@@ -257,6 +257,7 @@ int WebsiteSettingsUI::GetIdentityIconID(
int resource_id = IDR_PAGEINFO_INFO;
switch (status) {
case WebsiteSettings::SITE_IDENTITY_STATUS_UNKNOWN:
case WebsiteSettings::SITE_IDENTITY_STATUS_INTERNAL_PAGE:
break;
case WebsiteSettings::SITE_IDENTITY_STATUS_CERT:
case WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT:
......@@ -297,6 +298,7 @@ int WebsiteSettingsUI::GetConnectionIconID(
int resource_id = IDR_PAGEINFO_INFO;
switch (status) {
case WebsiteSettings::SITE_CONNECTION_STATUS_UNKNOWN:
case WebsiteSettings::SITE_CONNECTION_STATUS_INTERNAL_PAGE:
break;
case WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED:
resource_id = IDR_PAGEINFO_GOOD;
......@@ -337,25 +339,3 @@ const gfx::Image& WebsiteSettingsUI::GetFirstVisitIcon(
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
return rb.GetNativeImageNamed(GetFirstVisitIconID(first_visit));
}
// static
int WebsiteSettingsUI::GetConnectionSummaryMessageID(
WebsiteSettings::SiteConnectionStatus status) {
switch (status) {
case WebsiteSettings::SITE_CONNECTION_STATUS_UNKNOWN:
return IDS_PAGE_INFO_UNENCRYPTED_CONNECTION_SUMMARY_TEXT;
case WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED:
return IDS_PAGE_INFO_ENCRYPTED_CONNECTION_SUMMARY_TEXT;
case WebsiteSettings::SITE_CONNECTION_STATUS_MIXED_CONTENT:
return IDS_PAGE_INFO_MIXED_CONTENT_CONNECTION_SUMMARY_TEXT;
case WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED:
return IDS_PAGE_INFO_UNENCRYPTED_CONNECTION_SUMMARY_TEXT;
case WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED_ERROR:
return IDS_PAGE_INFO_UNENCRYPTED_CONNECTION_SUMMARY_TEXT;
case WebsiteSettings::SITE_CONNECTION_STATUS_INTERNAL_PAGE:
return IDS_PAGE_INFO_INTERNAL_PAGE;
default:
NOTREACHED();
return 0;
}
}
......@@ -154,10 +154,6 @@ class WebsiteSettingsUI {
// Returns the icon to show along with the first visit information.
static const gfx::Image& GetFirstVisitIcon(const base::string16& first_visit);
// Returns the ID of a short message for the given connection |status|.
static int GetConnectionSummaryMessageID(
WebsiteSettings::SiteConnectionStatus status);
// Sets cookie information.
virtual void SetCookieInfo(const CookieInfoList& cookie_info_list) = 0;
......
......@@ -118,6 +118,8 @@ class WebsiteSettingsTest : public ChromeRenderViewHostTestHarness {
EXPECT_CALL(*mock_ui, SetFirstVisit(base::string16()));
}
void SetURL(std::string url) { url_ = GURL(url); }
const GURL& url() const { return url_; }
MockCertStore* cert_store() { return &cert_store_; }
int cert_id() { return cert_id_; }
......@@ -391,3 +393,23 @@ TEST_F(WebsiteSettingsTest, ShowInfoBar) {
infobar_service()->RemoveInfoBar(infobar_service()->infobar_at(0));
}
TEST_F(WebsiteSettingsTest, AboutBlankPage) {
SetURL("about:blank");
SetDefaultUIExpectations(mock_ui());
EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_INTERNAL_PAGE,
website_settings()->site_connection_status());
EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_INTERNAL_PAGE,
website_settings()->site_identity_status());
EXPECT_EQ(base::string16(), website_settings()->organization_name());
}
TEST_F(WebsiteSettingsTest, InternalPage) {
SetURL("chrome://bookmarks");
SetDefaultUIExpectations(mock_ui());
EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_INTERNAL_PAGE,
website_settings()->site_connection_status());
EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_INTERNAL_PAGE,
website_settings()->site_identity_status());
EXPECT_EQ(base::string16(), website_settings()->organization_name());
}
......@@ -587,6 +587,8 @@
'chrome_strings_grd',
'chrome_version_java',
'profile_account_management_metrics_java',
'content_setting_java',
'content_settings_type_java',
'page_info_connection_type_java',
'profile_sync_service_model_type_selection_java',
'resource_id_java',
......@@ -631,6 +633,24 @@
'../build/java_strings_grd.gypi',
],
},
{
# GN: //chrome:content_setting_javagen
'target_name': 'content_setting_java',
'type': 'none',
'variables': {
'source_file': '../components/content_settings/core/common/content_settings.h',
},
'includes': [ '../build/android/java_cpp_enum.gypi' ],
},
{
# GN: //chrome:content_settings_type_javagen
'target_name': 'content_settings_type_java',
'type': 'none',
'variables': {
'source_file': '../components/content_settings/core/common/content_settings_types.h',
},
'includes': [ '../build/android/java_cpp_enum.gypi' ],
},
{
# GN: //chrome:page_info_connection_type_javagen
'target_name': 'page_info_connection_type_java',
......
......@@ -96,6 +96,7 @@ const char kChromeUIVersionURL[] = "chrome://version/";
const char kChromeUIVoiceSearchURL[] = "chrome://voicesearch/";
#if defined(OS_ANDROID)
const char kChromeUINativeScheme[] = "chrome-native";
const char kChromeUINativeNewTabURL[] = "chrome-native://newtab/";
const char kChromeUINativeBookmarksURL[] = "chrome-native://bookmarks/";
const char kChromeUINativeRecentTabsURL[] = "chrome-native://recent-tabs/";
......
......@@ -89,6 +89,7 @@ extern const char kChromeUIVersionURL[];
extern const char kChromeUIVoiceSearchURL[];
#if defined(OS_ANDROID)
extern const char kChromeUINativeScheme[];
extern const char kChromeUINativeNewTabURL[];
extern const char kChromeUINativeBookmarksURL[];
extern const char kChromeUINativeRecentTabsURL[];
......
......@@ -12,6 +12,8 @@
// Different settings that can be assigned for a particular content type. We
// give the user the ability to set these on a global and per-origin basis.
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser
enum ContentSetting {
CONTENT_SETTING_DEFAULT = 0,
CONTENT_SETTING_ALLOW,
......
......@@ -9,6 +9,8 @@
// A particular type of content to care about. We give the user various types
// of controls over each of these.
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser
enum ContentSettingsType {
// "DEFAULT" is only used as an argument to the Content Settings Window
// opener; there it means "whatever was last shown".
......
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