Bug 695477 - Use an indicator in toolbar to reflect security state [r=mfinkle, r=sriram]
authorJulien Vermet <ju.vermet@gmail.com>
Thu, 03 Nov 2011 18:53:34 -0400
changeset 83364 149e1178490fcf541f6019dd291e227abfeaa2fa
parent 83363 cae6fd409f5a0734e7a790d976f2071a2949771e
child 83365 ae273c520ce271f4fcef715b28f0870fb7cf17aa
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle, sriram
bugs695477
milestone10.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 695477 - Use an indicator in toolbar to reflect security state [r=mfinkle, r=sriram]
embedding/android/BrowserToolbar.java
embedding/android/GeckoApp.java
embedding/android/Tab.java
mobile/chrome/content/browser.js
--- a/embedding/android/BrowserToolbar.java
+++ b/embedding/android/BrowserToolbar.java
@@ -38,16 +38,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko;
 
 import android.content.Context;
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.Color;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.Button;
 import android.widget.ImageButton;
 import android.widget.LinearLayout;
 
 public class BrowserToolbar extends LinearLayout {
@@ -123,9 +124,18 @@ public class BrowserToolbar extends Line
         if (Tabs.getInstance().getSelectedTab().isLoading())
             return;
 
         if (image != null)
             mFavicon.setImageDrawable(image);
         else
             mFavicon.setImageResource(R.drawable.favicon);
     }
+    
+    public void setSecurityMode(String mode) {
+        if (mode.equals("identified"))
+            mFavicon.setBackgroundColor(Color.rgb(137, 215, 21));
+        else if (mode.equals("verified"))
+            mFavicon.setBackgroundColor(Color.rgb(101, 121, 227));
+        else
+            mFavicon.setBackgroundColor(Color.TRANSPARENT);
+    }
 }
--- a/embedding/android/GeckoApp.java
+++ b/embedding/android/GeckoApp.java
@@ -579,28 +579,45 @@ abstract public class GeckoApp
 
         if (oldBaseURI != null && oldBaseURI.indexOf('#') != -1)
             oldBaseURI = oldBaseURI.substring(0, oldBaseURI.indexOf('#'));
         
         if (baseURI.equals(oldBaseURI))
             return;
 
         tab.updateFavicon(null);
+        tab.updateSecurityMode("unknown");
 
         mMainHandler.post(new Runnable() {
             public void run() {
                 mAppContext.mDoorHanger.removeForTab(tabId);
                 if (Tabs.getInstance().isSelectedTab(tab)) {
                     mBrowserToolbar.setTitle(uri);
                     mBrowserToolbar.setFavicon(null);
+                    mBrowserToolbar.setSecurityMode("unknown");
                 }
             }
         });
     }
 
+    void handleSecurityChange(final int tabId, final String mode) {
+        final Tab tab = Tabs.getInstance().getTab(tabId);
+        if (tab == null)
+            return;
+
+        tab.updateSecurityMode(mode);
+        
+        mMainHandler.post(new Runnable() { 
+            public void run() {
+                if (Tabs.getInstance().isSelectedTab(tab))
+                    mBrowserToolbar.setSecurityMode(mode);
+            }
+        });
+    }
+
     void addTab() {
         Intent intent = new Intent(mAppContext, AwesomeBar.class);
         intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NO_HISTORY);
         intent.putExtra(AwesomeBar.TYPE_KEY, AwesomeBar.Type.ADD.name());
         startActivityForResult(intent, AWESOMEBAR_REQUEST);
     }
 
     void showTabs() {
@@ -682,22 +699,27 @@ abstract public class GeckoApp
                 final String rel = message.getString("rel");
                 final String href = message.getString("href");
                 Log.i(LOG_NAME, "link rel - " + rel + ", href - " + href);
                 handleLinkAdded(tabId, rel, href);
             } else if (event.equals("log")) {
                 // generic log listener
                 final String msg = message.getString("msg");
                 Log.i(LOG_NAME, "Log: " + msg);
-            } else if (event.equals("onLocationChange")) {
+            } else if (event.equals("Content:LocationChange")) {
                 final int tabId = message.getInt("tabID");
                 final String uri = message.getString("uri");
                 Log.i(LOG_NAME, "URI - " + uri);
                 handleLocationChange(tabId, uri);
-            } else if (event.equals("onStateChange")) {
+            } else if (event.equals("Content:SecurityChange")) {
+                final int tabId = message.getInt("tabID");
+                final String mode = message.getString("mode");
+                Log.i(LOG_NAME, "Security Mode - " + mode);
+                handleSecurityChange(tabId, mode);
+            } else if (event.equals("Content:StateChange")) {
                 final int tabId = message.getInt("tabID");
                 int state = message.getInt("state");
                 Log.i(LOG_NAME, "State - " + state);
                 if ((state & GeckoAppShell.WPL_STATE_IS_DOCUMENT) != 0) {
                     if ((state & GeckoAppShell.WPL_STATE_START) != 0) {
                         Log.i(LOG_NAME, "Got a document start");
                         handleDocumentStart(tabId);
                     } else if ((state & GeckoAppShell.WPL_STATE_STOP) != 0) {
@@ -805,34 +827,38 @@ abstract public class GeckoApp
         if (tab == null)
             return;
 
         mMainHandler.post(new Runnable() { 
             public void run() {
                 if (Tabs.getInstance().isSelectedTab(tab)) {
                     mBrowserToolbar.setTitle(tab.getDisplayTitle());
                     mBrowserToolbar.setFavicon(tab.getFavicon());
+                    mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
                     mBrowserToolbar.setProgressVisibility(tab.isLoading());
                     mDoorHanger.updateForTab(tab.getId());
                 }
             }
         });
     }
 
     void handleDocumentStart(int tabId) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
         tab.setLoading(true);
-        
+        tab.updateSecurityMode("unknown");
+
         mMainHandler.post(new Runnable() {
             public void run() {
-                if (Tabs.getInstance().isSelectedTab(tab))
+                if (Tabs.getInstance().isSelectedTab(tab)) {
+                    mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
                     mBrowserToolbar.setProgressVisibility(true);
+                }
                 onTabsChanged();
             }
         });
     }
 
     void handleDocumentStop(int tabId) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
@@ -1029,18 +1055,19 @@ abstract public class GeckoApp
             });
         }
 
         //register for events
         GeckoAppShell.registerGeckoEventListener("DOMContentLoaded", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("DOMTitleChanged", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("DOMLinkAdded", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("log", GeckoApp.mAppContext);
-        GeckoAppShell.registerGeckoEventListener("onLocationChange", GeckoApp.mAppContext);
-        GeckoAppShell.registerGeckoEventListener("onStateChange", GeckoApp.mAppContext);
+        GeckoAppShell.registerGeckoEventListener("Content:LocationChange", GeckoApp.mAppContext);
+        GeckoAppShell.registerGeckoEventListener("Content:SecurityChange", GeckoApp.mAppContext);
+        GeckoAppShell.registerGeckoEventListener("Content:StateChange", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("onCameraCapture", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Tab:Added", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Tab:Closed", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Tab:Selected", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Doorhanger:Add", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Menu:Add", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Menu:Remove", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Preferences:Data", GeckoApp.mAppContext);
@@ -1212,18 +1239,19 @@ abstract public class GeckoApp
         // in onXreExit.
         if (isFinishing())
             GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_SHUTDOWN));
         
         GeckoAppShell.unregisterGeckoEventListener("DOMContentLoaded", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("DOMTitleChanged", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("DOMLinkAdded", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("log", GeckoApp.mAppContext);
-        GeckoAppShell.unregisterGeckoEventListener("onLocationChange", GeckoApp.mAppContext);
-        GeckoAppShell.unregisterGeckoEventListener("onStateChange", GeckoApp.mAppContext);
+        GeckoAppShell.unregisterGeckoEventListener("Content:LocationChange", GeckoApp.mAppContext);
+        GeckoAppShell.unregisterGeckoEventListener("Content:SecurityChange", GeckoApp.mAppContext);
+        GeckoAppShell.unregisterGeckoEventListener("Content:StateChange", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("onCameraCapture", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Tab:Added", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Tab:Closed", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Tab:Selected", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Doorhanger:Add", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Menu:Add", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Menu:Remove", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Preferences:Data", GeckoApp.mAppContext);
--- a/embedding/android/Tab.java
+++ b/embedding/android/Tab.java
@@ -58,16 +58,17 @@ import java.util.List;
 
 public class Tab {
 
     private static final String LOG_NAME = "Tab";
     private int mId;
     private String mUrl;
     private String mTitle;
     private Drawable mFavicon;
+    private String mSecurityMode;
     private Drawable mThumbnail;
     private List<HistoryEntry> mHistory;
     private int mHistoryIndex;
     private boolean mLoading;
     private boolean mBookmark;
     private DownloadFaviconTask mFaviconDownloader;
 
     static class HistoryEntry {
@@ -84,16 +85,17 @@ public class Tab {
         this(-1, "");
     }
 
     public Tab(int id, String url) {
         mId = id;
         mUrl = url;
         mTitle = new String();
         mFavicon = null;
+        mSecurityMode = "unknown";
         mThumbnail = null;
         mHistory = new ArrayList<HistoryEntry>();
         mHistoryIndex = -1;
         mBookmark = false;
     }
 
     public int getId() {
         return mId;
@@ -114,16 +116,20 @@ public class Tab {
 
         return mUrl;
     }
 
     public Drawable getFavicon() {
         return mFavicon;
     }
 
+    public String getSecurityMode() {
+        return mSecurityMode;
+    }
+
     public boolean isLoading() {
         return mLoading;
     }
 
     public boolean isBookmark() {
         return mBookmark;
     }
 
@@ -171,16 +177,20 @@ public class Tab {
         return mHistory.get(mHistoryIndex);
     }
 
     public void updateFavicon(Drawable favicon) {
         mFavicon = favicon;
         Log.i(LOG_NAME, "Updated favicon for tab with id: " + mId);
     }
  
+    public void updateSecurityMode(String mode) {
+        mSecurityMode = mode;
+    }
+
     private void updateBookmark() {
         new CheckBookmarkTask().execute();
     }
 
     public void addBookmark() {
         new AddBookmarkTask().execute();
     }
 
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -874,17 +874,18 @@ Tab.prototype = {
         type: "Tab:Added",
         tabID: this.id,
         uri: aURL
       }
     };
     sendMessageToJava(message);
 
     let flags = Ci.nsIWebProgress.NOTIFY_STATE_ALL |
-                Ci.nsIWebProgress.NOTIFY_LOCATION;
+                Ci.nsIWebProgress.NOTIFY_LOCATION |
+                Ci.nsIWebProgress.NOTIFY_SECURITY;
     this.browser.addProgressListener(this, flags);
     this.browser.sessionHistory.addSHistoryListener(this);
     this.browser.loadURI(aURL);
   },
 
   destroy: function() {
     if (!this.browser)
       return;
@@ -926,17 +927,17 @@ Tab.prototype = {
       // Filter optimization: Only really send DOCUMENT state changes to Java listener
       let browser = BrowserApp.getBrowserForWindow(aWebProgress.DOMWindow);
       let uri = "";
       if (browser)
         uri = browser.currentURI.spec;
   
       let message = {
         gecko: {
-          type: "onStateChange",
+          type: "Content:StateChange",
           tabID: this.id,
           uri: uri,
           state: aStateFlags
         }
       };
   
       sendMessageToJava(message);
     }
@@ -947,26 +948,45 @@ Tab.prototype = {
     if (contentWin != contentWin.top)
         return;
 
     let browser = BrowserApp.getBrowserForWindow(contentWin);
     let uri = browser.currentURI.spec;
 
     let message = {
       gecko: {
-        type: "onLocationChange",
+        type: "Content:LocationChange",
         tabID: this.id,
         uri: uri
       }
     };
 
     sendMessageToJava(message);
   },
 
-  onSecurityChange: function(aBrowser, aWebProgress, aRequest, aState) {
+  onSecurityChange: function(aWebProgress, aRequest, aState) {
+    let mode = "unknown";
+    if (aState & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL)
+      mode = "identified";
+    else if (aState & Ci.nsIWebProgressListener.STATE_SECURE_HIGH)
+      mode = "verified";
+    else if (aState & Ci.nsIWebProgressListener.STATE_IS_BROKEN)
+      mode = "mixed";
+    else
+      mode = "unknown";
+
+   let message = {
+      gecko: {
+        type: "Content:SecurityChange",
+        tabID: this.id,
+        mode: mode
+      }
+    };
+
+     sendMessageToJava(message);
   },
 
   onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {
   },
 
   onStatusChange: function(aBrowser, aWebProgress, aRequest, aStatus, aMessage) {
   },