зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound. a=merge CLOSED TREE
This commit is contained in:
Коммит
98ff24cc58
|
@ -61,8 +61,7 @@ class ClickHandlerChild extends ActorChild {
|
|||
}
|
||||
}
|
||||
|
||||
// Bug 965637, query the CSP from the doc instead of the Principal
|
||||
let csp = ownerDoc.nodePrincipal.csp;
|
||||
let csp = ownerDoc.csp;
|
||||
if (csp) {
|
||||
csp = E10SUtils.serializeCSP(csp);
|
||||
}
|
||||
|
|
|
@ -781,8 +781,7 @@ class ContextMenuChild extends ActorChild {
|
|||
context.target = node;
|
||||
|
||||
context.principal = context.target.ownerDocument.nodePrincipal;
|
||||
// Bug 965637, query the CSP from the doc instead of the Principal
|
||||
context.csp = E10SUtils.serializeCSP(context.target.ownerDocument.nodePrincipal.csp);
|
||||
context.csp = E10SUtils.serializeCSP(context.target.ownerDocument.csp);
|
||||
|
||||
context.frameOuterWindowID = WebNavigationFrames.getFrameId(context.target.ownerGlobal);
|
||||
|
||||
|
|
|
@ -2599,19 +2599,6 @@ function loadURI(uri, referrerInfo, postData, allowThirdPartyFixup,
|
|||
throw new Error("Must load with a triggering Principal");
|
||||
}
|
||||
|
||||
// After Bug 965637 we can remove that Error because the CSP will not
|
||||
// hang off the Principal anymore. Please note that the SystemPrincipal
|
||||
// can not hold a CSP!
|
||||
if (AppConstants.EARLY_BETA_OR_EARLIER) {
|
||||
// Please note that the backend will still query the CSP from the Principal in
|
||||
// release versions of Firefox. We use this error just to annotate all the
|
||||
// callsites to explicitly pass a CSP before we can remove the CSP from
|
||||
// the Principal within Bug 965637.
|
||||
if (!triggeringPrincipal.isSystemPrincipal && triggeringPrincipal.csp && !csp) {
|
||||
throw new Error("If Principal has CSP then we need an explicit CSP");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
openLinkIn(uri, "current",
|
||||
{ referrerInfo,
|
||||
|
@ -5802,19 +5789,6 @@ nsBrowserAccess.prototype = {
|
|||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// After Bug 965637 we can remove that Error because the CSP will not
|
||||
// hang off the Principal anymore. Please note that the SystemPrincipal
|
||||
// can not hold a CSP!
|
||||
if (AppConstants.EARLY_BETA_OR_EARLIER) {
|
||||
// Please note that the backend will still query the CSP from the Principal in
|
||||
// release versions of Firefox. We use this error just to annotate all the
|
||||
// callsites to explicitly pass a CSP before we can remove the CSP from
|
||||
// the Principal within Bug 965637.
|
||||
if (!aTriggeringPrincipal.isSystemPrincipal && aTriggeringPrincipal.csp && !aCsp) {
|
||||
throw new Error("If Principal has CSP then we need an explicit CSP");
|
||||
}
|
||||
}
|
||||
|
||||
var newWindow = null;
|
||||
var isExternal = !!(aFlags & Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
|
||||
|
||||
|
@ -6507,9 +6481,6 @@ function handleLinkClick(event, href, linkNode) {
|
|||
!BrowserUtils.linkHasNoReferrer(linkNode),
|
||||
referrerURI);
|
||||
|
||||
// Bug 965637, query the CSP from the doc instead of the Principal
|
||||
let csp = doc.nodePrincipal.csp;
|
||||
|
||||
urlSecurityCheck(href, doc.nodePrincipal);
|
||||
let params = {
|
||||
charset: doc.characterSet,
|
||||
|
@ -6517,7 +6488,7 @@ function handleLinkClick(event, href, linkNode) {
|
|||
referrerInfo,
|
||||
originPrincipal: doc.nodePrincipal,
|
||||
triggeringPrincipal: doc.nodePrincipal,
|
||||
csp,
|
||||
csp: doc.csp,
|
||||
frameOuterWindowID,
|
||||
};
|
||||
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
|
||||
[browser_principalSerialization_version1.js]
|
||||
[browser_principalSerialization_csp.js]
|
||||
skip-if = debug # deliberately bypass assertions when deserializing. Bug 965637 removed the CSP from Principals, but the remaining bits in such Principals should deserialize correctly.
|
||||
|
|
|
@ -45,7 +45,8 @@ add_task(async function test_deserialize_principal_with_csp() {
|
|||
{
|
||||
"input": "ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAHmh0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTLwAAAAAAAAAFAAAACAAAAA8AAAAA/////wAAAAD/////AAAACAAAAA8AAAAXAAAABwAAABcAAAAHAAAAFwAAAAcAAAAeAAAAAAAAAAD/////AAAAAP////8AAAAA/////wAAAAD/////AQAAAAAAAAAAAAAAAQnZ7Rrl1EAEv+Anzrkj2ayzxMCuvV5MrYfgjSENuz+fAd6UctCANBHTk5kAEEug/UCSBzpUbXhPMJE6uHGBMgjGAAAAAv////8AAAG7AQAAAB5odHRwczovL3d3dy5tb3ppbGxhLm9yZy9lbi1VUy8AAAAAAAAABQAAAAgAAAAPAAAAAP////8AAAAA/////wAAAAgAAAAPAAAAFwAAAAcAAAAXAAAABwAAABcAAAAHAAAAHgAAAAAAAAAA/////wAAAAD/////AAAAAP////8AAAAA/////wEAAAAAAAAAAAABAAAFtgBzAGMAcgBpAHAAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIAAnAHUAbgBzAGEAZgBlAC0AaQBuAGwAaQBuAGUAJwAgACcAdQBuAHMAYQBmAGUALQBlAHYAYQBsACcAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdABhAGcAbQBhAG4AYQBnAGUAcgAuAGcAbwBvAGcAbABlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AcwAuAHkAdABpAG0AZwAuAGMAbwBtADsAIABpAG0AZwAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIABkAGEAdABhADoAIABoAHQAdABwAHMAOgAvAC8AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAZABzAGUAcgB2AGkAYwBlAC4AZwBvAG8AZwBsAGUALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AZABlACAAaAB0AHQAcABzADoALwAvAGEAZABzAGUAcgB2AGkAYwBlAC4AZwBvAG8AZwBsAGUALgBkAGsAIABoAHQAdABwAHMAOgAvAC8AYwByAGUAYQB0AGkAdgBlAGMAbwBtAG0AbwBuAHMALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwBhAGQALgBkAG8AdQBiAGwAZQBjAGwAaQBjAGsALgBuAGUAdAA7ACAAZABlAGYAYQB1AGwAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AOwAgAGYAcgBhAG0AZQAtAHMAcgBjACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAtAG4AbwBjAG8AbwBrAGkAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAcgBhAGMAawBlAHIAdABlAHMAdAAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AcwB1AHIAdgBlAHkAZwBpAHoAbQBvAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAuAGMAbgAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALgBjAG8AbQA7ACAAcwB0AHkAbABlAC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG4AZQB0ACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBjAG8AbQAgACcAdQBuAHMAYQBmAGUALQBpAG4AbABpAG4AZQAnADsAIABjAG8AbgBuAGUAYwB0AC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG4AZQB0ACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALwAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALgBjAG4ALwA7ACAAYwBoAGkAbABkAC0AcwByAGMAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC0AbgBvAGMAbwBvAGsAaQBlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdAByAGEAYwBrAGUAcgB0AGUAcwB0AC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBzAHUAcgB2AGUAeQBnAGkAegBtAG8ALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC4AYwBuACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAuAGMAbwBtAAA=",
|
||||
"output": {
|
||||
"cspJSON": "{\"csp-policies\":[{\"child-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"connect-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://accounts.firefox.com/\",\"https://accounts.firefox.com.cn/\"],\"default-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\"],\"frame-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"img-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"data:\",\"https://mozilla.org\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://adservice.google.com\",\"https://adservice.google.de\",\"https://adservice.google.dk\",\"https://creativecommons.org\",\"https://ad.doubleclick.net\"],\"report-only\":false,\"script-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\",\"'unsafe-eval'\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://tagmanager.google.com\",\"https://www.youtube.com\",\"https://s.ytimg.com\"],\"style-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\"]}]}",
|
||||
// Within Bug 965637 we removed CSP from Principals. Already serialized Principals however should still deserialize correctly (just without the CSP).
|
||||
// "cspJSON": "{\"csp-policies\":[{\"child-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"connect-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://accounts.firefox.com/\",\"https://accounts.firefox.com.cn/\"],\"default-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\"],\"frame-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"img-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"data:\",\"https://mozilla.org\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://adservice.google.com\",\"https://adservice.google.de\",\"https://adservice.google.dk\",\"https://creativecommons.org\",\"https://ad.doubleclick.net\"],\"report-only\":false,\"script-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\",\"'unsafe-eval'\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://tagmanager.google.com\",\"https://www.youtube.com\",\"https://s.ytimg.com\"],\"style-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\"]}]}",
|
||||
"URISpec": "https://www.mozilla.org/en-US/",
|
||||
"originAttributes": {
|
||||
"firstPartyDomain": "",
|
||||
|
@ -65,14 +66,14 @@ add_task(async function test_deserialize_principal_with_csp() {
|
|||
"privateBrowsingId": 0,
|
||||
"userContextId": 0,
|
||||
},
|
||||
"cspJSON": "{\"csp-policies\":[{\"child-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"connect-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://accounts.firefox.com/\",\"https://accounts.firefox.com.cn/\"],\"default-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\"],\"frame-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"img-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"data:\",\"https://mozilla.org\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://adservice.google.com\",\"https://adservice.google.de\",\"https://adservice.google.dk\",\"https://creativecommons.org\",\"https://ad.doubleclick.net\"],\"report-only\":false,\"script-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\",\"'unsafe-eval'\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://tagmanager.google.com\",\"https://www.youtube.com\",\"https://s.ytimg.com\"],\"style-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\"]}]}",
|
||||
// Within Bug 965637 we removed CSP from Principals. Already serialized Principals however should still deserialize correctly (just without the CSP).
|
||||
// "cspJSON": "{\"csp-policies\":[{\"child-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"connect-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://accounts.firefox.com/\",\"https://accounts.firefox.com.cn/\"],\"default-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\"],\"frame-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"img-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"data:\",\"https://mozilla.org\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://adservice.google.com\",\"https://adservice.google.de\",\"https://adservice.google.dk\",\"https://creativecommons.org\",\"https://ad.doubleclick.net\"],\"report-only\":false,\"script-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\",\"'unsafe-eval'\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://tagmanager.google.com\",\"https://www.youtube.com\",\"https://s.ytimg.com\"],\"style-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\"]}]}",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
for (let test of serializedPrincipalsFromFirefox) {
|
||||
let principal = E10SUtils.deserializePrincipal(test.input);
|
||||
is(principal.cspJSON, test.output.cspJSON, "should have CSP");
|
||||
|
||||
for (let key in principal.originAttributes) {
|
||||
is(principal.originAttributes[key], test.output.originAttributes[key], `Ensure value of ${key} is ${test.output.originAttributes[key]}`);
|
||||
|
|
|
@ -98,7 +98,6 @@ add_task(async function test_realHistoryCheck() {
|
|||
testData.output.URISpec = principal.URI.spec;
|
||||
}
|
||||
testData.output.originAttributes = principal.originAttributes;
|
||||
testData.output.cspJSON = principal.cspJSON;
|
||||
|
||||
tests.push(testData);
|
||||
}
|
||||
|
@ -118,7 +117,6 @@ add_task(async function test_realHistoryCheck() {
|
|||
"privateBrowsingId": 0,
|
||||
"userContextId": 0,
|
||||
},
|
||||
"cspJSON": "{}",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -131,7 +129,6 @@ add_task(async function test_realHistoryCheck() {
|
|||
"privateBrowsingId": 0,
|
||||
"userContextId": 0,
|
||||
},
|
||||
"cspJSON": "{}",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -144,7 +141,6 @@ add_task(async function test_realHistoryCheck() {
|
|||
"privateBrowsingId": 0,
|
||||
"userContextId": 0,
|
||||
},
|
||||
"cspJSON": "{}",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -157,14 +153,12 @@ add_task(async function test_realHistoryCheck() {
|
|||
"privateBrowsingId": 0,
|
||||
"userContextId": 0,
|
||||
},
|
||||
"cspJSON": "{}",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
for (let test of serializedPrincipalsFromFirefox) {
|
||||
let principal = E10SUtils.deserializePrincipal(test.input);
|
||||
is(principal.cspJSON, test.output.cspJSON, "should have CSP");
|
||||
|
||||
for (let key in principal.originAttributes) {
|
||||
is(principal.originAttributes[key], test.output.originAttributes[key], `Ensure value of ${key} is ${test.output.originAttributes[key]}`);
|
||||
|
|
|
@ -35,6 +35,7 @@ let LEGACY_ACTORS = {
|
|||
matches: ["about:logins"],
|
||||
module: "resource:///actors/AboutLoginsChild.jsm",
|
||||
events: {
|
||||
"AboutLoginsCreateLogin": {wantUntrusted: true},
|
||||
"AboutLoginsDeleteLogin": {wantUntrusted: true},
|
||||
"AboutLoginsOpenSite": {wantUntrusted: true},
|
||||
"AboutLoginsUpdateLogin": {wantUntrusted: true},
|
||||
|
@ -546,6 +547,7 @@ const listeners = {
|
|||
},
|
||||
|
||||
mm: {
|
||||
"AboutLogins:CreateLogin": ["AboutLoginsParent"],
|
||||
"AboutLogins:DeleteLogin": ["AboutLoginsParent"],
|
||||
"AboutLogins:OpenSite": ["AboutLoginsParent"],
|
||||
"AboutLogins:Subscribe": ["AboutLoginsParent"],
|
||||
|
|
|
@ -115,6 +115,10 @@ static const RedirEntry kRedirMap[] = {
|
|||
nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT},
|
||||
{"protections", "chrome://browser/content/protections.html",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT |
|
||||
nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGED_CHILD},
|
||||
};
|
||||
|
||||
static nsAutoCString GetAboutModuleName(nsIURI* aURI) {
|
||||
|
|
|
@ -19,6 +19,7 @@ pages = [
|
|||
'policies',
|
||||
'preferences',
|
||||
'privatebrowsing',
|
||||
'protections',
|
||||
'reader',
|
||||
'restartrequired',
|
||||
'rights',
|
||||
|
|
|
@ -31,6 +31,10 @@ class AboutLoginsChild extends ActorChild {
|
|||
});
|
||||
break;
|
||||
}
|
||||
case "AboutLoginsCreateLogin": {
|
||||
this.mm.sendAsyncMessage("AboutLogins:CreateLogin", {login: event.detail});
|
||||
break;
|
||||
}
|
||||
case "AboutLoginsDeleteLogin": {
|
||||
this.mm.sendAsyncMessage("AboutLogins:DeleteLogin", {login: event.detail});
|
||||
break;
|
||||
|
|
|
@ -39,12 +39,26 @@ const isValidLogin = login => {
|
|||
};
|
||||
|
||||
const convertSubjectToLogin = subject => {
|
||||
subject.QueryInterface(Ci.nsILoginMetaInfo).QueryInterface(Ci.nsILoginInfo);
|
||||
const login = LoginHelper.loginToVanillaObject(subject);
|
||||
if (!isValidLogin(login)) {
|
||||
return null;
|
||||
}
|
||||
return login;
|
||||
subject.QueryInterface(Ci.nsILoginMetaInfo).QueryInterface(Ci.nsILoginInfo);
|
||||
const login = LoginHelper.loginToVanillaObject(subject);
|
||||
if (!isValidLogin(login)) {
|
||||
return null;
|
||||
}
|
||||
return augmentVanillaLoginObject(login);
|
||||
};
|
||||
|
||||
const augmentVanillaLoginObject = login => {
|
||||
let title;
|
||||
try {
|
||||
title = (new URL(login.hostname)).host;
|
||||
} catch (ex) {
|
||||
title = login.hostname;
|
||||
}
|
||||
title = title.replace(/^http(s)?:\/\//, "").
|
||||
replace(/^www\d*\./, "");
|
||||
return Object.assign({}, login, {
|
||||
title,
|
||||
});
|
||||
};
|
||||
|
||||
var AboutLoginsParent = {
|
||||
|
@ -60,6 +74,16 @@ var AboutLoginsParent = {
|
|||
}
|
||||
|
||||
switch (message.name) {
|
||||
case "AboutLogins:CreateLogin": {
|
||||
let newLogin = message.data.login;
|
||||
Object.assign(newLogin, {
|
||||
formSubmitURL: "",
|
||||
usernameField: "",
|
||||
passwordField: "",
|
||||
});
|
||||
Services.logins.addLogin(LoginHelper.vanillaObjectToLogin(newLogin));
|
||||
break;
|
||||
}
|
||||
case "AboutLogins:DeleteLogin": {
|
||||
let login = LoginHelper.vanillaObjectToLogin(message.data.login);
|
||||
Services.logins.removeLogin(login);
|
||||
|
@ -68,8 +92,8 @@ var AboutLoginsParent = {
|
|||
case "AboutLogins:OpenSite": {
|
||||
let guid = message.data.login.guid;
|
||||
let logins = LoginHelper.searchLoginsWithObject({guid});
|
||||
if (!logins || logins.length != 1) {
|
||||
log.warn(`AboutLogins:OpenSite: expected to find a login for guid: ${guid} but found ${(logins || []).length}`);
|
||||
if (logins.length != 1) {
|
||||
log.warn(`AboutLogins:OpenSite: expected to find a login for guid: ${guid} but found ${logins.length}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -91,8 +115,8 @@ var AboutLoginsParent = {
|
|||
case "AboutLogins:UpdateLogin": {
|
||||
let loginUpdates = message.data.login;
|
||||
let logins = LoginHelper.searchLoginsWithObject({guid: loginUpdates.guid});
|
||||
if (!logins || logins.length != 1) {
|
||||
log.warn(`AboutLogins:UpdateLogin: expected to find a login for guid: ${loginUpdates.guid} but found ${(logins || []).length}`);
|
||||
if (logins.length != 1) {
|
||||
log.warn(`AboutLogins:UpdateLogin: expected to find a login for guid: ${loginUpdates.guid} but found ${logins.length}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -232,6 +256,7 @@ var AboutLoginsParent = {
|
|||
return Services.logins
|
||||
.getAllLogins()
|
||||
.filter(isValidLogin)
|
||||
.map(LoginHelper.loginToVanillaObject);
|
||||
.map(LoginHelper.loginToVanillaObject)
|
||||
.map(augmentVanillaLoginObject);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@ header {
|
|||
align-items: center;
|
||||
background-color: var(--in-content-box-background);
|
||||
border-bottom: 1px solid var(--in-content-box-border-color);
|
||||
padding: 0 18px;
|
||||
}
|
||||
|
||||
login-filter {
|
||||
|
@ -26,6 +27,7 @@ login-filter {
|
|||
|
||||
login-list {
|
||||
grid-area: logins;
|
||||
overflow: hidden auto;
|
||||
}
|
||||
|
||||
login-item {
|
||||
|
@ -35,7 +37,12 @@ login-item {
|
|||
|
||||
#branding-logo {
|
||||
height: 32px;
|
||||
margin-inline-end: 18px;
|
||||
}
|
||||
|
||||
#create-login-button {
|
||||
margin-inline-start: 18px;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
:root:not(.official-branding) #branding-logo {
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
### need to be applied to the composed node where they can be moved to the proper
|
||||
### descendant after translation.
|
||||
|
||||
about-logins-page-title = Login Manager
|
||||
about-logins-page-title = Logins & Passwords
|
||||
|
||||
create-login-button = New Login
|
||||
|
||||
login-filter =
|
||||
.placeholder = Search Logins
|
||||
|
@ -24,20 +26,21 @@ login-list =
|
|||
|
||||
login-item =
|
||||
.cancel-button = Cancel
|
||||
.copied-password-button = ✓ Copied!
|
||||
.copied-username-button = ✓ Copied!
|
||||
.copy-password-button = Copy
|
||||
.copy-username-button = Copy
|
||||
.delete-button = Delete
|
||||
.edit-button = Edit
|
||||
.hostname-label = Website Address
|
||||
.modal-input-reveal-checkbox-hide = Hide password
|
||||
.modal-input-reveal-checkbox-show = Show password
|
||||
.copied-password-button = ✓ Copied!
|
||||
.copied-username-button = ✓ Copied!
|
||||
.copy-password-button = Copy
|
||||
.copy-username-button = Copy
|
||||
.new-login-title = New Entry
|
||||
.open-site-button = Launch
|
||||
.password-label = Password
|
||||
.save-changes-button = Save Changes
|
||||
.time-created = Created: { DATETIME($timeCreated, day: "numeric", month: "long", year: "numeric") }
|
||||
.time-changed = Last changed: { DATETIME($timeChanged, day: "numeric", month: "long", year: "numeric") }
|
||||
.time-changed = Last modified: { DATETIME($timeChanged, day: "numeric", month: "long", year: "numeric") }
|
||||
.time-used = Last used: { DATETIME($timeUsed, day: "numeric", month: "long", year: "numeric") }
|
||||
.username-label = Username
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<img id="branding-logo" src="chrome://branding/content/aboutlogins.svg" alt=""/>
|
||||
<login-filter data-l10n-id="login-filter"
|
||||
data-l10n-attrs="placeholder"></login-filter>
|
||||
<button id="create-login-button" data-l10n-id="create-login-button"></button>
|
||||
</header>
|
||||
<login-list data-l10n-id="login-list"
|
||||
data-l10n-attrs="count"
|
||||
|
@ -41,6 +42,7 @@
|
|||
hostname-label,
|
||||
modal-input-reveal-checkbox-hide,
|
||||
modal-input-reveal-checkbox-show,
|
||||
new-login-title,
|
||||
open-site-button,
|
||||
password-label,
|
||||
save-changes-button,
|
||||
|
@ -77,7 +79,8 @@
|
|||
<div class="detail-row">
|
||||
<label>
|
||||
<span class="hostname-label field-label"></span>
|
||||
<span class="hostname"/>
|
||||
<span class="hostname-saved-value"></span>
|
||||
<input type="text" name="hostname"/>
|
||||
</label>
|
||||
<button class="open-site-button"></button>
|
||||
</div>
|
||||
|
|
|
@ -7,6 +7,12 @@ let gElements = {};
|
|||
document.addEventListener("DOMContentLoaded", () => {
|
||||
gElements.loginList = document.querySelector("login-list");
|
||||
gElements.loginItem = document.querySelector("login-item");
|
||||
gElements.newLoginButton = document.querySelector("#create-login-button");
|
||||
|
||||
gElements.newLoginButton.addEventListener("click", () => {
|
||||
gElements.loginItem.setLogin({});
|
||||
gElements.loginList.clearSelection();
|
||||
});
|
||||
|
||||
document.dispatchEvent(new CustomEvent("AboutLoginsInit", {bubbles: true}));
|
||||
}, {once: true});
|
||||
|
@ -19,6 +25,7 @@ window.addEventListener("AboutLoginsChromeToContent", event => {
|
|||
}
|
||||
case "LoginAdded": {
|
||||
gElements.loginList.loginAdded(event.detail.value);
|
||||
gElements.loginItem.loginAdded(event.detail.value);
|
||||
break;
|
||||
}
|
||||
case "LoginModified": {
|
||||
|
|
|
@ -7,6 +7,5 @@
|
|||
}
|
||||
|
||||
input {
|
||||
margin: 18px;
|
||||
flex: auto;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
padding-right: 40px;
|
||||
}
|
||||
|
||||
:host([isNewLogin]) .hostname-saved-value,
|
||||
:host([isNewLogin]) copy-to-clipboard-button,
|
||||
:host([isNewLogin]) .open-site-button,
|
||||
:host([isNewLogin]) .meta-info,
|
||||
:host(:not([isNewLogin])) input[name="hostname"],
|
||||
:host(:not([editing])) .save-changes-button,
|
||||
:host(:not([editing])) .cancel-button {
|
||||
display: none;
|
||||
|
|
|
@ -57,6 +57,7 @@ class LoginItem extends ReflectedFluentElement {
|
|||
"hostname-label",
|
||||
"modal-input-reveal-checkbox-hide",
|
||||
"modal-input-reveal-checkbox-show",
|
||||
"new-login-title",
|
||||
"open-site-button",
|
||||
"password-label",
|
||||
"save-changes-button",
|
||||
|
@ -97,6 +98,14 @@ class LoginItem extends ReflectedFluentElement {
|
|||
.setAttribute("reveal-checkbox-show", this.getAttribute(attrName));
|
||||
break;
|
||||
}
|
||||
case "new-login-title": {
|
||||
let title = this.shadowRoot.querySelector(".title");
|
||||
title.setAttribute(attrName, this.getAttribute(attrName));
|
||||
if (!this._login.title) {
|
||||
title.textContent = this.getAttribute(attrName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -110,9 +119,10 @@ class LoginItem extends ReflectedFluentElement {
|
|||
timeUsed: this._login.timeLastUsed || "",
|
||||
};
|
||||
document.l10n.setAttributes(this, "login-item", l10nArgs);
|
||||
let hostnameNoScheme = this._login.hostname && new URL(this._login.hostname).hostname;
|
||||
this.shadowRoot.querySelector(".title").textContent = hostnameNoScheme || "";
|
||||
this.shadowRoot.querySelector(".hostname").textContent = this._login.hostname || "";
|
||||
|
||||
let title = this.shadowRoot.querySelector(".title");
|
||||
title.textContent = this._login.title || title.getAttribute("new-login-title");
|
||||
this.shadowRoot.querySelector(".hostname-saved-value").textContent = this._login.hostname || "";
|
||||
this.shadowRoot.querySelector("modal-input[name='username']").setAttribute("value", this._login.username || "");
|
||||
this.shadowRoot.querySelector("modal-input[name='password']").setAttribute("value", this._login.password || "");
|
||||
}
|
||||
|
@ -154,21 +164,19 @@ class LoginItem extends ReflectedFluentElement {
|
|||
return;
|
||||
}
|
||||
if (event.target.classList.contains("save-changes-button")) {
|
||||
let loginUpdates = {
|
||||
guid: this._login.guid,
|
||||
};
|
||||
let formUsername = this.shadowRoot.querySelector("modal-input[name='username']").value.trim();
|
||||
if (formUsername != this._login.username) {
|
||||
loginUpdates.username = formUsername;
|
||||
let loginUpdates = this._loginFromForm();
|
||||
if (this._login.guid) {
|
||||
loginUpdates.guid = this._login.guid;
|
||||
document.dispatchEvent(new CustomEvent("AboutLoginsUpdateLogin", {
|
||||
bubbles: true,
|
||||
detail: loginUpdates,
|
||||
}));
|
||||
} else {
|
||||
document.dispatchEvent(new CustomEvent("AboutLoginsCreateLogin", {
|
||||
bubbles: true,
|
||||
detail: loginUpdates,
|
||||
}));
|
||||
}
|
||||
let formPassword = this.shadowRoot.querySelector("modal-input[name='password']").value.trim();
|
||||
if (formPassword != this._login.password) {
|
||||
loginUpdates.password = formPassword;
|
||||
}
|
||||
document.dispatchEvent(new CustomEvent("AboutLoginsUpdateLogin", {
|
||||
bubbles: true,
|
||||
detail: loginUpdates,
|
||||
}));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -176,17 +184,29 @@ class LoginItem extends ReflectedFluentElement {
|
|||
}
|
||||
|
||||
setLogin(login) {
|
||||
this._login = login;
|
||||
this.toggleAttribute("isNewLogin", !login.guid);
|
||||
this.toggleEditing(!login.guid);
|
||||
this.render();
|
||||
}
|
||||
|
||||
loginAdded(login) {
|
||||
if (this._login.guid ||
|
||||
!window.AboutLoginsUtils.doLoginsMatch(login, this._loginFromForm())) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.toggleEditing(false);
|
||||
this._login = login;
|
||||
this.render();
|
||||
}
|
||||
|
||||
loginModified(login) {
|
||||
if (login.guid != this._login.guid) {
|
||||
if (this._login.guid != login.guid) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._login = login;
|
||||
this.toggleEditing(false);
|
||||
this.render();
|
||||
}
|
||||
|
||||
|
@ -200,10 +220,24 @@ class LoginItem extends ReflectedFluentElement {
|
|||
|
||||
toggleEditing(force) {
|
||||
let shouldEdit = force !== undefined ? force : !this.hasAttribute("editing");
|
||||
|
||||
if (!shouldEdit) {
|
||||
this.removeAttribute("isNewLogin");
|
||||
}
|
||||
|
||||
this.shadowRoot.querySelector(".edit-button").disabled = shouldEdit;
|
||||
this.shadowRoot.querySelectorAll("modal-input")
|
||||
.forEach(el => el.toggleAttribute("editing", shouldEdit));
|
||||
this.toggleAttribute("editing", shouldEdit);
|
||||
}
|
||||
|
||||
_loginFromForm() {
|
||||
return {
|
||||
username: this.shadowRoot.querySelector("modal-input[name='username']").value.trim(),
|
||||
password: this.shadowRoot.querySelector("modal-input[name='password']").value.trim(),
|
||||
hostname: this.hasAttribute("isNewLogin") ? this.shadowRoot.querySelector("input[name='hostname']").value.trim()
|
||||
: this.shadowRoot.querySelector(".hostname-saved-value").textContent,
|
||||
};
|
||||
}
|
||||
}
|
||||
customElements.define("login-item", LoginItem);
|
||||
|
|
|
@ -29,6 +29,7 @@ class LoginList extends ReflectedFluentElement {
|
|||
|
||||
render() {
|
||||
let list = this.shadowRoot.querySelector("ol");
|
||||
list.textContent = "";
|
||||
for (let login of this._logins) {
|
||||
list.append(new LoginListItem(login));
|
||||
}
|
||||
|
@ -65,10 +66,10 @@ class LoginList extends ReflectedFluentElement {
|
|||
if (this._selectedItem.getAttribute("guid") == event.detail.guid) {
|
||||
return;
|
||||
}
|
||||
this._selectedItem.classList.toggle("selected", false);
|
||||
this._selectedItem.classList.remove("selected");
|
||||
}
|
||||
this._selectedItem = this.shadowRoot.querySelector(`login-list-item[guid="${event.detail.guid}"]`);
|
||||
this._selectedItem.classList.toggle("selected", true);
|
||||
this._selectedItem.classList.add("selected");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -82,9 +83,15 @@ class LoginList extends ReflectedFluentElement {
|
|||
return this.reflectedFluentIDs;
|
||||
}
|
||||
|
||||
clearSelection() {
|
||||
if (!this._selectedItem) {
|
||||
return;
|
||||
}
|
||||
this._selectedItem.classList.remove("selected");
|
||||
this._selectedItem = null;
|
||||
}
|
||||
|
||||
setLogins(logins) {
|
||||
let list = this.shadowRoot.querySelector("ol");
|
||||
list.textContent = "";
|
||||
this._logins = logins;
|
||||
this.render();
|
||||
}
|
||||
|
@ -93,6 +100,7 @@ class LoginList extends ReflectedFluentElement {
|
|||
this._logins.push(login);
|
||||
let list = this.shadowRoot.querySelector("ol");
|
||||
list.append(new LoginListItem(login));
|
||||
document.l10n.setAttributes(this, "login-list", {count: this._logins.length});
|
||||
}
|
||||
|
||||
loginModified(login) {
|
||||
|
@ -120,6 +128,7 @@ class LoginList extends ReflectedFluentElement {
|
|||
break;
|
||||
}
|
||||
}
|
||||
document.l10n.setAttributes(this, "login-list", {count: this._logins.length});
|
||||
}
|
||||
}
|
||||
customElements.define("login-list", LoginList);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
--reveal-button-opacity-active: 1;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:host([editing]) .locked-value,
|
||||
|
|
|
@ -54,19 +54,25 @@ add_task(async function setup() {
|
|||
|
||||
add_task(async function test_empty_item() {
|
||||
ok(gLoginItem, "loginItem exists");
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname").textContent, "", "hostname should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname-saved-value").textContent, "", "hostname should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='username']").value, "", "username should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='password']").value, "", "password should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, "", "time-created should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, "", "time-changed should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, "", "time-used should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, "", "time-created should be blank when undefined");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, "", "time-changed should be blank when undefined");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, "", "time-used should be blank when undefined");
|
||||
});
|
||||
|
||||
add_task(async function test_set_login() {
|
||||
gLoginItem.setLogin(TEST_LOGIN_1);
|
||||
await asyncElementRendered();
|
||||
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname").textContent, TEST_LOGIN_1.hostname, "hostname should be populated");
|
||||
ok(!gLoginItem.hasAttribute("editing"), "loginItem should not be in 'edit' mode");
|
||||
ok(!gLoginItem.hasAttribute("isNewLogin"), "loginItem should not be in 'isNewLogin' mode");
|
||||
let savedHostname = gLoginItem.shadowRoot.querySelector(".hostname-saved-value");
|
||||
is(getComputedStyle(savedHostname).display, "inline", ".hostname-saved-value should be visible for non-editing existing logins");
|
||||
let hostnameInput = gLoginItem.shadowRoot.querySelector("input[name='hostname']");
|
||||
is(getComputedStyle(hostnameInput).display, "none", "input[name='hostname'] should be hidden for non-editing existing logins");
|
||||
is(savedHostname.textContent, TEST_LOGIN_1.hostname, "hostname should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='username']").value, TEST_LOGIN_1.username, "username should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='password']").value, TEST_LOGIN_1.password, "password should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, TEST_LOGIN_1.timeCreated, "time-created should be populated");
|
||||
|
@ -74,12 +80,95 @@ add_task(async function test_set_login() {
|
|||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, TEST_LOGIN_1.timeLastUsed, "time-used should be populated");
|
||||
});
|
||||
|
||||
add_task(async function test_edit_login() {
|
||||
gLoginItem.setLogin(TEST_LOGIN_1);
|
||||
gLoginItem.shadowRoot.querySelector(".edit-button").click();
|
||||
await asyncElementRendered();
|
||||
|
||||
ok(gLoginItem.hasAttribute("editing"), "loginItem should be in 'edit' mode");
|
||||
ok(!gLoginItem.hasAttribute("isNewLogin"), "loginItem should not be in 'isNewLogin' mode");
|
||||
let savedHostname = gLoginItem.shadowRoot.querySelector(".hostname-saved-value");
|
||||
is(getComputedStyle(savedHostname).display, "inline", ".hostname-saved-value should be visible for editing existing logins");
|
||||
let hostnameInput = gLoginItem.shadowRoot.querySelector("input[name='hostname']");
|
||||
is(getComputedStyle(hostnameInput).display, "none", "input[name='hostname'] should be hidden for editing existing logins");
|
||||
is(savedHostname.textContent, TEST_LOGIN_1.hostname, "hostname should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='username']").value, TEST_LOGIN_1.username, "username should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='password']").value, TEST_LOGIN_1.password, "password should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, TEST_LOGIN_1.timeCreated, "time-created should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, TEST_LOGIN_1.timePasswordChanged, "time-changed should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, TEST_LOGIN_1.timeLastUsed, "time-used should be populated");
|
||||
|
||||
gLoginItem.shadowRoot.querySelector("modal-input[name='username']").value = "newUsername";
|
||||
gLoginItem.shadowRoot.querySelector("modal-input[name='password']").value = "newPassword";
|
||||
|
||||
let updateEventDispatched = false;
|
||||
document.addEventListener("AboutLoginsUpdateLogin", event => {
|
||||
is(event.detail.guid, TEST_LOGIN_1.guid, "event should include guid");
|
||||
is(event.detail.hostname, TEST_LOGIN_1.hostname, "event should include hostname");
|
||||
is(event.detail.username, "newUsername", "event should include new username");
|
||||
is(event.detail.password, "newPassword", "event should include new password");
|
||||
updateEventDispatched = true;
|
||||
}, {once: true});
|
||||
gLoginItem.shadowRoot.querySelector(".save-changes-button").click();
|
||||
ok(updateEventDispatched, "Clicking the .save-changes-button should dispatch the AboutLoginsUpdateLogin event");
|
||||
});
|
||||
|
||||
add_task(async function test_edit_login_cancel() {
|
||||
for (let login of [{}, TEST_LOGIN_1]) {
|
||||
let isNewLogin = !login.username;
|
||||
info("Testing with" + (isNewLogin ? "out" : "") + " a login");
|
||||
gLoginItem.setLogin(login);
|
||||
gLoginItem.shadowRoot.querySelector(".edit-button").click();
|
||||
|
||||
ok(gLoginItem.hasAttribute("editing"), "loginItem should be in 'edit' mode");
|
||||
is(gLoginItem.hasAttribute("isNewLogin"), isNewLogin,
|
||||
"loginItem should " + (isNewLogin ? "" : "not ") + "be in 'isNewLogin' mode");
|
||||
|
||||
gLoginItem.shadowRoot.querySelector(".cancel-button").click();
|
||||
ok(!gLoginItem.hasAttribute("editing"), "loginItem should not be in 'edit' mode");
|
||||
ok(!gLoginItem.hasAttribute("isNewLogin"), "loginItem should not be in 'isNewLogin' mode");
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_set_login_empty() {
|
||||
gLoginItem.setLogin({});
|
||||
await asyncElementRendered();
|
||||
|
||||
ok(gLoginItem.hasAttribute("editing"), "loginItem should be in 'edit' mode");
|
||||
ok(gLoginItem.hasAttribute("isNewLogin"), "loginItem should be in 'isNewLogin' mode");
|
||||
let savedHostname = gLoginItem.shadowRoot.querySelector(".hostname-saved-value");
|
||||
is(getComputedStyle(savedHostname).display, "none", ".hostname-saved-value should be hidden for new logins");
|
||||
let hostnameInput = gLoginItem.shadowRoot.querySelector("input[name='hostname']");
|
||||
is(getComputedStyle(hostnameInput).display, "inline", "input[name='hostname'] should be visible for new logins");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='username']").value, "", "username should be empty");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='password']").value, "", "password should be empty");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, "", "time-created should be blank when undefined");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, "", "time-changed should be blank when undefined");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, "", "time-used should be blank when undefined");
|
||||
|
||||
hostnameInput.value = "https://example.com/foo";
|
||||
gLoginItem.shadowRoot.querySelector("modal-input[name='username']").value = "user1";
|
||||
gLoginItem.shadowRoot.querySelector("modal-input[name='password']").value = "pass1";
|
||||
|
||||
let createEventDispatched = false;
|
||||
document.addEventListener("AboutLoginsCreateLogin", event => {
|
||||
is(event.detail.guid, undefined, "event should not include guid");
|
||||
is(event.detail.hostname, "https://example.com/foo", "event should include hostname");
|
||||
is(event.detail.username, "user1", "event should include new username");
|
||||
is(event.detail.password, "pass1", "event should include new password");
|
||||
createEventDispatched = true;
|
||||
}, {once: true});
|
||||
gLoginItem.shadowRoot.querySelector(".save-changes-button").click();
|
||||
ok(createEventDispatched, "Clicking the .save-changes-button should dispatch the AboutLoginsCreateLogin event");
|
||||
});
|
||||
|
||||
add_task(async function test_different_login_modified() {
|
||||
gLoginItem.setLogin(TEST_LOGIN_1);
|
||||
let otherLogin = Object.assign({}, TEST_LOGIN_1, {username: "fakeuser", guid: "fakeguid"});
|
||||
gLoginItem.loginModified(otherLogin);
|
||||
await asyncElementRendered();
|
||||
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname").textContent, TEST_LOGIN_1.hostname, "hostname should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname-saved-value").textContent, TEST_LOGIN_1.hostname, "hostname should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='username']").value, TEST_LOGIN_1.username, "username should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='password']").value, TEST_LOGIN_1.password, "password should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, TEST_LOGIN_1.timeCreated, "time-created should be unchanged");
|
||||
|
@ -88,11 +177,12 @@ add_task(async function test_different_login_modified() {
|
|||
});
|
||||
|
||||
add_task(async function test_different_login_removed() {
|
||||
gLoginItem.setLogin(TEST_LOGIN_1);
|
||||
let otherLogin = Object.assign({}, TEST_LOGIN_1, {username: "fakeuser", guid: "fakeguid"});
|
||||
gLoginItem.loginRemoved(otherLogin);
|
||||
await asyncElementRendered();
|
||||
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname").textContent, TEST_LOGIN_1.hostname, "hostname should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname-saved-value").textContent, TEST_LOGIN_1.hostname, "hostname should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='username']").value, TEST_LOGIN_1.username, "username should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='password']").value, TEST_LOGIN_1.password, "password should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, TEST_LOGIN_1.timeCreated, "time-created should be unchanged");
|
||||
|
@ -101,11 +191,12 @@ add_task(async function test_different_login_removed() {
|
|||
});
|
||||
|
||||
add_task(async function test_login_modified() {
|
||||
gLoginItem.setLogin(TEST_LOGIN_1);
|
||||
let modifiedLogin = Object.assign({}, TEST_LOGIN_1, {username: "updateduser"});
|
||||
gLoginItem.loginModified(modifiedLogin);
|
||||
await asyncElementRendered();
|
||||
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname").textContent, modifiedLogin.hostname, "hostname should be updated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname-saved-value").textContent, modifiedLogin.hostname, "hostname should be updated");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='username']").value, modifiedLogin.username, "username should be updated");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='password']").value, modifiedLogin.password, "password should be updated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, modifiedLogin.timeCreated, "time-created should be updated");
|
||||
|
@ -114,15 +205,16 @@ add_task(async function test_login_modified() {
|
|||
});
|
||||
|
||||
add_task(async function test_login_removed() {
|
||||
gLoginItem.setLogin(TEST_LOGIN_1);
|
||||
gLoginItem.loginRemoved(TEST_LOGIN_1);
|
||||
await asyncElementRendered();
|
||||
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname").textContent, "", "hostname should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname-saved-value").textContent, "", "hostname should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='username']").value, "", "username should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector("modal-input[name='password']").value, "", "password should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, "", "time-created should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, "", "time-changed should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, "", "time-used should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, "", "time-created should be blank when undefined");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, "", "time-changed should be blank when undefined");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, "", "time-used should be blank when undefined");
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
|
@ -87,15 +87,15 @@ async function test_cookie_settings({
|
|||
"Cookie lifetime pref lock status should be what is expected");
|
||||
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences");
|
||||
await tab.linkedBrowser.contentWindow.gotoPref("panePrivacy");
|
||||
// eslint-disable-next-line no-shadow
|
||||
await ContentTask.spawn(tab.linkedBrowser, {cookiesEnabled, cookieSettingsLocked}, async function({cookiesEnabled, cookieSettingsLocked}) {
|
||||
content.setTimeout(() => {
|
||||
let deleteOnCloseCheckbox = content.document.getElementById("deleteOnClose");
|
||||
let deleteOnCloseCheckbox = content.document.getElementById("deleteOnClose");
|
||||
isnot(deleteOnCloseCheckbox, null, "deleteOnCloseCheckbox should not be null.");
|
||||
|
||||
let expectControlsDisabled = !cookiesEnabled || cookieSettingsLocked;
|
||||
is(deleteOnCloseCheckbox.disabled, expectControlsDisabled,
|
||||
"\"Delete cookies when Firefox is closed\" checkbox disabled status should match expected");
|
||||
}, 0);
|
||||
let expectControlsDisabled = !cookiesEnabled || cookieSettingsLocked;
|
||||
is(deleteOnCloseCheckbox.disabled, expectControlsDisabled,
|
||||
"\"Delete cookies when Firefox is closed\" checkbox disabled status should match expected");
|
||||
});
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
|
||||
|
|
|
@ -220,8 +220,8 @@ this.windows = class extends ExtensionAPI {
|
|||
args.appendElement(context.principal); // originPrincipal - not important.
|
||||
args.appendElement(principal); // triggeringPrincipal
|
||||
args.appendElement(Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool)); // allowInheritPrincipal
|
||||
// Bug 965637, query the CSP from the doc instead of the Principal
|
||||
args.appendElement(principal.csp); // csp
|
||||
// There is no CSP associated with this extension, hence we explicitly pass null as the CSP argument.
|
||||
args.appendElement(null); // csp
|
||||
|
||||
let features = ["chrome"];
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ DIRS += [
|
|||
'pocket',
|
||||
'preferences',
|
||||
'privatebrowsing',
|
||||
'protections',
|
||||
'protocolhandler',
|
||||
'resistfingerprinting',
|
||||
'search',
|
||||
|
|
|
@ -57,20 +57,25 @@ export class _Trailhead extends React.PureComponent {
|
|||
link.rel = "localization";
|
||||
});
|
||||
|
||||
if (this.props.fxaEndpoint && !this.fxaMetricsInitialized) {
|
||||
await this.componentWillUpdate(this.props);
|
||||
}
|
||||
|
||||
// Get the fxa data if we don't have it yet from mount or update
|
||||
async componentWillUpdate(props) {
|
||||
if (props.fxaEndpoint && !this.fxaMetricsInitialized) {
|
||||
try {
|
||||
this.fxaMetricsInitialized = true;
|
||||
const url = new URL(`${this.props.fxaEndpoint}/metrics-flow?entrypoint=activity-stream-firstrun&form_type=email`);
|
||||
const url = new URL(`${props.fxaEndpoint}/metrics-flow?entrypoint=activity-stream-firstrun&form_type=email`);
|
||||
this.addUtmParams(url);
|
||||
const response = await fetch(url, {credentials: "omit"});
|
||||
if (response.status === 200) {
|
||||
const {deviceId, flowId, flowBeginTime} = await response.json();
|
||||
this.setState({deviceId, flowId, flowBeginTime});
|
||||
} else {
|
||||
this.props.dispatch(ac.OnlyToMain({type: at.TELEMETRY_UNDESIRED_EVENT, data: {event: "FXA_METRICS_FETCH_ERROR", value: response.status}}));
|
||||
props.dispatch(ac.OnlyToMain({type: at.TELEMETRY_UNDESIRED_EVENT, data: {event: "FXA_METRICS_FETCH_ERROR", value: response.status}}));
|
||||
}
|
||||
} catch (error) {
|
||||
this.props.dispatch(ac.OnlyToMain({type: at.TELEMETRY_UNDESIRED_EVENT, data: {event: "FXA_METRICS_ERROR"}}));
|
||||
props.dispatch(ac.OnlyToMain({type: at.TELEMETRY_UNDESIRED_EVENT, data: {event: "FXA_METRICS_ERROR"}}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3368,11 +3368,15 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon
|
|||
link.href = file;
|
||||
link.rel = "localization";
|
||||
});
|
||||
await this.componentWillUpdate(this.props);
|
||||
} // Get the fxa data if we don't have it yet from mount or update
|
||||
|
||||
if (this.props.fxaEndpoint && !this.fxaMetricsInitialized) {
|
||||
|
||||
async componentWillUpdate(props) {
|
||||
if (props.fxaEndpoint && !this.fxaMetricsInitialized) {
|
||||
try {
|
||||
this.fxaMetricsInitialized = true;
|
||||
const url = new URL(`${this.props.fxaEndpoint}/metrics-flow?entrypoint=activity-stream-firstrun&form_type=email`);
|
||||
const url = new URL(`${props.fxaEndpoint}/metrics-flow?entrypoint=activity-stream-firstrun&form_type=email`);
|
||||
this.addUtmParams(url);
|
||||
const response = await fetch(url, {
|
||||
credentials: "omit"
|
||||
|
@ -3390,7 +3394,7 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon
|
|||
flowBeginTime
|
||||
});
|
||||
} else {
|
||||
this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].OnlyToMain({
|
||||
props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].OnlyToMain({
|
||||
type: common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionTypes"].TELEMETRY_UNDESIRED_EVENT,
|
||||
data: {
|
||||
event: "FXA_METRICS_FETCH_ERROR",
|
||||
|
@ -3399,7 +3403,7 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon
|
|||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].OnlyToMain({
|
||||
props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].OnlyToMain({
|
||||
type: common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionTypes"].TELEMETRY_UNDESIRED_EVENT,
|
||||
data: {
|
||||
event: "FXA_METRICS_ERROR"
|
||||
|
|
|
@ -62,9 +62,9 @@ const TRAILHEAD_CONFIG = {
|
|||
},
|
||||
LOCALES: ["en-US", "en-GB", "en-CA", "de", "de-DE", "fr", "fr-FR"],
|
||||
EXPERIMENT_RATIOS: [
|
||||
["", 1],
|
||||
["", 0],
|
||||
["interrupts", 1],
|
||||
["triplets", 1],
|
||||
["triplets", 3],
|
||||
],
|
||||
};
|
||||
|
||||
|
|
|
@ -402,6 +402,7 @@ class PageAction {
|
|||
}
|
||||
footerText.parentNode.appendChild(stepsContainer);
|
||||
for (let step of content.descriptionDetails.steps) {
|
||||
// This li is a generic xul element with custom styling
|
||||
const li = this.window.document.createXULElement("li");
|
||||
this._l10n.setAttributes(li, step.string_id);
|
||||
stepsContainer.appendChild(li);
|
||||
|
|
|
@ -6,6 +6,7 @@ const {Localization} = ChromeUtils.import("resource://gre/modules/Localization.j
|
|||
const {FxAccountsConfig} = ChromeUtils.import("resource://gre/modules/FxAccountsConfig.jsm");
|
||||
const {AttributionCode} = ChromeUtils.import("resource:///modules/AttributionCode.jsm");
|
||||
const {AddonRepository} = ChromeUtils.import("resource://gre/modules/addons/AddonRepository.jsm");
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
async function getAddonInfo() {
|
||||
try {
|
||||
|
@ -223,7 +224,10 @@ const ONBOARDING_MESSAGES = async () => ([
|
|||
icon: "tracking",
|
||||
primary_button: {
|
||||
label: {string_id: "onboarding-tracking-protection-button2"},
|
||||
action: {
|
||||
action: Services.locale.appLocaleAsLangTag.substr(0, 2) === "en" ? {
|
||||
type: "OPEN_URL",
|
||||
data: {args: "https://mzl.la/ETPdefault", where: "tabshifted"},
|
||||
} : {
|
||||
type: "OPEN_PREFERENCES_PAGE",
|
||||
data: {category: "privacy-trackingprotection"},
|
||||
},
|
||||
|
@ -343,7 +347,7 @@ const ONBOARDING_MESSAGES = async () => ([
|
|||
label: {string_id: "onboarding-send-tabs-button"},
|
||||
action: {
|
||||
type: "OPEN_URL",
|
||||
data: {args: "https://support.mozilla.org/kb/send-tab-firefox-desktop-mobile", where: "tabshifted"},
|
||||
data: {args: "https://support.mozilla.org/kb/send-tab-firefox-desktop-other-devices", where: "tabshifted"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -93,6 +93,7 @@ prefs_home_header=Conținutul paginii de start Firefox
|
|||
prefs_home_description=Alege ce conținut vrei pe ecranul de start Firefox.
|
||||
|
||||
prefs_content_discovery_header=Pagina de start Firefox
|
||||
|
||||
prefs_content_discovery_description=Descoperirea de conținut din pagina de start Firefox îți permite să descoperi articole relevante de calitate înaltă de pe web.
|
||||
prefs_content_discovery_button=Dezactivează descoperirea de conținut
|
||||
|
||||
|
@ -204,7 +205,7 @@ firstrun_invalid_input=Necesită o adresă de e-mail validă
|
|||
|
||||
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
|
||||
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.
|
||||
firstrun_extra_legal_links=Prin continuare, agreezi {terms} și {privacy}.
|
||||
firstrun_extra_legal_links=Prin continuare, ești de acord cu {terms} și {privacy}.
|
||||
firstrun_terms_of_service=Termenii de utilizare a serviciului
|
||||
firstrun_privacy_notice=Politica de confidențialitate
|
||||
|
||||
|
|
|
@ -87,6 +87,10 @@ section_disclaimer_topstories_buttontext=ٹھیک ہے مجھے سمجھ آگئ
|
|||
# sidebar mozilla-central string for the panel that has preferences related to
|
||||
# what is shown for the homepage, new windows, and new tabs.
|
||||
prefs_home_header=Firefox ابتائی مواد
|
||||
|
||||
prefs_content_discovery_header=Firefox ابتدائی صفحہ
|
||||
|
||||
|
||||
# LOCALIZATION NOTE (prefs_section_rows_option): This is a semi-colon list of
|
||||
# plural forms used in a drop down of multiple row options (1 row, 2 rows).
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
|
|
|
@ -100,7 +100,7 @@ window.gActivityStreamStrings = {
|
|||
"firstrun_form_sub_header": "pentru a continua la Firefox Sync.",
|
||||
"firstrun_email_input_placeholder": "E-mail",
|
||||
"firstrun_invalid_input": "Necesită o adresă de e-mail validă",
|
||||
"firstrun_extra_legal_links": "Prin continuare, agreezi {terms} și {privacy}.",
|
||||
"firstrun_extra_legal_links": "Prin continuare, ești de acord cu {terms} și {privacy}.",
|
||||
"firstrun_terms_of_service": "Termenii de utilizare a serviciului",
|
||||
"firstrun_privacy_notice": "Politica de confidențialitate",
|
||||
"firstrun_continue_to_login": "Continuă",
|
||||
|
|
|
@ -64,6 +64,7 @@ describe("CFRPageActions", () => {
|
|||
PrivateBrowsingUtils: {isWindowPrivate: sandbox.stub().returns(false)},
|
||||
gBrowser: {selectedBrowser: fakeBrowser},
|
||||
});
|
||||
document.createXULElement = document.createElement;
|
||||
|
||||
elements = {};
|
||||
const [body] = document.getElementsByTagName("body");
|
||||
|
|
|
@ -18,7 +18,7 @@ describe("BookmarkPanelHub", () => {
|
|||
sandbox = sinon.createSandbox();
|
||||
globals = new GlobalOverrider();
|
||||
|
||||
fakeL10n = {setAttributes: sandbox.stub(), translateElements: sandbox.stub()};
|
||||
fakeL10n = {setAttributes: sandbox.stub()};
|
||||
globals.set("DOMLocalization", function() { return fakeL10n; }); // eslint-disable-line prefer-arrow-callback
|
||||
globals.set("FxAccounts", {config: {promiseEmailFirstURI: sandbox.stub()}});
|
||||
isBrowserPrivateStub = sandbox.stub().returns(false);
|
||||
|
@ -61,7 +61,10 @@ describe("BookmarkPanelHub", () => {
|
|||
close: sandbox.stub(),
|
||||
};
|
||||
fakeDispatch = sandbox.stub();
|
||||
fakeWindow = {ownerGlobal: {openLinkIn: sandbox.stub(), gBrowser: {selectedBrowser: "browser"}}};
|
||||
fakeWindow = {
|
||||
ownerGlobal: {openLinkIn: sandbox.stub(), gBrowser: {selectedBrowser: "browser"}},
|
||||
MozXULElement: {insertFTLIfNeeded: sandbox.stub()},
|
||||
};
|
||||
});
|
||||
afterEach(() => {
|
||||
instance.uninit();
|
||||
|
@ -140,6 +143,13 @@ describe("BookmarkPanelHub", () => {
|
|||
assert.calledWithExactly(instance.showMessage, "content", fakeTarget, fakeWindow);
|
||||
assert.calledOnce(instance.sendImpression);
|
||||
});
|
||||
it("should insert the appropriate ftl files with translations", () => {
|
||||
instance.onResponse({content: "content"}, fakeTarget, fakeWindow);
|
||||
|
||||
assert.calledTwice(fakeWindow.MozXULElement.insertFTLIfNeeded);
|
||||
assert.calledWith(fakeWindow.MozXULElement.insertFTLIfNeeded, "browser/newtab/asrouter.ftl");
|
||||
assert.calledWith(fakeWindow.MozXULElement.insertFTLIfNeeded, "browser/branding/sync-brand.ftl");
|
||||
});
|
||||
it("should dispatch a user impression", () => {
|
||||
sandbox.spy(instance, "sendUserEventTelemetry");
|
||||
|
||||
|
|
|
@ -597,9 +597,7 @@ var pktUIMessaging = (function() {
|
|||
var payload = JSON.parse(e.target.getAttribute("payload"))[0];
|
||||
var panelId = payload.panelId;
|
||||
var data = payload.data;
|
||||
// After Bug 965637 we can query the csp from the document instead
|
||||
// of the nodePrincipal, we can just use: e.target.ownerDocument.csp;
|
||||
var csp = e.target.nodePrincipal.csp;
|
||||
var csp = e.target.ownerDocument.csp;
|
||||
callback(panelId, data, nodePrincipal, csp);
|
||||
|
||||
// Cleanup the element
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
/* 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/. */
|
||||
.under-construction {
|
||||
background-image: url("chrome://browser/content/illustrations/under-construction.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
min-height: 300px;
|
||||
min-width: 300px;
|
||||
/* Move the image down a bit - should be slightly higher than halfway down the page */
|
||||
margin-top: -10%;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome: blob:">
|
||||
<link rel="stylesheet" media="screen, projection" type="text/css"
|
||||
href="chrome://global/skin/in-content/info-pages.css" title="infop">
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://browser/content/protections.css">
|
||||
<link rel="icon" href="chrome://global/skin/icons/warning.svg">
|
||||
<title>Protection Report</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="under-construction"><div/>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,7 @@
|
|||
# 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/.
|
||||
|
||||
browser.jar:
|
||||
content/browser/protections.css (content/protections.css)
|
||||
content/browser/protections.html (content/protections.html)
|
|
@ -0,0 +1,10 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Firefox', 'Tracking Protection')
|
|
@ -1,21 +1,15 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// This test is two fold:
|
||||
// a) if security.data_uri.unique_opaque_origin == false, then
|
||||
// this tests that session restore component does restore the right
|
||||
// content security policy with the document. (The policy being
|
||||
// tested disallows inline scripts).
|
||||
// b) if security.data_uri.unique_opaque_origin == true, then
|
||||
// this tests that data: URIs do not inherit the CSP from
|
||||
// it's enclosing context.
|
||||
// This test tests that session restore component does restore the right
|
||||
// content security policy with the document. (The policy being tested
|
||||
// disallows inline scripts).
|
||||
|
||||
add_task(async function test() {
|
||||
// allow top level data: URI navigations, otherwise clicking a data: link fails
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
"set": [["security.data_uri.block_toplevel_data_uri_navigations", false]],
|
||||
});
|
||||
let dataURIPref = Services.prefs.getBoolPref("security.data_uri.unique_opaque_origin");
|
||||
// create a tab that has a CSP
|
||||
let testURL = "http://mochi.test:8888/browser/browser/components/sessionstore/test/browser_911547_sample.html";
|
||||
let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, testURL);
|
||||
|
@ -32,27 +26,15 @@ add_task(async function test() {
|
|||
await ContentTask.spawn(browser, null, function() {
|
||||
is(content.document.getElementById("test_id1").value, "id1_initial",
|
||||
"CSP should block the inline script that modifies test_id");
|
||||
|
||||
|
||||
// (a) if security.data_uri.unique_opaque_origin == false:
|
||||
// attempt to click a link to a data: URI (will inherit the CSP of
|
||||
// the origin document) and navigate to the data URI in the link.
|
||||
// (b) if security.data_uri.unique_opaque_origin == true:
|
||||
// attempt to click a link to a data: URI (will *not* inherit the CSP of
|
||||
// the origin document) and navigate to the data URI in the link.
|
||||
content.document.getElementById("test_data_link").click();
|
||||
});
|
||||
|
||||
await loadedPromise;
|
||||
|
||||
await ContentTask.spawn(browser, {dataURIPref}, function( {dataURIPref}) { // eslint-disable-line
|
||||
if (dataURIPref) {
|
||||
is(content.document.getElementById("test_id2").value, "id2_modified",
|
||||
"data: URI should *not* inherit the CSP of the enclosing context");
|
||||
} else {
|
||||
is(content.document.getElementById("test_id2").value, "id2_initial",
|
||||
"CSP should block the script loaded by the clicked data URI");
|
||||
}
|
||||
await ContentTask.spawn(browser, {}, function( {}) { // eslint-disable-line
|
||||
// the data: URI inherits the CSP and the inline script needs to be blocked
|
||||
is(content.document.getElementById("test_id2").value, "id2_initial",
|
||||
"CSP should block the script loaded by the clicked data URI");
|
||||
});
|
||||
|
||||
// close the tab
|
||||
|
@ -63,14 +45,11 @@ add_task(async function test() {
|
|||
await promiseTabRestored(tab);
|
||||
browser = tab.linkedBrowser;
|
||||
|
||||
await ContentTask.spawn(browser, {dataURIPref}, function({dataURIPref}) { // eslint-disable-line
|
||||
if (dataURIPref) {
|
||||
is(content.document.getElementById("test_id2").value, "id2_modified",
|
||||
"data: URI should *not* inherit the CSP of the enclosing context");
|
||||
} else {
|
||||
is(content.document.getElementById("test_id2").value, "id2_initial",
|
||||
"CSP should block the script loaded by the clicked data URI after restore");
|
||||
}
|
||||
await ContentTask.spawn(browser, {}, function({}) { // eslint-disable-line
|
||||
// the data: URI should be restored including the inherited CSP and the
|
||||
// inline script should be blocked.
|
||||
is(content.document.getElementById("test_id2").value, "id2_initial",
|
||||
"CSP should block the script loaded by the clicked data URI after restore");
|
||||
});
|
||||
|
||||
// clean up
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
|
||||
<!--
|
||||
this element gets modified by an injected script;
|
||||
that script should be blocked by CSP if security.data_uri.unique_opaque_origin == false;
|
||||
Inline scripts can modify it, but not data uris.
|
||||
that script should be blocked by CSP
|
||||
-->
|
||||
<input type="text" id="test_id1" value="id1_initial">
|
||||
|
||||
|
|
|
@ -11,7 +11,10 @@ import platform
|
|||
import subprocess
|
||||
import sys
|
||||
import uuid
|
||||
import __builtin__
|
||||
try:
|
||||
import builtins
|
||||
except ImportError:
|
||||
import __builtin__ as builtins
|
||||
|
||||
from types import ModuleType
|
||||
|
||||
|
@ -434,4 +437,4 @@ class ImportHook(object):
|
|||
|
||||
|
||||
# Install our hook
|
||||
__builtin__.__import__ = ImportHook(__builtin__.__import__)
|
||||
builtins.__import__ = ImportHook(builtins.__import__)
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "mozilla/BasePrincipal.h"
|
||||
|
||||
#include "nsDocShell.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsIObjectInputStream.h"
|
||||
#include "nsIObjectOutputStream.h"
|
||||
#include "nsIStandardURL.h"
|
||||
|
@ -22,8 +21,6 @@
|
|||
#include "mozilla/NullPrincipal.h"
|
||||
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
||||
#include "mozilla/dom/ChromeUtils.h"
|
||||
#include "mozilla/dom/CSPDictionariesBinding.h"
|
||||
#include "mozilla/dom/nsCSPContext.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -165,88 +162,6 @@ BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aReport,
|
|||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp) {
|
||||
NS_IF_ADDREF(*aCsp = mCSP);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) {
|
||||
// Never destroy an existing CSP on the principal.
|
||||
// This method should only be called in rare cases.
|
||||
|
||||
MOZ_ASSERT(!mCSP, "do not destroy an existing CSP");
|
||||
if (mCSP) {
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
mCSP = aCsp;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::EnsureCSP(dom::Document* aDocument,
|
||||
nsIContentSecurityPolicy** aCSP) {
|
||||
if (mCSP) {
|
||||
// if there is a CSP already associated with this principal
|
||||
// then just return that - do not overwrite it!!!
|
||||
NS_IF_ADDREF(*aCSP = mCSP);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
mCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Store the request context for violation reports
|
||||
rv = aDocument ? mCSP->SetRequestContext(aDocument, nullptr)
|
||||
: mCSP->SetRequestContext(nullptr, this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_IF_ADDREF(*aCSP = mCSP);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) {
|
||||
NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::EnsurePreloadCSP(dom::Document* aDocument,
|
||||
nsIContentSecurityPolicy** aPreloadCSP) {
|
||||
if (mPreloadCSP) {
|
||||
// if there is a speculative CSP already associated with this principal
|
||||
// then just return that - do not overwrite it!!!
|
||||
NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
mPreloadCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Store the request context for violation reports
|
||||
rv = aDocument ? mPreloadCSP->SetRequestContext(aDocument, nullptr)
|
||||
: mPreloadCSP->SetRequestContext(nullptr, this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::GetCspJSON(nsAString& outCSPinJSON) {
|
||||
outCSPinJSON.Truncate();
|
||||
dom::CSPPolicies jsonPolicies;
|
||||
|
||||
if (!mCSP) {
|
||||
jsonPolicies.ToJSON(outCSPinJSON);
|
||||
return NS_OK;
|
||||
}
|
||||
return mCSP->ToJSON(outCSPinJSON);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::GetIsNullPrincipal(bool* aResult) {
|
||||
*aResult = Kind() == eNullPrincipal;
|
||||
|
@ -509,20 +424,6 @@ void BasePrincipal::FinishInit(BasePrincipal* aOther,
|
|||
|
||||
mOriginNoSuffix = aOther->mOriginNoSuffix;
|
||||
mHasExplicitDomain = aOther->mHasExplicitDomain;
|
||||
|
||||
if (aOther->mPreloadCSP) {
|
||||
mPreloadCSP = do_CreateInstance("@mozilla.org/cspcontext;1");
|
||||
nsCSPContext* preloadCSP = static_cast<nsCSPContext*>(mPreloadCSP.get());
|
||||
preloadCSP->InitFromOther(
|
||||
static_cast<nsCSPContext*>(aOther->mPreloadCSP.get()), nullptr, this);
|
||||
}
|
||||
|
||||
if (aOther->mCSP) {
|
||||
mCSP = do_CreateInstance("@mozilla.org/cspcontext;1");
|
||||
nsCSPContext* csp = static_cast<nsCSPContext*>(mCSP.get());
|
||||
csp->InitFromOther(static_cast<nsCSPContext*>(aOther->mCSP.get()), nullptr,
|
||||
this);
|
||||
}
|
||||
}
|
||||
|
||||
bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {
|
||||
|
|
|
@ -106,14 +106,6 @@ class BasePrincipal : public nsJSPrincipals {
|
|||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report,
|
||||
bool allowIfInheritsPrincipal) final;
|
||||
NS_IMETHOD GetAddonPolicy(nsISupports** aResult) final;
|
||||
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
|
||||
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
|
||||
NS_IMETHOD EnsureCSP(dom::Document* aDocument,
|
||||
nsIContentSecurityPolicy** aCSP) override;
|
||||
NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
|
||||
NS_IMETHOD EnsurePreloadCSP(dom::Document* aDocument,
|
||||
nsIContentSecurityPolicy** aCSP) override;
|
||||
NS_IMETHOD GetCspJSON(nsAString& outCSPinJSON) override;
|
||||
NS_IMETHOD GetIsNullPrincipal(bool* aResult) override;
|
||||
NS_IMETHOD GetIsCodebasePrincipal(bool* aResult) override;
|
||||
NS_IMETHOD GetIsExpandedPrincipal(bool* aResult) override;
|
||||
|
@ -249,9 +241,6 @@ class BasePrincipal : public nsJSPrincipals {
|
|||
void FinishInit(BasePrincipal* aOther,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> mCSP;
|
||||
nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
|
||||
|
||||
private:
|
||||
static already_AddRefed<BasePrincipal> CreateCodebasePrincipal(
|
||||
nsIURI* aURI, const OriginAttributes& aAttrs,
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "js/Wrapper.h"
|
||||
|
||||
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
||||
#include "mozilla/dom/nsCSPContext.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/ExtensionPolicyService.h"
|
||||
|
@ -51,10 +50,6 @@ NS_IMPL_CI_INTERFACE_GETTER(ContentPrincipal, nsIPrincipal, nsISerializable)
|
|||
ContentPrincipal::ContentPrincipal() : BasePrincipal(eCodebasePrincipal) {}
|
||||
|
||||
ContentPrincipal::~ContentPrincipal() {
|
||||
// let's clear the principal within the csp to avoid a tangling pointer
|
||||
if (mCSP) {
|
||||
static_cast<nsCSPContext*>(mCSP.get())->clearLoadingPrincipal();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult ContentPrincipal::Init(nsIURI* aCodebase,
|
||||
|
@ -581,8 +576,18 @@ ContentPrincipal::Read(nsIObjectInputStream* aStream) {
|
|||
bool ok = attrs.PopulateFromSuffix(suffix);
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
|
||||
|
||||
rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Since Bug 965637 we do not serialize the CSP within the
|
||||
// Principal anymore. Nevertheless there might still be
|
||||
// serialized Principals that do have a serialized CSP.
|
||||
// For now, we just read the CSP here but do not actually
|
||||
// consume it. Please note that we deliberately ignore
|
||||
// the return value to avoid CSP deserialization problems.
|
||||
// After Bug 1508939 we will have a new serialization for
|
||||
// Principals which allows us to update the code here.
|
||||
// Additionally, the format for serialized CSPs changed
|
||||
// within Bug 965637 which also can cause failures within
|
||||
// the CSP deserialization code.
|
||||
Unused << NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
|
||||
|
||||
nsAutoCString originNoSuffix;
|
||||
rv = GenerateOriginNoSuffixFromURI(codebase, originNoSuffix);
|
||||
|
@ -591,13 +596,6 @@ ContentPrincipal::Read(nsIObjectInputStream* aStream) {
|
|||
rv = Init(codebase, attrs, originNoSuffix);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCSP = do_QueryInterface(supports, &rv);
|
||||
// make sure setRequestContext is called after Init(),
|
||||
// to make sure the principals URI been initalized.
|
||||
if (mCSP) {
|
||||
mCSP->SetRequestContext(nullptr, this);
|
||||
}
|
||||
|
||||
// Note: we don't call SetDomain here because we don't need the wrapper
|
||||
// recomputation code there (we just created this principal).
|
||||
mDomain = domain;
|
||||
|
@ -629,8 +627,14 @@ ContentPrincipal::Write(nsIObjectOutputStream* aStream) {
|
|||
rv = aStream->WriteStringZ(suffix.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Since Bug 965637 we do not serialize the CSP within the
|
||||
// Principal anymore. Nevertheless there might still be
|
||||
// serialized Principals that do have a serialized CSP.
|
||||
// For now, we just write a null CSP here to avoid breakage.
|
||||
// After Bug 1508939 we will have a new serialization for
|
||||
// Principals which allows us to update the code here.
|
||||
rv = NS_WriteOptionalCompoundObject(
|
||||
aStream, mCSP, NS_GET_IID(nsIContentSecurityPolicy), true);
|
||||
aStream, nullptr, NS_GET_IID(nsIContentSecurityPolicy), true);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -169,6 +169,14 @@ bool ExpandedPrincipal::AddonAllowsLoad(nsIURI* aURI,
|
|||
return false;
|
||||
}
|
||||
|
||||
void ExpandedPrincipal::SetCsp(nsIContentSecurityPolicy* aCSP) { mCSP = aCSP; }
|
||||
|
||||
NS_IMETHODIMP
|
||||
ExpandedPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp) {
|
||||
NS_IF_ADDREF(*aCsp = mCSP);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPrincipal* ExpandedPrincipal::PrincipalToInherit(nsIURI* aRequestedURI) {
|
||||
if (aRequestedURI) {
|
||||
// If a given sub-principal subsumes the given URI, use that principal for
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
|
||||
class nsIContentSecurityPolicy;
|
||||
|
||||
class ExpandedPrincipal : public nsIExpandedPrincipal,
|
||||
public mozilla::BasePrincipal {
|
||||
public:
|
||||
|
@ -46,6 +48,8 @@ class ExpandedPrincipal : public nsIExpandedPrincipal,
|
|||
|
||||
bool AddonAllowsLoad(nsIURI* aURI, bool aExplicit = false);
|
||||
|
||||
void SetCsp(nsIContentSecurityPolicy* aCSP);
|
||||
|
||||
// Returns the principal to inherit when this principal requests the given
|
||||
// URL. See BasePrincipal::PrincipalToInherit.
|
||||
nsIPrincipal* PrincipalToInherit(nsIURI* aRequestedURI = nullptr);
|
||||
|
@ -64,6 +68,7 @@ class ExpandedPrincipal : public nsIExpandedPrincipal,
|
|||
|
||||
private:
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>> mPrincipals;
|
||||
nsCOMPtr<nsIContentSecurityPolicy> mCSP;
|
||||
};
|
||||
|
||||
#define NS_EXPANDEDPRINCIPAL_CONTRACTID "@mozilla.org/expandedprincipal;1"
|
||||
|
|
|
@ -133,20 +133,6 @@ nsresult NullPrincipal::GetScriptLocation(nsACString& aStr) {
|
|||
|
||||
uint32_t NullPrincipal::GetHashValue() { return (NS_PTR_TO_INT32(this) >> 2); }
|
||||
|
||||
NS_IMETHODIMP
|
||||
NullPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) {
|
||||
// Never destroy an existing CSP on the principal.
|
||||
// This method should only be called in rare cases.
|
||||
|
||||
MOZ_ASSERT(!mCSP, "do not destroy an existing CSP");
|
||||
if (mCSP) {
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
mCSP = aCsp;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NullPrincipal::GetURI(nsIURI** aURI) {
|
||||
nsCOMPtr<nsIURI> uri = mURI;
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "nsJSPrincipals.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
|
||||
|
@ -48,7 +47,6 @@ class NullPrincipal final : public BasePrincipal {
|
|||
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
|
||||
uint32_t GetHashValue() override;
|
||||
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
|
||||
NS_IMETHOD GetURI(nsIURI** aURI) override;
|
||||
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
|
||||
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
|
||||
|
|
|
@ -51,40 +51,6 @@ SystemPrincipal::GetURI(nsIURI** aURI) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SystemPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp) {
|
||||
*aCsp = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SystemPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) {
|
||||
// Never destroy an existing CSP on the principal.
|
||||
// This method should only be called in rare cases.
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SystemPrincipal::EnsureCSP(dom::Document* aDocument,
|
||||
nsIContentSecurityPolicy** aCSP) {
|
||||
// CSP on a system principal makes no sense
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SystemPrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) {
|
||||
*aPreloadCSP = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SystemPrincipal::EnsurePreloadCSP(dom::Document* aDocument,
|
||||
nsIContentSecurityPolicy** aPreloadCSP) {
|
||||
// CSP on a system principal makes no sense
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SystemPrincipal::GetDomain(nsIURI** aDomain) {
|
||||
*aDomain = nullptr;
|
||||
|
|
|
@ -38,13 +38,6 @@ class SystemPrincipal final : public BasePrincipal {
|
|||
NS_IMETHOD GetURI(nsIURI** aURI) override;
|
||||
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
|
||||
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
|
||||
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
|
||||
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
|
||||
NS_IMETHOD EnsureCSP(dom::Document* aDocument,
|
||||
nsIContentSecurityPolicy** aCSP) override;
|
||||
NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
|
||||
NS_IMETHOD EnsurePreloadCSP(dom::Document* aDocument,
|
||||
nsIContentSecurityPolicy** aCSP) override;
|
||||
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
|
||||
NS_IMETHOD GetAddonId(nsAString& aAddonId) override;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
/* Defines the abstract interface for a principal. */
|
||||
|
||||
#include "nsIContentSecurityPolicy.idl"
|
||||
#include "nsISerializable.idl"
|
||||
|
||||
%{C++
|
||||
|
@ -37,9 +38,6 @@ class OriginAttributes;
|
|||
%}
|
||||
|
||||
interface nsIURI;
|
||||
interface nsIContentSecurityPolicy;
|
||||
|
||||
webidl Document;
|
||||
|
||||
[ptr] native JSContext(JSContext);
|
||||
[ptr] native JSPrincipals(JSPrincipals);
|
||||
|
@ -150,53 +148,6 @@ interface nsIPrincipal : nsISerializable
|
|||
void checkMayLoad(in nsIURI uri, in boolean report,
|
||||
in boolean allowIfInheritsPrincipal);
|
||||
|
||||
/**
|
||||
* A Content Security Policy associated with this principal. Use this function to
|
||||
* query the associated CSP with this principal, but please *only* use this
|
||||
* function to *set* a CSP when you know exactly what you are doing.
|
||||
* Most likely you want to call ensureCSP instead of setCSP.
|
||||
*/
|
||||
readonly attribute nsIContentSecurityPolicy csp;
|
||||
[noscript] void setCsp(in nsIContentSecurityPolicy aCsp);
|
||||
|
||||
/*
|
||||
* Use this function to query a CSP associated with this principal.
|
||||
* If no CSP is associated with this principal then one is created
|
||||
* internally and setRequestContext is called on the CSP using aDocument.
|
||||
*
|
||||
* Please note if aDocument is null, then setRequestContext on the
|
||||
* CSP object is called using the current principal.
|
||||
*/
|
||||
[noscript] nsIContentSecurityPolicy ensureCSP(in Document aDocument);
|
||||
|
||||
/**
|
||||
* A speculative Content Security Policy associated with this
|
||||
* principal. Set during speculative loading (preloading) and
|
||||
* used *only* for preloads.
|
||||
*
|
||||
* If you want to query the CSP associated with that principal,
|
||||
* then this is *not* what you want. Instead query 'csp'.
|
||||
*/
|
||||
[noscript] readonly attribute nsIContentSecurityPolicy preloadCsp;
|
||||
|
||||
/*
|
||||
* Use this function to query a speculative CSP associated with this
|
||||
* principal. If no speculative CSP is associated with this principal
|
||||
* then one is created internally and setRequestContext is called on
|
||||
* the CSP using aDocument.
|
||||
*
|
||||
* Please note if aDocument is null, then setRequestContext on the
|
||||
* speculative CSP object is called using the current principal.
|
||||
*/
|
||||
[noscript] nsIContentSecurityPolicy ensurePreloadCSP(in Document aDocument);
|
||||
|
||||
/**
|
||||
* The CSP of the principal in JSON notation.
|
||||
* Note, that the CSP itself is not exposed to JS, but script
|
||||
* should be able to obtain a JSON representation of the CSP.
|
||||
*/
|
||||
readonly attribute AString cspJSON;
|
||||
|
||||
/**
|
||||
* A dictionary of the non-default origin attributes associated with this
|
||||
* nsIPrincipal.
|
||||
|
@ -361,4 +312,24 @@ interface nsIExpandedPrincipal : nsISupports
|
|||
*/
|
||||
[noscript, notxpcom, nostdcall]
|
||||
PrincipalArray AllowList();
|
||||
|
||||
|
||||
/**
|
||||
* Bug 1548468: Move CSP off ExpandedPrincipal.
|
||||
*
|
||||
* A Content Security Policy associated with this principal. Use this function
|
||||
* to query the associated CSP with this principal.
|
||||
*/
|
||||
readonly attribute nsIContentSecurityPolicy csp;
|
||||
|
||||
%{ C++
|
||||
inline already_AddRefed<nsIContentSecurityPolicy> GetCsp()
|
||||
{
|
||||
nsCOMPtr<nsIContentSecurityPolicy> result;
|
||||
mozilla::DebugOnly<nsresult> rv = GetCsp(getter_AddRefs(result));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
return result.forget();
|
||||
}
|
||||
%}
|
||||
|
||||
};
|
||||
|
|
|
@ -123,10 +123,10 @@ bool nsJSPrincipals::ReadPrincipals(JSContext* aCx,
|
|||
return ReadKnownPrincipalType(aCx, aReader, tag, aOutPrincipals);
|
||||
}
|
||||
|
||||
static bool ReadPrincipalInfo(
|
||||
JSStructuredCloneReader* aReader, OriginAttributes& aAttrs,
|
||||
nsACString& aSpec, nsACString& aOriginNoSuffix, nsACString& aBaseDomain,
|
||||
nsTArray<ContentSecurityPolicy>* aPolicies = nullptr) {
|
||||
static bool ReadPrincipalInfo(JSStructuredCloneReader* aReader,
|
||||
OriginAttributes& aAttrs, nsACString& aSpec,
|
||||
nsACString& aOriginNoSuffix,
|
||||
nsACString& aBaseDomain) {
|
||||
uint32_t suffixLength, specLength;
|
||||
if (!JS_ReadUint32Pair(aReader, &suffixLength, &specLength)) {
|
||||
return false;
|
||||
|
@ -153,13 +153,14 @@ static bool ReadPrincipalInfo(
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t originNoSuffixLength, policyCount;
|
||||
if (!JS_ReadUint32Pair(aReader, &originNoSuffixLength, &policyCount)) {
|
||||
uint32_t originNoSuffixLength, dummy;
|
||||
if (!JS_ReadUint32Pair(aReader, &originNoSuffixLength, &dummy)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aPolicies) {
|
||||
MOZ_ASSERT(policyCount == 0);
|
||||
MOZ_ASSERT(dummy == 0);
|
||||
if (dummy != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aOriginNoSuffix.SetLength(originNoSuffixLength, fallible)) {
|
||||
|
@ -171,29 +172,6 @@ static bool ReadPrincipalInfo(
|
|||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < policyCount; i++) {
|
||||
uint32_t policyLength, reportAndMeta;
|
||||
if (!JS_ReadUint32Pair(aReader, &policyLength, &reportAndMeta)) {
|
||||
return false;
|
||||
}
|
||||
bool reportOnly = reportAndMeta & 1;
|
||||
bool deliveredViaMetaTag = reportAndMeta & 2;
|
||||
|
||||
nsAutoCString policyStr;
|
||||
if (!policyStr.SetLength(policyLength, fallible)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JS_ReadBytes(aReader, policyStr.BeginWriting(), policyLength)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aPolicies) {
|
||||
aPolicies->AppendElement(ContentSecurityPolicy(
|
||||
NS_ConvertUTF8toUTF16(policyStr), reportOnly, deliveredViaMetaTag));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t baseDomainIsVoid, baseDomainLength;
|
||||
if (!JS_ReadUint32Pair(aReader, &baseDomainIsVoid, &baseDomainLength)) {
|
||||
return false;
|
||||
|
@ -259,9 +237,7 @@ static bool ReadPrincipalInfo(JSStructuredCloneReader* aReader, uint32_t aTag,
|
|||
nsAutoCString spec;
|
||||
nsAutoCString originNoSuffix;
|
||||
nsAutoCString baseDomain;
|
||||
nsTArray<ContentSecurityPolicy> policies;
|
||||
if (!ReadPrincipalInfo(aReader, attrs, spec, originNoSuffix, baseDomain,
|
||||
&policies)) {
|
||||
if (!ReadPrincipalInfo(aReader, attrs, spec, originNoSuffix, baseDomain)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -275,7 +251,7 @@ static bool ReadPrincipalInfo(JSStructuredCloneReader* aReader, uint32_t aTag,
|
|||
|
||||
// XXX: Do we care about mDomain for structured clone?
|
||||
aInfo = ContentPrincipalInfo(attrs, originNoSuffix, spec, Nothing(),
|
||||
std::move(policies), baseDomain);
|
||||
baseDomain);
|
||||
} else {
|
||||
#ifdef FUZZING
|
||||
return false;
|
||||
|
@ -344,37 +320,23 @@ bool nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool WritePrincipalInfo(
|
||||
JSStructuredCloneWriter* aWriter, const OriginAttributes& aAttrs,
|
||||
const nsCString& aSpec, const nsCString& aOriginNoSuffix,
|
||||
const nsCString& aBaseDomain,
|
||||
const nsTArray<ContentSecurityPolicy>* aPolicies = nullptr) {
|
||||
static bool WritePrincipalInfo(JSStructuredCloneWriter* aWriter,
|
||||
const OriginAttributes& aAttrs,
|
||||
const nsCString& aSpec,
|
||||
const nsCString& aOriginNoSuffix,
|
||||
const nsCString& aBaseDomain) {
|
||||
nsAutoCString suffix;
|
||||
aAttrs.CreateSuffix(suffix);
|
||||
size_t policyCount = aPolicies ? aPolicies->Length() : 0;
|
||||
|
||||
if (!(JS_WriteUint32Pair(aWriter, suffix.Length(), aSpec.Length()) &&
|
||||
JS_WriteBytes(aWriter, suffix.get(), suffix.Length()) &&
|
||||
JS_WriteBytes(aWriter, aSpec.get(), aSpec.Length()) &&
|
||||
JS_WriteUint32Pair(aWriter, aOriginNoSuffix.Length(), policyCount) &&
|
||||
JS_WriteUint32Pair(aWriter, aOriginNoSuffix.Length(), 0) &&
|
||||
JS_WriteBytes(aWriter, aOriginNoSuffix.get(),
|
||||
aOriginNoSuffix.Length()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < policyCount; i++) {
|
||||
nsCString policy;
|
||||
CopyUTF16toUTF8((*aPolicies)[i].policy(), policy);
|
||||
uint32_t reportAndMeta =
|
||||
((*aPolicies)[i].reportOnlyFlag() ? 1 : 0) |
|
||||
((*aPolicies)[i].deliveredViaMetaTagFlag() ? 2 : 0);
|
||||
if (!(JS_WriteUint32Pair(aWriter, policy.Length(), reportAndMeta) &&
|
||||
JS_WriteBytes(aWriter, PromiseFlatCString(policy).get(),
|
||||
policy.Length()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (aBaseDomain.IsVoid()) {
|
||||
return JS_WriteUint32Pair(aWriter, 1, 0);
|
||||
}
|
||||
|
@ -413,8 +375,7 @@ static bool WritePrincipalInfo(JSStructuredCloneWriter* aWriter,
|
|||
const ContentPrincipalInfo& cInfo = aInfo;
|
||||
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_CONTENT_PRINCIPAL, 0) &&
|
||||
WritePrincipalInfo(aWriter, cInfo.attrs(), cInfo.spec(),
|
||||
cInfo.originNoSuffix(), cInfo.baseDomain(),
|
||||
&(cInfo.securityPolicies()));
|
||||
cInfo.originNoSuffix(), cInfo.baseDomain());
|
||||
}
|
||||
|
||||
bool nsJSPrincipals::write(JSContext* aCx, JSStructuredCloneWriter* aWriter) {
|
||||
|
|
|
@ -274,97 +274,6 @@ nsScriptSecurityManager::GetChannelResultPrincipals(
|
|||
aStoragePrincipal);
|
||||
}
|
||||
|
||||
static void InheritAndSetCSPOnPrincipalIfNeeded(nsIChannel* aChannel,
|
||||
nsIPrincipal* aPrincipal) {
|
||||
// loading a data: URI into an iframe, or loading frame[srcdoc] need
|
||||
// to inherit the CSP (see Bug 1073952, 1381761).
|
||||
MOZ_ASSERT(aChannel && aPrincipal, "need a valid channel and principal");
|
||||
if (!aChannel) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
if (loadInfo->GetExternalContentPolicyType() !=
|
||||
nsIContentPolicy::TYPE_SUBDOCUMENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
nsAutoCString URISpec;
|
||||
rv = uri->GetSpec(URISpec);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
bool isSrcDoc = URISpec.EqualsLiteral("about:srcdoc");
|
||||
bool isData = (NS_SUCCEEDED(uri->SchemeIs("data", &isData)) && isData);
|
||||
|
||||
if (!isSrcDoc && !isData) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principalToInherit =
|
||||
loadInfo->FindPrincipalToInherit(aChannel);
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> originalCSP;
|
||||
principalToInherit->GetCsp(getter_AddRefs(originalCSP));
|
||||
if (!originalCSP) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if the principalToInherit had a CSP, add it to the before
|
||||
// created NullPrincipal (unless it already has one)
|
||||
MOZ_ASSERT(aPrincipal->GetIsNullPrincipal(),
|
||||
"inheriting the CSP only valid for NullPrincipal");
|
||||
nsCOMPtr<nsIContentSecurityPolicy> nullPrincipalCSP;
|
||||
aPrincipal->GetCsp(getter_AddRefs(nullPrincipalCSP));
|
||||
if (nullPrincipalCSP) {
|
||||
MOZ_ASSERT(nsCSPContext::Equals(originalCSP, nullPrincipalCSP));
|
||||
// CSPs are equal, no need to set it again.
|
||||
return;
|
||||
}
|
||||
|
||||
// After 965637 all that magical CSP inheritance goes away. For now,
|
||||
// we have to create a clone of the current CSP and have to manually
|
||||
// set it on the Principal.
|
||||
uint32_t count = 0;
|
||||
rv = originalCSP->GetPolicyCount(&count);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
// fast path: if there is nothing to inherit, we can return here.
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<nsCSPContext> newCSP = new nsCSPContext();
|
||||
nsWeakPtr loadingContext =
|
||||
static_cast<nsCSPContext*>(originalCSP.get())->GetLoadingContext();
|
||||
nsCOMPtr<Document> doc = do_QueryReferent(loadingContext);
|
||||
|
||||
rv = doc ? newCSP->SetRequestContext(doc, nullptr)
|
||||
: newCSP->SetRequestContext(nullptr, aPrincipal);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
const nsCSPPolicy* policy = originalCSP->GetPolicy(i);
|
||||
MOZ_ASSERT(policy);
|
||||
|
||||
nsAutoString policyString;
|
||||
policy->toString(policyString);
|
||||
|
||||
rv = newCSP->AppendPolicy(policyString, policy->getReportOnlyFlag(),
|
||||
policy->getDeliveredViaMetaTagFlag());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
aPrincipal->SetCsp(newCSP);
|
||||
}
|
||||
|
||||
nsresult nsScriptSecurityManager::GetChannelResultPrincipal(
|
||||
nsIChannel* aChannel, nsIPrincipal** aPrincipal, bool aIgnoreSandboxing) {
|
||||
MOZ_ASSERT(aChannel, "Must have channel!");
|
||||
|
@ -391,7 +300,6 @@ nsresult nsScriptSecurityManager::GetChannelResultPrincipal(
|
|||
nsCOMPtr<nsIPrincipal> sandboxedLoadingPrincipal =
|
||||
loadInfo->GetSandboxedLoadingPrincipal();
|
||||
MOZ_ASSERT(sandboxedLoadingPrincipal);
|
||||
InheritAndSetCSPOnPrincipalIfNeeded(aChannel, sandboxedLoadingPrincipal);
|
||||
sandboxedLoadingPrincipal.forget(aPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -433,10 +341,7 @@ nsresult nsScriptSecurityManager::GetChannelResultPrincipal(
|
|||
return NS_OK;
|
||||
}
|
||||
}
|
||||
nsresult rv = GetChannelURIPrincipal(aChannel, aPrincipal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
InheritAndSetCSPOnPrincipalIfNeeded(aChannel, *aPrincipal);
|
||||
return NS_OK;
|
||||
return GetChannelURIPrincipal(aChannel, aPrincipal);
|
||||
}
|
||||
|
||||
/* The principal of the URI that this channel is loading. This is never
|
||||
|
@ -494,16 +399,18 @@ NS_IMPL_ISUPPORTS(nsScriptSecurityManager, nsIScriptSecurityManager)
|
|||
bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
|
||||
JSContext* cx, JS::HandleValue aValue) {
|
||||
MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal = nsContentUtils::SubjectPrincipal();
|
||||
|
||||
#if defined(DEBUG) && !defined(ANDROID)
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal = nsContentUtils::SubjectPrincipal();
|
||||
nsContentSecurityManager::AssertEvalNotUsingSystemPrincipal(subjectPrincipal,
|
||||
cx);
|
||||
#endif
|
||||
|
||||
// Get the window, if any, corresponding to the current global
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
nsresult rv = subjectPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get CSP from principal.");
|
||||
if (nsGlobalWindowInner* win = xpc::CurrentWindowOrNull(cx)) {
|
||||
csp = win->GetCsp();
|
||||
}
|
||||
|
||||
// don't do anything unless there's a CSP
|
||||
if (!csp) return true;
|
||||
|
@ -519,7 +426,7 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
|
|||
|
||||
bool evalOK = true;
|
||||
bool reportViolation = false;
|
||||
rv = csp->GetAllowsEval(&reportViolation, &evalOK);
|
||||
nsresult rv = csp->GetAllowsEval(&reportViolation, &evalOK);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("CSP: failed to get allowsEval");
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
"babel-plugin-transform-imports": "^1.5.0",
|
||||
"codemirror": "^5.28.0",
|
||||
"devtools-environment": "^0.0.6",
|
||||
"devtools-launchpad": "^0.0.153",
|
||||
"devtools-launchpad": "^0.0.154",
|
||||
"devtools-linters": "^0.0.4",
|
||||
"devtools-reps": "0.23.0",
|
||||
"devtools-source-map": "0.16.0",
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"devtools-config": "^0.0.16",
|
||||
"devtools-launchpad": "^0.0.153",
|
||||
"devtools-launchpad": "^0.0.154",
|
||||
"devtools-license-check": "^0.7.0",
|
||||
"devtools-modules": "~1.1.0",
|
||||
"devtools-services": "^0.0.1",
|
||||
|
|
|
@ -15,7 +15,6 @@ import {
|
|||
getXHRBreakpoints,
|
||||
getSelectedSource,
|
||||
getBreakpointAtLocation,
|
||||
getConditionalPanelLocation,
|
||||
getBreakpointsForSource,
|
||||
getBreakpointsAtLine,
|
||||
} from "../../selectors";
|
||||
|
@ -27,7 +26,6 @@ import {
|
|||
disableBreakpoint,
|
||||
} from "./modify";
|
||||
import remapLocations from "./remapLocations";
|
||||
import { closeConditionalPanel } from "../ui";
|
||||
|
||||
// this will need to be changed so that addCLientBreakpoint is removed
|
||||
|
||||
|
@ -218,10 +216,6 @@ export function toggleBreakpointAtLine(cx: Context, line: number) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (getConditionalPanelLocation(getState())) {
|
||||
dispatch(closeConditionalPanel());
|
||||
}
|
||||
|
||||
const bp = getBreakpointAtLocation(state, { line, column: undefined });
|
||||
if (bp) {
|
||||
return dispatch(removeBreakpoint(cx, bp));
|
||||
|
|
|
@ -106,10 +106,15 @@ class Breakpoint extends PureComponent<Props> {
|
|||
};
|
||||
|
||||
onContextMenu = (event: MouseEvent) => {
|
||||
const { cx, breakpoint, breakpointActions } = this.props;
|
||||
const { cx, breakpoint, selectedSource, breakpointActions } = this.props;
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
showMenu(event, breakpointItems(cx, breakpoint, breakpointActions));
|
||||
const selectedLocation = getSelectedLocation(breakpoint, selectedSource);
|
||||
|
||||
showMenu(
|
||||
event,
|
||||
breakpointItems(cx, breakpoint, selectedLocation, breakpointActions)
|
||||
);
|
||||
};
|
||||
|
||||
addBreakpoint(props: Props) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import { showMenu } from "devtools-contextmenu";
|
|||
|
||||
import { getDocument } from "../../utils/editor";
|
||||
import { breakpointItems, createBreakpointItems } from "./menus/breakpoints";
|
||||
import { getSelectedLocation } from "../../utils/selected-location";
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
import type { ColumnBreakpoint as ColumnBreakpointType } from "../../selectors/visibleColumnBreakpoints";
|
||||
|
@ -101,12 +102,22 @@ export default class ColumnBreakpoint extends PureComponent<Props> {
|
|||
const {
|
||||
cx,
|
||||
columnBreakpoint: { breakpoint, location },
|
||||
source,
|
||||
breakpointActions,
|
||||
} = this.props;
|
||||
|
||||
const items = breakpoint
|
||||
? breakpointItems(cx, breakpoint, breakpointActions)
|
||||
: createBreakpointItems(cx, location, breakpointActions);
|
||||
let items = createBreakpointItems(cx, location, breakpointActions);
|
||||
|
||||
if (breakpoint) {
|
||||
const selectedLocation = getSelectedLocation(breakpoint, source);
|
||||
|
||||
items = breakpointItems(
|
||||
cx,
|
||||
breakpoint,
|
||||
selectedLocation,
|
||||
breakpointActions
|
||||
);
|
||||
}
|
||||
|
||||
showMenu(event, items);
|
||||
};
|
||||
|
|
|
@ -137,6 +137,7 @@ export class ConditionalPanel extends PureComponent<Props> {
|
|||
noHScroll: true,
|
||||
}
|
||||
);
|
||||
|
||||
if (this.input) {
|
||||
let parent: ?Node = this.input.parentNode;
|
||||
while (parent) {
|
||||
|
@ -158,7 +159,7 @@ export class ConditionalPanel extends PureComponent<Props> {
|
|||
}
|
||||
|
||||
createEditor = (input: ?HTMLTextAreaElement) => {
|
||||
const { log, editor } = this.props;
|
||||
const { log, editor, closeConditionalPanel } = this.props;
|
||||
|
||||
const codeMirror = editor.CodeMirror.fromTextArea(input, {
|
||||
mode: "javascript",
|
||||
|
@ -176,6 +177,8 @@ export class ConditionalPanel extends PureComponent<Props> {
|
|||
}
|
||||
});
|
||||
|
||||
codeMirror.on("blur", (cm, e) => closeConditionalPanel());
|
||||
|
||||
const codeMirrorWrapper = codeMirror.getWrapperElement();
|
||||
|
||||
codeMirrorWrapper.addEventListener("keydown", e => {
|
||||
|
@ -206,7 +209,6 @@ export class ConditionalPanel extends PureComponent<Props> {
|
|||
"log-point": log,
|
||||
})}
|
||||
onClick={() => this.keepFocusOnInput()}
|
||||
onBlur={this.props.closeConditionalPanel}
|
||||
ref={node => (this.panelNode = node)}
|
||||
>
|
||||
<div className="prompt">»</div>
|
||||
|
|
|
@ -61,11 +61,11 @@ export const editConditionalBreakpointItem = (
|
|||
|
||||
export const conditionalBreakpointItem = (
|
||||
breakpoint: Breakpoint,
|
||||
location: SourceLocation,
|
||||
breakpointActions: BreakpointItemActions
|
||||
) => {
|
||||
const {
|
||||
options: { condition },
|
||||
location,
|
||||
} = breakpoint;
|
||||
return condition
|
||||
? editConditionalBreakpointItem(location, breakpointActions)
|
||||
|
@ -98,11 +98,11 @@ export const editLogPointItem = (
|
|||
|
||||
export const logPointItem = (
|
||||
breakpoint: Breakpoint,
|
||||
location: SourceLocation,
|
||||
breakpointActions: BreakpointItemActions
|
||||
) => {
|
||||
const {
|
||||
options: { logValue },
|
||||
location,
|
||||
} = breakpoint;
|
||||
return logValue
|
||||
? editLogPointItem(location, breakpointActions)
|
||||
|
@ -133,6 +133,7 @@ export const toggleDisabledBreakpointItem = (
|
|||
export function breakpointItems(
|
||||
cx: Context,
|
||||
breakpoint: Breakpoint,
|
||||
selectedLocation: SourceLocation,
|
||||
breakpointActions: BreakpointItemActions
|
||||
) {
|
||||
const items = [
|
||||
|
@ -140,30 +141,19 @@ export function breakpointItems(
|
|||
toggleDisabledBreakpointItem(cx, breakpoint, breakpointActions),
|
||||
];
|
||||
|
||||
if (features.columnBreakpoints) {
|
||||
items.push(
|
||||
{ type: "separator" },
|
||||
removeBreakpointsOnLineItem(cx, breakpoint.location, breakpointActions),
|
||||
breakpoint.disabled
|
||||
? enableBreakpointsOnLineItem(
|
||||
cx,
|
||||
breakpoint.location,
|
||||
breakpointActions
|
||||
)
|
||||
: disableBreakpointsOnLineItem(
|
||||
cx,
|
||||
breakpoint.location,
|
||||
breakpointActions
|
||||
),
|
||||
{ type: "separator" }
|
||||
);
|
||||
}
|
||||
items.push(
|
||||
{ type: "separator" },
|
||||
removeBreakpointsOnLineItem(cx, selectedLocation, breakpointActions),
|
||||
breakpoint.disabled
|
||||
? enableBreakpointsOnLineItem(cx, selectedLocation, breakpointActions)
|
||||
: disableBreakpointsOnLineItem(cx, selectedLocation, breakpointActions),
|
||||
{ type: "separator" }
|
||||
);
|
||||
|
||||
items.push(conditionalBreakpointItem(breakpoint, breakpointActions));
|
||||
|
||||
if (features.logPoints) {
|
||||
items.push(logPointItem(breakpoint, breakpointActions));
|
||||
}
|
||||
items.push(
|
||||
conditionalBreakpointItem(breakpoint, selectedLocation, breakpointActions)
|
||||
);
|
||||
items.push(logPointItem(breakpoint, selectedLocation, breakpointActions));
|
||||
|
||||
return items;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
// Globals introduced in debugger-specific head.js
|
||||
"getContext": false,
|
||||
"getEditorLineGutter": false,
|
||||
"getCM": false,
|
||||
"getDebuggerSplitConsole": false,
|
||||
"hasConsoleMessage": false,
|
||||
|
@ -112,6 +113,7 @@
|
|||
"clickElement": false,
|
||||
"clickElementWithSelector": false,
|
||||
"clickDOMElement": false,
|
||||
"dblClickElement": false,
|
||||
"altClickElement": false,
|
||||
"rightClickElement": false,
|
||||
"rightClickEl": false,
|
||||
|
|
|
@ -689,6 +689,7 @@ skip-if = os == "win" # Bug 1448523, Bug 1448450
|
|||
[browser_dbg-breakpoints-actions.js]
|
||||
[browser_dbg-breakpoints-columns.js]
|
||||
[browser_dbg-breakpoints-cond.js]
|
||||
[browser_dbg-breakpoints-cond-source-maps.js]
|
||||
[browser_dbg-breakpoints-duplicate-functions.js]
|
||||
[browser_dbg-browser-content-toolbox.js]
|
||||
skip-if = !e10s || verify # This test is only valid in e10s
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/* 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/>. */
|
||||
|
||||
async function setLogPoint(dbg, index) {
|
||||
const gutterEl = await getEditorLineGutter(dbg, index);
|
||||
rightClickEl(dbg, gutterEl);
|
||||
selectContextMenuItem(
|
||||
dbg,
|
||||
`${selectors.addLogItem},${selectors.editLogItem}`
|
||||
);
|
||||
}
|
||||
|
||||
async function waitForConditionalPanelFocus(dbg) {
|
||||
await waitFor(() => dbg.win.document.activeElement.tagName === "TEXTAREA");
|
||||
}
|
||||
|
||||
function getConditionalPanel(dbg, line) {
|
||||
return getCM(dbg).doc.getLineHandle(line - 1).widgets[0];
|
||||
}
|
||||
|
||||
// Confirms that a conditional panel is opened at the
|
||||
// correct location in generated files.
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-sourcemaps.html", "entry.js");
|
||||
|
||||
await selectSource(dbg, "bundle.js");
|
||||
getCM(dbg).scrollIntoView({ line: 55, ch: 0 });
|
||||
|
||||
setLogPoint(dbg, 55);
|
||||
await waitForConditionalPanelFocus(dbg);
|
||||
ok(
|
||||
!!getConditionalPanel(dbg, 55),
|
||||
"conditional panel panel is open on line 55"
|
||||
);
|
||||
is(
|
||||
dbg.selectors.getConditionalPanelLocation().line,
|
||||
55,
|
||||
"conditional panel location is line 55"
|
||||
);
|
||||
});
|
|
@ -63,7 +63,6 @@ async function waitForConditionalPanelFocus(dbg) {
|
|||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-scripts.html", "simple2");
|
||||
await pushPref("devtools.debugger.features.column-breakpoints", true);
|
||||
await pushPref("devtools.debugger.features.log-points", true);
|
||||
|
||||
await selectSource(dbg, "simple2");
|
||||
await waitForSelectedSource(dbg, "simple2");
|
||||
|
@ -130,10 +129,10 @@ add_task(async function() {
|
|||
"TEXTAREA",
|
||||
"The textarea of conditional breakpoint panel is focused"
|
||||
);
|
||||
|
||||
|
||||
info("Click the conditional breakpoint in secondary pane");
|
||||
await clickElement(dbg, "conditionalBreakpointInSecPane");
|
||||
let conditonalPanel = findElement(dbg, "conditionalPanel");
|
||||
const conditonalPanel = findElement(dbg, "conditionalPanel");
|
||||
is(conditonalPanel, null, "The conditional breakpoint panel is closed");
|
||||
|
||||
rightClickElement(dbg, "breakpointItem", 2);
|
||||
|
@ -162,9 +161,9 @@ add_task(async function() {
|
|||
"TEXTAREA",
|
||||
"The textarea of logpoint panel is focused"
|
||||
);
|
||||
|
||||
|
||||
info("Click the logpoint in secondary pane");
|
||||
await clickElement(dbg, "logPointInSecPane");
|
||||
let logPointPanel = findElement(dbg, "logPointPanel");
|
||||
const logPointPanel = findElement(dbg, "logPointPanel");
|
||||
is(logPointPanel, null, "The logpoint panel is closed");
|
||||
});
|
||||
|
|
|
@ -1154,6 +1154,11 @@ function isVisible(outerEl, innerEl) {
|
|||
return visible;
|
||||
}
|
||||
|
||||
async function getEditorLineGutter(dbg, line) {
|
||||
const lineEl = await getEditorLineEl(dbg, line);
|
||||
return lineEl.firstChild;
|
||||
}
|
||||
|
||||
async function getEditorLineEl(dbg, line) {
|
||||
let el = await codeMirrorGutterElement(dbg, line);
|
||||
while (el && !el.matches(".CodeMirror-code > div")) {
|
||||
|
|
|
@ -3273,12 +3273,10 @@ devtools-config@^0.0.16:
|
|||
devtools-connection@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/devtools-connection/-/devtools-connection-1.0.7.tgz#16f23256f842dce339038cdc273c49c473ef83e0"
|
||||
integrity sha512-SrBHnM4nVhTrSfI4WnqcmppDOwB5iQvoEjqVNpwv63puGdKGtcdfWqv4+4gqfRYKHrdGB8tJfWJV2n+EyXb1Xw==
|
||||
|
||||
devtools-contextmenu@~1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/devtools-contextmenu/-/devtools-contextmenu-1.0.6.tgz#db31a6e5c90a7efeeb84fd156bd312633e642006"
|
||||
integrity sha512-5hYcY0RHkFeStvpA+Kyg1K5n0KuCuAntzHGID0xmwJsSjNrU5fs4gEEVk6BAOtW92IMSpdJ8qA8LIi+s6LkQXQ==
|
||||
devtools-contextmenu@~1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/devtools-contextmenu/-/devtools-contextmenu-1.0.7.tgz#dd56353a706c3be4cd06d49d6da6dc5219254c90"
|
||||
dependencies:
|
||||
devtools-modules "~1.1.3"
|
||||
|
||||
|
@ -3290,10 +3288,9 @@ devtools-environment@^0.0.6:
|
|||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/devtools-environment/-/devtools-environment-0.0.6.tgz#11584f5b1ead784c2356d8da647a630fed591a4e"
|
||||
|
||||
devtools-launchpad@^0.0.153:
|
||||
version "0.0.153"
|
||||
resolved "https://registry.yarnpkg.com/devtools-launchpad/-/devtools-launchpad-0.0.153.tgz#e310d4dfd67206b1ad2f59aabd2cffe885ae97ef"
|
||||
integrity sha512-i4v+Wf0ia9eGAryEKKMGvPfGvdj4WMLsNYxMmWUnfMNqGitlgyFxD3f5oZO7yNQgY6iX7P5vczxceJILsag57g==
|
||||
devtools-launchpad@^0.0.154:
|
||||
version "0.0.154"
|
||||
resolved "https://registry.yarnpkg.com/devtools-launchpad/-/devtools-launchpad-0.0.154.tgz#ee408dcae5b5e36eca9eb55338eeaf6920a46bf7"
|
||||
dependencies:
|
||||
amd-loader "0.0.8"
|
||||
autoprefixer "^7.1.2"
|
||||
|
@ -3319,7 +3316,7 @@ devtools-launchpad@^0.0.153:
|
|||
debug "^3.1.0"
|
||||
devtools-config "^0.0.16"
|
||||
devtools-connection "^1.0.7"
|
||||
devtools-contextmenu "~1.0.6"
|
||||
devtools-contextmenu "~1.0.7"
|
||||
devtools-environment "^0.0.5"
|
||||
devtools-license-check "^0.7.0"
|
||||
devtools-mc-assets "^0.0.7"
|
||||
|
@ -3414,7 +3411,6 @@ devtools-modules@~1.1.0:
|
|||
devtools-modules@~1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/devtools-modules/-/devtools-modules-1.1.3.tgz#4fbeee232263794bd3dd5b314c1a0ae28d76ea6f"
|
||||
integrity sha512-2bwfU72vwDcPCzLgXcK/rdtsmi9oWV764vxKttQdY43a7euwo94oCWOKfTOEXJG6HVgxMlYk87+/8QN9ELz9jQ==
|
||||
dependencies:
|
||||
devtools-services "0.0.1"
|
||||
punycode "^2.1.0"
|
||||
|
@ -3510,7 +3506,6 @@ domelementtype@1, domelementtype@^1.3.0:
|
|||
domelementtype@^1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
|
||||
integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
|
||||
|
||||
domelementtype@~1.1.1:
|
||||
version "1.1.3"
|
||||
|
@ -3871,7 +3866,6 @@ eslint-config-prettier@^4.0.0:
|
|||
eslint-import-resolver-node@^0.3.2:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a"
|
||||
integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==
|
||||
dependencies:
|
||||
debug "^2.6.9"
|
||||
resolve "^1.5.0"
|
||||
|
@ -3879,7 +3873,6 @@ eslint-import-resolver-node@^0.3.2:
|
|||
eslint-module-utils@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz#546178dab5e046c8b562bbb50705e2456d7bda49"
|
||||
integrity sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w==
|
||||
dependencies:
|
||||
debug "^2.6.8"
|
||||
pkg-dir "^2.0.0"
|
||||
|
@ -3903,7 +3896,6 @@ eslint-plugin-flowtype@^3.0.0:
|
|||
eslint-plugin-import@^2.16.0:
|
||||
version "2.16.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz#97ac3e75d0791c4fac0e15ef388510217be7f66f"
|
||||
integrity sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==
|
||||
dependencies:
|
||||
contains-path "^0.1.0"
|
||||
debug "^2.6.9"
|
||||
|
@ -3944,7 +3936,6 @@ eslint-plugin-mozilla@1.1.3:
|
|||
eslint-plugin-mozilla@1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-mozilla/-/eslint-plugin-mozilla-1.2.1.tgz#8aa80dca43bd45f300188d4ee53bc5a983aac0ba"
|
||||
integrity sha512-i6SAWTPgKI6T50L6Gy41efR3StjPGR3IWkFOW/4aGsJtpl+OmJVaOmUfhp5PGis3ZbDisNvQ/vzLiNicAWC7nw==
|
||||
dependencies:
|
||||
htmlparser2 "3.10.1"
|
||||
ini-parser "0.0.2"
|
||||
|
@ -4623,7 +4614,6 @@ flatten@^1.0.2:
|
|||
flow-bin@0.97.0:
|
||||
version "0.97.0"
|
||||
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.97.0.tgz#036ffcfc27503367a9d906ec9d843a0aa6f6bb83"
|
||||
integrity sha512-jXjD05gkatLuC4+e28frH1hZoRwr1iASP6oJr61Q64+kR4kmzaS+AdFBhYgoYS5kpoe4UzwDebWK8ETQFNh00w==
|
||||
|
||||
flush-write-stream@^1.0.0:
|
||||
version "1.0.3"
|
||||
|
@ -5371,7 +5361,6 @@ htmlparser2@3.10.0:
|
|||
htmlparser2@3.10.1:
|
||||
version "3.10.1"
|
||||
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
|
||||
integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==
|
||||
dependencies:
|
||||
domelementtype "^1.3.1"
|
||||
domhandler "^2.3.0"
|
||||
|
@ -8270,7 +8259,6 @@ path-parse@^1.0.5:
|
|||
path-parse@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
||||
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
|
||||
|
||||
path-to-regexp@0.1.7:
|
||||
version "0.1.7"
|
||||
|
@ -9394,7 +9382,6 @@ readable-stream@^3.0.6:
|
|||
readable-stream@^3.1.1:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.3.0.tgz#cb8011aad002eb717bf040291feba8569c986fb9"
|
||||
integrity sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==
|
||||
dependencies:
|
||||
inherits "^2.0.3"
|
||||
string_decoder "^1.1.1"
|
||||
|
@ -10137,7 +10124,6 @@ resolve@^1.1.6, resolve@^1.2.0, resolve@^1.3.2, resolve@^1.5.0:
|
|||
resolve@^1.9.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba"
|
||||
integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==
|
||||
dependencies:
|
||||
path-parse "^1.0.6"
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ support-files =
|
|||
doc_filter.html
|
||||
doc_frame_script.js
|
||||
doc_grid_names.html
|
||||
doc_grid_area_gridline_names.html
|
||||
doc_inline_sourcemap.html
|
||||
doc_invalid_sourcemap.css
|
||||
doc_invalid_sourcemap.html
|
||||
|
@ -190,6 +191,8 @@ skip-if = (os == "win" && debug) # bug 963492: win.
|
|||
[browser_rules_grid-toggle_04.js]
|
||||
[browser_rules_grid-toggle_05.js]
|
||||
[browser_rules_gridline-names-autocomplete.js]
|
||||
[browser_rules_gridline-names-are-shown-correctly.js]
|
||||
skip-if = os == 'linux' # focusEditableField times out consistently on linux.
|
||||
[browser_rules_guessIndentation.js]
|
||||
[browser_rules_highlight-element-rule.js]
|
||||
[browser_rules_highlight-property.js]
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests that the text editor correctly calculates the grid line names shown in the
|
||||
// autocomplete popup. We generally want to show all the grid line names for a grid
|
||||
// container, except for implicit line names created by an implicitly named area.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_grid_area_gridline_names.html";
|
||||
|
||||
add_task(async function() {
|
||||
await addTab(TEST_URL);
|
||||
const { inspector, view } = await openRuleView();
|
||||
|
||||
info("Test that implicit grid line names from explicit grid areas are shown.");
|
||||
await testExplicitNamedAreas(inspector, view);
|
||||
|
||||
info("Test that explicit grid line names creating implicit grid areas are shown.");
|
||||
await testImplicitNamedAreasWithExplicitGridLineNames(inspector, view);
|
||||
|
||||
info("Test that implicit grid line names creating implicit grid areas are not shown.");
|
||||
await testImplicitAreasWithImplicitGridLineNames(inspector, view);
|
||||
await testImplicitNamedAreasWithReversedGridLineNames(inspector, view);
|
||||
});
|
||||
|
||||
async function testExplicitNamedAreas(inspector, view) {
|
||||
await selectNode(".header", inspector);
|
||||
|
||||
const gridColLines = ["header-start", "header-end", "main-start", "main-end"];
|
||||
|
||||
const propertyName = view.styleDocument.querySelectorAll(".ruleview-propertyvalue")[0];
|
||||
const gridLineNamesUpdated = inspector.once("grid-line-names-updated");
|
||||
const editor = await focusEditableField(view, propertyName);
|
||||
const onPopupShown = once(editor.popup, "popup-opened");
|
||||
await gridLineNamesUpdated;
|
||||
|
||||
EventUtils.synthesizeKey("VK_DOWN", { shiftKey: true }, view.styleWindow);
|
||||
|
||||
await onPopupShown;
|
||||
|
||||
info("Check that the expected grid line column names are shown in the editor popup.");
|
||||
for (const lineName of gridColLines) {
|
||||
ok(editor.gridLineNames.cols.indexOf(lineName) > -1,
|
||||
`${lineName} is a suggested implicit grid line`);
|
||||
}
|
||||
}
|
||||
|
||||
async function testImplicitNamedAreasWithExplicitGridLineNames(inspector, view) {
|
||||
await selectNode(".contentArea", inspector);
|
||||
|
||||
const gridRowLines = ["main-start", "main-end", "content-start", "content-end"];
|
||||
|
||||
const propertyName = view.styleDocument.querySelectorAll(".ruleview-propertyvalue")[1];
|
||||
const gridLineNamesUpdated = inspector.once("grid-line-names-updated");
|
||||
const editor = await focusEditableField(view, propertyName);
|
||||
const onPopupShown = once(editor.popup, "popup-opened");
|
||||
await gridLineNamesUpdated;
|
||||
|
||||
EventUtils.synthesizeKey("VK_DOWN", { shiftKey: true }, view.styleWindow);
|
||||
|
||||
await onPopupShown;
|
||||
|
||||
info("Check that the expected grid line row names are shown in the editor popup.");
|
||||
for (const lineName of gridRowLines) {
|
||||
ok(editor.gridLineNames.rows.indexOf(lineName) > -1,
|
||||
`${lineName} is a suggested explicit grid line`);
|
||||
}
|
||||
}
|
||||
|
||||
async function testImplicitAreasWithImplicitGridLineNames(inspector, view) {
|
||||
await selectNode(".a", inspector);
|
||||
|
||||
const propertyName = view.styleDocument.querySelectorAll(".ruleview-propertyvalue")[0];
|
||||
const gridLineNamesUpdated = inspector.once("grid-line-names-updated");
|
||||
const editor = await focusEditableField(view, propertyName);
|
||||
const onPopupShown = once(editor.popup, "popup-opened");
|
||||
await gridLineNamesUpdated;
|
||||
|
||||
EventUtils.synthesizeKey("VK_DOWN", { shiftKey: true }, view.styleWindow);
|
||||
|
||||
await onPopupShown;
|
||||
|
||||
info("Check that the implicit grid lines created by implicit areas are not shown.");
|
||||
ok(!(editor.gridLineNames.cols.indexOf("a-end") > -1),
|
||||
"a-end is not shown because it is created by an implicit named area.");
|
||||
}
|
||||
|
||||
async function testImplicitNamedAreasWithReversedGridLineNames(inspector, view) {
|
||||
await selectNode(".b", inspector);
|
||||
|
||||
const propertyName = view.styleDocument.querySelectorAll(".ruleview-propertyvalue")[0];
|
||||
const gridLineNamesUpdated = inspector.once("grid-line-names-updated");
|
||||
const editor = await focusEditableField(view, propertyName);
|
||||
const onPopupShown = once(editor.popup, "popup-opened");
|
||||
await gridLineNamesUpdated;
|
||||
|
||||
EventUtils.synthesizeKey("VK_DOWN", { shiftKey: true }, view.styleWindow);
|
||||
|
||||
await onPopupShown;
|
||||
|
||||
info("Test that reversed implicit grid line names from implicit areas are not shown");
|
||||
ok(!(editor.gridLineNames.cols.indexOf("b-start") > -1),
|
||||
"b-start is not shown because it is created by an implicit named area.");
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<!doctype html>
|
||||
<style type='text/css'>
|
||||
/* Implicit gridlines created from explicit grid areas. */
|
||||
.wrapperA {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-auto-rows: minmax(100px, auto);
|
||||
grid-template-areas:
|
||||
"header header header"
|
||||
"main main main";
|
||||
}
|
||||
|
||||
.header {
|
||||
grid-column: header-start / header-end;
|
||||
grid-row: header-start / header-end;
|
||||
}
|
||||
|
||||
.main {
|
||||
grid-area: main;
|
||||
}
|
||||
|
||||
/* Implicit grid areas created from explicit gridlines */
|
||||
.wrapperB {
|
||||
display: grid;
|
||||
grid-template-columns: [main-start] 1fr [content-start] 1fr [content-end main-end];
|
||||
grid-template-rows: [main-start] 100px [content-start] 100px [content-end main-end];
|
||||
}
|
||||
|
||||
.contentArea {
|
||||
grid-column: content-start / content-end;
|
||||
grid-row: content-start / content-end;
|
||||
}
|
||||
|
||||
.wrapperC {
|
||||
display: grid;
|
||||
grid-template-columns: [a-start b-end] 1fr [c];
|
||||
}
|
||||
|
||||
.a {
|
||||
grid-column: a-start / a-end;
|
||||
}
|
||||
|
||||
.b {
|
||||
grid-column: b-start / b-end;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<div class="wrapperA">
|
||||
<div class="header">Header</div>
|
||||
<div class="main">Content</div>
|
||||
</div>
|
||||
<div class="wrapperB">
|
||||
<div class="contentArea">Implicit area named "content".</div>
|
||||
</div>
|
||||
<div class="wrapperC">
|
||||
<div class="a">A.</div>
|
||||
<div class="b">B.</div>
|
||||
</div>
|
||||
</div>
|
|
@ -330,10 +330,39 @@ TextPropertyEditor.prototype = {
|
|||
|
||||
for (const gridFragment of gridFragments) {
|
||||
for (const rowLine of gridFragment.rows.lines) {
|
||||
gridLineNames.rows = gridLineNames.rows.concat(rowLine.names);
|
||||
// We specifically ignore implicit line names created from implicitly named
|
||||
// areas. This is because showing implicit line names can be confusing for
|
||||
// designers who may have used a line name with "-start" or "-end" and created
|
||||
// an implicitly named grid area without meaning to.
|
||||
let gridArea;
|
||||
|
||||
for (const name of rowLine.names) {
|
||||
const rowLineName = name.substring(0, name.lastIndexOf("-start")) ||
|
||||
name.substring(0, name.lastIndexOf("-end"));
|
||||
gridArea = gridFragment.areas.find(area => area.name === rowLineName);
|
||||
|
||||
if (rowLine.type === "implicit" && gridArea &&
|
||||
gridArea.type === "implicit") {
|
||||
continue;
|
||||
}
|
||||
gridLineNames.rows.push(name);
|
||||
}
|
||||
}
|
||||
|
||||
for (const colLine of gridFragment.cols.lines) {
|
||||
gridLineNames.cols = gridLineNames.cols.concat(colLine.names);
|
||||
let gridArea;
|
||||
|
||||
for (const name of colLine.names) {
|
||||
const colLineName = name.substring(0, name.lastIndexOf("-start")) ||
|
||||
name.substring(0, name.lastIndexOf("-end"));
|
||||
gridArea = gridFragment.areas.find(area => area.name === colLineName);
|
||||
|
||||
if (colLine.type === "implicit" && gridArea &&
|
||||
gridArea.type === "implicit") {
|
||||
continue;
|
||||
}
|
||||
gridLineNames.cols.push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,10 +130,6 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
|||
"ruby-position",
|
||||
"scroll-behavior",
|
||||
"scroll-snap-align",
|
||||
"scroll-snap-coordinate",
|
||||
"scroll-snap-destination",
|
||||
"scroll-snap-points-x",
|
||||
"scroll-snap-points-y",
|
||||
"scroll-snap-type",
|
||||
"shape-rendering",
|
||||
"-moz-stack-sizing",
|
||||
|
|
|
@ -58,8 +58,8 @@ function getStringifiableArea({ columnEnd, columnStart, name, rowEnd, rowStart,
|
|||
return { columnEnd, columnStart, name, rowEnd, rowStart, type };
|
||||
}
|
||||
|
||||
function getStringifiableLine({ breadth, names, number, start }) {
|
||||
return { breadth, names, number, start };
|
||||
function getStringifiableLine({ breadth, names, number, start, type }) {
|
||||
return { breadth, names, number, start, type };
|
||||
}
|
||||
|
||||
function getStringifiableTrack({ breadth, start, state, type }) {
|
||||
|
|
|
@ -40,18 +40,21 @@ const GRID_FRAGMENT_DATA = {
|
|||
names: ["col-1", "col-start-1", "sidebar-start"],
|
||||
number: 1,
|
||||
start: 0,
|
||||
type: "explicit",
|
||||
},
|
||||
{
|
||||
breadth: 0,
|
||||
names: ["col-2", "header-start", "sidebar-end", "content-start"],
|
||||
number: 2,
|
||||
start: 100,
|
||||
type: "explicit",
|
||||
},
|
||||
{
|
||||
breadth: 0,
|
||||
names: ["header-end", "content-end"],
|
||||
number: 3,
|
||||
start: 200,
|
||||
type: "explicit",
|
||||
},
|
||||
],
|
||||
tracks: [
|
||||
|
@ -76,18 +79,21 @@ const GRID_FRAGMENT_DATA = {
|
|||
names: ["header-start"],
|
||||
number: 1,
|
||||
start: 0,
|
||||
type: "explicit",
|
||||
},
|
||||
{
|
||||
breadth: 0,
|
||||
names: ["header-end", "sidebar-start", "content-start"],
|
||||
number: 2,
|
||||
start: 100,
|
||||
type: "explicit",
|
||||
},
|
||||
{
|
||||
breadth: 0,
|
||||
names: ["sidebar-end", "content-end"],
|
||||
number: 3,
|
||||
start: 200,
|
||||
type: "explicit",
|
||||
},
|
||||
],
|
||||
tracks: [
|
||||
|
|
|
@ -3084,10 +3084,6 @@ exports.CSS_PROPERTIES = {
|
|||
"animation-play-state",
|
||||
"animation-fill-mode",
|
||||
"animation-delay",
|
||||
"scroll-snap-points-x",
|
||||
"scroll-snap-points-y",
|
||||
"scroll-snap-destination",
|
||||
"scroll-snap-coordinate",
|
||||
"transform",
|
||||
"rotate",
|
||||
"scale",
|
||||
|
@ -10719,10 +10715,6 @@ exports.PREFERENCES = [
|
|||
"scale",
|
||||
"layout.css.individual-transform.enabled"
|
||||
],
|
||||
[
|
||||
"scroll-snap-coordinate",
|
||||
"layout.css.scroll-snap.enabled"
|
||||
],
|
||||
[
|
||||
"scrollbar-color",
|
||||
"layout.css.scrollbar-color.enabled"
|
||||
|
@ -10731,18 +10723,6 @@ exports.PREFERENCES = [
|
|||
"translate",
|
||||
"layout.css.individual-transform.enabled"
|
||||
],
|
||||
[
|
||||
"scroll-snap-points-x",
|
||||
"layout.css.scroll-snap.enabled"
|
||||
],
|
||||
[
|
||||
"scroll-snap-points-y",
|
||||
"layout.css.scroll-snap.enabled"
|
||||
],
|
||||
[
|
||||
"scroll-snap-destination",
|
||||
"layout.css.scroll-snap.enabled"
|
||||
],
|
||||
[
|
||||
"-moz-binding",
|
||||
"layout.css.moz-binding.content.enabled"
|
||||
|
|
|
@ -4628,12 +4628,7 @@ nsDocShell::Reload(uint32_t aReloadFlags) {
|
|||
bool loadReplace = false;
|
||||
|
||||
nsIPrincipal* triggeringPrincipal = doc->NodePrincipal();
|
||||
// Currently the NodePrincipal holds the CSP for that document,
|
||||
// after Bug 965637 we can query the CSP directly from the doc
|
||||
// instead of doc->NodePrincipal().
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = doc->GetCsp();
|
||||
|
||||
nsAutoString contentTypeHint;
|
||||
doc->GetContentType(contentTypeHint);
|
||||
|
@ -5885,21 +5880,17 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
|
|||
// Set the triggering pricipal to aPrincipal if available, or current
|
||||
// document's principal otherwise.
|
||||
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
|
||||
RefPtr<Document> doc = GetDocument();
|
||||
if (!principal) {
|
||||
RefPtr<Document> doc = GetDocument();
|
||||
if (!doc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
principal = doc->NodePrincipal();
|
||||
}
|
||||
loadState->SetTriggeringPrincipal(principal);
|
||||
// Currently the principal (NodePrincipal) holds the CSP for that
|
||||
// document, after Bug 965637 we can query the CSP directly from
|
||||
// the doc instead of the principal.
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
nsresult rv = principal->GetCsp(getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
loadState->SetCsp(csp);
|
||||
if (doc) {
|
||||
loadState->SetCsp(doc->GetCsp());
|
||||
}
|
||||
|
||||
loadState->SetPrincipalIsExplicit(true);
|
||||
|
||||
|
@ -5907,7 +5898,7 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
|
|||
* to another site.
|
||||
*/
|
||||
bool equalUri = false;
|
||||
rv = aURI->Equals(mCurrentURI, &equalUri);
|
||||
nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
|
||||
if (NS_SUCCEEDED(rv) && (!equalUri) && aMetaRefresh &&
|
||||
aDelay <= REFRESH_REDIRECT_TIMER) {
|
||||
/* It is a META refresh based redirection within the threshold time
|
||||
|
@ -6905,13 +6896,7 @@ nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
|
|||
|
||||
LoadURIOptions loadURIOptions;
|
||||
loadURIOptions.mTriggeringPrincipal = triggeringPrincipal;
|
||||
// Currently we query the CSP from the triggeringPrincipal within
|
||||
// the loadInfo. After Bug 965637, we can query the CSP from the
|
||||
// loadInfo, which internally queries the CSP from the Client.
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
nsresult rv = triggeringPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
loadURIOptions.mCsp = csp;
|
||||
loadURIOptions.mCsp = loadInfo->GetCsp();
|
||||
loadURIOptions.mPostData = newPostData;
|
||||
return LoadURI(newSpecW, loadURIOptions);
|
||||
}
|
||||
|
@ -6976,6 +6961,7 @@ nsresult nsDocShell::EnsureContentViewer() {
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank;
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
nsIPrincipal* principal = GetInheritedPrincipal(false);
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
|
@ -6985,11 +6971,13 @@ nsresult nsDocShell::EnsureContentViewer() {
|
|||
nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal();
|
||||
if (parentElement) {
|
||||
baseURI = parentElement->GetBaseURI();
|
||||
cspToInheritForAboutBlank = parentElement->GetCsp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = CreateAboutBlankContentViewer(principal, baseURI);
|
||||
nsresult rv = CreateAboutBlankContentViewer(
|
||||
principal, cspToInheritForAboutBlank, baseURI);
|
||||
|
||||
NS_ENSURE_STATE(mContentViewer);
|
||||
|
||||
|
@ -7015,8 +7003,8 @@ nsresult nsDocShell::EnsureContentViewer() {
|
|||
}
|
||||
|
||||
nsresult nsDocShell::CreateAboutBlankContentViewer(
|
||||
nsIPrincipal* aPrincipal, nsIURI* aBaseURI, bool aTryToSaveOldPresentation,
|
||||
bool aCheckPermitUnload) {
|
||||
nsIPrincipal* aPrincipal, nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI,
|
||||
bool aTryToSaveOldPresentation, bool aCheckPermitUnload) {
|
||||
RefPtr<Document> blankDoc;
|
||||
nsCOMPtr<nsIContentViewer> viewer;
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
@ -7120,6 +7108,16 @@ nsresult nsDocShell::CreateAboutBlankContentViewer(
|
|||
// generate (about:blank) document to load
|
||||
blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal, this);
|
||||
if (blankDoc) {
|
||||
// Hack: manually set the CSP for the new document
|
||||
// Please create an actual copy of the CSP (do not share the same
|
||||
// reference) otherwise appending a new policy within the new
|
||||
// document will be incorrectly propagated to the opening doc.
|
||||
if (aCSP) {
|
||||
RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
|
||||
cspToInherit->InitFromOther(static_cast<nsCSPContext*>(aCSP));
|
||||
blankDoc->SetCsp(cspToInherit);
|
||||
}
|
||||
|
||||
// Hack: set the base URI manually, since this document never
|
||||
// got Reset() with a channel.
|
||||
blankDoc->SetBaseURI(aBaseURI);
|
||||
|
@ -7159,8 +7157,9 @@ nsresult nsDocShell::CreateAboutBlankContentViewer(
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal) {
|
||||
return CreateAboutBlankContentViewer(aPrincipal, nullptr);
|
||||
nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
|
||||
nsIContentSecurityPolicy* aCSP) {
|
||||
return CreateAboutBlankContentViewer(aPrincipal, aCSP, nullptr);
|
||||
}
|
||||
|
||||
bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
|
||||
|
@ -9050,13 +9049,7 @@ nsresult nsDocShell::MaybeHandleSameDocumentNavigation(
|
|||
} else {
|
||||
newURITriggeringPrincipal = aLoadState->TriggeringPrincipal();
|
||||
newURIPrincipalToInherit = doc->NodePrincipal();
|
||||
// This is a same-document navigation hence we query the CSP
|
||||
// from the current document. Please note that currently the
|
||||
// NodePrincipal holds the CSP for that document, after
|
||||
// Bug 965637 we can query the CSP directly from
|
||||
// the doc instead of the NodePrincipal.
|
||||
nsresult rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(newCsp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
newCsp = doc->GetCsp();
|
||||
}
|
||||
// Pass true for aCloneSHChildren, since we're not
|
||||
// changing documents here, so all of our subframes are
|
||||
|
@ -9354,7 +9347,7 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
|
|||
}
|
||||
|
||||
// clear the decks to prevent context bleed-through (bug 298255)
|
||||
rv = CreateAboutBlankContentViewer(nullptr, nullptr);
|
||||
rv = CreateAboutBlankContentViewer(nullptr, nullptr, nullptr);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -10010,23 +10003,10 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
|
|||
isc->SetBaseURI(baseURI);
|
||||
}
|
||||
|
||||
// Navigational requests that are same origin need to be upgraded in case
|
||||
// upgrade-insecure-requests is present. Please note that in that case
|
||||
// the triggeringPrincipal is holding the CSP that potentially
|
||||
// holds upgrade-insecure-requests.
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
aLoadState->TriggeringPrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
#ifdef DEBUG
|
||||
// We only serialize the CSP within CodebasePrincipals hence
|
||||
// lets only assert if the load is triggered by a CodebesPrincipal.
|
||||
// After Bug 965637 we can remove that assertion anyway.
|
||||
if (aLoadState->TriggeringPrincipal()->GetIsCodebasePrincipal()) {
|
||||
nsCOMPtr<nsIContentSecurityPolicy> argsCSP = aLoadState->Csp();
|
||||
MOZ_ASSERT(nsCSPContext::Equals(csp, argsCSP));
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp();
|
||||
if (csp) {
|
||||
// Navigational requests that are same origin need to be upgraded in case
|
||||
// upgrade-insecure-requests is present.
|
||||
bool upgradeInsecureRequests = false;
|
||||
csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
|
||||
if (upgradeInsecureRequests) {
|
||||
|
@ -10040,6 +10020,17 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
|
|||
loadInfo->SetUpgradeInsecureRequests();
|
||||
}
|
||||
}
|
||||
|
||||
if (CSP_ShouldResponseInheritCSP(channel)) {
|
||||
// If the new load needs to inherit the CSP, temporarily store the CSP
|
||||
// on the loadinfo, and transfer it to the new Document within
|
||||
// Document::InitCSP(). Please create an actual copy of the CSP (do not
|
||||
// share the same reference) otherwise a Meta CSP of an opaque origin
|
||||
// will incorrectly be propagated to the embedding document.
|
||||
RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
|
||||
cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
|
||||
loadInfo->SetCSPToInherit(cspToInherit);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
|
||||
|
@ -11140,12 +11131,7 @@ nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
|
|||
mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
|
||||
|
||||
bool scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
|
||||
|
||||
// Currently the NodePrincipal holds the CSP for that document,
|
||||
// after Bug 965637 we can query the CSP directly from
|
||||
// the doc instead of the NodePrincipal.
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
aDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
|
||||
|
||||
// Since we're not changing which page we have loaded, pass
|
||||
// true for aCloneChildren.
|
||||
|
@ -11185,18 +11171,12 @@ nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
|
|||
// Step 3.
|
||||
newSHEntry = mOSHE;
|
||||
|
||||
// Currently the NodePrincipal holds the CSP for that document,
|
||||
// after Bug 965637 we can query the CSP directly from
|
||||
// the doc instead of the NodePrincipal.
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
aDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
|
||||
// Since we're not changing which page we have loaded, pass
|
||||
if (!newSHEntry) {
|
||||
nsresult rv = AddToSessionHistory(
|
||||
aNewURI, nullptr,
|
||||
aDocument->NodePrincipal(), // triggeringPrincipal
|
||||
nullptr, csp, true, getter_AddRefs(newSHEntry));
|
||||
nullptr, aDocument->GetCsp(), true, getter_AddRefs(newSHEntry));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mOSHE = newSHEntry;
|
||||
}
|
||||
|
@ -11448,13 +11428,8 @@ nsresult nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
|
|||
if (!triggeringPrincipal) {
|
||||
triggeringPrincipal = loadInfo->TriggeringPrincipal();
|
||||
}
|
||||
if (!csp && triggeringPrincipal) {
|
||||
// Currently if no CSP is passed explicitly we query the CSP from
|
||||
// the triggeringPrincipal from within the loadinfo. After Bug 965637,
|
||||
// we can query the CSP from the loadInfo directly in case the CSP is
|
||||
// not passed explicitly. Internally the loadinfo queries the CSP
|
||||
// from the Client.
|
||||
triggeringPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
if (!csp) {
|
||||
csp = static_cast<net::LoadInfo*>(loadInfo.get())->GetCSPToInherit();
|
||||
}
|
||||
|
||||
loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
|
||||
|
@ -11619,7 +11594,7 @@ nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType) {
|
|||
// Don't cache the presentation if we're going to just reload the
|
||||
// current entry. Caching would lead to trying to save the different
|
||||
// content viewers in the same nsISHEntry object.
|
||||
rv = CreateAboutBlankContentViewer(principalToInherit, nullptr,
|
||||
rv = CreateAboutBlankContentViewer(principalToInherit, nullptr, nullptr,
|
||||
aEntry != mOSHE);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -12659,9 +12634,8 @@ nsDocShell::OnLinkClickSync(
|
|||
nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp;
|
||||
if (!csp) {
|
||||
// Currently, if no csp is passed explicitly we fall back to querying the
|
||||
// CSP from the NodePrincipal(). After Bug 965637 we can fall back to
|
||||
// querying the CSP from the document (aContent->OwnerDoc()).
|
||||
aContent->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
// CSP from the document.
|
||||
csp = aContent->GetCsp();
|
||||
}
|
||||
|
||||
uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
|
||||
|
@ -12930,7 +12904,8 @@ nsDocShell::InitOrReusePrintPreviewViewer(nsIWebBrowserPrint** aPrintPreview) {
|
|||
NullPrincipal::CreateWithInheritedAttributes(this);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:printpreview"));
|
||||
nsresult rv = CreateAboutBlankContentViewer(principal, uri);
|
||||
nsresult rv =
|
||||
CreateAboutBlankContentViewer(principal, /* aCsp = */ nullptr, uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Here we manually set current URI since we have just created a
|
||||
// brand new content viewer (about:blank) to host preview.
|
||||
|
|
|
@ -486,7 +486,9 @@ class nsDocShell final : public nsDocLoader,
|
|||
|
||||
// aPrincipal can be passed in if the caller wants. If null is
|
||||
// passed in, the about:blank principal will end up being used.
|
||||
// aCSP, if any, will be used for the new about:blank load.
|
||||
nsresult CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
|
||||
nsIContentSecurityPolicy* aCSP,
|
||||
nsIURI* aBaseURI,
|
||||
bool aTryToSaveOldPresentation = true,
|
||||
bool aCheckPermitUnload = true);
|
||||
|
|
|
@ -43,6 +43,7 @@ class ClientSource;
|
|||
interface nsIURI;
|
||||
interface nsIChannel;
|
||||
interface nsIContentViewer;
|
||||
interface nsIContentSecurityPolicy;
|
||||
interface nsIDocShellLoadInfo;
|
||||
interface nsIEditor;
|
||||
interface nsIEditingSession;
|
||||
|
@ -606,8 +607,10 @@ interface nsIDocShell : nsIDocShellTreeItem
|
|||
/**
|
||||
* Create a new about:blank document and content viewer.
|
||||
* @param aPrincipal the principal to use for the new document.
|
||||
* @param aCsp the CSP to use for the new document.
|
||||
*/
|
||||
void createAboutBlankContentViewer(in nsIPrincipal aPrincipal);
|
||||
void createAboutBlankContentViewer(in nsIPrincipal aPrincipal,
|
||||
[optional] in nsIContentSecurityPolicy aCSP);
|
||||
|
||||
/**
|
||||
* Upon getting, returns the canonical encoding label of the document
|
||||
|
|
|
@ -35,8 +35,7 @@ function verifyResult(aTestName, aBrowser, aDataURI, aPID, aSamePID) {
|
|||
}
|
||||
|
||||
// finally, evaluate that the CSP was set.
|
||||
let principal = channel.loadInfo.triggeringPrincipal;
|
||||
let cspOBJ = JSON.parse(principal.cspJSON);
|
||||
let cspOBJ = JSON.parse(content.document.cspJSON);
|
||||
let policies = cspOBJ["csp-policies"];
|
||||
is(policies.length, 1, "should be one policy");
|
||||
let policy = policies[0];
|
||||
|
|
|
@ -15,8 +15,7 @@ function verifyCSP(aTestName, aBrowser, aDataURI) {
|
|||
return ContentTask.spawn(aBrowser, {aTestName, aDataURI}, async function({aTestName, aDataURI}) {
|
||||
let channel = content.docShell.currentDocumentChannel;
|
||||
is(channel.URI.spec, aDataURI, "testing CSP for " + aTestName);
|
||||
let principal = channel.loadInfo.triggeringPrincipal;
|
||||
let cspJSON = principal.cspJSON;
|
||||
let cspJSON = content.document.cspJSON;
|
||||
let cspOBJ = JSON.parse(cspJSON);
|
||||
let policies = cspOBJ["csp-policies"];
|
||||
is(policies.length, 1, "should be one policy");
|
||||
|
|
|
@ -206,17 +206,12 @@ ContentAreaDropListener.prototype =
|
|||
if (sourceNode &&
|
||||
(sourceNode.localName !== "browser" ||
|
||||
sourceNode.namespaceURI !== "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul")) {
|
||||
// Use sourceNode's principal only if the sourceNode is not browser.
|
||||
// Use sourceNode's csp only if the sourceNode is not browser.
|
||||
//
|
||||
// If sourceNode is browser, the actual triggering principal may be
|
||||
// differ than sourceNode's principal, since sourceNode's principal is
|
||||
// top level document's one and the drag may be triggered from a frame
|
||||
// with different principal.
|
||||
if (sourceNode.nodePrincipal) {
|
||||
// Currently we query the CSP from the nodePrincipal. After Bug 965637 we can
|
||||
// query the CSP directly from the sourceNode.
|
||||
return sourceNode.nodePrincipal.csp;
|
||||
}
|
||||
// If sourceNode is browser, the actual triggering csp may be differ than sourceNode's csp,
|
||||
// since sourceNode's csp is top level document's one and the drag may be triggered from a
|
||||
// frame with different csp.
|
||||
return sourceNode.csp;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "mozilla/IntegerRange.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/LoadInfo.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/PresShellInlines.h"
|
||||
#include "mozilla/RestyleManager.h"
|
||||
|
@ -69,6 +70,7 @@
|
|||
#include "mozilla/dom/Attr.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/CSPDictionariesBinding.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/FeaturePolicy.h"
|
||||
|
@ -2697,7 +2699,8 @@ nsresult Document::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
|
|||
|
||||
// XFO needs to be checked after CSP because it is ignored if
|
||||
// the CSP defines frame-ancestors.
|
||||
if (!FramingChecker::CheckFrameOptions(aChannel, docShell, NodePrincipal())) {
|
||||
nsCOMPtr<nsIContentSecurityPolicy> cspForFA = mCSP;
|
||||
if (!FramingChecker::CheckFrameOptions(aChannel, docShell, cspForFA)) {
|
||||
MOZ_LOG(gCspPRLog, LogLevel::Debug,
|
||||
("XFO doesn't like frame's ancestry, not loading."));
|
||||
// stop! ERROR page!
|
||||
|
@ -2719,6 +2722,29 @@ nsresult Document::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContentSecurityPolicy* Document::GetCsp() const { return mCSP; }
|
||||
|
||||
void Document::SetCsp(nsIContentSecurityPolicy* aCSP) { mCSP = aCSP; }
|
||||
|
||||
nsIContentSecurityPolicy* Document::GetPreloadCsp() const {
|
||||
return mPreloadCSP;
|
||||
}
|
||||
|
||||
void Document::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP) {
|
||||
mPreloadCSP = aPreloadCSP;
|
||||
}
|
||||
|
||||
void Document::GetCspJSON(nsString& aJSON) {
|
||||
aJSON.Truncate();
|
||||
|
||||
if (!mCSP) {
|
||||
dom::CSPPolicies jsonPolicies;
|
||||
jsonPolicies.ToJSON(aJSON);
|
||||
return;
|
||||
}
|
||||
mCSP->ToJSON(aJSON);
|
||||
}
|
||||
|
||||
void Document::SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages) {
|
||||
for (uint32_t i = 0; i < aMessages.Length(); ++i) {
|
||||
nsAutoString messageTag;
|
||||
|
@ -2738,14 +2764,11 @@ void Document::ApplySettingsFromCSP(bool aSpeculative) {
|
|||
nsresult rv = NS_OK;
|
||||
if (!aSpeculative) {
|
||||
// 1) apply settings from regular CSP
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
rv = NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
if (csp) {
|
||||
if (mCSP) {
|
||||
// Set up 'block-all-mixed-content' if not already inherited
|
||||
// from the parent context or set by any other CSP.
|
||||
if (!mBlockAllMixedContent) {
|
||||
rv = csp->GetBlockAllMixedContent(&mBlockAllMixedContent);
|
||||
rv = mCSP->GetBlockAllMixedContent(&mBlockAllMixedContent);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
}
|
||||
if (!mBlockAllMixedContentPreloads) {
|
||||
|
@ -2755,7 +2778,7 @@ void Document::ApplySettingsFromCSP(bool aSpeculative) {
|
|||
// Set up 'upgrade-insecure-requests' if not already inherited
|
||||
// from the parent context or set by any other CSP.
|
||||
if (!mUpgradeInsecureRequests) {
|
||||
rv = csp->GetUpgradeInsecureRequests(&mUpgradeInsecureRequests);
|
||||
rv = mCSP->GetUpgradeInsecureRequests(&mUpgradeInsecureRequests);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
}
|
||||
if (!mUpgradeInsecurePreloads) {
|
||||
|
@ -2766,16 +2789,13 @@ void Document::ApplySettingsFromCSP(bool aSpeculative) {
|
|||
}
|
||||
|
||||
// 2) apply settings from speculative csp
|
||||
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
|
||||
rv = NodePrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
if (preloadCsp) {
|
||||
if (mPreloadCSP) {
|
||||
if (!mBlockAllMixedContentPreloads) {
|
||||
rv = preloadCsp->GetBlockAllMixedContent(&mBlockAllMixedContentPreloads);
|
||||
rv = mPreloadCSP->GetBlockAllMixedContent(&mBlockAllMixedContentPreloads);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
}
|
||||
if (!mUpgradeInsecurePreloads) {
|
||||
rv = preloadCsp->GetUpgradeInsecureRequests(&mUpgradeInsecurePreloads);
|
||||
rv = mPreloadCSP->GetUpgradeInsecureRequests(&mUpgradeInsecurePreloads);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
}
|
||||
}
|
||||
|
@ -2795,10 +2815,41 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// If this is a system privileged document - do not apply a CSP.
|
||||
// After Bug 1496418 we can remove the early return and apply
|
||||
// a CSP even when loading using a SystemPrincipal.
|
||||
if (nsContentUtils::IsSystemPrincipal(NodePrincipal())) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mCSP, "where did mCSP get set if not here?");
|
||||
|
||||
// If there is a CSP that needs to be inherited either from the
|
||||
// embedding doc or from the opening doc, then we query it here
|
||||
// from the loadinfo because the docshell temporarily stored it
|
||||
// on the loadinfo so we can set it here.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
mCSP = static_cast<net::LoadInfo*>(loadInfo.get())->GetCSPToInherit();
|
||||
|
||||
// If there is no CSP to inherit, then we create a new CSP here so
|
||||
// that history entries always have the right reference in case a
|
||||
// Meta CSP gets dynamically added after the history entry has
|
||||
// already been created.
|
||||
if (!mCSP) {
|
||||
mCSP = new nsCSPContext();
|
||||
}
|
||||
|
||||
// Always overwrite the requesting context of the CSP so that any new
|
||||
// 'self' keyword added to an inherited CSP translates correctly.
|
||||
nsresult rv = mCSP->SetRequestContextWithDocument(this);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoCString tCspHeaderValue, tCspROHeaderValue;
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel;
|
||||
nsresult rv = GetHttpChannelHelper(aChannel, getter_AddRefs(httpChannel));
|
||||
rv = GetHttpChannelHelper(aChannel, getter_AddRefs(httpChannel));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -2818,20 +2869,6 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
|
|||
nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
|
||||
auto addonPolicy = BasePrincipal::Cast(principal)->AddonPolicy();
|
||||
|
||||
// Unless the NodePrincipal is a SystemPrincipal, which currently can not
|
||||
// hold a CSP, we always call EnsureCSP() on the Principal. We do this
|
||||
// so that a Meta CSP does not have to create a new CSP object. This is
|
||||
// important because history entries hold a reference to the CSP object,
|
||||
// which then gets dynamically updated in case a meta CSP is present.
|
||||
// Note that after Bug 965637 we can remove that carve out, because the
|
||||
// CSP will hang off the Client/Document and not the Principal anymore.
|
||||
if (principal->IsSystemPrincipal()) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
rv = principal->EnsureCSP(this, getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If there's no CSP to apply, go ahead and return early
|
||||
if (!addonPolicy && cspHeaderValue.IsEmpty() && cspROHeaderValue.IsEmpty()) {
|
||||
if (MOZ_LOG_TEST(gCspPRLog, LogLevel::Debug)) {
|
||||
|
@ -2853,20 +2890,28 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
|
|||
if (addonPolicy) {
|
||||
nsAutoString addonCSP;
|
||||
Unused << ExtensionPolicyService::GetSingleton().GetBaseCSP(addonCSP);
|
||||
csp->AppendPolicy(addonCSP, false, false);
|
||||
mCSP->AppendPolicy(addonCSP, false, false);
|
||||
|
||||
csp->AppendPolicy(addonPolicy->ContentSecurityPolicy(), false, false);
|
||||
mCSP->AppendPolicy(addonPolicy->ContentSecurityPolicy(), false, false);
|
||||
// Bug 1548468: Move CSP off ExpandedPrincipal
|
||||
// Currently the LoadInfo holds the source of truth for every resource load
|
||||
// because LoadInfo::GetCSP() queries the CSP from an ExpandedPrincipal
|
||||
// (and not from the Client) if the load was triggered by an extension.
|
||||
auto* basePrin = BasePrincipal::Cast(principal);
|
||||
if (basePrin->Is<ExpandedPrincipal>()) {
|
||||
basePrin->As<ExpandedPrincipal>()->SetCsp(mCSP);
|
||||
}
|
||||
}
|
||||
|
||||
// ----- if there's a full-strength CSP header, apply it.
|
||||
if (!cspHeaderValue.IsEmpty()) {
|
||||
rv = CSP_AppendCSPFromHeader(csp, cspHeaderValue, false);
|
||||
rv = CSP_AppendCSPFromHeader(mCSP, cspHeaderValue, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// ----- if there's a report-only CSP header, apply it.
|
||||
if (!cspROHeaderValue.IsEmpty()) {
|
||||
rv = CSP_AppendCSPFromHeader(csp, cspROHeaderValue, true);
|
||||
rv = CSP_AppendCSPFromHeader(mCSP, cspROHeaderValue, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -2876,7 +2921,7 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
|
|||
// directive, intersect the CSP sandbox flags with the existing flags. This
|
||||
// corresponds to the _least_ permissive policy.
|
||||
uint32_t cspSandboxFlags = SANDBOXED_NONE;
|
||||
rv = csp->GetCSPSandboxFlags(&cspSandboxFlags);
|
||||
rv = mCSP->GetCSPSandboxFlags(&cspSandboxFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Probably the iframe sandbox attribute already caused the creation of a
|
||||
|
@ -2889,7 +2934,6 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
|
|||
|
||||
if (needNewNullPrincipal) {
|
||||
principal = NullPrincipal::CreateWithInheritedAttributes(principal);
|
||||
principal->SetCsp(csp);
|
||||
SetPrincipals(principal, principal);
|
||||
}
|
||||
|
||||
|
@ -2899,7 +2943,7 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
|
|||
bool safeAncestry = false;
|
||||
|
||||
// PermitsAncestry sends violation reports when necessary
|
||||
rv = csp->PermitsAncestry(docShell, &safeAncestry);
|
||||
rv = mCSP->PermitsAncestry(docShell, &safeAncestry);
|
||||
|
||||
if (NS_FAILED(rv) || !safeAncestry) {
|
||||
MOZ_LOG(gCspPRLog, LogLevel::Debug,
|
||||
|
@ -4733,10 +4777,8 @@ void Document::SetScriptGlobalObject(
|
|||
// Now that we know what our window is, we can flush the CSP errors to the
|
||||
// Web Console. We are flushing all messages that occured and were stored
|
||||
// in the queue prior to this point.
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
if (csp) {
|
||||
static_cast<nsCSPContext*>(csp.get())->flushConsoleMessages();
|
||||
if (mCSP) {
|
||||
static_cast<nsCSPContext*>(mCSP.get())->flushConsoleMessages();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannelInternal> internalChannel =
|
||||
|
@ -5112,12 +5154,11 @@ void Document::DispatchContentLoadedEvents() {
|
|||
// the CSP allows precisely the resources that need to be loaded; but it
|
||||
// should at least be as strong as:
|
||||
// <meta http-equiv="Content-Security-Policy" content="default-src chrome:"/>
|
||||
static void AssertAboutPageHasCSP(nsIURI* aDocumentURI,
|
||||
nsIPrincipal* aPrincipal) {
|
||||
static void AssertAboutPageHasCSP(Document* aDocument) {
|
||||
// Check if we are loading an about: URI at all
|
||||
nsCOMPtr<nsIURI> documentURI = aDocument->GetDocumentURI();
|
||||
bool isAboutURI =
|
||||
(NS_SUCCEEDED(aDocumentURI->SchemeIs("about", &isAboutURI)) &&
|
||||
isAboutURI);
|
||||
(NS_SUCCEEDED(documentURI->SchemeIs("about", &isAboutURI)) && isAboutURI);
|
||||
|
||||
if (!isAboutURI ||
|
||||
Preferences::GetBool("csp.skip_about_page_has_csp_assert")) {
|
||||
|
@ -5145,7 +5186,7 @@ static void AssertAboutPageHasCSP(nsIURI* aDocumentURI,
|
|||
|
||||
// Check if the about URI is whitelisted
|
||||
nsAutoCString aboutSpec;
|
||||
aDocumentURI->GetSpec(aboutSpec);
|
||||
documentURI->GetSpec(aboutSpec);
|
||||
ToLowerCase(aboutSpec);
|
||||
for (auto& legacyPageEntry : *sLegacyAboutPagesWithNoCSP) {
|
||||
// please note that we perform a substring match here on purpose,
|
||||
|
@ -5156,8 +5197,7 @@ static void AssertAboutPageHasCSP(nsIURI* aDocumentURI,
|
|||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
aPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
|
||||
bool foundDefaultSrc = false;
|
||||
if (csp) {
|
||||
uint32_t policyCount = 0;
|
||||
|
@ -5185,7 +5225,7 @@ void Document::EndLoad() {
|
|||
// only assert if nothing stopped the load on purpose
|
||||
// TODO: we probably also want to check XUL documents here too
|
||||
if (!mParserAborted && !IsXULDocument()) {
|
||||
AssertAboutPageHasCSP(mDocumentURI, NodePrincipal());
|
||||
AssertAboutPageHasCSP(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -11687,12 +11727,9 @@ bool Document::HasScriptsBlockedBySandbox() {
|
|||
bool Document::InlineScriptAllowedByCSP() {
|
||||
// this function assumes the inline script is parser created
|
||||
// (e.g., before setting attribute(!) event handlers)
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
nsresult rv = NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
bool allowsInlineScript = true;
|
||||
if (csp) {
|
||||
nsresult rv = csp->GetAllowsInline(
|
||||
if (mCSP) {
|
||||
nsresult rv = mCSP->GetAllowsInline(
|
||||
nsIContentPolicy::TYPE_SCRIPT,
|
||||
EmptyString(), // aNonce
|
||||
true, // aParserCreated
|
||||
|
|
|
@ -98,6 +98,7 @@ class nsAtom;
|
|||
class nsIBFCacheEntry;
|
||||
class nsIChannel;
|
||||
class nsIContent;
|
||||
class nsIContentSecurityPolicy;
|
||||
class nsIContentSink;
|
||||
class nsIDocShell;
|
||||
class nsIDocShellTreeItem;
|
||||
|
@ -696,6 +697,24 @@ class Document : public nsINode,
|
|||
*/
|
||||
void SetChromeXHRDocBaseURI(nsIURI* aURI) { mChromeXHRDocBaseURI = aURI; }
|
||||
|
||||
/**
|
||||
* The CSP in general is stored in the ClientInfo, but we also cache
|
||||
* the CSP on the document so subresources loaded within a document
|
||||
* can query that cached CSP instead of having to deserialize the CSP
|
||||
* from the Client.
|
||||
*
|
||||
* Please note that at the time of CSP parsing the Client is not
|
||||
* available yet, hence we sync CSP of document and Client when the
|
||||
* Client becomes available within nsGlobalWindowInner::EnsureClientSource().
|
||||
*/
|
||||
nsIContentSecurityPolicy* GetCsp() const;
|
||||
void SetCsp(nsIContentSecurityPolicy* aCSP);
|
||||
|
||||
nsIContentSecurityPolicy* GetPreloadCsp() const;
|
||||
void SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP);
|
||||
|
||||
void GetCspJSON(nsString& aJSON);
|
||||
|
||||
/**
|
||||
* Set referrer policy and upgrade-insecure-requests flags
|
||||
*/
|
||||
|
@ -4415,6 +4434,12 @@ class Document : public nsINode,
|
|||
// The channel that got passed to Document::StartDocumentLoad(), if any.
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
|
||||
// The CSP for every load lives in the Client within the LoadInfo. For all
|
||||
// document-initiated subresource loads we can use that cached version of the
|
||||
// CSP so we do not have to deserialize the CSP from the Client all the time.
|
||||
nsCOMPtr<nsIContentSecurityPolicy> mCSP;
|
||||
nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
|
||||
|
||||
private:
|
||||
nsCString mContentType;
|
||||
|
||||
|
|
|
@ -150,15 +150,9 @@ already_AddRefed<nsDocShellLoadState> Location::CheckURL(
|
|||
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
|
||||
|
||||
loadState->SetTriggeringPrincipal(triggeringPrincipal);
|
||||
|
||||
// Currently we query the CSP from the triggeringPrincipal, which is the
|
||||
// doc->NodePrincipal() in case there is a doc. In that case we can query
|
||||
// the CSP directly from the doc after Bug 965637. In case there is no doc,
|
||||
// then we also do not need to query the CSP, because only documents can have
|
||||
// a CSP attached.
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
triggeringPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
loadState->SetCsp(csp);
|
||||
if (doc) {
|
||||
loadState->SetCsp(doc->GetCsp());
|
||||
}
|
||||
|
||||
if (sourceURI) {
|
||||
nsCOMPtr<nsIReferrerInfo> referrerInfo =
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "mozilla/dom/ResizeObserver.h"
|
||||
|
||||
#include "mozilla/dom/DOMRect.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsSVGUtils.h"
|
||||
|
@ -219,15 +220,13 @@ uint32_t ResizeObserver::BroadcastActiveObservations() {
|
|||
|
||||
for (auto& observation : mActiveTargets) {
|
||||
Element* target = observation->Target();
|
||||
RefPtr<ResizeObserverEntry> entry = new ResizeObserverEntry(this, *target);
|
||||
|
||||
nsSize borderBoxSize =
|
||||
GetTargetSize(target, ResizeObserverBoxOptions::Border_box);
|
||||
entry->SetBorderBoxSize(borderBoxSize);
|
||||
|
||||
nsSize contentBoxSize =
|
||||
GetTargetSize(target, ResizeObserverBoxOptions::Content_box);
|
||||
entry->SetContentRectAndSize(contentBoxSize);
|
||||
RefPtr<ResizeObserverEntry> entry =
|
||||
new ResizeObserverEntry(this, *target, borderBoxSize, contentBoxSize);
|
||||
|
||||
if (!entries.AppendElement(entry.forget(), fallible)) {
|
||||
// Out of memory.
|
||||
|
@ -271,13 +270,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObserverEntry)
|
|||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
already_AddRefed<ResizeObserverEntry> ResizeObserverEntry::Constructor(
|
||||
const GlobalObject& aGlobal, Element& aTarget, ErrorResult& aRv) {
|
||||
RefPtr<ResizeObserverEntry> observerEntry =
|
||||
new ResizeObserverEntry(aGlobal.GetAsSupports(), aTarget);
|
||||
return observerEntry.forget();
|
||||
}
|
||||
|
||||
void ResizeObserverEntry::SetBorderBoxSize(const nsSize& aSize) {
|
||||
nsIFrame* frame = mTarget->GetPrimaryFrame();
|
||||
const WritingMode wm = frame ? frame->GetWritingMode() : WritingMode();
|
||||
|
@ -292,7 +284,7 @@ void ResizeObserverEntry::SetContentRectAndSize(const nsSize& aSize) {
|
|||
// Per the spec, we need to use the top-left padding offset as the origin of
|
||||
// our contentRect.
|
||||
nsRect rect(nsPoint(padding.left, padding.top), aSize);
|
||||
RefPtr<DOMRect> contentRect = new DOMRect(mTarget);
|
||||
RefPtr<DOMRect> contentRect = new DOMRect(this);
|
||||
contentRect->SetLayoutRect(rect);
|
||||
mContentRect = contentRect.forget();
|
||||
|
||||
|
|
|
@ -175,10 +175,15 @@ class ResizeObserverEntry final : public nsISupports, public nsWrapperCache {
|
|||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserverEntry)
|
||||
|
||||
ResizeObserverEntry(nsISupports* aOwner, Element& aTarget)
|
||||
ResizeObserverEntry(nsISupports* aOwner, Element& aTarget,
|
||||
const nsSize& aBorderBoxSize,
|
||||
const nsSize& aContentBoxSize)
|
||||
: mOwner(aOwner), mTarget(&aTarget) {
|
||||
MOZ_ASSERT(mOwner, "Need a non-null owner");
|
||||
MOZ_ASSERT(mTarget, "Need a non-null target element");
|
||||
|
||||
SetBorderBoxSize(aBorderBoxSize);
|
||||
SetContentRectAndSize(aContentBoxSize);
|
||||
}
|
||||
|
||||
nsISupports* GetParentObject() const { return mOwner; }
|
||||
|
@ -188,9 +193,6 @@ class ResizeObserverEntry final : public nsISupports, public nsWrapperCache {
|
|||
return ResizeObserverEntry_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
static already_AddRefed<ResizeObserverEntry> Constructor(
|
||||
const GlobalObject& global, Element& target, ErrorResult& aRv);
|
||||
|
||||
Element* Target() const { return mTarget; }
|
||||
|
||||
/**
|
||||
|
@ -206,14 +208,14 @@ class ResizeObserverEntry final : public nsISupports, public nsWrapperCache {
|
|||
ResizeObserverSize* BorderBoxSize() const { return mBorderBoxSize; }
|
||||
ResizeObserverSize* ContentBoxSize() const { return mContentBoxSize; }
|
||||
|
||||
private:
|
||||
~ResizeObserverEntry() = default;
|
||||
|
||||
// Set borderBoxSize.
|
||||
void SetBorderBoxSize(const nsSize& aSize);
|
||||
// Set contentRect and contentBoxSize.
|
||||
void SetContentRectAndSize(const nsSize& aSize);
|
||||
|
||||
protected:
|
||||
~ResizeObserverEntry() = default;
|
||||
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
nsCOMPtr<Element> mTarget;
|
||||
|
||||
|
|
|
@ -70,7 +70,6 @@ inline nsresult nsContentPolicy::CheckPolicy(CPMethod policyMethod,
|
|||
int16_t* decision) {
|
||||
nsContentPolicyType contentType = loadInfo->InternalContentPolicyType();
|
||||
nsCOMPtr<nsISupports> requestingContext = loadInfo->GetLoadingContext();
|
||||
nsCOMPtr<nsIPrincipal> requestPrincipal = loadInfo->TriggeringPrincipal();
|
||||
nsCOMPtr<nsIURI> requestingLocation;
|
||||
nsCOMPtr<nsIPrincipal> loadingPrincipal = loadInfo->LoadingPrincipal();
|
||||
if (loadingPrincipal) {
|
||||
|
@ -98,18 +97,17 @@ inline nsresult nsContentPolicy::CheckPolicy(CPMethod policyMethod,
|
|||
* iframes with an image as src. Get the uri from the dom node.
|
||||
* See bug 254510
|
||||
*/
|
||||
if (!requestingLocation) {
|
||||
nsCOMPtr<mozilla::dom::Document> doc;
|
||||
nsCOMPtr<nsIContent> node = do_QueryInterface(requestingContext);
|
||||
if (node) {
|
||||
doc = node->OwnerDoc();
|
||||
}
|
||||
if (!doc) {
|
||||
doc = do_QueryInterface(requestingContext);
|
||||
}
|
||||
if (doc) {
|
||||
requestingLocation = doc->GetDocumentURI();
|
||||
}
|
||||
nsCOMPtr<mozilla::dom::Document> doc;
|
||||
nsCOMPtr<nsIContent> node = do_QueryInterface(requestingContext);
|
||||
if (node) {
|
||||
doc = node->OwnerDoc();
|
||||
}
|
||||
if (!doc) {
|
||||
doc = do_QueryInterface(requestingContext);
|
||||
}
|
||||
|
||||
if (!requestingLocation && doc) {
|
||||
requestingLocation = doc->GetDocumentURI();
|
||||
}
|
||||
|
||||
nsContentPolicyType externalType =
|
||||
|
@ -129,9 +127,8 @@ inline nsresult nsContentPolicy::CheckPolicy(CPMethod policyMethod,
|
|||
window = do_QueryInterface(requestingContext);
|
||||
}
|
||||
|
||||
if (requestPrincipal) {
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
requestPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = doc->GetCsp();
|
||||
if (csp && window) {
|
||||
csp->EnsureEventTarget(
|
||||
window->EventTargetFor(mozilla::TaskCategory::Other));
|
||||
|
|
|
@ -5058,12 +5058,8 @@ void nsContentUtils::TriggerLink(nsIContent* aContent,
|
|||
fileName.SetIsVoid(true); // No actionable download attribute was found.
|
||||
}
|
||||
|
||||
// Currently we query the CSP from the triggeringPrincipal, which is
|
||||
// aContent->NodePrincipal(). After Bug 965637 we can query the CSP
|
||||
// directly from the doc instead (aContent->OwnerDoc()).
|
||||
nsCOMPtr<nsIPrincipal> triggeringPrincipal = aContent->NodePrincipal();
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
triggeringPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = aContent->GetCsp();
|
||||
|
||||
handler->OnLinkClick(
|
||||
aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec : EmptyString(),
|
||||
|
@ -9795,15 +9791,7 @@ bool nsContentUtils::AttemptLargeAllocationLoad(nsIHttpChannel* aChannel) {
|
|||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
nsCOMPtr<nsIPrincipal> triggeringPrincipal = loadInfo->TriggeringPrincipal();
|
||||
|
||||
// Currently we query the CSP from the triggeringPrincipal within the
|
||||
// loadInfo. After Bug 965637, we can query the CSP from the loadInfo, which
|
||||
// internally queries the CSP from the Client.
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
if (triggeringPrincipal) {
|
||||
rv = triggeringPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = loadInfo->GetCsp();
|
||||
|
||||
// Get the channel's load flags, and use them to generate nsIWebNavigation
|
||||
// load flags. We want to make sure to propagate the refresh and cache busting
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#include "BrowserParent.h"
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/ExpandedPrincipal.h"
|
||||
#include "mozilla/GuardObjects.h"
|
||||
#include "mozilla/HTMLEditor.h"
|
||||
#include "mozilla/NullPrincipal.h"
|
||||
|
@ -405,10 +406,7 @@ void nsFrameLoader::LoadFrame(bool aOriginalSrc) {
|
|||
if (isSrcdoc) {
|
||||
src.AssignLiteral("about:srcdoc");
|
||||
principal = mOwnerContent->NodePrincipal();
|
||||
// Currently the NodePrincipal holds the CSP for a document. After
|
||||
// Bug 965637 we can query the CSP from mOwnerContent->OwnerDoc()
|
||||
// instead of mOwnerContent->NodePrincipal().
|
||||
mOwnerContent->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
csp = mOwnerContent->GetCsp();
|
||||
} else {
|
||||
GetURL(src, getter_AddRefs(principal), getter_AddRefs(csp));
|
||||
|
||||
|
@ -425,10 +423,7 @@ void nsFrameLoader::LoadFrame(bool aOriginalSrc) {
|
|||
}
|
||||
src.AssignLiteral("about:blank");
|
||||
principal = mOwnerContent->NodePrincipal();
|
||||
// Currently the NodePrincipal holds the CSP for a document. After
|
||||
// Bug 965637 we can query the CSP from mOwnerContent->OwnerDoc()
|
||||
// instead of mOwnerContent->NodePrincipal().
|
||||
mOwnerContent->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
csp = mOwnerContent->GetCsp();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -520,8 +515,7 @@ void nsFrameLoader::ResumeLoad(uint64_t aPendingSwitchID) {
|
|||
mURIToLoad = nullptr;
|
||||
mPendingSwitchID = aPendingSwitchID;
|
||||
mTriggeringPrincipal = mOwnerContent->NodePrincipal();
|
||||
// NOTE: This can be gotten off of the document after bug 965637.
|
||||
mOwnerContent->NodePrincipal()->GetCsp(getter_AddRefs(mCsp));
|
||||
mCsp = mOwnerContent->GetCsp();
|
||||
|
||||
nsresult rv = doc->InitializeFrameLoader(this);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -627,18 +621,14 @@ nsresult nsFrameLoader::ReallyStartLoadingInternal() {
|
|||
}
|
||||
|
||||
// If we have an explicit CSP, we set it. If not, we only query it from
|
||||
// the NodePrincipal in case there was no explicit triggeringPrincipal.
|
||||
// the document in case there was no explicit triggeringPrincipal.
|
||||
// Otherwise it's possible that the original triggeringPrincipal did not
|
||||
// have a CSP which causes the CSP on the Principal and explicit CSP
|
||||
// to be out of sync.
|
||||
if (mCsp) {
|
||||
loadState->SetCsp(mCsp);
|
||||
} else if (!mTriggeringPrincipal) {
|
||||
// Currently the NodePrincipal holds the CSP for a document. After
|
||||
// Bug 965637 we can query the CSP from mOwnerContent->OwnerDoc()
|
||||
// instead of mOwnerContent->NodePrincipal().
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
mOwnerContent->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = mOwnerContent->GetCsp();
|
||||
loadState->SetCsp(csp);
|
||||
}
|
||||
|
||||
|
@ -2343,16 +2333,12 @@ void nsFrameLoader::GetURL(nsString& aURI, nsIPrincipal** aTriggeringPrincipal,
|
|||
nsIContentSecurityPolicy** aCsp) {
|
||||
aURI.Truncate();
|
||||
// Within this function we default to using the NodePrincipal as the
|
||||
// triggeringPrincipal and the CSP of the document, currently stored
|
||||
// on the NodePrincipal. After Bug 965637 we can query the CSP from
|
||||
// mOwnerContent->OwnerDoc() instead of mOwnerContent->NodePrincipal().
|
||||
// triggeringPrincipal and the CSP of the document.
|
||||
// Expanded Principals however override the CSP of the document, hence
|
||||
// if frame->GetSrcTriggeringPrincipal() returns a valid principal, we
|
||||
// have to query the CSP from that Principal. Note that even after
|
||||
// Bug 965637, Expanded Principals will hold their own CSP.
|
||||
// have to query the CSP from that Principal.
|
||||
nsCOMPtr<nsIPrincipal> triggeringPrincipal = mOwnerContent->NodePrincipal();
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
mOwnerContent->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = mOwnerContent->GetCsp();
|
||||
|
||||
if (mOwnerContent->IsHTMLElement(nsGkAtoms::object)) {
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, aURI);
|
||||
|
@ -2363,7 +2349,11 @@ void nsFrameLoader::GetURL(nsString& aURI, nsIPrincipal** aTriggeringPrincipal,
|
|||
nsCOMPtr<nsIPrincipal> srcPrincipal = frame->GetSrcTriggeringPrincipal();
|
||||
if (srcPrincipal) {
|
||||
triggeringPrincipal = srcPrincipal;
|
||||
triggeringPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
nsCOMPtr<nsIExpandedPrincipal> ep =
|
||||
do_QueryInterface(triggeringPrincipal);
|
||||
if (ep) {
|
||||
csp = ep->GetCsp();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "nsDOMWindowList.h"
|
||||
#include "mozilla/dom/WakeLock.h"
|
||||
#include "mozilla/dom/power/PowerManagerService.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsIDocShellTreeOwner.h"
|
||||
#include "nsIDocumentLoader.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
|
@ -1122,11 +1123,12 @@ void nsGlobalWindowInner::FreeInnerObjects() {
|
|||
#endif
|
||||
|
||||
if (mDoc) {
|
||||
// Remember the document's principal and URI.
|
||||
// Remember the document's principal, URI, and CSP.
|
||||
mDocumentPrincipal = mDoc->NodePrincipal();
|
||||
mDocumentStoragePrincipal = mDoc->EffectiveStoragePrincipal();
|
||||
mDocumentURI = mDoc->GetDocumentURI();
|
||||
mDocBaseURI = mDoc->GetDocBaseURI();
|
||||
mDocumentCsp = mDoc->GetCsp();
|
||||
|
||||
while (mDoc->EventHandlingSuppressed()) {
|
||||
mDoc->UnsuppressEventHandlingAndFireEvents(false);
|
||||
|
@ -1350,6 +1352,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowInner)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentStoragePrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentCsp)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserChild)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)
|
||||
|
||||
|
@ -1454,6 +1457,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)
|
|||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentStoragePrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentCsp)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserChild)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
|
||||
|
||||
|
@ -1789,6 +1793,14 @@ nsresult nsGlobalWindowInner::EnsureClientSource() {
|
|||
}
|
||||
}
|
||||
|
||||
// Generally the CSP is stored within the Client and cached on the document.
|
||||
// At the time of CSP parsing however, the Client has not been created yet,
|
||||
// hence we store the CSP on the document and propagate/sync the CSP with
|
||||
// Client here when we create the Client.
|
||||
if (mClientSource) {
|
||||
mClientSource->SetCsp(mDoc->GetCsp());
|
||||
}
|
||||
|
||||
// Its possible that we got a client just after being frozen in
|
||||
// the bfcache. In that case freeze the client immediately.
|
||||
if (newClientSource && IsFrozen()) {
|
||||
|
@ -2197,6 +2209,18 @@ Maybe<ServiceWorkerDescriptor> nsPIDOMWindowInner::GetController() const {
|
|||
return nsGlobalWindowInner::Cast(this)->GetController();
|
||||
}
|
||||
|
||||
void nsPIDOMWindowInner::SetCsp(nsIContentSecurityPolicy* aCsp) {
|
||||
return nsGlobalWindowInner::Cast(this)->SetCsp(aCsp);
|
||||
}
|
||||
|
||||
void nsPIDOMWindowInner::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCsp) {
|
||||
return nsGlobalWindowInner::Cast(this)->SetPreloadCsp(aPreloadCsp);
|
||||
}
|
||||
|
||||
nsIContentSecurityPolicy* nsPIDOMWindowInner::GetCsp() {
|
||||
return nsGlobalWindowInner::Cast(this)->GetCsp();
|
||||
}
|
||||
|
||||
void nsPIDOMWindowInner::NoteCalledRegisterForServiceWorkerScope(
|
||||
const nsACString& aScope) {
|
||||
nsGlobalWindowInner::Cast(this)->NoteCalledRegisterForServiceWorkerScope(
|
||||
|
@ -5363,6 +5387,37 @@ Maybe<ServiceWorkerDescriptor> nsGlobalWindowInner::GetController() const {
|
|||
return controller;
|
||||
}
|
||||
|
||||
void nsGlobalWindowInner::SetCsp(nsIContentSecurityPolicy* aCsp) {
|
||||
if (!mClientSource) {
|
||||
return;
|
||||
}
|
||||
mClientSource->SetCsp(aCsp);
|
||||
// Also cache the CSP within the document
|
||||
mDoc->SetCsp(aCsp);
|
||||
}
|
||||
|
||||
void nsGlobalWindowInner::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCsp) {
|
||||
if (!mClientSource) {
|
||||
return;
|
||||
}
|
||||
mClientSource->SetPreloadCsp(aPreloadCsp);
|
||||
// Also cache the preload CSP within the document
|
||||
mDoc->SetPreloadCsp(aPreloadCsp);
|
||||
}
|
||||
|
||||
nsIContentSecurityPolicy* nsGlobalWindowInner::GetCsp() {
|
||||
if (mDoc) {
|
||||
return mDoc->GetCsp();
|
||||
}
|
||||
|
||||
// If the window is partially torn down and has its document nulled out,
|
||||
// we query the CSP we snapshot in FreeInnerObjects.
|
||||
if (mDocumentCsp) {
|
||||
return mDocumentCsp;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorker> nsGlobalWindowInner::GetOrCreateServiceWorker(
|
||||
const ServiceWorkerDescriptor& aDescriptor) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
|
|
@ -322,6 +322,10 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
|||
mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController()
|
||||
const override;
|
||||
|
||||
void SetCsp(nsIContentSecurityPolicy* aCsp);
|
||||
void SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCsp);
|
||||
nsIContentSecurityPolicy* GetCsp();
|
||||
|
||||
virtual RefPtr<mozilla::dom::ServiceWorker> GetOrCreateServiceWorker(
|
||||
const mozilla::dom::ServiceWorkerDescriptor& aDescriptor) override;
|
||||
|
||||
|
@ -1301,8 +1305,11 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
|||
|
||||
RefPtr<mozilla::dom::VisualViewport> mVisualViewport;
|
||||
|
||||
// The document's principals and CSP are only stored if
|
||||
// FreeInnerObjects has been called.
|
||||
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
|
||||
nsCOMPtr<nsIPrincipal> mDocumentStoragePrincipal;
|
||||
nsCOMPtr<nsIContentSecurityPolicy> mDocumentCsp;
|
||||
|
||||
// mBrowserChild is only ever populated in the content process.
|
||||
nsCOMPtr<nsIBrowserChild> mBrowserChild;
|
||||
|
|
|
@ -1548,7 +1548,8 @@ bool nsGlobalWindowOuter::WouldReuseInnerWindow(Document* aNewDocument) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void nsGlobalWindowOuter::SetInitialPrincipalToSubject() {
|
||||
void nsGlobalWindowOuter::SetInitialPrincipalToSubject(
|
||||
nsIContentSecurityPolicy* aCSP) {
|
||||
// First, grab the subject principal.
|
||||
nsCOMPtr<nsIPrincipal> newWindowPrincipal =
|
||||
nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
|
||||
|
@ -1581,7 +1582,7 @@ void nsGlobalWindowOuter::SetInitialPrincipalToSubject() {
|
|||
#endif
|
||||
}
|
||||
|
||||
GetDocShell()->CreateAboutBlankContentViewer(newWindowPrincipal);
|
||||
GetDocShell()->CreateAboutBlankContentViewer(newWindowPrincipal, aCSP);
|
||||
|
||||
if (mDoc) {
|
||||
mDoc->SetIsInitialDocument(true);
|
||||
|
|
|
@ -298,7 +298,8 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
|
|||
mozilla::dom::EventTarget* aChromeEventHandler) override;
|
||||
|
||||
// Outer windows only.
|
||||
virtual void SetInitialPrincipalToSubject() override;
|
||||
virtual void SetInitialPrincipalToSubject(
|
||||
nsIContentSecurityPolicy* aCSP) override;
|
||||
|
||||
virtual already_AddRefed<nsISupports> SaveWindowState() override;
|
||||
virtual nsresult RestoreWindowState(nsISupports* aState) override;
|
||||
|
|
|
@ -195,6 +195,10 @@ void* nsINode::UnsetProperty(const nsAtom* aPropertyName, nsresult* aStatus) {
|
|||
aStatus);
|
||||
}
|
||||
|
||||
nsIContentSecurityPolicy* nsINode::GetCsp() const {
|
||||
return OwnerDoc()->GetCsp();
|
||||
}
|
||||
|
||||
nsINode::nsSlots* nsINode::CreateSlots() { return new nsSlots(); }
|
||||
|
||||
nsIContent* nsINode::GetTextEditorRootContent(TextEditor** aTextEditor) {
|
||||
|
|
|
@ -40,6 +40,7 @@ class nsAttrChildContentList;
|
|||
class nsDOMAttributeMap;
|
||||
class nsIAnimationObserver;
|
||||
class nsIContent;
|
||||
class nsIContentSecurityPolicy;
|
||||
class nsIFrame;
|
||||
class nsIHTMLCollection;
|
||||
class nsIMutationObserver;
|
||||
|
@ -854,6 +855,11 @@ class nsINode : public mozilla::dom::EventTarget {
|
|||
return mNodeInfo->NodeInfoManager()->DocumentPrincipal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CSP of this node's document, if any.
|
||||
*/
|
||||
nsIContentSecurityPolicy* GetCsp() const;
|
||||
|
||||
/**
|
||||
* Get the parent nsIContent for this node.
|
||||
* @return the parent, or null if no parent or the parent is not an nsIContent
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsError.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "nsIScriptTimeoutHandler.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
|
|
@ -228,10 +228,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent,
|
|||
mozilla::ErrorResult& aRv) {
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
void LegacyCall(JSContext* aCx, JS::Handle<JS::Value> aThisVal,
|
||||
const mozilla::dom::Sequence<JS::Value>& aArguments,
|
||||
JS::MutableHandle<JS::Value> aRetval,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
uint32_t GetRunID(mozilla::dom::SystemCallerGuarantee,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
|
|
@ -31,6 +31,7 @@ class nsGlobalWindowOuter;
|
|||
class nsIArray;
|
||||
class nsIChannel;
|
||||
class nsIContent;
|
||||
class nsIContentSecurityPolicy;
|
||||
class nsICSSDeclaration;
|
||||
class nsIDocShell;
|
||||
class nsDocShellLoadState;
|
||||
|
@ -326,6 +327,10 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
|
|||
mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
|
||||
mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
|
||||
|
||||
void SetCsp(nsIContentSecurityPolicy* aCsp);
|
||||
void SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCsp);
|
||||
nsIContentSecurityPolicy* GetCsp();
|
||||
|
||||
void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
|
||||
|
||||
void NoteDOMContentLoaded();
|
||||
|
@ -821,8 +826,8 @@ class nsPIDOMWindowOuter : public mozIDOMWindowProxy {
|
|||
}
|
||||
|
||||
// Set the window up with an about:blank document with the current subject
|
||||
// principal.
|
||||
virtual void SetInitialPrincipalToSubject() = 0;
|
||||
// principal and potentially a CSP.
|
||||
virtual void SetInitialPrincipalToSubject(nsIContentSecurityPolicy* aCSP) = 0;
|
||||
|
||||
// Returns an object containing the window's state. This also suspends
|
||||
// all running timeouts in the window.
|
||||
|
|
|
@ -330,9 +330,8 @@ nsStyleLinkElement::DoUpdateStyleSheet(Document* aOldDocument,
|
|||
MOZ_ASSERT(thisContent->IsElement());
|
||||
nsresult rv = NS_OK;
|
||||
if (!nsStyleUtil::CSPAllowsInlineStyle(
|
||||
thisContent->AsElement(), thisContent->NodePrincipal(),
|
||||
info->mTriggeringPrincipal, doc->GetDocumentURI(), mLineNumber,
|
||||
mColumnNumber, text, &rv)) {
|
||||
thisContent->AsElement(), doc, info->mTriggeringPrincipal,
|
||||
mLineNumber, mColumnNumber, text, &rv)) {
|
||||
if (NS_FAILED(rv)) {
|
||||
return Err(rv);
|
||||
}
|
||||
|
|
|
@ -185,9 +185,9 @@ void nsStyledElement::ParseStyleAttribute(const nsAString& aValue,
|
|||
Document* doc = OwnerDoc();
|
||||
bool isNativeAnon = IsInNativeAnonymousSubtree();
|
||||
|
||||
if (!isNativeAnon && !nsStyleUtil::CSPAllowsInlineStyle(
|
||||
this, NodePrincipal(), aMaybeScriptedPrincipal,
|
||||
doc->GetDocumentURI(), 0, 0, aValue, nullptr))
|
||||
if (!isNativeAnon &&
|
||||
!nsStyleUtil::CSPAllowsInlineStyle(this, doc, aMaybeScriptedPrincipal, 0,
|
||||
0, aValue, nullptr))
|
||||
return;
|
||||
|
||||
if (aForceInDataDoc || !doc->IsLoadedAsData() || GetExistingStyle() ||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче