1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 * RemotePageAccessManager determines which RPM functions a given
7 * about page is allowed to access. It does this based on a map from about
8 * page URLs to allowed functions for that page/URL.
10 * An RPM function will be exported into the page only if it appears
11 * in the access managers's accessMap for that page's uri.
13 * This module may be used from both the child and parent process.
15 * Please note that prefs that one wants to update need to be
16 * explicitly allowed within AsyncPrefs.sys.mjs.
18 export let RemotePageAccessManager = {
19 /* The accessMap lists the permissions that are allowed per page.
20 * The structure should be of the following form:
22 * <function name>: [<keys>],
25 * For the page with given URL, permission is allowed for each
26 * listed function with a matching key. The first argument to the
27 * function must match one of the keys. If keys is an array with a
28 * single asterisk element ["*"], then all values are permitted.
32 RPMSendAsyncMessage: [
33 "Browser:EnableOnlineMode",
34 "Browser:ResetSSLPreferences",
35 "GetChangedCertPrefs",
36 "Browser:OpenCaptivePortalPage",
37 "Browser:SSLErrorGoBack",
39 "Browser:ResetEnterpriseRootsPref",
40 "DisplayOfflineSupportPage",
42 RPMRecordGleanEvent: ["*"],
43 RPMAddMessageListener: ["*"],
44 RPMRemoveMessageListener: ["*"],
45 RPMGetFormatURLPref: ["app.support.baseURL"],
47 "security.certerrors.mitm.priming.enabled",
48 "security.certerrors.permanentOverride",
49 "security.enterprise_roots.auto-enabled",
50 "security.certerror.hideAddException",
51 "network.trr.display_fallback_warning",
52 "security.certerrors.felt-privacy-v1",
55 "security.dialog_enable_delay",
56 "services.settings.clock_skew_seconds",
57 "services.settings.last_update_seconds",
59 RPMGetAppBuildID: ["*"],
60 RPMGetInnerMostURI: ["*"],
61 RPMIsWindowPrivate: ["*"],
62 RPMAddToHistogram: ["*"],
65 RPMSendAsyncMessage: ["ActivityStream:ContentToMain"],
66 RPMAddMessageListener: ["ActivityStream:MainToContent"],
68 "about:httpsonlyerror": {
69 RPMGetFormatURLPref: ["app.support.baseURL"],
70 RPMGetIntPref: ["security.dialog_enable_delay"],
71 RPMSendAsyncMessage: ["goBack", "openInsecure"],
72 RPMAddMessageListener: ["WWWReachable"],
73 RPMTryPingSecureWWWLink: ["*"],
74 RPMOpenSecureWWWLink: ["*"],
76 "about:certificate": {
77 RPMSendQuery: ["getCertificates"],
80 RPMSendAsyncMessage: [
81 "Browser:EnableOnlineMode",
82 "Browser:ResetSSLPreferences",
83 "GetChangedCertPrefs",
84 "Browser:OpenCaptivePortalPage",
85 "Browser:SSLErrorGoBack",
87 "Browser:ResetEnterpriseRootsPref",
88 "ReportBlockingError",
89 "DisplayOfflineSupportPage",
92 RPMCheckAlternateHostAvailable: ["*"],
93 RPMRecordGleanEvent: ["securityDohNeterror", "securityUiTlserror"],
94 RPMAddMessageListener: ["*"],
95 RPMRemoveMessageListener: ["*"],
96 RPMGetFormatURLPref: [
97 "app.support.baseURL",
98 "network.trr_ui.skip_reason_learn_more_url",
101 "security.certerror.hideAddException",
102 "security.xfocsp.errorReporting.automatic",
103 "security.xfocsp.errorReporting.enabled",
104 "security.xfocsp.hideOpenInNewWindow",
105 "network.trr.display_fallback_warning",
106 "security.certerrors.felt-privacy-v1",
109 "security.xfocsp.errorReporting.automatic",
110 "network.trr.display_fallback_warning",
112 RPMAddToHistogram: ["*"],
113 RPMGetInnerMostURI: ["*"],
114 RPMGetHttpResponseHeader: ["*"],
115 RPMIsTRROnlyFailure: ["*"],
117 RPMIsNativeFallbackFailure: ["*"],
118 RPMGetTRRSkipReason: ["*"],
119 RPMGetTRRDomain: ["*"],
120 RPMIsSiteSpecificTRRError: ["*"],
121 RPMSetTRRDisabledLoadFlags: ["*"],
122 RPMShowOSXLocalNetworkPermissionWarning: ["*"],
123 RPMSendQuery: ["Browser:AddTRRExcludedDomain"],
124 RPMGetIntPref: ["network.trr.mode"],
127 RPMSendAsyncMessage: ["ActivityStream:ContentToMain"],
128 RPMAddMessageListener: ["ActivityStream:MainToContent"],
130 "about:pocket-saved": {
131 RPMSendAsyncMessage: ["*"],
132 RPMAddMessageListener: ["*"],
133 RPMRemoveMessageListener: ["*"],
134 RPMGetStringPref: ["extensions.pocket.site"],
136 "about:pocket-signup": {
137 RPMSendAsyncMessage: ["*"],
138 RPMAddMessageListener: ["*"],
139 RPMRemoveMessageListener: ["*"],
140 RPMGetStringPref: ["extensions.pocket.site"],
142 "about:pocket-home": {
143 RPMSendAsyncMessage: ["*"],
144 RPMAddMessageListener: ["*"],
145 RPMRemoveMessageListener: ["*"],
146 RPMGetStringPref: ["extensions.pocket.site"],
148 "about:pocket-style-guide": {
149 RPMSendAsyncMessage: ["*"],
150 RPMAddMessageListener: ["*"],
151 RPMRemoveMessageListener: ["*"],
153 "about:privatebrowsing": {
154 RPMSendAsyncMessage: [
156 "SearchBannerDismissed",
157 "OpenSearchPreferences",
162 "ShouldShowSearchBanner",
164 "SpecialMessageActionDispatch",
166 RPMAddMessageListener: ["*"],
167 RPMRemoveMessageListener: ["*"],
168 RPMGetFormatURLPref: [
169 "app.support.baseURL",
170 "browser.privatebrowsing.vpnpromourl",
172 RPMIsWindowPrivate: ["*"],
173 RPMGetBoolPref: ["browser.privatebrowsing.felt-privacy-v1"],
175 "about:deleteprofile": {
176 RPMSendQuery: ["Profiles:GetDeleteProfileContent"],
177 RPMSendAsyncMessage: ["Profiles:CancelDelete", "Profiles:DeleteProfile"],
179 "about:editprofile": {
181 "Profiles:GetEditProfileContent",
182 "Profiles:UpdateProfileTheme",
184 RPMSendAsyncMessage: [
185 "Profiles:UpdateProfileName",
186 "Profiles:UpdateProfileAvatar",
187 "Profiles:OpenDeletePage",
188 "Profiles:CloseProfileTab",
191 "about:newprofile": {
193 "Profiles:GetNewProfileContent",
194 "Profiles:UpdateProfileTheme",
196 RPMSendAsyncMessage: [
197 "Profiles:UpdateProfileName",
198 "Profiles:UpdateProfileAvatar",
199 "Profiles:DeleteProfile",
200 "Profiles:CloseProfileTab",
202 RPMGetBoolPref: ["browser.profiles.profile-name.updated"],
203 RPMGetFormatURLPref: ["app.support.baseURL"],
205 "about:protections": {
206 RPMSendAsyncMessage: [
207 "OpenContentBlockingPreferences",
209 "OpenSyncPreferences",
214 "FetchUserLoginsData",
216 "FetchContentBlockingEvents",
217 "FetchMobileDeviceConnected",
223 RPMAddMessageListener: ["*"],
224 RPMRemoveMessageListener: ["*"],
226 "browser.contentblocking.report.show_mobile_app",
227 "browser.contentblocking.report.hide_vpn_banner",
230 "browser.contentblocking.report.lockwise.enabled",
231 "browser.contentblocking.report.monitor.enabled",
232 "privacy.fingerprintingProtection",
233 "privacy.socialtracking.block_cookies.enabled",
234 "browser.contentblocking.report.proxy.enabled",
235 "privacy.trackingprotection.cryptomining.enabled",
236 "privacy.trackingprotection.fingerprinting.enabled",
237 "privacy.trackingprotection.enabled",
238 "privacy.trackingprotection.socialtracking.enabled",
239 "browser.contentblocking.report.show_mobile_app",
240 "browser.contentblocking.report.hide_vpn_banner",
241 "browser.vpn_promo.enabled",
244 "browser.contentblocking.category",
245 "browser.contentblocking.report.monitor.url",
246 "browser.contentblocking.report.monitor.sign_in_url",
247 "browser.contentblocking.report.manage_devices.url",
248 "browser.contentblocking.report.proxy_extension.url",
249 "browser.contentblocking.report.lockwise.mobile-android.url",
250 "browser.contentblocking.report.lockwise.mobile-ios.url",
251 "browser.contentblocking.report.mobile-ios.url",
252 "browser.contentblocking.report.mobile-android.url",
253 "browser.contentblocking.report.vpn.url",
254 "browser.contentblocking.report.vpn-promo.url",
255 "browser.contentblocking.report.vpn-android.url",
256 "browser.contentblocking.report.vpn-ios.url",
258 RPMGetIntPref: ["network.cookie.cookieBehavior"],
259 RPMGetFormatURLPref: [
260 "browser.contentblocking.report.monitor.how_it_works.url",
261 "browser.contentblocking.report.lockwise.how_it_works.url",
262 "browser.contentblocking.report.monitor.preferences_url",
263 "browser.contentblocking.report.monitor.home_page_url",
264 "browser.contentblocking.report.social.url",
265 "browser.contentblocking.report.cookie.url",
266 "browser.contentblocking.report.tracker.url",
267 "browser.contentblocking.report.fingerprinter.url",
268 "browser.contentblocking.report.cryptominer.url",
270 RPMRecordGleanEvent: ["securityUiProtections"],
272 "about:shoppingsidebar": {
274 "browser.shopping.experience2023.optedIn",
275 "browser.shopping.experience2023.active",
276 "browser.shopping.experience2023.ads.userEnabled",
277 "browser.shopping.experience2023.sidebarClosedCount",
278 "browser.shopping.experience2023.showKeepSidebarClosedMessage",
279 "browser.shopping.experience2023.autoOpen.userEnabled",
281 RPMGetFormatURLPref: ["app.support.baseURL"],
282 RPMGetIntPref: ["browser.shopping.experience2023.sidebarClosedCount"],
284 "browser.shopping.experience2023.showKeepSidebarClosedMessage",
286 "browser.shopping.experience2023.integratedSidebar",
289 "about:tabcrashed": {
290 RPMSendAsyncMessage: ["Load", "closeTab", "restoreTab", "restoreAll"],
291 RPMAddMessageListener: ["*"],
292 RPMRemoveMessageListener: ["*"],
295 RPMSendAsyncMessage: ["ActivityStream:ContentToMain"],
296 RPMAddMessageListener: ["ActivityStream:MainToContent"],
301 * Check if access is allowed to the given feature for a given document.
302 * This should be called from within the child process.
304 * The feature within the accessMap must list the given aValue, for access to
307 * @param aDocument child process document to call from
308 * @param aFeature to feature to check access to
309 * @param aValue value that must be included with that feature's allow list
310 * @returns true if access is allowed or false otherwise
312 checkAllowAccess(aDocument, aFeature, aValue) {
313 let principal = aDocument.nodePrincipal;
314 // if there is no content principal; deny access
319 return this.checkAllowAccessWithPrincipal(
328 * Check if access is allowed to the given feature for a given principal.
329 * This may be called from within the child or parent process.
331 * The feature within the accessMap must list the given aValue, for access to
334 * In the parent process, the passed-in document is expected to be null.
336 * @param aPrincipal principal being called from
337 * @param aFeature to feature to check access to
338 * @param aValue value that must be included with that feature's allow list
339 * @param aDocument optional child process document to call from
340 * @returns true if access is allowed or false otherwise
342 checkAllowAccessWithPrincipal(aPrincipal, aFeature, aValue, aDocument) {
343 let accessMapForFeature = this.checkAllowAccessToFeature(
348 if (!accessMapForFeature) {
350 "RemotePageAccessManager does not allow access to Feature: ",
359 // If the actual value is in the allow list for that feature;
361 if (accessMapForFeature.includes(aValue) || accessMapForFeature[0] == "*") {
369 * Check if a particular feature can be accessed without checking for a
370 * specific feature value.
372 * @param aPrincipal principal being called from
373 * @param aFeature to feature to check access to
374 * @param aDocument optional child process document to call from
375 * @returns non-null allow list if access is allowed or null otherwise
377 checkAllowAccessToFeature(aPrincipal, aFeature, aDocument) {
379 if (!aPrincipal.isContentPrincipal) {
380 // For the sake of remote pages, when the principal has no uri,
381 // we want to access the "real" document URI directly, e.g. if the
382 // about: page is sandboxed.
386 if (!aDocument.documentURIObject.schemeIs("about")) {
390 aDocument.documentURIObject.prePath +
391 aDocument.documentURIObject.filePath;
393 if (!aPrincipal.schemeIs("about")) {
396 spec = aPrincipal.prePath + aPrincipal.filePath;
399 // Check if there is an entry for that requestying URI in the accessMap;
400 // if not, deny access.
401 let accessMapForURI = this.accessMap[spec];
402 if (!accessMapForURI) {
406 // Check if the feature is allowed to be accessed for that URI;
407 // if not, deny access.
408 return accessMapForURI[aFeature];
412 * This function adds a new page to the access map, but can only
413 * be used in a test environment.
415 addPage(aUrl, aFunctionMap) {
416 if (!Cu.isInAutomation) {
417 throw new Error("Cannot only modify privileges during testing");
420 if (aUrl in this.accessMap) {
421 throw new Error("Cannot modify privileges of existing page");
424 this.accessMap[aUrl] = aFunctionMap;