зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
Коммит
572e74ee99
|
@ -1456,7 +1456,7 @@ pref("dom.ipc.cpows.forbid-unsafe-from-browser", true);
|
|||
pref("dom.ipc.cpows.forbid-cpows-in-compat-addons", true);
|
||||
|
||||
// ...except for these add-ons:
|
||||
pref("dom.ipc.cpows.allow-cpows-in-compat-addons", "{b9db16a4-6edc-47ec-a1f4-b86292ed211d},privateTab@infocatcher,mousegesturessuite@lemon_juice.addons.mozilla.org,firegestures@xuldev.org,treestyletab@piro.sakura.ne.jp,{DDC359D1-844A-42a7-9AA1-88A850A938A8},ich@maltegoetz.de,{AE93811A-5C9A-4d34-8462-F7B864FC4696}");
|
||||
pref("dom.ipc.cpows.allow-cpows-in-compat-addons", "{b9db16a4-6edc-47ec-a1f4-b86292ed211d},firegestures@xuldev.org,{DDC359D1-844A-42a7-9AA1-88A850A938A8},privateTab@infocatcher,mousegesturessuite@lemon_juice.addons.mozilla.org,treestyletab@piro.sakura.ne.jp,cliqz@cliqz.com,{AE93811A-5C9A-4d34-8462-F7B864FC4696},contextsearch2@lwz.addons.mozilla.org,{EF522540-89F5-46b9-B6FE-1829E2B572C6},{677a8f98-fd64-40b0-a883-b8c95d0cbf17},images@wink.su,fx-devtools,toolkit/require,url_advisor@kaspersky.com,{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d},{dc572301-7619-498c-a57d-39143191b318},dta@downthemall.net,{86095750-AD15-46d8-BF32-C0789F7E6A32},screenwise-prod@google.com,{91aa5abe-9de4-4347-b7b5-322c38dd9271},secureLogin@blueimp.net,ich@maltegoetz.de,come.back.block.image.from@cat-in-136.blogspot.com,{7b1bf0b6-a1b9-42b0-b75d-252036438bdc},s3crypto@data,{1e0fd655-5aea-4b4c-a583-f76ef1e3af9c},akahuku.fx.sp@toshiakisp.github.io,{aff87fa2-a58e-4edd-b852-0a20203c1e17},{1018e4d6-728f-4b20-ad56-37578a4de76b},rehostimage@engy.us,lazarus@interclue.com,{b2e69492-2358-071a-7056-24ad0c3defb1},flashstopper@byo.co.il,{e4a8a97b-f2ed-450b-b12d-ee082ba24781},jid1-f3mYMbCpz2AZYl@jetpack,{8c550e28-88c9-4764-bb52-aa489cf2efcd},{37fa1426-b82d-11db-8314-0800200c9a66},{ac2cfa60-bc96-11e0-962b-0800200c9a66},igetter@presenta.net,killspinners@byo.co.il,abhere2@moztw.org,{fc6339b8-9581-4fc7-b824-dffcb091fcb7},wampi@wink.su,backtrack@byalexv.co.uk,Gladiator_X@mail.ru,{73a6fe31-595d-460b-a920-fcc0f8843232},{46551EC9-40F0-4e47-8E18-8E5CF550CFB8},acewebextension_unlisted@acestream.org,@screen_maker,yasearch@yandex.ru,sp@avast.com,s3google@translator,igetterextension@presenta.net,{C1A2A613-35F1-4FCF-B27F-2840527B6556},screenwise-testing@google.com,helper-sig@savefrom.net,browser-loader,ImageSaver@Merci.chao,proxtube@abz.agency,wrc@avast.com,{9AA46F4F-4DC7-4c06-97AF-5035170634FE},jid1-CikLKKPVkw6ipw@jetpack,artur.dubovoy@gmail.com,nlgfeb@nlgfeb.ext,{A065A84F-95B6-433A-A0C8-4C040B77CE8A},fdm_ffext@freedownloadmanager.org");
|
||||
|
||||
// Enable e10s hang monitoring (slow script checking and plugin hang
|
||||
// detection).
|
||||
|
|
|
@ -1128,6 +1128,7 @@ var gBrowserInit = {
|
|||
// [4]: allowThirdPartyFixup (bool)
|
||||
// [5]: referrerPolicy (int)
|
||||
// [6]: userContextId (int)
|
||||
// [7]: originPrincipal (nsIPrincipal)
|
||||
else if (window.arguments.length >= 3) {
|
||||
let referrerURI = window.arguments[2];
|
||||
if (typeof(referrerURI) == "string") {
|
||||
|
@ -1142,7 +1143,10 @@ var gBrowserInit = {
|
|||
let userContextId = (window.arguments[6] != undefined ?
|
||||
window.arguments[6] : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID);
|
||||
loadURI(uriToLoad, referrerURI, window.arguments[3] || null,
|
||||
window.arguments[4] || false, referrerPolicy, userContextId);
|
||||
window.arguments[4] || false, referrerPolicy, userContextId,
|
||||
// pass the origin principal (if any) and force its use to create
|
||||
// an initial about:blank viewer if present:
|
||||
window.arguments[7], !!window.arguments[7]);
|
||||
window.focus();
|
||||
}
|
||||
// Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
|
||||
|
@ -2033,14 +2037,17 @@ function BrowserTryToCloseWindow()
|
|||
}
|
||||
|
||||
function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy,
|
||||
userContextId) {
|
||||
userContextId, originPrincipal, forceAboutBlankViewerInCurrent) {
|
||||
try {
|
||||
openLinkIn(uri, "current",
|
||||
{ referrerURI: referrer,
|
||||
referrerPolicy: referrerPolicy,
|
||||
postData: postData,
|
||||
allowThirdPartyFixup: allowThirdPartyFixup,
|
||||
userContextId: userContextId });
|
||||
userContextId: userContextId,
|
||||
originPrincipal,
|
||||
forceAboutBlankViewerInCurrent,
|
||||
});
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
|
@ -5584,11 +5591,14 @@ function handleLinkClick(event, href, linkNode) {
|
|||
}
|
||||
|
||||
urlSecurityCheck(href, doc.nodePrincipal);
|
||||
let params = { charset: doc.characterSet,
|
||||
allowMixedContent: persistAllowMixedContentInChildTab,
|
||||
referrerURI: referrerURI,
|
||||
referrerPolicy: referrerPolicy,
|
||||
noReferrer: BrowserUtils.linkHasNoReferrer(linkNode) };
|
||||
let params = {
|
||||
charset: doc.characterSet,
|
||||
allowMixedContent: persistAllowMixedContentInChildTab,
|
||||
referrerURI: referrerURI,
|
||||
referrerPolicy: referrerPolicy,
|
||||
noReferrer: BrowserUtils.linkHasNoReferrer(linkNode),
|
||||
originPrincipal: doc.nodePrincipal,
|
||||
};
|
||||
|
||||
// The new tab/window must use the same userContextId
|
||||
if (doc.nodePrincipal.originAttributes.userContextId) {
|
||||
|
|
|
@ -507,6 +507,7 @@ var ClickEventHandler = {
|
|||
json.allowMixedContent = true;
|
||||
} catch (e) {}
|
||||
}
|
||||
json.originPrincipal = ownerDoc.nodePrincipal;
|
||||
|
||||
sendAsyncMessage("Content:Click", json);
|
||||
return;
|
||||
|
|
|
@ -965,6 +965,7 @@ nsContextMenu.prototype = {
|
|||
|
||||
_openLinkInParameters : function (extra) {
|
||||
let params = { charset: gContextMenuContentData.charSet,
|
||||
originPrincipal: this.principal,
|
||||
referrerURI: gContextMenuContentData.documentURIObject,
|
||||
referrerPolicy: gContextMenuContentData.referrerPolicy,
|
||||
noReferrer: this.linkHasNoReferrer };
|
||||
|
|
|
@ -1500,6 +1500,7 @@
|
|||
var aNoReferrer;
|
||||
var aUserContextId;
|
||||
var aRelatedBrowser;
|
||||
var aOriginPrincipal;
|
||||
if (arguments.length == 2 &&
|
||||
typeof arguments[1] == "object" &&
|
||||
!(arguments[1] instanceof Ci.nsIURI)) {
|
||||
|
@ -1518,6 +1519,7 @@
|
|||
aNoReferrer = params.noReferrer;
|
||||
aUserContextId = params.userContextId;
|
||||
aRelatedBrowser = params.relatedBrowser;
|
||||
aOriginPrincipal = params.originPrincipal;
|
||||
}
|
||||
|
||||
var bgLoad = (aLoadInBackground != null) ? aLoadInBackground :
|
||||
|
@ -1537,6 +1539,7 @@
|
|||
forceNotRemote: aForceNotRemote,
|
||||
noReferrer: aNoReferrer,
|
||||
userContextId: aUserContextId,
|
||||
originPrincipal: aOriginPrincipal,
|
||||
relatedBrowser: aRelatedBrowser });
|
||||
if (!bgLoad)
|
||||
this.selectedTab = tab;
|
||||
|
@ -2043,6 +2046,7 @@
|
|||
var aUserContextId;
|
||||
var aEventDetail;
|
||||
var aRelatedBrowser;
|
||||
var aOriginPrincipal;
|
||||
if (arguments.length == 2 &&
|
||||
typeof arguments[1] == "object" &&
|
||||
!(arguments[1] instanceof Ci.nsIURI)) {
|
||||
|
@ -2062,6 +2066,7 @@
|
|||
aUserContextId = params.userContextId;
|
||||
aEventDetail = params.eventDetail;
|
||||
aRelatedBrowser = params.relatedBrowser;
|
||||
aOriginPrincipal = params.originPrincipal;
|
||||
}
|
||||
|
||||
// if we're adding tabs, we're past interrupt mode, ditch the owner
|
||||
|
@ -2141,6 +2146,10 @@
|
|||
var evt = new CustomEvent("TabOpen", { bubbles: true, detail });
|
||||
t.dispatchEvent(evt);
|
||||
|
||||
if (!usingPreloadedContent && aOriginPrincipal) {
|
||||
b.createAboutBlankContentViewer(aOriginPrincipal);
|
||||
}
|
||||
|
||||
// If we didn't swap docShells with a preloaded browser
|
||||
// then let's just continue loading the page normally.
|
||||
if (!usingPreloadedContent && !uriIsAboutBlank) {
|
||||
|
@ -3669,7 +3678,11 @@
|
|||
assert: function(cond) {
|
||||
if (!cond) {
|
||||
dump("Assertion failure\n" + Error().stack);
|
||||
throw new Error("Assertion failure");
|
||||
|
||||
// Don't break a user's browser if an assertion fails.
|
||||
if (this.tabbrowser.AppConstants.DEBUG) {
|
||||
throw new Error("Assertion failure");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -118,6 +118,7 @@ support-files =
|
|||
file_bug1045809_2.html
|
||||
file_csp_block_all_mixedcontent.html
|
||||
file_csp_block_all_mixedcontent.js
|
||||
!/image/test/mochitest/blue.png
|
||||
!/toolkit/components/passwordmgr/test/browser/form_basic.html
|
||||
!/toolkit/components/passwordmgr/test/browser/insecure_test.html
|
||||
!/toolkit/components/passwordmgr/test/browser/insecure_test_subframe.html
|
||||
|
@ -342,6 +343,7 @@ subsuite = clipboard
|
|||
[browser_mixed_content_cert_override.js]
|
||||
[browser_mixedcontent_securityflags.js]
|
||||
tags = mcb
|
||||
[browser_modifiedclick_inherit_principal.js]
|
||||
[browser_offlineQuotaNotification.js]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[browser_feed_discovery.js]
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
"use strict";
|
||||
|
||||
const kURL =
|
||||
"http://example.com/browser/browser/base/content/test/general/dummy_page.html";
|
||||
"data:text/html,<a href=''>Middle-click me</a>";
|
||||
|
||||
/*
|
||||
* Check that when manually opening content JS links in new tabs/windows,
|
||||
* we use the correct principal, and we don't clear the URL bar.
|
||||
*/
|
||||
add_task(function* () {
|
||||
yield BrowserTestUtils.withNewTab(kURL, function* (browser) {
|
||||
let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser);
|
||||
yield ContentTask.spawn(browser, null, function* () {
|
||||
let a = content.document.createElement("a");
|
||||
a.href = "javascript:document.write('spoof'); void(0);";
|
||||
a.textContent = "Some link";
|
||||
content.document.body.appendChild(a);
|
||||
});
|
||||
info("Added element");
|
||||
yield BrowserTestUtils.synthesizeMouseAtCenter("a", {button: 1}, browser);
|
||||
let newTab = yield newTabPromise;
|
||||
is(newTab.linkedBrowser.contentPrincipal.origin, "http://example.com",
|
||||
"Principal should be for example.com");
|
||||
yield BrowserTestUtils.switchTab(gBrowser, newTab);
|
||||
info(gURLBar.value);
|
||||
isnot(gURLBar.value, "", "URL bar should not be empty.");
|
||||
yield BrowserTestUtils.removeTab(newTab);
|
||||
});
|
||||
});
|
|
@ -222,6 +222,9 @@ function openLinkIn(url, where, params) {
|
|||
var aAllowPopups = !!params.allowPopups;
|
||||
var aUserContextId = params.userContextId;
|
||||
var aIndicateErrorPageLoad = params.indicateErrorPageLoad;
|
||||
var aPrincipal = params.originPrincipal;
|
||||
var aForceAboutBlankViewerInCurrent =
|
||||
params.forceAboutBlankViewerInCurrent;
|
||||
|
||||
if (where == "save") {
|
||||
// TODO(1073187): propagate referrerPolicy.
|
||||
|
@ -290,6 +293,7 @@ function openLinkIn(url, where, params) {
|
|||
sa.AppendElement(allowThirdPartyFixupSupports);
|
||||
sa.AppendElement(referrerPolicySupports);
|
||||
sa.AppendElement(userContextIdSupports);
|
||||
sa.AppendElement(aPrincipal);
|
||||
|
||||
let features = "chrome,dialog=no,all";
|
||||
if (aIsPrivate) {
|
||||
|
@ -357,6 +361,10 @@ function openLinkIn(url, where, params) {
|
|||
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ERROR_LOAD_CHANGES_RV;
|
||||
}
|
||||
|
||||
if (aForceAboutBlankViewerInCurrent) {
|
||||
w.gBrowser.selectedBrowser.createAboutBlankContentViewer(aPrincipal);
|
||||
}
|
||||
|
||||
w.gBrowser.loadURIWithFlags(url, {
|
||||
flags: flags,
|
||||
referrerURI: aNoReferrer ? null : aReferrerURI,
|
||||
|
@ -380,7 +388,8 @@ function openLinkIn(url, where, params) {
|
|||
skipAnimation: aSkipTabAnimation,
|
||||
allowMixedContent: aAllowMixedContent,
|
||||
noReferrer: aNoReferrer,
|
||||
userContextId: aUserContextId
|
||||
userContextId: aUserContextId,
|
||||
originPrincipal: aPrincipal,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -77,12 +77,15 @@ var ContentClick = {
|
|||
|
||||
// Todo(903022): code for where == save
|
||||
|
||||
let params = { charset: browser.characterSet,
|
||||
referrerURI: browser.documentURI,
|
||||
referrerPolicy: json.referrerPolicy,
|
||||
noReferrer: json.noReferrer,
|
||||
allowMixedContent: json.allowMixedContent,
|
||||
isContentWindowPrivate: json.isContentWindowPrivate};
|
||||
let params = {
|
||||
charset: browser.characterSet,
|
||||
referrerURI: browser.documentURI,
|
||||
referrerPolicy: json.referrerPolicy,
|
||||
noReferrer: json.noReferrer,
|
||||
allowMixedContent: json.allowMixedContent,
|
||||
isContentWindowPrivate: json.isContentWindowPrivate,
|
||||
originPrincipal: json.originPrincipal,
|
||||
};
|
||||
|
||||
// The new tab/window must use the same userContextId.
|
||||
if (json.originAttributes.userContextId) {
|
||||
|
|
|
@ -191,22 +191,11 @@ toolbar[brighttext] #downloads-indicator-counter {
|
|||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
:root[devtoolstheme="dark"] #identity-icon:-moz-lwtheme {
|
||||
--identity-icon-normal: url(chrome://browser/skin/identity-icon.svg#normal-white);
|
||||
--identity-icon-hover: url(chrome://browser/skin/identity-icon.svg#hover-white);
|
||||
--identity-icon-notice: url(chrome://browser/skin/identity-icon.svg#notice-white);
|
||||
--identity-icon-notice-hover: url(chrome://browser/skin/identity-icon.svg#notice-hover-white);
|
||||
}
|
||||
|
||||
:root[devtoolstheme="dark"] #tracking-protection-icon:-moz-lwtheme {
|
||||
--tracking-protection-icon-enabled: url(chrome://browser/skin/tracking-protection-16.svg#enabled-white);
|
||||
--tracking-protection-icon-disabled: url(chrome://browser/skin/tracking-protection-16.svg#disabled-white);
|
||||
}
|
||||
|
||||
:root[devtoolstheme="dark"] #connection-icon:-moz-lwtheme {
|
||||
--connection-icon-mixed-passive-loaded: url(chrome://browser/skin/connection-mixed-passive-loaded.svg#icon-white);
|
||||
--connection-icon-mixed-active-loaded: url(chrome://browser/skin/connection-mixed-active-loaded.svg#icon-white);
|
||||
}
|
||||
%filter substitution
|
||||
%define selectorPrefix :root[devtoolstheme="dark"]
|
||||
%define selectorSuffix :-moz-lwtheme
|
||||
%define iconVariant -white
|
||||
%include identity-block/icons.inc.css
|
||||
|
||||
#urlbar {
|
||||
border-inline-start: none !important;
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
%if 0
|
||||
/* 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/. */
|
||||
%endif
|
||||
|
||||
@selectorPrefix@#identity-icon@selectorSuffix@ {
|
||||
list-style-image: url(chrome://browser/skin/identity-icon.svg#normal@iconVariant@);
|
||||
}
|
||||
|
||||
@selectorPrefix@#identity-box:hover > #identity-icon:not(.no-hover)@selectorSuffix@,
|
||||
@selectorPrefix@#identity-box[open=true] > #identity-icon@selectorSuffix@ {
|
||||
list-style-image: url(chrome://browser/skin/identity-icon.svg#hover@iconVariant@);
|
||||
}
|
||||
|
||||
@selectorPrefix@#identity-box.grantedPermissions > #identity-icon@selectorSuffix@ {
|
||||
list-style-image: url(chrome://browser/skin/identity-icon.svg#notice@iconVariant@);
|
||||
}
|
||||
|
||||
@selectorPrefix@#identity-box.grantedPermissions:hover > #identity-icon:not(.no-hover)@selectorSuffix@,
|
||||
@selectorPrefix@#identity-box.grantedPermissions[open=true] > #identity-icon@selectorSuffix@ {
|
||||
list-style-image: url(chrome://browser/skin/identity-icon.svg#notice-hover@iconVariant@);
|
||||
}
|
||||
|
||||
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.chromeUI > #identity-icon@selectorSuffix@ {
|
||||
list-style-image: url(chrome://branding/content/identity-icons-brand.svg);
|
||||
}
|
||||
|
||||
|
||||
@selectorPrefix@#tracking-protection-icon@selectorSuffix@ {
|
||||
list-style-image: url(chrome://browser/skin/tracking-protection-16.svg#enabled@iconVariant@);
|
||||
}
|
||||
|
||||
@selectorPrefix@#tracking-protection-icon[state="loaded-tracking-content"]@selectorSuffix@ {
|
||||
list-style-image: url(chrome://browser/skin/tracking-protection-16.svg#disabled@iconVariant@);
|
||||
}
|
||||
|
||||
|
||||
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.verifiedDomain > #connection-icon@selectorSuffix@,
|
||||
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity > #connection-icon@selectorSuffix@,
|
||||
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.mixedActiveBlocked > #connection-icon@selectorSuffix@ {
|
||||
list-style-image: url(chrome://browser/skin/connection-secure.svg);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.certUserOverridden > #connection-icon@selectorSuffix@ {
|
||||
list-style-image: url(chrome://browser/skin/connection-mixed-passive-loaded.svg#icon@iconVariant@);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.insecureLoginForms > #connection-icon@selectorSuffix@,
|
||||
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.mixedActiveContent > #connection-icon@selectorSuffix@ {
|
||||
list-style-image: url(chrome://browser/skin/connection-mixed-active-loaded.svg#icon@iconVariant@);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.weakCipher > #connection-icon@selectorSuffix@,
|
||||
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.mixedDisplayContent > #connection-icon@selectorSuffix@,
|
||||
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.mixedDisplayContentLoadedActiveBlocked > #connection-icon@selectorSuffix@ {
|
||||
list-style-image: url(chrome://browser/skin/connection-mixed-passive-loaded.svg#icon@iconVariant@);
|
||||
visibility: visible;
|
||||
}
|
|
@ -4,6 +4,18 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
%endif
|
||||
|
||||
%filter substitution
|
||||
|
||||
%define selectorPrefix
|
||||
%define selectorSuffix
|
||||
%define iconVariant
|
||||
%include icons.inc.css
|
||||
|
||||
%define selectorPrefix
|
||||
%define selectorSuffix :-moz-lwtheme
|
||||
%define iconVariant -black
|
||||
%include icons.inc.css
|
||||
|
||||
#identity-box {
|
||||
font-size: .9em;
|
||||
padding: 3px 5px;
|
||||
|
@ -52,39 +64,8 @@
|
|||
/* MAIN IDENTITY ICON */
|
||||
|
||||
#identity-icon {
|
||||
--identity-icon-normal: url(chrome://browser/skin/identity-icon.svg#normal);
|
||||
--identity-icon-hover: url(chrome://browser/skin/identity-icon.svg#hover);
|
||||
--identity-icon-notice: url(chrome://browser/skin/identity-icon.svg#notice);
|
||||
--identity-icon-notice-hover: url(chrome://browser/skin/identity-icon.svg#notice-hover);
|
||||
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
list-style-image: var(--identity-icon-normal);
|
||||
}
|
||||
|
||||
#identity-icon:-moz-lwtheme {
|
||||
--identity-icon-normal: url(chrome://browser/skin/identity-icon.svg#normal-black);
|
||||
--identity-icon-hover: url(chrome://browser/skin/identity-icon.svg#hover-black);
|
||||
--identity-icon-notice: url(chrome://browser/skin/identity-icon.svg#notice-black);
|
||||
--identity-icon-notice-hover: url(chrome://browser/skin/identity-icon.svg#notice-hover-black);
|
||||
}
|
||||
|
||||
#identity-box:hover > #identity-icon:not(.no-hover),
|
||||
#identity-box[open=true] > #identity-icon {
|
||||
list-style-image: var(--identity-icon-hover);
|
||||
}
|
||||
|
||||
#identity-box.grantedPermissions > #identity-icon {
|
||||
list-style-image: var(--identity-icon-notice);
|
||||
}
|
||||
|
||||
#identity-box.grantedPermissions:hover > #identity-icon:not(.no-hover),
|
||||
#identity-box.grantedPermissions[open=true] > #identity-icon {
|
||||
list-style-image: var(--identity-icon-notice-hover);
|
||||
}
|
||||
|
||||
#urlbar[pageproxystate="valid"] > #identity-box.chromeUI > #identity-icon {
|
||||
list-style-image: url(chrome://branding/content/identity-icons-brand.svg);
|
||||
}
|
||||
|
||||
#urlbar[pageproxystate="invalid"] > #identity-box > #identity-icon {
|
||||
|
@ -142,23 +123,10 @@
|
|||
/* TRACKING PROTECTION ICON */
|
||||
|
||||
#tracking-protection-icon {
|
||||
--tracking-protection-icon-enabled: url(chrome://browser/skin/tracking-protection-16.svg#enabled);
|
||||
--tracking-protection-icon-disabled: url(chrome://browser/skin/tracking-protection-16.svg#disabled);
|
||||
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-inline-start: 2px;
|
||||
margin-inline-end: 0;
|
||||
list-style-image: var(--tracking-protection-icon-enabled);
|
||||
}
|
||||
|
||||
#tracking-protection-icon:-moz-lwtheme {
|
||||
--tracking-protection-icon-enabled: url(chrome://browser/skin/tracking-protection-16.svg#enabled-black);
|
||||
--tracking-protection-icon-disabled: url(chrome://browser/skin/tracking-protection-16.svg#disabled-black);
|
||||
}
|
||||
|
||||
#tracking-protection-icon[state="loaded-tracking-content"] {
|
||||
list-style-image: var(--tracking-protection-icon-disabled);
|
||||
}
|
||||
|
||||
#tracking-protection-icon[animate] {
|
||||
|
@ -184,37 +152,5 @@
|
|||
height: 16px;
|
||||
margin-inline-start: 2px;
|
||||
visibility: collapse;
|
||||
|
||||
--connection-icon-mixed-passive-loaded: url(chrome://browser/skin/connection-mixed-passive-loaded.svg#icon);
|
||||
--connection-icon-mixed-active-loaded: url(chrome://browser/skin/connection-mixed-active-loaded.svg#icon);
|
||||
}
|
||||
|
||||
#connection-icon:-moz-lwtheme {
|
||||
--connection-icon-mixed-passive-loaded: url(chrome://browser/skin/connection-mixed-passive-loaded.svg#icon-black);
|
||||
--connection-icon-mixed-active-loaded: url(chrome://browser/skin/connection-mixed-active-loaded.svg#icon-black);
|
||||
}
|
||||
|
||||
#urlbar[pageproxystate="valid"] > #identity-box.verifiedDomain > #connection-icon,
|
||||
#urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity > #connection-icon,
|
||||
#urlbar[pageproxystate="valid"] > #identity-box.mixedActiveBlocked > #connection-icon {
|
||||
list-style-image: url(chrome://browser/skin/connection-secure.svg);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#urlbar[pageproxystate="valid"] > #identity-box.certUserOverridden > #connection-icon {
|
||||
list-style-image: var(--connection-icon-mixed-passive-loaded);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#urlbar[pageproxystate="valid"] > #identity-box.insecureLoginForms > #connection-icon,
|
||||
#urlbar[pageproxystate="valid"] > #identity-box.mixedActiveContent > #connection-icon {
|
||||
list-style-image: var(--connection-icon-mixed-active-loaded);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#urlbar[pageproxystate="valid"] > #identity-box.weakCipher > #connection-icon,
|
||||
#urlbar[pageproxystate="valid"] > #identity-box.mixedDisplayContent > #connection-icon,
|
||||
#urlbar[pageproxystate="valid"] > #identity-box.mixedDisplayContentLoadedActiveBlocked > #connection-icon {
|
||||
list-style-image: var(--connection-icon-mixed-passive-loaded);
|
||||
visibility: visible;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=995943
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestCompleteLog();
|
||||
if (navigator.userAgent.indexOf("Mac OS X 10.10") != -1)
|
||||
SimpleTest.expectAssertions(6, 9); // See bug 1067022
|
||||
SimpleTest.expectAssertions(5, 9); // See bug 1067022
|
||||
else if (Services.appinfo.OS == "WINNT")
|
||||
SimpleTest.expectAssertions(0, 1); // See bug 1067022
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
# vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
# 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/.
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# This script checks encoding of the files that define JSErrorFormatStrings.
|
||||
#
|
||||
# JSErrorFormatString.format member should be in ASCII encoding.
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
from check_utils import get_all_toplevel_filenames
|
||||
|
||||
scriptname = os.path.basename(__file__);
|
||||
expected_encoding = 'ascii'
|
||||
|
||||
# The following files don't define JSErrorFormatString.
|
||||
ignore_files = [
|
||||
'dom/base/domerr.msg',
|
||||
'js/xpconnect/src/xpc.msg',
|
||||
]
|
||||
|
||||
def log_pass(filename, text):
|
||||
print('TEST-PASS | {} | {} | {}'.format(scriptname, filename, text))
|
||||
|
||||
def log_fail(filename, text):
|
||||
print('TEST-UNEXPECTED-FAIL | {} | {} | {}'.format(scriptname, filename,
|
||||
text))
|
||||
|
||||
def check_single_file(filename):
|
||||
with open(filename, 'rb') as f:
|
||||
data = f.read()
|
||||
try:
|
||||
data.decode(expected_encoding)
|
||||
except:
|
||||
log_fail(filename, 'not in {} encoding'.format(expected_encoding))
|
||||
|
||||
log_pass(filename, 'ok')
|
||||
return True
|
||||
|
||||
def check_files():
|
||||
result = True
|
||||
|
||||
for filename in get_all_toplevel_filenames():
|
||||
if filename.endswith('.msg'):
|
||||
if filename not in ignore_files:
|
||||
if not check_single_file(filename):
|
||||
result = False
|
||||
|
||||
return result
|
||||
|
||||
def main():
|
||||
if not check_files():
|
||||
sys.exit(1)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -934,9 +934,12 @@ cargo_build_flags += --verbose
|
|||
# We need to run cargo unconditionally, because cargo is the only thing that
|
||||
# has full visibility into how changes in Rust sources might affect the final
|
||||
# build.
|
||||
#
|
||||
# XXX: We're passing `-C debuginfo=1` to rustc to work around an llvm-dsymutil
|
||||
# crash (bug 1301751). This should be temporary until we upgrade to Rust 1.12.
|
||||
force-cargo-build:
|
||||
$(REPORT_BUILD)
|
||||
env CARGO_TARGET_DIR=. RUSTC=$(RUSTC) $(CARGO) build $(cargo_build_flags) --
|
||||
env CARGO_TARGET_DIR=. RUSTC=$(RUSTC) RUSTFLAGS='-C debuginfo=1' $(CARGO) build $(cargo_build_flags) --
|
||||
|
||||
$(RUST_LIBRARY_FILE): force-cargo-build
|
||||
endif # CARGO_FILE
|
||||
|
|
|
@ -60,7 +60,9 @@ function pushPrefEnv() {
|
|||
let options = {
|
||||
"set": [
|
||||
["security.mixed_content.block_active_content", true],
|
||||
["security.mixed_content.block_display_content", true]
|
||||
["security.mixed_content.block_display_content", true],
|
||||
["security.mixed_content.use_hsts", false],
|
||||
["security.mixed_content.send_hsts_priming", false],
|
||||
]
|
||||
};
|
||||
SpecialPowers.pushPrefEnv(options, deferred.resolve);
|
||||
|
|
|
@ -94,6 +94,13 @@ function testXhrWarn() {
|
|||
});
|
||||
|
||||
let lastRequest = yield waitForFinishedRequest(XHR_WARN_REQUEST_PREDICATE);
|
||||
if (lastRequest.request.method == "HEAD") {
|
||||
// in non-e10s, we get the HEAD request that priming sends, so make sure
|
||||
// a priming request should be sent, and then get the actual request
|
||||
is(Services.prefs.getBoolPref("security.mixed_content.send_hsts_priming"),
|
||||
true, "Found HSTS Priming Request");
|
||||
lastRequest = yield waitForFinishedRequest(XHR_WARN_REQUEST_PREDICATE);
|
||||
}
|
||||
|
||||
ok(lastRequest, "testXhrWarn() was logged");
|
||||
is(lastRequest.request.method, "GET", "Method is correct");
|
||||
|
|
|
@ -380,7 +380,8 @@ exports.defineLazyGetter(this, "NetworkHelper", () => {
|
|||
* - window: the window to get the loadGroup from
|
||||
* - charset: the charset to use if the channel doesn't provide one
|
||||
* - principal: the principal to use, if omitted, the request is loaded
|
||||
* with the system principal
|
||||
* with a codebase principal corresponding to the url being
|
||||
* loaded, using the origin attributes of the window, if any.
|
||||
* - cacheKey: when loading from cache, use this key to retrieve a cache
|
||||
* specific to a given SHEntry. (Allows loading POST
|
||||
* requests from cache)
|
||||
|
@ -526,51 +527,44 @@ function mainThreadFetch(aURL, aOptions = { loadFromCache: true,
|
|||
*/
|
||||
function newChannelForURL(url, { policy, window, principal }) {
|
||||
var securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
|
||||
if (window) {
|
||||
// Respect private browsing.
|
||||
var req = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocumentLoader)
|
||||
.loadGroup;
|
||||
if (req) {
|
||||
var nc = req.notificationCallbacks;
|
||||
if (nc) {
|
||||
try {
|
||||
var lc = nc.getInterface(Ci.nsILoadContext);
|
||||
if (lc) {
|
||||
if (lc.usePrivateBrowsing) {
|
||||
securityFlags |= Ci.nsILoadInfo.SEC_FORCE_PRIVATE_BROWSING;
|
||||
}
|
||||
}
|
||||
} catch (ex) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let channelOptions = {
|
||||
contentPolicyType: policy,
|
||||
securityFlags: securityFlags,
|
||||
uri: url
|
||||
};
|
||||
if (principal) {
|
||||
// contentPolicyType is required when loading with a custom principal
|
||||
if (!channelOptions.contentPolicyType) {
|
||||
channelOptions.contentPolicyType = Ci.nsIContentPolicy.TYPE_OTHER;
|
||||
}
|
||||
channelOptions.loadingPrincipal = principal;
|
||||
} else {
|
||||
channelOptions.loadUsingSystemPrincipal = true;
|
||||
}
|
||||
|
||||
let uri;
|
||||
try {
|
||||
return NetUtil.newChannel(channelOptions);
|
||||
uri = Services.io.newURI(url, null, null);
|
||||
} catch (e) {
|
||||
// In the xpcshell tests, the script url is the absolute path of the test
|
||||
// file, which will make a malformed URI error be thrown. Add the file
|
||||
// scheme to see if it helps.
|
||||
channelOptions.uri = "file://" + url;
|
||||
uri = Services.io.newURI("file://" + url, null, null);
|
||||
}
|
||||
let channelOptions = {
|
||||
contentPolicyType: policy,
|
||||
securityFlags: securityFlags,
|
||||
uri: uri
|
||||
};
|
||||
let prin = principal;
|
||||
if (!prin) {
|
||||
let oa = {};
|
||||
if (window) {
|
||||
oa = window.document.nodePrincipal.originAttributes;
|
||||
}
|
||||
prin = Services.scriptSecurityManager
|
||||
.createCodebasePrincipal(uri, oa);
|
||||
}
|
||||
// contentPolicyType is required when specifying a principal
|
||||
if (!channelOptions.contentPolicyType) {
|
||||
channelOptions.contentPolicyType = Ci.nsIContentPolicy.TYPE_OTHER;
|
||||
}
|
||||
channelOptions.loadingPrincipal = prin;
|
||||
|
||||
try {
|
||||
return NetUtil.newChannel(channelOptions);
|
||||
} catch (e) {
|
||||
// In xpcshell tests on Windows, nsExternalProtocolHandler::NewChannel()
|
||||
// can throw NS_ERROR_UNKNOWN_PROTOCOL if the external protocol isn't
|
||||
// supported by Windows, so we also need to handle the exception here if
|
||||
// parsing the URL above doesn't throw.
|
||||
return newChannelForURL("file://" + url, { policy, window, principal });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4986,10 +4986,10 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
|||
do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI,
|
||||
flags, &isStsHost);
|
||||
flags, nullptr, &isStsHost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HPKP, aURI,
|
||||
flags, &isPinnedHost);
|
||||
flags, nullptr, &isPinnedHost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
mozilla::dom::ContentChild* cc =
|
||||
|
@ -9862,6 +9862,25 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
|||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
|
||||
// If HSTS priming was set by nsMixedContentBlocker::ShouldLoad, and we
|
||||
// would block due to mixed content, go ahead and block here. If we try to
|
||||
// proceed with priming, we will error out later on.
|
||||
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(context);
|
||||
NS_ENSURE_TRUE(docShell, NS_OK);
|
||||
if (docShell) {
|
||||
nsIDocument* document = docShell->GetDocument();
|
||||
NS_ENSURE_TRUE(document, NS_OK);
|
||||
|
||||
HSTSPrimingState state = document->GetHSTSPrimingStateForLocation(aURI);
|
||||
if (state == HSTSPrimingState::eHSTS_PRIMING_BLOCK) {
|
||||
// HSTS Priming currently disabled for InternalLoad, so we need to clear
|
||||
// the location that was added by nsMixedContentBlocker::ShouldLoad
|
||||
// Bug 1269815 will address images loaded via InternalLoad
|
||||
document->ClearHSTSPrimingLocation(aURI);
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
|
||||
//
|
||||
// Get a principal from the current document if necessary. Note that we only
|
||||
|
@ -10838,10 +10857,6 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
|||
securityFlags |= nsILoadInfo::SEC_SANDBOXED;
|
||||
}
|
||||
|
||||
if (UsePrivateBrowsing()) {
|
||||
securityFlags |= nsILoadInfo::SEC_FORCE_PRIVATE_BROWSING;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo =
|
||||
(aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) ?
|
||||
new LoadInfo(loadingWindow, triggeringPrincipal,
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
#include "nsIUUIDGenerator.h"
|
||||
#include "nsPIDOMWindow.h" // for use in inline functions
|
||||
#include "nsPropertyTable.h" // for member
|
||||
#include "nsTHashtable.h" // for member
|
||||
#include "nsDataHashtable.h" // for member
|
||||
#include "nsURIHashKey.h" // for member
|
||||
#include "mozilla/net/ReferrerPolicy.h" // for member
|
||||
#include "nsWeakReference.h"
|
||||
#include "mozilla/UseCounter.h"
|
||||
|
@ -175,6 +176,13 @@ enum DocumentFlavor {
|
|||
DocumentFlavorPlain, // Just a Document
|
||||
};
|
||||
|
||||
// Enum for HSTS priming states
|
||||
enum class HSTSPrimingState {
|
||||
eNO_HSTS_PRIMING = 0, // don't do HSTS Priming
|
||||
eHSTS_PRIMING_ALLOW = 1, // if HSTS priming fails, allow the load to proceed
|
||||
eHSTS_PRIMING_BLOCK = 2 // if HSTS priming fails, block the load
|
||||
};
|
||||
|
||||
// Document states
|
||||
|
||||
// RTL locale: specific to the XUL localedir attribute
|
||||
|
@ -364,6 +372,34 @@ public:
|
|||
mReferrer = aReferrer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a subresource we want to load requires HSTS priming
|
||||
* to be done.
|
||||
*/
|
||||
HSTSPrimingState GetHSTSPrimingStateForLocation(nsIURI* aContentLocation) const
|
||||
{
|
||||
HSTSPrimingState state;
|
||||
if (mHSTSPrimingURIList.Get(aContentLocation, &state)) {
|
||||
return state;
|
||||
}
|
||||
return HSTSPrimingState::eNO_HSTS_PRIMING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a subresource to the HSTS priming list. If this URI is
|
||||
* not in the HSTS cache, it will trigger an HSTS priming request
|
||||
* when we try to load it.
|
||||
*/
|
||||
void AddHSTSPrimingLocation(nsIURI* aContentLocation, HSTSPrimingState aState)
|
||||
{
|
||||
mHSTSPrimingURIList.Put(aContentLocation, aState);
|
||||
}
|
||||
|
||||
void ClearHSTSPrimingLocation(nsIURI* aContentLocation)
|
||||
{
|
||||
mHSTSPrimingURIList.Remove(aContentLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the principal responsible for this document.
|
||||
*/
|
||||
|
@ -2768,16 +2804,6 @@ public:
|
|||
return mHasScrollLinkedEffect;
|
||||
}
|
||||
|
||||
bool MayHavePluginFramesForPrinting()
|
||||
{
|
||||
return mMayHavePluginFramesForPrinting;
|
||||
}
|
||||
|
||||
void SetMayHavePluginFramesForPrinting()
|
||||
{
|
||||
mMayHavePluginFramesForPrinting = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool GetUseCounter(mozilla::UseCounter aUseCounter)
|
||||
{
|
||||
|
@ -2866,6 +2892,11 @@ protected:
|
|||
bool mUpgradeInsecureRequests;
|
||||
bool mUpgradeInsecurePreloads;
|
||||
|
||||
// if nsMixedContentBlocker requires sending an HSTS priming request,
|
||||
// temporarily store that in the document so that it can be propogated to the
|
||||
// LoadInfo and eventually the HTTP Channel
|
||||
nsDataHashtable<nsURIHashKey, HSTSPrimingState> mHSTSPrimingURIList;
|
||||
|
||||
mozilla::WeakPtr<nsDocShell> mDocumentContainer;
|
||||
|
||||
nsCString mCharacterSet;
|
||||
|
@ -3074,10 +3105,6 @@ protected:
|
|||
// True is document has ever been in a foreground window.
|
||||
bool mEverInForeground : 1;
|
||||
|
||||
// True if this document is a static clone for printing and may
|
||||
// have elements referring to plugins in the original document.
|
||||
bool mMayHavePluginFramesForPrinting : 1;
|
||||
|
||||
enum Type {
|
||||
eUnknown, // should never be used
|
||||
eHTML,
|
||||
|
|
|
@ -1765,7 +1765,8 @@ nsINode::Before(const Sequence<OwningNodeOrString>& aNodes,
|
|||
return;
|
||||
}
|
||||
|
||||
nsINode* viablePreviousSibling = FindViablePreviousSibling(*this, aNodes);
|
||||
nsCOMPtr<nsINode> viablePreviousSibling =
|
||||
FindViablePreviousSibling(*this, aNodes);
|
||||
|
||||
nsCOMPtr<nsINode> node =
|
||||
ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv);
|
||||
|
@ -1788,7 +1789,7 @@ nsINode::After(const Sequence<OwningNodeOrString>& aNodes,
|
|||
return;
|
||||
}
|
||||
|
||||
nsINode* viableNextSibling = FindViableNextSibling(*this, aNodes);
|
||||
nsCOMPtr<nsINode> viableNextSibling = FindViableNextSibling(*this, aNodes);
|
||||
|
||||
nsCOMPtr<nsINode> node =
|
||||
ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv);
|
||||
|
@ -1808,7 +1809,7 @@ nsINode::ReplaceWith(const Sequence<OwningNodeOrString>& aNodes,
|
|||
return;
|
||||
}
|
||||
|
||||
nsINode* viableNextSibling = FindViableNextSibling(*this, aNodes);
|
||||
nsCOMPtr<nsINode> viableNextSibling = FindViableNextSibling(*this, aNodes);
|
||||
|
||||
nsCOMPtr<nsINode> node =
|
||||
ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv);
|
||||
|
|
|
@ -2907,13 +2907,9 @@ nsObjectLoadingContent::CreateStaticClone(nsObjectLoadingContent* aDest) const
|
|||
aDest->mPrintFrame = const_cast<nsObjectLoadingContent*>(this)->GetExistingFrame();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(aDest));
|
||||
if (aDest->mPrintFrame) {
|
||||
content->OwnerDoc()->SetMayHavePluginFramesForPrinting();
|
||||
}
|
||||
|
||||
if (mFrameLoader) {
|
||||
nsCOMPtr<nsIContent> content =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(aDest));
|
||||
nsFrameLoader* fl = nsFrameLoader::Create(content->AsElement(), false);
|
||||
if (fl) {
|
||||
aDest->mFrameLoader = fl;
|
||||
|
|
|
@ -194,6 +194,12 @@ function createPolicyTest(policy, optionalEarlierPolicy) {
|
|||
}
|
||||
|
||||
function handleRequest(request, response) {
|
||||
if (request.method == 'HEAD') {
|
||||
// respond to a HEAD request with a 418 so that we can easily distinguish
|
||||
// HSTS priming responses and ignore them
|
||||
response.setStatusLine('1.1', 418, "I'm a teapot");
|
||||
return;
|
||||
}
|
||||
var sharedKey = 'bug704320.sjs';
|
||||
var params = request.queryString.split('&');
|
||||
var action = params[0].split('=')[1];
|
||||
|
|
|
@ -25,6 +25,9 @@ function doXHR(url, onSuccess, onFail) {
|
|||
xhr.onload = function () {
|
||||
if (xhr.status == 200) {
|
||||
onSuccess(xhr);
|
||||
} else if (xhr.status == 418) {
|
||||
// Ignore HSTS priming responses
|
||||
return;
|
||||
} else {
|
||||
onFail(xhr);
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ MSG_DEF(MSG_SW_INSTALL_ERROR, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for
|
|||
MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")
|
||||
MSG_DEF(MSG_TYPEDARRAY_IS_SHARED, 1, JSEXN_TYPEERR, "{0} can't be a typed array on SharedArrayBuffer")
|
||||
MSG_DEF(MSG_CACHE_ADD_FAILED_RESPONSE, 3, JSEXN_TYPEERR, "Cache got {0} response with bad status {1} while trying to add request {2}")
|
||||
MSG_DEF(MSG_SW_UPDATE_BAD_REGISTRATION, 2, JSEXN_TYPEERR, "Failed to update the ServiceWorker for scope {0] because the registration has been {1} since the update was scheduled.")
|
||||
MSG_DEF(MSG_SW_UPDATE_BAD_REGISTRATION, 2, JSEXN_TYPEERR, "Failed to update the ServiceWorker for scope {0} because the registration has been {1} since the update was scheduled.")
|
||||
MSG_DEF(MSG_INVALID_DURATION_ERROR, 1, JSEXN_TYPEERR, "Invalid duration '{0}'.")
|
||||
MSG_DEF(MSG_INVALID_EASING_ERROR, 1, JSEXN_TYPEERR, "Invalid easing '{0}'.")
|
||||
MSG_DEF(MSG_INVALID_SPACING_MODE_ERROR, 1, JSEXN_TYPEERR, "Invalid spacing '{0}'.")
|
||||
|
|
|
@ -5768,6 +5768,8 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t aX, int32_t aY, uint32_t
|
|||
//uint8_t *src = aArray->Data();
|
||||
uint8_t *dst = imgsurf->Data();
|
||||
uint8_t* srcLine = aArray->Data() + copyY * (aW * 4) + copyX * 4;
|
||||
// For opaque canvases, we must still premultiply the RGB components, but write the alpha as opaque.
|
||||
uint8_t alphaMask = mOpaque ? 255 : 0;
|
||||
#if 0
|
||||
printf("PutImageData_explicit: dirty x=%d y=%d w=%d h=%d copy x=%d y=%d w=%d h=%d ext x=%d y=%d w=%d h=%d\n",
|
||||
dirtyRect.x, dirtyRect.y, copyWidth, copyHeight,
|
||||
|
@ -5787,9 +5789,9 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t aX, int32_t aY, uint32_t
|
|||
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + b];
|
||||
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + g];
|
||||
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + r];
|
||||
*dst++ = a;
|
||||
*dst++ = a | alphaMask;
|
||||
#else
|
||||
*dst++ = a;
|
||||
*dst++ = a | alphaMask;
|
||||
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + r];
|
||||
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + g];
|
||||
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + b];
|
||||
|
|
|
@ -569,7 +569,7 @@ BaseCaps(const WebGLContextOptions& options, WebGLContext* webgl)
|
|||
if (!forwarder)
|
||||
break;
|
||||
|
||||
baseCaps.surfaceAllocator = static_cast<layers::ISurfaceAllocator*>(forwarder);
|
||||
baseCaps.surfaceAllocator = forwarder->GetTextureForwarder();
|
||||
} while (false);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<canvas id='cid'></canvas>
|
||||
<script>
|
||||
var x=document.getElementById('cid').getContext('2d',{alpha: false});
|
||||
x.putImageData(x.createImageData(250,27434.63),Number.MAX_SAFE_INTEGER,23);
|
||||
</script>
|
|
@ -37,4 +37,5 @@ load 1290628-1.html
|
|||
load 1283113-1.html
|
||||
load 1286458-1.html
|
||||
load 1299062-1.html
|
||||
load 1305312-1.html
|
||||
|
||||
|
|
|
@ -3442,7 +3442,7 @@ HTMLInputElement::Focus(ErrorResult& aError)
|
|||
return;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_LINUX)
|
||||
#if !defined(ANDROID) && !defined(XP_MACOSX)
|
||||
bool
|
||||
HTMLInputElement::IsNodeApzAwareInternal() const
|
||||
{
|
||||
|
@ -4538,7 +4538,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
|||
}
|
||||
break;
|
||||
}
|
||||
#if defined(XP_WIN) || defined(XP_LINUX)
|
||||
#if !defined(ANDROID) && !defined(XP_MACOSX)
|
||||
case eWheel: {
|
||||
// Handle wheel events as increasing / decreasing the input element's
|
||||
// value when it's focused and it's type is number or range.
|
||||
|
@ -6203,7 +6203,7 @@ FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget,
|
|||
void
|
||||
HTMLInputElement::UpdateApzAwareFlag()
|
||||
{
|
||||
#if defined(XP_WIN) || defined(XP_LINUX)
|
||||
#if !defined(ANDROID) && !defined(XP_MACOSX)
|
||||
if ((mType == NS_FORM_INPUT_NUMBER) || (mType == NS_FORM_INPUT_RANGE)) {
|
||||
SetMayBeApzAware();
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ public:
|
|||
virtual void Focus(ErrorResult& aError) override;
|
||||
|
||||
// nsINode
|
||||
#if defined(XP_WIN) || defined(XP_LINUX)
|
||||
#if !defined(ANDROID) && !defined(XP_MACOSX)
|
||||
virtual bool IsNodeApzAwareInternal() const override;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -565,16 +565,6 @@ public:
|
|||
? nsIContentPolicy::TYPE_INTERNAL_AUDIO :
|
||||
nsIContentPolicy::TYPE_INTERNAL_VIDEO;
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = aElement->OwnerDoc()->GetDocShell();
|
||||
if (docShell) {
|
||||
nsDocShell* docShellPtr = nsDocShell::Cast(docShell);
|
||||
bool privateBrowsing;
|
||||
docShellPtr->GetUsePrivateBrowsing(&privateBrowsing);
|
||||
if (privateBrowsing) {
|
||||
securityFlags |= nsILoadInfo::SEC_FORCE_PRIVATE_BROWSING;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = aElement->GetDocumentLoadGroup();
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
|
|
|
@ -622,11 +622,11 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
|
|||
[test_bug1250401.html]
|
||||
[test_bug1260664.html]
|
||||
[test_bug1261673.html]
|
||||
skip-if = (os != 'win' && os != 'linux')
|
||||
skip-if = (os == 'android' || os == 'mac')
|
||||
[test_bug1261674-1.html]
|
||||
skip-if = (os != 'win' && os != 'linux')
|
||||
skip-if = (os == 'android' || os == 'mac')
|
||||
[test_bug1261674-2.html]
|
||||
skip-if = (os != 'win' && os != 'linux')
|
||||
skip-if = (os == 'android' || os == 'mac')
|
||||
[test_bug1260704.html]
|
||||
[test_allowMedia.html]
|
||||
[test_bug1292522_same_domain_with_different_port_number.html]
|
||||
|
|
|
@ -41,11 +41,14 @@ let tests = [
|
|||
Services.prefs.setBoolPref("browser.send_pings", true);
|
||||
Services.prefs.setIntPref("browser.send_pings.max_per_link", -1);
|
||||
Services.prefs.setBoolPref("security.mixed_content.block_active_content", false);
|
||||
// The server we create can't handle the priming HEAD requests
|
||||
Services.prefs.setBoolPref("security.mixed_content.send_hsts_priming", false);
|
||||
|
||||
SimpleTest.registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("browser.send_pings");
|
||||
Services.prefs.clearUserPref("browser.send_pings.max_per_link");
|
||||
Services.prefs.clearUserPref("security.mixed_content.block_active_content");
|
||||
Services.prefs.clearUserPref("security.mixed_content.send_hsts_priming");
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -5314,7 +5314,7 @@ private:
|
|||
struct IdleThreadInfo;
|
||||
struct ThreadInfo;
|
||||
class ThreadRunnable;
|
||||
struct TransactionInfo;
|
||||
class TransactionInfo;
|
||||
struct TransactionInfoPair;
|
||||
|
||||
// This mutex guards mDatabases, see below.
|
||||
|
@ -5713,10 +5713,14 @@ private:
|
|||
NS_DECL_NSIRUNNABLE
|
||||
};
|
||||
|
||||
struct ConnectionPool::TransactionInfo final
|
||||
class ConnectionPool::TransactionInfo final
|
||||
{
|
||||
friend class nsAutoPtr<TransactionInfo>;
|
||||
|
||||
nsTHashtable<nsPtrHashKey<TransactionInfo>> mBlocking;
|
||||
nsTArray<TransactionInfo*> mBlockingOrdered;
|
||||
|
||||
public:
|
||||
DatabaseInfo* mDatabaseInfo;
|
||||
const nsID mBackgroundChildLoggingId;
|
||||
const nsCString mDatabaseId;
|
||||
|
@ -5724,7 +5728,6 @@ struct ConnectionPool::TransactionInfo final
|
|||
const int64_t mLoggingSerialNumber;
|
||||
const nsTArray<nsString> mObjectStoreNames;
|
||||
nsTHashtable<nsPtrHashKey<TransactionInfo>> mBlockedOn;
|
||||
nsTHashtable<nsPtrHashKey<TransactionInfo>> mBlocking;
|
||||
nsTArray<nsCOMPtr<nsIRunnable>> mQueuedRunnables;
|
||||
const bool mIsWriteTransaction;
|
||||
bool mRunning;
|
||||
|
@ -5743,10 +5746,16 @@ struct ConnectionPool::TransactionInfo final
|
|||
TransactionDatabaseOperationBase* aTransactionOp);
|
||||
|
||||
void
|
||||
Schedule();
|
||||
AddBlockingTransaction(TransactionInfo* aTransactionInfo);
|
||||
|
||||
void
|
||||
RemoveBlockingTransactions();
|
||||
|
||||
private:
|
||||
~TransactionInfo();
|
||||
|
||||
void
|
||||
MaybeUnblock(TransactionInfo* aTransactionInfo);
|
||||
};
|
||||
|
||||
struct ConnectionPool::TransactionInfoPair final
|
||||
|
@ -11745,7 +11754,7 @@ ConnectionPool::Start(const nsID& aBackgroundChildLoggingId,
|
|||
// Mark what we are blocking on.
|
||||
if (TransactionInfo* blockingRead = blockInfo->mLastBlockingReads) {
|
||||
transactionInfo->mBlockedOn.PutEntry(blockingRead);
|
||||
blockingRead->mBlocking.PutEntry(transactionInfo);
|
||||
blockingRead->AddBlockingTransaction(transactionInfo);
|
||||
}
|
||||
|
||||
if (aIsWriteTransaction) {
|
||||
|
@ -11756,7 +11765,7 @@ ConnectionPool::Start(const nsID& aBackgroundChildLoggingId,
|
|||
MOZ_ASSERT(blockingWrite);
|
||||
|
||||
transactionInfo->mBlockedOn.PutEntry(blockingWrite);
|
||||
blockingWrite->mBlocking.PutEntry(transactionInfo);
|
||||
blockingWrite->AddBlockingTransaction(transactionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12288,18 +12297,7 @@ ConnectionPool::NoteFinishedTransaction(uint64_t aTransactionId)
|
|||
blockInfo->mLastBlockingWrites.RemoveElement(transactionInfo);
|
||||
}
|
||||
|
||||
for (auto iter = transactionInfo->mBlocking.Iter();
|
||||
!iter.Done();
|
||||
iter.Next()) {
|
||||
TransactionInfo* blockedInfo = iter.Get()->GetKey();
|
||||
MOZ_ASSERT(blockedInfo);
|
||||
MOZ_ASSERT(blockedInfo->mBlockedOn.Contains(transactionInfo));
|
||||
|
||||
blockedInfo->mBlockedOn.RemoveEntry(transactionInfo);
|
||||
if (!blockedInfo->mBlockedOn.Count()) {
|
||||
blockedInfo->Schedule();
|
||||
}
|
||||
}
|
||||
transactionInfo->RemoveBlockingTransactions();
|
||||
|
||||
if (transactionInfo->mIsWriteTransaction) {
|
||||
MOZ_ASSERT(dbInfo->mWriteTransactionCount);
|
||||
|
@ -13068,18 +13066,55 @@ TransactionInfo::~TransactionInfo()
|
|||
|
||||
void
|
||||
ConnectionPool::
|
||||
TransactionInfo::Schedule()
|
||||
TransactionInfo::AddBlockingTransaction(TransactionInfo* aTransactionInfo)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mDatabaseInfo);
|
||||
MOZ_ASSERT(aTransactionInfo);
|
||||
|
||||
ConnectionPool* connectionPool = mDatabaseInfo->mConnectionPool;
|
||||
MOZ_ASSERT(connectionPool);
|
||||
connectionPool->AssertIsOnOwningThread();
|
||||
if (!mBlocking.Contains(aTransactionInfo)) {
|
||||
mBlocking.PutEntry(aTransactionInfo);
|
||||
mBlockingOrdered.AppendElement(aTransactionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
Unused <<
|
||||
connectionPool->ScheduleTransaction(this,
|
||||
/* aFromQueuedTransactions */ false);
|
||||
void
|
||||
ConnectionPool::
|
||||
TransactionInfo::RemoveBlockingTransactions()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
for (uint32_t index = 0, count = mBlockingOrdered.Length();
|
||||
index < count;
|
||||
index++) {
|
||||
TransactionInfo* blockedInfo = mBlockingOrdered[index];
|
||||
MOZ_ASSERT(blockedInfo);
|
||||
|
||||
blockedInfo->MaybeUnblock(this);
|
||||
}
|
||||
|
||||
mBlocking.Clear();
|
||||
mBlockingOrdered.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionPool::
|
||||
TransactionInfo::MaybeUnblock(TransactionInfo* aTransactionInfo)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mBlockedOn.Contains(aTransactionInfo));
|
||||
|
||||
mBlockedOn.RemoveEntry(aTransactionInfo);
|
||||
if (!mBlockedOn.Count()) {
|
||||
MOZ_ASSERT(mDatabaseInfo);
|
||||
|
||||
ConnectionPool* connectionPool = mDatabaseInfo->mConnectionPool;
|
||||
MOZ_ASSERT(connectionPool);
|
||||
connectionPool->AssertIsOnOwningThread();
|
||||
|
||||
Unused <<
|
||||
connectionPool->ScheduleTransaction(this,
|
||||
/* aFromQueuedTransactions */ false);
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionPool::
|
||||
|
|
|
@ -1554,7 +1554,8 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBObjectStore)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexes);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexes)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeletedIndexes)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBObjectStore)
|
||||
|
@ -1562,7 +1563,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBObjectStore)
|
|||
|
||||
// Don't unlink mTransaction!
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexes);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexes)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDeletedIndexes)
|
||||
|
||||
tmp->mCachedKeyPath.setUndefined();
|
||||
|
||||
|
@ -1774,13 +1776,11 @@ IDBObjectStore::CreateIndex(const nsAString& aName,
|
|||
}
|
||||
|
||||
IDBTransaction* transaction = IDBTransaction::GetCurrent();
|
||||
if (!transaction || transaction != mTransaction) {
|
||||
if (!transaction || transaction != mTransaction || !transaction->IsOpen()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(transaction->IsOpen());
|
||||
|
||||
auto& indexes = const_cast<nsTArray<IndexMetadata>&>(mSpec->indexes());
|
||||
for (uint32_t count = indexes.Length(), index = 0;
|
||||
index < count;
|
||||
|
@ -1888,13 +1888,11 @@ IDBObjectStore::DeleteIndex(const nsAString& aName, ErrorResult& aRv)
|
|||
}
|
||||
|
||||
IDBTransaction* transaction = IDBTransaction::GetCurrent();
|
||||
if (!transaction || transaction != mTransaction) {
|
||||
if (!transaction || transaction != mTransaction || !transaction->IsOpen()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(transaction->IsOpen());
|
||||
|
||||
auto& metadataArray = const_cast<nsTArray<IndexMetadata>&>(mSpec->indexes());
|
||||
|
||||
int64_t foundId = 0;
|
||||
|
@ -1916,6 +1914,11 @@ IDBObjectStore::DeleteIndex(const nsAString& aName, ErrorResult& aRv)
|
|||
|
||||
if (index->Id() == foundId) {
|
||||
index->NoteDeletion();
|
||||
|
||||
RefPtr<IDBIndex>* deletedIndex =
|
||||
mDeletedIndexes.AppendElement();
|
||||
deletedIndex->swap(mIndexes[indexIndex]);
|
||||
|
||||
mIndexes.RemoveElementAt(indexIndex);
|
||||
break;
|
||||
}
|
||||
|
@ -2130,6 +2133,12 @@ IDBObjectStore::RefreshSpec(bool aMayDelete)
|
|||
mIndexes[idxIndex]->RefreshMetadata(aMayDelete);
|
||||
}
|
||||
|
||||
for (uint32_t idxCount = mDeletedIndexes.Length(), idxIndex = 0;
|
||||
idxIndex < idxCount;
|
||||
idxIndex++) {
|
||||
mDeletedIndexes[idxIndex]->RefreshMetadata(false);
|
||||
}
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -2202,13 +2211,11 @@ IDBObjectStore::SetName(const nsAString& aName, ErrorResult& aRv)
|
|||
}
|
||||
|
||||
IDBTransaction* transaction = IDBTransaction::GetCurrent();
|
||||
if (!transaction || transaction != mTransaction) {
|
||||
if (!transaction || transaction != mTransaction || !transaction->IsOpen()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(transaction->IsOpen());
|
||||
|
||||
if (aName == mSpec->metadata().name()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ class IDBObjectStore final
|
|||
nsAutoPtr<ObjectStoreSpec> mDeletedSpec;
|
||||
|
||||
nsTArray<RefPtr<IDBIndex>> mIndexes;
|
||||
nsTArray<RefPtr<IDBIndex>> mDeletedIndexes;
|
||||
|
||||
const int64_t mId;
|
||||
bool mRooted;
|
||||
|
|
|
@ -653,6 +653,12 @@ IDBTransaction::AbortInternal(nsresult aAbortCode,
|
|||
mDatabase->RevertToPreviousState();
|
||||
}
|
||||
|
||||
// We do the reversion only for the mObjectStores/mDeletedObjectStores but
|
||||
// not for the mIndexes/mDeletedIndexes of each IDBObjectStore because it's
|
||||
// time-consuming(O(m*n)) and mIndexes/mDeletedIndexes won't be used anymore
|
||||
// in IDBObjectStore::(Create|Delete)Index() and IDBObjectStore::Index() in
|
||||
// which all the executions are returned earlier by !transaction->IsOpen().
|
||||
|
||||
const nsTArray<ObjectStoreSpec>& specArray =
|
||||
mDatabase->Spec()->objectStores();
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ support-files =
|
|||
service_worker_client.html
|
||||
third_party_iframe1.html
|
||||
third_party_iframe2.html
|
||||
unit/test_abort_deleted_index.js
|
||||
unit/test_abort_deleted_objectStore.js
|
||||
unit/test_add_put.js
|
||||
unit/test_add_twice_failure.js
|
||||
unit/test_advance.js
|
||||
|
@ -115,6 +117,10 @@ support-files =
|
|||
webapp_clearBrowserData_appFrame.html
|
||||
webapp_clearBrowserData_browserFrame.html
|
||||
|
||||
[test_abort_deleted_index.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_abort_deleted_objectStore.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_add_put.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_add_twice_failure.html]
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Abort Deleted Index Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7" src="unit/test_abort_deleted_index.js"></script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="runTest();"></body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,19 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Abort Deleted ObjectStore Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7" src="unit/test_abort_deleted_objectStore.js"></script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="runTest();"></body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var testGenerator = testSteps();
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const name = this.window ? window.location.pathname : "Splendid Test";
|
||||
const storeName = "test store";
|
||||
const indexName_ToBeDeleted = "test index to be deleted";
|
||||
|
||||
info("Create index in v1.");
|
||||
let request = indexedDB.open(name, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
let event = yield undefined;
|
||||
|
||||
let db = event.target.result;
|
||||
let txn = event.target.transaction;
|
||||
|
||||
is(db.objectStoreNames.length, 0, "Correct objectStoreNames list");
|
||||
|
||||
let objectStore = db.createObjectStore(storeName, { keyPath: "foo" });
|
||||
is(db.objectStoreNames.length, 1, "Correct objectStoreNames list");
|
||||
is(db.objectStoreNames.item(0), objectStore.name, "Correct object store name");
|
||||
|
||||
// create index to be deleted later in v2.
|
||||
objectStore.createIndex(indexName_ToBeDeleted, "foo");
|
||||
ok(objectStore.index(indexName_ToBeDeleted), "Index created.");
|
||||
|
||||
txn.oncomplete = continueToNextStepSync;
|
||||
yield undefined;
|
||||
request.onsuccess = continueToNextStep;
|
||||
yield undefined;
|
||||
db.close();
|
||||
|
||||
info("Delete index in v2.");
|
||||
request = indexedDB.open(name, 2);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
event = yield undefined;
|
||||
|
||||
db = event.target.result;
|
||||
txn = event.target.transaction;
|
||||
|
||||
objectStore = txn.objectStore(storeName);
|
||||
let index = objectStore.index(indexName_ToBeDeleted);
|
||||
ok(index, "index is valid.");
|
||||
objectStore.deleteIndex(indexName_ToBeDeleted);
|
||||
|
||||
// Aborting the transaction.
|
||||
request.onerror = expectedErrorHandler("AbortError");
|
||||
txn.abort();
|
||||
try {
|
||||
index.get('foo');
|
||||
ok(false, "TransactionInactiveError shall be thrown right after a deletion of an index is aborted.");
|
||||
} catch (e) {
|
||||
ok(e instanceof DOMException, "got a database exception");
|
||||
is(e.name, "TransactionInactiveError", "TransactionInactiveError shall be thrown right after a deletion of an index is aborted.");
|
||||
}
|
||||
|
||||
yield undefined;
|
||||
|
||||
try {
|
||||
index.get('foo');
|
||||
ok(false, "TransactionInactiveError shall be thrown after the transaction is inactive.");
|
||||
} catch (e) {
|
||||
ok(e instanceof DOMException, "got a database exception");
|
||||
is(e.name, "TransactionInactiveError", "TransactionInactiveError shall be thrown after the transaction is inactive.");
|
||||
}
|
||||
|
||||
finishTest();
|
||||
yield undefined;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var testGenerator = testSteps();
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const name = this.window ? window.location.pathname : "Splendid Test";
|
||||
const storeName_ToBeDeleted = "test store to be deleted";
|
||||
|
||||
info("Create objectStore in v1.");
|
||||
let request = indexedDB.open(name, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
let event = yield undefined;
|
||||
|
||||
let db = event.target.result;
|
||||
let txn = event.target.transaction;
|
||||
|
||||
is(db.objectStoreNames.length, 0, "Correct objectStoreNames list");
|
||||
|
||||
// create objectstore to be deleted later in v2.
|
||||
db.createObjectStore(storeName_ToBeDeleted, { keyPath: "foo" });
|
||||
is(db.objectStoreNames.length, 1, "Correct objectStoreNames list");
|
||||
ok(db.objectStoreNames.contains(storeName_ToBeDeleted), "Correct name");
|
||||
|
||||
txn.oncomplete = continueToNextStepSync;
|
||||
yield undefined;
|
||||
request.onsuccess = continueToNextStep;
|
||||
yield undefined;
|
||||
db.close();
|
||||
|
||||
info("Delete objectStore in v2.");
|
||||
request = indexedDB.open(name, 2);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
event = yield undefined;
|
||||
|
||||
db = event.target.result;
|
||||
txn = event.target.transaction;
|
||||
|
||||
let objectStore = txn.objectStore(storeName_ToBeDeleted);
|
||||
ok(objectStore, "objectStore is available");
|
||||
|
||||
db.deleteObjectStore(storeName_ToBeDeleted);
|
||||
|
||||
// Aborting the transaction.
|
||||
request.onerror = expectedErrorHandler("AbortError");
|
||||
txn.abort();
|
||||
try {
|
||||
objectStore.get('foo');
|
||||
ok(false, "TransactionInactiveError shall be thrown if the transaction is inactive.");
|
||||
} catch (e) {
|
||||
ok(e instanceof DOMException, "got a database exception");
|
||||
is(e.name, "TransactionInactiveError", "correct error");
|
||||
}
|
||||
|
||||
yield undefined;
|
||||
|
||||
try {
|
||||
objectStore.get('foo');
|
||||
ok(false, "TransactionInactiveError shall be thrown if the transaction is inactive.");
|
||||
} catch (e) {
|
||||
ok(e instanceof DOMException, "got a database exception");
|
||||
is(e.name, "TransactionInactiveError", "correct error");
|
||||
}
|
||||
|
||||
finishTest();
|
||||
yield undefined;
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
# 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/.
|
||||
|
||||
[test_abort_deleted_index.js]
|
||||
[test_abort_deleted_objectStore.js]
|
||||
[test_add_put.js]
|
||||
[test_add_twice_failure.js]
|
||||
[test_advance.js]
|
||||
|
|
|
@ -3574,10 +3574,7 @@ BlobChild::SetMysteryBlobInfo(const nsString& aContentType, uint64_t aLength)
|
|||
MOZ_ASSERT(mBlobImpl);
|
||||
MOZ_ASSERT(mRemoteBlobImpl);
|
||||
|
||||
nsString voidString;
|
||||
voidString.SetIsVoid(true);
|
||||
|
||||
mBlobImpl->SetLazyData(voidString, aContentType, aLength, INT64_MAX);
|
||||
mBlobImpl->SetLazyData(NullString(), aContentType, aLength, INT64_MAX);
|
||||
|
||||
NormalBlobConstructorParams params(aContentType,
|
||||
aLength,
|
||||
|
@ -4400,10 +4397,7 @@ BlobParent::RecvResolveMystery(const ResolveMysteryParams& aParams)
|
|||
return false;
|
||||
}
|
||||
|
||||
nsString voidString;
|
||||
voidString.SetIsVoid(true);
|
||||
|
||||
mBlobImpl->SetLazyData(voidString,
|
||||
mBlobImpl->SetLazyData(NullString(),
|
||||
params.contentType(),
|
||||
params.length(),
|
||||
INT64_MAX);
|
||||
|
|
|
@ -822,14 +822,15 @@ ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
|
|||
renderFrame = nullptr;
|
||||
}
|
||||
|
||||
ShowInfo showInfo(EmptyString(), false, false, true, false, 0, 0);
|
||||
ShowInfo showInfo(EmptyString(), false, false, true, false, 0, 0, 0);
|
||||
auto* opener = nsPIDOMWindowOuter::From(aParent);
|
||||
nsIDocShell* openerShell;
|
||||
if (opener && (openerShell = opener->GetDocShell())) {
|
||||
nsCOMPtr<nsILoadContext> context = do_QueryInterface(openerShell);
|
||||
showInfo = ShowInfo(EmptyString(), false,
|
||||
context->UsePrivateBrowsing(), true, false,
|
||||
aTabOpener->mDPI, aTabOpener->mDefaultScale);
|
||||
aTabOpener->mDPI, aTabOpener->mRounding,
|
||||
aTabOpener->mDefaultScale);
|
||||
}
|
||||
|
||||
// Unfortunately we don't get a window unless we've shown the frame. That's
|
||||
|
|
|
@ -3901,18 +3901,18 @@ ContentParent::RecvIsSecureURI(const uint32_t& type,
|
|||
if (!ourURI) {
|
||||
return false;
|
||||
}
|
||||
nsresult rv = sss->IsSecureURI(type, ourURI, flags, isSecureURI);
|
||||
nsresult rv = sss->IsSecureURI(type, ourURI, flags, nullptr, isSecureURI);
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool& aActive)
|
||||
ContentParent::RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool& aActive, const bool& aHSTSPriming)
|
||||
{
|
||||
nsCOMPtr<nsIURI> ourURI = DeserializeURI(aURI);
|
||||
if (!ourURI) {
|
||||
return false;
|
||||
}
|
||||
nsMixedContentBlocker::AccumulateMixedContentHSTS(ourURI, aActive);
|
||||
nsMixedContentBlocker::AccumulateMixedContentHSTS(ourURI, aActive, aHSTSPriming);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -789,7 +789,8 @@ private:
|
|||
const uint32_t& aFlags, bool* aIsSecureURI) override;
|
||||
|
||||
virtual bool RecvAccumulateMixedContentHSTS(const URIParams& aURI,
|
||||
const bool& aActive) override;
|
||||
const bool& aActive,
|
||||
const bool& aHSTSPriming) override;
|
||||
|
||||
virtual bool DeallocPHalParent(PHalParent*) override;
|
||||
|
||||
|
|
|
@ -101,6 +101,7 @@ struct ShowInfo
|
|||
bool fakeShowInfo;
|
||||
bool isTransparent;
|
||||
float dpi;
|
||||
int32_t widgetRounding;
|
||||
double defaultScale;
|
||||
};
|
||||
|
||||
|
@ -375,6 +376,11 @@ parent:
|
|||
*/
|
||||
sync GetDefaultScale() returns (double value);
|
||||
|
||||
/**
|
||||
* Gets the rounding of coordinates in the widget.
|
||||
*/
|
||||
sync GetWidgetRounding() returns (int32_t value);
|
||||
|
||||
/**
|
||||
* Gets maximum of touch points at current device.
|
||||
*/
|
||||
|
@ -793,7 +799,7 @@ child:
|
|||
* value (-1) but in the majority of the cases this saves us from two
|
||||
* sync requests from the child to the parent.
|
||||
*/
|
||||
async UIResolutionChanged(float dpi, double scale);
|
||||
async UIResolutionChanged(float dpi, int32_t rounding, double scale);
|
||||
|
||||
/**
|
||||
* Tell the child that the system theme has changed, and that a repaint
|
||||
|
|
|
@ -838,7 +838,7 @@ parent:
|
|||
sync IsSecureURI(uint32_t type, URIParams uri, uint32_t flags)
|
||||
returns (bool isSecureURI);
|
||||
|
||||
async AccumulateMixedContentHSTS(URIParams uri, bool active);
|
||||
async AccumulateMixedContentHSTS(URIParams uri, bool active, bool hasHSTSPriming);
|
||||
|
||||
sync GetLookAndFeelCache()
|
||||
returns (LookAndFeelInt[] lookAndFeelIntCache);
|
||||
|
|
|
@ -541,6 +541,7 @@ TabChild::TabChild(nsIContentChild* aManager,
|
|||
, mDestroyed(false)
|
||||
, mUniqueId(aTabId)
|
||||
, mDPI(0)
|
||||
, mRounding(0)
|
||||
, mDefaultScale(0)
|
||||
, mIsTransparent(false)
|
||||
, mIPCOpen(false)
|
||||
|
@ -1549,6 +1550,7 @@ TabChild::ApplyShowInfo(const ShowInfo& aInfo)
|
|||
}
|
||||
}
|
||||
mDPI = aInfo.dpi();
|
||||
mRounding = aInfo.widgetRounding();
|
||||
mDefaultScale = aInfo.defaultScale();
|
||||
mIsTransparent = aInfo.isTransparent();
|
||||
}
|
||||
|
@ -2942,6 +2944,22 @@ TabChild::GetDefaultScale(double* aScale)
|
|||
SendGetDefaultScale(aScale);
|
||||
}
|
||||
|
||||
void
|
||||
TabChild::GetWidgetRounding(int32_t* aRounding)
|
||||
{
|
||||
*aRounding = 1;
|
||||
if (!mRemoteFrame) {
|
||||
return;
|
||||
}
|
||||
if (mRounding > 0) {
|
||||
*aRounding = mRounding;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback to a sync call if needed.
|
||||
SendGetWidgetRounding(aRounding);
|
||||
}
|
||||
|
||||
void
|
||||
TabChild::GetMaxTouchPoints(uint32_t* aTouchPoints)
|
||||
{
|
||||
|
@ -3285,12 +3303,15 @@ TabChild::RecvRequestNotifyAfterRemotePaint()
|
|||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvUIResolutionChanged(const float& aDpi, const double& aScale)
|
||||
TabChild::RecvUIResolutionChanged(const float& aDpi,
|
||||
const int32_t& aRounding,
|
||||
const double& aScale)
|
||||
{
|
||||
ScreenIntSize oldScreenSize = GetInnerSize();
|
||||
mDPI = 0;
|
||||
mRounding = 0;
|
||||
mDefaultScale = 0;
|
||||
static_cast<PuppetWidget*>(mPuppetWidget.get())->UpdateBackingScaleCache(aDpi, aScale);
|
||||
static_cast<PuppetWidget*>(mPuppetWidget.get())->UpdateBackingScaleCache(aDpi, aRounding, aScale);
|
||||
nsCOMPtr<nsIDocument> document(GetDocument());
|
||||
nsCOMPtr<nsIPresShell> presShell = document->GetShell();
|
||||
if (presShell) {
|
||||
|
|
|
@ -484,6 +484,8 @@ public:
|
|||
|
||||
void GetDefaultScale(double *aScale);
|
||||
|
||||
void GetWidgetRounding(int32_t* aRounding);
|
||||
|
||||
bool IsTransparent() const { return mIsTransparent; }
|
||||
|
||||
void GetMaxTouchPoints(uint32_t* aTouchPoints);
|
||||
|
@ -572,6 +574,7 @@ public:
|
|||
}
|
||||
|
||||
virtual bool RecvUIResolutionChanged(const float& aDpi,
|
||||
const int32_t& aRounding,
|
||||
const double& aScale) override;
|
||||
|
||||
virtual bool
|
||||
|
@ -777,6 +780,7 @@ private:
|
|||
|
||||
friend class ContentChild;
|
||||
float mDPI;
|
||||
int32_t mRounding;
|
||||
double mDefaultScale;
|
||||
|
||||
bool mIsTransparent;
|
||||
|
|
|
@ -277,6 +277,7 @@ TabParent::TabParent(nsIContentParent* aManager,
|
|||
, mDimensions(0, 0)
|
||||
, mOrientation(0)
|
||||
, mDPI(0)
|
||||
, mRounding(0)
|
||||
, mDefaultScale(0)
|
||||
, mUpdatedDimensions(false)
|
||||
, mSizeMode(nsSizeMode_Normal)
|
||||
|
@ -1030,7 +1031,8 @@ TabParent::UIResolutionChanged()
|
|||
// fails to cache the values, then mDefaultScale.scale might be invalid.
|
||||
// We don't want to send that value to content. Just send -1 for it too in
|
||||
// that case.
|
||||
Unused << SendUIResolutionChanged(mDPI, mDPI < 0 ? -1.0 : mDefaultScale.scale);
|
||||
Unused << SendUIResolutionChanged(mDPI, mRounding,
|
||||
mDPI < 0 ? -1.0 : mDefaultScale.scale);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2499,6 +2501,17 @@ TabParent::RecvGetDefaultScale(double* aValue)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvGetWidgetRounding(int32_t* aValue)
|
||||
{
|
||||
TryCacheDPIAndScale();
|
||||
|
||||
MOZ_ASSERT(mRounding > 0,
|
||||
"Must not ask for rounding before OwnerElement is received!");
|
||||
*aValue = mRounding;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvGetMaxTouchPoints(uint32_t* aTouchPoints)
|
||||
{
|
||||
|
@ -2766,6 +2779,7 @@ TabParent::TryCacheDPIAndScale()
|
|||
|
||||
if (widget) {
|
||||
mDPI = widget->GetDPI();
|
||||
mRounding = widget->RoundsWidgetCoordinatesTo();
|
||||
mDefaultScale = widget->GetDefaultScale();
|
||||
}
|
||||
}
|
||||
|
@ -3374,11 +3388,11 @@ TabParent::GetShowInfo()
|
|||
nsContentUtils::IsChromeDoc(mFrameElement->OwnerDoc()) &&
|
||||
mFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::transparent);
|
||||
return ShowInfo(name, allowFullscreen, isPrivate, false,
|
||||
isTransparent, mDPI, mDefaultScale.scale);
|
||||
isTransparent, mDPI, mRounding, mDefaultScale.scale);
|
||||
}
|
||||
|
||||
return ShowInfo(EmptyString(), false, false, false,
|
||||
false, mDPI, mDefaultScale.scale);
|
||||
false, mDPI, mRounding, mDefaultScale.scale);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -321,6 +321,8 @@ public:
|
|||
|
||||
virtual bool RecvGetDefaultScale(double* aValue) override;
|
||||
|
||||
virtual bool RecvGetWidgetRounding(int32_t* aValue) override;
|
||||
|
||||
virtual bool RecvGetMaxTouchPoints(uint32_t* aTouchPoints) override;
|
||||
|
||||
virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue) override;
|
||||
|
@ -635,6 +637,7 @@ protected:
|
|||
ScreenIntSize mDimensions;
|
||||
ScreenOrientationInternal mOrientation;
|
||||
float mDPI;
|
||||
int32_t mRounding;
|
||||
CSSToLayoutDeviceScale mDefaultScale;
|
||||
bool mUpdatedDimensions;
|
||||
nsSizeMode mSizeMode;
|
||||
|
|
|
@ -70,7 +70,6 @@ nsJSON::Encode(JS::Handle<JS::Value> aValue, JSContext* cx, uint8_t aArgc,
|
|||
return rv;
|
||||
|
||||
if (aArgc == 0) {
|
||||
aJSON.Truncate();
|
||||
aJSON.SetIsVoid(true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -83,7 +82,6 @@ nsJSON::Encode(JS::Handle<JS::Value> aValue, JSContext* cx, uint8_t aArgc,
|
|||
rv = NS_OK;
|
||||
// if we didn't consume anything, it's not JSON, so return null
|
||||
if (!writer.DidWrite()) {
|
||||
aJSON.Truncate();
|
||||
aJSON.SetIsVoid(true);
|
||||
} else {
|
||||
writer.FlushBuffer();
|
||||
|
|
|
@ -365,7 +365,8 @@ AudioStream::OpenCubeb(cubeb* aContext, cubeb_stream_params& aParams,
|
|||
|
||||
cubeb_stream* stream = nullptr;
|
||||
/* Convert from milliseconds to frames. */
|
||||
uint32_t latency_frames = CubebUtils::GetCubebLatency() * aParams.rate / 1000;
|
||||
uint32_t latency_frames =
|
||||
CubebUtils::GetCubebPlaybackLatencyInMilliseconds() * aParams.rate / 1000;
|
||||
if (cubeb_stream_init(aContext, &stream, "AudioStream",
|
||||
nullptr, nullptr, nullptr, &aParams,
|
||||
latency_frames,
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
#include "prdtoa.h"
|
||||
|
||||
#define PREF_VOLUME_SCALE "media.volume_scale"
|
||||
#define PREF_CUBEB_LATENCY "media.cubeb_latency_ms"
|
||||
#define PREF_CUBEB_LATENCY_PLAYBACK "media.cubeb_latency_playback_ms"
|
||||
#define PREF_CUBEB_LATENCY_MSG "media.cubeb_latency_msg_frames"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -34,8 +35,10 @@ enum class CubebState {
|
|||
} sCubebState = CubebState::Uninitialized;
|
||||
cubeb* sCubebContext;
|
||||
double sVolumeScale;
|
||||
uint32_t sCubebLatency;
|
||||
bool sCubebLatencyPrefSet;
|
||||
uint32_t sCubebPlaybackLatencyInMilliseconds;
|
||||
uint32_t sCubebMSGLatencyInFrames;
|
||||
bool sCubebPlaybackLatencyPrefSet;
|
||||
bool sCubebMSGLatencyPrefSet;
|
||||
bool sAudioStreamInitEverSucceeded = false;
|
||||
StaticAutoPtr<char> sBrandName;
|
||||
|
||||
|
@ -81,6 +84,8 @@ uint32_t sPreferredSampleRate;
|
|||
extern LazyLogModule gAudioStreamLog;
|
||||
|
||||
static const uint32_t CUBEB_NORMAL_LATENCY_MS = 100;
|
||||
// Consevative default that can work on all platforms.
|
||||
static const uint32_t CUBEB_NORMAL_LATENCY_FRAMES = 1024;
|
||||
|
||||
namespace CubebUtils {
|
||||
|
||||
|
@ -95,14 +100,23 @@ void PrefChanged(const char* aPref, void* aClosure)
|
|||
NS_ConvertUTF16toUTF8 utf8(value);
|
||||
sVolumeScale = std::max<double>(0, PR_strtod(utf8.get(), nullptr));
|
||||
}
|
||||
} else if (strcmp(aPref, PREF_CUBEB_LATENCY) == 0) {
|
||||
} else if (strcmp(aPref, PREF_CUBEB_LATENCY_PLAYBACK) == 0) {
|
||||
// Arbitrary default stream latency of 100ms. The higher this
|
||||
// value, the longer stream volume changes will take to become
|
||||
// audible.
|
||||
sCubebLatencyPrefSet = Preferences::HasUserValue(aPref);
|
||||
sCubebPlaybackLatencyPrefSet = Preferences::HasUserValue(aPref);
|
||||
uint32_t value = Preferences::GetUint(aPref, CUBEB_NORMAL_LATENCY_MS);
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
sCubebLatency = std::min<uint32_t>(std::max<uint32_t>(value, 1), 1000);
|
||||
sCubebPlaybackLatencyInMilliseconds = std::min<uint32_t>(std::max<uint32_t>(value, 1), 1000);
|
||||
} else if (strcmp(aPref, PREF_CUBEB_LATENCY_MSG) == 0) {
|
||||
sCubebMSGLatencyPrefSet = Preferences::HasUserValue(aPref);
|
||||
uint32_t value = Preferences::GetUint(aPref, CUBEB_NORMAL_LATENCY_FRAMES);
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
// 128 is the block size for the Web Audio API, which limits how low the
|
||||
// latency can be here.
|
||||
// We don't want to limit the upper limit too much, so that people can
|
||||
// experiment.
|
||||
sCubebMSGLatencyInFrames = std::min<uint32_t>(std::max<uint32_t>(value, 128), 1e6);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,24 +252,42 @@ void ReportCubebStreamInitFailure(bool aIsFirst)
|
|||
: CUBEB_BACKEND_INIT_FAILURE_OTHER);
|
||||
}
|
||||
|
||||
uint32_t GetCubebLatency()
|
||||
uint32_t GetCubebPlaybackLatencyInMilliseconds()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
return sCubebLatency;
|
||||
return sCubebPlaybackLatencyInMilliseconds;
|
||||
}
|
||||
|
||||
bool CubebLatencyPrefSet()
|
||||
bool CubebPlaybackLatencyPrefSet()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
return sCubebLatencyPrefSet;
|
||||
return sCubebPlaybackLatencyPrefSet;
|
||||
}
|
||||
|
||||
bool CubebMSGLatencyPrefSet()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
return sCubebMSGLatencyPrefSet;
|
||||
}
|
||||
|
||||
Maybe<uint32_t> GetCubebMSGLatencyInFrames()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (!sCubebMSGLatencyPrefSet) {
|
||||
return Maybe<uint32_t>();
|
||||
}
|
||||
MOZ_ASSERT(sCubebMSGLatencyInFrames > 0);
|
||||
return Some(sCubebMSGLatencyInFrames);
|
||||
}
|
||||
|
||||
void InitLibrary()
|
||||
{
|
||||
PrefChanged(PREF_VOLUME_SCALE, nullptr);
|
||||
Preferences::RegisterCallback(PrefChanged, PREF_VOLUME_SCALE);
|
||||
PrefChanged(PREF_CUBEB_LATENCY, nullptr);
|
||||
Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LATENCY);
|
||||
PrefChanged(PREF_CUBEB_LATENCY_PLAYBACK, nullptr);
|
||||
PrefChanged(PREF_CUBEB_LATENCY_MSG, nullptr);
|
||||
Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LATENCY_PLAYBACK);
|
||||
Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LATENCY_MSG);
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(&InitBrandName));
|
||||
#endif
|
||||
|
@ -264,7 +296,8 @@ void InitLibrary()
|
|||
void ShutdownLibrary()
|
||||
{
|
||||
Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE);
|
||||
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY);
|
||||
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY_PLAYBACK);
|
||||
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY_MSG);
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (sCubebContext) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "cubeb/cubeb.h"
|
||||
#include "mozilla/dom/AudioChannelBinding.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace CubebUtils {
|
||||
|
@ -36,7 +37,8 @@ cubeb* GetCubebContext();
|
|||
cubeb* GetCubebContextUnlocked();
|
||||
void ReportCubebStreamInitFailure(bool aIsFirstStream);
|
||||
void ReportCubebBackendUsed();
|
||||
uint32_t GetCubebLatency();
|
||||
uint32_t GetCubebPlaybackLatencyInMilliseconds();
|
||||
Maybe<uint32_t> GetCubebMSGLatencyInFrames();
|
||||
bool CubebLatencyPrefSet();
|
||||
#if defined(__ANDROID__) && defined(MOZ_B2G)
|
||||
cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel);
|
||||
|
|
|
@ -628,9 +628,14 @@ AudioCallbackDriver::Init()
|
|||
output.format = CUBEB_SAMPLE_FLOAT32NE;
|
||||
}
|
||||
|
||||
if (cubeb_get_min_latency(cubebContext, output, &latency_frames) != CUBEB_OK) {
|
||||
NS_WARNING("Could not get minimal latency from cubeb.");
|
||||
return;
|
||||
Maybe<uint32_t> latencyPref = CubebUtils::GetCubebMSGLatencyInFrames();
|
||||
if (latencyPref) {
|
||||
latency_frames = latencyPref.value();
|
||||
} else {
|
||||
if (cubeb_get_min_latency(cubebContext, output, &latency_frames) != CUBEB_OK) {
|
||||
NS_WARNING("Could not get minimal latency from cubeb.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
input = output;
|
||||
|
|
|
@ -72,7 +72,6 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
|
|||
, mPreviousDecodedKeyframeTime_us(sNoPreviousDecodedKeyframe)
|
||||
, mLayersBackendType(aLayersBackend)
|
||||
, mInitDone(false)
|
||||
, mIsEncrypted(false)
|
||||
, mTrackDemuxersMayBlock(false)
|
||||
, mDemuxOnly(false)
|
||||
, mSeekScheduled(false)
|
||||
|
@ -337,9 +336,6 @@ MediaFormatReader::OnDemuxerInitDone(nsresult)
|
|||
}
|
||||
|
||||
UniquePtr<EncryptionInfo> crypto = mDemuxer->GetCrypto();
|
||||
|
||||
mIsEncrypted = crypto && crypto->IsEncrypted();
|
||||
|
||||
if (mDecoder && crypto && crypto->IsEncrypted()) {
|
||||
#ifdef MOZ_EME
|
||||
// Try and dispatch 'encrypted'. Won't go if ready state still HAVE_NOTHING.
|
||||
|
@ -375,6 +371,13 @@ MediaFormatReader::OnDemuxerInitDone(nsresult)
|
|||
mMetadataPromise.Resolve(metadata, __func__);
|
||||
}
|
||||
|
||||
bool
|
||||
MediaFormatReader::IsEncrypted() const
|
||||
{
|
||||
return (HasAudio() && mInfo.mAudio.mCrypto.mValid) ||
|
||||
(HasVideo() && mInfo.mVideo.mCrypto.mValid);
|
||||
}
|
||||
|
||||
void
|
||||
MediaFormatReader::OnDemuxerInitFailed(const MediaResult& aError)
|
||||
{
|
||||
|
|
|
@ -105,8 +105,8 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
bool HasVideo() { return mVideo.mTrackDemuxer; }
|
||||
bool HasAudio() { return mAudio.mTrackDemuxer; }
|
||||
bool HasVideo() const { return mVideo.mTrackDemuxer; }
|
||||
bool HasAudio() const { return mAudio.mTrackDemuxer; }
|
||||
|
||||
bool IsWaitingOnCDMResource();
|
||||
|
||||
|
@ -528,11 +528,7 @@ private:
|
|||
// True if we've read the streams' metadata.
|
||||
bool mInitDone;
|
||||
MozPromiseHolder<MetadataPromise> mMetadataPromise;
|
||||
bool IsEncrypted()
|
||||
{
|
||||
return mIsEncrypted;
|
||||
}
|
||||
bool mIsEncrypted;
|
||||
bool IsEncrypted() const;
|
||||
|
||||
// Set to true if any of our track buffers may be blocking.
|
||||
bool mTrackDemuxersMayBlock;
|
||||
|
|
|
@ -154,4 +154,17 @@ IsClearkeyKeySystem(const nsAString& aKeySystem)
|
|||
return !CompareUTF8toUTF16(kEMEKeySystemClearkey, aKeySystem);
|
||||
}
|
||||
|
||||
CDMType
|
||||
ToCDMTypeTelemetryEnum(const nsString& aKeySystem)
|
||||
{
|
||||
if (!CompareUTF8toUTF16(kEMEKeySystemWidevine, aKeySystem)) {
|
||||
return CDMType::eWidevine;
|
||||
} else if (!CompareUTF8toUTF16(kEMEKeySystemClearkey, aKeySystem)) {
|
||||
return CDMType::eClearKey;
|
||||
} else if (!CompareUTF8toUTF16(kEMEKeySystemPrimetime, aKeySystem)) {
|
||||
return CDMType::ePrimetime;
|
||||
}
|
||||
return CDMType::eUnknown;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -106,6 +106,16 @@ KeySystemToGMPName(const nsAString& aKeySystem);
|
|||
bool
|
||||
IsClearkeyKeySystem(const nsAString& aKeySystem);
|
||||
|
||||
enum CDMType {
|
||||
eClearKey = 0,
|
||||
ePrimetime = 1,
|
||||
eWidevine = 2,
|
||||
eUnknown = 3
|
||||
};
|
||||
|
||||
CDMType
|
||||
ToCDMTypeTelemetryEnum(const nsString& aKeySystem);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // EME_LOG_H_
|
||||
|
|
|
@ -199,6 +199,9 @@ MediaKeySession::GenerateRequest(const nsAString& aInitDataType,
|
|||
return promise.forget();
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(Telemetry::VIDEO_CDM_GENERATE_REQUEST_CALLED,
|
||||
ToCDMTypeTelemetryEnum(mKeySystem));
|
||||
|
||||
// Convert initData to base64 for easier logging.
|
||||
// Note: CreateSession() Move()s the data out of the array, so we have
|
||||
// to copy it here.
|
||||
|
|
|
@ -401,26 +401,6 @@ MediaKeys::Init(ErrorResult& aRv)
|
|||
return promise.forget();
|
||||
}
|
||||
|
||||
enum CDMCreatedType {
|
||||
eClearKey = 0,
|
||||
ePrimetime = 1,
|
||||
eWidevine = 2,
|
||||
eUnknown = 3
|
||||
};
|
||||
|
||||
static CDMCreatedType
|
||||
ToCDMCreatedTelemetryEnum(const nsString& aKeySystem)
|
||||
{
|
||||
if (!CompareUTF8toUTF16(kEMEKeySystemWidevine, aKeySystem)) {
|
||||
return CDMCreatedType::eWidevine;
|
||||
} else if (!CompareUTF8toUTF16(kEMEKeySystemClearkey, aKeySystem)) {
|
||||
return CDMCreatedType::eClearKey;
|
||||
} else if (!CompareUTF8toUTF16(kEMEKeySystemPrimetime, aKeySystem)) {
|
||||
return CDMCreatedType::ePrimetime;
|
||||
}
|
||||
return CDMCreatedType::eUnknown;
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const uint32_t aPluginId)
|
||||
{
|
||||
|
@ -440,7 +420,7 @@ MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const uint32_t
|
|||
mKeySystem,
|
||||
MediaKeySystemStatus::Cdm_created);
|
||||
|
||||
Telemetry::Accumulate(Telemetry::VIDEO_CDM_CREATED, ToCDMCreatedTelemetryEnum(mKeySystem));
|
||||
Telemetry::Accumulate(Telemetry::VIDEO_CDM_CREATED, ToCDMTypeTelemetryEnum(mKeySystem));
|
||||
}
|
||||
|
||||
already_AddRefed<MediaKeySession>
|
||||
|
|
|
@ -1075,7 +1075,6 @@ TrackBuffersManager::OnDemuxerInitDone(nsresult)
|
|||
// We clear our crypto init data array, so the MediaFormatReader will
|
||||
// not emit an encrypted event for the same init data again.
|
||||
info.mCrypto.mInitDatas.Clear();
|
||||
mEncrypted = true;
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -240,7 +240,6 @@ private:
|
|||
void OnDemuxerInitFailed(const MediaResult& aFailure);
|
||||
void OnDemuxerResetDone(nsresult);
|
||||
MozPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest;
|
||||
bool mEncrypted;
|
||||
|
||||
void OnDemuxFailed(TrackType aTrack, const MediaResult& aError);
|
||||
void DoDemuxVideo();
|
||||
|
|
|
@ -29,33 +29,6 @@ using namespace mozilla::gl;
|
|||
using namespace mozilla::java::sdk;
|
||||
using media::TimeUnit;
|
||||
|
||||
namespace {
|
||||
template<class T>
|
||||
mozilla::jni::ByteArray::LocalRef
|
||||
CreateAndInitJByteArray(const T& data, jsize length)
|
||||
{
|
||||
JNIEnv* const jenv = mozilla::jni::GetEnvForThread();
|
||||
jbyteArray result = jenv->NewByteArray(length);
|
||||
MOZ_CATCH_JNI_EXCEPTION(jenv);
|
||||
jenv->SetByteArrayRegion(result, 0, length, reinterpret_cast<const jbyte*>(const_cast<T>(data)));
|
||||
MOZ_CATCH_JNI_EXCEPTION(jenv);
|
||||
return mozilla::jni::ByteArray::LocalRef::Adopt(jenv, result);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
mozilla::jni::IntArray::LocalRef
|
||||
CreateAndInitJIntArray(const T& data, jsize length)
|
||||
{
|
||||
JNIEnv* const jenv = mozilla::jni::GetEnvForThread();
|
||||
jintArray result = jenv->NewIntArray(length);
|
||||
MOZ_CATCH_JNI_EXCEPTION(jenv);
|
||||
jenv->SetIntArrayRegion(result, 0, length, reinterpret_cast<const jint*>(const_cast<T>(data)));
|
||||
MOZ_CATCH_JNI_EXCEPTION(jenv);
|
||||
return mozilla::jni::IntArray::LocalRef::Adopt(jenv, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
mozilla::LazyLogModule sAndroidDecoderModuleLog("AndroidDecoderModule");
|
||||
|
@ -125,11 +98,17 @@ GetCryptoInfoFromSample(const MediaRawData* aSample)
|
|||
tempIV.AppendElement(0);
|
||||
}
|
||||
|
||||
auto numBytesOfPlainData = CreateAndInitJIntArray(&plainSizes[0], plainSizes.Length());
|
||||
auto numBytesOfEncryptedData = CreateAndInitJIntArray(&cryptoObj.mEncryptedSizes[0],
|
||||
cryptoObj.mEncryptedSizes.Length());
|
||||
auto iv = CreateAndInitJByteArray(&tempIV[0], tempIV.Length());
|
||||
auto keyId = CreateAndInitJByteArray(&cryptoObj.mKeyId[0], cryptoObj.mKeyId.Length());
|
||||
auto numBytesOfPlainData = mozilla::jni::IntArray::New(
|
||||
reinterpret_cast<int32_t*>(&plainSizes[0]),
|
||||
plainSizes.Length());
|
||||
|
||||
auto numBytesOfEncryptedData =
|
||||
mozilla::jni::IntArray::New(reinterpret_cast<const int32_t*>(&cryptoObj.mEncryptedSizes[0]),
|
||||
cryptoObj.mEncryptedSizes.Length());
|
||||
auto iv = mozilla::jni::ByteArray::New(reinterpret_cast<int8_t*>(&tempIV[0]),
|
||||
tempIV.Length());
|
||||
auto keyId = mozilla::jni::ByteArray::New(reinterpret_cast<const int8_t*>(&cryptoObj.mKeyId[0]),
|
||||
cryptoObj.mKeyId.Length());
|
||||
cryptoInfo->Set(numSubSamples,
|
||||
numBytesOfPlainData,
|
||||
numBytesOfEncryptedData,
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
, mGrallocFormat(aGrallocFormat)
|
||||
{}
|
||||
|
||||
already_AddRefed<TextureClient> Allocate(TextureForwarder* aAllocator) override
|
||||
already_AddRefed<TextureClient> Allocate(KnowsCompositor* aAllocator) override
|
||||
{
|
||||
uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN |
|
||||
android::GraphicBuffer::USAGE_SW_WRITE_OFTEN |
|
||||
|
@ -60,7 +60,7 @@ public:
|
|||
|
||||
GrallocTextureData* texData = GrallocTextureData::Create(mSize, mGrallocFormat,
|
||||
gfx::BackendType::NONE,
|
||||
usage, aAllocator);
|
||||
usage, aAllocator->GetTextureForwarder());
|
||||
if (!texData) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
RefPtr<TextureClient> textureClient =
|
||||
TextureClient::CreateWithData(texData, TextureFlags::DEALLOCATE_CLIENT, aAllocator);
|
||||
TextureClient::CreateWithData(texData, TextureFlags::DEALLOCATE_CLIENT, aAllocator->GetTextureForwarder());
|
||||
return textureClient.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -930,3 +930,4 @@ tags = suspend
|
|||
tags = suspend
|
||||
[test_background_video_no_suspend_disabled.html]
|
||||
tags = suspend
|
||||
[test_temporary_file_blob_video_plays.html]
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test MediaRecorder Recording canvas stream</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/dom/canvas/test/captureStream_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<div id="content">
|
||||
</div>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function startTest() {
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = canvas.height = 100;
|
||||
document.getElementById("content").appendChild(canvas);
|
||||
|
||||
var helper = new CaptureStreamTestHelper2D(100, 100);
|
||||
helper.drawColor(canvas, helper.red);
|
||||
|
||||
var stream = canvas.captureStream(0);
|
||||
|
||||
var blob;
|
||||
|
||||
mediaRecorder = new MediaRecorder(stream);
|
||||
is(mediaRecorder.stream, stream,
|
||||
"Media recorder stream = canvas stream at the start of recording");
|
||||
|
||||
mediaRecorder.onwarning = () => ok(false, "warning unexpectedly fired");
|
||||
|
||||
mediaRecorder.onerror = () => ok(false, "Recording failed");
|
||||
|
||||
mediaRecorder.ondataavailable = ev => {
|
||||
is(blob, undefined, "Should only get one dataavailable event");
|
||||
blob = ev.data;
|
||||
};
|
||||
|
||||
mediaRecorder.onstart = () => {
|
||||
info("Got 'start' event");
|
||||
// We just want one frame encoded, to see that the recorder produces something readable.
|
||||
mediaRecorder.stop();
|
||||
};
|
||||
|
||||
mediaRecorder.onstop = () => {
|
||||
info("Got 'stop' event");
|
||||
ok(blob, "Should have gotten a data blob");
|
||||
|
||||
var video = document.createElement("video");
|
||||
video.id = "recorded-video";
|
||||
video.src = URL.createObjectURL(blob);
|
||||
video.play();
|
||||
video.onerror = err => {
|
||||
ok(false, "Should be able to play the recording. Got error. code=" + video.error.code);
|
||||
SimpleTest.finish();
|
||||
};
|
||||
document.getElementById("content").appendChild(video);
|
||||
helper.waitForPixelColor(video, helper.red, 128, "Should become red")
|
||||
.then(SimpleTest.finish);
|
||||
};
|
||||
|
||||
mediaRecorder.start();
|
||||
is(mediaRecorder.state, "recording", "Media recorder should be recording");
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({set:[["media.recorder.max_memory", 1]]}, startTest);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -253,9 +253,7 @@ inline nsCString
|
|||
NullableString(const char* aString)
|
||||
{
|
||||
if (!aString) {
|
||||
nsCString str;
|
||||
str.SetIsVoid(true);
|
||||
return str;
|
||||
return NullCString();
|
||||
}
|
||||
return nsCString(aString);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ EXPORTS.mozilla.dom += [
|
|||
|
||||
EXPORTS += [
|
||||
'nsContentSecurityManager.h',
|
||||
'nsMixedContentBlocker.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsCORSListenerProxy.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsMixedContentBlocker.h"
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
|
@ -381,6 +383,14 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
|
|||
if (NS_CP_REJECTED(shouldLoad)) {
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
|
||||
if (nsMixedContentBlocker::sSendHSTSPriming) {
|
||||
rv = nsMixedContentBlocker::MarkLoadInfoForPriming(uri,
|
||||
requestingContext,
|
||||
aLoadInfo);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -489,7 +499,7 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
|||
rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckLoadURIWithPrincipal(oldPrincipal, newOriginalURI, flags);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aCb->OnRedirectVerifyCallback(NS_OK);
|
||||
return NS_OK;
|
||||
|
|
|
@ -54,6 +54,11 @@ bool nsMixedContentBlocker::sBlockMixedScript = false;
|
|||
// Is mixed display content blocking (images, audio, video, <a ping>) enabled?
|
||||
bool nsMixedContentBlocker::sBlockMixedDisplay = false;
|
||||
|
||||
// Do we move HSTS before mixed-content
|
||||
bool nsMixedContentBlocker::sUseHSTS = false;
|
||||
// Do we send an HSTS priming request
|
||||
bool nsMixedContentBlocker::sSendHSTSPriming = false;
|
||||
|
||||
// Fired at the document that attempted to load mixed content. The UI could
|
||||
// handle this event, for example, by displaying an info bar that offers the
|
||||
// choice to reload the page with mixed content permitted.
|
||||
|
@ -195,6 +200,14 @@ nsMixedContentBlocker::nsMixedContentBlocker()
|
|||
// Cache the pref for mixed display blocking
|
||||
Preferences::AddBoolVarCache(&sBlockMixedDisplay,
|
||||
"security.mixed_content.block_display_content");
|
||||
|
||||
// Cache the pref for HSTS
|
||||
Preferences::AddBoolVarCache(&sUseHSTS,
|
||||
"security.mixed_content.use_hsts");
|
||||
|
||||
// Cache the pref for sending HSTS priming
|
||||
Preferences::AddBoolVarCache(&sSendHSTSPriming,
|
||||
"security.mixed_content.send_hsts_priming");
|
||||
}
|
||||
|
||||
nsMixedContentBlocker::~nsMixedContentBlocker()
|
||||
|
@ -238,8 +251,6 @@ LogMixedContentMessage(MixedContentTypes aClassification,
|
|||
messageLookupKey.get(), strings, ArrayLength(strings));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* nsIChannelEventSink implementation
|
||||
* This code is called when a request is redirected.
|
||||
* We check the channel associated with the new uri is allowed to load
|
||||
|
@ -309,17 +320,35 @@ nsMixedContentBlocker::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> requestingContext = loadInfo->LoadingNode();
|
||||
|
||||
int16_t decision = REJECT_REQUEST;
|
||||
rv = ShouldLoad(contentPolicyType,
|
||||
newUri,
|
||||
requestingLocation,
|
||||
loadInfo->LoadingNode(),
|
||||
requestingContext,
|
||||
EmptyCString(), // aMimeGuess
|
||||
nullptr, // aExtra
|
||||
requestingPrincipal,
|
||||
&decision);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (nsMixedContentBlocker::sSendHSTSPriming) {
|
||||
// The LoadInfo passed in is for the original channel, HSTS priming needs to
|
||||
// be set on the new channel, if required. If the redirect changes
|
||||
// http->https, or vice-versa, the need for priming may change.
|
||||
nsCOMPtr<nsILoadInfo> newLoadInfo;
|
||||
rv = aNewChannel->GetLoadInfo(getter_AddRefs(newLoadInfo));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = nsMixedContentBlocker::MarkLoadInfoForPriming(newUri,
|
||||
requestingContext,
|
||||
newLoadInfo);
|
||||
if (NS_FAILED(rv)) {
|
||||
decision = REJECT_REQUEST;
|
||||
newLoadInfo->ClearHSTSPriming();
|
||||
}
|
||||
}
|
||||
|
||||
// If the channel is about to load mixed content, abort the channel
|
||||
if (!NS_CP_ACCEPTED(decision)) {
|
||||
autoCallback.DontCallback();
|
||||
|
@ -463,7 +492,6 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
|||
*aDecision = ACCEPT;
|
||||
return NS_OK;
|
||||
|
||||
|
||||
// Static display content is considered moderate risk for mixed content so
|
||||
// these will be blocked according to the mixed display preference
|
||||
case TYPE_IMAGE:
|
||||
|
@ -497,7 +525,6 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
|||
// This content policy works as a whitelist.
|
||||
default:
|
||||
MOZ_ASSERT(false, "Mixed content of unknown type");
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure to get the URI the load started with. No need to check
|
||||
|
@ -677,7 +704,9 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
|||
bool isHttpScheme = false;
|
||||
rv = innerContentLocation->SchemeIs("http", &isHttpScheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isHttpScheme && docShell->GetDocument()->GetUpgradeInsecureRequests(isPreload)) {
|
||||
nsIDocument* document = docShell->GetDocument();
|
||||
MOZ_ASSERT(document, "Expected a document");
|
||||
if (isHttpScheme && document->GetUpgradeInsecureRequests(isPreload)) {
|
||||
*aDecision = ACCEPT;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -688,7 +717,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
|||
// Block all non secure loads in case the CSP directive is present. Please note
|
||||
// that at this point we already know, based on |schemeSecure| that the load is
|
||||
// not secure, so we can bail out early at this point.
|
||||
if (docShell->GetDocument()->GetBlockAllMixedContent(isPreload)) {
|
||||
if (document->GetBlockAllMixedContent(isPreload)) {
|
||||
// log a message to the console before returning.
|
||||
nsAutoCString spec;
|
||||
rv = aContentLocation->GetSpec(spec);
|
||||
|
@ -703,7 +732,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
|||
0, // aLineNumber
|
||||
0, // aColumnNumber
|
||||
nsIScriptError::errorFlag, "CSP",
|
||||
docShell->GetDocument()->InnerWindowID());
|
||||
document->InnerWindowID());
|
||||
*aDecision = REJECT_REQUEST;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -796,6 +825,34 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
|||
}
|
||||
nsresult stateRV = securityUI->GetState(&state);
|
||||
|
||||
bool doHSTSPriming = false;
|
||||
if (isHttpScheme) {
|
||||
bool hsts = false;
|
||||
bool cached = false;
|
||||
nsCOMPtr<nsISiteSecurityService> sss =
|
||||
do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aContentLocation,
|
||||
0, &cached, &hsts);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (hsts && sUseHSTS) {
|
||||
// assume we will be upgraded later
|
||||
*aDecision = ACCEPT;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Send a priming request if the result is not already cached and priming
|
||||
// requests are allowed
|
||||
if (!cached && sSendHSTSPriming) {
|
||||
// add this URI as a priming location
|
||||
doHSTSPriming = true;
|
||||
document->AddHSTSPrimingLocation(innerContentLocation,
|
||||
HSTSPrimingState::eHSTS_PRIMING_ALLOW);
|
||||
*aDecision = ACCEPT;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point we know that the request is mixed content, and the only
|
||||
// question is whether we block it. Record telemetry at this point as to
|
||||
// whether HSTS would have fixed things by making the content location
|
||||
|
@ -811,14 +868,14 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
|||
bool active = (classification == eMixedScript);
|
||||
if (!aHadInsecureImageRedirect) {
|
||||
if (XRE_IsParentProcess()) {
|
||||
AccumulateMixedContentHSTS(innerContentLocation, active);
|
||||
AccumulateMixedContentHSTS(innerContentLocation, active, doHSTSPriming);
|
||||
} else {
|
||||
// Ask the parent process to do the same call
|
||||
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
|
||||
if (cc) {
|
||||
mozilla::ipc::URIParams uri;
|
||||
SerializeURI(innerContentLocation, uri);
|
||||
cc->SendAccumulateMixedContentHSTS(uri, active);
|
||||
cc->SendAccumulateMixedContentHSTS(uri, active, doHSTSPriming);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -861,7 +918,13 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
*aDecision = nsIContentPolicy::REJECT_REQUEST;
|
||||
if (doHSTSPriming) {
|
||||
document->AddHSTSPrimingLocation(innerContentLocation,
|
||||
HSTSPrimingState::eHSTS_PRIMING_BLOCK);
|
||||
*aDecision = nsIContentPolicy::ACCEPT;
|
||||
} else {
|
||||
*aDecision = nsIContentPolicy::REJECT_REQUEST;
|
||||
}
|
||||
LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked);
|
||||
if (!rootDoc->GetHasMixedDisplayContentBlocked() && NS_SUCCEEDED(stateRV)) {
|
||||
rootDoc->SetHasMixedDisplayContentBlocked(true);
|
||||
|
@ -907,7 +970,13 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
|||
}
|
||||
} else {
|
||||
//User has not overriden the pref by Disabling protection. Reject the request and update the security state.
|
||||
*aDecision = nsIContentPolicy::REJECT_REQUEST;
|
||||
if (doHSTSPriming) {
|
||||
document->AddHSTSPrimingLocation(innerContentLocation,
|
||||
HSTSPrimingState::eHSTS_PRIMING_BLOCK);
|
||||
*aDecision = nsIContentPolicy::ACCEPT;
|
||||
} else {
|
||||
*aDecision = nsIContentPolicy::REJECT_REQUEST;
|
||||
}
|
||||
LogMixedContentMessage(classification, aContentLocation, rootDoc, eBlocked);
|
||||
// See if the pref will change here. If it will, only then do we need to call OnSecurityChange() to update the UI.
|
||||
if (rootDoc->GetHasMixedActiveContentBlocked()) {
|
||||
|
@ -922,7 +991,6 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
|
|||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} else {
|
||||
// The content is not blocked by the mixed content prefs.
|
||||
|
||||
|
@ -973,10 +1041,24 @@ enum MixedContentHSTSState {
|
|||
MCB_HSTS_ACTIVE_WITH_HSTS = 3
|
||||
};
|
||||
|
||||
// Similar to the existing mixed-content HSTS, except MCB_HSTS_*_NO_HSTS is
|
||||
// broken into two distinct states, indicating whether we plan to send a priming
|
||||
// request or not. If we decided not go send a priming request, it could be
|
||||
// because it is a type we do not support, or because we cached a previous
|
||||
// negative response.
|
||||
enum MixedContentHSTSPrimingState {
|
||||
eMCB_HSTS_PASSIVE_WITH_HSTS = 0,
|
||||
eMCB_HSTS_ACTIVE_WITH_HSTS = 1,
|
||||
eMCB_HSTS_PASSIVE_NO_PRIMING = 2,
|
||||
eMCB_HSTS_PASSIVE_DO_PRIMING = 3,
|
||||
eMCB_HSTS_ACTIVE_NO_PRIMING = 4,
|
||||
eMCB_HSTS_ACTIVE_DO_PRIMING = 5
|
||||
};
|
||||
|
||||
// Record information on when HSTS would have made mixed content not mixed
|
||||
// content (regardless of whether it was actually blocked)
|
||||
void
|
||||
nsMixedContentBlocker::AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive)
|
||||
nsMixedContentBlocker::AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive, bool aHasHSTSPriming)
|
||||
{
|
||||
// This method must only be called in the parent, because
|
||||
// nsSiteSecurityService is only available in the parent
|
||||
|
@ -991,28 +1073,113 @@ nsMixedContentBlocker::AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive)
|
|||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, 0, &hsts);
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, 0, nullptr, &hsts);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// states: would upgrade, would prime, hsts info cached
|
||||
// active, passive
|
||||
//
|
||||
if (!aActive) {
|
||||
if (!hsts) {
|
||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
|
||||
MCB_HSTS_PASSIVE_NO_HSTS);
|
||||
if (aHasHSTSPriming) {
|
||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
|
||||
eMCB_HSTS_PASSIVE_DO_PRIMING);
|
||||
} else {
|
||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
|
||||
eMCB_HSTS_PASSIVE_NO_PRIMING);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
|
||||
MCB_HSTS_PASSIVE_WITH_HSTS);
|
||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
|
||||
eMCB_HSTS_PASSIVE_WITH_HSTS);
|
||||
}
|
||||
} else {
|
||||
if (!hsts) {
|
||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
|
||||
MCB_HSTS_ACTIVE_NO_HSTS);
|
||||
if (aHasHSTSPriming) {
|
||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
|
||||
eMCB_HSTS_ACTIVE_DO_PRIMING);
|
||||
} else {
|
||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
|
||||
eMCB_HSTS_ACTIVE_NO_PRIMING);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS,
|
||||
MCB_HSTS_ACTIVE_WITH_HSTS);
|
||||
Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING,
|
||||
eMCB_HSTS_ACTIVE_WITH_HSTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
nsresult
|
||||
nsMixedContentBlocker::MarkLoadInfoForPriming(nsIURI* aURI,
|
||||
nsISupports* aRequestingContext,
|
||||
nsILoadInfo* aLoadInfo)
|
||||
{
|
||||
nsresult rv;
|
||||
bool sendPriming = false;
|
||||
bool mixedContentWouldBlock = false;
|
||||
rv = GetHSTSPrimingFromRequestingContext(aURI,
|
||||
aRequestingContext,
|
||||
&sendPriming,
|
||||
&mixedContentWouldBlock);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (sendPriming) {
|
||||
aLoadInfo->SetHSTSPriming(mixedContentWouldBlock);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//static
|
||||
nsresult
|
||||
nsMixedContentBlocker::GetHSTSPrimingFromRequestingContext(nsIURI* aURI,
|
||||
nsISupports* aRequestingContext,
|
||||
bool* aSendPrimingRequest,
|
||||
bool* aMixedContentWouldBlock)
|
||||
{
|
||||
*aSendPrimingRequest = false;
|
||||
*aMixedContentWouldBlock = false;
|
||||
// If we marked for priming, we used the innermost URI, so get that
|
||||
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
|
||||
if (!innerURI) {
|
||||
NS_ERROR("Can't get innerURI from aContentLocation");
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
|
||||
bool isHttp = false;
|
||||
innerURI->SchemeIs("http", &isHttp);
|
||||
if (!isHttp) {
|
||||
// there is nothign to do
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If the DocShell was marked for HSTS priming, propagate that to the LoadInfo
|
||||
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
|
||||
if (!docShell) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIDocument> document = docShell->GetDocument();
|
||||
if (!document) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
HSTSPrimingState status = document->GetHSTSPrimingStateForLocation(innerURI);
|
||||
if (status != HSTSPrimingState::eNO_HSTS_PRIMING) {
|
||||
*aSendPrimingRequest = (status != HSTSPrimingState::eNO_HSTS_PRIMING);
|
||||
*aMixedContentWouldBlock = (status == HSTSPrimingState::eHSTS_PRIMING_BLOCK);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ enum MixedContentTypes {
|
|||
#include "nsIChannelEventSink.h"
|
||||
#include "imgRequest.h"
|
||||
|
||||
class nsILoadInfo; // forward declaration
|
||||
|
||||
class nsMixedContentBlocker : public nsIContentPolicy,
|
||||
public nsIChannelEventSink
|
||||
{
|
||||
|
@ -59,9 +61,41 @@ public:
|
|||
nsISupports* aExtra,
|
||||
nsIPrincipal* aRequestPrincipal,
|
||||
int16_t* aDecision);
|
||||
static void AccumulateMixedContentHSTS(nsIURI* aURI, bool aActive);
|
||||
static void AccumulateMixedContentHSTS(nsIURI* aURI,
|
||||
bool aActive,
|
||||
bool aHasHSTSPriming);
|
||||
/* If the document associated with aRequestingContext requires priming for
|
||||
* aURI, propagate that to the LoadInfo so the HttpChannel will find out about
|
||||
* it.
|
||||
*
|
||||
* @param aURI The URI associated with the load
|
||||
* @param aRequestingContext the requesting context passed to ShouldLoad
|
||||
* @param aLoadInfo the LoadInfo for the load
|
||||
*/
|
||||
static nsresult MarkLoadInfoForPriming(nsIURI* aURI,
|
||||
nsISupports* aRequestingContext,
|
||||
nsILoadInfo* aLoadInfo);
|
||||
|
||||
/* Given a context, return whether HSTS was marked on the document associated
|
||||
* with the load for the given URI. This is used by MarkLoadInfoForPriming and
|
||||
* directly by the image loader to determine whether to allow a load to occur
|
||||
* from the cache.
|
||||
*
|
||||
* @param aURI The URI associated with the load
|
||||
* @param aRequestingContext the requesting context passed to ShouldLoad
|
||||
* @param aSendPrimingRequest out true if priming is required on the channel
|
||||
* @param aMixedContentWouldBlock out true if mixed content would block
|
||||
*/
|
||||
static nsresult GetHSTSPrimingFromRequestingContext(nsIURI* aURI,
|
||||
nsISupports* aRequestingContext,
|
||||
bool* aSendPrimingRequest,
|
||||
bool* aMixedContentWouldBlock);
|
||||
|
||||
|
||||
static bool sBlockMixedScript;
|
||||
static bool sBlockMixedDisplay;
|
||||
static bool sUseHSTS;
|
||||
static bool sSendHSTSPriming;
|
||||
};
|
||||
|
||||
#endif /* nsMixedContentBlocker_h___ */
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
file_priming-top.html
|
||||
file_testserver.sjs
|
||||
file_1x1.png
|
||||
file_priming.js
|
||||
file_stylesheet.css
|
||||
|
||||
[browser_hsts-priming_main.js]
|
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
* Description of the test:
|
||||
* Check that HSTS priming occurs correctly with mixed content
|
||||
*
|
||||
* This test uses three hostnames, each of which treats an HSTS priming
|
||||
* request differently.
|
||||
* * no-ssl never returns an ssl response
|
||||
* * reject-upgrade returns an ssl response, but with no STS header
|
||||
* * prime-hsts returns an ssl response with the appropriate STS header
|
||||
*
|
||||
* For each server, test that it response appropriately when the we allow
|
||||
* or block active or display content, as well as when we send an hsts priming
|
||||
* request, but do not change the order of mixed-content and HSTS.
|
||||
*
|
||||
* This test uses http-on-examine-response, so must be run in browser context.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var TOP_URI = "https://example.com/browser/dom/security/test/hsts/file_priming-top.html";
|
||||
|
||||
var test_servers = {
|
||||
// a test server that does not support TLS
|
||||
'no-ssl': {
|
||||
host: 'example.co.jp',
|
||||
response: false,
|
||||
id: 'no-ssl',
|
||||
},
|
||||
// a test server which does not support STS upgrade
|
||||
'reject-upgrade': {
|
||||
host: 'example.org',
|
||||
response: true,
|
||||
id: 'reject-upgrade',
|
||||
},
|
||||
// a test server when sends an STS header when priming
|
||||
'prime-hsts': {
|
||||
host: 'test1.example.com',
|
||||
response: true,
|
||||
id: 'prime-hsts'
|
||||
},
|
||||
};
|
||||
// The number of priming responses we expect to see
|
||||
var priming_count = 2;
|
||||
|
||||
var test_settings = {
|
||||
// mixed active content is allowed, priming will upgrade
|
||||
allow_active: {
|
||||
block_active: false,
|
||||
block_display: false,
|
||||
use_hsts: true,
|
||||
send_hsts_priming: true,
|
||||
type: 'script',
|
||||
result: {
|
||||
'no-ssl': 'insecure',
|
||||
'reject-upgrade': 'insecure',
|
||||
'prime-hsts': 'secure',
|
||||
},
|
||||
},
|
||||
// mixed active content is blocked, priming will upgrade
|
||||
block_active: {
|
||||
block_active: true,
|
||||
block_display: false,
|
||||
use_hsts: true,
|
||||
send_hsts_priming: true,
|
||||
type: 'script',
|
||||
result: {
|
||||
'no-ssl': 'blocked',
|
||||
'reject-upgrade': 'blocked',
|
||||
'prime-hsts': 'secure',
|
||||
},
|
||||
},
|
||||
// keep the original order of mixed-content and HSTS, but send
|
||||
// priming requests
|
||||
hsts_after_mixed: {
|
||||
block_active: true,
|
||||
block_display: false,
|
||||
use_hsts: false,
|
||||
send_hsts_priming: true,
|
||||
type: 'script',
|
||||
result: {
|
||||
'no-ssl': 'blocked',
|
||||
'reject-upgrade': 'blocked',
|
||||
'prime-hsts': 'blocked',
|
||||
},
|
||||
},
|
||||
// mixed display content is allowed, priming will upgrade
|
||||
allow_display: {
|
||||
block_active: true,
|
||||
block_display: false,
|
||||
use_hsts: true,
|
||||
send_hsts_priming: true,
|
||||
type: 'img',
|
||||
result: {
|
||||
'no-ssl': 'insecure',
|
||||
'reject-upgrade': 'insecure',
|
||||
'prime-hsts': 'secure',
|
||||
},
|
||||
},
|
||||
// mixed display content is blocked, priming will upgrade
|
||||
block_display: {
|
||||
block_active: true,
|
||||
block_display: true,
|
||||
use_hsts: true,
|
||||
send_hsts_priming: true,
|
||||
type: 'img',
|
||||
result: {
|
||||
'no-ssl': 'blocked',
|
||||
'reject-upgrade': 'blocked',
|
||||
'prime-hsts': 'secure',
|
||||
},
|
||||
},
|
||||
// mixed active content is blocked, priming will upgrade (css)
|
||||
block_active_css: {
|
||||
block_active: true,
|
||||
block_display: false,
|
||||
use_hsts: true,
|
||||
send_hsts_priming: true,
|
||||
type: 'css',
|
||||
result: {
|
||||
'no-ssl': 'blocked',
|
||||
'reject-upgrade': 'blocked',
|
||||
'prime-hsts': 'secure',
|
||||
},
|
||||
},
|
||||
// mixed active content is blocked, priming will upgrade
|
||||
// redirect to the same host
|
||||
block_active_with_redir_same: {
|
||||
block_active: true,
|
||||
block_display: false,
|
||||
use_hsts: true,
|
||||
send_hsts_priming: true,
|
||||
type: 'script',
|
||||
redir: 'same',
|
||||
result: {
|
||||
'no-ssl': 'blocked',
|
||||
'reject-upgrade': 'blocked',
|
||||
'prime-hsts': 'secure',
|
||||
},
|
||||
},
|
||||
}
|
||||
// track which test we are on
|
||||
var which_test = "";
|
||||
|
||||
const Observer = {
|
||||
observe: function (subject, topic, data) {
|
||||
switch (topic) {
|
||||
case 'console-api-log-event':
|
||||
return Observer.console_api_log_event(subject, topic, data);
|
||||
case 'http-on-examine-response':
|
||||
return Observer.http_on_examine_response(subject, topic, data);
|
||||
}
|
||||
throw "Can't handle topic "+topic;
|
||||
},
|
||||
// When a load is blocked which results in an error event within a page, the
|
||||
// test logs to the console.
|
||||
console_api_log_event: function (subject, topic, data) {
|
||||
var message = subject.wrappedJSObject.arguments[0];
|
||||
// when we are blocked, this will match the message we sent to the console,
|
||||
// ignore everything else.
|
||||
var re = RegExp(/^HSTS_PRIMING: Blocked ([-\w]+).*$/);
|
||||
if (!re.test(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let id = message.replace(re, '$1');
|
||||
let curTest =test_servers[id];
|
||||
|
||||
if (!curTest) {
|
||||
ok(false, "HSTS priming got a console message blocked, "+
|
||||
"but doesn't match expectations "+id+" (msg="+message);
|
||||
return;
|
||||
}
|
||||
|
||||
is("blocked", test_settings[which_test].result[curTest.id], "HSTS priming "+
|
||||
which_test+":"+curTest.id+" expected "+
|
||||
test_settings[which_test].result[curTest.id]+", got blocked");
|
||||
test_settings[which_test].finished[curTest.id] = "blocked";
|
||||
},
|
||||
// When we see a response come back, peek at the response and test it is secure
|
||||
// or insecure as needed. Addtionally, watch the response for priming requests.
|
||||
http_on_examine_response: function (subject, topic, data) {
|
||||
let curTest = null;
|
||||
let channel = subject.QueryInterface(Ci.nsIHttpChannel);
|
||||
for (let item in test_servers) {
|
||||
let re = RegExp('https?://'+test_servers[item].host);
|
||||
if (re.test(channel.URI.asciiSpec)) {
|
||||
curTest = test_servers[item];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!curTest) {
|
||||
return;
|
||||
}
|
||||
|
||||
let result = (channel.URI.asciiSpec.startsWith('https:')) ? "secure" : "insecure";
|
||||
|
||||
// This is a priming request, go ahead and validate we were supposed to see
|
||||
// a response from the server
|
||||
if (channel.requestMethod == 'HEAD') {
|
||||
is(true, curTest.response, "HSTS priming response found " + curTest.id);
|
||||
test_settings[which_test].priming[curTest.id] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// This is the response to our query, make sure it matches
|
||||
is(result, test_settings[which_test].result[curTest.id],
|
||||
"HSTS priming result " + which_test + ":" + curTest.id);
|
||||
test_settings[which_test].finished[curTest.id] = result;
|
||||
},
|
||||
};
|
||||
|
||||
// opens `uri' in a new tab and focuses it.
|
||||
// returns the newly opened tab
|
||||
function openTab(uri) {
|
||||
let tab = gBrowser.addTab(uri);
|
||||
|
||||
// select tab and make sure its browser is focused
|
||||
gBrowser.selectedTab = tab;
|
||||
tab.ownerDocument.defaultView.focus();
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
function clear_sts_data() {
|
||||
for (let test in test_servers) {
|
||||
SpecialPowers.cleanUpSTSData('http://'+test_servers[test].host);
|
||||
}
|
||||
}
|
||||
|
||||
function do_cleanup() {
|
||||
clear_sts_data();
|
||||
|
||||
Services.obs.removeObserver(Observer, "console-api-log-event");
|
||||
Services.obs.removeObserver(Observer, "http-on-examine-response");
|
||||
}
|
||||
|
||||
function SetupPrefTestEnvironment(which) {
|
||||
which_test = which;
|
||||
clear_sts_data();
|
||||
|
||||
var settings = test_settings[which];
|
||||
// priming counts how many priming requests we saw
|
||||
settings.priming = {};
|
||||
// priming counts how many tests were finished
|
||||
settings.finished= {};
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [["security.mixed_content.block_active_content",
|
||||
settings.block_active],
|
||||
["security.mixed_content.block_display_content",
|
||||
settings.block_display],
|
||||
["security.mixed_content.use_hsts",
|
||||
settings.use_hsts],
|
||||
["security.mixed_content.send_hsts_priming",
|
||||
settings.send_hsts_priming]]});
|
||||
}
|
||||
|
||||
// make the top-level test uri
|
||||
function build_test_uri(base_uri, host, test_id, type) {
|
||||
return base_uri +
|
||||
"?host=" + escape(host) +
|
||||
"&id=" + escape(test_id) +
|
||||
"&type=" + escape(type);
|
||||
}
|
||||
|
||||
// open a new tab, load the test, and wait for it to finish
|
||||
function execute_test(test, mimetype) {
|
||||
var src = build_test_uri(TOP_URI, test_servers[test].host,
|
||||
test, test_settings[which_test].type);
|
||||
|
||||
let tab = openTab(src);
|
||||
test_servers[test]['tab'] = tab;
|
||||
|
||||
let browser = gBrowser.getBrowserForTab(tab);
|
||||
yield BrowserTestUtils.browserLoaded(browser);
|
||||
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
|
||||
//jscs:disable
|
||||
add_task(function*() {
|
||||
//jscs:enable
|
||||
Services.obs.addObserver(Observer, "console-api-log-event", false);
|
||||
Services.obs.addObserver(Observer, "http-on-examine-response", false);
|
||||
registerCleanupFunction(do_cleanup);
|
||||
requestLongerTimeout(4);
|
||||
|
||||
for (let which of Object.keys(test_settings)) {
|
||||
SetupPrefTestEnvironment(which);
|
||||
|
||||
for (let server of Object.keys(test_servers)) {
|
||||
yield execute_test(server, test_settings[which].mimetype);
|
||||
}
|
||||
|
||||
SpecialPowers.popPrefEnv();
|
||||
}
|
||||
});
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 17 KiB |
|
@ -0,0 +1,84 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1246540</title>
|
||||
<meta http-equiv='content-type' content="text/html;charset=utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="visibility: hidden">
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
/*
|
||||
* Description of the test:
|
||||
* Attempt to load an insecure resource. If the resource responds to HSTS
|
||||
* priming with an STS header, the load should continue securely.
|
||||
* If it does not, the load should continue be blocked or continue insecurely.
|
||||
*/
|
||||
|
||||
function parse_query_string() {
|
||||
var q = {};
|
||||
document.location.search.substr(1).
|
||||
split('&').forEach(function (item, idx, ar) {
|
||||
let [k, v] = item.split('=');
|
||||
q[k] = unescape(v);
|
||||
});
|
||||
return q;
|
||||
}
|
||||
|
||||
var args = parse_query_string();
|
||||
|
||||
var subresources = {
|
||||
css: { mimetype: 'text/css', file: 'file_stylesheet.css' },
|
||||
img: { mimetype: 'image/png', file: 'file_1x1.png' },
|
||||
script: { mimetype: 'text/javascript', file: 'file_priming.js' },
|
||||
};
|
||||
|
||||
function handler(ev) {
|
||||
console.log("HSTS_PRIMING: Blocked "+args.id);
|
||||
}
|
||||
|
||||
function loadCss(src) {
|
||||
let head = document.getElementsByTagName("head")[0];
|
||||
let link = document.createElement("link");
|
||||
link.setAttribute("rel", "stylesheet");
|
||||
link.setAttribute("type", subresources[args.type].mimetype);
|
||||
link.setAttribute("href", src);
|
||||
head.appendChild(link);
|
||||
}
|
||||
|
||||
function loadResource(src) {
|
||||
let content = document.getElementById("content");
|
||||
let testElem = document.createElement(args.type);
|
||||
testElem.setAttribute("id", args.id);
|
||||
testElem.setAttribute("charset", "UTF-8");
|
||||
testElem.onerror = handler;
|
||||
content.appendChild(testElem);
|
||||
testElem.src = src;
|
||||
}
|
||||
|
||||
function loadTest() {
|
||||
let subresource = subresources[args.type];
|
||||
|
||||
let src = "http://"
|
||||
+ args.host
|
||||
+ "/browser/dom/security/test/hsts/file_testserver.sjs"
|
||||
+ "?file=" +escape("browser/dom/security/test/hsts/" + subresource.file)
|
||||
+ "&primer=" + escape(args.id)
|
||||
+ "&mimetype=" + escape(subresource.mimetype)
|
||||
;
|
||||
if (args.type == 'css') {
|
||||
loadCss(src);
|
||||
return;
|
||||
}
|
||||
|
||||
loadResource(src);
|
||||
}
|
||||
|
||||
// start running the tests
|
||||
loadTest();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,4 @@
|
|||
function completed() {
|
||||
return;
|
||||
}
|
||||
completed();
|
|
@ -0,0 +1,66 @@
|
|||
// SJS file for HSTS mochitests
|
||||
|
||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
||||
Components.utils.importGlobalProperties(["URLSearchParams"]);
|
||||
|
||||
function loadFromFile(path) {
|
||||
// Load the HTML to return in the response from file.
|
||||
// Since it's relative to the cwd of the test runner, we start there and
|
||||
// append to get to the actual path of the file.
|
||||
var testFile =
|
||||
Components.classes["@mozilla.org/file/directory_service;1"].
|
||||
getService(Components.interfaces.nsIProperties).
|
||||
get("CurWorkD", Components.interfaces.nsILocalFile);
|
||||
var dirs = path.split("/");
|
||||
for (var i = 0; i < dirs.length; i++) {
|
||||
testFile.append(dirs[i]);
|
||||
}
|
||||
var testFileStream =
|
||||
Components.classes["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(Components.interfaces.nsIFileInputStream);
|
||||
testFileStream.init(testFile, -1, 0, 0);
|
||||
var test = NetUtil.readInputStreamToString(testFileStream, testFileStream.available());
|
||||
return test;
|
||||
}
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
const query = new URLSearchParams(request.queryString);
|
||||
|
||||
redir = query.get('redir');
|
||||
if (redir == 'same') {
|
||||
query.delete("redir");
|
||||
response.setStatus(302);
|
||||
let newURI = request.uri;
|
||||
newURI.queryString = query.serialize();
|
||||
response.setHeader("Location", newURI.spec)
|
||||
}
|
||||
|
||||
// avoid confusing cache behaviors
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
|
||||
// if we have a priming header, check for required behavior
|
||||
// and set header appropriately
|
||||
if (request.hasHeader('Upgrade-Insecure-Requests')) {
|
||||
var expected = query.get('primer');
|
||||
if (expected == 'prime-hsts') {
|
||||
// set it for 5 minutes
|
||||
response.setHeader("Strict-Transport-Security", "max-age="+(60*5), false);
|
||||
} else if (expected == 'reject-upgrade') {
|
||||
response.setHeader("Strict-Transport-Security", "max-age=0", false);
|
||||
}
|
||||
response.write('');
|
||||
return;
|
||||
}
|
||||
|
||||
var file = query.get('file');
|
||||
if (file) {
|
||||
var mimetype = unescape(query.get('mimetype'));
|
||||
response.setHeader("Content-Type", mimetype, false);
|
||||
response.write(loadFromFile(unescape(file)));
|
||||
return;
|
||||
}
|
||||
|
||||
response.setHeader("Content-Type", "application/json", false);
|
||||
response.write('{}');
|
||||
}
|
|
@ -162,6 +162,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=62178
|
|||
}
|
||||
|
||||
function startTest() {
|
||||
// Set prefs to use mixed-content before HSTS
|
||||
SpecialPowers.pushPrefEnv({'set': [["security.mixed_content.use_hsts", false],
|
||||
["security.mixed_content.send_hsts_priming", false]]});
|
||||
//Set the first set of mixed content settings and increment the counter.
|
||||
//Enable <picture> and <img srcset> for the test.
|
||||
changePrefs([[ "dom.image.srcset.enabled", true ], [ "dom.image.picture.enabled", true ]],
|
||||
|
|
|
@ -27,4 +27,5 @@ MOCHITEST_CHROME_MANIFESTS += [
|
|||
BROWSER_CHROME_MANIFESTS += [
|
||||
'contentverifier/browser.ini',
|
||||
'csp/browser.ini',
|
||||
'hsts/browser.ini',
|
||||
]
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
// Keep track of one in-flight XHR by allowing secondary ones to
|
||||
// tell us when the client has received a Progress event and wants
|
||||
// more data or to stop the in-flight XHR.
|
||||
|
||||
const STATE_NAME = "bug918719_loading_event_test";
|
||||
const CHUNK_DATA = "chunk";
|
||||
|
||||
function setReq(req) {
|
||||
setObjectState(STATE_NAME, req);
|
||||
}
|
||||
|
||||
function getReq() {
|
||||
let req;
|
||||
getObjectState(STATE_NAME, function(v) {
|
||||
req = v;
|
||||
});
|
||||
return req;
|
||||
}
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
var pairs = request.queryString.split("&");
|
||||
var command = pairs.shift();
|
||||
|
||||
response.setHeader("Content-Type", "text/plain");
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
|
||||
switch(command) {
|
||||
case "more":
|
||||
getReq().write(CHUNK_DATA);
|
||||
break;
|
||||
|
||||
case "done":
|
||||
getReq().finish();
|
||||
setReq(null);
|
||||
break;
|
||||
|
||||
default:
|
||||
response.processAsync();
|
||||
response.write(CHUNK_DATA);
|
||||
setReq(response);
|
||||
return;
|
||||
}
|
||||
|
||||
response.setHeader("Content-Length", "2", false);
|
||||
response.write("ok");
|
||||
}
|
|
@ -7,7 +7,6 @@ support-files =
|
|||
bug346659-parent-echoer.html
|
||||
bug346659-parent.html
|
||||
bug458091_child.html
|
||||
bug918719.sjs
|
||||
child_bug260264.html
|
||||
devicemotion_inner.html
|
||||
devicemotion_outer.html
|
||||
|
@ -156,7 +155,6 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
|||
[test_bug857555.html]
|
||||
[test_bug862540.html]
|
||||
[test_bug876098.html]
|
||||
[test_bug918719.html]
|
||||
[test_bug927901.html]
|
||||
[test_devicemotion_multiple_listeners.html]
|
||||
skip-if = toolkit == 'android' #bug 775227
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=918719
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 918719</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=918719">Mozilla Bug 918719</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const SERVER_URL = "bug918719.sjs";
|
||||
|
||||
function sendCommand(cmd) {
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("get", SERVER_URL + "?" + cmd);
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
// Manipulate one in-flight XHR using secondary command XHRs, to guarantee
|
||||
// that multiple OnDataAvailable events are triggered (which are where
|
||||
// LOADING readystatechanges are triggered). We return a promise that will
|
||||
// resolve with a count of the number of LOADING events that were detected.
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let xhr = new XMLHttpRequest();
|
||||
let numProgressEvents = 0;
|
||||
let numLoadingEvents = 0;
|
||||
|
||||
xhr.onreadystatechange = e => {
|
||||
if (xhr.readyState === xhr.LOADING) {
|
||||
++numLoadingEvents;
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onprogress = e => {
|
||||
if (++numProgressEvents < 2) {
|
||||
sendCommand("more");
|
||||
} else {
|
||||
sendCommand("done");
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = e => {
|
||||
reject(e);
|
||||
};
|
||||
|
||||
xhr.onloadend = e => {
|
||||
resolve(numLoadingEvents);
|
||||
};
|
||||
|
||||
xhr.open("GET", SERVER_URL);
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
||||
function prefChangePromise(args) {
|
||||
return new Promise(function(resolve) {
|
||||
SpecialPowers.pushPrefEnv(args, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
runTest().then(function(count) {
|
||||
ok(count === 1, "Only one loading readystatechange event should have been fired with the pref off.");
|
||||
}).then(function() {
|
||||
return prefChangePromise({"set": [["dom.fire_extra_xhr_loading_readystatechanges", true]]});
|
||||
}).then(function() {
|
||||
return runTest();
|
||||
}).then(function(count) {
|
||||
ok(count > 1, "Multiple loading readystatechange events should have been fired with the pref on.");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -3,4 +3,4 @@
|
|||
<pre id=log>Hello World</pre>
|
||||
<script>
|
||||
var worker = new SharedWorker('sharedWorker_fetch.js');
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
addEventListener('fetch', function(event) {
|
||||
if (event.request.url.indexOf("fail.html") !== -1) {
|
||||
event.respondWith(fetch("serviceworker.html", {"integrity": "abc"}));
|
||||
event.respondWith(fetch("hello.html", {"integrity": "abc"}));
|
||||
} else if (event.request.url.indexOf("fake.html") !== -1) {
|
||||
event.respondWith(fetch("serviceworker.html"));
|
||||
} else {
|
||||
event.respondWith(new Response("Hello world"));
|
||||
event.respondWith(fetch("hello.html"));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
Hello.
|
||||
</body>
|
||||
<html>
|
|
@ -210,7 +210,7 @@ support-files =
|
|||
sw_bad_mime_type.js^headers^
|
||||
error_reporting_helpers.js
|
||||
fetch.js
|
||||
serviceworker.html
|
||||
hello.html
|
||||
create_another_sharedWorker.html
|
||||
sharedWorker_fetch.js
|
||||
|
||||
|
|
|
@ -27,5 +27,3 @@ onconnect = function(e) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -175,4 +175,4 @@ add_task(function* test_integrity_sharedWorker() {
|
|||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -169,7 +169,6 @@ XMLHttpRequestMainThread::XMLHttpRequestMainThread()
|
|||
mFlagSyncLooping(false), mFlagBackgroundRequest(false),
|
||||
mFlagHadUploadListenersOnSend(false), mFlagACwithCredentials(false),
|
||||
mFlagTimedOut(false), mFlagDeleted(false), mFlagSend(false),
|
||||
mSendExtraLoadingEvents(Preferences::GetBool("dom.fire_extra_xhr_loading_readystatechanges", true)),
|
||||
mUploadTransferred(0), mUploadTotal(0), mUploadComplete(true),
|
||||
mProgressSinceLastProgressEvent(false),
|
||||
mRequestSentTime(0), mTimeoutMilliseconds(0),
|
||||
|
@ -1715,9 +1714,7 @@ XMLHttpRequestMainThread::OnDataAvailable(nsIRequest *request,
|
|||
|
||||
mDataAvailable += totalRead;
|
||||
|
||||
if (mState == State::headers_received || mSendExtraLoadingEvents) {
|
||||
ChangeState(State::loading);
|
||||
}
|
||||
ChangeState(State::loading);
|
||||
|
||||
if (!mFlagSynchronous && !mProgressTimerIsActive) {
|
||||
StartProgressEventTimer();
|
||||
|
@ -2414,6 +2411,27 @@ XMLHttpRequestMainThread::CreateChannel()
|
|||
secFlags |= nsILoadInfo::SEC_COOKIES_OMIT;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIExpandedPrincipal> ep = do_QueryInterface(mPrincipal);
|
||||
if (ep) {
|
||||
// If we have an expanded principal, instead of using that, select the
|
||||
// principal in the whitelist which can load our URL, and use that instead.
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>>* whitelist = nullptr;
|
||||
ep->GetWhiteList(&whitelist);
|
||||
if (!whitelist) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
MOZ_ASSERT(!(secFlags & nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS));
|
||||
bool dataInherits = (secFlags &
|
||||
(nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
|
||||
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS)) != 0;
|
||||
for (const auto& principal : *whitelist) {
|
||||
if (NS_SUCCEEDED(principal->CheckMayLoad(mRequestURL, false, dataInherits))) {
|
||||
mPrincipal = principal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use the responsibleDocument if we have it, except for dedicated workers
|
||||
// where it will be the parent document, which is not the one we want to use.
|
||||
nsresult rv;
|
||||
|
|
|
@ -686,14 +686,6 @@ protected:
|
|||
// late, and ensure the XHR only handles one in-flight request at once.
|
||||
bool mFlagSend;
|
||||
|
||||
// Before ProgressEvents were a thing, multiple readystatechange events were
|
||||
// fired during the loading state to give sites a way to monitor XHR progress.
|
||||
// The XHR spec now has proper progress events and dictates that only one
|
||||
// "loading" readystatechange should be fired per send. However, it's possible
|
||||
// that some content still relies on this old behavior, so we're keeping it
|
||||
// (behind a preference) for now. See bug 918719.
|
||||
bool mSendExtraLoadingEvents;
|
||||
|
||||
RefPtr<XMLHttpRequestUpload> mUpload;
|
||||
int64_t mUploadTransferred;
|
||||
int64_t mUploadTotal;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
52342
|
||||
52343
|
||||
0/nm
|
||||
0th/pt
|
||||
1/n1
|
||||
|
@ -13747,6 +13747,7 @@ adolescence/SM
|
|||
adolescent/SM
|
||||
adopt/AGVDS
|
||||
adoptable
|
||||
adoptee/MS
|
||||
adopter/MS
|
||||
adoption/SM
|
||||
adorableness/M
|
||||
|
|
|
@ -823,7 +823,7 @@ GLContextGLX::CreateGLContext(CreateContextFlags flags, const SurfaceCaps& caps,
|
|||
RefPtr<GLContextGLX> glContext;
|
||||
bool error;
|
||||
|
||||
ScopedXErrorHandler xErrorHandler;
|
||||
OffMainThreadScopedXErrorHandler xErrorHandler;
|
||||
|
||||
do {
|
||||
error = false;
|
||||
|
@ -1311,7 +1311,7 @@ CreateOffscreenPixmapContext(CreateContextFlags flags, const IntSize& size,
|
|||
int depth;
|
||||
FindVisualAndDepth(display, visid, &visual, &depth);
|
||||
|
||||
ScopedXErrorHandler xErrorHandler;
|
||||
OffMainThreadScopedXErrorHandler xErrorHandler;
|
||||
bool error = false;
|
||||
|
||||
Drawable drawable;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include "SurfaceTypes.h"
|
||||
|
||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||
#include "mozilla/layers/TextureForwarder.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class ISurfaceAllocator;
|
||||
class LayersIPCChannel;
|
||||
} // namespace layers
|
||||
|
||||
namespace gl {
|
||||
|
@ -29,7 +29,7 @@ struct SurfaceCaps final
|
|||
|
||||
// The surface allocator that we want to create this
|
||||
// for. May be null.
|
||||
RefPtr<layers::ISurfaceAllocator> surfaceAllocator;
|
||||
RefPtr<layers::LayersIPCChannel> surfaceAllocator;
|
||||
|
||||
SurfaceCaps();
|
||||
SurfaceCaps(const SurfaceCaps& other);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче