Bug 1567443 - Added flag for indicating secure Chrome UI in nsIAboutModule. r=pbz,webcompat-reviewers,twisniewski

Differential Revision: https://phabricator.services.mozilla.com/D128188
This commit is contained in:
Hannah Peuckmann 2021-10-26 13:32:31 +00:00
parent 6ee464104f
commit 09b6c3a033
12 changed files with 161 additions and 53 deletions

View file

@ -53,12 +53,6 @@ var gIdentityHandler = {
*/
_state: 0,
/**
* RegExp used to decide if an about url should be shown as being part of
* the browser UI.
*/
_secureInternalPages: /^(?:accounts|addons|cache|certificate|config|crashes|downloads|license|logins|preferences|protections|rights|sessionrestore|support|welcomeback|ion)(?:[?#]|$)/i,
/**
* Whether the established HTTPS connection is considered "broken".
* This could have several reasons, such as mixed content or weak
@ -1149,9 +1143,17 @@ var gIdentityHandler = {
this._uriHasHost = false;
}
this._isSecureInternalUI =
uri.schemeIs("about") && this._secureInternalPages.test(uri.pathQueryRef);
if (uri.schemeIs("about")) {
let module = E10SUtils.getAboutModule(uri);
if (module) {
let flags = module.getURIFlags(uri);
this._isSecureInternalUI = !!(
flags & Ci.nsIAboutModule.IS_SECURE_CHROME_UI
);
}
} else {
this._isSecureInternalUI = false;
}
this._pageExtensionPolicy = WebExtensionPolicy.getByURI(uri);
// Create a channel for the sole purpose of getting the resolved URI

View file

@ -4,6 +4,9 @@
"use strict";
const { AppConstants } = ChromeUtils.import(
"resource://gre/modules/AppConstants.jsm"
);
const DUMMY = "browser/browser/base/content/test/siteIdentity/dummy_page.html";
const INSECURE_ICON_PREF = "security.insecure_connection_icon.enabled";
const INSECURE_TEXT_PREF = "security.insecure_connection_text.enabled";
@ -56,6 +59,82 @@ async function getReaderModeURL() {
// This test is slow on Linux debug e10s
requestLongerTimeout(2);
add_task(async function chromeUITest() {
// needs to be set due to bug in ion.js that occurs when testing
SpecialPowers.pushPrefEnv({
set: [
["toolkit.pioneer.testCachedContent", "[]"],
["toolkit.pioneer.testCachedAddons", "[]"],
],
});
// Might needs to be extended with new secure chrome pages
// about:debugging is a secure chrome UI but is not tested for causing problems.
let secureChromePages = [
"addons",
"cache",
"certificate",
"compat",
"config",
"devtools",
"downloads",
"ion",
"license",
"logins",
"loginsimportreport",
"performance",
"plugins",
"policies",
"preferences",
"processes",
"profiles",
"profiling",
"protections",
"rights",
"sessionrestore",
"studies",
"support",
"telemetry",
"welcomeback",
];
// else skip about:crashes, it is only available with plugin
if (AppConstants.MOZ_CRASHREPORTER) {
secureChromePages.push("crashes");
}
let nonSecureExamplePages = [
"about:about",
"about:credits",
"about:home",
"about:logo",
"about:memory",
"about:mozilla",
"about:networking",
"about:privatebrowsing",
"about:robots",
"about:serviceWorkers",
"about:sync-log",
"about:unloads",
"about:url-classifier",
"about:webrtc",
"about:welcome",
"http://example.com/" + DUMMY,
];
for (let i = 0; i < secureChromePages.length; i++) {
await BrowserTestUtils.withNewTab("about:" + secureChromePages[i], () => {
is(getIdentityMode(), "chromeUI", "Identity should be chromeUI");
});
}
for (let i = 0; i < nonSecureExamplePages.length; i++) {
console.log(nonSecureExamplePages[i]);
await BrowserTestUtils.withNewTab(nonSecureExamplePages[i], () => {
ok(getIdentityMode() != "chromeUI", "Identity should not be chromeUI");
});
}
});
async function webpageTest(secureCheck) {
await SpecialPowers.pushPrefEnv({ set: [[INSECURE_ICON_PREF, secureCheck]] });
let oldTab = await loadNewTab("about:robots");

View file

@ -65,34 +65,38 @@ static const RedirEntry kRedirMap[] = {
{"logins", "chrome://browser/content/aboutlogins/aboutLogins.html",
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS |
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT},
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::IS_SECURE_CHROME_UI},
{"loginsimportreport",
"chrome://browser/content/aboutlogins/aboutLoginsImportReport.html",
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS |
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT},
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::IS_SECURE_CHROME_UI},
{"tabcrashed", "chrome://browser/content/aboutTabCrashed.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT},
{"policies", "chrome://browser/content/policies/aboutPolicies.html",
nsIAboutModule::ALLOW_SCRIPT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI},
{"privatebrowsing", "chrome://browser/content/aboutPrivateBrowsing.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS},
{"profiling",
"chrome://devtools/content/performance-new/aboutprofiling/index.xhtml",
nsIAboutModule::ALLOW_SCRIPT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI},
{"rights", "chrome://global/content/aboutRights.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI},
{"robots", "chrome://browser/content/aboutRobots.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT},
{"sessionrestore", "chrome://browser/content/aboutSessionRestore.xhtml",
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT |
nsIAboutModule::IS_SECURE_CHROME_UI},
{"welcomeback", "chrome://browser/content/aboutWelcomeBack.xhtml",
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT |
nsIAboutModule::IS_SECURE_CHROME_UI},
// Actual activity stream URL for home and newtab are set in channel
// creation
{"home", "about:blank", ACTIVITY_STREAM_FLAGS},
@ -115,10 +119,10 @@ static const RedirEntry kRedirMap[] = {
nsIAboutModule::URI_CAN_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT},
{"preferences", "chrome://browser/content/preferences/preferences.xhtml",
nsIAboutModule::ALLOW_SCRIPT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI},
{"downloads",
"chrome://browser/content/downloads/contentAreaDownloadsView.xhtml",
nsIAboutModule::ALLOW_SCRIPT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI},
{"reader", "chrome://global/content/reader/aboutReader.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
@ -128,9 +132,11 @@ static const RedirEntry kRedirMap[] = {
{"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_PRIVILEGEDABOUT_PROCESS},
nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS |
nsIAboutModule::IS_SECURE_CHROME_UI},
{"ion", "chrome://browser/content/ion.html",
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT |
nsIAboutModule::IS_SECURE_CHROME_UI},
};
static nsAutoCString GetAboutModuleName(nsIURI* aURI) {

View file

@ -19,7 +19,10 @@ function AboutCompat() {
AboutCompat.prototype = {
QueryInterface: ChromeUtils.generateQI(["nsIAboutModule"]),
getURIFlags() {
return Ci.nsIAboutModule.URI_MUST_LOAD_IN_EXTENSION_PROCESS;
return (
Ci.nsIAboutModule.URI_MUST_LOAD_IN_EXTENSION_PROCESS |
Ci.nsIAboutModule.IS_SECURE_CHROME_UI
);
},
newChannel(aURI, aLoadInfo) {

View file

@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "Web Compatibility Interventions",
"description": "Urgent post-release fixes for web compatibility.",
"version": "27.4.0",
"version": "27.5.0",
"applications": {
"gecko": {
"id": "webcompat@mozilla.org",

View file

@ -29,7 +29,7 @@ AboutDebugging.prototype = {
},
getURIFlags: function(uri) {
return nsIAboutModule.ALLOW_SCRIPT;
return nsIAboutModule.ALLOW_SCRIPT | nsIAboutModule.IS_SECURE_CHROME_UI;
},
getChromeURI: function(_uri) {

View file

@ -29,7 +29,7 @@ AboutDevtools.prototype = {
},
getURIFlags: function(uri) {
return nsIAboutModule.ALLOW_SCRIPT;
return nsIAboutModule.ALLOW_SCRIPT | nsIAboutModule.IS_SECURE_CHROME_UI;
},
getChromeURI: function(_uri) {

View file

@ -65,19 +65,23 @@ class CrashChannel final : public nsBaseChannel {
static const RedirEntry kRedirMap[] = {
{"about", "chrome://global/content/aboutAbout.html", 0},
{"addons", "chrome://mozapps/content/extensions/aboutaddons.html",
nsIAboutModule::ALLOW_SCRIPT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI},
{"buildconfig", "chrome://global/content/buildconfig.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT},
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::IS_SECURE_CHROME_UI},
{"checkerboard", "chrome://global/content/aboutCheckerboard.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT},
#ifndef MOZ_WIDGET_ANDROID
{"config", "chrome://global/content/aboutconfig/aboutconfig.html", 0},
{"config", "chrome://global/content/aboutconfig/aboutconfig.html",
nsIAboutModule::IS_SECURE_CHROME_UI},
#else
{"config", "chrome://geckoview/content/config.xhtml", 0},
{"config", "chrome://geckoview/content/config.xhtml",
nsIAboutModule::IS_SECURE_CHROME_UI},
#endif
#ifdef MOZ_CRASHREPORTER
{"crashes", "chrome://global/content/crashes.html", 0},
{"crashes", "chrome://global/content/crashes.html",
nsIAboutModule::IS_SECURE_CHROME_UI},
#endif
{"credits", "https://www.mozilla.org/credits/",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
@ -87,7 +91,8 @@ static const RedirEntry kRedirMap[] = {
nsIAboutModule::URI_CAN_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT},
{"license", "chrome://global/content/license.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT},
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::IS_SECURE_CHROME_UI},
{"logo", "chrome://branding/content/about.png",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
// Linkable for testing reasons.
@ -98,7 +103,8 @@ static const RedirEntry kRedirMap[] = {
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS},
nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS |
nsIAboutModule::IS_SECURE_CHROME_UI},
{"mozilla", "chrome://global/content/mozilla.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT},
{"neterror", "chrome://global/content/netError.xhtml",
@ -108,11 +114,12 @@ static const RedirEntry kRedirMap[] = {
{"networking", "chrome://global/content/aboutNetworking.html",
nsIAboutModule::ALLOW_SCRIPT},
{"performance", "chrome://global/content/aboutPerformance.html",
nsIAboutModule::ALLOW_SCRIPT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI},
{"plugins", "chrome://global/content/plugins.html",
nsIAboutModule::URI_MUST_LOAD_IN_CHILD},
nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
nsIAboutModule::IS_SECURE_CHROME_UI},
{"processes", "chrome://global/content/aboutProcesses.html",
nsIAboutModule::ALLOW_SCRIPT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI},
// about:serviceworkers always wants to load in the parent process because
// the only place nsIServiceWorkerManager has any data is in the parent
// process.
@ -125,7 +132,7 @@ static const RedirEntry kRedirMap[] = {
nsIAboutModule::ALLOW_SCRIPT},
#ifndef ANDROID
{"profiles", "chrome://global/content/aboutProfiles.xhtml",
nsIAboutModule::ALLOW_SCRIPT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI},
#endif
// about:srcdoc is unresolvable by specification. It is included here
// because the security manager would disallow srcdoc iframes otherwise.
@ -135,7 +142,7 @@ static const RedirEntry kRedirMap[] = {
// Needs to be linkable so content can touch its own srcdoc frames
nsIAboutModule::MAKE_LINKABLE | nsIAboutModule::URI_CAN_LOAD_IN_CHILD},
{"support", "chrome://global/content/aboutSupport.xhtml",
nsIAboutModule::ALLOW_SCRIPT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI},
#ifdef XP_WIN
{"third-party", "chrome://global/content/aboutThirdParty.html",
nsIAboutModule::ALLOW_SCRIPT},
@ -145,7 +152,7 @@ static const RedirEntry kRedirMap[] = {
nsIAboutModule::HIDE_FROM_ABOUTABOUT | nsIAboutModule::ALLOW_SCRIPT},
#endif
{"telemetry", "chrome://global/content/aboutTelemetry.xhtml",
nsIAboutModule::ALLOW_SCRIPT},
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI},
{"url-classifier", "chrome://global/content/aboutUrlClassifier.xhtml",
nsIAboutModule::ALLOW_SCRIPT},
{"webrtc", "chrome://global/content/aboutwebrtc/aboutWebrtc.html",

View file

@ -508,7 +508,8 @@ nsresult nsAboutCache::Channel::FlushBuffer() {
NS_IMETHODIMP
nsAboutCache::GetURIFlags(nsIURI* aURI, uint32_t* result) {
*result = nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT;
*result = nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::IS_SECURE_CHROME_UI;
return NS_OK;
}

View file

@ -92,6 +92,11 @@ interface nsIAboutModule : nsISupports
*/
const unsigned long ALLOW_UNSANITIZED_CONTENT = (1 << 10);
/**
* A flag that indicates that this about: URI is a secure chrome UI
*/
const unsigned long IS_SECURE_CHROME_UI = (1 << 11);
/**
* A method to get the flags that apply to a given about: URI. The URI
* passed in is guaranteed to be one of the URIs that this module

View file

@ -108,7 +108,8 @@ XPCOMUtils.defineLazyGetter(AboutPages, "aboutStudies", () => {
uriFlags:
Ci.nsIAboutModule.ALLOW_SCRIPT |
Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD,
Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD |
Ci.nsIAboutModule.IS_SECURE_CHROME_UI,
});
// Extra methods for about:study-specific behavior.

View file

@ -57,19 +57,6 @@ XPCOMUtils.defineLazyServiceGetter(
"nsIExternalProtocolService"
);
function getAboutModule(aURL) {
// Needs to match NS_GetAboutModuleName
let moduleName = aURL.pathQueryRef.replace(/[#?].*/, "").toLowerCase();
let contract = "@mozilla.org/network/protocol/about;1?what=" + moduleName;
try {
return Cc[contract].getService(Ci.nsIAboutModule);
} catch (e) {
// Either the about module isn't defined or it is broken. In either case
// ignore it.
return null;
}
}
function getOriginalReaderModeURI(aURI) {
try {
let searchParams = new URLSearchParams(aURI.query);
@ -278,6 +265,23 @@ var E10SUtils = {
LARGE_ALLOCATION_REMOTE_TYPE,
FISSION_WEB_REMOTE_TYPE,
/**
* @param aURI The URI of the about page
* @return The instance of the nsIAboutModule related to this uri
*/
getAboutModule(aURL) {
// Needs to match NS_GetAboutModuleName
let moduleName = aURL.pathQueryRef.replace(/[#?].*/, "").toLowerCase();
let contract = "@mozilla.org/network/protocol/about;1?what=" + moduleName;
try {
return Cc[contract].getService(Ci.nsIAboutModule);
} catch (e) {
// Either the about module isn't defined or it is broken. In either case
// ignore it.
return null;
}
},
useCrossOriginOpenerPolicy() {
return useCrossOriginOpenerPolicy;
},
@ -442,7 +446,7 @@ var E10SUtils = {
: DEFAULT_REMOTE_TYPE;
case "about":
let module = getAboutModule(aURI);
let module = this.getAboutModule(aURI);
// If the module doesn't exist then an error page will be loading, that
// should be ok to load in any process
if (!module) {