Backed out 3 changesets (bug 1642676) fro sharedworker related failures. CLOSED TREE

Backed out changeset 166624b9d855 (bug 1642676)
Backed out changeset 110cd0433bbe (bug 1642676)
Backed out changeset ca0591418c37 (bug 1642676)
This commit is contained in:
Cosmin Sabou 2020-06-23 20:47:29 +03:00
Родитель ce70c59eeb
Коммит de4bc9e6bd
21 изменённых файлов: 40 добавлений и 784 удалений

Просмотреть файл

@ -122,18 +122,6 @@ interface nsIServiceWorkerManagerListener : nsISupports
[scriptable, builtinclass, uuid(7404c8e8-4d47-4449-8ed1-47d1261d4e33)]
interface nsIServiceWorkerManager : nsISupports
{
/**
* A testing helper that registers a service worker for testing purpose (e.g. used to test
* a remote worker that has to spawn a new process to be launched).
* This method can only be used when "dom.serviceWorkers.testing.enabled" is true and
* it doesn't support all the registration options (e.g. updateViaCache is set automatically
* to "imports").
*/
[implicit_jscontext]
Promise registerForTest(in nsIPrincipal aPrincipal,
in AString aScope,
in AString aScriptURL);
/**
* Unregister an existing ServiceWorker registration for `aScope`.
* It keeps aCallback alive until the operation is concluded.

Просмотреть файл

@ -939,85 +939,6 @@ class ResolvePromiseRunnable final : public CancelableRunnable {
} // namespace
NS_IMETHODIMP
ServiceWorkerManager::RegisterForTest(nsIPrincipal* aPrincipal,
const nsAString& aScopeURL,
const nsAString& aScriptURL,
JSContext* aCx,
mozilla::dom::Promise** aPromise) {
nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
if (NS_WARN_IF(!global)) {
return NS_ERROR_FAILURE;
}
ErrorResult erv;
RefPtr<Promise> outer = Promise::Create(global, erv);
if (NS_WARN_IF(erv.Failed())) {
return erv.StealNSResult();
}
if (!StaticPrefs::dom_serviceWorkers_testing_enabled()) {
outer->MaybeRejectWithAbortError(
"registerForTest only allowed when dom.serviceWorkers.testing.enabled "
"is true");
return NS_OK;
}
if (aPrincipal == nullptr) {
outer->MaybeRejectWithAbortError("Missing principal");
return NS_OK;
}
if (aScriptURL.IsEmpty()) {
outer->MaybeRejectWithAbortError("Missing script url");
return NS_OK;
}
if (aScopeURL.IsEmpty()) {
outer->MaybeRejectWithAbortError("Missing scope url");
return NS_OK;
}
// The ClientType isn't really used here, but ClientType::Window
// is the least bad choice since this is happening on the main thread.
Maybe<ClientInfo> clientInfo =
dom::ClientManager::CreateInfo(ClientType::Window, aPrincipal);
if (!clientInfo.isSome()) {
outer->MaybeRejectWithUnknownError("Error creating clientInfo");
return NS_OK;
}
auto scope = NS_ConvertUTF16toUTF8(aScopeURL);
auto scriptURL = NS_ConvertUTF16toUTF8(aScriptURL);
auto regPromise = Register(clientInfo.ref(), scope, scriptURL,
dom::ServiceWorkerUpdateViaCache::Imports);
const RefPtr<ServiceWorkerManager> self(this);
const nsCOMPtr<nsIPrincipal> principal(aPrincipal);
regPromise->Then(
GetMainThreadSerialEventTarget(), __func__,
[self, outer, principal,
scope](const ServiceWorkerRegistrationDescriptor& regDesc) {
RefPtr<ServiceWorkerRegistrationInfo> registration =
self->GetRegistration(principal, NS_ConvertUTF16toUTF8(scope));
if (registration) {
outer->MaybeResolve(registration);
} else {
outer->MaybeRejectWithUnknownError(
"Failed to retrieve ServiceWorkerRegistrationInfo");
}
},
[outer](const mozilla::CopyableErrorResult& err) {
CopyableErrorResult result(err);
outer->MaybeReject(std::move(result));
});
outer.forget(aPromise);
return NS_OK;
}
RefPtr<ServiceWorkerRegistrationPromise> ServiceWorkerManager::Register(
const ClientInfo& aClientInfo, const nsACString& aScopeURL,
const nsACString& aScriptURL, ServiceWorkerUpdateViaCache aUpdateViaCache) {

Просмотреть файл

@ -43,7 +43,6 @@
#include "mozilla/dom/InternalRequest.h"
#include "mozilla/dom/ReferrerInfo.h"
#include "mozilla/dom/RemoteWorkerControllerChild.h"
#include "mozilla/dom/RemoteWorkerManager.h" // RemoteWorkerManager::GetRemoteType
#include "mozilla/dom/ServiceWorkerBinding.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/IPCStreamUtils.h"
@ -187,12 +186,6 @@ nsresult ServiceWorkerPrivateImpl::Initialize() {
return rv;
}
auto remoteType = RemoteWorkerManager::GetRemoteType(
principal, WorkerType::WorkerTypeService);
if (NS_WARN_IF(remoteType.isErr())) {
return remoteType.unwrapErr();
}
mRemoteWorkerData = RemoteWorkerData(
NS_ConvertUTF8toUTF16(mOuter->mInfo->ScriptSpec()), baseScriptURL,
baseScriptURL, /* name */ VoidString(),
@ -211,8 +204,7 @@ nsresult ServiceWorkerPrivateImpl::Initialize() {
// already_AddRefed<>. Let's set it to null.
/* referrerInfo */ nullptr,
storageAccess, std::move(serviceWorkerData), regInfo->AgentClusterId(),
remoteType.unwrap());
storageAccess, std::move(serviceWorkerData), regInfo->AgentClusterId());
mRemoteWorkerData.referrerInfo() = MakeAndAddRef<ReferrerInfo>();

Просмотреть файл

@ -32,7 +32,6 @@
#include "mozilla/dom/FetchEventOpProxyChild.h"
#include "mozilla/dom/IndexedDatabaseManager.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/RemoteWorkerManager.h" // RemoteWorkerManager::IsRemoteTypeAllowed
#include "mozilla/dom/RemoteWorkerTypes.h"
#include "mozilla/dom/ServiceWorkerDescriptor.h"
#include "mozilla/dom/ServiceWorkerInterceptController.h"
@ -313,14 +312,6 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(RemoteWorkerData&& aData) {
auto scopeExit = MakeScopeExit([&] { TransitionStateToTerminated(); });
// Verify the the RemoteWorker should be really allowed to run in this
// process, and fail if it shouldn't (This shouldn't normally happen,
// unless the RemoteWorkerData has been tempered in the process it was
// sent from).
if (!RemoteWorkerManager::IsRemoteTypeAllowed(aData)) {
return NS_ERROR_UNEXPECTED;
}
auto principalOrErr = PrincipalInfoToPrincipal(aData.principalInfo());
if (NS_WARN_IF(principalOrErr.isErr())) {
return principalOrErr.unwrapErr();

Просмотреть файл

@ -10,7 +10,6 @@
#include "mozilla/SchedulerGroup.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/dom/ContentChild.h" // ContentChild::GetSingleton
#include "mozilla/dom/RemoteWorkerParent.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/BackgroundUtils.h"
@ -38,6 +37,18 @@ bool IsServiceWorker(const RemoteWorkerData& aData) {
OptionalServiceWorkerData::TServiceWorkerData;
}
// Respecting COOP and COEP requires processing headers in the parent
// process in order to choose an appropriate content process, but the
// workers' ScriptLoader processes headers in content processes. An
// intermediary step that provides security guarantees is to simply never
// allow SharedWorkers and ServiceWorkers to exist in a COOP+COEP process.
// The ultimate goal is to allow these worker types to be put in such
// processes based on their script response headers.
// https://bugzilla.mozilla.org/show_bug.cgi?id=1595206
bool IsServiceWorkerRemoteType(const nsAString& aRemoteType) {
return IsWebRemoteType(aRemoteType) && !IsWebCoopCoepRemoteType(aRemoteType);
}
void TransmitPermissionsAndBlobURLsForPrincipalInfo(
ContentParent* aContentParent, const PrincipalInfo& aPrincipalInfo) {
AssertIsOnMainThread();
@ -59,111 +70,6 @@ void TransmitPermissionsAndBlobURLsForPrincipalInfo(
} // namespace
// static
Result<nsString, nsresult> RemoteWorkerManager::GetRemoteType(
const nsCOMPtr<nsIPrincipal>& aPrincipal, WorkerType aWorkerType) {
AssertIsOnMainThread();
if (aWorkerType != WorkerType::WorkerTypeService &&
aWorkerType != WorkerType::WorkerTypeShared) {
// This methods isn't expected to be called for worker type that
// aren't remote workers (currently Service and Shared workers).
return Err(NS_ERROR_UNEXPECTED);
}
nsString remoteType;
// If Gecko is running in single process mode, there is no child process
// to select, return without assigning any remoteType.
if (!BrowserTabsRemoteAutostart()) {
return remoteType;
}
auto* contentChild = ContentChild::GetSingleton();
bool isSystem = !!BasePrincipal::Cast(aPrincipal)->IsSystemPrincipal();
bool isMozExtension =
!isSystem && !!BasePrincipal::Cast(aPrincipal)->AddonPolicy();
if (aWorkerType == WorkerType::WorkerTypeShared && !contentChild &&
!isSystem) {
// Prevent content principals SharedWorkers to be launched in the main
// process while running in multiprocess mode.
//
// NOTE this also prevents moz-extension SharedWorker to be created
// while the extension process is disabled by prefs, allowing it would
// also trigger an assertion failure in
// RemoteWorkerManager::SelectorTargetActor, due to an unexpected
// content-principal parent-process workers while e10s is on).
return Err(NS_ERROR_ABORT);
}
bool separatePrivilegedMozilla = Preferences::GetBool(
"browser.tabs.remote.separatePrivilegedMozillaWebContentProcess", false);
if (isMozExtension) {
remoteType.Assign(NS_LITERAL_STRING(EXTENSION_REMOTE_TYPE));
} else if (separatePrivilegedMozilla) {
bool isPrivilegedMozilla = false;
aPrincipal->IsURIInPrefList("browser.tabs.remote.separatedMozillaDomains",
&isPrivilegedMozilla);
if (isPrivilegedMozilla) {
remoteType.Assign(NS_LITERAL_STRING(PRIVILEGEDMOZILLA_REMOTE_TYPE));
} else {
remoteType.Assign(aWorkerType == WorkerType::WorkerTypeShared &&
contentChild
? contentChild->GetRemoteType()
: NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
}
} else {
remoteType.Assign(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
}
return remoteType;
}
// static
bool RemoteWorkerManager::IsRemoteTypeAllowed(const RemoteWorkerData& aData) {
AssertIsOnMainThread();
// If Gecko is running in single process mode, there is no child process
// to select and we have to just consider it valid (if it should haven't
// been launched it should have been already prevented before reaching
// a RemoteWorkerChild instance).
if (!BrowserTabsRemoteAutostart()) {
return true;
}
const auto& principalInfo = aData.principalInfo();
auto* contentChild = ContentChild::GetSingleton();
if (!contentChild) {
// If e10s isn't disabled, only workers related to the system principal
// should be allowed to run in the parent process.
return principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo;
}
auto principalOrErr = PrincipalInfoToPrincipal(principalInfo);
if (NS_WARN_IF(principalOrErr.isErr())) {
return false;
}
nsCOMPtr<nsIPrincipal> principal = principalOrErr.unwrap();
// Recompute the remoteType based on the principal, to double-check that it
// has not been tempered to select a different child process than the one
// expected.
bool isServiceWorker = aData.serviceWorkerData().type() ==
OptionalServiceWorkerData::TServiceWorkerData;
auto remoteType = GetRemoteType(
principal, isServiceWorker ? WorkerTypeService : WorkerTypeShared);
if (NS_WARN_IF(remoteType.isErr())) {
return false;
}
return remoteType.unwrap().Equals(contentChild->GetRemoteType());
}
/* static */
already_AddRefed<RemoteWorkerManager> RemoteWorkerManager::GetOrCreate() {
AssertIsInMainProcess();
@ -205,24 +111,27 @@ void RemoteWorkerManager::RegisterActor(RemoteWorkerServiceParent* aActor) {
MOZ_ASSERT(!mChildActors.Contains(aActor));
mChildActors.AppendElement(aActor);
if (!mPendings.IsEmpty()) {
const auto& remoteType = GetRemoteTypeForActor(aActor);
nsTArray<Pending> unlaunched;
nsTArray<Pending> unlaunched;
RefPtr<ContentParent> contentParent =
BackgroundParent::GetContentParent(aActor->Manager());
auto scopeExit =
MakeScopeExit([&] { NS_ReleaseOnMainThread(contentParent.forget()); });
const auto& remoteType = contentParent->GetRemoteType();
if (!mPendings.IsEmpty()) {
// Flush pending launching.
for (Pending& p : mPendings) {
if (p.mController->IsTerminated()) {
continue;
}
const auto& workerRemoteType = p.mData.remoteType();
if (MatchRemoteType(remoteType, workerRemoteType)) {
LaunchInternal(p.mController, aActor, p.mData);
} else {
if (IsServiceWorker(p.mData) && !IsServiceWorkerRemoteType(remoteType)) {
unlaunched.AppendElement(std::move(p));
continue;
}
LaunchInternal(p.mController, aActor, p.mData);
}
std::swap(mPendings, unlaunched);
@ -318,28 +227,6 @@ void RemoteWorkerManager::AsyncCreationFailed(
NS_DispatchToCurrentThread(r.forget());
}
/* static */
nsString RemoteWorkerManager::GetRemoteTypeForActor(
const RemoteWorkerServiceParent* aActor) {
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
RefPtr<ContentParent> contentParent =
BackgroundParent::GetContentParent(aActor->Manager());
auto scopeExit =
MakeScopeExit([&] { NS_ReleaseOnMainThread(contentParent.forget()); });
if (NS_WARN_IF(!contentParent)) {
return EmptyString();
}
nsString aRemoteType(contentParent->GetRemoteType());
return aRemoteType;
}
template <typename Callback>
void RemoteWorkerManager::ForEachActor(Callback&& aCallback) const {
AssertIsOnBackgroundThread();
@ -403,13 +290,11 @@ RemoteWorkerManager::SelectTargetActorForServiceWorker(
RemoteWorkerServiceParent* actor = nullptr;
const auto& workerRemoteType = aData.remoteType();
ForEachActor([&](RemoteWorkerServiceParent* aActor,
RefPtr<ContentParent>&& aContentParent) {
const auto& remoteType = aContentParent->GetRemoteType();
if (MatchRemoteType(remoteType, workerRemoteType)) {
if (IsServiceWorkerRemoteType(remoteType)) {
auto lock = aContentParent->mRemoteWorkerActorData.Lock();
if (lock->mCount || !lock->mShutdownStarted) {
@ -442,7 +327,7 @@ RemoteWorkerManager::SelectTargetActorForServiceWorker(
RemoteWorkerServiceParent*
RemoteWorkerManager::SelectTargetActorForSharedWorker(
base::ProcessId aProcessId, const RemoteWorkerData& aData) const {
base::ProcessId aProcessId) const {
AssertIsOnBackgroundThread();
MOZ_ASSERT(!mChildActors.IsEmpty());
@ -450,10 +335,7 @@ RemoteWorkerManager::SelectTargetActorForSharedWorker(
ForEachActor([&](RemoteWorkerServiceParent* aActor,
RefPtr<ContentParent>&& aContentParent) {
bool matchRemoteType =
MatchRemoteType(aContentParent->GetRemoteType(), aData.remoteType());
if (!matchRemoteType) {
if (IsWebCoopCoepRemoteType(aContentParent->GetRemoteType())) {
return true;
}
@ -496,9 +378,8 @@ RemoteWorkerServiceParent* RemoteWorkerManager::SelectTargetActor(
return nullptr;
}
return IsServiceWorker(aData)
? SelectTargetActorForServiceWorker(aData)
: SelectTargetActorForSharedWorker(aProcessId, aData);
return IsServiceWorker(aData) ? SelectTargetActorForServiceWorker(aData)
: SelectTargetActorForSharedWorker(aProcessId);
}
void RemoteWorkerManager::LaunchNewContentProcess(
@ -520,8 +401,7 @@ void RemoteWorkerManager::LaunchNewContentProcess(
principalInfo = aData.principalInfo(),
bgEventTarget = std::move(bgEventTarget),
self = RefPtr<RemoteWorkerManager>(this)](
const CallbackParamType& aValue,
const nsString& remoteType) mutable {
const CallbackParamType& aValue) mutable {
if (aValue.IsResolve()) {
if (isServiceWorker) {
TransmitPermissionsAndBlobURLsForPrincipalInfo(aValue.ResolveValue(),
@ -533,21 +413,12 @@ void RemoteWorkerManager::LaunchNewContentProcess(
NS_ProxyRelease(__func__, bgEventTarget, self.forget());
} else {
// The "real" failure callback.
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
__func__, [self = std::move(self), remoteType] {
nsTArray<Pending> uncancelled;
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableFunction(__func__, [self = std::move(self)] {
auto pendings = std::move(self->mPendings);
for (const auto& pending : pendings) {
const auto& workerRemoteType = pending.mData.remoteType();
if (self->MatchRemoteType(remoteType, workerRemoteType)) {
pending.mController->CreationFailed();
} else {
uncancelled.AppendElement(pending);
}
pending.mController->CreationFailed();
}
std::swap(self->mPendings, uncancelled);
});
bgEventTarget->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
@ -555,19 +426,14 @@ void RemoteWorkerManager::LaunchNewContentProcess(
};
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
__func__, [callback = std::move(processLaunchCallback),
workerRemoteType = aData.remoteType()]() mutable {
auto remoteType = workerRemoteType.IsEmpty()
? NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE)
: workerRemoteType;
__func__, [callback = std::move(processLaunchCallback)]() mutable {
ContentParent::GetNewOrUsedBrowserProcessAsync(
/* aFrameElement = */ nullptr,
/* aRemoteType = */ remoteType)
/* aRemoteType = */ NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE))
->Then(GetCurrentSerialEventTarget(), __func__,
[callback = std::move(callback),
remoteType](const CallbackParamType& aValue) mutable {
callback(aValue, remoteType);
[callback = std::move(callback)](
const CallbackParamType& aValue) mutable {
callback(aValue);
});
});

Просмотреть файл

@ -11,7 +11,6 @@
#include "mozilla/RefPtr.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/RemoteWorkerTypes.h"
#include "mozilla/dom/WorkerPrivate.h" // WorkerType enum
#include "nsISupportsImpl.h"
#include "nsTArray.h"
@ -35,47 +34,6 @@ class RemoteWorkerManager final {
void Launch(RemoteWorkerController* aController,
const RemoteWorkerData& aData, base::ProcessId aProcessId);
static bool MatchRemoteType(const nsAString& processRemoteType,
const nsAString& workerRemoteType) {
if (processRemoteType.Equals(workerRemoteType)) {
return true;
}
// Respecting COOP and COEP requires processing headers in the parent
// process in order to choose an appropriate content process, but the
// workers' ScriptLoader processes headers in content processes. An
// intermediary step that provides security guarantees is to simply never
// allow SharedWorkers and ServiceWorkers to exist in a COOP+COEP process.
// The ultimate goal is to allow these worker types to be put in such
// processes based on their script response headers.
// https://bugzilla.mozilla.org/show_bug.cgi?id=1595206
if (IsWebCoopCoepRemoteType(processRemoteType)) {
return false;
}
// A worker for a non privileged child process can be launched in
// any web child process that is not COOP and COEP.
if ((workerRemoteType.IsEmpty() || IsWebRemoteType(workerRemoteType)) &&
IsWebRemoteType(processRemoteType)) {
return true;
}
return false;
}
/**
* Get the child process RemoteType where a RemoteWorker should be
* launched.
*/
static Result<nsString, nsresult> GetRemoteType(
const nsCOMPtr<nsIPrincipal>& aPrincipal, WorkerType aWorkerType);
/**
* Verify if a remote worker should be allowed to run in the current
* child process remoteType.
*/
static bool IsRemoteTypeAllowed(const RemoteWorkerData& aData);
private:
RemoteWorkerManager();
~RemoteWorkerManager();
@ -87,7 +45,7 @@ class RemoteWorkerManager final {
const RemoteWorkerData& aData) const;
RemoteWorkerServiceParent* SelectTargetActorForSharedWorker(
base::ProcessId aProcessId, const RemoteWorkerData& aData) const;
base::ProcessId aProcessId) const;
void LaunchInternal(RemoteWorkerController* aController,
RemoteWorkerServiceParent* aTargetActor,
@ -98,9 +56,6 @@ class RemoteWorkerManager final {
void AsyncCreationFailed(RemoteWorkerController* aController);
static nsString GetRemoteTypeForActor(
const RemoteWorkerServiceParent* aActor);
// Iterate through all RemoteWorkerServiceParent actors, starting from a
// random index (as if iterating through a circular array).
//

Просмотреть файл

@ -70,9 +70,6 @@ struct RemoteWorkerData
OptionalServiceWorkerData serviceWorkerData;
nsID agentClusterId;
// Child process remote type where the worker should only run on.
nsString remoteType;
};
// ErrorData/ErrorDataNote correspond to WorkerErrorReport/WorkerErrorNote

Просмотреть файл

@ -1,65 +0,0 @@
/* -*- 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 "../RemoteWorkerManager.h"
using namespace mozilla::dom;
TEST(RemoteWorkerManager, TestMatchRemoteType)
{
static const struct {
const nsString processRemoteType;
const nsString workerRemoteType;
const bool shouldMatch;
} tests[] = {
// Test exact matches between process and worker remote types.
{NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), true},
{NS_LITERAL_STRING(EXTENSION_REMOTE_TYPE),
NS_LITERAL_STRING(EXTENSION_REMOTE_TYPE), true},
{NS_LITERAL_STRING(PRIVILEGEDMOZILLA_REMOTE_TYPE),
NS_LITERAL_STRING(PRIVILEGEDMOZILLA_REMOTE_TYPE), true},
// Test workers with remoteType "web" not launched on non-web or coop+coep
// processes.
{NS_LITERAL_STRING(PRIVILEGEDMOZILLA_REMOTE_TYPE),
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), false},
{NS_LITERAL_STRING(PRIVILEGEDABOUT_REMOTE_TYPE),
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), false},
{NS_LITERAL_STRING(EXTENSION_REMOTE_TYPE),
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), false},
{NS_LITERAL_STRING(FILE_REMOTE_TYPE),
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), false},
{NS_LITERAL_STRING(WITH_COOP_COEP_REMOTE_TYPE_PREFIX),
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), false},
// Test workers with remoteType "web" launched in web child processes.
{NS_LITERAL_STRING(LARGE_ALLOCATION_REMOTE_TYPE),
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), true},
{NS_LITERAL_STRING(FISSION_WEB_REMOTE_TYPE),
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), true},
// Test empty remoteType default to "web" remoteType.
{NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), EmptyString(), true},
{NS_LITERAL_STRING(WITH_COOP_COEP_REMOTE_TYPE_PREFIX), EmptyString(),
false},
{NS_LITERAL_STRING(PRIVILEGEDMOZILLA_REMOTE_TYPE), EmptyString(), false},
{NS_LITERAL_STRING(EXTENSION_REMOTE_TYPE), EmptyString(), false},
};
for (const auto& test : tests) {
auto message =
nsPrintfCString(R"(MatchRemoteType("%s", "%s") should return %s)",
NS_ConvertUTF16toUTF8(test.processRemoteType).get(),
NS_ConvertUTF16toUTF8(test.workerRemoteType).get(),
test.shouldMatch ? "true" : "false");
ASSERT_EQ(RemoteWorkerManager::MatchRemoteType(test.processRemoteType,
test.workerRemoteType),
test.shouldMatch)
<< message;
}
}

Просмотреть файл

@ -1,13 +0,0 @@
# -*- 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/.
UNIFIED_SOURCES = [
'TestMatchRemoteType.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul-gtest'

Просмотреть файл

@ -9,7 +9,6 @@ EXPORTS.mozilla.dom += [
'RemoteWorkerController.h',
'RemoteWorkerControllerChild.h',
'RemoteWorkerControllerParent.h',
'RemoteWorkerManager.h',
'RemoteWorkerParent.h',
'RemoteWorkerService.h',
'RemoteWorkerServiceChild.h',
@ -40,8 +39,6 @@ IPDL_SOURCES += [
'RemoteWorkerTypes.ipdlh',
]
TEST_DIRS += ['gtest']
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

Просмотреть файл

@ -13,7 +13,6 @@
#include "mozilla/dom/MessageChannel.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/PMessagePort.h"
#include "mozilla/dom/RemoteWorkerManager.h" // RemoteWorkerManager::GetRemoteType
#include "mozilla/dom/RemoteWorkerTypes.h"
#include "mozilla/dom/SharedWorkerBinding.h"
#include "mozilla/dom/SharedWorkerChild.h"
@ -199,21 +198,13 @@ already_AddRefed<SharedWorker> SharedWorker::Constructor(
MOZ_ASSERT(loadInfo.mCookieJarSettings);
net::CookieJarSettings::Cast(loadInfo.mCookieJarSettings)->Serialize(cjsData);
auto remoteType = RemoteWorkerManager::GetRemoteType(
loadInfo.mPrincipal, WorkerType::WorkerTypeShared);
if (NS_WARN_IF(remoteType.isErr())) {
aRv.Throw(remoteType.unwrapErr());
return nullptr;
}
RemoteWorkerData remoteWorkerData(
nsString(aScriptURL), baseURL, resolvedScriptURL, name,
loadingPrincipalInfo, principalInfo, partitionedPrincipalInfo,
loadInfo.mUseRegularPrincipal,
loadInfo.mHasStorageAccessPermissionGranted, cjsData, loadInfo.mDomain,
isSecureContext, ipcClientInfo, loadInfo.mReferrerInfo, storageAllowed,
void_t() /* OptionalServiceWorkerData */, agentClusterId,
remoteType.unwrap());
void_t() /* OptionalServiceWorkerData */, agentClusterId);
PSharedWorkerChild* pActor = actorChild->SendPSharedWorkerConstructor(
remoteWorkerData, loadInfo.mWindowID, portIdentifier.release());

Просмотреть файл

@ -18,7 +18,3 @@ support-files =
file_use_counter_worker.js
file_use_counter_shared_worker.js
file_use_counter_service_worker.js
[browser_privilegedmozilla_remoteworker.js]
support-files =
file_service_worker.js
file_service_worker_container.html

Просмотреть файл

@ -1,117 +0,0 @@
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({
set: [
["browser.tabs.remote.separatePrivilegedMozillaWebContentProcess", true],
["browser.tabs.remote.separatedMozillaDomains", "example.org"],
["dom.ipc.processCount.web", 1],
["dom.ipc.processCount.privilegedmozilla", 1],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.serviceworkers.parent_intercept", true],
],
});
});
// This test attempts to verify proper placement of spawned remoteworkers
// by spawning them and then verifying that they were spawned in the expected
// process by way of nsIWorkerDebuggerManager enumeration.
//
// Unfortunately, there's no other way to introspect where a worker global was
// spawned at this time. (devtools just ends up enumerating all workers in all
// processes and we don't want to depend on devtools in this test).
//
// As a result, this test currently only tests situations where it's known that
// a remote worker will be spawned in the same process that is initiating its
// spawning.
//
// This should be enhanced in the future.
add_task(async function test_serviceworker() {
const basePath = "browser/dom/workers/test";
const pagePath = `${basePath}/file_service_worker_container.html`;
const scriptPath = `${basePath}/file_service_worker.js`;
Services.ppmm.releaseCachedProcesses();
async function runWorkerInProcess() {
function getActiveWorkerURLs() {
const wdm = Cc[
"@mozilla.org/dom/workers/workerdebuggermanager;1"
].getService(Ci.nsIWorkerDebuggerManager);
const workerDebuggerUrls = Array.from(
wdm.getWorkerDebuggerEnumerator()
).map(wd => {
return wd.url;
});
return workerDebuggerUrls;
}
return new Promise(resolve => {
content.navigator.serviceWorker.ready.then(({ active }) => {
const { port1, port2 } = new content.MessageChannel();
active.postMessage("webpage->serviceworker", [port2]);
port1.onmessage = evt => {
resolve({
msg: evt.data,
workerUrls: getActiveWorkerURLs(),
});
};
});
}).then(async res => {
// Unregister the service worker used in this test.
const registration = await content.navigator.serviceWorker.ready;
await registration.unregister();
return res;
});
}
const testCaseList = [
// TODO: find a reasonable way to test the non-privileged scenario
// (because more than 1 process is usually available and the worker
// can be launched in a different one from the one where the tab
// is running).
/*{
remoteType: "web",
hostname: "example.com",
},*/
{
remoteType: "privilegedmozilla",
hostname: `example.org`,
},
];
for (const testCase of testCaseList) {
const { remoteType, hostname } = testCase;
info(`Test remote serviceworkers launch selects a ${remoteType} process`);
const tab = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
url: `https://${hostname}/${pagePath}`,
});
is(
tab.linkedBrowser.remoteType,
remoteType,
`Got the expected remoteType for ${hostname} tab`
);
const results = await SpecialPowers.spawn(
tab.linkedBrowser,
[],
runWorkerInProcess
);
Assert.deepEqual(
results,
{
msg: "serviceworker-reply",
workerUrls: [`https://${hostname}/${scriptPath}`],
},
`Got the expected results for ${hostname} tab`
);
BrowserTestUtils.removeTab(tab);
}
});

Просмотреть файл

@ -1,3 +0,0 @@
self.onmessage = evt => {
evt.ports[0].postMessage("serviceworker-reply");
};

Просмотреть файл

@ -1,15 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
(async function () {
await navigator.serviceWorker.register("file_service_worker.js");
await navigator.serviceWorker.ready;
})();
</script>
</head>
<body>
Service Worker Container
</body>
</html>

Просмотреть файл

@ -1,134 +0,0 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { TestUtils } = ChromeUtils.import(
"resource://testing-common/TestUtils.jsm"
);
const { AddonTestUtils } = ChromeUtils.import(
"resource://testing-common/AddonTestUtils.jsm"
);
const { createHttpServer } = AddonTestUtils;
// Force ServiceWorkerRegistrar to init by calling do_get_profile.
// (This has to be called before AddonTestUtils.init, because it does
// also call do_get_profile internally but it doesn't notify
// profile-after-change).
do_get_profile(true);
AddonTestUtils.init(this);
const server = createHttpServer({
hosts: ["localhost", "example.org"],
});
server.registerPathHandler("/sw.js", (request, response) => {
info(`/sw.js is being requested: ${JSON.stringify(request)}`);
response.setHeader("Content-Type", "application/javascript");
response.write("");
});
add_task(async function setup_prefs() {
equal(
Services.prefs.getBoolPref("browser.tabs.remote.autostart"),
true,
"e10s is expected to be enabled"
);
// Enable nsIServiceWorkerManager.registerForTest.
Services.prefs.setBoolPref("dom.serviceWorkers.testing.enabled", true);
// Configure prefs to configure example.org as a domain to load
// in a privilegedmozilla content child process.
Services.prefs.setBoolPref(
"browser.tabs.remote.separatePrivilegedMozillaWebContentProcess",
true
);
Services.prefs.setCharPref(
"browser.tabs.remote.separatedMozillaDomains",
"example.org"
);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("dom.serviceWorkers.testing.enabled");
Services.prefs.clearUserPref(
"browser.tabs.remote.separatePrivilegedMozillaWebContentProcess"
);
Services.prefs.clearUserPref("browser.tabs.remote.separatedMozillaDomains");
});
});
/**
* This test installs a ServiceWorker via test API and verify that the install
* process spawns a new process. (Normally ServiceWorker installation won't
* cause a new content process to be spawned because the call to register must
* be coming from within an existing content process, but the registerForTest
* API allows us to bypass this restriction.)
*
* This models the real-world situation of a push notification being received
* from the network which results in a ServiceWorker being spawned without their
* necessarily being an existing content process to host it (especially under Fission).
*/
add_task(async function launch_remoteworkers_in_new_processes() {
const swm = Cc["@mozilla.org/serviceworkers/manager;1"].getService(
Ci.nsIServiceWorkerManager
);
const ssm = Services.scriptSecurityManager;
const initialChildCount = Services.ppmm.childCount;
// A test service worker that should spawn a regular web content child process.
const swRegInfoWeb = await swm.registerForTest(
ssm.createContentPrincipal(Services.io.newURI("http://localhost"), {}),
"http://localhost/scope",
"http://localhost/sw.js"
);
swRegInfoWeb.QueryInterface(Ci.nsIServiceWorkerRegistrationInfo);
info(
`web content service worker registered: ${JSON.stringify({
principal: swRegInfoWeb.principal.URI.spec,
scope: swRegInfoWeb.scope,
})}`
);
// A test service worker that should spawn a privilegedmozilla child process.
const swRegInfoPriv = await swm.registerForTest(
ssm.createContentPrincipal(Services.io.newURI("http://example.org"), {}),
"http://example.org/scope",
"http://example.org/sw.js"
);
swRegInfoPriv.QueryInterface(Ci.nsIServiceWorkerRegistrationInfo);
info(
`privilegedmozilla service worker registered: ${JSON.stringify({
principal: swRegInfoPriv.principal.URI.spec,
scope: swRegInfoPriv.scope,
})}`
);
info("Wait new process to be launched");
await TestUtils.waitForCondition(() => {
return Services.ppmm.childCount - initialChildCount >= 2;
}, "wait for a new child processes to be started");
// Wait both workers to become active to be sure that. besides spawning
// the new child processes as expected, the two remote worker have been
// able to run successfully (in other word their remote worker data did
// pass successfull the IsRemoteTypeAllowed check in RemoteworkerChild).
info("Wait for webcontent worker to become active");
await TestUtils.waitForCondition(
() => swRegInfoPriv.activeWorker,
`wait workers for scope ${swRegInfoPriv.scope} to be active`
);
info("Wait for privilegedmozille worker to become active");
await TestUtils.waitForCondition(
() => swRegInfoPriv.activeWorker,
`wait workers for scope ${swRegInfoPriv.scope} to be active`
);
});

Просмотреть файл

@ -8,12 +8,3 @@ support-files =
[test_workers.js]
[test_fileReader.js]
[test_remoteworker_launch_new_process.js]
# The following firefox-appdir make sure that this xpcshell test will run
# with e10s enabled (which is needed to make sure that the test case is
# going to launch the expected new processes)
firefox-appdir = browser
# Disable plugin loading to make it rr able to record and replay this test.
prefs =
plugin.disable=true

Просмотреть файл

@ -1,34 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// This test attemps to verify that:
// - SharedWorkers can be created and successfully spawned by web extensions
// when web-extensions run in their own child process.
add_task(async function test_spawn_shared_worker() {
const background = async function() {
const worker = new SharedWorker("worker.js");
await new Promise(resolve => {
worker.port.onmessage = resolve;
worker.port.postMessage("bgpage->worker");
});
browser.test.sendMessage("test-shared-worker:done");
};
const extension = ExtensionTestUtils.loadExtension({
background,
files: {
"worker.js": function() {
self.onconnect = evt => {
const port = evt.ports[0];
port.onmessage = () => port.postMessage("worker-reply");
};
},
},
});
await extension.startup();
await extension.awaitMessage("test-shared-worker:done");
await extension.unload();
});

Просмотреть файл

@ -1,46 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// This test attemps to verify that:
// - SharedWorkers cannot be created by web extensions when web extensions
// are being run in the main process (because SharedWorkers are only
// allowed to be spawned in the parent process if they have a system principal).
add_task(async function test_spawn_shared_worker() {
const background = function() {
// This test covers the builds where the extensions are still
// running in the main process (it just checks that we don't
// allow it).
browser.test.assertThrows(
() => {
try {
new SharedWorker("worker.js");
} catch (e) {
// assertThrows is currently failing to match the error message
// automatically, let's cheat a little bit for now.
throw new Error(`${e}`);
}
},
/NS_ERROR_ABORT/,
"Got the expected failure in non-remote mode"
);
browser.test.sendMessage("test-shared-worker:done");
};
const extension = ExtensionTestUtils.loadExtension({
background,
files: {
"worker.js": function() {
self.onconnect = evt => {
const port = evt.ports[0];
port.onmessage = () => port.postMessage("worker-reply");
};
},
},
});
await extension.startup();
await extension.awaitMessage("test-shared-worker:done");
await extension.unload();
});

Просмотреть файл

@ -27,4 +27,3 @@ skip-if = tsan
[test_WebExtensionContentScript.js]
[test_ext_ipcBlob.js]
skip-if = os == 'android' && processor == 'x86_64'
[test_ext_shared_workers.js]

Просмотреть файл

@ -71,7 +71,6 @@ skip-if = os == 'android' && processor == 'x86_64'
[test_ext_test_wrapper.js]
[test_ext_unknown_permissions.js]
skip-if = os == 'android' && processor == 'x86_64'
[test_ext_shared_workers_mainprocess_disallowed.js]
[test_ext_webRequest_urlclassification.js]
[test_extension_permissions_migration.js]
[test_load_all_api_modules.js]