Bug 1099088 - Part 1: Add CHROMEUI SiteIdentity for about: pages r=liuche
This replicates desktop behaviour.
--- a/mobile/android/base/java/org/mozilla/gecko/SiteIdentity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/SiteIdentity.java
@@ -23,31 +23,32 @@ public class SiteIdentity {
private String mVerifier;
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");
+ VERIFIED("verified"),
+ CHROMEUI("chromeUI");
private final String mId;
private SecurityMode(String id) {
mId = id;
}
public static SecurityMode fromString(String id) {
if (id == null) {
throw new IllegalArgumentException("Can't convert null String to SiteIdentity");
}
for (SecurityMode mode : SecurityMode.values()) {
- if (TextUtils.equals(mode.mId, id.toLowerCase())) {
+ if (TextUtils.equals(mode.mId, id)) {
return mode;
}
}
throw new IllegalArgumentException("Could not convert String id to SiteIdentity");
}
@Override
@@ -175,20 +176,20 @@ public class SiteIdentity {
mSecurityMode = SecurityMode.fromString(mode.getString("identity"));
} catch (Exception e) {
resetIdentity();
return;
}
try {
mOrigin = identityData.getString("origin");
- mHost = identityData.getString("host");
+ mHost = identityData.optString("host", null);
mOwner = identityData.optString("owner", null);
mSupplemental = identityData.optString("supplemental", null);
- mVerifier = identityData.getString("verifier");
+ mVerifier = identityData.optString("verifier", null);
mSecure = identityData.optBoolean("secure", false);
} catch (Exception e) {
resetIdentity();
}
} catch (Exception e) {
reset();
}
}
--- a/mobile/android/base/java/org/mozilla/gecko/toolbar/SiteIdentityPopup.java
+++ b/mobile/android/base/java/org/mozilla/gecko/toolbar/SiteIdentityPopup.java
@@ -135,17 +135,18 @@ public class SiteIdentityPopup extends A
mSiteSettingsLink = (TextView) mIdentity.findViewById(R.id.site_settings_link);
}
private void updateIdentity(final SiteIdentity siteIdentity) {
if (!mInflated) {
init();
}
- final boolean isIdentityKnown = (siteIdentity.getSecurityMode() != SecurityMode.UNKNOWN);
+ final boolean isIdentityKnown = (siteIdentity.getSecurityMode() == SecurityMode.IDENTIFIED ||
+ siteIdentity.getSecurityMode() == SecurityMode.VERIFIED);
updateConnectionState(siteIdentity);
toggleIdentityKnownContainerVisibility(isIdentityKnown);
if (isIdentityKnown) {
updateIdentityInformation(siteIdentity);
}
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -6314,16 +6314,19 @@ var IdentityHandler = {
IDENTITY_MODE_UNKNOWN: "unknown",
// Domain-Validation SSL CA-signed domain verification (DV).
IDENTITY_MODE_IDENTIFIED: "identified",
// Extended-Validation SSL CA-signed identity information (EV). A more rigorous validation process.
IDENTITY_MODE_VERIFIED: "verified",
+ // Part of the product's UI (built in about: pages)
+ IDENTITY_MODE_CHROMEUI: "chromeUI",
+
// The following mixed content modes are only used if "security.mixed_content.block_active_content"
// is enabled. Our Java frontend coalesces them into one indicator.
// No mixed content information. No mixed content icon is shown.
MIXED_MODE_UNKNOWN: "unknown",
// Blocked active mixed content.
MIXED_MODE_CONTENT_BLOCKED: "blocked",
@@ -6378,25 +6381,31 @@ var IdentityHandler = {
result.cert = cert;
return result;
},
/**
* Determines the identity mode corresponding to the icon we show in the urlbar.
*/
- getIdentityMode: function getIdentityMode(aState) {
+ getIdentityMode: function getIdentityMode(aState, uri) {
if (aState & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL) {
return this.IDENTITY_MODE_VERIFIED;
}
if (aState & Ci.nsIWebProgressListener.STATE_IS_SECURE) {
return this.IDENTITY_MODE_IDENTIFIED;
}
+ // We also allow "about:" by allowing the selector to be empty (i.e. '(|.....|...|...)'
+ let whitelist = /^about:($|about|accounts|addons|buildconfig|cache|config|crashes|devices|downloads|fennec|firefox|feedback|healthreport|license|logins|logo|memory|mozilla|networking|plugins|privatebrowsing|rights|serviceworkers|support|telemetry|webrtc)($|\?)/i;
+ if (uri.schemeIs("about") && whitelist.test(uri.spec)) {
+ return this.IDENTITY_MODE_CHROMEUI;
+ }
+
return this.IDENTITY_MODE_UNKNOWN;
},
getMixedDisplayMode: function getMixedDisplayMode(aState) {
if (aState & Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT) {
return this.MIXED_MODE_CONTENT_LOADED;
}
@@ -6481,33 +6490,43 @@ var IdentityHandler = {
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 uri = aBrowser.currentURI;
+ try {
+ uri = Services.uriFixup.createExposableURI(uri);
+ } catch (e) {}
+
+ let identityMode = this.getIdentityMode(aState, uri);
let mixedDisplay = this.getMixedDisplayMode(aState);
let mixedActive = this.getMixedActiveMode(aState);
let trackingMode = this.getTrackingMode(aState, aBrowser);
let result = {
origin: locationObj.origin,
mode: {
identity: identityMode,
mixed_display: mixedDisplay,
mixed_active: mixedActive,
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) {
+ // We also return for CHROMEUI pages since they don't have any certificate
+ // information to load either. result.secure specifically refers to connection
+ // security, which is irrelevant for about: pages, as they're loaded locally.
+ if (identityMode == this.IDENTITY_MODE_UNKNOWN ||
+ identityMode == this.IDENTITY_MODE_CHROMEUI ||
+ aState & Ci.nsIWebProgressListener.STATE_IS_BROKEN) {
result.secure = false;
return result;
}
result.secure = true;
result.host = this.getEffectiveHost();
--- a/mobile/android/tests/browser/chrome/chrome.ini
+++ b/mobile/android/tests/browser/chrome/chrome.ini
@@ -15,16 +15,17 @@ support-files =
[test_accounts.html]
[test_android_log.html]
[test_app_constants.html]
[test_debugger_server.html]
[test_desktop_useragent.html]
[test_device_search_engine.html]
[test_get_last_visited.html]
[test_home_provider.html]
+[test_identity_mode.html]
[test_java_addons.html]
[test_jni.html]
[test_migrate_ui.html]
[test_network_manager.html]
[test_offline_page.html]
[test_reader_view.html]
[test_resource_substitutions.html]
[test_restricted_profiles.html]
new file mode 100644
--- /dev/null
+++ b/mobile/android/tests/browser/chrome/test_identity_mode.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1099088
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for getIdentityMode</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="head.js"></script>
+ <script type="application/javascript;version=1.7">
+
+ "use strict";
+
+ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+ Cu.import("resource://gre/modules/Services.jsm");
+
+ let chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
+ let IdentityHandler = chromeWin.IdentityHandler;
+
+ ok(IdentityHandler.getIdentityMode(0, Services.io.newURI("about:", null, null)) == IdentityHandler.IDENTITY_MODE_CHROMEUI,
+ "'about:' is a verified internal page");
+ ok(IdentityHandler.getIdentityMode(0, Services.io.newURI("about:config", null, null)) == IdentityHandler.IDENTITY_MODE_CHROMEUI,
+ "'about:config' is a verified internal page");
+ ok(IdentityHandler.getIdentityMode(0, Services.io.newURI("about:accounts", null, null)) == IdentityHandler.IDENTITY_MODE_CHROMEUI,
+ "'about:accounts is a verified internal page");
+ ok(IdentityHandler.getIdentityMode(0, Services.io.newURI("about:addonss", null, null)) == IdentityHandler.IDENTITY_MODE_UNKNOWN,
+ "'about:addonss is not a verified internal page");
+ ok(IdentityHandler.getIdentityMode(0, Services.io.newURI("about:accountss", null, null)) == IdentityHandler.IDENTITY_MODE_UNKNOWN,
+ "'about:accountss is not a verified internal page");
+ ok(IdentityHandler.getIdentityMode(0, Services.io.newURI("about:accounts?action=signup", null, null)) == IdentityHandler.IDENTITY_MODE_CHROMEUI,
+ "'about:accounts?action=signup is a verified internal page");
+ ok(IdentityHandler.getIdentityMode(0, Services.io.newURI("about:evil_extension_page", null, null)) == IdentityHandler.IDENTITY_MODE_UNKNOWN,
+ "'about:evil_extension_page' is not a verified internal page");
+
+ ok(IdentityHandler.getIdentityMode(0, Services.io.newURI("http://mozilla.com", null, null)) == IdentityHandler.IDENTITY_MODE_UNKNOWN,
+ "http://mozilla.com is an unknown page");
+ ok(IdentityHandler.getIdentityMode(0, Services.io.newURI("https://mozilla.com", null, null)) == IdentityHandler.IDENTITY_MODE_UNKNOWN,
+ "https://mozilla.com over an insecure connection is an unknown page");
+ ok(IdentityHandler.getIdentityMode(Ci.nsIWebProgressListener.STATE_IS_SECURE, Services.io.newURI("https://mozilla.com", null, null)) == IdentityHandler.IDENTITY_MODE_IDENTIFIED,
+ "https://mozilla.com over a secure connection is a verified page");
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1099088">Mozilla Bug 1099088</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>