Bug 1889091 - Part 6: Remove "scratch" register parameter from emitPushArguments...
[gecko.git] / dom / ipc / ProcessIsolation.cpp
blobddfbeb3d2877ab3be777eb0fd57ebe4c8fc84ba1
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 : */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/ProcessIsolation.h"
9 #include "mozilla/Assertions.h"
10 #include "mozilla/dom/BrowsingContextGroup.h"
11 #include "mozilla/dom/CanonicalBrowsingContext.h"
12 #include "mozilla/dom/ContentChild.h"
13 #include "mozilla/dom/ContentParent.h"
14 #include "mozilla/dom/Element.h"
15 #include "mozilla/dom/RemoteType.h"
16 #include "mozilla/dom/WindowGlobalParent.h"
17 #include "mozilla/extensions/WebExtensionPolicy.h"
18 #include "mozilla/BasePrincipal.h"
19 #include "mozilla/ClearOnShutdown.h"
20 #include "mozilla/ContentPrincipal.h"
21 #include "mozilla/ExtensionPolicyService.h"
22 #include "mozilla/Logging.h"
23 #include "mozilla/NullPrincipal.h"
24 #include "mozilla/PermissionManager.h"
25 #include "mozilla/Preferences.h"
26 #include "mozilla/RefPtr.h"
27 #include "mozilla/StaticPrefs_browser.h"
28 #include "mozilla/StaticPrefs_fission.h"
29 #include "mozilla/StaticPtr.h"
30 #include "nsAboutProtocolUtils.h"
31 #include "nsDocShell.h"
32 #include "nsError.h"
33 #include "nsIChromeRegistry.h"
34 #include "nsIHttpChannel.h"
35 #include "nsIHttpChannelInternal.h"
36 #include "nsIProtocolHandler.h"
37 #include "nsIXULRuntime.h"
38 #include "nsNetUtil.h"
39 #include "nsServiceManagerUtils.h"
40 #include "nsSHistory.h"
41 #include "nsURLHelper.h"
43 namespace mozilla::dom {
45 mozilla::LazyLogModule gProcessIsolationLog{"ProcessIsolation"};
47 namespace {
49 // Strategy used to determine whether or not a particular site should load into
50 // a webIsolated content process. The particular strategy chosen is controlled
51 // by the `fission.webContentIsolationStrategy` pref, which must hold one of the
52 // following values.
53 enum class WebContentIsolationStrategy : uint32_t {
54 // All web content is loaded into a shared `web` content process. This is
55 // similar to the non-Fission behaviour, however remote subframes may still
56 // be used for sites with special isolation behaviour, such as extension or
57 // mozillaweb content processes.
58 IsolateNothing = 0,
59 // Web content is always isolated into its own `webIsolated` content process
60 // based on site-origin, and will only load in a shared `web` content process
61 // if site-origin could not be determined.
62 IsolateEverything = 1,
63 // Only isolates web content loaded by sites which are considered "high
64 // value". A site is considered "high value" if it has been granted a
65 // `highValue*` permission by the permission manager, which is done in
66 // response to certain actions.
67 IsolateHighValue = 2,
70 /**
71 * Helper class for caching the result of splitting prefs which are represented
72 * as a comma-separated list of strings.
74 struct CommaSeparatedPref {
75 public:
76 explicit constexpr CommaSeparatedPref(nsLiteralCString aPrefName)
77 : mPrefName(aPrefName) {}
79 void OnChange() {
80 if (mValues) {
81 mValues->Clear();
82 nsAutoCString prefValue;
83 if (NS_SUCCEEDED(Preferences::GetCString(mPrefName.get(), prefValue))) {
84 for (const auto& value :
85 nsCCharSeparatedTokenizer(prefValue, ',').ToRange()) {
86 mValues->EmplaceBack(value);
92 const nsTArray<nsCString>& Get() {
93 if (!mValues) {
94 mValues = new nsTArray<nsCString>;
95 Preferences::RegisterCallbackAndCall(
96 [](const char*, void* aData) {
97 static_cast<CommaSeparatedPref*>(aData)->OnChange();
99 mPrefName, this);
100 RunOnShutdown([this] {
101 delete this->mValues;
102 this->mValues = nullptr;
105 return *mValues;
108 auto begin() { return Get().cbegin(); }
109 auto end() { return Get().cend(); }
111 private:
112 nsLiteralCString mPrefName;
113 nsTArray<nsCString>* MOZ_OWNING_REF mValues = nullptr;
116 CommaSeparatedPref sSeparatedMozillaDomains{
117 "browser.tabs.remote.separatedMozillaDomains"_ns};
120 * Certain URIs have special isolation behaviour, and need to be loaded within
121 * specific process types.
123 enum class IsolationBehavior {
124 // This URI loads web content and should be treated as a content load, being
125 // isolated based on the response principal if enabled.
126 WebContent,
127 // Forcibly load in a process with the "web" remote type. This will ignore the
128 // response principal completely.
129 // This is generally reserved for internal documents which are loaded in
130 // content, but not in the privilegedabout content process.
131 ForceWebRemoteType,
132 // Load this URI in the privileged about content process.
133 PrivilegedAbout,
134 // Load this URI in the extension process.
135 Extension,
136 // Load this URI in the file content process.
137 File,
138 // Load this URI in the priviliged mozilla content process.
139 PrivilegedMozilla,
140 // Load this URI explicitly in the parent process.
141 Parent,
142 // Load this URI wherever the browsing context is currently loaded. This is
143 // generally used for error pages.
144 Anywhere,
145 // May only be returned for subframes. Inherits the remote type of the parent
146 // document which is embedding this document.
147 Inherit,
148 // Special case for the `about:reader` URI which should be loaded in the same
149 // process which would be used for the "url" query parameter.
150 AboutReader,
151 // There was a fatal error, and the load should be aborted.
152 Error,
156 * Returns a static string with the name of the given isolation behaviour. For
157 * use in logging code.
159 static const char* IsolationBehaviorName(IsolationBehavior aBehavior) {
160 switch (aBehavior) {
161 case IsolationBehavior::WebContent:
162 return "WebContent";
163 case IsolationBehavior::ForceWebRemoteType:
164 return "ForceWebRemoteType";
165 case IsolationBehavior::PrivilegedAbout:
166 return "PrivilegedAbout";
167 case IsolationBehavior::Extension:
168 return "Extension";
169 case IsolationBehavior::File:
170 return "File";
171 case IsolationBehavior::PrivilegedMozilla:
172 return "PrivilegedMozilla";
173 case IsolationBehavior::Parent:
174 return "Parent";
175 case IsolationBehavior::Anywhere:
176 return "Anywhere";
177 case IsolationBehavior::Inherit:
178 return "Inherit";
179 case IsolationBehavior::AboutReader:
180 return "AboutReader";
181 case IsolationBehavior::Error:
182 return "Error";
183 default:
184 return "Unknown";
189 * Returns a static string with the name of the given worker kind. For use in
190 * logging code.
192 static const char* WorkerKindName(WorkerKind aWorkerKind) {
193 switch (aWorkerKind) {
194 case WorkerKindDedicated:
195 return "Dedicated";
196 case WorkerKindShared:
197 return "Shared";
198 case WorkerKindService:
199 return "Service";
200 default:
201 return "Unknown";
206 * Check if a given URI has specialized process isolation behaviour, such as
207 * needing to be loaded within a specific type of content process.
209 * When handling a navigation, this method will be called twice: first with the
210 * channel's creation URI, and then it will be called with a result principal's
211 * URI.
213 static IsolationBehavior IsolationBehaviorForURI(nsIURI* aURI, bool aIsSubframe,
214 bool aForChannelCreationURI) {
215 nsAutoCString scheme;
216 MOZ_ALWAYS_SUCCEEDS(aURI->GetScheme(scheme));
218 if (scheme == "chrome"_ns) {
219 // `chrome://` URIs are always loaded in the parent process, unless they
220 // have opted in to loading in a content process. This is currently only
221 // done in tests.
223 // FIXME: These flags should be removed from `chrome` URIs at some point.
224 nsCOMPtr<nsIXULChromeRegistry> chromeReg =
225 do_GetService("@mozilla.org/chrome/chrome-registry;1");
226 bool mustLoadRemotely = false;
227 if (NS_SUCCEEDED(chromeReg->MustLoadURLRemotely(aURI, &mustLoadRemotely)) &&
228 mustLoadRemotely) {
229 return IsolationBehavior::ForceWebRemoteType;
231 bool canLoadRemotely = false;
232 if (NS_SUCCEEDED(chromeReg->CanLoadURLRemotely(aURI, &canLoadRemotely)) &&
233 canLoadRemotely) {
234 return IsolationBehavior::Anywhere;
236 return IsolationBehavior::Parent;
239 if (scheme == "about"_ns) {
240 nsAutoCString path;
241 MOZ_ALWAYS_SUCCEEDS(NS_GetAboutModuleName(aURI, path));
243 // The `about:blank` and `about:srcdoc` pages are loaded by normal web
244 // content, and should be allocated processes based on their simple content
245 // principals.
246 if (path == "blank"_ns || path == "srcdoc"_ns) {
247 MOZ_ASSERT(NS_IsContentAccessibleAboutURI(aURI));
248 return IsolationBehavior::WebContent;
251 MOZ_ASSERT(!NS_IsContentAccessibleAboutURI(aURI));
252 // If we're loading an `about:reader` URI, perform isolation based on the
253 // principal of the URI being loaded.
254 if (path == "reader"_ns && aForChannelCreationURI) {
255 return IsolationBehavior::AboutReader;
258 // Otherwise, we're going to be loading an about: page. Consult the module.
259 nsCOMPtr<nsIAboutModule> aboutModule;
260 if (NS_FAILED(NS_GetAboutModule(aURI, getter_AddRefs(aboutModule))) ||
261 !aboutModule) {
262 // If we don't know of an about: module for this load, it's going to end
263 // up being a network error. Allow the load to finish as normal.
264 return IsolationBehavior::WebContent;
267 // NOTE: about modules can be implemented in JS, so this may run script, and
268 // therefore can spuriously fail.
269 uint32_t flags = 0;
270 if (NS_FAILED(aboutModule->GetURIFlags(aURI, &flags))) {
271 NS_WARNING(
272 "nsIAboutModule::GetURIFlags unexpectedly failed. Abort the load");
273 return IsolationBehavior::Error;
276 if (flags & nsIAboutModule::URI_MUST_LOAD_IN_EXTENSION_PROCESS) {
277 return IsolationBehavior::Extension;
280 if (flags & nsIAboutModule::URI_MUST_LOAD_IN_CHILD) {
281 if (flags & nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS) {
282 return IsolationBehavior::PrivilegedAbout;
284 return IsolationBehavior::ForceWebRemoteType;
287 if (flags & nsIAboutModule::URI_CAN_LOAD_IN_CHILD) {
288 return IsolationBehavior::Anywhere;
291 return IsolationBehavior::Parent;
294 // If the test-only `dataUriInDefaultWebProcess` pref is enabled, dump all
295 // `data:` URIs in a "web" content process, rather than loading them in
296 // content processes based on their precursor origins.
297 if (StaticPrefs::browser_tabs_remote_dataUriInDefaultWebProcess() &&
298 scheme == "data"_ns) {
299 return IsolationBehavior::ForceWebRemoteType;
302 // Make sure to unwrap nested URIs before we early return for channel creation
303 // URI. The checks past this point are intended to operate on the principal,
304 // which has it's origin constructed from the innermost URI.
305 nsCOMPtr<nsIURI> inner;
306 if (nsCOMPtr<nsINestedURI> nested = do_QueryInterface(aURI);
307 nested && NS_SUCCEEDED(nested->GetInnerURI(getter_AddRefs(inner)))) {
308 return IsolationBehaviorForURI(inner, aIsSubframe, aForChannelCreationURI);
311 // If we're doing the initial check based on the channel creation URI, stop
312 // here as we want to only perform the following checks on the true channel
313 // result principal.
314 if (aForChannelCreationURI) {
315 return IsolationBehavior::WebContent;
318 // Protocols used by Thunderbird to display email messages.
319 if (scheme == "imap"_ns || scheme == "mailbox"_ns || scheme == "news"_ns ||
320 scheme == "nntp"_ns || scheme == "snews"_ns) {
321 return IsolationBehavior::Parent;
324 // There is more handling for extension content processes in the caller, but
325 // they should load in an extension content process unless we're loading a
326 // subframe.
327 if (scheme == "moz-extension"_ns) {
328 if (aIsSubframe) {
329 // As a temporary measure, extension iframes must be loaded within the
330 // same process as their parent document.
331 return IsolationBehavior::Inherit;
333 return IsolationBehavior::Extension;
336 if (scheme == "file"_ns) {
337 return IsolationBehavior::File;
340 // Check if the URI is listed as a privileged mozilla content process.
341 if (scheme == "https"_ns &&
342 StaticPrefs::
343 browser_tabs_remote_separatePrivilegedMozillaWebContentProcess()) {
344 nsAutoCString host;
345 if (NS_SUCCEEDED(aURI->GetAsciiHost(host))) {
346 // This code is duplicated in E10SUtils.sys.mjs, please update both
347 for (const auto& separatedDomain : sSeparatedMozillaDomains) {
348 // If the domain exactly matches our host, or our host ends with "." +
349 // separatedDomain, we consider it matching.
350 if (separatedDomain == host ||
351 (separatedDomain.Length() < host.Length() &&
352 host.CharAt(host.Length() - separatedDomain.Length() - 1) == '.' &&
353 StringEndsWith(host, separatedDomain))) {
354 return IsolationBehavior::PrivilegedMozilla;
360 nsCOMPtr<nsIScriptSecurityManager> secMan =
361 nsContentUtils::GetSecurityManager();
362 bool inFileURIAllowList = false;
363 if (NS_SUCCEEDED(secMan->InFileURIAllowlist(aURI, &inFileURIAllowList)) &&
364 inFileURIAllowList) {
365 return IsolationBehavior::File;
368 return IsolationBehavior::WebContent;
372 * Helper method for logging the origin of a principal as a string.
374 static nsAutoCString OriginString(nsIPrincipal* aPrincipal) {
375 nsAutoCString origin;
376 aPrincipal->GetOrigin(origin);
377 return origin;
381 * Trim the OriginAttributes from aPrincipal, and use it to create a
382 * OriginSuffix string appropriate to use within a remoteType string.
384 static nsAutoCString OriginSuffixForRemoteType(nsIPrincipal* aPrincipal) {
385 nsAutoCString originSuffix;
386 OriginAttributes attrs = aPrincipal->OriginAttributesRef();
387 attrs.StripAttributes(OriginAttributes::STRIP_FIRST_PARTY_DOMAIN |
388 OriginAttributes::STRIP_PARITION_KEY);
389 attrs.CreateSuffix(originSuffix);
390 return originSuffix;
394 * Given an about:reader URI, extract the "url" query parameter, and use it to
395 * construct a principal which should be used for process selection.
397 static already_AddRefed<BasePrincipal> GetAboutReaderURLPrincipal(
398 nsIURI* aURI, const OriginAttributes& aAttrs) {
399 #ifdef DEBUG
400 MOZ_ASSERT(aURI->SchemeIs("about"));
401 nsAutoCString path;
402 MOZ_ALWAYS_SUCCEEDS(NS_GetAboutModuleName(aURI, path));
403 MOZ_ASSERT(path == "reader"_ns);
404 #endif
406 nsAutoCString query;
407 MOZ_ALWAYS_SUCCEEDS(aURI->GetQuery(query));
409 // Extract the "url" parameter from the `about:reader`'s query parameters,
410 // and recover a content principal from it.
411 nsAutoCString readerSpec;
412 if (URLParams::Extract(query, "url"_ns, readerSpec)) {
413 nsCOMPtr<nsIURI> readerUri;
414 if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(readerUri), readerSpec))) {
415 return BasePrincipal::CreateContentPrincipal(readerUri, aAttrs);
418 return nullptr;
422 * Returns `true` if loads for this site should be isolated on a per-site basis.
423 * If `aTopBC` is nullptr, this is being called to check if a shared or service
424 * worker should be isolated.
426 static bool ShouldIsolateSite(nsIPrincipal* aPrincipal,
427 bool aUseRemoteSubframes) {
428 // If Fission is disabled, we never want to isolate. We check the toplevel BC
429 // if it's available, or the global pref if checking for shared or service
430 // workers.
431 if (!aUseRemoteSubframes) {
432 return false;
435 // non-content principals currently can't have webIsolated remote types
436 // assigned to them, so should not be isolated.
437 if (!aPrincipal->GetIsContentPrincipal()) {
438 return false;
441 switch (WebContentIsolationStrategy(
442 StaticPrefs::fission_webContentIsolationStrategy())) {
443 case WebContentIsolationStrategy::IsolateNothing:
444 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
445 ("Not isolating '%s' as isolation is disabled",
446 OriginString(aPrincipal).get()));
447 return false;
448 case WebContentIsolationStrategy::IsolateEverything:
449 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
450 ("Isolating '%s' as isolation is enabled for all sites",
451 OriginString(aPrincipal).get()));
452 return true;
453 case WebContentIsolationStrategy::IsolateHighValue: {
454 RefPtr<PermissionManager> perms = PermissionManager::GetInstance();
455 if (NS_WARN_IF(!perms)) {
456 // If we somehow have no permission manager, fall back to the safest
457 // option, and try to isolate.
458 MOZ_ASSERT_UNREACHABLE("Permission manager is missing");
459 return true;
462 static constexpr nsLiteralCString kHighValuePermissions[] = {
463 mozilla::dom::kHighValueCOOPPermission,
464 mozilla::dom::kHighValueHasSavedLoginPermission,
465 mozilla::dom::kHighValueIsLoggedInPermission,
468 for (const auto& type : kHighValuePermissions) {
469 uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
470 if (NS_SUCCEEDED(perms->TestPermissionFromPrincipal(aPrincipal, type,
471 &permission)) &&
472 permission == nsIPermissionManager::ALLOW_ACTION) {
473 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
474 ("Isolating '%s' due to high-value permission '%s'",
475 OriginString(aPrincipal).get(), type.get()));
476 return true;
479 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
480 ("Not isolating '%s' as it is not high-value",
481 OriginString(aPrincipal).get()));
482 return false;
484 default:
485 // An invalid pref value was used. Fall back to the safest option and
486 // isolate everything.
487 NS_WARNING("Invalid pref value for fission.webContentIsolationStrategy");
488 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
489 ("Isolating '%s' due to unknown strategy pref value",
490 OriginString(aPrincipal).get()));
491 return true;
495 static Result<nsCString, nsresult> SpecialBehaviorRemoteType(
496 IsolationBehavior aBehavior, const nsACString& aCurrentRemoteType,
497 WindowGlobalParent* aParentWindow) {
498 switch (aBehavior) {
499 case IsolationBehavior::ForceWebRemoteType:
500 return {WEB_REMOTE_TYPE};
501 case IsolationBehavior::PrivilegedAbout:
502 // The privileged about: content process cannot be disabled, as it
503 // causes various actors to break.
504 return {PRIVILEGEDABOUT_REMOTE_TYPE};
505 case IsolationBehavior::Extension:
506 if (ExtensionPolicyService::GetSingleton().UseRemoteExtensions()) {
507 return {EXTENSION_REMOTE_TYPE};
509 return {NOT_REMOTE_TYPE};
510 case IsolationBehavior::File:
511 if (StaticPrefs::browser_tabs_remote_separateFileUriProcess()) {
512 return {FILE_REMOTE_TYPE};
514 return {WEB_REMOTE_TYPE};
515 case IsolationBehavior::PrivilegedMozilla:
516 return {PRIVILEGEDMOZILLA_REMOTE_TYPE};
517 case IsolationBehavior::Parent:
518 return {NOT_REMOTE_TYPE};
519 case IsolationBehavior::Anywhere:
520 return {nsCString(aCurrentRemoteType)};
521 case IsolationBehavior::Inherit:
522 MOZ_DIAGNOSTIC_ASSERT(aParentWindow);
523 return {nsCString(aParentWindow->GetRemoteType())};
525 case IsolationBehavior::Error:
526 return Err(NS_ERROR_UNEXPECTED);
528 default:
529 MOZ_ASSERT_UNREACHABLE();
530 return Err(NS_ERROR_UNEXPECTED);
534 enum class WebProcessType {
535 Web,
536 WebIsolated,
537 WebCoopCoep,
540 } // namespace
542 Result<NavigationIsolationOptions, nsresult> IsolationOptionsForNavigation(
543 CanonicalBrowsingContext* aTopBC, WindowGlobalParent* aParentWindow,
544 nsIURI* aChannelCreationURI, nsIChannel* aChannel,
545 const nsACString& aCurrentRemoteType, bool aHasCOOPMismatch,
546 bool aForNewTab, uint32_t aLoadStateLoadType,
547 const Maybe<uint64_t>& aChannelId,
548 const Maybe<nsCString>& aRemoteTypeOverride) {
549 // Get the final principal, used to select which process to load into.
550 nsCOMPtr<nsIPrincipal> resultPrincipal;
551 nsresult rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
552 aChannel, getter_AddRefs(resultPrincipal));
553 if (NS_FAILED(rv)) {
554 MOZ_LOG(gProcessIsolationLog, LogLevel::Error,
555 ("failed to get channel result principal"));
556 return Err(rv);
559 MOZ_LOG(
560 gProcessIsolationLog, LogLevel::Verbose,
561 ("IsolationOptionsForNavigation principal:%s, uri:%s, parentUri:%s",
562 OriginString(resultPrincipal).get(),
563 aChannelCreationURI->GetSpecOrDefault().get(),
564 aParentWindow ? aParentWindow->GetDocumentURI()->GetSpecOrDefault().get()
565 : ""));
567 // If we're loading a null principal, we can't easily make a process
568 // selection decision off ot it. Instead, we'll use our null principal's
569 // precursor principal to make process selection decisions.
570 bool isNullPrincipalPrecursor = false;
571 nsCOMPtr<nsIPrincipal> resultOrPrecursor(resultPrincipal);
572 if (nsCOMPtr<nsIPrincipal> precursor =
573 resultOrPrecursor->GetPrecursorPrincipal()) {
574 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
575 ("using null principal precursor origin %s",
576 OriginString(precursor).get()));
577 resultOrPrecursor = precursor;
578 isNullPrincipalPrecursor = true;
581 NavigationIsolationOptions options;
582 options.mReplaceBrowsingContext = aHasCOOPMismatch;
584 // Check if this load has an explicit remote type override. This is used to
585 // perform an about:blank load within a specific content process.
586 if (aRemoteTypeOverride) {
587 MOZ_DIAGNOSTIC_ASSERT(
588 NS_IsAboutBlank(aChannelCreationURI),
589 "Should only have aRemoteTypeOverride for about:blank URIs");
590 if (NS_WARN_IF(!resultPrincipal->GetIsNullPrincipal())) {
591 MOZ_LOG(gProcessIsolationLog, LogLevel::Error,
592 ("invalid remote type override on non-null principal"));
593 return Err(NS_ERROR_DOM_SECURITY_ERR);
596 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
597 ("using remote type override (%s) for load",
598 aRemoteTypeOverride->get()));
599 options.mRemoteType = *aRemoteTypeOverride;
600 return options;
603 // First, check for any special cases which should be handled using the
604 // channel creation URI, and handle them.
605 auto behavior = IsolationBehaviorForURI(aChannelCreationURI, aParentWindow,
606 /* aForChannelCreationURI */ true);
607 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
608 ("Channel Creation Isolation Behavior: %s",
609 IsolationBehaviorName(behavior)));
611 // In the about:reader special case, we want to fetch the relevant information
612 // from the URI, an then treat it as a normal web content load.
613 if (behavior == IsolationBehavior::AboutReader) {
614 if (RefPtr<BasePrincipal> readerURIPrincipal = GetAboutReaderURLPrincipal(
615 aChannelCreationURI, resultOrPrecursor->OriginAttributesRef())) {
616 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
617 ("using about:reader's url origin %s",
618 OriginString(readerURIPrincipal).get()));
619 resultOrPrecursor = readerURIPrincipal;
621 behavior = IsolationBehavior::WebContent;
622 // If loading an about:reader page in a BrowsingContext which shares a
623 // BrowsingContextGroup with other toplevel documents, replace the
624 // BrowsingContext to destroy any references.
626 // With SHIP we can apply this to all about:reader loads, but otherwise
627 // do it at least where there are opener/group relationships.
628 if (mozilla::SessionHistoryInParent() ||
629 aTopBC->Group()->Toplevels().Length() > 1) {
630 options.mReplaceBrowsingContext = true;
634 // If we're running in a test which is requesting that system-triggered
635 // about:blank documents load within the current process, override the
636 // behaviour for loads which meet the requirements.
637 if (StaticPrefs::browser_tabs_remote_systemTriggeredAboutBlankAnywhere() &&
638 NS_IsAboutBlank(aChannelCreationURI)) {
639 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
640 if (loadInfo->TriggeringPrincipal()->IsSystemPrincipal() &&
641 resultOrPrecursor->GetIsNullPrincipal()) {
642 MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
643 ("Forcing system-principal triggered about:blank load to "
644 "complete in the current process"));
645 behavior = IsolationBehavior::Anywhere;
649 #ifdef MOZ_WIDGET_ANDROID
650 // If we're loading an error page on android, it must complete within the same
651 // process as the errored page load would complete in due to code expecting
652 // that behavior. See bug 1673763.
653 if (aLoadStateLoadType == LOAD_ERROR_PAGE) {
654 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
655 ("Forcing error page load to complete in the current process"));
656 behavior = IsolationBehavior::Anywhere;
658 #endif
660 // If we're loading for a specific extension, we'll need to perform a
661 // BCG-switching load to get our toplevel extension window in the correct
662 // BrowsingContextGroup.
663 if (auto* addonPolicy =
664 BasePrincipal::Cast(resultOrPrecursor)->AddonPolicy()) {
665 if (aParentWindow) {
666 // As a temporary measure, extension iframes must be loaded within the
667 // same process as their parent document.
668 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
669 ("Loading extension subframe in same process as parent"));
670 behavior = IsolationBehavior::Inherit;
671 } else {
672 MOZ_LOG(
673 gProcessIsolationLog, LogLevel::Verbose,
674 ("Found extension frame with addon policy. Will use group id %" PRIx64
675 " (currentId: %" PRIx64 ")",
676 addonPolicy->GetBrowsingContextGroupId(), aTopBC->Group()->Id()));
677 behavior = IsolationBehavior::Extension;
678 if (aTopBC->Group()->Id() != addonPolicy->GetBrowsingContextGroupId()) {
679 options.mReplaceBrowsingContext = true;
680 options.mSpecificGroupId = addonPolicy->GetBrowsingContextGroupId();
685 // Do a second run of `GetIsolationBehavior`, this time using the
686 // principal's URI to handle additional special cases such as the file and
687 // privilegedmozilla content process.
688 if (behavior == IsolationBehavior::WebContent) {
689 if (resultOrPrecursor->IsSystemPrincipal()) {
690 // We're loading something with a system principal which isn't caught in
691 // one of our other edge-cases. If the load started in the parent process,
692 // and it's safe for it to end in the parent process, we should finish the
693 // load there.
694 bool isUIResource = false;
695 if (aCurrentRemoteType.IsEmpty() &&
696 (aChannelCreationURI->SchemeIs("about") ||
697 (NS_SUCCEEDED(NS_URIChainHasFlags(
698 aChannelCreationURI, nsIProtocolHandler::URI_IS_UI_RESOURCE,
699 &isUIResource)) &&
700 isUIResource))) {
701 behavior = IsolationBehavior::Parent;
702 } else {
703 // In general, we don't want to load documents with a system principal
704 // in a content process, however we need to in some cases, such as when
705 // loading blob: URLs created by system code. We can force the load to
706 // finish in a content process instead.
707 behavior = IsolationBehavior::ForceWebRemoteType;
709 } else if (nsCOMPtr<nsIURI> principalURI = resultOrPrecursor->GetURI()) {
710 behavior = IsolationBehaviorForURI(principalURI, aParentWindow,
711 /* aForChannelCreationURI */ false);
715 // If we're currently loaded in the extension process, and are going to switch
716 // to some other remote type, make sure we leave the extension's BCG which we
717 // may have entered earlier to separate extension and non-extension BCGs from
718 // each-other.
719 if (!aParentWindow && aCurrentRemoteType == EXTENSION_REMOTE_TYPE &&
720 behavior != IsolationBehavior::Extension &&
721 behavior != IsolationBehavior::Anywhere) {
722 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
723 ("Forcing BC replacement to leave extension BrowsingContextGroup "
724 "%" PRIx64 " on navigation",
725 aTopBC->Group()->Id()));
726 options.mReplaceBrowsingContext = true;
729 // We don't want to load documents with sandboxed null principals, like
730 // `data:` URIs, in the parent process, even if they were created by a
731 // document which would otherwise be loaded in the parent process.
732 if (behavior == IsolationBehavior::Parent && isNullPrincipalPrecursor) {
733 MOZ_LOG(gProcessIsolationLog, LogLevel::Debug,
734 ("Ensuring sandboxed null-principal load doesn't occur in the "
735 "parent process"));
736 behavior = IsolationBehavior::ForceWebRemoteType;
739 MOZ_LOG(
740 gProcessIsolationLog, LogLevel::Debug,
741 ("Using IsolationBehavior %s for %s (original uri %s)",
742 IsolationBehaviorName(behavior), OriginString(resultOrPrecursor).get(),
743 aChannelCreationURI->GetSpecOrDefault().get()));
745 // Check if we can put the previous document into the BFCache.
746 if (mozilla::BFCacheInParent() && nsSHistory::GetMaxTotalViewers() > 0 &&
747 !aForNewTab && !aParentWindow && !aTopBC->HadOriginalOpener() &&
748 behavior != IsolationBehavior::Parent &&
749 (ExtensionPolicyService::GetSingleton().UseRemoteExtensions() ||
750 behavior != IsolationBehavior::Extension) &&
751 !aCurrentRemoteType.IsEmpty() &&
752 aTopBC->GetHasLoadedNonInitialDocument() &&
753 (aLoadStateLoadType == LOAD_NORMAL ||
754 aLoadStateLoadType == LOAD_HISTORY || aLoadStateLoadType == LOAD_LINK ||
755 aLoadStateLoadType == LOAD_STOP_CONTENT ||
756 aLoadStateLoadType == LOAD_STOP_CONTENT_AND_REPLACE) &&
757 (!aTopBC->GetActiveSessionHistoryEntry() ||
758 aTopBC->GetActiveSessionHistoryEntry()->GetSaveLayoutStateFlag())) {
759 if (nsCOMPtr<nsIURI> uri = aTopBC->GetCurrentURI()) {
760 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
761 ("current uri: %s", uri->GetSpecOrDefault().get()));
763 options.mTryUseBFCache =
764 aTopBC->AllowedInBFCache(aChannelId, aChannelCreationURI);
765 if (options.mTryUseBFCache) {
766 options.mReplaceBrowsingContext = true;
767 options.mActiveSessionHistoryEntry =
768 aTopBC->GetActiveSessionHistoryEntry();
772 // If the load has any special remote type handling, do so at this point.
773 if (behavior != IsolationBehavior::WebContent) {
774 MOZ_TRY_VAR(
775 options.mRemoteType,
776 SpecialBehaviorRemoteType(behavior, aCurrentRemoteType, aParentWindow));
778 if (options.mRemoteType != aCurrentRemoteType &&
779 (options.mRemoteType.IsEmpty() || aCurrentRemoteType.IsEmpty())) {
780 options.mReplaceBrowsingContext = true;
783 MOZ_LOG(
784 gProcessIsolationLog, LogLevel::Debug,
785 ("Selecting specific remote type (%s) due to a special case isolation "
786 "behavior %s",
787 options.mRemoteType.get(), IsolationBehaviorName(behavior)));
788 return options;
791 // At this point we're definitely not going to be loading in the parent
792 // process anymore, so we're definitely going to be replacing BrowsingContext
793 // if we're in the parent process.
794 if (aCurrentRemoteType.IsEmpty()) {
795 MOZ_ASSERT(!aParentWindow);
796 options.mReplaceBrowsingContext = true;
799 nsAutoCString siteOriginNoSuffix;
800 MOZ_TRY(resultOrPrecursor->GetSiteOriginNoSuffix(siteOriginNoSuffix));
802 // Check if we've already loaded a document with the given principal in some
803 // content process. We want to finish the load in the same process in that
804 // case.
806 // The exception to that is with extension loads and the system principal,
807 // where we may have multiple documents with the same principal in different
808 // processes. Those have been handled above, and will not be reaching here.
810 // If we're doing a replace load or opening a new tab, we won't be staying in
811 // the same BrowsingContextGroup, so ignore this step.
812 if (!options.mReplaceBrowsingContext && !aForNewTab) {
813 // Helper for efficiently determining if a given origin is same-site. This
814 // will attempt to do a fast equality check, and will only fall back to
815 // computing the site-origin for content principals.
816 auto principalIsSameSite = [&](nsIPrincipal* aDocumentPrincipal) -> bool {
817 // If we're working with a null principal with a precursor, compare
818 // precursors, as `resultOrPrecursor` has already been stripped to its
819 // precursor.
820 nsCOMPtr<nsIPrincipal> documentPrincipal(aDocumentPrincipal);
821 if (nsCOMPtr<nsIPrincipal> precursor =
822 documentPrincipal->GetPrecursorPrincipal()) {
823 documentPrincipal = precursor;
826 // First, attempt to use `Equals` to compare principals, and if that
827 // fails compare siteOrigins. Only compare siteOrigin for content
828 // principals, as non-content principals will never have siteOrigin !=
829 // origin.
830 nsAutoCString documentSiteOrigin;
831 return resultOrPrecursor->Equals(documentPrincipal) ||
832 (documentPrincipal->GetIsContentPrincipal() &&
833 resultOrPrecursor->GetIsContentPrincipal() &&
834 NS_SUCCEEDED(documentPrincipal->GetSiteOriginNoSuffix(
835 documentSiteOrigin)) &&
836 documentSiteOrigin == siteOriginNoSuffix);
839 // XXX: Consider also checking in-flight process switches to see if any have
840 // matching principals?
841 AutoTArray<RefPtr<BrowsingContext>, 8> contexts;
842 aTopBC->Group()->GetToplevels(contexts);
843 while (!contexts.IsEmpty()) {
844 auto bc = contexts.PopLastElement();
845 for (const auto& wc : bc->GetWindowContexts()) {
846 WindowGlobalParent* wgp = wc->Canonical();
848 // Check if this WindowGlobalParent has the given resultPrincipal, and
849 // if it does, we need to load in that process.
850 if (!wgp->GetRemoteType().IsEmpty() &&
851 principalIsSameSite(wgp->DocumentPrincipal())) {
852 MOZ_LOG(gProcessIsolationLog, LogLevel::Debug,
853 ("Found existing frame with matching principal "
854 "(remoteType:(%s), origin:%s)",
855 PromiseFlatCString(wgp->GetRemoteType()).get(),
856 OriginString(wgp->DocumentPrincipal()).get()));
857 options.mRemoteType = wgp->GetRemoteType();
858 return options;
861 // Also enumerate over this WindowContexts' subframes.
862 contexts.AppendElements(wc->Children());
867 nsAutoCString originSuffix = OriginSuffixForRemoteType(resultOrPrecursor);
869 WebProcessType webProcessType = WebProcessType::Web;
870 if (ShouldIsolateSite(resultOrPrecursor, aTopBC->UseRemoteSubframes())) {
871 webProcessType = WebProcessType::WebIsolated;
874 // Check if we should be loading in a webCOOP+COEP remote type due to our COOP
875 // status.
876 nsILoadInfo::CrossOriginOpenerPolicy coop =
877 nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
878 if (aParentWindow) {
879 coop = aTopBC->GetOpenerPolicy();
880 } else if (nsCOMPtr<nsIHttpChannelInternal> httpChannel =
881 do_QueryInterface(aChannel)) {
882 MOZ_ALWAYS_SUCCEEDS(httpChannel->GetCrossOriginOpenerPolicy(&coop));
884 if (coop ==
885 nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) {
886 webProcessType = WebProcessType::WebCoopCoep;
888 // If we're changing BrowsingContext, and are going to end up within a
889 // webCOOP+COEP group, ensure we use a cross-origin isolated BCG ID.
890 if (options.mReplaceBrowsingContext) {
891 MOZ_ASSERT(!options.mSpecificGroupId,
892 "overriding previously-specified BCG ID");
893 options.mSpecificGroupId = BrowsingContextGroup::CreateId(
894 /* aPotentiallyCrossOriginIsolated */ true);
898 switch (webProcessType) {
899 case WebProcessType::Web:
900 options.mRemoteType = WEB_REMOTE_TYPE;
901 break;
902 case WebProcessType::WebIsolated:
903 options.mRemoteType =
904 FISSION_WEB_REMOTE_TYPE "="_ns + siteOriginNoSuffix + originSuffix;
905 break;
906 case WebProcessType::WebCoopCoep:
907 options.mRemoteType =
908 WITH_COOP_COEP_REMOTE_TYPE "="_ns + siteOriginNoSuffix + originSuffix;
909 break;
911 return options;
914 Result<WorkerIsolationOptions, nsresult> IsolationOptionsForWorker(
915 nsIPrincipal* aPrincipal, WorkerKind aWorkerKind,
916 const nsACString& aCurrentRemoteType, bool aUseRemoteSubframes) {
917 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
918 ("IsolationOptionsForWorker principal:%s, kind:%s, current:%s",
919 OriginString(aPrincipal).get(), WorkerKindName(aWorkerKind),
920 PromiseFlatCString(aCurrentRemoteType).get()));
922 MOZ_ASSERT(NS_IsMainThread());
923 MOZ_RELEASE_ASSERT(
924 aWorkerKind == WorkerKindService || aWorkerKind == WorkerKindShared,
925 "Unexpected remote worker kind");
927 if (aWorkerKind == WorkerKindService &&
928 !aPrincipal->GetIsContentPrincipal()) {
929 MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
930 ("Rejecting service worker with non-content principal"));
931 return Err(NS_ERROR_UNEXPECTED);
934 if (aPrincipal->GetIsExpandedPrincipal()) {
935 MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
936 ("Rejecting remote worker with expanded principal"));
937 return Err(NS_ERROR_UNEXPECTED);
940 // In some cases, such as for null principals without precursors, we will want
941 // to load a shared worker in a process based on the current process. This is
942 // not done for service workers - process selection for those should function
943 // the same in all processes.
945 // We only allow the current remote type to be used if it is not a COOP+COEP
946 // remote type, in order to avoid loading a shared worker in one of these
947 // processes. Currently process selection for workers occurs before response
948 // headers are available, so we will never select to load a shared worker in a
949 // COOP+COEP content process.
950 nsCString preferredRemoteType = DEFAULT_REMOTE_TYPE;
951 if (aWorkerKind == WorkerKind::WorkerKindShared &&
952 !StringBeginsWith(aCurrentRemoteType,
953 WITH_COOP_COEP_REMOTE_TYPE_PREFIX)) {
954 preferredRemoteType = aCurrentRemoteType;
957 WorkerIsolationOptions options;
959 // If we're loading a null principal, we can't easily make a process
960 // selection decision off ot it. Instead, we'll use our null principal's
961 // precursor principal to make process selection decisions.
962 bool isNullPrincipalPrecursor = false;
963 nsCOMPtr<nsIPrincipal> resultOrPrecursor(aPrincipal);
964 if (nsCOMPtr<nsIPrincipal> precursor =
965 resultOrPrecursor->GetPrecursorPrincipal()) {
966 MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
967 ("using null principal precursor origin %s",
968 OriginString(precursor).get()));
969 resultOrPrecursor = precursor;
970 isNullPrincipalPrecursor = true;
973 IsolationBehavior behavior = IsolationBehavior::WebContent;
974 if (resultOrPrecursor->GetIsContentPrincipal()) {
975 nsCOMPtr<nsIURI> uri = resultOrPrecursor->GetURI();
976 behavior = IsolationBehaviorForURI(uri, /* aIsSubframe */ false,
977 /* aForChannelCreationURI */ false);
978 } else if (resultOrPrecursor->IsSystemPrincipal()) {
979 MOZ_ASSERT(aWorkerKind == WorkerKindShared);
981 // Allow system principal shared workers to load within either the
982 // parent process or privilegedabout process, depending on the
983 // responsible process.
984 if (preferredRemoteType == NOT_REMOTE_TYPE) {
985 MOZ_LOG(gProcessIsolationLog, LogLevel::Debug,
986 ("Loading system principal shared worker in parent process"));
987 behavior = IsolationBehavior::Parent;
988 } else if (preferredRemoteType == PRIVILEGEDABOUT_REMOTE_TYPE) {
989 MOZ_LOG(gProcessIsolationLog, LogLevel::Debug,
990 ("Loading system principal shared worker in privilegedabout "
991 "process"));
992 behavior = IsolationBehavior::PrivilegedAbout;
993 } else {
994 MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
995 ("Cannot load system-principal shared worker in "
996 "non-privilegedabout content process"));
997 return Err(NS_ERROR_UNEXPECTED);
999 } else {
1000 MOZ_ASSERT(resultOrPrecursor->GetIsNullPrincipal());
1001 MOZ_ASSERT(aWorkerKind == WorkerKindShared);
1003 if (preferredRemoteType == NOT_REMOTE_TYPE) {
1004 MOZ_LOG(gProcessIsolationLog, LogLevel::Debug,
1005 ("Ensuring precursorless null principal shared worker loads in a "
1006 "content process"));
1007 behavior = IsolationBehavior::ForceWebRemoteType;
1008 } else {
1009 MOZ_LOG(gProcessIsolationLog, LogLevel::Debug,
1010 ("Loading precursorless null principal shared worker within "
1011 "current remotetype: (%s)",
1012 preferredRemoteType.get()));
1013 behavior = IsolationBehavior::Anywhere;
1017 if (behavior == IsolationBehavior::Parent && isNullPrincipalPrecursor) {
1018 MOZ_LOG(gProcessIsolationLog, LogLevel::Debug,
1019 ("Ensuring sandboxed null-principal shared worker doesn't load in "
1020 "the parent process"));
1021 behavior = IsolationBehavior::ForceWebRemoteType;
1024 if (behavior != IsolationBehavior::WebContent) {
1025 MOZ_TRY_VAR(
1026 options.mRemoteType,
1027 SpecialBehaviorRemoteType(behavior, preferredRemoteType, nullptr));
1029 MOZ_LOG(
1030 gProcessIsolationLog, LogLevel::Debug,
1031 ("Selecting specific %s worker remote type (%s) due to a special case "
1032 "isolation behavior %s",
1033 WorkerKindName(aWorkerKind), options.mRemoteType.get(),
1034 IsolationBehaviorName(behavior)));
1035 return options;
1038 // If we should be isolating this site, we can determine the correct fission
1039 // remote type from the principal's site-origin.
1040 if (ShouldIsolateSite(resultOrPrecursor, aUseRemoteSubframes)) {
1041 nsAutoCString siteOriginNoSuffix;
1042 MOZ_TRY(resultOrPrecursor->GetSiteOriginNoSuffix(siteOriginNoSuffix));
1043 nsAutoCString originSuffix = OriginSuffixForRemoteType(resultOrPrecursor);
1045 nsCString prefix = aWorkerKind == WorkerKindService
1046 ? SERVICEWORKER_REMOTE_TYPE
1047 : FISSION_WEB_REMOTE_TYPE;
1048 options.mRemoteType = prefix + "="_ns + siteOriginNoSuffix + originSuffix;
1050 MOZ_LOG(gProcessIsolationLog, LogLevel::Debug,
1051 ("Isolating web content %s worker in remote type (%s)",
1052 WorkerKindName(aWorkerKind), options.mRemoteType.get()));
1053 } else {
1054 options.mRemoteType = WEB_REMOTE_TYPE;
1056 MOZ_LOG(gProcessIsolationLog, LogLevel::Debug,
1057 ("Loading web content %s worker in shared web remote type",
1058 WorkerKindName(aWorkerKind)));
1060 return options;
1063 void AddHighValuePermission(nsIPrincipal* aResultPrincipal,
1064 const nsACString& aPermissionType) {
1065 RefPtr<PermissionManager> perms = PermissionManager::GetInstance();
1066 if (NS_WARN_IF(!perms)) {
1067 return;
1070 // We can't act on non-content principals, so if the load was sandboxed, try
1071 // to use the unsandboxed precursor principal to add the highValue permission.
1072 nsCOMPtr<nsIPrincipal> resultOrPrecursor(aResultPrincipal);
1073 if (!aResultPrincipal->GetIsContentPrincipal()) {
1074 resultOrPrecursor = aResultPrincipal->GetPrecursorPrincipal();
1075 if (!resultOrPrecursor) {
1076 return;
1080 // Use the site-origin principal as we want to add the permission for the
1081 // entire site, rather than a specific subdomain, as process isolation acts on
1082 // a site granularity.
1083 nsAutoCString siteOrigin;
1084 if (NS_FAILED(resultOrPrecursor->GetSiteOrigin(siteOrigin))) {
1085 return;
1088 nsCOMPtr<nsIPrincipal> sitePrincipal =
1089 BasePrincipal::CreateContentPrincipal(siteOrigin);
1090 if (!sitePrincipal || !sitePrincipal->GetIsContentPrincipal()) {
1091 return;
1094 MOZ_LOG(dom::gProcessIsolationLog, LogLevel::Verbose,
1095 ("Adding %s Permission for site '%s'", aPermissionType.BeginReading(),
1096 siteOrigin.get()));
1098 uint32_t expiration = 0;
1099 if (aPermissionType.Equals(mozilla::dom::kHighValueCOOPPermission)) {
1100 expiration = StaticPrefs::fission_highValue_coop_expiration();
1101 } else if (aPermissionType.Equals(
1102 mozilla::dom::kHighValueHasSavedLoginPermission) ||
1103 aPermissionType.Equals(
1104 mozilla::dom::kHighValueIsLoggedInPermission)) {
1105 expiration = StaticPrefs::fission_highValue_login_expiration();
1106 } else {
1107 MOZ_ASSERT_UNREACHABLE("Unknown permission type");
1110 // XXX: Would be nice if we could use `TimeStamp` here, but there's
1111 // unfortunately no convenient way to recover a time in milliseconds since the
1112 // unix epoch from `TimeStamp`.
1113 int64_t expirationTime =
1114 (PR_Now() / PR_USEC_PER_MSEC) + (int64_t(expiration) * PR_MSEC_PER_SEC);
1115 Unused << perms->AddFromPrincipal(
1116 sitePrincipal, aPermissionType, nsIPermissionManager::ALLOW_ACTION,
1117 nsIPermissionManager::EXPIRE_TIME, expirationTime);
1120 void AddHighValuePermission(const nsACString& aOrigin,
1121 const nsACString& aPermissionType) {
1122 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
1123 nsCOMPtr<nsIPrincipal> principal;
1124 nsresult rv =
1125 ssm->CreateContentPrincipalFromOrigin(aOrigin, getter_AddRefs(principal));
1126 if (NS_WARN_IF(NS_FAILED(rv))) {
1127 return;
1130 AddHighValuePermission(principal, aPermissionType);
1133 bool IsIsolateHighValueSiteEnabled() {
1134 return mozilla::FissionAutostart() &&
1135 WebContentIsolationStrategy(
1136 StaticPrefs::fission_webContentIsolationStrategy()) ==
1137 WebContentIsolationStrategy::IsolateHighValue;
1140 } // namespace mozilla::dom