diff options
Diffstat (limited to 'dom/ipc/gtest/ProcessIsolationTest.cpp')
-rw-r--r-- | dom/ipc/gtest/ProcessIsolationTest.cpp | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/dom/ipc/gtest/ProcessIsolationTest.cpp b/dom/ipc/gtest/ProcessIsolationTest.cpp new file mode 100644 index 0000000000..197feabf8c --- /dev/null +++ b/dom/ipc/gtest/ProcessIsolationTest.cpp @@ -0,0 +1,234 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "gtest/gtest.h" +#include "mozilla/BasePrincipal.h" +#include "mozilla/dom/ProcessIsolation.h" +#include "mozilla/dom/WorkerPrivate.h" +#include "mozilla/ExpandedPrincipal.h" +#include "mozilla/ExtensionPolicyService.h" +#include "mozilla/gtest/MozAssertions.h" +#include "mozilla/gtest/MozHelpers.h" +#include "mozilla/NullPrincipal.h" +#include "mozilla/SystemPrincipal.h" +#include "mozilla/StaticPrefs_browser.h" + +using namespace mozilla; +using namespace mozilla::dom; + +static nsCOMPtr<nsIPrincipal> MakeTestPrincipal(const char* aURI) { + nsCOMPtr<nsIURI> uri; + MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), aURI)); + return BasePrincipal::CreateContentPrincipal(uri, {}); +} + +namespace { +struct RemoteTypes { + nsCString mIsolated; + nsCString mUnisolated; +}; + +struct WorkerExpectation { + nsCOMPtr<nsIPrincipal> mPrincipal; + WorkerKind mWorkerKind = WorkerKindShared; + Result<RemoteTypes, nsresult> mExpected = Err(NS_ERROR_FAILURE); + nsCString mCurrentRemoteType = "fakeRemoteType"_ns; + + void Check(bool aUseRemoteSubframes) { + nsAutoCString origin; + ASSERT_NS_SUCCEEDED(mPrincipal->GetOrigin(origin)); + + nsPrintfCString describe( + "origin: %s, workerKind: %s, currentRemoteType: %s, " + "useRemoteSubframes: %d", + origin.get(), mWorkerKind == WorkerKindShared ? "shared" : "service", + mCurrentRemoteType.get(), aUseRemoteSubframes); + + auto result = IsolationOptionsForWorker( + mPrincipal, mWorkerKind, mCurrentRemoteType, aUseRemoteSubframes); + ASSERT_EQ(result.isOk(), mExpected.isOk()) + << "Unexpected status (expected " << (mExpected.isOk() ? "ok" : "err") + << ") for " << describe; + if (mExpected.isOk()) { + const nsCString& expected = aUseRemoteSubframes + ? mExpected.inspect().mIsolated + : mExpected.inspect().mUnisolated; + ASSERT_EQ(result.inspect().mRemoteType, expected) + << "Unexpected remote type (expected " << expected << ") for " + << describe; + } + } +}; +} // namespace + +static nsCString WebIsolatedRemoteType(nsIPrincipal* aPrincipal) { + nsAutoCString origin; + MOZ_ALWAYS_SUCCEEDS(aPrincipal->GetSiteOrigin(origin)); + return FISSION_WEB_REMOTE_TYPE + "="_ns + origin; +} + +static nsCString CoopCoepRemoteType(nsIPrincipal* aPrincipal) { + nsAutoCString origin; + MOZ_ALWAYS_SUCCEEDS(aPrincipal->GetSiteOrigin(origin)); + return WITH_COOP_COEP_REMOTE_TYPE + "="_ns + origin; +} + +static nsCString ServiceWorkerIsolatedRemoteType(nsIPrincipal* aPrincipal) { + nsAutoCString origin; + MOZ_ALWAYS_SUCCEEDS(aPrincipal->GetSiteOrigin(origin)); + return SERVICEWORKER_REMOTE_TYPE + "="_ns + origin; +} + +TEST(ProcessIsolationTest, WorkerOptions) +{ + // Forcibly enable the privileged mozilla content process for the duration of + // the test. + MOZ_ALWAYS_SUCCEEDS(Preferences::SetCString( + "browser.tabs.remote.separatedMozillaDomains", "addons.mozilla.org")); + MOZ_ALWAYS_SUCCEEDS(Preferences::SetBool( + "browser.tabs.remote.separatePrivilegedMozillaWebContentProcess", true)); + auto cleanup = MakeScopeExit([&] { + MOZ_ALWAYS_SUCCEEDS( + Preferences::ClearUser("browser.tabs.remote.separatedMozillaDomains")); + MOZ_ALWAYS_SUCCEEDS(Preferences::ClearUser( + "browser.tabs.remote.separatePrivilegedMozillaWebContentProcess")); + }); + + nsCOMPtr<nsIPrincipal> systemPrincipal = SystemPrincipal::Get(); + nsCOMPtr<nsIPrincipal> nullPrincipal = + NullPrincipal::CreateWithoutOriginAttributes(); + nsCOMPtr<nsIPrincipal> secureComPrincipal = + MakeTestPrincipal("https://example.com"); + nsCOMPtr<nsIPrincipal> secureOrgPrincipal = + MakeTestPrincipal("https://example.org"); + nsCOMPtr<nsIPrincipal> insecureOrgPrincipal = + MakeTestPrincipal("http://example.org"); + nsCOMPtr<nsIPrincipal> filePrincipal = + MakeTestPrincipal("file:///path/to/dir"); + nsCOMPtr<nsIPrincipal> extensionPrincipal = + MakeTestPrincipal("moz-extension://fake-uuid"); + nsCOMPtr<nsIPrincipal> privilegedMozillaPrincipal = + MakeTestPrincipal("https://addons.mozilla.org"); + nsCOMPtr<nsIPrincipal> expandedPrincipal = ExpandedPrincipal::Create( + nsTArray{secureComPrincipal, extensionPrincipal}, {}); + nsCOMPtr<nsIPrincipal> nullSecureComPrecursorPrincipal = + NullPrincipal::CreateWithInheritedAttributes(secureComPrincipal); + + nsCString extensionRemoteType = + ExtensionPolicyService::GetSingleton().UseRemoteExtensions() + ? EXTENSION_REMOTE_TYPE + : NOT_REMOTE_TYPE; + nsCString fileRemoteType = + StaticPrefs::browser_tabs_remote_separateFileUriProcess() + ? FILE_REMOTE_TYPE + : WEB_REMOTE_TYPE; + + WorkerExpectation expectations[] = { + // Neither service not shared workers can have expanded principals + {.mPrincipal = expandedPrincipal, + .mWorkerKind = WorkerKindService, + .mExpected = Err(NS_ERROR_UNEXPECTED)}, + {.mPrincipal = expandedPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = Err(NS_ERROR_UNEXPECTED)}, + + // Service workers cannot have system or null principals + {.mPrincipal = systemPrincipal, + .mWorkerKind = WorkerKindService, + .mExpected = Err(NS_ERROR_UNEXPECTED)}, + {.mPrincipal = nullPrincipal, + .mWorkerKind = WorkerKindService, + .mExpected = Err(NS_ERROR_UNEXPECTED)}, + {.mPrincipal = nullSecureComPrecursorPrincipal, + .mWorkerKind = WorkerKindService, + .mExpected = Err(NS_ERROR_UNEXPECTED)}, + + // Service workers with various content principals + {.mPrincipal = secureComPrincipal, + .mWorkerKind = WorkerKindService, + .mExpected = + RemoteTypes{ServiceWorkerIsolatedRemoteType(secureComPrincipal), + WEB_REMOTE_TYPE}}, + {.mPrincipal = secureOrgPrincipal, + .mWorkerKind = WorkerKindService, + .mExpected = + RemoteTypes{ServiceWorkerIsolatedRemoteType(secureOrgPrincipal), + WEB_REMOTE_TYPE}}, + {.mPrincipal = extensionPrincipal, + .mWorkerKind = WorkerKindService, + .mExpected = RemoteTypes{extensionRemoteType, extensionRemoteType}}, + {.mPrincipal = privilegedMozillaPrincipal, + .mWorkerKind = WorkerKindService, + .mExpected = RemoteTypes{PRIVILEGEDMOZILLA_REMOTE_TYPE, + PRIVILEGEDMOZILLA_REMOTE_TYPE}}, + + // Shared Worker loaded from within a webCOOP+COEP remote type process, + // should load elsewhere. + {.mPrincipal = secureComPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = RemoteTypes{WebIsolatedRemoteType(secureComPrincipal), + WEB_REMOTE_TYPE}, + .mCurrentRemoteType = CoopCoepRemoteType(secureComPrincipal)}, + + // Even precursorless null principal should load elsewhere. + {.mPrincipal = nullPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = RemoteTypes{WEB_REMOTE_TYPE, WEB_REMOTE_TYPE}, + .mCurrentRemoteType = CoopCoepRemoteType(secureComPrincipal)}, + + // System principal shared workers can only load in the parent process or + // the privilegedabout remote type. + {.mPrincipal = systemPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = RemoteTypes{NOT_REMOTE_TYPE, NOT_REMOTE_TYPE}, + .mCurrentRemoteType = NOT_REMOTE_TYPE}, + {.mPrincipal = systemPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = RemoteTypes{PRIVILEGEDABOUT_REMOTE_TYPE, + PRIVILEGEDABOUT_REMOTE_TYPE}, + .mCurrentRemoteType = PRIVILEGEDABOUT_REMOTE_TYPE}, + {.mPrincipal = systemPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = Err(NS_ERROR_UNEXPECTED)}, + {.mPrincipal = systemPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = Err(NS_ERROR_UNEXPECTED)}, + + // Content principals should load in the appropriate remote types, + // ignoring the current remote type. + {.mPrincipal = secureComPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = RemoteTypes{WebIsolatedRemoteType(secureComPrincipal), + WEB_REMOTE_TYPE}}, + {.mPrincipal = secureOrgPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = RemoteTypes{WebIsolatedRemoteType(secureOrgPrincipal), + WEB_REMOTE_TYPE}}, + {.mPrincipal = insecureOrgPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = RemoteTypes{WebIsolatedRemoteType(insecureOrgPrincipal), + WEB_REMOTE_TYPE}}, + {.mPrincipal = filePrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = RemoteTypes{fileRemoteType, fileRemoteType}}, + {.mPrincipal = extensionPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = RemoteTypes{extensionRemoteType, extensionRemoteType}}, + {.mPrincipal = privilegedMozillaPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = RemoteTypes{PRIVILEGEDMOZILLA_REMOTE_TYPE, + PRIVILEGEDMOZILLA_REMOTE_TYPE}}, + {.mPrincipal = nullSecureComPrecursorPrincipal, + .mWorkerKind = WorkerKindShared, + .mExpected = RemoteTypes{WebIsolatedRemoteType(secureComPrincipal), + WEB_REMOTE_TYPE}}, + }; + + for (auto& expectation : expectations) { + expectation.Check(true); + expectation.Check(false); + } +} |