diff --git a/CLOBBER b/CLOBBER index 6881acdc0fcf..a69337ad6c5e 100644 --- a/CLOBBER +++ b/CLOBBER @@ -22,4 +22,4 @@ # changes to stick? As of bug 928195, this shouldn't be necessary! Please # don't change CLOBBER for WebIDL changes any more. -Bug 1210154 - Update the clang toolchain +Bug 1215696 - Update mp4parse to v0.1.1 diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 7acdef9e1527..88e5edac66da 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -257,6 +257,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode", XPCOMUtils.defineLazyModuleGetter(this, "ReaderParent", "resource:///modules/ReaderParent.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerParent", + "resource://gre/modules/LoginManagerParent.jsm"); + var gInitialPages = [ "about:blank", "about:newtab", @@ -1194,6 +1197,10 @@ var gBrowserInit = { } }, false, true); + gBrowser.addEventListener("InsecureLoginFormsStateChange", function() { + gIdentityHandler.refreshForInsecureLoginForms(); + }); + let uriToLoad = this._getUriToLoad(); if (uriToLoad && uriToLoad != "about:blank") { if (uriToLoad instanceof Ci.nsISupportsArray) { @@ -7056,9 +7063,7 @@ var gIdentityHandler = { } // Then, update the user interface with the available data. - if (this._identityBox) { - this.refreshIdentityBlock(); - } + this.refreshIdentityBlock(); // Handle a location change while the Control Center is focused // by closing the popup (bug 1207542) if (shouldHidePopup) { @@ -7071,6 +7076,20 @@ var gIdentityHandler = { // information we don't want to suddenly change the panel contents. }, + /** + * This is called asynchronously when requested by the Logins module, after + * the insecure login forms state for the page has been updated. + */ + refreshForInsecureLoginForms() { + // Check this._uri because we don't want to refresh the user interface if + // this is called before the first page load in the window for any reason. + if (!this._uri) { + Cu.reportError("Unexpected early call to refreshForInsecureLoginForms."); + return; + } + this.refreshIdentityBlock(); + }, + /** * Attempt to provide proper IDN treatment for host names */ @@ -7107,6 +7126,10 @@ var gIdentityHandler = { * Updates the identity block user interface with the data from this object. */ refreshIdentityBlock() { + if (!this._identityBox) { + return; + } + let icon_label = ""; let tooltip = ""; let icon_country_label = ""; @@ -7175,6 +7198,11 @@ var gIdentityHandler = { this._identityBox.classList.add("weakCipher"); } } + if (LoginManagerParent.hasInsecureLoginForms(gBrowser.selectedBrowser)) { + // Insecure login forms can only be present on "unknown identity" + // pages, either already insecure or with mixed active content loaded. + this._identityBox.classList.add("insecureLoginForms"); + } tooltip = gNavigatorBundle.getString("identity.unknown.tooltip"); } @@ -7212,6 +7240,12 @@ var gIdentityHandler = { connection = "secure"; } + // Determine if there are insecure login forms. + let loginforms = "secure"; + if (LoginManagerParent.hasInsecureLoginForms(gBrowser.selectedBrowser)) { + loginforms = "insecure"; + } + // Determine the mixed content state. let mixedcontent = []; if (this._isMixedPassiveContentLoaded) { @@ -7249,6 +7283,7 @@ var gIdentityHandler = { for (let id of elementIDs) { let element = document.getElementById(id); updateAttribute(element, "connection", connection); + updateAttribute(element, "loginforms", loginforms); updateAttribute(element, "ciphers", ciphers); updateAttribute(element, "mixedcontent", mixedcontent); updateAttribute(element, "isbroken", this._isBroken); diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini index 0af044441ef3..c50ddb821f15 100644 --- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -268,7 +268,7 @@ tags = mcb tags = mcb [browser_bug906190.js] tags = mcb -skip-if = buildapp == "mulet" || e10s # Bug 1093642 - test manipulates content and relies on content focus +skip-if = buildapp == "mulet" || e10s || os == "linux" # Bug 1093642 - test manipulates content and relies on content focus, Bug 1212520 - Re-enable on Linux [browser_mixedContentFromOnunload.js] tags = mcb [browser_mixedContentFramesOnHttp.js] @@ -322,6 +322,7 @@ skip-if = e10s # Bug 863514 - no gesture support. [browser_homeDrop.js] skip-if = buildapp == 'mulet' [browser_identity_UI.js] +[browser_insecureLoginForms.js] [browser_keywordBookmarklets.js] skip-if = e10s # Bug 1102025 - different principals for the bookmarklet only in e10s mode (unclear if test or 'real' issue) [browser_keywordSearch.js] diff --git a/browser/base/content/test/general/browser_insecureLoginForms.js b/browser/base/content/test/general/browser_insecureLoginForms.js new file mode 100644 index 000000000000..fabb66cbfb91 --- /dev/null +++ b/browser/base/content/test/general/browser_insecureLoginForms.js @@ -0,0 +1,92 @@ +/* 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/"; + +/** + * 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); +} + +/** + * Checks the insecure login forms logic for the identity block. + */ +add_task(function* test_simple() { + for (let scheme of ["http", "https"]) { + let tab = gBrowser.addTab(scheme + 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") { + 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"), "") + .getPropertyValue("background-image"); + is(identityBoxImage, + "url(\"chrome://browser/skin/identity-mixed-active-loaded.svg\")", + "Using expected icon image in the identity block"); + is(securityViewBG, + "url(\"chrome://browser/skin/controlcenter/mcb-disabled.svg\")", + "Using expected icon image in the Control Center main view"); + is(securityContentBG, + "url(\"chrome://browser/skin/controlcenter/mcb-disabled.svg\")", + "Using expected icon image in the Control Center subview"); + } + + // 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."); + + 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 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), + ]); + + assertMixedContentBlockingState(browser, { activeLoaded: true, + activeBlocked: false, + passiveLoaded: false }); + + gBrowser.removeTab(tab); +}); diff --git a/browser/base/content/test/general/head.js b/browser/base/content/test/general/head.js index 86adcb9e53fc..c202c592a9e9 100644 --- a/browser/base/content/test/general/head.js +++ b/browser/base/content/test/general/head.js @@ -890,6 +890,13 @@ function assertMixedContentBlockingState(tabbrowser, states = {}) { } } + if (activeLoaded || activeBlocked || passiveLoaded) { + doc.getElementById("identity-popup-security-expander").click(); + is(Array.filter(doc.querySelectorAll("[observes=identity-popup-mcb-learn-more]"), + element => !is_hidden(element)).length, 1, + "The 'Learn more' link should be visible once."); + } + gIdentityHandler._identityPopup.hidden = true; } diff --git a/browser/components/controlcenter/content/panel.inc.xul b/browser/components/controlcenter/content/panel.inc.xul index 2648b93d8640..205a7df6ca83 100644 --- a/browser/components/controlcenter/content/panel.inc.xul +++ b/browser/components/controlcenter/content/panel.inc.xul @@ -41,6 +41,7 @@ &identity.activeLoaded; &identity.weakEncryption; + &identity.insecureLoginForms;