Bug 1141904 - Update SiteIdentity popup to match Doorhanger popup. r=ally
authorChenxia Liu <liuche@mozilla.com>
Wed, 10 Jun 2015 14:57:38 -0700
changeset 279476 4af0399648041e6e890f0d451a38a3d424f6f4ff
parent 279475 67fceb70fc6de648ee12d24fa430f8f47da640f6
child 279477 0a6778a3d65ab8a3aa364fcfe1e02906f0edb2f9
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersally
bugs1141904
milestone41.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
Bug 1141904 - Update SiteIdentity popup to match Doorhanger popup. r=ally
mobile/android/base/SiteIdentity.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/layout/site_identity.xml
mobile/android/base/resources/values/colors.xml
mobile/android/base/resources/values/styles.xml
mobile/android/base/strings.xml.in
mobile/android/base/toolbar/SiteIdentityPopup.java
mobile/android/chrome/content/browser.js
mobile/android/locales/en-US/chrome/browser.properties
--- a/mobile/android/base/SiteIdentity.java
+++ b/mobile/android/base/SiteIdentity.java
@@ -1,28 +1,31 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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;
 
+import android.util.Log;
 import org.json.JSONObject;
 
 import android.text.TextUtils;
 
 public class SiteIdentity {
+    private final String LOGTAG = "GeckoSiteIdentity";
     private SecurityMode mSecurityMode;
     private MixedMode mMixedMode;
     private TrackingMode mTrackingMode;
     private String mHost;
     private String mOwner;
     private String mSupplemental;
     private String mVerifier;
-    private String mEncrypted;
+    private boolean mEncrypted;
+    private String mOrigin;
 
     // The order of the items here relate to image levels in
     // site_security_level.xml
     public enum SecurityMode {
         UNKNOWN("unknown"),
         IDENTIFIED("identified"),
         VERIFIED("verified");
 
@@ -119,21 +122,22 @@ public class SiteIdentity {
     }
 
     public SiteIdentity() {
         reset();
     }
 
     public void resetIdentity() {
         mSecurityMode = SecurityMode.UNKNOWN;
+        mOrigin = null;
         mHost = null;
         mOwner = null;
         mSupplemental = null;
         mVerifier = null;
-        mEncrypted = null;
+        mEncrypted = false;
     }
 
     public void reset() {
         resetIdentity();
         mMixedMode = MixedMode.UNKNOWN;
         mTrackingMode = TrackingMode.UNKNOWN;
     }
 
@@ -161,50 +165,56 @@ public class SiteIdentity {
             try {
                 mSecurityMode = SecurityMode.fromString(mode.getString("identity"));
             } catch (Exception e) {
                 resetIdentity();
                 return;
             }
 
             try {
+                mOrigin = identityData.getString("origin");
                 mHost = identityData.getString("host");
                 mOwner = identityData.optString("owner", null);
                 mSupplemental = identityData.optString("supplemental", null);
                 mVerifier = identityData.getString("verifier");
-                mEncrypted = identityData.getString("encrypted");
+                mEncrypted = identityData.optBoolean("encrypted", false);
             } catch (Exception e) {
+                Log.e(LOGTAG, "Error fetching Site identity host info", e);
                 resetIdentity();
             }
         } catch (Exception e) {
             reset();
         }
     }
 
     public SecurityMode getSecurityMode() {
         return mSecurityMode;
     }
 
+    public String getOrigin() {
+        return mOrigin;
+    }
+
     public String getHost() {
         return mHost;
     }
 
     public String getOwner() {
         return mOwner;
     }
 
     public String getSupplemental() {
         return mSupplemental;
     }
 
     public String getVerifier() {
         return mVerifier;
     }
 
-    public String getEncrypted() {
+    public boolean getEncrypted() {
         return mEncrypted;
     }
 
     public MixedMode getMixedMode() {
         return mMixedMode;
     }
 
     public TrackingMode getTrackingMode() {
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -543,16 +543,17 @@ Example Enterprises, Inc.
 
 The layout of the identity dialog prevents combining this into a single string with
 substitution variables.  If it is difficult to translate the sense of the string
 with that structure, consider a translation which ignores the preceding domain and
 just addresses the organization to follow, e.g. "This site is run by " -->
 <!ENTITY identity_run_by "which is run by">
 <!ENTITY identity_no_info "This website does not supply identity information.">
 <!ENTITY identity_not_encrypted "Your connection to this website is not encrypted.">
+<!ENTITY identity_encrypted "Encrypted">
 
 <!-- Mixed content notifications in site identity popup -->
 <!ENTITY loaded_mixed_content_message "This page is displaying content that isn\'t secure.">
 <!ENTITY blocked_mixed_content_message_top "&brandShortName; has blocked content that isn\'t secure.">
 <!ENTITY blocked_mixed_content_message_bottom "Most websites will still work properly even when this content is blocked.">
 
 <!-- Tracking content notifications in site identity popup -->
 <!ENTITY loaded_tracking_content_message_top "Tracking protection disabled.">
--- a/mobile/android/base/resources/layout/site_identity.xml
+++ b/mobile/android/base/resources/layout/site_identity.xml
@@ -9,34 +9,48 @@
               android:orientation="vertical">
 
     <LinearLayout android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:orientation="horizontal"
                   android:padding="@dimen/doorhanger_padding">
 
         <ImageView android:id="@+id/larry"
-                   android:layout_width="wrap_content"
-                   android:layout_height="wrap_content"
+                   android:layout_width="@dimen/doorhanger_icon_size"
+                   android:layout_height="@dimen/doorhanger_icon_size"
                    android:src="@drawable/larry"
                    android:paddingRight="@dimen/doorhanger_padding"/>
 
         <LinearLayout android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      android:orientation="vertical"
                      android:layout_weight="1.0">
 
             <include layout="@layout/site_identity_unknown" />
 
             <LinearLayout android:id="@+id/site_identity_known_container"
                           android:layout_width="match_parent"
                           android:layout_height="wrap_content"
                           android:visibility="gone"
                           android:orientation="vertical">
 
+                <TextView android:id="@+id/site_identity_title"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:layout_marginBottom="@dimen/doorhanger_section_padding_small"
+                          android:textAppearance="@style/TextAppearance.DoorHanger.Medium.Light"/>
+
+                <TextView android:id="@+id/site_identity_encrypted"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:layout_marginBottom="@dimen/doorhanger_section_padding_small"
+                          android:textAppearance="@style/TextAppearance.DoorHanger.Medium.Bold"
+                          android:textColor="@color/affirmative_green"
+                          android:text="@string/identity_encrypted"/>
+
                 <TextView android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:textAppearance="@style/TextAppearance.DoorHanger.Medium.Light"
                           android:text="@string/identity_connected_to"/>
 
                 <TextView android:id="@+id/host"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
--- a/mobile/android/base/resources/values/colors.xml
+++ b/mobile/android/base/resources/values/colors.xml
@@ -1,16 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- 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/. -->
 
 <resources>
   <!-- Fennec color palette (bug 1127517) -->
   <color name="fennec_ui_orange">#FF9500</color>
+  <color name="affirmative_green">#6FBE4A</color>
   <color name="action_orange">#E66000</color>
   <color name="action_orange_pressed">#DC5600</color>
   <color name="link_blue">#0096DD</color>
   <color name="link_blue_pressed">#0082C6</color>
   <color name="private_browsing_purple">#CF68FF</color>
 
   <color name="placeholder_active_grey">#222222</color>
   <color name="placeholder_grey">#777777</color>
--- a/mobile/android/base/resources/values/styles.xml
+++ b/mobile/android/base/resources/values/styles.xml
@@ -422,16 +422,20 @@
         <item name="android:textColor">@color/placeholder_active_grey</item>
         <item name="android:textColorLink">@color/doorhanger_link</item>
     </style>
 
     <style name="TextAppearance.DoorHanger.Medium">
         <item name="android:textSize">16dp</item>
     </style>
 
+    <style name="TextAppearance.DoorHanger.Medium.Bold">
+        <item name="android:fontFamily">sans-serif-medium</item>
+    </style>
+
     <style name="TextAppearance.DoorHanger.Medium.Light">
         <item name="android:fontFamily">sans-serif-light</item>
     </style>
 
     <style name="TextAppearance.DoorHanger.Small">
         <item name="android:textSize">14sp</item>
     </style>
 
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -453,16 +453,17 @@
   <string name="bookmarkdefaults_title_marketplace">@bookmarks_marketplace@</string>
   <string name="bookmarkdefaults_url_marketplace">https://marketplace.firefox.com/</string>
 
   <!-- Site identity popup -->
   <string name="identity_connected_to">&identity_connected_to;</string>
   <string name="identity_run_by">&identity_run_by;</string>
   <string name="identity_no_info">&identity_no_info;</string>
   <string name="identity_not_encrypted">&identity_not_encrypted;</string>
+  <string name="identity_encrypted">&identity_encrypted;</string>
   <string name="loaded_mixed_content_message">&loaded_mixed_content_message;</string>
   <string name="blocked_mixed_content_message_top">&blocked_mixed_content_message_top;</string>
   <string name="blocked_mixed_content_message_bottom">&blocked_mixed_content_message_bottom;</string>
   <string name="loaded_tracking_content_message_top">&loaded_tracking_content_message_top;</string>
   <string name="loaded_tracking_content_message_bottom">&loaded_tracking_content_message_bottom;</string>
   <string name="blocked_tracking_content_message_top">&blocked_tracking_content_message_top2;</string>
   <string name="blocked_tracking_content_message_bottom">&blocked_tracking_content_message_bottom2;</string>
   <string name="learn_more">&learn_more;</string>
--- a/mobile/android/base/toolbar/SiteIdentityPopup.java
+++ b/mobile/android/base/toolbar/SiteIdentityPopup.java
@@ -1,31 +1,35 @@
 /* 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.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
 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;
 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;
 import org.mozilla.gecko.widget.DoorHanger;
 import org.mozilla.gecko.widget.DoorHanger.OnButtonClickListener;
 import org.json.JSONObject;
 
 import android.content.Context;
@@ -59,16 +63,18 @@ public class SiteIdentityPopup extends A
 
     private SiteIdentity mSiteIdentity;
 
     private LinearLayout mIdentity;
 
     private LinearLayout mIdentityKnownContainer;
     private LinearLayout mIdentityUnknownContainer;
 
+    private TextView mTitle;
+    private TextView mEncrypted;
     private TextView mHost;
     private TextView mOwnerLabel;
     private TextView mOwner;
     private TextView mVerifier;
 
     private View mDivider;
 
     private DoorHanger mMixedContentNotification;
@@ -96,16 +102,19 @@ public class SiteIdentityPopup extends A
         mIdentity = (LinearLayout) inflater.inflate(R.layout.site_identity, null);
         mContent.addView(mIdentity);
 
         mIdentityKnownContainer =
                 (LinearLayout) mIdentity.findViewById(R.id.site_identity_known_container);
         mIdentityUnknownContainer =
                 (LinearLayout) mIdentity.findViewById(R.id.site_identity_unknown_container);
 
+
+        mTitle = (TextView) mIdentityKnownContainer.findViewById(R.id.site_identity_title);
+        mEncrypted = (TextView) mIdentityKnownContainer.findViewById(R.id.site_identity_encrypted);
         mHost = (TextView) mIdentityKnownContainer.findViewById(R.id.host);
         mOwnerLabel = (TextView) mIdentityKnownContainer.findViewById(R.id.owner_label);
         mOwner = (TextView) mIdentityKnownContainer.findViewById(R.id.owner);
         mVerifier = (TextView) mIdentityKnownContainer.findViewById(R.id.verifier);
         mDivider = mIdentity.findViewById(R.id.divider_doorhanger);
 
         final TextView siteSettingsLink = (TextView) mIdentity.findViewById(R.id.site_settings_link);
         siteSettingsLink.setOnClickListener(new View.OnClickListener() {
@@ -263,16 +272,35 @@ public class SiteIdentityPopup extends A
             mIdentityUnknownContainer.setVisibility(View.GONE);
         } else {
             mIdentityKnownContainer.setVisibility(View.GONE);
             mIdentityUnknownContainer.setVisibility(View.VISIBLE);
         }
     }
 
     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());
 
         String owner = siteIdentity.getOwner();
         if (owner == null) {
             mOwnerLabel.setVisibility(View.GONE);
             mOwner.setVisibility(View.GONE);
         } else {
             mOwnerLabel.setVisibility(View.VISIBLE);
@@ -282,18 +310,17 @@ public class SiteIdentityPopup extends A
             final String supplemental = siteIdentity.getSupplemental();
             if (!TextUtils.isEmpty(supplemental)) {
                 owner += "\n" + supplemental;
             }
             mOwner.setText(owner);
         }
 
         final String verifier = siteIdentity.getVerifier();
-        final String encrypted = siteIdentity.getEncrypted();
-        mVerifier.setText(verifier + "\n" + encrypted);
+        mVerifier.setText(verifier);
     }
 
     private void addMixedContentNotification(boolean blocked) {
         // Remove any existing mixed content notification.
         removeMixedContentNotification();
 
         final DoorhangerConfig config = new DoorhangerConfig(DoorHanger.Type.MIXED_CONTENT, mContentButtonClickListener);
         int icon;
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -7023,42 +7023,43 @@ var IdentityHandler = {
     // hold on to the window object too long.  Just pass in the fields we
     // care about. (bug 424829)
     let locationObj = {};
     try {
       let location = aBrowser.contentWindow.location;
       locationObj.host = location.host;
       locationObj.hostname = location.hostname;
       locationObj.port = location.port;
+      locationObj.origin = location.origin;
     } catch (ex) {
       // Can sometimes throw if the URL being visited has no host/hostname,
       // e.g. about:blank. The _state for these pages means we won't need these
       // properties anyways, though.
     }
     this._lastLocation = locationObj;
 
     let identityMode = this.getIdentityMode(aState);
     let mixedMode = this.getMixedMode(aState);
     let trackingMode = this.getTrackingMode(aState);
     let result = {
+      origin: locationObj.origin,
       mode: {
         identity: identityMode,
         mixed: mixedMode,
         tracking: trackingMode
       }
     };
 
     // Don't show identity data for pages with an unknown identity or if any
     // mixed content is loaded (mixed display content is loaded by default).
     if (identityMode == this.IDENTITY_MODE_UNKNOWN || aState & Ci.nsIWebProgressListener.STATE_IS_BROKEN) {
       return result;
     }
 
-    // Ideally we'd just make this a Java string
-    result.encrypted = Strings.browser.GetStringFromName("identity.encrypted2");
+    result.encrypted = true;
     result.host = this.getEffectiveHost();
 
     let iData = this.getIdentityData();
     result.verifier = Strings.browser.formatStringFromName("identity.identified.verifier", [iData.caOrg], 1);
 
     // If the cert is identified, then we can populate the results with credentials
     if (aState & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL) {
       result.owner = iData.subjectOrg;
--- a/mobile/android/locales/en-US/chrome/browser.properties
+++ b/mobile/android/locales/en-US/chrome/browser.properties
@@ -93,17 +93,16 @@ xpinstallDisabledMessageLocked=Software 
 xpinstallDisabledMessage2=Software installation is currently disabled. Press Enable and try again.
 xpinstallDisabledButton=Enable
 
 # Site Identity
 identity.identified.verifier=Verified by: %S
 identity.identified.verified_by_you=You have added a security exception for this site
 identity.identified.state_and_country=%S, %S
 identity.identified.title_with_country=%S (%S)
-identity.encrypted2=Encrypted
 
 # Geolocation UI
 geolocation.allow=Share
 geolocation.dontAllow=Don't share
 geolocation.ask=Share your location with %S?
 # LOCALIZATION NOTE (geolocation.shareLocation): Label that will be used in
 # site settings dialog.
 geolocation.shareLocation=Share Location