| Index: chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java
|
| index c3d3ab9c3433dea915ec353ab7c48ccffd3380eb..f7d462dd21d78f8053939f562fccd06443f413ac 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java
|
| @@ -12,13 +12,20 @@ import android.graphics.drawable.ColorDrawable;
|
| import android.text.Spannable;
|
| import android.text.SpannableStringBuilder;
|
| import android.text.style.ForegroundColorSpan;
|
| -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;
|
| @@ -27,11 +34,37 @@ import org.chromium.chrome.ChromeSwitches;
|
| import org.chromium.chrome.R;
|
| import org.chromium.content.browser.WebContentsObserverAndroid;
|
| import org.chromium.content_public.browser.WebContents;
|
| +import org.chromium.ui.base.Clipboard;
|
| +
|
| +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;
|
| + }
|
| +
|
| + public String toString() {
|
| + return name;
|
| + }
|
| + }
|
| +
|
| private final Context mContext;
|
| private final WebContents mWebContents;
|
|
|
| @@ -44,13 +77,21 @@ 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;
|
| +
|
| /**
|
| - * 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.
|
| */
|
| private WebsiteSettingsPopup(Context context, WebContents webContents) {
|
| mContext = context;
|
| @@ -63,7 +104,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);
|
| @@ -81,8 +137,8 @@ public class WebsiteSettingsPopup {
|
| 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();
|
| }
|
| };
|
| @@ -97,72 +153,152 @@ 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.
|
| + */
|
| + 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 : "Icon requested for invalid permission: " + permission;
|
| + return -1;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Sets the URL in the title of the dialog.
|
| + *
|
| + * @param url The URL to display, and to copy to the clipboard if the user selects 'copy'.
|
| + * @param connectionType The type of connection (determines the colours used for the URL); must
|
| + * be a valid PageInfoConnectionType.
|
| + * @param schemeEndIndex The index of the last character in the scheme (e.g. the index of the
|
| + * 's' in https://www.google.com/)
|
| + * @param domainEndIndex The index of the last character of the domain (e.g. the index of 'm' in
|
| + * https://www.google.com/foo).
|
| */
|
| @CalledByNative
|
| - private void setURLTitle(String scheme, String domain, String path, int connectionType) {
|
| - boolean makeDomainBold = false;
|
| + private void setURL(String url, int connectionType, int schemeEndIndex, int domainEndIndex) {
|
| + mFullUrl = url;
|
| 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;
|
| default:
|
| - assert false : "Unexpected connection type: " + connectionType;
|
| + assert false : "Unknown connection type: " + connectionType;
|
| }
|
|
|
| - SpannableStringBuilder sb = new SpannableStringBuilder(scheme + "://" + domain + path);
|
| + SpannableStringBuilder sb = new SpannableStringBuilder(url);
|
|
|
| ForegroundColorSpan schemeColorSpan = new ForegroundColorSpan(
|
| mContext.getResources().getColor(schemeColorId));
|
| - sb.setSpan(schemeColorSpan, 0, scheme.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
| + sb.setSpan(schemeColorSpan, 0, schemeEndIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
|
|
| - 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(),
|
| + sb.setSpan(domainColorSpan, schemeEndIndex + 1, domainEndIndex,
|
| Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
|
|
| - if (makeDomainBold) {
|
| - StyleSpan boldStyleSpan = new StyleSpan(android.graphics.Typeface.BOLD);
|
| - sb.setSpan(boldStyleSpan, domainStartIndex, domainStartIndex + domain.length(),
|
| - Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
| - }
|
| -
|
| 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").
|
| + * Sets the connection message displayed at the top of the dialog (e.g. "Could not securely
|
| + * connect to this site").
|
| + *
|
| + * @param connectionMessage The connection message to display.
|
| */
|
| @CalledByNative
|
| private void setConnectionMessage(String connectionMessage) {
|
| mUrlConnectionMessage.setText(connectionMessage);
|
| }
|
|
|
| - /** Displays the WebsiteSettingsPopup. */
|
| + /**
|
| + * 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 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);
|
| +
|
| + // Save the permission type in a tag inside the spinner.
|
| + permission_spinner.setTag(R.id.website_settings_popup_permission_type, type);
|
| +
|
| + // 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 current setting specified: " + currentSetting;
|
| + }
|
| +
|
| + 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.
|
| + */
|
| @CalledByNative
|
| private void showDialog() {
|
| // Wrap the dialog in a ScrollView in case the content is too long.
|
| @@ -172,8 +308,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);
|
| @@ -181,14 +317,51 @@ public class WebsiteSettingsPopup {
|
| mDialog.show();
|
| }
|
|
|
| + @Override
|
| + public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
|
| + int settingsType = (Integer) parent.getTag(R.id.website_settings_popup_permission_type);
|
| +
|
| + int selectedSetting = -1;
|
| + switch (pos) {
|
| + case 0:
|
| + selectedSetting = ContentSetting.ALLOW;
|
| + break;
|
| + case 1:
|
| + selectedSetting = ContentSetting.BLOCK;
|
| + break;
|
| + default:
|
| + assert false : "Invalid permission option selected: " + pos;
|
| + }
|
| +
|
| + nativeOnPermissionSettingChanged(mNativeWebsiteSettingsPopup, settingsType,
|
| + selectedSetting);
|
| + }
|
| +
|
| + @Override
|
| + public void onNothingSelected(AdapterView<?> parent) {
|
| + // Do nothing intentionally.
|
| + }
|
| +
|
| + @Override
|
| + public void onClick(View view) {
|
| + if (view == mCopyUrlButton) {
|
| + new Clipboard(mContext).setText(mFullUrl, mFullUrl);
|
| + } 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) {
|
| @@ -203,4 +376,7 @@ public class WebsiteSettingsPopup {
|
| WebContents webContents);
|
|
|
| private native void nativeDestroy(long nativeWebsiteSettingsPopupAndroid);
|
| +
|
| + private native void nativeOnPermissionSettingChanged(long nativeWebsiteSettingsPopupAndroid,
|
| + int type, int setting);
|
| }
|
|
|