diff --git a/mobile/android/base/DoorHangerPopup.java b/mobile/android/base/DoorHangerPopup.java index 6740a9bca67..d7b5483fd10 100644 --- a/mobile/android/base/DoorHangerPopup.java +++ b/mobile/android/base/DoorHangerPopup.java @@ -277,15 +277,21 @@ public class DoorHangerPopup extends AnchoredPopup // Show doorhangers for the selected tab int tabId = tab.getId(); boolean shouldShowPopup = false; + DoorHanger firstDoorhanger = null; for (DoorHanger dh : mDoorHangers) { if (dh.getTabId() == tabId) { dh.setVisibility(View.VISIBLE); shouldShowPopup = true; + if (firstDoorhanger == null) { + firstDoorhanger = dh; + } else { + dh.hideTitle(); + } } else { dh.setVisibility(View.GONE); } } - + // Dismiss the popup if there are no doorhangers to show for this tab if (!shouldShowPopup) { dismiss(); @@ -298,6 +304,8 @@ public class DoorHangerPopup extends AnchoredPopup return; } + firstDoorhanger.showTitle(tab.getFavicon(), tab.getBaseDomain()); + // Make the popup focusable for accessibility. This gets done here // so the node can be accessibility focused, but on pre-ICS devices this // causes crashes, so it is done after the popup is shown. diff --git a/mobile/android/base/resources/layout/doorhanger.xml b/mobile/android/base/resources/layout/doorhanger.xml index 777aad929e7..e6b95dc9d3d 100644 --- a/mobile/android/base/resources/layout/doorhanger.xml +++ b/mobile/android/base/resources/layout/doorhanger.xml @@ -8,7 +8,7 @@ + android:padding="@dimen/doorhanger_section_padding_small"> - + + + + + + + diff --git a/mobile/android/base/resources/layout/login_doorhanger.xml b/mobile/android/base/resources/layout/login_doorhanger.xml index 29922514539..50e9e156662 100644 --- a/mobile/android/base/resources/layout/login_doorhanger.xml +++ b/mobile/android/base/resources/layout/login_doorhanger.xml @@ -8,12 +8,6 @@ android:layout_height="wrap_content" android:orientation="vertical"> - - + android:layout_marginTop="@dimen/doorhanger_subsection_padding"/> diff --git a/mobile/android/base/resources/layout/site_identity.xml b/mobile/android/base/resources/layout/site_identity.xml index fdaecb64554..1b282d88a18 100644 --- a/mobile/android/base/resources/layout/site_identity.xml +++ b/mobile/android/base/resources/layout/site_identity.xml @@ -11,13 +11,13 @@ + android:padding="@dimen/doorhanger_section_padding_small"> + android:paddingRight="@dimen/doorhanger_section_padding_small"/> diff --git a/mobile/android/base/resources/values/dimens.xml b/mobile/android/base/resources/values/dimens.xml index c04f110eae4..1e8adff878e 100644 --- a/mobile/android/base/resources/values/dimens.xml +++ b/mobile/android/base/resources/values/dimens.xml @@ -102,11 +102,11 @@ 300dp 250dp 9sp - 15dp 12dp 67dp 7dp 5dp + 8dp 20dp 30dp 60dp diff --git a/mobile/android/base/toolbar/SiteIdentityPopup.java b/mobile/android/base/toolbar/SiteIdentityPopup.java index 483b0e5d56f..9b98213a373 100644 --- a/mobile/android/base/toolbar/SiteIdentityPopup.java +++ b/mobile/android/base/toolbar/SiteIdentityPopup.java @@ -8,6 +8,8 @@ import android.content.ClipData; import android.content.ClipboardManager; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.widget.ImageView; import android.widget.Toast; import org.json.JSONException; import org.json.JSONArray; @@ -23,8 +25,6 @@ import org.mozilla.gecko.SiteIdentity.MixedMode; import org.mozilla.gecko.SiteIdentity.TrackingMode; import org.mozilla.gecko.Tab; import org.mozilla.gecko.Tabs; -import org.mozilla.gecko.favicons.Favicons; -import org.mozilla.gecko.favicons.OnFaviconLoadedListener; import org.mozilla.gecko.util.GeckoEventListener; import org.mozilla.gecko.util.ThreadUtils; import org.mozilla.gecko.widget.AnchoredPopup; @@ -174,10 +174,9 @@ public class SiteIdentityPopup extends AnchoredPopup implements GeckoEventListen } private void addLoginsToTab(JSONObject data) throws JSONException { - final JSONObject titleObj = data.getJSONObject("title"); final JSONArray logins = data.getJSONArray("logins"); - final SiteLogins siteLogins = new SiteLogins(titleObj, logins); + final SiteLogins siteLogins = new SiteLogins(logins); Tabs.getInstance().getSelectedTab().setSiteLogins(siteLogins); } @@ -241,8 +240,6 @@ public class SiteIdentityPopup extends AnchoredPopup implements GeckoEventListen // Set options. final JSONObject options = new JSONObject(); - final JSONObject titleObj = siteLogins.getTitle(); - options.put("title", titleObj); // Add action text only if there are other logins to select. if (logins.length() > 1) { @@ -293,23 +290,6 @@ public class SiteIdentityPopup extends AnchoredPopup implements GeckoEventListen } private void updateIdentityInformation(final SiteIdentity siteIdentity) { - final String host = siteIdentity.getHost(); - mTitle.setText(host); - - final String hostUrl = siteIdentity.getOrigin(); - Favicons.getSizedFaviconForPageFromLocal(mContext, hostUrl, 32, new OnFaviconLoadedListener() { - @Override - public void onFaviconLoaded(String url, String faviconURL, Bitmap favicon) { - if (favicon == null) { - // If there is no favicon, clear the compound drawable. - mTitle.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); - } else { - mTitle.setCompoundDrawablesWithIntrinsicBounds(new BitmapDrawable(mContext.getResources(), favicon), null, null, null); - mTitle.setCompoundDrawablePadding((int) mContext.getResources().getDimension(R.dimen.doorhanger_drawable_padding)); - } - } - }); - mEncrypted.setVisibility(siteIdentity.getEncrypted() ? View.VISIBLE : View.GONE); mHost.setText(siteIdentity.getHost()); @@ -451,6 +431,13 @@ public class SiteIdentityPopup extends AnchoredPopup implements GeckoEventListen Log.e(LOGTAG, "Error adding selectLogin doorhanger", e); } + mTitle.setText(selectedTab.getBaseDomain()); + final Bitmap favicon = selectedTab.getFavicon(); + if (favicon != null) { + mTitle.setCompoundDrawablesWithIntrinsicBounds(new BitmapDrawable(mContext.getResources(), favicon), null, null, null); + mTitle.setCompoundDrawablePadding((int) mContext.getResources().getDimension(R.dimen.doorhanger_drawable_padding)); + } + showDividers(); super.show(); @@ -491,6 +478,7 @@ public class SiteIdentityPopup extends AnchoredPopup implements GeckoEventListen removeMixedContentNotification(); removeTrackingContentNotification(); removeSelectLoginDoorhanger(); + mTitle.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); mDivider.setVisibility(View.GONE); } diff --git a/mobile/android/base/widget/DefaultDoorHanger.java b/mobile/android/base/widget/DefaultDoorHanger.java index e356474fedf..5d8c8da3e4a 100644 --- a/mobile/android/base/widget/DefaultDoorHanger.java +++ b/mobile/android/base/widget/DefaultDoorHanger.java @@ -109,7 +109,7 @@ public class DefaultDoorHanger extends DoorHanger { PromptInput input = PromptInput.getInput(inputs.getJSONObject(i)); mInputs.add(input); - final int padding = mResources.getDimensionPixelSize(R.dimen.doorhanger_padding); + final int padding = mResources.getDimensionPixelSize(R.dimen.doorhanger_section_padding_small); View v = input.getView(getContext()); styleInput(input, v); v.setPadding(0, 0, 0, padding); @@ -198,7 +198,7 @@ public class DefaultDoorHanger extends DoorHanger { if (input instanceof PromptInput.MenulistInput) { styleDropdownInputs(input, view); } - view.setPadding(0, 0, 0, mResources.getDimensionPixelSize(R.dimen.doorhanger_padding)); + view.setPadding(0, 0, 0, mResources.getDimensionPixelSize(R.dimen.doorhanger_subsection_padding)); } private void styleDropdownInputs(PromptInput input, View view) { diff --git a/mobile/android/base/widget/DoorHanger.java b/mobile/android/base/widget/DoorHanger.java index bb6fde9a02b..2a146c6d66e 100644 --- a/mobile/android/base/widget/DoorHanger.java +++ b/mobile/android/base/widget/DoorHanger.java @@ -7,14 +7,19 @@ package org.mozilla.gecko.widget; import android.content.Context; import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewStub; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.TextView; import org.json.JSONObject; import org.mozilla.gecko.R; +import org.mozilla.gecko.Tabs; public abstract class DoorHanger extends LinearLayout { @@ -54,6 +59,7 @@ public abstract class DoorHanger extends LinearLayout { protected final Type mType; protected final ImageView mIcon; + protected final TextView mDoorhangerTitle; protected final Context mContext; protected final Resources mResources; @@ -78,6 +84,7 @@ public abstract class DoorHanger extends LinearLayout { mDivider = findViewById(R.id.divider_doorhanger); mIcon = (ImageView) findViewById(R.id.doorhanger_icon); + mDoorhangerTitle = (TextView) findViewById(R.id.doorhanger_title); mNegativeButton = (Button) findViewById(R.id.doorhanger_button_negative); mPositiveButton = (Button) findViewById(R.id.doorhanger_button_positive); @@ -175,4 +182,17 @@ public abstract class DoorHanger extends LinearLayout { return true; } + + public void showTitle(Bitmap favicon, String title) { + mDoorhangerTitle.setText(title); + mDoorhangerTitle.setCompoundDrawablesWithIntrinsicBounds(new BitmapDrawable(getResources(), favicon), null, null, null); + if (favicon != null) { + mDoorhangerTitle.setCompoundDrawablePadding((int) mContext.getResources().getDimension(R.dimen.doorhanger_drawable_padding)); + } + mDoorhangerTitle.setVisibility(VISIBLE); + } + + public void hideTitle() { + mDoorhangerTitle.setVisibility(GONE); + } } diff --git a/mobile/android/base/widget/LoginDoorHanger.java b/mobile/android/base/widget/LoginDoorHanger.java index b79f2ffb02e..99738b2e89a 100644 --- a/mobile/android/base/widget/LoginDoorHanger.java +++ b/mobile/android/base/widget/LoginDoorHanger.java @@ -35,7 +35,6 @@ public class LoginDoorHanger extends DoorHanger { private static final String LOGTAG = "LoginDoorHanger"; private enum ActionType { EDIT, SELECT } - private final TextView mTitle; private final TextView mMessage; private final TextView mLink; private final DoorhangerConfig.ButtonConfig mButtonConfig; @@ -43,7 +42,6 @@ public class LoginDoorHanger extends DoorHanger { public LoginDoorHanger(Context context, DoorhangerConfig config) { super(context, config, Type.LOGIN); - mTitle = (TextView) findViewById(R.id.doorhanger_title); mMessage = (TextView) findViewById(R.id.doorhanger_message); mLink = (TextView) findViewById(R.id.doorhanger_link); mIcon.setImageResource(R.drawable.icon_key); @@ -76,30 +74,6 @@ public class LoginDoorHanger extends DoorHanger { protected void setOptions(final JSONObject options) { super.setOptions(options); - final JSONObject titleObj = options.optJSONObject("title"); - if (titleObj != null) { - - try { - final String text = titleObj.getString("text"); - mTitle.setText(text); - } catch (JSONException e) { - Log.e(LOGTAG, "Error loading title from options JSON", e); - } - - final String resource = titleObj.optString("resource"); - if (resource != null) { - Favicons.getSizedFaviconForPageFromLocal(mContext, resource, 32, new OnFaviconLoadedListener() { - @Override - public void onFaviconLoaded(String url, String faviconURL, Bitmap favicon) { - if (favicon != null) { - mTitle.setCompoundDrawablesWithIntrinsicBounds(new BitmapDrawable(mResources, favicon), null, null, null); - mTitle.setCompoundDrawablePadding((int) mResources.getDimension(R.dimen.doorhanger_drawable_padding)); - } - } - }); - } - } - final JSONObject actionText = options.optJSONObject("actionText"); addActionText(actionText); } diff --git a/mobile/android/base/widget/SiteLogins.java b/mobile/android/base/widget/SiteLogins.java index bf2c667b88b..4d4a9227589 100644 --- a/mobile/android/base/widget/SiteLogins.java +++ b/mobile/android/base/widget/SiteLogins.java @@ -4,19 +4,13 @@ import org.json.JSONArray; import org.json.JSONObject; public class SiteLogins { - private final JSONObject titleObj; private final JSONArray logins; - public SiteLogins(JSONObject titleObj, JSONArray logins) { + public SiteLogins(JSONArray logins) { this.logins = logins; - this.titleObj = titleObj; } public JSONArray getLogins() { return logins; } - - public JSONObject getTitle() { - return titleObj; - } } diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 38e62a9d5b4..f12b40f5ae0 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -2330,14 +2330,7 @@ var NativeWindow = { * * checkbox: A string to appear next to a checkbox under the notification * message. The button callback functions will be called with - * the checked state as an argument. - * - * title: An object that specifies text to display as the title, and - * optionally a resource, such as a favicon cache url that can be - * used to fetch a favicon from the FaviconCache. (This can be - * generalized to other resources if the situation arises.) - * { text: , - * resource: <resource_url> } + * the checked state as an argument. * * actionText: An object that specifies a clickable string, a type of action, * and a bundle blob for the consumer to create a click action. diff --git a/mobile/android/components/LoginManagerPrompter.js b/mobile/android/components/LoginManagerPrompter.js index 0106d667a3c..d2fce47489f 100644 --- a/mobile/android/components/LoginManagerPrompter.js +++ b/mobile/android/components/LoginManagerPrompter.js @@ -140,8 +140,6 @@ LoginManagerPrompter.prototype = { * _showLoginNotification * * Displays a notification doorhanger. - * @param aTitle - * Object with title and optional resource to display with the title, such as a favicon key * @param aBody * String message to be displayed in the doorhanger * @param aButtons @@ -151,7 +149,7 @@ LoginManagerPrompter.prototype = { * @param aPassword * Password string used in creating a doorhanger action */ - _showLoginNotification : function (aTitle, aBody, aButtons, aUsername, aPassword) { + _showLoginNotification : function (aBody, aButtons, aUsername, aPassword) { let notifyWin = this._window.top; let chromeWin = this._getChromeWindow(notifyWin).wrappedJSObject; let browser = chromeWin.BrowserApp.getBrowserForWindow(notifyWin); @@ -174,7 +172,6 @@ LoginManagerPrompter.prototype = { let options = { persistWhileVisible: true, timeout: Date.now() + 10000, - title: aTitle, actionText: actionText } @@ -196,9 +193,6 @@ LoginManagerPrompter.prototype = { let brandShortName = this._strBundle.brand.GetStringFromName("brandShortName"); let notificationText = this._getLocalizedString("saveLogin", [brandShortName]); - let displayHost = this._getShortDisplayHost(aLogin.hostname); - let title = { text: displayHost, resource: aLogin.hostname }; - let username = aLogin.username ? this._sanitizeUsername(aLogin.username) : ""; // The callbacks in |buttons| have a closure to access the variables @@ -230,7 +224,7 @@ LoginManagerPrompter.prototype = { } ]; - this._showLoginNotification(title, notificationText, buttons, aLogin.username, aLogin.password); + this._showLoginNotification(notificationText, buttons, aLogin.username, aLogin.password); }, /* @@ -261,9 +255,6 @@ LoginManagerPrompter.prototype = { notificationText = this._getLocalizedString("updatePasswordNoUser"); } - let displayHost = this._getShortDisplayHost(aOldLogin.hostname); - let title = { text: displayHost, resource: aOldLogin.hostname }; - // The callbacks in |buttons| have a closure to access the variables // in scope here; set one to |this._pwmgr| so we can get back to pwmgr // without a getService() call. @@ -290,7 +281,7 @@ LoginManagerPrompter.prototype = { } ]; - this._showLoginNotification(title, notificationText, buttons, aOldLogin.username, aNewPassword); + this._showLoginNotification(notificationText, buttons, aOldLogin.username, aNewPassword); }, @@ -462,35 +453,6 @@ LoginManagerPrompter.prototype = { return hostname; }, - - /* - * _getShortDisplayHost - * - * Converts a login's hostname field (a URL) to a short string for - * prompting purposes. Eg, "http://foo.com" --> "foo.com", or - * "ftp://www.site.co.uk" --> "site.co.uk". - */ - _getShortDisplayHost: function (aURIString) { - var displayHost; - - var eTLDService = Cc["@mozilla.org/network/effective-tld-service;1"]. - getService(Ci.nsIEffectiveTLDService); - var idnService = Cc["@mozilla.org/network/idn-service;1"]. - getService(Ci.nsIIDNService); - try { - var uri = Services.io.newURI(aURIString, null, null); - var baseDomain = eTLDService.getBaseDomain(uri); - displayHost = idnService.convertToDisplayIDN(baseDomain, {}); - } catch (e) { - this.log("_getShortDisplayHost couldn't process " + aURIString); - } - - if (!displayHost) - displayHost = aURIString; - - return displayHost; - }, - }; // end of LoginManagerPrompter implementation