From 975f9b571eb76ffb672c4bf13d6cc2f50843dd89 Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Fri, 9 Dec 2016 14:17:12 -1000 Subject: [PATCH 01/25] Bug 1321556 - Remove unused bindings from urlbarbindings.xml. r=dao MozReview-Commit-ID: FfIsoh76ajn --HG-- extra : rebase_source : cfc30eb7a1d9961d108dbad9ca0fb32d5c208043 --- browser/base/content/browser-places.js | 1 - browser/base/content/browser.css | 8 +- browser/base/content/urlbarBindings.xml | 126 +----------------------- dom/base/nsGkAtomList.h | 1 - layout/xul/nsMenuPopupFrame.cpp | 1 - toolkit/themes/linux/global/menu.css | 7 +- toolkit/themes/windows/global/menu.css | 16 +-- 7 files changed, 9 insertions(+), 151 deletions(-) diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js index b5b5e185dafe..08e326b7e0fe 100644 --- a/browser/base/content/browser-places.js +++ b/browser/base/content/browser-places.js @@ -834,7 +834,6 @@ var BookmarksEventHandler = { if (node.localName == "menupopup") node.hidePopup(); else if (node.localName != "menu" && - node.localName != "splitmenu" && node.localName != "hbox" && node.localName != "vbox" ) break; diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css index b007362fced5..bcdc798e39cf 100644 --- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -434,13 +434,7 @@ toolbar:not(#TabsToolbar) > #personal-bookmarks { background-position: bottom left; } -.menuitem-tooltip { - -moz-binding: url("chrome://browser/content/urlbarBindings.xml#menuitem-tooltip"); -} - -.menuitem-iconic-tooltip, -.menuitem-tooltip[type="checkbox"], -.menuitem-tooltip[type="radio"] { +.menuitem-iconic-tooltip { -moz-binding: url("chrome://browser/content/urlbarBindings.xml#menuitem-iconic-tooltip"); } diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index 2cb7538ae155..b49492b85407 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -2528,131 +2528,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. - - - - - - - - - - - - - - - document.getAnonymousElementByAttribute(this, "anonid", "menuitem"); - - - document.getAnonymousElementByAttribute(this, "anonid", "menu"); - - - 600 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Equals(nsGkAtoms::menu, kNameSpaceID_XUL) || - ni->Equals(nsGkAtoms::splitmenu, kNameSpaceID_XUL) || ni->Equals(nsGkAtoms::popupset, kNameSpaceID_XUL) || ((ni->Equals(nsGkAtoms::button, kNameSpaceID_XUL) || ni->Equals(nsGkAtoms::toolbarbutton, kNameSpaceID_XUL)) && diff --git a/toolkit/themes/linux/global/menu.css b/toolkit/themes/linux/global/menu.css index 06e3b217bddc..386d9116ba8a 100644 --- a/toolkit/themes/linux/global/menu.css +++ b/toolkit/themes/linux/global/menu.css @@ -12,8 +12,7 @@ menu, menuitem, -menucaption, -.splitmenu-menuitem { +menucaption { -moz-appearance: menuitem; -moz-box-align: center; max-width: 42em; @@ -28,15 +27,13 @@ menuitem[default="true"] { } menu[_moz-menuactive="true"], -menuitem[_moz-menuactive="true"], -.splitmenu-menuitem[_moz-menuactive="true"] { +menuitem[_moz-menuactive="true"] { color: -moz-menuhovertext; background-color: -moz-menuhover; } menu[disabled="true"], menuitem[disabled="true"], -.splitmenu-menuitem[disabled="true"], menucaption[disabled="true"] { color: GrayText; } diff --git a/toolkit/themes/windows/global/menu.css b/toolkit/themes/windows/global/menu.css index 2a228251d4b1..aaaa3e1a5798 100644 --- a/toolkit/themes/windows/global/menu.css +++ b/toolkit/themes/windows/global/menu.css @@ -12,8 +12,7 @@ menu, menuitem, -menucaption, -.splitmenu-menuitem { +menucaption { -moz-appearance: menuitem; -moz-box-align: center; color: MenuText; @@ -28,10 +27,8 @@ menuitem[default="true"] { menu[disabled="true"], menuitem[disabled="true"], -.splitmenu-menuitem[disabled="true"], menu[_moz-menuactive="true"][disabled="true"], -menuitem[_moz-menuactive="true"][disabled="true"], -.splitmenu-menuitem[_moz-menuactive="true"][disabled="true"] { +menuitem[_moz-menuactive="true"][disabled="true"] { color: GrayText; text-shadow: none; } @@ -39,8 +36,7 @@ menuitem[_moz-menuactive="true"][disabled="true"], @media (-moz-windows-classic) { menu[disabled="true"], menubar > menu[disabled="true"][_moz-menuactive="true"], - menuitem[disabled="true"], - .splitmenu-menuitem[disabled="true"] { + menuitem[disabled="true"] { color: ThreeDShadow; text-shadow: 1px 1px ThreeDHighlight; } @@ -102,8 +98,7 @@ menucaption > .menu-iconic-text { } menu.menu-iconic > .menu-iconic-left, -menuitem.menuitem-iconic > .menu-iconic-left, -.splitmenu-menuitem[iconic="true"] > .menu-iconic-left { +menuitem.menuitem-iconic > .menu-iconic-left { -moz-appearance: menuimage; padding-top: 2px; } @@ -186,8 +181,7 @@ menupopup > menucaption { } menu[_moz-menuactive="true"], -menuitem[_moz-menuactive="true"], -.splitmenu-menuitem[_moz-menuactive="true"] { +menuitem[_moz-menuactive="true"] { background-color: -moz-menuhover; color: -moz-menuhovertext; } From 96cd40a06293aec910218009bb47facce275d35f Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Thu, 15 Dec 2016 00:58:21 +0100 Subject: [PATCH 02/25] Bug 1323600 - Some fields have been converted to properties and won't reset anymore when the binding is recreated. r=mossop MozReview-Commit-ID: CHxBFpbW6aS --HG-- extra : rebase_source : caa8602ca6e0648b8f52e8de9c430298528d3286 --- toolkit/content/widgets/autocomplete.xml | 16 ++++++------ toolkit/content/widgets/tabbox.xml | 32 ++++++++++++------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/toolkit/content/widgets/autocomplete.xml b/toolkit/content/widgets/autocomplete.xml index e7da8e962055..ac20f255a93f 100644 --- a/toolkit/content/widgets/autocomplete.xml +++ b/toolkit/content/widgets/autocomplete.xml @@ -69,8 +69,15 @@ + null diff --git a/toolkit/content/widgets/tabbox.xml b/toolkit/content/widgets/tabbox.xml index 107e12ee9a04..c142c29d07ce 100644 --- a/toolkit/content/widgets/tabbox.xml +++ b/toolkit/content/widgets/tabbox.xml @@ -347,8 +347,15 @@ + null @@ -642,8 +642,15 @@ + null From 3a04c5d5139e34c9ff02b35a060118651b9550f2 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Thu, 8 Dec 2016 16:31:51 -1000 Subject: [PATCH 03/25] Bug 1322606: Don't hide MediaError::message behind a pref. r=Ehsan MozReview-Commit-ID: y2Wbf7amvQ --HG-- extra : rebase_source : ba2283adc0cce64fc3facec43d1bd15a3ca2fd14 --- dom/media/test/test_decode_error.html | 1 - dom/webidl/MediaError.webidl | 1 - modules/libpref/init/all.js | 7 ------- 3 files changed, 9 deletions(-) diff --git a/dom/media/test/test_decode_error.html b/dom/media/test/test_decode_error.html index bb48d4343670..e940fcd18638 100644 --- a/dom/media/test/test_decode_error.html +++ b/dom/media/test/test_decode_error.html @@ -55,7 +55,6 @@ SimpleTest.waitForExplicitFinish(); SpecialPowers.pushPrefEnv({ "set": [ ["media.cache_size", 40000], - ["dom.MediaError.message.enabled", true] ] }, beginTest); function beginTest() { diff --git a/dom/webidl/MediaError.webidl b/dom/webidl/MediaError.webidl index 4c575e543906..bd1ed4e3f67c 100644 --- a/dom/webidl/MediaError.webidl +++ b/dom/webidl/MediaError.webidl @@ -20,6 +20,5 @@ interface MediaError { [Constant] readonly attribute unsigned short code; - [Pref="dom.MediaError.message.enabled"] readonly attribute DOMString message; }; diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 9f0a4d657192..f58ee161cbd5 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -305,13 +305,6 @@ pref("mathml.disabled", false); // Enable scale transform for stretchy MathML operators. See bug 414277. pref("mathml.scale_stretchy_operators.enabled", true); -// Disable MediaError.message. -#ifdef RELEASE_OR_BETA -pref("dom.MediaError.message.enabled", false); -#else -pref("dom.MediaError.message.enabled", true); -#endif - // Enabled on nightly only until we fix mochitest failures. #ifdef NIGHTLY_BUILD pref("media.dormant-on-pause-timeout-ms", 5000); From a75599dcaee46cc72dadca417329a408c528f786 Mon Sep 17 00:00:00 2001 From: Ricky Chien Date: Thu, 24 Nov 2016 21:50:49 +0800 Subject: [PATCH 04/25] Bug 1309188 - Implement Security Panel r=Honza MozReview-Commit-ID: LgYB97ByYdR --HG-- extra : rebase_source : 727106dd9413e05b7c0ad5a6fa8bd109ca91a7e6 --- devtools/client/netmonitor/details-view.js | 120 +---------- devtools/client/netmonitor/netmonitor.xul | 200 +----------------- .../netmonitor/shared/components/moz.build | 1 + .../shared/components/security-panel.js | 176 +++++++++++++++ .../test/browser_net_security-details.js | 69 +++--- .../test/browser_net_security-error.js | 9 +- .../test/browser_net_security-warnings.js | 4 +- .../shared/components/tree/tree-view.js | 7 +- devtools/client/themes/netmonitor.css | 53 ++++- 9 files changed, 275 insertions(+), 364 deletions(-) create mode 100644 devtools/client/netmonitor/shared/components/security-panel.js diff --git a/devtools/client/netmonitor/details-view.js b/devtools/client/netmonitor/details-view.js index 1e93bf2ce59d..77fa5a33d870 100644 --- a/devtools/client/netmonitor/details-view.js +++ b/devtools/client/netmonitor/details-view.js @@ -24,12 +24,12 @@ const { getFormDataSections, getUrlBaseName, getUrlQuery, - getUrlHost, parseQueryString, } = require("./request-utils"); const { createFactory } = require("devtools/client/shared/vendor/react"); const ReactDOM = require("devtools/client/shared/vendor/react-dom"); const Provider = createFactory(require("devtools/client/shared/vendor/react-redux").Provider); +const SecurityPanel = createFactory(require("./shared/components/security-panel")); const TimingsPanel = createFactory(require("./shared/components/timings-panel")); // 100 KB in bytes @@ -93,6 +93,13 @@ DetailsView.prototype = { initialize: function (store) { dumpn("Initializing the DetailsView"); + this._securityPanelNode = $("#react-security-tabpanel-hook"); + + ReactDOM.render(Provider( + { store }, + SecurityPanel() + ), this._securityPanelNode); + this._timingsPanelNode = $("#react-timings-tabpanel-hook"); ReactDOM.render(Provider( @@ -145,6 +152,7 @@ DetailsView.prototype = { */ destroy: function () { dumpn("Destroying the DetailsView"); + ReactDOM.unmountComponentAtNode(this._securityPanelNode); ReactDOM.unmountComponentAtNode(this._timingsPanelNode); this.sidebar.destroy(); $("tabpanels", this.widget).removeEventListener("select", @@ -255,10 +263,6 @@ DetailsView.prototype = { case 3: yield view._setResponseBody(src.url, src.responseContent); break; - // "Security" - case 5: - yield view._setSecurityInfo(src.securityInfo, src.url); - break; // "Preview" case 6: yield view._setHtmlPreview(src.responseContent); @@ -717,112 +721,6 @@ DetailsView.prototype = { return undefined; }), - /** - * Sets the security information shown in this view. - * - * @param object securityInfo - * The data received from server - * @param string url - * The URL of this request - * @return object - * A promise that is resolved when the security info is rendered. - */ - _setSecurityInfo: Task.async(function* (securityInfo, url) { - if (!securityInfo) { - // We don't have security info. This could mean one of two things: - // 1) This connection is not secure and this tab is not visible and thus - // we shouldn't be here. - // 2) We have already received securityState and the tab is visible BUT - // the rest of the information is still on its way. Once it arrives - // this method is called again. - return; - } - - /** - * A helper that sets value and tooltiptext attributes of an element to - * specified value. - * - * @param string selector - * A selector for the element. - * @param string value - * The value to set. If this evaluates to false a placeholder string - * is used instead. - */ - function setValue(selector, value) { - let label = $(selector); - if (!value) { - label.setAttribute("value", L10N.getStr( - "netmonitor.security.notAvailable")); - label.setAttribute("tooltiptext", label.getAttribute("value")); - } else { - label.setAttribute("value", value); - label.setAttribute("tooltiptext", value); - } - } - - let errorbox = $("#security-error"); - let infobox = $("#security-information"); - - if (securityInfo.state === "secure" || securityInfo.state === "weak") { - infobox.hidden = false; - errorbox.hidden = true; - - // Warning icons - let cipher = $("#security-warning-cipher"); - - if (securityInfo.state === "weak") { - cipher.hidden = securityInfo.weaknessReasons.indexOf("cipher") === -1; - } else { - cipher.hidden = true; - } - - let enabledLabel = L10N.getStr("netmonitor.security.enabled"); - let disabledLabel = L10N.getStr("netmonitor.security.disabled"); - - // Connection parameters - setValue("#security-protocol-version-value", - securityInfo.protocolVersion); - setValue("#security-ciphersuite-value", securityInfo.cipherSuite); - - // Host header - let domain = getUrlHost(url); - let hostHeader = L10N.getFormatStr("netmonitor.security.hostHeader", - domain); - setValue("#security-info-host-header", hostHeader); - - // Parameters related to the domain - setValue("#security-http-strict-transport-security-value", - securityInfo.hsts ? enabledLabel : disabledLabel); - - setValue("#security-public-key-pinning-value", - securityInfo.hpkp ? enabledLabel : disabledLabel); - - // Certificate parameters - let cert = securityInfo.cert; - setValue("#security-cert-subject-cn", cert.subject.commonName); - setValue("#security-cert-subject-o", cert.subject.organization); - setValue("#security-cert-subject-ou", cert.subject.organizationalUnit); - - setValue("#security-cert-issuer-cn", cert.issuer.commonName); - setValue("#security-cert-issuer-o", cert.issuer.organization); - setValue("#security-cert-issuer-ou", cert.issuer.organizationalUnit); - - setValue("#security-cert-validity-begins", cert.validity.start); - setValue("#security-cert-validity-expires", cert.validity.end); - - setValue("#security-cert-sha1-fingerprint", cert.fingerprint.sha1); - setValue("#security-cert-sha256-fingerprint", cert.fingerprint.sha256); - } else { - infobox.hidden = true; - errorbox.hidden = false; - - // Strip any HTML from the message. - let plain = new DOMParser().parseFromString(securityInfo.errorMessage, - "text/html"); - setValue("#security-error-message", plain.body.textContent); - } - }), - _dataSrc: null, _headers: null, _cookies: null, diff --git a/devtools/client/netmonitor/netmonitor.xul b/devtools/client/netmonitor/netmonitor.xul index 9b4e1f86bdae..3d0f5ace3fb8 100644 --- a/devtools/client/netmonitor/netmonitor.xul +++ b/devtools/client/netmonitor/netmonitor.xul @@ -267,204 +267,8 @@ - - - - - - - - - - + diff --git a/devtools/client/netmonitor/shared/components/moz.build b/devtools/client/netmonitor/shared/components/moz.build index ce44aaec6a88..2c7ccfea5118 100644 --- a/devtools/client/netmonitor/shared/components/moz.build +++ b/devtools/client/netmonitor/shared/components/moz.build @@ -3,5 +3,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. DevToolsModules( + 'security-panel.js', 'timings-panel.js', ) diff --git a/devtools/client/netmonitor/shared/components/security-panel.js b/devtools/client/netmonitor/shared/components/security-panel.js new file mode 100644 index 000000000000..75d7373ed209 --- /dev/null +++ b/devtools/client/netmonitor/shared/components/security-panel.js @@ -0,0 +1,176 @@ +/* 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/. */ + +"use strict"; + +const { DOM, PropTypes, createFactory } = require("devtools/client/shared/vendor/react"); +const { connect } = require("devtools/client/shared/vendor/react-redux"); +const TreeView = createFactory(require("devtools/client/shared/components/tree/tree-view")); +const { L10N } = require("../../l10n"); +const { getUrlHost } = require("../../request-utils"); +const { getSelectedRequest } = require("../../selectors/index"); + +const { div, input } = DOM; + +/* + * Security panel component + * If the site is being served over HTTPS, you get an extra tab labeled "Security". + * This contains details about the secure connection used including the protocol, + * the cipher suite, and certificate details + */ +function SecurityPanel({ + securityInfo, + url, +}) { + if (!securityInfo || !url) { + return div(); + } + + const notAvailable = L10N.getStr("netmonitor.security.notAvailable"); + let object; + + if ((securityInfo.state === "secure" || securityInfo.state === "weak")) { + const { subject, issuer, validity, fingerprint } = securityInfo.cert; + const enabledLabel = L10N.getStr("netmonitor.security.enabled"); + const disabledLabel = L10N.getStr("netmonitor.security.disabled"); + + object = { + [L10N.getStr("netmonitor.security.connection")]: { + [L10N.getStr("netmonitor.security.protocolVersion")]: + securityInfo.protocolVersion || notAvailable, + [L10N.getStr("netmonitor.security.cipherSuite")]: + securityInfo.cipherSuite || notAvailable, + }, + [L10N.getFormatStr("netmonitor.security.hostHeader", getUrlHost(url))]: { + [L10N.getStr("netmonitor.security.hsts")]: + securityInfo.hsts ? enabledLabel : disabledLabel, + [L10N.getStr("netmonitor.security.hpkp")]: + securityInfo.hpkp ? enabledLabel : disabledLabel, + }, + [L10N.getStr("netmonitor.security.certificate")]: { + [L10N.getStr("certmgr.subjectinfo.label")]: { + [L10N.getStr("certmgr.certdetail.cn")]: + subject.commonName || notAvailable, + [L10N.getStr("certmgr.certdetail.o")]: + subject.organization || notAvailable, + [L10N.getStr("certmgr.certdetail.ou")]: + subject.organizationUnit || notAvailable, + }, + [L10N.getStr("certmgr.issuerinfo.label")]: { + [L10N.getStr("certmgr.certdetail.cn")]: + issuer.commonName || notAvailable, + [L10N.getStr("certmgr.certdetail.o")]: + issuer.organization || notAvailable, + [L10N.getStr("certmgr.certdetail.ou")]: + issuer.organizationUnit || notAvailable, + }, + [L10N.getStr("certmgr.periodofvalidity.label")]: { + [L10N.getStr("certmgr.begins")]: + validity.start || notAvailable, + [L10N.getStr("certmgr.expires")]: + validity.end || notAvailable, + }, + [L10N.getStr("certmgr.fingerprints.label")]: { + [L10N.getStr("certmgr.certdetail.sha256fingerprint")]: + fingerprint.sha256 || notAvailable, + [L10N.getStr("certmgr.certdetail.sha1fingerprint")]: + fingerprint.sha1 || notAvailable, + }, + }, + }; + } else { + object = { + [L10N.getStr("netmonitor.security.error")]: + new DOMParser().parseFromString(securityInfo.errorMessage, "text/html") + .body.textContent || notAvailable + }; + } + + return div({ id: "security-information" }, + TreeView({ + object, + columns: [{ + id: "value", + width: "100%", + }], + renderValue: renderValue.bind(null, securityInfo.weaknessReasons), + expandedNodes: getExpandedNodes(object), + expandableStrings: false, + }) + ); +} + +SecurityPanel.displayName = "SecurityPanel"; + +SecurityPanel.propTypes = { + securityInfo: PropTypes.object.isRequired, + url: PropTypes.string.isRequired, +}; + +function renderValue(weaknessReasons = [], props) { + const { member, value } = props; + + // Hide object summary + if (typeof member.value === "object") { + return null; + } + + return div({ className: "security-info-value" }, + member.name === L10N.getStr("netmonitor.security.error") ? + // Display multiline text for security error + value + : + // Display one line selectable text for security details + input({ + className: "textbox-input", + readonly: "true", + value, + }) + , + weaknessReasons.indexOf("cipher") !== -1 && + member.name === L10N.getStr("netmonitor.security.cipherSuite") ? + // Display an extra warning icon after the cipher suite + div({ + id: "security-warning-cipher", + className: "security-warning-icon", + title: L10N.getStr("netmonitor.security.warning.cipher"), + }) + : + null + ); +} + +function getExpandedNodes(object, path = "", level = 0) { + if (typeof object !== "object") { + return null; + } + + let expandedNodes = new Set(); + for (let prop in object) { + let nodePath = path + "/" + prop; + expandedNodes.add(nodePath); + + let nodes = getExpandedNodes(object[prop], nodePath, level + 1); + if (nodes) { + expandedNodes = new Set([...expandedNodes, ...nodes]); + } + } + return expandedNodes; +} + +module.exports = connect( + (state) => { + const selectedRequest = getSelectedRequest(state); + + if (selectedRequest) { + const { securityInfo, url} = selectedRequest; + return { + securityInfo, + url, + }; + } + + return {}; + } +)(SecurityPanel); diff --git a/devtools/client/netmonitor/test/browser_net_security-details.js b/devtools/client/netmonitor/test/browser_net_security-details.js index f0874e543fd5..b4a9f06eb193 100644 --- a/devtools/client/netmonitor/test/browser_net_security-details.js +++ b/devtools/client/netmonitor/test/browser_net_security-details.js @@ -9,7 +9,7 @@ add_task(function* () { let { tab, monitor } = yield initNetMonitor(CUSTOM_GET_URL); - let { $, EVENTS, NetMonitorView } = monitor.panelWin; + let { $, $all, EVENTS, NetMonitorView } = monitor.panelWin; let { RequestsMenu, NetworkDetails } = NetMonitorView; RequestsMenu.lazyUpdate = false; @@ -36,67 +36,50 @@ add_task(function* () { let errorbox = $("#security-error"); let infobox = $("#security-information"); - is(errorbox.hidden, true, "Error box is hidden."); - is(infobox.hidden, false, "Information box visible."); + is(errorbox, null, "Error box is hidden."); + ok(infobox, "Information box visible."); + let textboxes = $all(".textbox-input"); // Connection // The protocol will be TLS but the exact version depends on which protocol // the test server example.com supports. - let protocol = $("#security-protocol-version-value").value; + let protocol = textboxes[0].value; ok(protocol.startsWith("TLS"), "The protocol " + protocol + " seems valid."); // The cipher suite used by the test server example.com might change at any // moment but all of them should start with "TLS_". // http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml - let suite = $("#security-ciphersuite-value").value; + let suite = textboxes[1].value; ok(suite.startsWith("TLS_"), "The suite " + suite + " seems valid."); // Host - checkLabel("#security-info-host-header", "Host example.com:"); - checkLabel("#security-http-strict-transport-security-value", "Disabled"); - checkLabel("#security-public-key-pinning-value", "Disabled"); + let hostLabel = $all(".treeLabel.objectLabel")[1]; + is(hostLabel.textContent, "Host example.com:", "Label has the expected value."); + is(textboxes[2].value, "Disabled", "Label has the expected value."); + is(textboxes[3].value, "Disabled", "Label has the expected value."); // Cert - checkLabel("#security-cert-subject-cn", "example.com"); - checkLabel("#security-cert-subject-o", ""); - checkLabel("#security-cert-subject-ou", ""); + is(textboxes[4].value, "example.com", "Label has the expected value."); + is(textboxes[5].value, "", "Label has the expected value."); + is(textboxes[6].value, "", "Label has the expected value."); - checkLabel("#security-cert-issuer-cn", "Temporary Certificate Authority"); - checkLabel("#security-cert-issuer-o", "Mozilla Testing"); - checkLabel("#security-cert-issuer-ou", ""); + is(textboxes[7].value, "Temporary Certificate Authority", "Label has the expected value."); + is(textboxes[8].value, "Mozilla Testing", "Label has the expected value."); + is(textboxes[9].value, "Profile Guided Optimization", "Label has the expected value."); // Locale sensitive and varies between timezones. Cant't compare equality or // the test fails depending on which part of the world the test is executed. - checkLabelNotEmpty("#security-cert-validity-begins"); - checkLabelNotEmpty("#security-cert-validity-expires"); - checkLabelNotEmpty("#security-cert-sha1-fingerprint"); - checkLabelNotEmpty("#security-cert-sha256-fingerprint"); + // cert validity begins + isnot(textboxes[10].value, "", "Label was not empty."); + // cert validity expires + isnot(textboxes[11].value, "", "Label was not empty."); + + // cert sha1 fingerprint + isnot(textboxes[12].value, "", "Label was not empty."); + // cert sha256 fingerprint + isnot(textboxes[13].value, "", "Label was not empty."); + yield teardown(monitor); - - /** - * A helper that compares value attribute of a label with given selector to the - * expected value. - */ - function checkLabel(selector, expected) { - info("Checking label " + selector); - - let element = $(selector); - - ok(element, "Selector matched an element."); - is(element.value, expected, "Label has the expected value."); - } - - /** - * A helper that checks the label with given selector is not an empty string. - */ - function checkLabelNotEmpty(selector) { - info("Checking that label " + selector + " is non-empty."); - - let element = $(selector); - - ok(element, "Selector matched an element."); - isnot(element.value, "", "Label was not empty."); - } }); diff --git a/devtools/client/netmonitor/test/browser_net_security-error.js b/devtools/client/netmonitor/test/browser_net_security-error.js index ebb39b1b643a..4f43577c9c79 100644 --- a/devtools/client/netmonitor/test/browser_net_security-error.js +++ b/devtools/client/netmonitor/test/browser_net_security-error.js @@ -33,14 +33,9 @@ add_task(function* () { info("Waiting for security tab to be updated."); yield monitor.panelWin.once(EVENTS.TAB_UPDATED); - let errorbox = $("#security-error"); - let errormsg = $("#security-error-message"); - let infobox = $("#security-information"); + let errormsg = $(".security-info-value"); - is(errorbox.hidden, false, "Error box is visble."); - is(infobox.hidden, true, "Information box is hidden."); - - isnot(errormsg.value, "", "Error message is not empty."); + isnot(errormsg.textContent, "", "Error message is not empty."); return teardown(monitor); diff --git a/devtools/client/netmonitor/test/browser_net_security-warnings.js b/devtools/client/netmonitor/test/browser_net_security-warnings.js index f6894c3be317..73d3fcfbbbb3 100644 --- a/devtools/client/netmonitor/test/browser_net_security-warnings.js +++ b/devtools/client/netmonitor/test/browser_net_security-warnings.js @@ -11,7 +11,7 @@ const TEST_CASES = [ { desc: "no warnings", uri: "https://example.com" + CORS_SJS_PATH, - warnCipher: false, + warnCipher: null, }, ]; @@ -47,7 +47,7 @@ add_task(function* () { yield monitor.panelWin.once(EVENTS.TAB_UPDATED); } - is(cipher.hidden, !test.warnCipher, "Cipher suite warning is hidden."); + is(cipher, test.warnCipher, "Cipher suite warning is hidden."); RequestsMenu.clear(); } diff --git a/devtools/client/shared/components/tree/tree-view.js b/devtools/client/shared/components/tree/tree-view.js index 9fae9addbdc0..1791e5d46bd6 100644 --- a/devtools/client/shared/components/tree/tree-view.js +++ b/devtools/client/shared/components/tree/tree-view.js @@ -97,6 +97,8 @@ define(function (require, exports, module) { onSort: PropTypes.func, // A header is displayed if set to true header: PropTypes.bool, + // Long string is expandable by a toggle button + expandableStrings: PropTypes.bool, // Array of columns columns: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.string.isRequired, @@ -111,6 +113,7 @@ define(function (require, exports, module) { renderRow: null, provider: ObjectProvider, expandedNodes: new Set(), + expandableStrings: true, columns: [] }; }, @@ -179,7 +182,7 @@ define(function (require, exports, module) { return []; } - let provider = this.props.provider; + let { expandableStrings, provider } = this.props; let children = provider.getChildren(parent) || []; // If the return value is non-array, the children @@ -201,7 +204,7 @@ define(function (require, exports, module) { // Value for actual column is get when a cell is rendered. let value = provider.getValue(child); - if (isLongString(value)) { + if (expandableStrings && isLongString(value)) { hasChildren = true; } diff --git a/devtools/client/themes/netmonitor.css b/devtools/client/themes/netmonitor.css index a3bf7c5171c9..aafb6b16ed63 100644 --- a/devtools/client/themes/netmonitor.css +++ b/devtools/client/themes/netmonitor.css @@ -1,8 +1,9 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ /* 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/. */ +@import "resource://devtools/client/shared/components/tree/tree-view.css"; + #toolbar-labels { overflow: hidden; display: flex; @@ -786,6 +787,7 @@ #security-tabpanel { overflow: auto; + -moz-user-select: text; } .security-warning-icon { @@ -1084,10 +1086,59 @@ } } +/* Overwrite tree-view cell colon and use l10n string instead */ +.treeTable .treeLabelCell::after { + content: ""; +} + +/* Layout additional warning icon in tree value cell */ +.security-info-value { + display: flex; +} + +.security-info-value .textbox-input { + text-overflow: ellipsis; + border: none; + background: none; + color: inherit; + width: 100%; + margin-inline-end: 2px; +} + +.security-info-value .textbox-input:focus { + outline: 0; + box-shadow: var(--theme-focus-box-shadow-textbox); +} + +.treeTable .treeLabel { + font-weight: 600; +} + +/* Customize default tree table style to align with devtools theme */ +.theme-light .treeTable .treeLabel, +.theme-light .treeTable .treeRow.hasChildren > .treeLabelCell > .treeLabel:hover { + color: var(--theme-highlight-red); +} + +.theme-dark .treeTable .treeLabel, +.theme-dark .treeTable .treeRow.hasChildren > .treeLabelCell > .treeLabel:hover { + color: var(--theme-highlight-purple); +} + +.theme-firebug .treeTable .treeLabel { + color: var(--theme-body-color); +} + +.treeTable .treeRow.hasChildren > .treeLabelCell > .treeLabel:hover { + cursor: default; + text-decoration: none; +} + /* * FIXME: normal html block element cannot fill outer XUL element * This workaround should be removed after sidebar is migrated to react */ +#react-security-tabpanel-hook, #react-timings-tabpanel-hook { display: -moz-box; -moz-box-orient: vertical; From bce016bed3abd09bf1ce81ac33c2c6f9a24a6273 Mon Sep 17 00:00:00 2001 From: ctai Date: Fri, 18 Nov 2016 11:29:33 +0800 Subject: [PATCH 05/25] Bug 1118337 - Enable resource-selection-invoke-insert-source.html. r=jwwang This test case can be pass. This bug is fixed in bug 1222980. MozReview-Commit-ID: FbCQe35A2cD --HG-- extra : rebase_source : 0b62c31e95bc1b941c57c8bce62121bcb7483889 --- .../resource-selection-invoke-insert-source.html.ini | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 testing/web-platform/meta/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html.ini diff --git a/testing/web-platform/meta/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html.ini b/testing/web-platform/meta/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html.ini deleted file mode 100644 index e7fd87a4aa03..000000000000 --- a/testing/web-platform/meta/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[resource-selection-invoke-insert-source.html] - type: testharness - [invoking resource selection by inserting ] - expected: FAIL - From d44c8978b24920d28bc3b6a845b5206bfde5542d Mon Sep 17 00:00:00 2001 From: ctai Date: Tue, 13 Dec 2016 15:45:59 +0800 Subject: [PATCH 06/25] Bug 1222980 - Dispatch |QueueLoadFromSourceTask| to main thread. And end the synchronous section and asynchronously await a stable state when the src is not set. r=jwwang. Dispatch |QueueLoadFromSourceTask| to main thread to make sure the task will be executed later than loadstart event. And when the src get errors, we need to end the synchronous section. MozReview-Commit-ID: EQ0jVIMnqoZ --HG-- extra : rebase_source : 6651826ad8de361deda5bdc0a49b2c68dcf86220 --- dom/html/HTMLMediaElement.cpp | 24 ++++++++++++++++-------- dom/html/HTMLMediaElement.h | 8 ++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 15f895475d6a..9fc9cd9c51b8 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -2068,6 +2068,14 @@ void HTMLMediaElement::NotifyMediaStreamTracksAvailable(DOMMediaStream* aStream) mWatchManager.ManualNotify(&HTMLMediaElement::UpdateReadyStateInternal); } +void HTMLMediaElement::DealWithFailedElement(nsIContent* aSourceElement) +{ + DispatchAsyncSourceError(aSourceElement); + nsCOMPtr event = + NewRunnableMethod(this, &HTMLMediaElement::QueueLoadFromSourceTask); + NS_DispatchToMainThread(event); +} + void HTMLMediaElement::NotifyOutputTrackStopped(DOMMediaStream* aOwningStream, TrackID aDestinationTrackID) @@ -2125,8 +2133,8 @@ void HTMLMediaElement::LoadFromSourceChildren() nsAutoString src; if (!child->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) { ReportLoadError("MediaLoadSourceMissingSrc"); - DispatchAsyncSourceError(child); - continue; + DealWithFailedElement(child); + return; } // If we have a type attribute, it must be a supported type. @@ -2137,20 +2145,20 @@ void HTMLMediaElement::LoadFromSourceChildren() diagnostics.StoreFormatDiagnostics( OwnerDoc(), type, canPlay != CANPLAY_NO, __func__); if (canPlay == CANPLAY_NO) { - DispatchAsyncSourceError(child); const char16_t* params[] = { type.get(), src.get() }; ReportLoadError("MediaLoadUnsupportedTypeAttribute", params, ArrayLength(params)); - continue; + DealWithFailedElement(child); + return; } } nsAutoString media; HTMLSourceElement *childSrc = HTMLSourceElement::FromContent(child); MOZ_ASSERT(childSrc, "Expect child to be HTMLSourceElement"); if (childSrc && !childSrc->MatchesCurrentMedia()) { - DispatchAsyncSourceError(child); const char16_t* params[] = { media.get(), src.get() }; ReportLoadError("MediaLoadSourceMediaNotMatched", params, ArrayLength(params)); - continue; + DealWithFailedElement(child); + return; } LOG(LogLevel::Debug, ("%p Trying load from =%s type=%s media=%s", this, NS_ConvertUTF16toUTF8(src).get(), NS_ConvertUTF16toUTF8(type).get(), @@ -2159,10 +2167,10 @@ void HTMLMediaElement::LoadFromSourceChildren() nsCOMPtr uri; NewURIFromString(src, getter_AddRefs(uri)); if (!uri) { - DispatchAsyncSourceError(child); const char16_t* params[] = { src.get() }; ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params)); - continue; + DealWithFailedElement(child); + return; } RemoveMediaElementFromURITable(); diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h index e7eff165eb7b..28fcb187ffa5 100644 --- a/dom/html/HTMLMediaElement.h +++ b/dom/html/HTMLMediaElement.h @@ -964,6 +964,14 @@ protected: */ void NoSupportedMediaSourceError(const nsACString& aErrorDetails = nsCString()); + /** + * Per spec, Failed with elements: Queue a task, using the DOM manipulation + * task source, to fire a simple event named error at the candidate element. + * So dispatch |QueueLoadFromSourceTask| to main thread to make sure the task + * will be executed later than loadstart event. + */ + void DealWithFailedElement(nsIContent* aSourceElement); + /** * Attempts to load resources from the children. This is a * substep of the resource selection algorithm. Do not call this directly, From e36bde43f5043f0a0c9875081c3e311ff0c47b82 Mon Sep 17 00:00:00 2001 From: ctai Date: Fri, 18 Nov 2016 11:24:00 +0800 Subject: [PATCH 07/25] Bug 1222980 - Enable resource-selection-invoke-insert-source-not-in-document.html. r=jwwang. MozReview-Commit-ID: Bjqs24D3AGb --HG-- extra : rebase_source : 87adbfc2a9eec4aa096f37bca22f1c090a5cbbde --- ...e-selection-invoke-insert-source-not-in-document.html.ini | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 testing/web-platform/meta/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html.ini diff --git a/testing/web-platform/meta/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html.ini b/testing/web-platform/meta/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html.ini deleted file mode 100644 index d6c3a5c9926a..000000000000 --- a/testing/web-platform/meta/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[resource-selection-invoke-insert-source-not-in-document.html] - type: testharness - [invoking resource selection by inserting in video not in a document] - expected: FAIL - From 81f1a5ff994b4127c0e22cb4ffbc40603e24d955 Mon Sep 17 00:00:00 2001 From: ctai Date: Wed, 14 Dec 2016 11:23:52 +0800 Subject: [PATCH 08/25] Bug 1222980 - Disable resource-selection-invoke-remove-src.html. r=jwwang Disable resource-selection-invoke-remove-src.html because it should be failed. Bug 1318196 should be able to fix this test. MozReview-Commit-ID: L3zzna9FKDm --HG-- extra : rebase_source : f4e43311fb9de8fb30ce6014b3e26c19c53dce93 --- .../resource-selection-invoke-remove-src.html.ini | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 testing/web-platform/meta/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html.ini diff --git a/testing/web-platform/meta/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html.ini b/testing/web-platform/meta/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html.ini new file mode 100644 index 000000000000..963342376639 --- /dev/null +++ b/testing/web-platform/meta/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html.ini @@ -0,0 +1,5 @@ +[resource-selection-invoke-remove-src.html] + type: testharness + [NOT invoking media load or resource selection when removing the src attribute] + expected: FAIL + From c3d82be2df3b3b4e5b62208d0182c269c0619890 Mon Sep 17 00:00:00 2001 From: "Fischer.json" Date: Tue, 15 Nov 2016 14:49:18 +0800 Subject: [PATCH 09/25] Bug 1312361 - Clear all sites data from the Site Data section, r=Gijs MozReview-Commit-ID: 7JbzO7TQaeX --HG-- extra : rebase_source : d0fcc521cc12bd84eee00525982e3d2cabe92eee --- .../preferences/SiteDataManager.jsm | 35 +++- .../preferences/in-content/advanced.js | 25 ++- .../preferences/in-content/advanced.xul | 2 + .../preferences/in-content/tests/browser.ini | 2 + .../tests/browser_advanced_siteData.js | 154 ++++++++++++++++++ .../preferences/in-content/tests/head.js | 18 ++ .../in-content/tests/site_data_test.html | 29 ++++ .../chrome/browser/preferences/advanced.dtd | 4 +- .../preferences/preferences.properties | 3 + 9 files changed, 266 insertions(+), 6 deletions(-) create mode 100644 browser/components/preferences/in-content/tests/browser_advanced_siteData.js create mode 100755 browser/components/preferences/in-content/tests/site_data_test.html diff --git a/browser/components/preferences/SiteDataManager.jsm b/browser/components/preferences/SiteDataManager.jsm index 4d56d745411f..dcf2cb1986cf 100644 --- a/browser/components/preferences/SiteDataManager.jsm +++ b/browser/components/preferences/SiteDataManager.jsm @@ -5,6 +5,9 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "OfflineAppCacheHelper", + "resource:///modules/offlineAppCache.jsm"); + this.EXPORTED_SYMBOLS = [ "SiteDataManager" ]; @@ -62,12 +65,17 @@ this.SiteDataManager = { this._updateQuota(); this._updateAppCache(); this._updateDiskCache(); + + Promise.all([this._updateQuotaPromise, this._updateDiskCachePromise]) + .then(() => { + Services.obs.notifyObservers(null, "sitedatamanager:sites-updated", null); + }); }, _updateQuota() { this._quotaUsageRequests = []; let promises = []; - for (let [key, site] of this._sites) { // eslint-disable-line no-unused-vars + for (let site of this._sites.values()) { promises.push(new Promise(resolve => { let callback = { onUsageResult: function(request) { @@ -96,7 +104,7 @@ this.SiteDataManager = { _updateAppCache() { let groups = this._appCache.getGroups(); - for (let [key, site] of this._sites) { // eslint-disable-line no-unused-vars + for (let site of this._sites.values()) { for (let group of groups) { let uri = Services.io.newURI(group, null, null); if (site.perm.matchesURI(uri, true)) { @@ -113,7 +121,7 @@ this.SiteDataManager = { let sites = this._sites; let visitor = { onCacheEntryInfo: function(uri, idEnhance, dataSize) { - for (let [key, site] of sites) { // eslint-disable-line no-unused-vars + for (let site of sites.values()) { if (site.perm.matchesURI(uri, true)) { site.diskCacheList.push({ dataSize, @@ -138,7 +146,7 @@ this.SiteDataManager = { return Promise.all([this._updateQuotaPromise, this._updateDiskCachePromise]) .then(() => { let usage = 0; - for (let [key, site] of this._sites) { // eslint-disable-line no-unused-vars + for (let site of this._sites.values()) { let cache = null; for (cache of site.appCacheList) { usage += cache.usage; @@ -151,4 +159,23 @@ this.SiteDataManager = { return usage; }); }, + + _removePermission(site) { + Services.perms.removePermission(site.perm); + }, + + _removeQuotaUsage(site) { + this._qms.clearStoragesForPrincipal(site.perm.principal, null, true); + }, + + removeAll() { + for (let site of this._sites.values()) { + this._removePermission(site); + this._removeQuotaUsage(site); + } + Services.cache2.clear(); + Services.cookies.removeAll(); + OfflineAppCacheHelper.clear(); + this.updateSites(); + } }; diff --git a/browser/components/preferences/in-content/advanced.js b/browser/components/preferences/in-content/advanced.js index a4ebf82093da..3245d64b19ba 100644 --- a/browser/components/preferences/in-content/advanced.js +++ b/browser/components/preferences/in-content/advanced.js @@ -56,8 +56,10 @@ var gAdvancedPane = { this.updateActualAppCacheSize(); if (Services.prefs.getBoolPref("browser.storageManager.enabled")) { + Services.obs.addObserver(this, "sitedatamanager:sites-updated", false); SiteDataManager.updateSites(); - this.updateTotalSiteDataSize(); + setEventListener("clearSiteDataButton", "command", + gAdvancedPane.clearSiteData); } setEventListener("layers.acceleration.disabled", "change", @@ -479,6 +481,23 @@ var gAdvancedPane = { this.updateOfflineApps(); }, + clearSiteData: function() { + let flags = + Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 + + Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1 + + Services.prompt.BUTTON_POS_0_DEFAULT; + let prefStrBundle = document.getElementById("bundlePreferences"); + let title = prefStrBundle.getString("clearSiteDataPromptTitle"); + let text = prefStrBundle.getString("clearSiteDataPromptText"); + let btn0Label = prefStrBundle.getString("clearSiteDataNow"); + + let result = Services.prompt.confirmEx( + window, title, text, flags, btn0Label, null, null, null, {}); + if (result == 0) { + SiteDataManager.removeAll(); + } + }, + readOfflineNotify: function() { var pref = document.getElementById("browser.offline-apps.notify"); @@ -774,6 +793,10 @@ var gAdvancedPane = { case "nsPref:changed": this.updateReadPrefs(); break; + + case "sitedatamanager:sites-updated": + this.updateTotalSiteDataSize(); + break; } } }, diff --git a/browser/components/preferences/in-content/advanced.xul b/browser/components/preferences/in-content/advanced.xul index b0dfd5eaf244..b1b4e3fa37c4 100644 --- a/browser/components/preferences/in-content/advanced.xul +++ b/browser/components/preferences/in-content/advanced.xul @@ -335,6 +335,8 @@ +