Bug 1217133 - Don't warn about insecure passwords on localhost pages. r=paolo,MattN a=ritu
authorPanos Astithas <past@mozilla.com>
Wed, 11 Nov 2015 08:39:06 +0200
changeset 305534 e792fb3161930b312a413fe92ae53da747f3cc89
parent 305533 c9902056c1842019b9ad58f6aaf6c0f0cc7b8756
child 305535 2c5f51e5d0afeff3b547ecaa3d45965a4f5a8cda
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspaolo, MattN, ritu
bugs1217133
milestone44.0a2
Bug 1217133 - Don't warn about insecure passwords on localhost pages. r=paolo,MattN a=ritu
browser/base/content/test/general/browser_insecureLoginForms.js
dom/interfaces/security/nsIContentSecurityManager.idl
toolkit/components/passwordmgr/LoginManagerContent.jsm
--- a/browser/base/content/test/general/browser_insecureLoginForms.js
+++ b/browser/base/content/test/general/browser_insecureLoginForms.js
@@ -1,14 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Load directly from the browser-chrome support files of login tests.
-const testUrlPath =
-      "://example.com/browser/toolkit/components/passwordmgr/test/browser/";
+const TEST_URL_PATH = "/browser/toolkit/components/passwordmgr/test/browser/";
 
 /**
  * Waits for the given number of occurrences of InsecureLoginFormsStateChange
  * on the given browser element.
  */
 function waitForInsecureLoginFormsStateChange(browser, count) {
   return BrowserTestUtils.waitForEvent(browser, "InsecureLoginFormsStateChange",
                                        false, () => --count == 0);
@@ -17,31 +16,36 @@ function waitForInsecureLoginFormsStateC
 /**
  * Checks the insecure login forms logic for the identity block.
  */
 add_task(function* test_simple() {
   yield new Promise(resolve => SpecialPowers.pushPrefEnv({
     "set": [["security.insecure_password.ui.enabled", true]],
   }, resolve));
 
-  for (let scheme of ["http", "https"]) {
-    let tab = gBrowser.addTab(scheme + testUrlPath + "form_basic.html");
+  for (let [origin, expectWarning] of [
+    ["http://example.com", true],
+    ["http://127.0.0.1", false],
+    ["https://example.com", false],
+  ]) {
+    let testUrlPath = origin + TEST_URL_PATH;
+    let tab = gBrowser.addTab(testUrlPath + "form_basic.html");
     let browser = tab.linkedBrowser;
     yield Promise.all([
       BrowserTestUtils.switchTab(gBrowser, tab),
       BrowserTestUtils.browserLoaded(browser),
       // One event is triggered by pageshow and one by DOMFormHasPassword.
       waitForInsecureLoginFormsStateChange(browser, 2),
     ]);
 
     let { gIdentityHandler } = gBrowser.ownerGlobal;
     gIdentityHandler._identityBox.click();
     document.getElementById("identity-popup-security-expander").click();
 
-    if (scheme == "http") {
+    if (expectWarning) {
       let identityBoxImage = gBrowser.ownerGlobal
             .getComputedStyle(document.getElementById("page-proxy-favicon"), "")
             .getPropertyValue("list-style-image");
       let securityViewBG = gBrowser.ownerGlobal
             .getComputedStyle(document.getElementById("identity-popup-securityView"), "")
             .getPropertyValue("background-image");
       let securityContentBG = gBrowser.ownerGlobal
             .getComputedStyle(document.getElementById("identity-popup-security-content"), "")
@@ -59,34 +63,35 @@ add_task(function* test_simple() {
                       element => !is_hidden(element)).length, 1,
          "The 'Learn more' link should be visible once.");
     }
 
     // Messages should be visible when the scheme is HTTP, and invisible when
     // the scheme is HTTPS.
     is(Array.every(document.querySelectorAll("[when-loginforms=insecure]"),
                    element => !is_hidden(element)),
-       scheme == "http",
-       "The relevant messages should visible or hidden.");
+       expectWarning,
+       "The relevant messages should be visible or hidden.");
 
     gIdentityHandler._identityPopup.hidden = true;
     gBrowser.removeTab(tab);
   }
 });
 
 /**
  * Checks that the insecure login forms logic does not regress mixed content
  * blocking messages when mixed active content is loaded.
  */
 add_task(function* test_mixedcontent() {
   yield new Promise(resolve => SpecialPowers.pushPrefEnv({
     "set": [["security.mixed_content.block_active_content", false]],
   }, resolve));
 
   // Load the page with the subframe in a new tab.
+  let testUrlPath = "://example.com" + TEST_URL_PATH;
   let tab = gBrowser.addTab("https" + testUrlPath + "insecure_test.html");
   let browser = tab.linkedBrowser;
   yield Promise.all([
     BrowserTestUtils.switchTab(gBrowser, tab),
     BrowserTestUtils.browserLoaded(browser),
     // Two events are triggered by pageshow and one by DOMFormHasPassword.
     waitForInsecureLoginFormsStateChange(browser, 3),
   ]);
--- a/dom/interfaces/security/nsIContentSecurityManager.idl
+++ b/dom/interfaces/security/nsIContentSecurityManager.idl
@@ -41,14 +41,14 @@ interface nsIContentSecurityManager : ns
    nsIStreamListener performSecurityCheck(in nsIChannel aChannel,
                                           in nsIStreamListener aStreamListener);
 
   /**
    * Implementation of
    * https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy
    *
    * This method should only be used when the context of the URI isn't available
-   * since isSecureContext is preffered as it handles parent contexts.
+   * since isSecureContext is preferred as it handles parent contexts.
    *
    * This method returns false instead of throwing upon errors.
    */
   boolean isURIPotentiallyTrustworthy(in nsIURI aURI);
 };
--- a/toolkit/components/passwordmgr/LoginManagerContent.jsm
+++ b/toolkit/components/passwordmgr/LoginManagerContent.jsm
@@ -17,16 +17,20 @@ Cu.import("resource://gre/modules/Promis
 
 XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask", "resource://gre/modules/DeferredTask.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "LoginRecipesContent",
                                   "resource://gre/modules/LoginRecipes.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
                                   "resource://gre/modules/LoginHelper.jsm");
 
+XPCOMUtils.defineLazyServiceGetter(this, "gContentSecurityManager",
+                                   "@mozilla.org/contentsecuritymanager;1",
+                                   "nsIContentSecurityManager");
+
 XPCOMUtils.defineLazyGetter(this, "log", () => {
   let logger = LoginHelper.createLogger("LoginManagerContent");
   return logger.log.bind(logger);
 });
 
 // These mirror signon.* prefs.
 var gEnabled, gAutofillForms, gStoreWhenAutocompleteOff;
 
@@ -1130,17 +1134,19 @@ var LoginManagerContent = {
    *   both places. Look at
    *   https://bugzilla.mozilla.org/show_bug.cgi?id=899099 for more info.
    */
   checkIfURIisSecure : function(uri) {
     let isSafe = false;
     let netutil = Cc["@mozilla.org/network/util;1"].getService(Ci.nsINetUtil);
     let ph = Ci.nsIProtocolHandler;
 
-    if (netutil.URIChainHasFlags(uri, ph.URI_IS_LOCAL_RESOURCE) ||
+    // Is the connection to localhost? Consider localhost safe for passwords.
+    if (gContentSecurityManager.isURIPotentiallyTrustworthy(uri) ||
+        netutil.URIChainHasFlags(uri, ph.URI_IS_LOCAL_RESOURCE) ||
         netutil.URIChainHasFlags(uri, ph.URI_DOES_NOT_RETURN_DATA) ||
         netutil.URIChainHasFlags(uri, ph.URI_INHERITS_SECURITY_CONTEXT) ||
         netutil.URIChainHasFlags(uri, ph.URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT)) {
 
       isSafe = true;
     }
 
     return isSafe;