author | Chenxia Liu <liuche@mozilla.com> |
Wed, 06 May 2015 19:39:07 -0700 | |
changeset 244017 | acc34206a8ab3d111baff9d3e55007d84a43b76d |
parent 244016 | 09b6e5f3e10d572c9c2b5950cfabfcc5bf20548b |
child 244018 | 85b0cc1fbddce86fe0702d9f5299e9a0500a65fa |
push id | 59820 |
push user | cbook@mozilla.com |
push date | Fri, 15 May 2015 15:41:47 +0000 |
treeherder | mozilla-inbound@5943d32f3515 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | ally |
bugs | 1126608 |
milestone | 41.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/mobile/android/base/locales/en-US/android_strings.dtd +++ b/mobile/android/base/locales/en-US/android_strings.dtd @@ -375,16 +375,18 @@ size. --> contains brackets to indicate this is not actually a username, but rather a placeholder --> <!ENTITY doorhanger_login_no_username "[No username]"> <!ENTITY doorhanger_login_edit_title "Edit login"> <!ENTITY doorhanger_login_edit_username_hint "Username"> <!ENTITY doorhanger_login_edit_password_hint "Password"> <!ENTITY doorhanger_login_edit_toggle "Show password"> <!ENTITY doorhanger_login_edit_toast_error "Failed to save login"> <!ENTITY doorhanger_login_select_message "Copy password from &formatS;?"> +<!ENTITY doorhanger_login_select_toast_copy "Password copied to clipboard"> +<!ENTITY doorhanger_login_select_toast_copy_error "Couldn\'t copy password"> <!ENTITY pref_titlebar_mode "Title bar"> <!ENTITY pref_titlebar_mode_title "Show page title"> <!ENTITY pref_titlebar_mode_url "Show page address"> <!-- Localization note (pref_scroll_title_bar2): Label for setting that controls whether or not the dynamic toolbar is enabled. --> <!ENTITY pref_scroll_title_bar2 "Full-screen browsing"> @@ -435,16 +437,17 @@ size. --> <!ENTITY button_ok "OK"> <!ENTITY button_cancel "Cancel"> <!ENTITY button_yes "Yes"> <!ENTITY button_no "No"> <!ENTITY button_clear_data "Clear data"> <!ENTITY button_set "Set"> <!ENTITY button_clear "Clear"> <!ENTITY button_remember "Remember"> +<!ENTITY button_copy "Copy"> <!ENTITY firstrun_panel_title_welcome "Welcome"> <!ENTITY home_top_sites_title "Top Sites"> <!-- Localization note (home_top_sites_add): This string is used as placeholder text underneath empty thumbnails in the Top Sites page on about:home. --> <!ENTITY home_top_sites_add "Add a site">
--- a/mobile/android/base/strings.xml.in +++ b/mobile/android/base/strings.xml.in @@ -342,16 +342,18 @@ <string name="doorhanger_login_no_username">&doorhanger_login_no_username;</string> <string name="doorhanger_login_edit_title">&doorhanger_login_edit_title;</string> <string name="doorhanger_login_edit_username_hint">&doorhanger_login_edit_username_hint;</string> <string name="doorhanger_login_edit_password_hint">&doorhanger_login_edit_password_hint;</string> <string name="doorhanger_login_edit_toggle">&doorhanger_login_edit_toggle;</string> <string name="doorhanger_login_edit_toast_error">&doorhanger_login_edit_toast_error;</string> <string name="doorhanger_login_select_message">&doorhanger_login_select_message;</string> + <string name="doorhanger_login_select_toast_copy">&doorhanger_login_select_toast_copy;</string> + <string name="doorhanger_login_select_toast_copy_error">&doorhanger_login_select_toast_copy_error;</string> <string name="pref_titlebar_mode">&pref_titlebar_mode;</string> <string name="pref_titlebar_mode_title">&pref_titlebar_mode_title;</string> <string name="pref_titlebar_mode_url">&pref_titlebar_mode_url;</string> <string name="pref_scroll_title_bar2">&pref_scroll_title_bar2;</string> <string name="pref_scroll_title_bar_summary">&pref_scroll_title_bar_summary;</string> @@ -371,16 +373,17 @@ <string name="button_ok">&button_ok;</string> <string name="button_cancel">&button_cancel;</string> <string name="button_clear_data">&button_clear_data;</string> <string name="button_set">&button_set;</string> <string name="button_clear">&button_clear;</string> <string name="button_yes">&button_yes;</string> <string name="button_no">&button_no;</string> <string name="button_remember">&button_remember;</string> + <string name="button_copy">&button_copy;</string> <string name="firstrun_panel_title_welcome">&firstrun_panel_title_welcome;</string> <string name="home_title">&home_title;</string> <string name="home_top_sites_title">&home_top_sites_title;</string> <string name="home_top_sites_add">&home_top_sites_add;</string> <string name="home_history_title">&home_history_title;</string> <string name="home_clear_history_button">&home_clear_history_button;</string>
--- a/mobile/android/base/toolbar/SiteIdentityPopup.java +++ b/mobile/android/base/toolbar/SiteIdentityPopup.java @@ -1,17 +1,21 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.toolbar; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.widget.Toast; import org.json.JSONException; import org.json.JSONArray; import org.mozilla.gecko.AboutPages; +import org.mozilla.gecko.AppConstants; import org.mozilla.gecko.EventDispatcher; import org.mozilla.gecko.R; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoEvent; import org.mozilla.gecko.SiteIdentity; import org.mozilla.gecko.SiteIdentity.SecurityMode; import org.mozilla.gecko.SiteIdentity.MixedMode; import org.mozilla.gecko.SiteIdentity.TrackingMode; @@ -35,17 +39,17 @@ import org.mozilla.gecko.widget.Doorhang import org.mozilla.gecko.widget.SiteLogins; /** * SiteIdentityPopup is a singleton class that displays site identity data in * an arrow panel popup hanging from the lock icon in the browser toolbar. */ public class SiteIdentityPopup extends AnchoredPopup implements GeckoEventListener { - public static enum ButtonType { DISABLE, ENABLE, KEEP_BLOCKING }; + public static enum ButtonType { DISABLE, ENABLE, KEEP_BLOCKING, CANCEL, COPY }; private static final String LOGTAG = "GeckoSiteIdentityPopup"; private static final String MIXED_CONTENT_SUPPORT_URL = "https://support.mozilla.org/kb/how-does-insecure-content-affect-safety-android"; private static final String TRACKING_CONTENT_SUPPORT_URL = "https://support.mozilla.org/kb/firefox-android-tracking-protection"; @@ -66,22 +70,22 @@ public class SiteIdentityPopup extends A private TextView mVerifier; private View mDivider; private DoorHanger mMixedContentNotification; private DoorHanger mTrackingContentNotification; private DoorHanger mSelectLoginDoorhanger; - private final OnButtonClickListener mButtonClickListener; + private final OnButtonClickListener mContentButtonClickListener; public SiteIdentityPopup(Context context) { super(context); - mButtonClickListener = new PopupButtonListener(); + mContentButtonClickListener = new ContentNotificationButtonListener(); EventDispatcher.getInstance().registerGeckoThreadListener(this, "Doorhanger:Logins"); } @Override protected void init() { super.init(); // Make the popup focusable so it doesn't inadvertently trigger click events elsewhere @@ -158,17 +162,45 @@ public class SiteIdentityPopup extends A return; } final JSONArray logins = siteLogins.getLogins(); if (logins.length() == 0) { return; } - final DoorhangerConfig config = new DoorhangerConfig(DoorHanger.Type.LOGIN, null); + final JSONObject login = (JSONObject) logins.get(0); + final OnButtonClickListener buttonClickListener = new OnButtonClickListener() { + @Override + public void onButtonClick(JSONObject response, DoorHanger doorhanger) { + try { + final int buttonId = response.getInt("callback"); + if (buttonId == ButtonType.COPY.ordinal()) { + final ClipboardManager manager = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE); + final String password = login.getString("password"); + if (AppConstants.Versions.feature11Plus) { + manager.setPrimaryClip(ClipData.newPlainText("password", password)); + } else { + manager.setText(password); + } + Toast.makeText(mContext, R.string.doorhanger_login_select_toast_copy, Toast.LENGTH_SHORT).show(); + } + dismiss(); + } catch (JSONException e) { + Log.e(LOGTAG, "Error handling Select login button click", e); + Toast.makeText(mContext, R.string.doorhanger_login_select_toast_copy_error, Toast.LENGTH_SHORT).show(); + } + } + }; + + final DoorhangerConfig config = new DoorhangerConfig(DoorHanger.Type.LOGIN, buttonClickListener); + + // Set buttons. + config.appendButton(mContext.getString(R.string.button_cancel), ButtonType.CANCEL.ordinal()); + config.appendButton(mContext.getString(R.string.button_copy), ButtonType.COPY.ordinal()); // Set message. String username = ((JSONObject) logins.get(0)).getString("username"); if (TextUtils.isEmpty(username)) { username = mContext.getString(R.string.doorhanger_login_no_username); } final String message = mContext.getString(R.string.doorhanger_login_select_message).replace(FORMAT_S, username); @@ -243,17 +275,17 @@ public class SiteIdentityPopup extends A final String encrypted = siteIdentity.getEncrypted(); mVerifier.setText(verifier + "\n" + encrypted); } private void addMixedContentNotification(boolean blocked) { // Remove any existing mixed content notification. removeMixedContentNotification(); - final DoorhangerConfig config = new DoorhangerConfig(DoorHanger.Type.MIXED_CONTENT, mButtonClickListener); + final DoorhangerConfig config = new DoorhangerConfig(DoorHanger.Type.MIXED_CONTENT, mContentButtonClickListener); int icon; if (blocked) { icon = R.drawable.shield_enabled_doorhanger; config.setMessage(mContext.getString(R.string.blocked_mixed_content_message_top) + "\n\n" + mContext.getString(R.string.blocked_mixed_content_message_bottom)); } else { icon = R.drawable.shield_disabled_doorhanger; config.setMessage(mContext.getString(R.string.loaded_mixed_content_message)); @@ -275,17 +307,17 @@ public class SiteIdentityPopup extends A mMixedContentNotification = null; } } private void addTrackingContentNotification(boolean blocked) { // Remove any existing tracking content notification. removeTrackingContentNotification(); - final DoorhangerConfig config = new DoorhangerConfig(DoorHanger.Type.TRACKING, mButtonClickListener); + final DoorhangerConfig config = new DoorhangerConfig(DoorHanger.Type.TRACKING, mContentButtonClickListener); int icon; if (blocked) { icon = R.drawable.shield_enabled_doorhanger; config.setMessage(mContext.getString(R.string.blocked_tracking_content_message_top) + "\n\n" + mContext.getString(R.string.blocked_tracking_content_message_bottom)); } else { icon = R.drawable.shield_disabled_doorhanger; @@ -398,17 +430,17 @@ public class SiteIdentityPopup extends A public void dismiss() { super.dismiss(); removeMixedContentNotification(); removeTrackingContentNotification(); removeSelectLoginDoorhanger(); mDivider.setVisibility(View.GONE); } - private class PopupButtonListener implements OnButtonClickListener { + private class ContentNotificationButtonListener implements OnButtonClickListener { @Override public void onButtonClick(JSONObject response, DoorHanger doorhanger) { GeckoEvent e = GeckoEvent.createBroadcastEvent("Session:Reload", response.toString()); GeckoAppShell.sendEventToGecko(e); dismiss(); } } }
--- a/mobile/android/base/widget/DoorHanger.java +++ b/mobile/android/base/widget/DoorHanger.java @@ -122,17 +122,16 @@ public abstract class DoorHanger extends final long timeout = options.optLong("timeout"); if (timeout > 0) { mTimeout = timeout; } } protected void setButtons(DoorhangerConfig config) { final JSONArray buttons = config.getButtons(); - final OnButtonClickListener listener = config.getButtonClickListener(); for (int i = 0; i < buttons.length(); i++) { try { final JSONObject buttonObject = buttons.getJSONObject(i); final String label = buttonObject.getString("label"); final int callbackId = buttonObject.getInt("callback"); addButtonToLayout(label, callbackId); } catch (JSONException e) { Log.e(LOGTAG, "Error creating doorhanger button", e);