Bug 1438945 - Part 2: PSharedWorker protocol. r=asuth

--HG--
extra : rebase_source : 1ec6d2c9fc8dcffb9aa4958d81784408090df534
This commit is contained in:
Andrea Marchesini 2018-11-19 15:18:20 -08:00
parent b0cbc4dcf9
commit 1bf562b370
16 changed files with 335 additions and 89 deletions

View File

@ -1408,6 +1408,7 @@ RuntimeService::RegisterWorker(WorkerPrivate* aWorkerPrivate)
domainInfo->mActiveWorkers.AppendElement(aWorkerPrivate);
}
/* TODO
if (isSharedWorker) {
#ifdef DEBUG
for (const UniquePtr<SharedWorkerInfo>& data : domainInfo->mSharedWorkerInfos) {
@ -1427,6 +1428,7 @@ RuntimeService::RegisterWorker(WorkerPrivate* aWorkerPrivate)
aWorkerPrivate->WorkerName()));
domainInfo->mSharedWorkerInfos.AppendElement(std::move(sharedWorkerInfo));
}
*/
}
// From here on out we must call UnregisterWorker if something fails!
@ -1485,6 +1487,7 @@ void
RuntimeService::RemoveSharedWorker(WorkerDomainInfo* aDomainInfo,
WorkerPrivate* aWorkerPrivate)
{
/* TODO
for (uint32_t i = 0; i < aDomainInfo->mSharedWorkerInfos.Length(); ++i) {
const UniquePtr<SharedWorkerInfo>& data =
aDomainInfo->mSharedWorkerInfos[i];
@ -1493,6 +1496,7 @@ RuntimeService::RemoveSharedWorker(WorkerDomainInfo* aDomainInfo,
break;
}
}
*/
}
void
@ -2291,55 +2295,6 @@ RuntimeService::PropagateFirstPartyStorageAccessGranted(nsPIDOMWindowInner* aWin
}
}
nsresult
RuntimeService::CreateSharedWorker(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
const nsAString& aName,
SharedWorker** aSharedWorker)
{
AssertIsOnMainThread();
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
MOZ_ASSERT(window);
// If the window is blocked from accessing storage, do not allow it
// to connect to a SharedWorker. This would potentially allow it
// to communicate with other windows that do have storage access.
// Allow private browsing, however, as we handle that isolation
// via the principal.
auto storageAllowed = nsContentUtils::StorageAllowedForWindow(window);
if (storageAllowed != nsContentUtils::StorageAccess::eAllow &&
storageAllowed != nsContentUtils::StorageAccess::ePrivateBrowsing) {
return NS_ERROR_DOM_SECURITY_ERR;
}
// Assert that the principal private browsing state matches the
// StorageAccess value.
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
if (storageAllowed == nsContentUtils::StorageAccess::ePrivateBrowsing) {
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
nsCOMPtr<nsIPrincipal> principal = doc ? doc->NodePrincipal() : nullptr;
uint32_t privateBrowsingId = 0;
if (principal) {
MOZ_ALWAYS_SUCCEEDS(principal->GetPrivateBrowsingId(&privateBrowsingId));
}
MOZ_DIAGNOSTIC_ASSERT(privateBrowsingId != 0);
}
#endif // MOZ_DIAGNOSTIC_ASSERT_ENABLED
JSContext* cx = aGlobal.Context();
WorkerLoadInfo loadInfo;
nsresult rv = WorkerPrivate::GetLoadInfo(cx, window, nullptr, aScriptURL,
false,
WorkerPrivate::OverrideLoadGroup,
WorkerTypeShared, &loadInfo);
NS_ENSURE_SUCCESS(rv, rv);
return CreateSharedWorkerFromLoadInfo(cx, &loadInfo, aScriptURL, aName,
aSharedWorker);
}
nsresult
RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx,
WorkerLoadInfo* aLoadInfo,
@ -2347,6 +2302,7 @@ RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx,
const nsAString& aName,
SharedWorker** aSharedWorker)
{
/* TODO
AssertIsOnMainThread();
MOZ_ASSERT(aLoadInfo);
MOZ_ASSERT(aLoadInfo->mResolvedScriptURI);
@ -2459,6 +2415,7 @@ RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx,
}
sharedWorker.forget(aSharedWorker);
*/
return NS_OK;
}

View File

@ -155,12 +155,6 @@ public:
void
PropagateFirstPartyStorageAccessGranted(nsPIDOMWindowInner* aWindow);
nsresult
CreateSharedWorker(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
const nsAString& aName,
SharedWorker** aSharedWorker);
void
ForgetSharedWorker(WorkerPrivate* aWorkerPrivate);

View File

@ -0,0 +1,20 @@
/* 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 protocol PBackground;
namespace mozilla {
namespace dom {
protocol PSharedWorker
{
manager PBackground;
child:
// TODO:
async __delete__();
};
} // namespace dom
} // namespace mozilla

View File

@ -6,42 +6,40 @@
#include "SharedWorker.h"
#include "nsPIDOMWindow.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/EventTarget.h"
#include "mozilla/dom/MessageChannel.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/PMessagePort.h"
#include "mozilla/dom/SharedWorkerBinding.h"
#include "mozilla/dom/SharedWorkerChild.h"
#include "mozilla/dom/WorkerBinding.h"
#include "mozilla/Telemetry.h"
#include "nsContentUtils.h"
#include "nsIClassInfoImpl.h"
#include "mozilla/dom/workerinternals/RuntimeService.h"
#include "mozilla/dom/WorkerLoadInfo.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "nsContentUtils.h"
#include "nsPIDOMWindow.h"
#ifdef XP_WIN
#undef PostMessage
#endif
using mozilla::dom::Optional;
using mozilla::dom::Sequence;
using mozilla::dom::MessagePort;
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::ipc;
SharedWorker::SharedWorker(nsPIDOMWindowInner* aWindow,
WorkerPrivate* aWorkerPrivate,
SharedWorkerChild* aActor,
MessagePort* aMessagePort)
: DOMEventTargetHelper(aWindow)
, mWorkerPrivate(aWorkerPrivate)
, mActor(aActor)
, mMessagePort(aMessagePort)
, mFrozen(false)
{
AssertIsOnMainThread();
MOZ_ASSERT(aWorkerPrivate);
MOZ_ASSERT(aActor);
MOZ_ASSERT(aMessagePort);
}
@ -59,13 +57,36 @@ SharedWorker::Constructor(const GlobalObject& aGlobal,
{
AssertIsOnMainThread();
workerinternals::RuntimeService* rts =
workerinternals::RuntimeService::GetOrCreateService();
if (!rts) {
aRv = NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsPIDOMWindowInner> window =
do_QueryInterface(aGlobal.GetAsSupports());
MOZ_ASSERT(window);
// If the window is blocked from accessing storage, do not allow it
// to connect to a SharedWorker. This would potentially allow it
// to communicate with other windows that do have storage access.
// Allow private browsing, however, as we handle that isolation
// via the principal.
auto storageAllowed = nsContentUtils::StorageAllowedForWindow(window);
if (storageAllowed != nsContentUtils::StorageAccess::eAllow &&
storageAllowed != nsContentUtils::StorageAccess::ePrivateBrowsing) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
// Assert that the principal private browsing state matches the
// StorageAccess value.
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
if (storageAllowed == nsContentUtils::StorageAccess::ePrivateBrowsing) {
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
nsCOMPtr<nsIPrincipal> principal = doc ? doc->NodePrincipal() : nullptr;
uint32_t privateBrowsingId = 0;
if (principal) {
MOZ_ALWAYS_SUCCEEDS(principal->GetPrivateBrowsingId(&privateBrowsingId));
}
MOZ_DIAGNOSTIC_ASSERT(privateBrowsingId != 0);
}
#endif // MOZ_DIAGNOSTIC_ASSERT_ENABLED
nsAutoString name;
if (aOptions.IsString()) {
name = aOptions.GetAsString();
@ -74,14 +95,69 @@ SharedWorker::Constructor(const GlobalObject& aGlobal,
name = aOptions.GetAsWorkerOptions().mName;
}
RefPtr<SharedWorker> sharedWorker;
nsresult rv = rts->CreateSharedWorker(aGlobal, aScriptURL, name,
getter_AddRefs(sharedWorker));
if (NS_FAILED(rv)) {
aRv = rv;
JSContext* cx = aGlobal.Context();
WorkerLoadInfo loadInfo;
aRv = WorkerPrivate::GetLoadInfo(cx, window, nullptr, aScriptURL,
false, WorkerPrivate::OverrideLoadGroup,
WorkerTypeShared, &loadInfo);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
PrincipalInfo principalInfo;
aRv = PrincipalToPrincipalInfo(loadInfo.mPrincipal, &principalInfo);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
PrincipalInfo loadingPrincipalInfo;
aRv = PrincipalToPrincipalInfo(loadInfo.mLoadingPrincipal,
&loadingPrincipalInfo);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
// We don't actually care about this MessageChannel, but we use it to 'steal'
// its 2 connected ports.
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(window);
RefPtr<MessageChannel> channel = MessageChannel::Constructor(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
MessagePortIdentifier portIdentifier;
channel->Port1()->CloneAndDisentangle(portIdentifier);
nsAutoCString resolvedScriptURL;
aRv = loadInfo.mResolvedScriptURI->GetSpec(resolvedScriptURL);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
nsAutoCString baseURL;
aRv = loadInfo.mBaseURI->GetSpec(baseURL);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
// Register this component to PBackground.
PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
SharedWorkerLoadInfo sharedWorkerLoadInfo(nsString(aScriptURL), baseURL,
resolvedScriptURL, name,
loadingPrincipalInfo, principalInfo,
loadInfo.mDomain, portIdentifier);
PSharedWorkerChild* pActor =
actorChild->SendPSharedWorkerConstructor(sharedWorkerLoadInfo);
RefPtr<SharedWorkerChild> actor = static_cast<SharedWorkerChild*>(pActor);
MOZ_ASSERT(actor);
RefPtr<SharedWorker> sharedWorker = new SharedWorker(window, actor,
channel->Port2());
return sharedWorker.forget();
}
@ -153,7 +229,6 @@ SharedWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
ErrorResult& aRv)
{
AssertIsOnMainThread();
MOZ_ASSERT(mWorkerPrivate);
MOZ_ASSERT(mMessagePort);
mMessagePort->PostMessage(aCx, aMessage, aTransferable, aRv);

View File

@ -23,13 +23,14 @@ class EventChainPreVisitor;
namespace dom {
class MessagePort;
class StringOrWorkerOptions;
class WorkerPrivate;
class Event;
namespace workerinternals {
class RuntimeService;
}
class SharedWorkerChild;
class SharedWorker final : public DOMEventTargetHelper
{
friend class workerinternals::RuntimeService;
@ -37,7 +38,7 @@ class SharedWorker final : public DOMEventTargetHelper
typedef mozilla::ErrorResult ErrorResult;
typedef mozilla::dom::GlobalObject GlobalObject;
RefPtr<WorkerPrivate> mWorkerPrivate;
RefPtr<SharedWorkerChild> mActor;
RefPtr<MessagePort> mMessagePort;
nsTArray<RefPtr<Event>> mFrozenEvents;
bool mFrozen;
@ -78,16 +79,10 @@ public:
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
WorkerPrivate*
GetWorkerPrivate() const
{
return mWorkerPrivate;
}
private:
// This class can only be created from the RuntimeService.
SharedWorker(nsPIDOMWindowInner* aWindow,
WorkerPrivate* aWorkerPrivate,
SharedWorkerChild* aActor,
MessagePort* aMessagePort);
// This class is reference-counted and will be destroyed from Release().

View File

@ -0,0 +1,19 @@
/* -*- 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 "SharedWorkerChild.h"
namespace mozilla {
namespace dom {
SharedWorkerChild::SharedWorkerChild()
{
}
SharedWorkerChild::~SharedWorkerChild() = default;
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,34 @@
/* -*- 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/. */
#ifndef mozilla_dom_dom_SharedWorkerChild_h
#define mozilla_dom_dom_SharedWorkerChild_h
#include "mozilla/dom/PSharedWorkerChild.h"
#include "nsISupportsImpl.h"
namespace mozilla {
namespace dom {
class SharedWorker;
class SharedWorkerChild final : public mozilla::dom::PSharedWorkerChild
{
public:
NS_INLINE_DECL_REFCOUNTING(SharedWorkerChild)
SharedWorkerChild();
private:
~SharedWorkerChild();
void ActorDestroy(ActorDestroyReason aWhy) override;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_dom_SharedWorkerChild_h

View File

@ -0,0 +1,29 @@
/* -*- 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 "SharedWorkerParent.h"
namespace mozilla {
using ipc::PrincipalInfo;
namespace dom {
SharedWorkerParent::SharedWorkerParent()
{
// TODO
}
SharedWorkerParent::~SharedWorkerParent() = default;
void
SharedWorkerParent::ActorDestroy(IProtocol::ActorDestroyReason aReason)
{
// TODO
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,34 @@
/* -*- 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/. */
#ifndef mozilla_dom_dom_SharedWorkerParent_h
#define mozilla_dom_dom_SharedWorkerParent_h
#include "mozilla/dom/PSharedWorkerParent.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "nsISupportsImpl.h"
namespace mozilla {
namespace dom {
class SharedWorkerParent final : public mozilla::dom::PSharedWorkerParent
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedWorkerParent)
SharedWorkerParent();
private:
~SharedWorkerParent();
void
ActorDestroy(IProtocol::ActorDestroyReason aReason) override;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_dom_SharedWorkerParent_h

View File

@ -0,0 +1,30 @@
/* 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 DOMTypes;
include PBackgroundSharedTypes;
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
namespace mozilla {
namespace dom {
struct SharedWorkerLoadInfo
{
nsString originalScriptURL;
nsCString baseScriptURL;
nsCString resolvedScriptURL;
nsString name;
PrincipalInfo loadingPrincipalInfo;
PrincipalInfo principalInfo;
nsCString domain;
MessagePortIdentifier portIdentifier;
};
} // namespace dom
} // namespace mozilla

View File

@ -6,10 +6,19 @@
EXPORTS.mozilla.dom += [
'SharedWorker.h',
'SharedWorkerChild.h',
'SharedWorkerParent.h',
]
UNIFIED_SOURCES += [
'SharedWorker.cpp',
'SharedWorkerChild.cpp',
'SharedWorkerParent.cpp',
]
IPDL_SOURCES += [
'PSharedWorker.ipdl',
'SharedWorkerTypes.ipdlh',
]
include('/ipc/chromium/chromium-config.mozbuild')

View File

@ -27,6 +27,7 @@
#include "mozilla/dom/ipc/PendingIPCBlobChild.h"
#include "mozilla/dom/ipc/TemporaryIPCBlobChild.h"
#include "mozilla/dom/quota/PQuotaChild.h"
#include "mozilla/dom/SharedWorkerChild.h"
#include "mozilla/dom/StorageIPC.h"
#include "mozilla/dom/GamepadEventChannelChild.h"
#include "mozilla/dom/GamepadTestChannelChild.h"
@ -288,6 +289,21 @@ BackgroundChildImpl::DeallocPPendingIPCBlobChild(PPendingIPCBlobChild* aActor)
return true;
}
dom::PSharedWorkerChild*
BackgroundChildImpl::AllocPSharedWorkerChild(const dom::SharedWorkerLoadInfo& aInfo)
{
RefPtr<dom::SharedWorkerChild> agent = new dom::SharedWorkerChild();
return agent.forget().take();
}
bool
BackgroundChildImpl::DeallocPSharedWorkerChild(dom::PSharedWorkerChild* aActor)
{
RefPtr<dom::SharedWorkerChild> actor =
dont_AddRef(static_cast<dom::SharedWorkerChild*>(aActor));
return true;
}
PTemporaryIPCBlobChild*
BackgroundChildImpl::AllocPTemporaryIPCBlobChild()
{

View File

@ -114,6 +114,12 @@ protected:
virtual bool
DeallocPTemporaryIPCBlobChild(PTemporaryIPCBlobChild* aActor) override;
virtual mozilla::dom::PSharedWorkerChild*
AllocPSharedWorkerChild(const mozilla::dom::SharedWorkerLoadInfo& aInfo) override;
virtual bool
DeallocPSharedWorkerChild(mozilla::dom::PSharedWorkerChild* aActor) override;
virtual PFileDescriptorSetChild*
AllocPFileDescriptorSetChild(const FileDescriptor& aFileDescriptor)
override;

View File

@ -35,6 +35,7 @@
#include "mozilla/dom/ipc/TemporaryIPCBlobParent.h"
#include "mozilla/dom/quota/ActorsParent.h"
#include "mozilla/dom/simpledb/ActorsParent.h"
#include "mozilla/dom/SharedWorkerParent.h"
#include "mozilla/dom/StorageIPC.h"
#include "mozilla/dom/MIDIManagerParent.h"
#include "mozilla/dom/MIDIPortParent.h"
@ -386,6 +387,22 @@ BackgroundParentImpl::DeallocPPendingIPCBlobParent(PPendingIPCBlobParent* aActor
return true;
}
mozilla::dom::PSharedWorkerParent*
BackgroundParentImpl::AllocPSharedWorkerParent(const mozilla::dom::SharedWorkerLoadInfo& aInfo)
{
RefPtr<dom::SharedWorkerParent> agent =
new mozilla::dom::SharedWorkerParent();
return agent.forget().take();
}
bool
BackgroundParentImpl::DeallocPSharedWorkerParent(mozilla::dom::PSharedWorkerParent* aActor)
{
RefPtr<mozilla::dom::SharedWorkerParent> actor =
dont_AddRef(static_cast<mozilla::dom::SharedWorkerParent*>(aActor));
return true;
}
PTemporaryIPCBlobParent*
BackgroundParentImpl::AllocPTemporaryIPCBlobParent()
{

View File

@ -133,6 +133,12 @@ protected:
virtual bool
DeallocPTemporaryIPCBlobParent(PTemporaryIPCBlobParent* aActor) override;
virtual mozilla::dom::PSharedWorkerParent*
AllocPSharedWorkerParent(const mozilla::dom::SharedWorkerLoadInfo& aInfo) override;
virtual bool
DeallocPSharedWorkerParent(PSharedWorkerParent* aActor) override;
virtual PFileDescriptorSetParent*
AllocPFileDescriptorSetParent(const FileDescriptor& aFileDescriptor)
override;

View File

@ -21,6 +21,7 @@ include protocol PGamepadTestChannel;
include protocol PHttpBackgroundChannel;
include protocol PIPCBlobInputStream;
include protocol PPendingIPCBlob;
include protocol PSharedWorker;
include protocol PTemporaryIPCBlob;
include protocol PMessagePort;
include protocol PCameras;
@ -45,6 +46,7 @@ include PBackgroundSharedTypes;
include PBackgroundIDBSharedTypes;
include PFileSystemParams;
include ProtocolTypes;
include SharedWorkerTypes;
include MIDITypes;
include "mozilla/dom/cache/IPCUtils.h";
@ -83,6 +85,7 @@ sync protocol PBackground
manages PHttpBackgroundChannel;
manages PIPCBlobInputStream;
manages PPendingIPCBlob;
manages PSharedWorker;
manages PTemporaryIPCBlob;
manages PMessagePort;
manages PCameras;
@ -153,6 +156,8 @@ parent:
async PWebAuthnTransaction();
async PSharedWorker(SharedWorkerLoadInfo loadInfo);
async PTemporaryIPCBlob();
async PClientManager();