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); |
} |