зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1536411 - StoragePrincipal - part 2 - Worker and StoragePrincipal, r=Ehsan
Differential Revision: https://phabricator.services.mozilla.com/D24026 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
a438b12ebd
Коммит
79ac7cee82
|
@ -1751,7 +1751,8 @@ nsresult ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
|
|||
|
||||
WorkerPrivate::OverrideLoadInfoLoadGroup(info, info.mPrincipal);
|
||||
|
||||
rv = info.SetPrincipalOnMainThread(info.mPrincipal, info.mLoadGroup);
|
||||
rv = info.SetPrincipalsOnMainThread(info.mPrincipal, info.mStoragePrincipal,
|
||||
info.mLoadGroup);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -1188,7 +1188,7 @@ class ScriptLoaderRunnable final : public nsIRunnable, public nsINamed {
|
|||
// URL must exactly match the final worker script URL in order to
|
||||
// properly set the referrer header on fetch/xhr requests. If bug 1340694
|
||||
// is ever fixed this can be removed.
|
||||
rv = mWorkerPrivate->SetPrincipalFromChannel(channel);
|
||||
rv = mWorkerPrivate->SetPrincipalsFromChannel(channel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = mWorkerPrivate->GetCSP();
|
||||
|
@ -1296,8 +1296,9 @@ class ScriptLoaderRunnable final : public nsIRunnable, public nsINamed {
|
|||
// referrer logic depends on the WorkerPrivate principal having a URL
|
||||
// that matches the worker script URL. If bug 1340694 is ever fixed
|
||||
// this can be removed.
|
||||
rv = mWorkerPrivate->SetPrincipalOnMainThread(responsePrincipal,
|
||||
loadGroup);
|
||||
// TODO: storagePrincipal here?
|
||||
rv = mWorkerPrivate->SetPrincipalsOnMainThread(
|
||||
responsePrincipal, responsePrincipal, loadGroup);
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
rv = mWorkerPrivate->SetCSPFromHeaderValues(aCSPHeaderValue,
|
||||
|
@ -1841,7 +1842,7 @@ class ChannelGetterRunnable final : public WorkerMainThreadRunnable {
|
|||
getter_AddRefs(channel));
|
||||
NS_ENSURE_SUCCESS(mResult, true);
|
||||
|
||||
mResult = mLoadInfo.SetPrincipalFromChannel(channel);
|
||||
mResult = mLoadInfo.SetPrincipalsFromChannel(channel);
|
||||
NS_ENSURE_SUCCESS(mResult, true);
|
||||
|
||||
mLoadInfo.mChannel = channel.forget();
|
||||
|
|
|
@ -92,12 +92,14 @@ WorkerLoadInfoData::WorkerLoadInfoData()
|
|||
mServiceWorkersTestingInWindow(false),
|
||||
mSecureContext(eNotSet) {}
|
||||
|
||||
nsresult WorkerLoadInfo::SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
|
||||
nsILoadGroup* aLoadGroup) {
|
||||
nsresult WorkerLoadInfo::SetPrincipalsOnMainThread(
|
||||
nsIPrincipal* aPrincipal, nsIPrincipal* aStoragePrincipal,
|
||||
nsILoadGroup* aLoadGroup) {
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(aLoadGroup, aPrincipal));
|
||||
|
||||
mPrincipal = aPrincipal;
|
||||
mStoragePrincipal = aStoragePrincipal;
|
||||
mPrincipalIsSystem = nsContentUtils::IsSystemPrincipal(aPrincipal);
|
||||
|
||||
nsresult rv = aPrincipal->GetCsp(getter_AddRefs(mCSP));
|
||||
|
@ -113,23 +115,33 @@ nsresult WorkerLoadInfo::SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
|
|||
mLoadGroup = aLoadGroup;
|
||||
|
||||
mPrincipalInfo = new PrincipalInfo();
|
||||
mStoragePrincipalInfo = new PrincipalInfo();
|
||||
mOriginAttributes = nsContentUtils::GetOriginAttributes(aLoadGroup);
|
||||
|
||||
rv = PrincipalToPrincipalInfo(aPrincipal, mPrincipalInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aPrincipal->Equals(aStoragePrincipal)) {
|
||||
*mStoragePrincipalInfo = *mPrincipalInfo;
|
||||
} else {
|
||||
mStoragePrincipalInfo = new PrincipalInfo();
|
||||
rv = PrincipalToPrincipalInfo(aStoragePrincipal, mStoragePrincipalInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = nsContentUtils::GetUTFOrigin(aPrincipal, mOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(
|
||||
nsresult WorkerLoadInfo::GetPrincipalsAndLoadGroupFromChannel(
|
||||
nsIChannel* aChannel, nsIPrincipal** aPrincipalOut,
|
||||
nsILoadGroup** aLoadGroupOut) {
|
||||
nsIPrincipal** aStoragePrincipalOut, nsILoadGroup** aLoadGroupOut) {
|
||||
AssertIsOnMainThread();
|
||||
MOZ_DIAGNOSTIC_ASSERT(aChannel);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aPrincipalOut);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aStoragePrincipalOut);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aLoadGroupOut);
|
||||
|
||||
// Initial triggering principal should be set
|
||||
|
@ -143,6 +155,11 @@ nsresult WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(
|
|||
aChannel, getter_AddRefs(channelPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> channelStoragePrincipal;
|
||||
rv = ssm->GetChannelResultStoragePrincipal(
|
||||
aChannel, getter_AddRefs(channelStoragePrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Every time we call GetChannelResultPrincipal() it will return a different
|
||||
// null principal for a data URL. We don't want to change the worker's
|
||||
// principal again, though. Instead just keep the original null principal we
|
||||
|
@ -154,6 +171,7 @@ nsresult WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(
|
|||
if (mPrincipal && mPrincipal->GetIsNullPrincipal() &&
|
||||
channelPrincipal->GetIsNullPrincipal()) {
|
||||
channelPrincipal = mPrincipal;
|
||||
channelStoragePrincipal = mPrincipal;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadGroup> channelLoadGroup;
|
||||
|
@ -186,6 +204,7 @@ nsresult WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(
|
|||
// Assign the system principal to the resource:// worker only if it
|
||||
// was loaded from code using the system principal.
|
||||
channelPrincipal = mLoadingPrincipal;
|
||||
channelStoragePrincipal = mLoadingPrincipal;
|
||||
} else {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
@ -197,30 +216,35 @@ nsresult WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(
|
|||
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(channelLoadGroup, channelPrincipal));
|
||||
|
||||
channelPrincipal.forget(aPrincipalOut);
|
||||
channelStoragePrincipal.forget(aStoragePrincipalOut);
|
||||
channelLoadGroup.forget(aLoadGroupOut);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult WorkerLoadInfo::SetPrincipalFromChannel(nsIChannel* aChannel) {
|
||||
nsresult WorkerLoadInfo::SetPrincipalsFromChannel(nsIChannel* aChannel) {
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsCOMPtr<nsIPrincipal> storagePrincipal;
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
nsresult rv = GetPrincipalAndLoadGroupFromChannel(
|
||||
aChannel, getter_AddRefs(principal), getter_AddRefs(loadGroup));
|
||||
nsresult rv = GetPrincipalsAndLoadGroupFromChannel(
|
||||
aChannel, getter_AddRefs(principal), getter_AddRefs(storagePrincipal),
|
||||
getter_AddRefs(loadGroup));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return SetPrincipalOnMainThread(principal, loadGroup);
|
||||
return SetPrincipalsOnMainThread(principal, storagePrincipal, loadGroup);
|
||||
}
|
||||
|
||||
bool WorkerLoadInfo::FinalChannelPrincipalIsValid(nsIChannel* aChannel) {
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsCOMPtr<nsIPrincipal> storagePrincipal;
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
nsresult rv = GetPrincipalAndLoadGroupFromChannel(
|
||||
aChannel, getter_AddRefs(principal), getter_AddRefs(loadGroup));
|
||||
nsresult rv = GetPrincipalsAndLoadGroupFromChannel(
|
||||
aChannel, getter_AddRefs(principal), getter_AddRefs(storagePrincipal),
|
||||
getter_AddRefs(loadGroup));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
// Verify that the channel is still a null principal. We don't care
|
||||
|
@ -243,7 +267,10 @@ bool WorkerLoadInfo::FinalChannelPrincipalIsValid(nsIChannel* aChannel) {
|
|||
bool WorkerLoadInfo::PrincipalIsValid() const {
|
||||
return mPrincipal && mPrincipalInfo &&
|
||||
mPrincipalInfo->type() != PrincipalInfo::T__None &&
|
||||
mPrincipalInfo->type() <= PrincipalInfo::T__Last;
|
||||
mPrincipalInfo->type() <= PrincipalInfo::T__Last &&
|
||||
mStoragePrincipal && mStoragePrincipalInfo &&
|
||||
mStoragePrincipalInfo->type() != PrincipalInfo::T__None &&
|
||||
mStoragePrincipalInfo->type() <= PrincipalInfo::T__Last;
|
||||
}
|
||||
|
||||
bool WorkerLoadInfo::PrincipalURIMatchesScriptURL() {
|
||||
|
@ -312,7 +339,7 @@ bool WorkerLoadInfo::ProxyReleaseMainThreadObjects(
|
|||
|
||||
bool WorkerLoadInfo::ProxyReleaseMainThreadObjects(
|
||||
WorkerPrivate* aWorkerPrivate, nsCOMPtr<nsILoadGroup>& aLoadGroupToCancel) {
|
||||
static const uint32_t kDoomedCount = 10;
|
||||
static const uint32_t kDoomedCount = 11;
|
||||
nsTArray<nsCOMPtr<nsISupports>> doomed(kDoomedCount);
|
||||
|
||||
SwapToISupportsArray(mWindow, doomed);
|
||||
|
@ -320,6 +347,7 @@ bool WorkerLoadInfo::ProxyReleaseMainThreadObjects(
|
|||
SwapToISupportsArray(mBaseURI, doomed);
|
||||
SwapToISupportsArray(mResolvedScriptURI, doomed);
|
||||
SwapToISupportsArray(mPrincipal, doomed);
|
||||
SwapToISupportsArray(mStoragePrincipal, doomed);
|
||||
SwapToISupportsArray(mLoadingPrincipal, doomed);
|
||||
SwapToISupportsArray(mChannel, doomed);
|
||||
SwapToISupportsArray(mCSP, doomed);
|
||||
|
|
|
@ -50,6 +50,7 @@ struct WorkerLoadInfoData {
|
|||
// If we load a data: URL, mPrincipal will be a null principal.
|
||||
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIPrincipal> mStoragePrincipal;
|
||||
|
||||
// Taken from the parent context.
|
||||
nsCOMPtr<nsICookieSettings> mCookieSettings;
|
||||
|
@ -91,6 +92,7 @@ struct WorkerLoadInfoData {
|
|||
RefPtr<InterfaceRequestor> mInterfaceRequestor;
|
||||
|
||||
nsAutoPtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
|
||||
nsAutoPtr<mozilla::ipc::PrincipalInfo> mStoragePrincipalInfo;
|
||||
nsCString mDomain;
|
||||
nsString mOrigin; // Derived from mPrincipal; can be used on worker thread.
|
||||
|
||||
|
@ -136,14 +138,15 @@ struct WorkerLoadInfo : WorkerLoadInfoData {
|
|||
|
||||
WorkerLoadInfo& operator=(WorkerLoadInfo&& aOther) = default;
|
||||
|
||||
nsresult SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
|
||||
nsILoadGroup* aLoadGroup);
|
||||
nsresult SetPrincipalsOnMainThread(nsIPrincipal* aPrincipal,
|
||||
nsIPrincipal* aStoragePrincipal,
|
||||
nsILoadGroup* aLoadGroup);
|
||||
|
||||
nsresult GetPrincipalAndLoadGroupFromChannel(nsIChannel* aChannel,
|
||||
nsIPrincipal** aPrincipalOut,
|
||||
nsILoadGroup** aLoadGroupOut);
|
||||
nsresult GetPrincipalsAndLoadGroupFromChannel(
|
||||
nsIChannel* aChannel, nsIPrincipal** aPrincipalOut,
|
||||
nsIPrincipal** aStoragePrincipalOut, nsILoadGroup** aLoadGroupOut);
|
||||
|
||||
nsresult SetPrincipalFromChannel(nsIChannel* aChannel);
|
||||
nsresult SetPrincipalsFromChannel(nsIChannel* aChannel);
|
||||
|
||||
bool FinalChannelPrincipalIsValid(nsIChannel* aChannel);
|
||||
|
||||
|
|
|
@ -1932,13 +1932,15 @@ void WorkerPrivate::SetBaseURI(nsIURI* aBaseURI) {
|
|||
nsContentUtils::GetUTFOrigin(aBaseURI, mLocationInfo.mOrigin);
|
||||
}
|
||||
|
||||
nsresult WorkerPrivate::SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
|
||||
nsILoadGroup* aLoadGroup) {
|
||||
return mLoadInfo.SetPrincipalOnMainThread(aPrincipal, aLoadGroup);
|
||||
nsresult WorkerPrivate::SetPrincipalsOnMainThread(
|
||||
nsIPrincipal* aPrincipal, nsIPrincipal* aStoragePrincipal,
|
||||
nsILoadGroup* aLoadGroup) {
|
||||
return mLoadInfo.SetPrincipalsOnMainThread(aPrincipal, aStoragePrincipal,
|
||||
aLoadGroup);
|
||||
}
|
||||
|
||||
nsresult WorkerPrivate::SetPrincipalFromChannel(nsIChannel* aChannel) {
|
||||
return mLoadInfo.SetPrincipalFromChannel(aChannel);
|
||||
nsresult WorkerPrivate::SetPrincipalsFromChannel(nsIChannel* aChannel) {
|
||||
return mLoadInfo.SetPrincipalsFromChannel(aChannel);
|
||||
}
|
||||
|
||||
bool WorkerPrivate::FinalChannelPrincipalIsValid(nsIChannel* aChannel) {
|
||||
|
@ -2562,7 +2564,7 @@ nsresult WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindowInner* aWindow,
|
|||
getter_AddRefs(loadInfo.mResolvedScriptURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = loadInfo.SetPrincipalFromChannel(loadInfo.mChannel);
|
||||
rv = loadInfo.SetPrincipalsFromChannel(loadInfo.mChannel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -662,6 +662,11 @@ class WorkerPrivate : public RelativeTimeline {
|
|||
return mLoadInfo.mPrincipal;
|
||||
}
|
||||
|
||||
nsIPrincipal* GetEffectiveStoragePrincipal() const {
|
||||
AssertIsOnMainThread();
|
||||
return mLoadInfo.mStoragePrincipal;
|
||||
}
|
||||
|
||||
nsIPrincipal* GetLoadingPrincipal() const {
|
||||
AssertIsOnMainThread();
|
||||
return mLoadInfo.mLoadingPrincipal;
|
||||
|
@ -680,6 +685,10 @@ class WorkerPrivate : public RelativeTimeline {
|
|||
return *mLoadInfo.mPrincipalInfo;
|
||||
}
|
||||
|
||||
const mozilla::ipc::PrincipalInfo& GetEffectiveStoragePrincipalInfo() const {
|
||||
return *mLoadInfo.mStoragePrincipalInfo;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIChannel> ForgetWorkerChannel() {
|
||||
AssertIsOnMainThread();
|
||||
return mLoadInfo.mChannel.forget();
|
||||
|
@ -788,10 +797,11 @@ class WorkerPrivate : public RelativeTimeline {
|
|||
|
||||
void CycleCollect(bool aDummy);
|
||||
|
||||
nsresult SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
|
||||
nsILoadGroup* aLoadGroup);
|
||||
nsresult SetPrincipalsOnMainThread(nsIPrincipal* aPrincipal,
|
||||
nsIPrincipal* aStoragePrincipal,
|
||||
nsILoadGroup* aLoadGroup);
|
||||
|
||||
nsresult SetPrincipalFromChannel(nsIChannel* aChannel);
|
||||
nsresult SetPrincipalsFromChannel(nsIChannel* aChannel);
|
||||
|
||||
bool FinalChannelPrincipalIsValid(nsIChannel* aChannel);
|
||||
|
||||
|
|
|
@ -262,14 +262,29 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> storagePrincipal =
|
||||
PrincipalInfoToPrincipal(aData.storagePrincipalInfo(), &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = PopulatePrincipalContentSecurityPolicy(
|
||||
storagePrincipal, aData.storagePrincipalCsp(),
|
||||
aData.storagePrincipalPreloadCsp());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
WorkerLoadInfo info;
|
||||
info.mBaseURI = DeserializeURI(aData.baseScriptURL());
|
||||
info.mResolvedScriptURI = DeserializeURI(aData.resolvedScriptURL());
|
||||
|
||||
info.mPrincipalInfo = new PrincipalInfo(aData.principalInfo());
|
||||
info.mStoragePrincipalInfo = new PrincipalInfo(aData.storagePrincipalInfo());
|
||||
|
||||
info.mDomain = aData.domain();
|
||||
info.mPrincipal = principal;
|
||||
info.mStoragePrincipal = storagePrincipal;
|
||||
info.mLoadingPrincipal = loadingPrincipal;
|
||||
info.mStorageAccess = aData.storageAccess();
|
||||
info.mOriginAttributes =
|
||||
|
@ -290,7 +305,8 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(
|
|||
new SharedWorkerInterfaceRequestor();
|
||||
info.mInterfaceRequestor->SetOuterRequestor(requestor);
|
||||
|
||||
rv = info.SetPrincipalOnMainThread(info.mPrincipal, info.mLoadGroup);
|
||||
rv = info.SetPrincipalsOnMainThread(info.mPrincipal, info.mStoragePrincipal,
|
||||
info.mLoadGroup);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,10 @@ struct RemoteWorkerData
|
|||
ContentSecurityPolicy[] principalCsp;
|
||||
ContentSecurityPolicy[] principalPreloadCsp;
|
||||
|
||||
PrincipalInfo storagePrincipalInfo;
|
||||
ContentSecurityPolicy[] storagePrincipalCsp;
|
||||
ContentSecurityPolicy[] storagePrincipalPreloadCsp;
|
||||
|
||||
nsCString domain;
|
||||
|
||||
bool isSecureContext;
|
||||
|
|
|
@ -176,6 +176,26 @@ already_AddRefed<SharedWorker> SharedWorker::Constructor(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
PrincipalInfo storagePrincipalInfo;
|
||||
if (loadInfo.mPrincipal->Equals(loadInfo.mStoragePrincipal)) {
|
||||
storagePrincipalInfo = principalInfo;
|
||||
} else {
|
||||
aRv = PrincipalToPrincipalInfo(loadInfo.mStoragePrincipal,
|
||||
&storagePrincipalInfo);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<ContentSecurityPolicy> storagePrincipalCSP;
|
||||
nsTArray<ContentSecurityPolicy> storagePrincipalPreloadCSP;
|
||||
aRv = PopulateContentSecurityPolicyArray(loadInfo.mStoragePrincipal,
|
||||
storagePrincipalCSP,
|
||||
storagePrincipalPreloadCSP);
|
||||
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);
|
||||
|
@ -207,7 +227,8 @@ already_AddRefed<SharedWorker> SharedWorker::Constructor(
|
|||
RemoteWorkerData remoteWorkerData(
|
||||
nsString(aScriptURL), baseURL, resolvedScriptURL, name,
|
||||
loadingPrincipalInfo, loadingPrincipalCSP, loadingPrincipalPreloadCSP,
|
||||
principalInfo, principalCSP, principalPreloadCSP, loadInfo.mDomain,
|
||||
principalInfo, principalCSP, principalPreloadCSP, storagePrincipalInfo,
|
||||
storagePrincipalCSP, storagePrincipalPreloadCSP, loadInfo.mDomain,
|
||||
isSecureContext, ipcClientInfo, storageAllowed, true /* sharedWorker */);
|
||||
|
||||
PSharedWorkerChild* pActor = actorChild->SendPSharedWorkerConstructor(
|
||||
|
|
Загрузка…
Ссылка в новой задаче