|
@@ -0,0 +1,1688 @@
|
|
|
+# HG changeset patch
|
|
|
+# User Andrea Marchesini <amarchesini@mozilla.com>
|
|
|
+# Date 1517303524 -3600
|
|
|
+# Node ID f891bdb45bc7100b46d664a7055da0b3467f3540
|
|
|
+# Parent 41f034c05ddace7b63bd58f302e71a88a2196233
|
|
|
+Bug 1413112 - Move WorkerLoadInfo into separate files, r=bkelly
|
|
|
+
|
|
|
+diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp
|
|
|
+--- a/dom/workers/RuntimeService.cpp
|
|
|
++++ b/dom/workers/RuntimeService.cpp
|
|
|
+@@ -64,16 +64,17 @@
|
|
|
+ #include "nsXPCOM.h"
|
|
|
+ #include "nsXPCOMPrivate.h"
|
|
|
+ #include "OSFileConstants.h"
|
|
|
+ #include "xpcpublic.h"
|
|
|
+
|
|
|
+ #include "Principal.h"
|
|
|
+ #include "SharedWorker.h"
|
|
|
+ #include "WorkerDebuggerManager.h"
|
|
|
++#include "WorkerLoadInfo.h"
|
|
|
+ #include "WorkerPrivate.h"
|
|
|
+ #include "WorkerRunnable.h"
|
|
|
+ #include "WorkerScope.h"
|
|
|
+ #include "WorkerThread.h"
|
|
|
+ #include "prsystem.h"
|
|
|
+
|
|
|
+ using namespace mozilla;
|
|
|
+ using namespace mozilla::dom;
|
|
|
+diff --git a/dom/workers/RuntimeService.h b/dom/workers/RuntimeService.h
|
|
|
+--- a/dom/workers/RuntimeService.h
|
|
|
++++ b/dom/workers/RuntimeService.h
|
|
|
+@@ -17,16 +17,17 @@
|
|
|
+ #include "nsTArray.h"
|
|
|
+
|
|
|
+ class nsITimer;
|
|
|
+ class nsPIDOMWindowInner;
|
|
|
+
|
|
|
+ BEGIN_WORKERS_NAMESPACE
|
|
|
+
|
|
|
+ class SharedWorker;
|
|
|
++struct WorkerLoadInfo;
|
|
|
+ class WorkerThread;
|
|
|
+
|
|
|
+ class RuntimeService final : public nsIObserver
|
|
|
+ {
|
|
|
+ struct SharedWorkerInfo
|
|
|
+ {
|
|
|
+ WorkerPrivate* mWorkerPrivate;
|
|
|
+ nsCString mScriptSpec;
|
|
|
+diff --git a/dom/workers/WorkerCommon.h b/dom/workers/WorkerCommon.h
|
|
|
+--- a/dom/workers/WorkerCommon.h
|
|
|
++++ b/dom/workers/WorkerCommon.h
|
|
|
+@@ -15,47 +15,35 @@
|
|
|
+ #include "nsAutoPtr.h"
|
|
|
+ #include "nsCOMPtr.h"
|
|
|
+ #include "nsDebug.h"
|
|
|
+ #include "nsString.h"
|
|
|
+ #include "nsTArray.h"
|
|
|
+
|
|
|
+ #include "nsILoadContext.h"
|
|
|
+ #include "nsIWeakReferenceUtils.h"
|
|
|
+-#include "nsIInterfaceRequestor.h"
|
|
|
+ #include "mozilla/dom/ChannelInfo.h"
|
|
|
+ #include "mozilla/dom/ServiceWorkerDescriptor.h"
|
|
|
+ #include "mozilla/net/ReferrerPolicy.h"
|
|
|
+
|
|
|
+ #define BEGIN_WORKERS_NAMESPACE \
|
|
|
+ namespace mozilla { namespace dom { namespace workers {
|
|
|
+ #define END_WORKERS_NAMESPACE \
|
|
|
+ } /* namespace workers */ } /* namespace dom */ } /* namespace mozilla */
|
|
|
+ #define USING_WORKERS_NAMESPACE \
|
|
|
+ using namespace mozilla::dom::workers;
|
|
|
+
|
|
|
+ #define WORKERS_SHUTDOWN_TOPIC "web-workers-shutdown"
|
|
|
+
|
|
|
+-class nsIContentSecurityPolicy;
|
|
|
+-class nsIScriptContext;
|
|
|
+ class nsIGlobalObject;
|
|
|
+ class nsPIDOMWindowInner;
|
|
|
+-class nsIPrincipal;
|
|
|
+-class nsILoadGroup;
|
|
|
+-class nsITabChild;
|
|
|
+-class nsIChannel;
|
|
|
+-class nsIRunnable;
|
|
|
+-class nsIURI;
|
|
|
+
|
|
|
+ namespace mozilla {
|
|
|
+-namespace ipc {
|
|
|
+-class PrincipalInfo;
|
|
|
+-} // namespace ipc
|
|
|
++namespace dom {
|
|
|
+
|
|
|
+-namespace dom {
|
|
|
+ // If you change this, the corresponding list in nsIWorkerDebugger.idl needs to
|
|
|
+ // be updated too.
|
|
|
+ enum WorkerType
|
|
|
+ {
|
|
|
+ WorkerTypeDedicated,
|
|
|
+ WorkerTypeShared,
|
|
|
+ WorkerTypeService
|
|
|
+ };
|
|
|
+@@ -181,127 +169,16 @@ struct JSSettings
|
|
|
+ foundSetting->key.reset();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+-// Implemented in WorkerPrivate.cpp
|
|
|
+-
|
|
|
+-struct WorkerLoadInfo
|
|
|
+-{
|
|
|
+- // All of these should be released in WorkerPrivateParent::ForgetMainThreadObjects.
|
|
|
+- nsCOMPtr<nsIURI> mBaseURI;
|
|
|
+- nsCOMPtr<nsIURI> mResolvedScriptURI;
|
|
|
+-
|
|
|
+- // This is the principal of the global (parent worker or a window) loading
|
|
|
+- // the worker. It can be null if we are executing a ServiceWorker, otherwise,
|
|
|
+- // except for data: URL, it must subsumes the worker principal.
|
|
|
+- // If we load a data: URL, mPrincipal will be a null principal.
|
|
|
+- nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
|
|
|
+- nsCOMPtr<nsIPrincipal> mPrincipal;
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIScriptContext> mScriptContext;
|
|
|
+- nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
|
|
+- nsCOMPtr<nsIContentSecurityPolicy> mCSP;
|
|
|
+- nsCOMPtr<nsIChannel> mChannel;
|
|
|
+- nsCOMPtr<nsILoadGroup> mLoadGroup;
|
|
|
+-
|
|
|
+- // mLoadFailedAsyncRunnable will execute on main thread if script loading
|
|
|
+- // fails during script loading. If script loading is never started due to
|
|
|
+- // a synchronous error, then the runnable is never executed. The runnable
|
|
|
+- // is guaranteed to be released on the main thread.
|
|
|
+- nsCOMPtr<nsIRunnable> mLoadFailedAsyncRunnable;
|
|
|
+-
|
|
|
+- class InterfaceRequestor final : public nsIInterfaceRequestor
|
|
|
+- {
|
|
|
+- NS_DECL_ISUPPORTS
|
|
|
+-
|
|
|
+- public:
|
|
|
+- InterfaceRequestor(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
|
|
|
+- void MaybeAddTabChild(nsILoadGroup* aLoadGroup);
|
|
|
+- NS_IMETHOD GetInterface(const nsIID& aIID, void** aSink) override;
|
|
|
+-
|
|
|
+- private:
|
|
|
+- ~InterfaceRequestor() { }
|
|
|
+-
|
|
|
+- already_AddRefed<nsITabChild> GetAnyLiveTabChild();
|
|
|
+-
|
|
|
+- nsCOMPtr<nsILoadContext> mLoadContext;
|
|
|
+- nsCOMPtr<nsIInterfaceRequestor> mOuterRequestor;
|
|
|
+-
|
|
|
+- // Array of weak references to nsITabChild. We do not want to keep TabChild
|
|
|
+- // actors alive for long after their ActorDestroy() methods are called.
|
|
|
+- nsTArray<nsWeakPtr> mTabChildList;
|
|
|
+- };
|
|
|
+-
|
|
|
+- // Only set if we have a custom overriden load group
|
|
|
+- RefPtr<InterfaceRequestor> mInterfaceRequestor;
|
|
|
+-
|
|
|
+- nsAutoPtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
|
|
|
+- nsCString mDomain;
|
|
|
+- nsString mOrigin; // Derived from mPrincipal; can be used on worker thread.
|
|
|
+-
|
|
|
+- nsString mServiceWorkerCacheName;
|
|
|
+- Maybe<ServiceWorkerDescriptor> mServiceWorkerDescriptor;
|
|
|
+-
|
|
|
+- Maybe<ServiceWorkerDescriptor> mParentController;
|
|
|
+-
|
|
|
+- ChannelInfo mChannelInfo;
|
|
|
+- nsLoadFlags mLoadFlags;
|
|
|
+-
|
|
|
+- uint64_t mWindowID;
|
|
|
+-
|
|
|
+- net::ReferrerPolicy mReferrerPolicy;
|
|
|
+- bool mFromWindow;
|
|
|
+- bool mEvalAllowed;
|
|
|
+- bool mReportCSPViolations;
|
|
|
+- bool mXHRParamsAllowed;
|
|
|
+- bool mPrincipalIsSystem;
|
|
|
+- bool mStorageAllowed;
|
|
|
+- bool mServiceWorkersTestingInWindow;
|
|
|
+- OriginAttributes mOriginAttributes;
|
|
|
+-
|
|
|
+- WorkerLoadInfo();
|
|
|
+- ~WorkerLoadInfo();
|
|
|
+-
|
|
|
+- void StealFrom(WorkerLoadInfo& aOther);
|
|
|
+-
|
|
|
+- nsresult
|
|
|
+- SetPrincipalOnMainThread(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
|
|
|
+-
|
|
|
+- nsresult
|
|
|
+- GetPrincipalAndLoadGroupFromChannel(nsIChannel* aChannel,
|
|
|
+- nsIPrincipal** aPrincipalOut,
|
|
|
+- nsILoadGroup** aLoadGroupOut);
|
|
|
+-
|
|
|
+- nsresult
|
|
|
+- SetPrincipalFromChannel(nsIChannel* aChannel);
|
|
|
+-
|
|
|
+- bool
|
|
|
+- FinalChannelPrincipalIsValid(nsIChannel* aChannel);
|
|
|
+-
|
|
|
+-#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
|
|
+- bool
|
|
|
+- PrincipalIsValid() const;
|
|
|
+-
|
|
|
+- bool
|
|
|
+- PrincipalURIMatchesScriptURL();
|
|
|
+-#endif
|
|
|
+-
|
|
|
+- bool
|
|
|
+- ProxyReleaseMainThreadObjects(WorkerPrivate* aWorkerPrivate);
|
|
|
+-
|
|
|
+- bool
|
|
|
+- ProxyReleaseMainThreadObjects(WorkerPrivate* aWorkerPrivate,
|
|
|
+- nsCOMPtr<nsILoadGroup>& aLoadGroupToCancel);
|
|
|
+-};
|
|
|
+-
|
|
|
+ // All of these are implemented in RuntimeService.cpp
|
|
|
+
|
|
|
+ void
|
|
|
+ CancelWorkersForWindow(nsPIDOMWindowInner* aWindow);
|
|
|
+
|
|
|
+ void
|
|
|
+ FreezeWorkersForWindow(nsPIDOMWindowInner* aWindow);
|
|
|
+
|
|
|
+diff --git a/dom/workers/WorkerLoadInfo.cpp b/dom/workers/WorkerLoadInfo.cpp
|
|
|
+new file mode 100644
|
|
|
+--- /dev/null
|
|
|
++++ b/dom/workers/WorkerLoadInfo.cpp
|
|
|
+@@ -0,0 +1,547 @@
|
|
|
++/* -*- 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 "WorkerLoadInfo.h"
|
|
|
++#include "WorkerPrivate.h"
|
|
|
++
|
|
|
++#include "mozilla/dom/TabChild.h"
|
|
|
++#include "mozilla/ipc/BackgroundUtils.h"
|
|
|
++#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
|
|
++#include "mozilla/LoadContext.h"
|
|
|
++#include "nsContentUtils.h"
|
|
|
++#include "nsIContentSecurityPolicy.h"
|
|
|
++#include "nsINetworkInterceptController.h"
|
|
|
++#include "nsIProtocolHandler.h"
|
|
|
++#include "nsITabChild.h"
|
|
|
++#include "nsNetUtil.h"
|
|
|
++
|
|
|
++namespace mozilla {
|
|
|
++
|
|
|
++using namespace ipc;
|
|
|
++
|
|
|
++namespace dom {
|
|
|
++namespace workers {
|
|
|
++
|
|
|
++namespace {
|
|
|
++
|
|
|
++class MainThreadReleaseRunnable final : public Runnable
|
|
|
++{
|
|
|
++ nsTArray<nsCOMPtr<nsISupports>> mDoomed;
|
|
|
++ nsCOMPtr<nsILoadGroup> mLoadGroupToCancel;
|
|
|
++
|
|
|
++public:
|
|
|
++ MainThreadReleaseRunnable(nsTArray<nsCOMPtr<nsISupports>>& aDoomed,
|
|
|
++ nsCOMPtr<nsILoadGroup>& aLoadGroupToCancel)
|
|
|
++ : mozilla::Runnable("MainThreadReleaseRunnable")
|
|
|
++ {
|
|
|
++ mDoomed.SwapElements(aDoomed);
|
|
|
++ mLoadGroupToCancel.swap(aLoadGroupToCancel);
|
|
|
++ }
|
|
|
++
|
|
|
++ NS_DECL_ISUPPORTS_INHERITED
|
|
|
++
|
|
|
++ NS_IMETHOD
|
|
|
++ Run() override
|
|
|
++ {
|
|
|
++ if (mLoadGroupToCancel) {
|
|
|
++ mLoadGroupToCancel->Cancel(NS_BINDING_ABORTED);
|
|
|
++ mLoadGroupToCancel = nullptr;
|
|
|
++ }
|
|
|
++
|
|
|
++ mDoomed.Clear();
|
|
|
++ return NS_OK;
|
|
|
++ }
|
|
|
++
|
|
|
++private:
|
|
|
++ ~MainThreadReleaseRunnable()
|
|
|
++ { }
|
|
|
++};
|
|
|
++
|
|
|
++// Specialize this if there's some class that has multiple nsISupports bases.
|
|
|
++template <class T>
|
|
|
++struct ISupportsBaseInfo
|
|
|
++{
|
|
|
++ typedef T ISupportsBase;
|
|
|
++};
|
|
|
++
|
|
|
++template <template <class> class SmartPtr, class T>
|
|
|
++inline void
|
|
|
++SwapToISupportsArray(SmartPtr<T>& aSrc,
|
|
|
++ nsTArray<nsCOMPtr<nsISupports> >& aDest)
|
|
|
++{
|
|
|
++ nsCOMPtr<nsISupports>* dest = aDest.AppendElement();
|
|
|
++
|
|
|
++ T* raw = nullptr;
|
|
|
++ aSrc.swap(raw);
|
|
|
++
|
|
|
++ nsISupports* rawSupports =
|
|
|
++ static_cast<typename ISupportsBaseInfo<T>::ISupportsBase*>(raw);
|
|
|
++ dest->swap(rawSupports);
|
|
|
++}
|
|
|
++
|
|
|
++} // anonymous
|
|
|
++
|
|
|
++NS_IMPL_ISUPPORTS_INHERITED0(MainThreadReleaseRunnable, Runnable)
|
|
|
++
|
|
|
++WorkerLoadInfo::WorkerLoadInfo()
|
|
|
++ : mLoadFlags(nsIRequest::LOAD_NORMAL)
|
|
|
++ , mWindowID(UINT64_MAX)
|
|
|
++ , mReferrerPolicy(net::RP_Unset)
|
|
|
++ , mFromWindow(false)
|
|
|
++ , mEvalAllowed(false)
|
|
|
++ , mReportCSPViolations(false)
|
|
|
++ , mXHRParamsAllowed(false)
|
|
|
++ , mPrincipalIsSystem(false)
|
|
|
++ , mStorageAllowed(false)
|
|
|
++ , mServiceWorkersTestingInWindow(false)
|
|
|
++{
|
|
|
++ MOZ_COUNT_CTOR(WorkerLoadInfo);
|
|
|
++}
|
|
|
++
|
|
|
++WorkerLoadInfo::~WorkerLoadInfo()
|
|
|
++{
|
|
|
++ MOZ_COUNT_DTOR(WorkerLoadInfo);
|
|
|
++}
|
|
|
++
|
|
|
++void
|
|
|
++WorkerLoadInfo::StealFrom(WorkerLoadInfo& aOther)
|
|
|
++{
|
|
|
++ MOZ_ASSERT(!mBaseURI);
|
|
|
++ aOther.mBaseURI.swap(mBaseURI);
|
|
|
++
|
|
|
++ MOZ_ASSERT(!mResolvedScriptURI);
|
|
|
++ aOther.mResolvedScriptURI.swap(mResolvedScriptURI);
|
|
|
++
|
|
|
++ MOZ_ASSERT(!mPrincipal);
|
|
|
++ aOther.mPrincipal.swap(mPrincipal);
|
|
|
++
|
|
|
++ // mLoadingPrincipal can be null if this is a ServiceWorker.
|
|
|
++ aOther.mLoadingPrincipal.swap(mLoadingPrincipal);
|
|
|
++
|
|
|
++ MOZ_ASSERT(!mScriptContext);
|
|
|
++ aOther.mScriptContext.swap(mScriptContext);
|
|
|
++
|
|
|
++ MOZ_ASSERT(!mWindow);
|
|
|
++ aOther.mWindow.swap(mWindow);
|
|
|
++
|
|
|
++ MOZ_ASSERT(!mCSP);
|
|
|
++ aOther.mCSP.swap(mCSP);
|
|
|
++
|
|
|
++ MOZ_ASSERT(!mChannel);
|
|
|
++ aOther.mChannel.swap(mChannel);
|
|
|
++
|
|
|
++ MOZ_ASSERT(!mLoadGroup);
|
|
|
++ aOther.mLoadGroup.swap(mLoadGroup);
|
|
|
++
|
|
|
++ MOZ_ASSERT(!mLoadFailedAsyncRunnable);
|
|
|
++ aOther.mLoadFailedAsyncRunnable.swap(mLoadFailedAsyncRunnable);
|
|
|
++
|
|
|
++ MOZ_ASSERT(!mInterfaceRequestor);
|
|
|
++ aOther.mInterfaceRequestor.swap(mInterfaceRequestor);
|
|
|
++
|
|
|
++ MOZ_ASSERT(!mPrincipalInfo);
|
|
|
++ mPrincipalInfo = aOther.mPrincipalInfo.forget();
|
|
|
++
|
|
|
++ mDomain = aOther.mDomain;
|
|
|
++ mOrigin = aOther.mOrigin;
|
|
|
++ mServiceWorkerCacheName = aOther.mServiceWorkerCacheName;
|
|
|
++ mServiceWorkerDescriptor = aOther.mServiceWorkerDescriptor;
|
|
|
++ mLoadFlags = aOther.mLoadFlags;
|
|
|
++ mWindowID = aOther.mWindowID;
|
|
|
++ mReferrerPolicy = aOther.mReferrerPolicy;
|
|
|
++ mFromWindow = aOther.mFromWindow;
|
|
|
++ mEvalAllowed = aOther.mEvalAllowed;
|
|
|
++ mReportCSPViolations = aOther.mReportCSPViolations;
|
|
|
++ mXHRParamsAllowed = aOther.mXHRParamsAllowed;
|
|
|
++ mPrincipalIsSystem = aOther.mPrincipalIsSystem;
|
|
|
++ mStorageAllowed = aOther.mStorageAllowed;
|
|
|
++ mServiceWorkersTestingInWindow = aOther.mServiceWorkersTestingInWindow;
|
|
|
++ mOriginAttributes = aOther.mOriginAttributes;
|
|
|
++ mParentController = aOther.mParentController;
|
|
|
++}
|
|
|
++
|
|
|
++nsresult
|
|
|
++WorkerLoadInfo::SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
|
|
|
++ nsILoadGroup* aLoadGroup)
|
|
|
++{
|
|
|
++ AssertIsOnMainThread();
|
|
|
++ MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(aLoadGroup, aPrincipal));
|
|
|
++
|
|
|
++ mPrincipal = aPrincipal;
|
|
|
++ mPrincipalIsSystem = nsContentUtils::IsSystemPrincipal(aPrincipal);
|
|
|
++
|
|
|
++ nsresult rv = aPrincipal->GetCsp(getter_AddRefs(mCSP));
|
|
|
++ NS_ENSURE_SUCCESS(rv, rv);
|
|
|
++
|
|
|
++ if (mCSP) {
|
|
|
++ mCSP->GetAllowsEval(&mReportCSPViolations, &mEvalAllowed);
|
|
|
++ // Set ReferrerPolicy
|
|
|
++ bool hasReferrerPolicy = false;
|
|
|
++ uint32_t rp = mozilla::net::RP_Unset;
|
|
|
++
|
|
|
++ rv = mCSP->GetReferrerPolicy(&rp, &hasReferrerPolicy);
|
|
|
++ NS_ENSURE_SUCCESS(rv, rv);
|
|
|
++
|
|
|
++ if (hasReferrerPolicy) {
|
|
|
++ mReferrerPolicy = static_cast<net::ReferrerPolicy>(rp);
|
|
|
++ }
|
|
|
++ } else {
|
|
|
++ mEvalAllowed = true;
|
|
|
++ mReportCSPViolations = false;
|
|
|
++ }
|
|
|
++
|
|
|
++ mLoadGroup = aLoadGroup;
|
|
|
++
|
|
|
++ mPrincipalInfo = new PrincipalInfo();
|
|
|
++ mOriginAttributes = nsContentUtils::GetOriginAttributes(aLoadGroup);
|
|
|
++
|
|
|
++ rv = PrincipalToPrincipalInfo(aPrincipal, mPrincipalInfo);
|
|
|
++ NS_ENSURE_SUCCESS(rv, rv);
|
|
|
++
|
|
|
++ rv = nsContentUtils::GetUTFOrigin(aPrincipal, mOrigin);
|
|
|
++ NS_ENSURE_SUCCESS(rv, rv);
|
|
|
++
|
|
|
++ return NS_OK;
|
|
|
++}
|
|
|
++
|
|
|
++nsresult
|
|
|
++WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(nsIChannel* aChannel,
|
|
|
++ nsIPrincipal** aPrincipalOut,
|
|
|
++ nsILoadGroup** aLoadGroupOut)
|
|
|
++{
|
|
|
++ AssertIsOnMainThread();
|
|
|
++ MOZ_DIAGNOSTIC_ASSERT(aChannel);
|
|
|
++ MOZ_DIAGNOSTIC_ASSERT(aPrincipalOut);
|
|
|
++ MOZ_DIAGNOSTIC_ASSERT(aLoadGroupOut);
|
|
|
++
|
|
|
++ // Initial triggering principal should be set
|
|
|
++ NS_ENSURE_TRUE(mLoadingPrincipal, NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
++
|
|
|
++ nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
|
|
++ MOZ_DIAGNOSTIC_ASSERT(ssm);
|
|
|
++
|
|
|
++ nsCOMPtr<nsIPrincipal> channelPrincipal;
|
|
|
++ nsresult rv = ssm->GetChannelResultPrincipal(aChannel, getter_AddRefs(channelPrincipal));
|
|
|
++ 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
|
|
|
++ // first got from the channel.
|
|
|
++ //
|
|
|
++ // Note, we don't do this by setting principalToInherit on the channel's
|
|
|
++ // load info because we don't yet have the first null principal when we
|
|
|
++ // create the channel.
|
|
|
++ if (mPrincipal && mPrincipal->GetIsNullPrincipal() &&
|
|
|
++ channelPrincipal->GetIsNullPrincipal()) {
|
|
|
++ channelPrincipal = mPrincipal;
|
|
|
++ }
|
|
|
++
|
|
|
++ nsCOMPtr<nsILoadGroup> channelLoadGroup;
|
|
|
++ rv = aChannel->GetLoadGroup(getter_AddRefs(channelLoadGroup));
|
|
|
++ NS_ENSURE_SUCCESS(rv, rv);
|
|
|
++ MOZ_ASSERT(channelLoadGroup);
|
|
|
++
|
|
|
++ // If the loading principal is the system principal then the channel
|
|
|
++ // principal must also be the system principal (we do not allow chrome
|
|
|
++ // code to create workers with non-chrome scripts, and if we ever decide
|
|
|
++ // to change this we need to make sure we don't always set
|
|
|
++ // mPrincipalIsSystem to true in WorkerPrivate::GetLoadInfo()). Otherwise
|
|
|
++ // this channel principal must be same origin with the load principal (we
|
|
|
++ // check again here in case redirects changed the location of the script).
|
|
|
++ if (nsContentUtils::IsSystemPrincipal(mLoadingPrincipal)) {
|
|
|
++ if (!nsContentUtils::IsSystemPrincipal(channelPrincipal)) {
|
|
|
++ nsCOMPtr<nsIURI> finalURI;
|
|
|
++ rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalURI));
|
|
|
++ NS_ENSURE_SUCCESS(rv, rv);
|
|
|
++
|
|
|
++ // See if this is a resource URI. Since JSMs usually come from
|
|
|
++ // resource:// URIs we're currently considering all URIs with the
|
|
|
++ // URI_IS_UI_RESOURCE flag as valid for creating privileged workers.
|
|
|
++ bool isResource;
|
|
|
++ rv = NS_URIChainHasFlags(finalURI,
|
|
|
++ nsIProtocolHandler::URI_IS_UI_RESOURCE,
|
|
|
++ &isResource);
|
|
|
++ NS_ENSURE_SUCCESS(rv, rv);
|
|
|
++
|
|
|
++ if (isResource) {
|
|
|
++ // Assign the system principal to the resource:// worker only if it
|
|
|
++ // was loaded from code using the system principal.
|
|
|
++ channelPrincipal = mLoadingPrincipal;
|
|
|
++ } else {
|
|
|
++ return NS_ERROR_DOM_BAD_URI;
|
|
|
++ }
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ // The principal can change, but it should still match the original
|
|
|
++ // load group's appId and browser element flag.
|
|
|
++ MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(channelLoadGroup, channelPrincipal));
|
|
|
++
|
|
|
++ channelPrincipal.forget(aPrincipalOut);
|
|
|
++ channelLoadGroup.forget(aLoadGroupOut);
|
|
|
++
|
|
|
++ return NS_OK;
|
|
|
++}
|
|
|
++
|
|
|
++nsresult
|
|
|
++WorkerLoadInfo::SetPrincipalFromChannel(nsIChannel* aChannel)
|
|
|
++{
|
|
|
++ AssertIsOnMainThread();
|
|
|
++
|
|
|
++ nsCOMPtr<nsIPrincipal> principal;
|
|
|
++ nsCOMPtr<nsILoadGroup> loadGroup;
|
|
|
++ nsresult rv = GetPrincipalAndLoadGroupFromChannel(aChannel,
|
|
|
++ getter_AddRefs(principal),
|
|
|
++ getter_AddRefs(loadGroup));
|
|
|
++ NS_ENSURE_SUCCESS(rv, rv);
|
|
|
++
|
|
|
++ return SetPrincipalOnMainThread(principal, loadGroup);
|
|
|
++}
|
|
|
++
|
|
|
++bool
|
|
|
++WorkerLoadInfo::FinalChannelPrincipalIsValid(nsIChannel* aChannel)
|
|
|
++{
|
|
|
++ AssertIsOnMainThread();
|
|
|
++
|
|
|
++ nsCOMPtr<nsIPrincipal> principal;
|
|
|
++ nsCOMPtr<nsILoadGroup> loadGroup;
|
|
|
++ nsresult rv = GetPrincipalAndLoadGroupFromChannel(aChannel,
|
|
|
++ getter_AddRefs(principal),
|
|
|
++ getter_AddRefs(loadGroup));
|
|
|
++ NS_ENSURE_SUCCESS(rv, false);
|
|
|
++
|
|
|
++
|
|
|
++ // Verify that the channel is still a null principal. We don't care
|
|
|
++ // if these are the exact same null principal object, though. From
|
|
|
++ // the worker's perspective its the same effect.
|
|
|
++ if (principal->GetIsNullPrincipal() && mPrincipal->GetIsNullPrincipal()) {
|
|
|
++ return true;
|
|
|
++ }
|
|
|
++
|
|
|
++ // Otherwise we require exact equality. Redirects can happen, but they
|
|
|
++ // are not allowed to change our principal.
|
|
|
++ if (principal->Equals(mPrincipal)) {
|
|
|
++ return true;
|
|
|
++ }
|
|
|
++
|
|
|
++ return false;
|
|
|
++}
|
|
|
++
|
|
|
++#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
|
|
++bool
|
|
|
++WorkerLoadInfo::PrincipalIsValid() const
|
|
|
++{
|
|
|
++ return mPrincipal && mPrincipalInfo &&
|
|
|
++ mPrincipalInfo->type() != PrincipalInfo::T__None &&
|
|
|
++ mPrincipalInfo->type() <= PrincipalInfo::T__Last;
|
|
|
++}
|
|
|
++
|
|
|
++bool
|
|
|
++WorkerLoadInfo::PrincipalURIMatchesScriptURL()
|
|
|
++{
|
|
|
++ AssertIsOnMainThread();
|
|
|
++
|
|
|
++ nsAutoCString scheme;
|
|
|
++ nsresult rv = mBaseURI->GetScheme(scheme);
|
|
|
++ NS_ENSURE_SUCCESS(rv, false);
|
|
|
++
|
|
|
++ // A system principal must either be a blob URL or a resource JSM.
|
|
|
++ if (mPrincipal->GetIsSystemPrincipal()) {
|
|
|
++ if (scheme == NS_LITERAL_CSTRING("blob")) {
|
|
|
++ return true;
|
|
|
++ }
|
|
|
++
|
|
|
++ bool isResource = false;
|
|
|
++ nsresult rv = NS_URIChainHasFlags(mBaseURI,
|
|
|
++ nsIProtocolHandler::URI_IS_UI_RESOURCE,
|
|
|
++ &isResource);
|
|
|
++ NS_ENSURE_SUCCESS(rv, false);
|
|
|
++
|
|
|
++ return isResource;
|
|
|
++ }
|
|
|
++
|
|
|
++ // A null principal can occur for a data URL worker script or a blob URL
|
|
|
++ // worker script from a sandboxed iframe.
|
|
|
++ if (mPrincipal->GetIsNullPrincipal()) {
|
|
|
++ return scheme == NS_LITERAL_CSTRING("data") ||
|
|
|
++ scheme == NS_LITERAL_CSTRING("blob");
|
|
|
++ }
|
|
|
++
|
|
|
++ // The principal for a blob: URL worker script does not have a matching URL.
|
|
|
++ // This is likely a bug in our referer setting logic, but exempt it for now.
|
|
|
++ // This is another reason we should fix bug 1340694 so that referer does not
|
|
|
++ // depend on the principal URI.
|
|
|
++ if (scheme == NS_LITERAL_CSTRING("blob")) {
|
|
|
++ return true;
|
|
|
++ }
|
|
|
++
|
|
|
++ nsCOMPtr<nsIURI> principalURI;
|
|
|
++ rv = mPrincipal->GetURI(getter_AddRefs(principalURI));
|
|
|
++ NS_ENSURE_SUCCESS(rv, false);
|
|
|
++ NS_ENSURE_TRUE(principalURI, false);
|
|
|
++
|
|
|
++ bool equal = false;
|
|
|
++ rv = principalURI->Equals(mBaseURI, &equal);
|
|
|
++ NS_ENSURE_SUCCESS(rv, false);
|
|
|
++
|
|
|
++ return equal;
|
|
|
++}
|
|
|
++#endif // MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
|
|
++
|
|
|
++bool
|
|
|
++WorkerLoadInfo::ProxyReleaseMainThreadObjects(WorkerPrivate* aWorkerPrivate)
|
|
|
++{
|
|
|
++ nsCOMPtr<nsILoadGroup> nullLoadGroup;
|
|
|
++ return ProxyReleaseMainThreadObjects(aWorkerPrivate, nullLoadGroup);
|
|
|
++}
|
|
|
++
|
|
|
++bool
|
|
|
++WorkerLoadInfo::ProxyReleaseMainThreadObjects(WorkerPrivate* aWorkerPrivate,
|
|
|
++ nsCOMPtr<nsILoadGroup>& aLoadGroupToCancel)
|
|
|
++{
|
|
|
++
|
|
|
++ static const uint32_t kDoomedCount = 11;
|
|
|
++ nsTArray<nsCOMPtr<nsISupports>> doomed(kDoomedCount);
|
|
|
++
|
|
|
++ SwapToISupportsArray(mWindow, doomed);
|
|
|
++ SwapToISupportsArray(mScriptContext, doomed);
|
|
|
++ SwapToISupportsArray(mBaseURI, doomed);
|
|
|
++ SwapToISupportsArray(mResolvedScriptURI, doomed);
|
|
|
++ SwapToISupportsArray(mPrincipal, doomed);
|
|
|
++ SwapToISupportsArray(mLoadingPrincipal, doomed);
|
|
|
++ SwapToISupportsArray(mChannel, doomed);
|
|
|
++ SwapToISupportsArray(mCSP, doomed);
|
|
|
++ SwapToISupportsArray(mLoadGroup, doomed);
|
|
|
++ SwapToISupportsArray(mLoadFailedAsyncRunnable, doomed);
|
|
|
++ SwapToISupportsArray(mInterfaceRequestor, doomed);
|
|
|
++ // Before adding anything here update kDoomedCount above!
|
|
|
++
|
|
|
++ MOZ_ASSERT(doomed.Length() == kDoomedCount);
|
|
|
++
|
|
|
++ RefPtr<MainThreadReleaseRunnable> runnable =
|
|
|
++ new MainThreadReleaseRunnable(doomed, aLoadGroupToCancel);
|
|
|
++ return NS_SUCCEEDED(aWorkerPrivate->DispatchToMainThread(runnable.forget()));
|
|
|
++}
|
|
|
++
|
|
|
++WorkerLoadInfo::
|
|
|
++InterfaceRequestor::InterfaceRequestor(nsIPrincipal* aPrincipal,
|
|
|
++ nsILoadGroup* aLoadGroup)
|
|
|
++{
|
|
|
++ MOZ_ASSERT(NS_IsMainThread());
|
|
|
++ MOZ_ASSERT(aPrincipal);
|
|
|
++
|
|
|
++ // Look for an existing LoadContext. This is optional and it's ok if
|
|
|
++ // we don't find one.
|
|
|
++ nsCOMPtr<nsILoadContext> baseContext;
|
|
|
++ if (aLoadGroup) {
|
|
|
++ nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
|
|
++ aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
|
|
++ if (callbacks) {
|
|
|
++ callbacks->GetInterface(NS_GET_IID(nsILoadContext),
|
|
|
++ getter_AddRefs(baseContext));
|
|
|
++ }
|
|
|
++ mOuterRequestor = callbacks;
|
|
|
++ }
|
|
|
++
|
|
|
++ mLoadContext = new LoadContext(aPrincipal, baseContext);
|
|
|
++}
|
|
|
++
|
|
|
++void
|
|
|
++WorkerLoadInfo::
|
|
|
++InterfaceRequestor::MaybeAddTabChild(nsILoadGroup* aLoadGroup)
|
|
|
++{
|
|
|
++ MOZ_ASSERT(NS_IsMainThread());
|
|
|
++
|
|
|
++ if (!aLoadGroup) {
|
|
|
++ return;
|
|
|
++ }
|
|
|
++
|
|
|
++ nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
|
|
++ aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
|
|
++ if (!callbacks) {
|
|
|
++ return;
|
|
|
++ }
|
|
|
++
|
|
|
++ nsCOMPtr<nsITabChild> tabChild;
|
|
|
++ callbacks->GetInterface(NS_GET_IID(nsITabChild), getter_AddRefs(tabChild));
|
|
|
++ if (!tabChild) {
|
|
|
++ return;
|
|
|
++ }
|
|
|
++
|
|
|
++ // Use weak references to the tab child. Holding a strong reference will
|
|
|
++ // not prevent an ActorDestroy() from being called on the TabChild.
|
|
|
++ // Therefore, we should let the TabChild destroy itself as soon as possible.
|
|
|
++ mTabChildList.AppendElement(do_GetWeakReference(tabChild));
|
|
|
++}
|
|
|
++
|
|
|
++NS_IMETHODIMP
|
|
|
++WorkerLoadInfo::
|
|
|
++InterfaceRequestor::GetInterface(const nsIID& aIID, void** aSink)
|
|
|
++{
|
|
|
++ MOZ_ASSERT(NS_IsMainThread());
|
|
|
++ MOZ_ASSERT(mLoadContext);
|
|
|
++
|
|
|
++ if (aIID.Equals(NS_GET_IID(nsILoadContext))) {
|
|
|
++ nsCOMPtr<nsILoadContext> ref = mLoadContext;
|
|
|
++ ref.forget(aSink);
|
|
|
++ return NS_OK;
|
|
|
++ }
|
|
|
++
|
|
|
++ // If we still have an active nsITabChild, then return it. Its possible,
|
|
|
++ // though, that all of the TabChild objects have been destroyed. In that
|
|
|
++ // case we return NS_NOINTERFACE.
|
|
|
++ if (aIID.Equals(NS_GET_IID(nsITabChild))) {
|
|
|
++ nsCOMPtr<nsITabChild> tabChild = GetAnyLiveTabChild();
|
|
|
++ if (!tabChild) {
|
|
|
++ return NS_NOINTERFACE;
|
|
|
++ }
|
|
|
++ tabChild.forget(aSink);
|
|
|
++ return NS_OK;
|
|
|
++ }
|
|
|
++
|
|
|
++ if (aIID.Equals(NS_GET_IID(nsINetworkInterceptController)) &&
|
|
|
++ mOuterRequestor) {
|
|
|
++ // If asked for the network intercept controller, ask the outer requestor,
|
|
|
++ // which could be the docshell.
|
|
|
++ return mOuterRequestor->GetInterface(aIID, aSink);
|
|
|
++ }
|
|
|
++
|
|
|
++ return NS_NOINTERFACE;
|
|
|
++}
|
|
|
++
|
|
|
++already_AddRefed<nsITabChild>
|
|
|
++WorkerLoadInfo::
|
|
|
++InterfaceRequestor::GetAnyLiveTabChild()
|
|
|
++{
|
|
|
++ MOZ_ASSERT(NS_IsMainThread());
|
|
|
++
|
|
|
++ // Search our list of known TabChild objects for one that still exists.
|
|
|
++ while (!mTabChildList.IsEmpty()) {
|
|
|
++ nsCOMPtr<nsITabChild> tabChild =
|
|
|
++ do_QueryReferent(mTabChildList.LastElement());
|
|
|
++
|
|
|
++ // Does this tab child still exist? If so, return it. We are done. If the
|
|
|
++ // PBrowser actor is no longer useful, don't bother returning this tab.
|
|
|
++ if (tabChild && !static_cast<TabChild*>(tabChild.get())->IsDestroyed()) {
|
|
|
++ return tabChild.forget();
|
|
|
++ }
|
|
|
++
|
|
|
++ // Otherwise remove the stale weak reference and check the next one
|
|
|
++ mTabChildList.RemoveElementAt(mTabChildList.Length() - 1);
|
|
|
++ }
|
|
|
++
|
|
|
++ return nullptr;
|
|
|
++}
|
|
|
++
|
|
|
++NS_IMPL_ADDREF(WorkerLoadInfo::InterfaceRequestor)
|
|
|
++NS_IMPL_RELEASE(WorkerLoadInfo::InterfaceRequestor)
|
|
|
++NS_IMPL_QUERY_INTERFACE(WorkerLoadInfo::InterfaceRequestor,
|
|
|
++ nsIInterfaceRequestor)
|
|
|
++
|
|
|
++} // worker namespace
|
|
|
++} // dom namespace
|
|
|
++} // mozilla namespace
|
|
|
+diff --git a/dom/workers/WorkerLoadInfo.h b/dom/workers/WorkerLoadInfo.h
|
|
|
+new file mode 100644
|
|
|
+--- /dev/null
|
|
|
++++ b/dom/workers/WorkerLoadInfo.h
|
|
|
+@@ -0,0 +1,143 @@
|
|
|
++/* -*- 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_workers_WorkerLoadInfo_h
|
|
|
++#define mozilla_dom_workers_WorkerLoadInfo_h
|
|
|
++
|
|
|
++#include "mozilla/dom/workers/WorkerCommon.h"
|
|
|
++#include "nsIInterfaceRequestor.h"
|
|
|
++#include "nsISupportsImpl.h"
|
|
|
++
|
|
|
++class nsIChannel;
|
|
|
++class nsIContentSecurityPolicy;
|
|
|
++class nsILoadGroup;
|
|
|
++class nsIPrincipal;
|
|
|
++class nsIRunnable;
|
|
|
++class nsIScriptContext;
|
|
|
++class nsITabChild;
|
|
|
++class nsIURI;
|
|
|
++class nsPIDOMWindowInner;
|
|
|
++
|
|
|
++namespace mozilla {
|
|
|
++namespace ipc {
|
|
|
++class PrincipalInfo;
|
|
|
++} // namespace ipc
|
|
|
++} // namespace mozilla
|
|
|
++
|
|
|
++BEGIN_WORKERS_NAMESPACE
|
|
|
++
|
|
|
++struct WorkerLoadInfo
|
|
|
++{
|
|
|
++ // All of these should be released in WorkerPrivateParent::ForgetMainThreadObjects.
|
|
|
++ nsCOMPtr<nsIURI> mBaseURI;
|
|
|
++ nsCOMPtr<nsIURI> mResolvedScriptURI;
|
|
|
++
|
|
|
++ // This is the principal of the global (parent worker or a window) loading
|
|
|
++ // the worker. It can be null if we are executing a ServiceWorker, otherwise,
|
|
|
++ // except for data: URL, it must subsumes the worker principal.
|
|
|
++ // If we load a data: URL, mPrincipal will be a null principal.
|
|
|
++ nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
|
|
|
++ nsCOMPtr<nsIPrincipal> mPrincipal;
|
|
|
++
|
|
|
++ nsCOMPtr<nsIScriptContext> mScriptContext;
|
|
|
++ nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
|
|
++ nsCOMPtr<nsIContentSecurityPolicy> mCSP;
|
|
|
++ nsCOMPtr<nsIChannel> mChannel;
|
|
|
++ nsCOMPtr<nsILoadGroup> mLoadGroup;
|
|
|
++
|
|
|
++ // mLoadFailedAsyncRunnable will execute on main thread if script loading
|
|
|
++ // fails during script loading. If script loading is never started due to
|
|
|
++ // a synchronous error, then the runnable is never executed. The runnable
|
|
|
++ // is guaranteed to be released on the main thread.
|
|
|
++ nsCOMPtr<nsIRunnable> mLoadFailedAsyncRunnable;
|
|
|
++
|
|
|
++ class InterfaceRequestor final : public nsIInterfaceRequestor
|
|
|
++ {
|
|
|
++ NS_DECL_ISUPPORTS
|
|
|
++
|
|
|
++ public:
|
|
|
++ InterfaceRequestor(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
|
|
|
++ void MaybeAddTabChild(nsILoadGroup* aLoadGroup);
|
|
|
++ NS_IMETHOD GetInterface(const nsIID& aIID, void** aSink) override;
|
|
|
++
|
|
|
++ private:
|
|
|
++ ~InterfaceRequestor() { }
|
|
|
++
|
|
|
++ already_AddRefed<nsITabChild> GetAnyLiveTabChild();
|
|
|
++
|
|
|
++ nsCOMPtr<nsILoadContext> mLoadContext;
|
|
|
++ nsCOMPtr<nsIInterfaceRequestor> mOuterRequestor;
|
|
|
++
|
|
|
++ // Array of weak references to nsITabChild. We do not want to keep TabChild
|
|
|
++ // actors alive for long after their ActorDestroy() methods are called.
|
|
|
++ nsTArray<nsWeakPtr> mTabChildList;
|
|
|
++ };
|
|
|
++
|
|
|
++ // Only set if we have a custom overriden load group
|
|
|
++ RefPtr<InterfaceRequestor> mInterfaceRequestor;
|
|
|
++
|
|
|
++ nsAutoPtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
|
|
|
++ nsCString mDomain;
|
|
|
++ nsString mOrigin; // Derived from mPrincipal; can be used on worker thread.
|
|
|
++
|
|
|
++ nsString mServiceWorkerCacheName;
|
|
|
++ Maybe<ServiceWorkerDescriptor> mServiceWorkerDescriptor;
|
|
|
++
|
|
|
++ Maybe<ServiceWorkerDescriptor> mParentController;
|
|
|
++
|
|
|
++ ChannelInfo mChannelInfo;
|
|
|
++ nsLoadFlags mLoadFlags;
|
|
|
++
|
|
|
++ uint64_t mWindowID;
|
|
|
++
|
|
|
++ net::ReferrerPolicy mReferrerPolicy;
|
|
|
++ bool mFromWindow;
|
|
|
++ bool mEvalAllowed;
|
|
|
++ bool mReportCSPViolations;
|
|
|
++ bool mXHRParamsAllowed;
|
|
|
++ bool mPrincipalIsSystem;
|
|
|
++ bool mStorageAllowed;
|
|
|
++ bool mServiceWorkersTestingInWindow;
|
|
|
++ OriginAttributes mOriginAttributes;
|
|
|
++
|
|
|
++ WorkerLoadInfo();
|
|
|
++ ~WorkerLoadInfo();
|
|
|
++
|
|
|
++ void StealFrom(WorkerLoadInfo& aOther);
|
|
|
++
|
|
|
++ nsresult
|
|
|
++ SetPrincipalOnMainThread(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
|
|
|
++
|
|
|
++ nsresult
|
|
|
++ GetPrincipalAndLoadGroupFromChannel(nsIChannel* aChannel,
|
|
|
++ nsIPrincipal** aPrincipalOut,
|
|
|
++ nsILoadGroup** aLoadGroupOut);
|
|
|
++
|
|
|
++ nsresult
|
|
|
++ SetPrincipalFromChannel(nsIChannel* aChannel);
|
|
|
++
|
|
|
++ bool
|
|
|
++ FinalChannelPrincipalIsValid(nsIChannel* aChannel);
|
|
|
++
|
|
|
++#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
|
|
++ bool
|
|
|
++ PrincipalIsValid() const;
|
|
|
++
|
|
|
++ bool
|
|
|
++ PrincipalURIMatchesScriptURL();
|
|
|
++#endif
|
|
|
++
|
|
|
++ bool
|
|
|
++ ProxyReleaseMainThreadObjects(WorkerPrivate* aWorkerPrivate);
|
|
|
++
|
|
|
++ bool
|
|
|
++ ProxyReleaseMainThreadObjects(WorkerPrivate* aWorkerPrivate,
|
|
|
++ nsCOMPtr<nsILoadGroup>& aLoadGroupToCancel);
|
|
|
++};
|
|
|
++
|
|
|
++END_WORKERS_NAMESPACE
|
|
|
++
|
|
|
++#endif // mozilla_dom_workers_WorkerLoadInfo_h
|
|
|
+diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
|
|
|
+--- a/dom/workers/WorkerPrivate.cpp
|
|
|
++++ b/dom/workers/WorkerPrivate.cpp
|
|
|
+@@ -12,23 +12,21 @@
|
|
|
+ #include "nsIConsoleService.h"
|
|
|
+ #include "nsIDOMDOMException.h"
|
|
|
+ #include "nsIDOMEvent.h"
|
|
|
+ #include "nsIDocument.h"
|
|
|
+ #include "nsIDocShell.h"
|
|
|
+ #include "nsIInterfaceRequestor.h"
|
|
|
+ #include "nsIMemoryReporter.h"
|
|
|
+ #include "nsINamed.h"
|
|
|
+-#include "nsINetworkInterceptController.h"
|
|
|
+ #include "nsIPermissionManager.h"
|
|
|
+ #include "nsIScriptError.h"
|
|
|
+ #include "nsIScriptGlobalObject.h"
|
|
|
+ #include "nsIScriptSecurityManager.h"
|
|
|
+ #include "nsIScriptTimeoutHandler.h"
|
|
|
+-#include "nsITabChild.h"
|
|
|
+ #include "nsITextToSubURI.h"
|
|
|
+ #include "nsIThreadInternal.h"
|
|
|
+ #include "nsITimer.h"
|
|
|
+ #include "nsIURI.h"
|
|
|
+ #include "nsIURL.h"
|
|
|
+ #include "nsIWeakReferenceUtils.h"
|
|
|
+ #include "nsIWorkerDebugger.h"
|
|
|
+ #include "nsIXPConnect.h"
|
|
|
+@@ -40,17 +38,16 @@
|
|
|
+ #include "jsfriendapi.h"
|
|
|
+ #include "js/MemoryMetrics.h"
|
|
|
+ #include "MessageEventRunnable.h"
|
|
|
+ #include "mozilla/Assertions.h"
|
|
|
+ #include "mozilla/Attributes.h"
|
|
|
+ #include "mozilla/ContentEvents.h"
|
|
|
+ #include "mozilla/EventDispatcher.h"
|
|
|
+ #include "mozilla/Likely.h"
|
|
|
+-#include "mozilla/LoadContext.h"
|
|
|
+ #include "mozilla/Move.h"
|
|
|
+ #include "mozilla/dom/BindingUtils.h"
|
|
|
+ #include "mozilla/dom/ClientManager.h"
|
|
|
+ #include "mozilla/dom/ClientSource.h"
|
|
|
+ #include "mozilla/dom/ClientState.h"
|
|
|
+ #include "mozilla/dom/Console.h"
|
|
|
+ #include "mozilla/dom/DocGroup.h"
|
|
|
+ #include "mozilla/dom/ErrorEvent.h"
|
|
|
+@@ -68,17 +65,16 @@
|
|
|
+ #include "mozilla/dom/PerformanceStorageWorker.h"
|
|
|
+ #include "mozilla/dom/PMessagePort.h"
|
|
|
+ #include "mozilla/dom/Promise.h"
|
|
|
+ #include "mozilla/dom/PromiseDebugging.h"
|
|
|
+ #include "mozilla/dom/PromiseNativeHandler.h"
|
|
|
+ #include "mozilla/dom/SimpleGlobalObject.h"
|
|
|
+ #include "mozilla/dom/ScriptSettings.h"
|
|
|
+ #include "mozilla/dom/StructuredCloneHolder.h"
|
|
|
+-#include "mozilla/dom/TabChild.h"
|
|
|
+ #include "mozilla/dom/WorkerBinding.h"
|
|
|
+ #include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h"
|
|
|
+ #include "mozilla/dom/WorkerGlobalScopeBinding.h"
|
|
|
+ #include "mozilla/Preferences.h"
|
|
|
+ #include "mozilla/ThreadEventQueue.h"
|
|
|
+ #include "mozilla/ThrottledEventQueue.h"
|
|
|
+ #include "mozilla/TimelineConsumers.h"
|
|
|
+ #include "mozilla/WorkerTimelineMarker.h"
|
|
|
+@@ -196,38 +192,16 @@ public:
|
|
|
+
|
|
|
+ template <class T>
|
|
|
+ inline AutoPtrComparator<T>
|
|
|
+ GetAutoPtrComparator(const nsTArray<nsAutoPtr<T> >&)
|
|
|
+ {
|
|
|
+ return AutoPtrComparator<T>();
|
|
|
+ }
|
|
|
+
|
|
|
+-// Specialize this if there's some class that has multiple nsISupports bases.
|
|
|
+-template <class T>
|
|
|
+-struct ISupportsBaseInfo
|
|
|
+-{
|
|
|
+- typedef T ISupportsBase;
|
|
|
+-};
|
|
|
+-
|
|
|
+-template <template <class> class SmartPtr, class T>
|
|
|
+-inline void
|
|
|
+-SwapToISupportsArray(SmartPtr<T>& aSrc,
|
|
|
+- nsTArray<nsCOMPtr<nsISupports> >& aDest)
|
|
|
+-{
|
|
|
+- nsCOMPtr<nsISupports>* dest = aDest.AppendElement();
|
|
|
+-
|
|
|
+- T* raw = nullptr;
|
|
|
+- aSrc.swap(raw);
|
|
|
+-
|
|
|
+- nsISupports* rawSupports =
|
|
|
+- static_cast<typename ISupportsBaseInfo<T>::ISupportsBase*>(raw);
|
|
|
+- dest->swap(rawSupports);
|
|
|
+-}
|
|
|
+-
|
|
|
+ // This class is used to wrap any runnables that the worker receives via the
|
|
|
+ // nsIEventTarget::Dispatch() method (either from NS_DispatchToCurrentThread or
|
|
|
+ // from the worker's EventTarget).
|
|
|
+ class ExternalRunnableWrapper final : public WorkerRunnable
|
|
|
+ {
|
|
|
+ nsCOMPtr<nsIRunnable> mWrappedRunnable;
|
|
|
+
|
|
|
+ public:
|
|
|
+@@ -359,49 +333,16 @@ LogErrorToConsole(const WorkerErrorRepor
|
|
|
+ __android_log_print(ANDROID_LOG_INFO, "Gecko", kErrorString, msg.get(),
|
|
|
+ filename.get(), aReport.mLineNumber);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ fprintf(stderr, kErrorString, msg.get(), filename.get(), aReport.mLineNumber);
|
|
|
+ fflush(stderr);
|
|
|
+ }
|
|
|
+
|
|
|
+-class MainThreadReleaseRunnable final : public Runnable
|
|
|
+-{
|
|
|
+- nsTArray<nsCOMPtr<nsISupports>> mDoomed;
|
|
|
+- nsCOMPtr<nsILoadGroup> mLoadGroupToCancel;
|
|
|
+-
|
|
|
+-public:
|
|
|
+- MainThreadReleaseRunnable(nsTArray<nsCOMPtr<nsISupports>>& aDoomed,
|
|
|
+- nsCOMPtr<nsILoadGroup>& aLoadGroupToCancel)
|
|
|
+- : mozilla::Runnable("MainThreadReleaseRunnable")
|
|
|
+- {
|
|
|
+- mDoomed.SwapElements(aDoomed);
|
|
|
+- mLoadGroupToCancel.swap(aLoadGroupToCancel);
|
|
|
+- }
|
|
|
+-
|
|
|
+- NS_DECL_ISUPPORTS_INHERITED
|
|
|
+-
|
|
|
+- NS_IMETHOD
|
|
|
+- Run() override
|
|
|
+- {
|
|
|
+- if (mLoadGroupToCancel) {
|
|
|
+- mLoadGroupToCancel->Cancel(NS_BINDING_ABORTED);
|
|
|
+- mLoadGroupToCancel = nullptr;
|
|
|
+- }
|
|
|
+-
|
|
|
+- mDoomed.Clear();
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+-private:
|
|
|
+- ~MainThreadReleaseRunnable()
|
|
|
+- { }
|
|
|
+-};
|
|
|
+-
|
|
|
+ class WorkerFinishedRunnable final : public WorkerControlRunnable
|
|
|
+ {
|
|
|
+ WorkerPrivate* mFinishedWorker;
|
|
|
+
|
|
|
+ public:
|
|
|
+ WorkerFinishedRunnable(WorkerPrivate* aWorkerPrivate,
|
|
|
+ WorkerPrivate* aFinishedWorker)
|
|
|
+ : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
|
|
|
+@@ -1457,18 +1398,16 @@ public:
|
|
|
+ : WorkerHolder("SimpleWorkerHolder")
|
|
|
+ {}
|
|
|
+
|
|
|
+ virtual bool Notify(Status aStatus) override { return true; }
|
|
|
+ };
|
|
|
+
|
|
|
+ } /* anonymous namespace */
|
|
|
+
|
|
|
+-NS_IMPL_ISUPPORTS_INHERITED0(MainThreadReleaseRunnable, Runnable)
|
|
|
+-
|
|
|
+ NS_IMPL_ISUPPORTS_INHERITED0(TopLevelWorkerFinishedRunnable, Runnable)
|
|
|
+
|
|
|
+ namespace {
|
|
|
+
|
|
|
+ class WrappedControlRunnable final : public WorkerControlRunnable
|
|
|
+ {
|
|
|
+ nsCOMPtr<nsIRunnable> mInner;
|
|
|
+
|
|
|
+@@ -1636,357 +1575,16 @@ public:
|
|
|
+ NS_DECL_THREADSAFE_ISUPPORTS
|
|
|
+ };
|
|
|
+
|
|
|
+ NS_IMPL_ISUPPORTS(WorkerEventTarget, nsIEventTarget,
|
|
|
+ nsISerialEventTarget)
|
|
|
+
|
|
|
+ END_WORKERS_NAMESPACE
|
|
|
+
|
|
|
+-WorkerLoadInfo::WorkerLoadInfo()
|
|
|
+- : mLoadFlags(nsIRequest::LOAD_NORMAL)
|
|
|
+- , mWindowID(UINT64_MAX)
|
|
|
+- , mReferrerPolicy(net::RP_Unset)
|
|
|
+- , mFromWindow(false)
|
|
|
+- , mEvalAllowed(false)
|
|
|
+- , mReportCSPViolations(false)
|
|
|
+- , mXHRParamsAllowed(false)
|
|
|
+- , mPrincipalIsSystem(false)
|
|
|
+- , mStorageAllowed(false)
|
|
|
+- , mServiceWorkersTestingInWindow(false)
|
|
|
+-{
|
|
|
+- MOZ_COUNT_CTOR(WorkerLoadInfo);
|
|
|
+-}
|
|
|
+-
|
|
|
+-WorkerLoadInfo::~WorkerLoadInfo()
|
|
|
+-{
|
|
|
+- MOZ_COUNT_DTOR(WorkerLoadInfo);
|
|
|
+-}
|
|
|
+-
|
|
|
+-void
|
|
|
+-WorkerLoadInfo::StealFrom(WorkerLoadInfo& aOther)
|
|
|
+-{
|
|
|
+- MOZ_ASSERT(!mBaseURI);
|
|
|
+- aOther.mBaseURI.swap(mBaseURI);
|
|
|
+-
|
|
|
+- MOZ_ASSERT(!mResolvedScriptURI);
|
|
|
+- aOther.mResolvedScriptURI.swap(mResolvedScriptURI);
|
|
|
+-
|
|
|
+- MOZ_ASSERT(!mPrincipal);
|
|
|
+- aOther.mPrincipal.swap(mPrincipal);
|
|
|
+-
|
|
|
+- // mLoadingPrincipal can be null if this is a ServiceWorker.
|
|
|
+- aOther.mLoadingPrincipal.swap(mLoadingPrincipal);
|
|
|
+-
|
|
|
+- MOZ_ASSERT(!mScriptContext);
|
|
|
+- aOther.mScriptContext.swap(mScriptContext);
|
|
|
+-
|
|
|
+- MOZ_ASSERT(!mWindow);
|
|
|
+- aOther.mWindow.swap(mWindow);
|
|
|
+-
|
|
|
+- MOZ_ASSERT(!mCSP);
|
|
|
+- aOther.mCSP.swap(mCSP);
|
|
|
+-
|
|
|
+- MOZ_ASSERT(!mChannel);
|
|
|
+- aOther.mChannel.swap(mChannel);
|
|
|
+-
|
|
|
+- MOZ_ASSERT(!mLoadGroup);
|
|
|
+- aOther.mLoadGroup.swap(mLoadGroup);
|
|
|
+-
|
|
|
+- MOZ_ASSERT(!mLoadFailedAsyncRunnable);
|
|
|
+- aOther.mLoadFailedAsyncRunnable.swap(mLoadFailedAsyncRunnable);
|
|
|
+-
|
|
|
+- MOZ_ASSERT(!mInterfaceRequestor);
|
|
|
+- aOther.mInterfaceRequestor.swap(mInterfaceRequestor);
|
|
|
+-
|
|
|
+- MOZ_ASSERT(!mPrincipalInfo);
|
|
|
+- mPrincipalInfo = aOther.mPrincipalInfo.forget();
|
|
|
+-
|
|
|
+- mDomain = aOther.mDomain;
|
|
|
+- mOrigin = aOther.mOrigin;
|
|
|
+- mServiceWorkerCacheName = aOther.mServiceWorkerCacheName;
|
|
|
+- mServiceWorkerDescriptor = aOther.mServiceWorkerDescriptor;
|
|
|
+- mLoadFlags = aOther.mLoadFlags;
|
|
|
+- mWindowID = aOther.mWindowID;
|
|
|
+- mReferrerPolicy = aOther.mReferrerPolicy;
|
|
|
+- mFromWindow = aOther.mFromWindow;
|
|
|
+- mEvalAllowed = aOther.mEvalAllowed;
|
|
|
+- mReportCSPViolations = aOther.mReportCSPViolations;
|
|
|
+- mXHRParamsAllowed = aOther.mXHRParamsAllowed;
|
|
|
+- mPrincipalIsSystem = aOther.mPrincipalIsSystem;
|
|
|
+- mStorageAllowed = aOther.mStorageAllowed;
|
|
|
+- mServiceWorkersTestingInWindow = aOther.mServiceWorkersTestingInWindow;
|
|
|
+- mOriginAttributes = aOther.mOriginAttributes;
|
|
|
+- mParentController = aOther.mParentController;
|
|
|
+-}
|
|
|
+-
|
|
|
+-nsresult
|
|
|
+-WorkerLoadInfo::SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
|
|
|
+- nsILoadGroup* aLoadGroup)
|
|
|
+-{
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(aLoadGroup, aPrincipal));
|
|
|
+-
|
|
|
+- mPrincipal = aPrincipal;
|
|
|
+- mPrincipalIsSystem = nsContentUtils::IsSystemPrincipal(aPrincipal);
|
|
|
+-
|
|
|
+- nsresult rv = aPrincipal->GetCsp(getter_AddRefs(mCSP));
|
|
|
+- NS_ENSURE_SUCCESS(rv, rv);
|
|
|
+-
|
|
|
+- if (mCSP) {
|
|
|
+- mCSP->GetAllowsEval(&mReportCSPViolations, &mEvalAllowed);
|
|
|
+- // Set ReferrerPolicy
|
|
|
+- bool hasReferrerPolicy = false;
|
|
|
+- uint32_t rp = mozilla::net::RP_Unset;
|
|
|
+-
|
|
|
+- rv = mCSP->GetReferrerPolicy(&rp, &hasReferrerPolicy);
|
|
|
+- NS_ENSURE_SUCCESS(rv, rv);
|
|
|
+-
|
|
|
+- if (hasReferrerPolicy) {
|
|
|
+- mReferrerPolicy = static_cast<net::ReferrerPolicy>(rp);
|
|
|
+- }
|
|
|
+- } else {
|
|
|
+- mEvalAllowed = true;
|
|
|
+- mReportCSPViolations = false;
|
|
|
+- }
|
|
|
+-
|
|
|
+- mLoadGroup = aLoadGroup;
|
|
|
+-
|
|
|
+- mPrincipalInfo = new PrincipalInfo();
|
|
|
+- mOriginAttributes = nsContentUtils::GetOriginAttributes(aLoadGroup);
|
|
|
+-
|
|
|
+- rv = PrincipalToPrincipalInfo(aPrincipal, mPrincipalInfo);
|
|
|
+- NS_ENSURE_SUCCESS(rv, rv);
|
|
|
+-
|
|
|
+- rv = nsContentUtils::GetUTFOrigin(aPrincipal, mOrigin);
|
|
|
+- NS_ENSURE_SUCCESS(rv, rv);
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+-}
|
|
|
+-
|
|
|
+-nsresult
|
|
|
+-WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(nsIChannel* aChannel,
|
|
|
+- nsIPrincipal** aPrincipalOut,
|
|
|
+- nsILoadGroup** aLoadGroupOut)
|
|
|
+-{
|
|
|
+- AssertIsOnMainThread();
|
|
|
+- MOZ_DIAGNOSTIC_ASSERT(aChannel);
|
|
|
+- MOZ_DIAGNOSTIC_ASSERT(aPrincipalOut);
|
|
|
+- MOZ_DIAGNOSTIC_ASSERT(aLoadGroupOut);
|
|
|
+-
|
|
|
+- // Initial triggering principal should be set
|
|
|
+- NS_ENSURE_TRUE(mLoadingPrincipal, NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
+-
|
|
|
+- nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
|
|
+- MOZ_DIAGNOSTIC_ASSERT(ssm);
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIPrincipal> channelPrincipal;
|
|
|
+- nsresult rv = ssm->GetChannelResultPrincipal(aChannel, getter_AddRefs(channelPrincipal));
|
|
|
+- 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
|
|
|
+- // first got from the channel.
|
|
|
+- //
|
|
|
+- // Note, we don't do this by setting principalToInherit on the channel's
|
|
|
+- // load info because we don't yet have the first null principal when we
|
|
|
+- // create the channel.
|
|
|
+- if (mPrincipal && mPrincipal->GetIsNullPrincipal() &&
|
|
|
+- channelPrincipal->GetIsNullPrincipal()) {
|
|
|
+- channelPrincipal = mPrincipal;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsILoadGroup> channelLoadGroup;
|
|
|
+- rv = aChannel->GetLoadGroup(getter_AddRefs(channelLoadGroup));
|
|
|
+- NS_ENSURE_SUCCESS(rv, rv);
|
|
|
+- MOZ_ASSERT(channelLoadGroup);
|
|
|
+-
|
|
|
+- // If the loading principal is the system principal then the channel
|
|
|
+- // principal must also be the system principal (we do not allow chrome
|
|
|
+- // code to create workers with non-chrome scripts, and if we ever decide
|
|
|
+- // to change this we need to make sure we don't always set
|
|
|
+- // mPrincipalIsSystem to true in WorkerPrivate::GetLoadInfo()). Otherwise
|
|
|
+- // this channel principal must be same origin with the load principal (we
|
|
|
+- // check again here in case redirects changed the location of the script).
|
|
|
+- if (nsContentUtils::IsSystemPrincipal(mLoadingPrincipal)) {
|
|
|
+- if (!nsContentUtils::IsSystemPrincipal(channelPrincipal)) {
|
|
|
+- nsCOMPtr<nsIURI> finalURI;
|
|
|
+- rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalURI));
|
|
|
+- NS_ENSURE_SUCCESS(rv, rv);
|
|
|
+-
|
|
|
+- // See if this is a resource URI. Since JSMs usually come from
|
|
|
+- // resource:// URIs we're currently considering all URIs with the
|
|
|
+- // URI_IS_UI_RESOURCE flag as valid for creating privileged workers.
|
|
|
+- bool isResource;
|
|
|
+- rv = NS_URIChainHasFlags(finalURI,
|
|
|
+- nsIProtocolHandler::URI_IS_UI_RESOURCE,
|
|
|
+- &isResource);
|
|
|
+- NS_ENSURE_SUCCESS(rv, rv);
|
|
|
+-
|
|
|
+- if (isResource) {
|
|
|
+- // Assign the system principal to the resource:// worker only if it
|
|
|
+- // was loaded from code using the system principal.
|
|
|
+- channelPrincipal = mLoadingPrincipal;
|
|
|
+- } else {
|
|
|
+- return NS_ERROR_DOM_BAD_URI;
|
|
|
+- }
|
|
|
+- }
|
|
|
+- }
|
|
|
+-
|
|
|
+- // The principal can change, but it should still match the original
|
|
|
+- // load group's appId and browser element flag.
|
|
|
+- MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(channelLoadGroup, channelPrincipal));
|
|
|
+-
|
|
|
+- channelPrincipal.forget(aPrincipalOut);
|
|
|
+- channelLoadGroup.forget(aLoadGroupOut);
|
|
|
+-
|
|
|
+- return NS_OK;
|
|
|
+-}
|
|
|
+-
|
|
|
+-nsresult
|
|
|
+-WorkerLoadInfo::SetPrincipalFromChannel(nsIChannel* aChannel)
|
|
|
+-{
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIPrincipal> principal;
|
|
|
+- nsCOMPtr<nsILoadGroup> loadGroup;
|
|
|
+- nsresult rv = GetPrincipalAndLoadGroupFromChannel(aChannel,
|
|
|
+- getter_AddRefs(principal),
|
|
|
+- getter_AddRefs(loadGroup));
|
|
|
+- NS_ENSURE_SUCCESS(rv, rv);
|
|
|
+-
|
|
|
+- return SetPrincipalOnMainThread(principal, loadGroup);
|
|
|
+-}
|
|
|
+-
|
|
|
+-bool
|
|
|
+-WorkerLoadInfo::FinalChannelPrincipalIsValid(nsIChannel* aChannel)
|
|
|
+-{
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIPrincipal> principal;
|
|
|
+- nsCOMPtr<nsILoadGroup> loadGroup;
|
|
|
+- nsresult rv = GetPrincipalAndLoadGroupFromChannel(aChannel,
|
|
|
+- getter_AddRefs(principal),
|
|
|
+- getter_AddRefs(loadGroup));
|
|
|
+- NS_ENSURE_SUCCESS(rv, false);
|
|
|
+-
|
|
|
+-
|
|
|
+- // Verify that the channel is still a null principal. We don't care
|
|
|
+- // if these are the exact same null principal object, though. From
|
|
|
+- // the worker's perspective its the same effect.
|
|
|
+- if (principal->GetIsNullPrincipal() && mPrincipal->GetIsNullPrincipal()) {
|
|
|
+- return true;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // Otherwise we require exact equality. Redirects can happen, but they
|
|
|
+- // are not allowed to change our principal.
|
|
|
+- if (principal->Equals(mPrincipal)) {
|
|
|
+- return true;
|
|
|
+- }
|
|
|
+-
|
|
|
+- return false;
|
|
|
+-}
|
|
|
+-
|
|
|
+-#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
|
|
+-bool
|
|
|
+-WorkerLoadInfo::PrincipalIsValid() const
|
|
|
+-{
|
|
|
+- return mPrincipal && mPrincipalInfo &&
|
|
|
+- mPrincipalInfo->type() != PrincipalInfo::T__None &&
|
|
|
+- mPrincipalInfo->type() <= PrincipalInfo::T__Last;
|
|
|
+-}
|
|
|
+-
|
|
|
+-bool
|
|
|
+-WorkerLoadInfo::PrincipalURIMatchesScriptURL()
|
|
|
+-{
|
|
|
+- AssertIsOnMainThread();
|
|
|
+-
|
|
|
+- nsAutoCString scheme;
|
|
|
+- nsresult rv = mBaseURI->GetScheme(scheme);
|
|
|
+- NS_ENSURE_SUCCESS(rv, false);
|
|
|
+-
|
|
|
+- // A system principal must either be a blob URL or a resource JSM.
|
|
|
+- if (mPrincipal->GetIsSystemPrincipal()) {
|
|
|
+- if (scheme == NS_LITERAL_CSTRING("blob")) {
|
|
|
+- return true;
|
|
|
+- }
|
|
|
+-
|
|
|
+- bool isResource = false;
|
|
|
+- nsresult rv = NS_URIChainHasFlags(mBaseURI,
|
|
|
+- nsIProtocolHandler::URI_IS_UI_RESOURCE,
|
|
|
+- &isResource);
|
|
|
+- NS_ENSURE_SUCCESS(rv, false);
|
|
|
+-
|
|
|
+- return isResource;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // A null principal can occur for a data URL worker script or a blob URL
|
|
|
+- // worker script from a sandboxed iframe.
|
|
|
+- if (mPrincipal->GetIsNullPrincipal()) {
|
|
|
+- return scheme == NS_LITERAL_CSTRING("data") ||
|
|
|
+- scheme == NS_LITERAL_CSTRING("blob");
|
|
|
+- }
|
|
|
+-
|
|
|
+- // The principal for a blob: URL worker script does not have a matching URL.
|
|
|
+- // This is likely a bug in our referer setting logic, but exempt it for now.
|
|
|
+- // This is another reason we should fix bug 1340694 so that referer does not
|
|
|
+- // depend on the principal URI.
|
|
|
+- if (scheme == NS_LITERAL_CSTRING("blob")) {
|
|
|
+- return true;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIURI> principalURI;
|
|
|
+- rv = mPrincipal->GetURI(getter_AddRefs(principalURI));
|
|
|
+- NS_ENSURE_SUCCESS(rv, false);
|
|
|
+- NS_ENSURE_TRUE(principalURI, false);
|
|
|
+-
|
|
|
+- bool equal = false;
|
|
|
+- rv = principalURI->Equals(mBaseURI, &equal);
|
|
|
+- NS_ENSURE_SUCCESS(rv, false);
|
|
|
+-
|
|
|
+- return equal;
|
|
|
+-}
|
|
|
+-#endif // MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
|
|
+-
|
|
|
+-bool
|
|
|
+-WorkerLoadInfo::ProxyReleaseMainThreadObjects(WorkerPrivate* aWorkerPrivate)
|
|
|
+-{
|
|
|
+- nsCOMPtr<nsILoadGroup> nullLoadGroup;
|
|
|
+- return ProxyReleaseMainThreadObjects(aWorkerPrivate, nullLoadGroup);
|
|
|
+-}
|
|
|
+-
|
|
|
+-bool
|
|
|
+-WorkerLoadInfo::ProxyReleaseMainThreadObjects(WorkerPrivate* aWorkerPrivate,
|
|
|
+- nsCOMPtr<nsILoadGroup>& aLoadGroupToCancel)
|
|
|
+-{
|
|
|
+-
|
|
|
+- static const uint32_t kDoomedCount = 11;
|
|
|
+- nsTArray<nsCOMPtr<nsISupports>> doomed(kDoomedCount);
|
|
|
+-
|
|
|
+- SwapToISupportsArray(mWindow, doomed);
|
|
|
+- SwapToISupportsArray(mScriptContext, doomed);
|
|
|
+- SwapToISupportsArray(mBaseURI, doomed);
|
|
|
+- SwapToISupportsArray(mResolvedScriptURI, doomed);
|
|
|
+- SwapToISupportsArray(mPrincipal, doomed);
|
|
|
+- SwapToISupportsArray(mLoadingPrincipal, doomed);
|
|
|
+- SwapToISupportsArray(mChannel, doomed);
|
|
|
+- SwapToISupportsArray(mCSP, doomed);
|
|
|
+- SwapToISupportsArray(mLoadGroup, doomed);
|
|
|
+- SwapToISupportsArray(mLoadFailedAsyncRunnable, doomed);
|
|
|
+- SwapToISupportsArray(mInterfaceRequestor, doomed);
|
|
|
+- // Before adding anything here update kDoomedCount above!
|
|
|
+-
|
|
|
+- MOZ_ASSERT(doomed.Length() == kDoomedCount);
|
|
|
+-
|
|
|
+- RefPtr<MainThreadReleaseRunnable> runnable =
|
|
|
+- new MainThreadReleaseRunnable(doomed, aLoadGroupToCancel);
|
|
|
+- return NS_SUCCEEDED(aWorkerPrivate->DispatchToMainThread(runnable.forget()));
|
|
|
+-}
|
|
|
+-
|
|
|
+ template <class Derived>
|
|
|
+ class WorkerPrivateParent<Derived>::EventTarget final
|
|
|
+ : public nsISerialEventTarget
|
|
|
+ {
|
|
|
+ // This mutex protects mWorkerPrivate and must be acquired *before* the
|
|
|
+ // WorkerPrivate's mutex whenever they must both be held.
|
|
|
+ mozilla::Mutex mMutex;
|
|
|
+ WorkerPrivate* mWorkerPrivate;
|
|
|
+@@ -2033,130 +1631,16 @@ public:
|
|
|
+ NS_DECL_THREADSAFE_ISUPPORTS
|
|
|
+ NS_DECL_NSIEVENTTARGET_FULL
|
|
|
+
|
|
|
+ private:
|
|
|
+ ~EventTarget()
|
|
|
+ { }
|
|
|
+ };
|
|
|
+
|
|
|
+-WorkerLoadInfo::
|
|
|
+-InterfaceRequestor::InterfaceRequestor(nsIPrincipal* aPrincipal,
|
|
|
+- nsILoadGroup* aLoadGroup)
|
|
|
+-{
|
|
|
+- MOZ_ASSERT(NS_IsMainThread());
|
|
|
+- MOZ_ASSERT(aPrincipal);
|
|
|
+-
|
|
|
+- // Look for an existing LoadContext. This is optional and it's ok if
|
|
|
+- // we don't find one.
|
|
|
+- nsCOMPtr<nsILoadContext> baseContext;
|
|
|
+- if (aLoadGroup) {
|
|
|
+- nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
|
|
+- aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
|
|
+- if (callbacks) {
|
|
|
+- callbacks->GetInterface(NS_GET_IID(nsILoadContext),
|
|
|
+- getter_AddRefs(baseContext));
|
|
|
+- }
|
|
|
+- mOuterRequestor = callbacks;
|
|
|
+- }
|
|
|
+-
|
|
|
+- mLoadContext = new LoadContext(aPrincipal, baseContext);
|
|
|
+-}
|
|
|
+-
|
|
|
+-void
|
|
|
+-WorkerLoadInfo::
|
|
|
+-InterfaceRequestor::MaybeAddTabChild(nsILoadGroup* aLoadGroup)
|
|
|
+-{
|
|
|
+- MOZ_ASSERT(NS_IsMainThread());
|
|
|
+-
|
|
|
+- if (!aLoadGroup) {
|
|
|
+- return;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
|
|
+- aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
|
|
+- if (!callbacks) {
|
|
|
+- return;
|
|
|
+- }
|
|
|
+-
|
|
|
+- nsCOMPtr<nsITabChild> tabChild;
|
|
|
+- callbacks->GetInterface(NS_GET_IID(nsITabChild), getter_AddRefs(tabChild));
|
|
|
+- if (!tabChild) {
|
|
|
+- return;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // Use weak references to the tab child. Holding a strong reference will
|
|
|
+- // not prevent an ActorDestroy() from being called on the TabChild.
|
|
|
+- // Therefore, we should let the TabChild destroy itself as soon as possible.
|
|
|
+- mTabChildList.AppendElement(do_GetWeakReference(tabChild));
|
|
|
+-}
|
|
|
+-
|
|
|
+-NS_IMETHODIMP
|
|
|
+-WorkerLoadInfo::
|
|
|
+-InterfaceRequestor::GetInterface(const nsIID& aIID, void** aSink)
|
|
|
+-{
|
|
|
+- MOZ_ASSERT(NS_IsMainThread());
|
|
|
+- MOZ_ASSERT(mLoadContext);
|
|
|
+-
|
|
|
+- if (aIID.Equals(NS_GET_IID(nsILoadContext))) {
|
|
|
+- nsCOMPtr<nsILoadContext> ref = mLoadContext;
|
|
|
+- ref.forget(aSink);
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- // If we still have an active nsITabChild, then return it. Its possible,
|
|
|
+- // though, that all of the TabChild objects have been destroyed. In that
|
|
|
+- // case we return NS_NOINTERFACE.
|
|
|
+- if (aIID.Equals(NS_GET_IID(nsITabChild))) {
|
|
|
+- nsCOMPtr<nsITabChild> tabChild = GetAnyLiveTabChild();
|
|
|
+- if (!tabChild) {
|
|
|
+- return NS_NOINTERFACE;
|
|
|
+- }
|
|
|
+- tabChild.forget(aSink);
|
|
|
+- return NS_OK;
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (aIID.Equals(NS_GET_IID(nsINetworkInterceptController)) &&
|
|
|
+- mOuterRequestor) {
|
|
|
+- // If asked for the network intercept controller, ask the outer requestor,
|
|
|
+- // which could be the docshell.
|
|
|
+- return mOuterRequestor->GetInterface(aIID, aSink);
|
|
|
+- }
|
|
|
+-
|
|
|
+- return NS_NOINTERFACE;
|
|
|
+-}
|
|
|
+-
|
|
|
+-already_AddRefed<nsITabChild>
|
|
|
+-WorkerLoadInfo::
|
|
|
+-InterfaceRequestor::GetAnyLiveTabChild()
|
|
|
+-{
|
|
|
+- MOZ_ASSERT(NS_IsMainThread());
|
|
|
+-
|
|
|
+- // Search our list of known TabChild objects for one that still exists.
|
|
|
+- while (!mTabChildList.IsEmpty()) {
|
|
|
+- nsCOMPtr<nsITabChild> tabChild =
|
|
|
+- do_QueryReferent(mTabChildList.LastElement());
|
|
|
+-
|
|
|
+- // Does this tab child still exist? If so, return it. We are done. If the
|
|
|
+- // PBrowser actor is no longer useful, don't bother returning this tab.
|
|
|
+- if (tabChild && !static_cast<TabChild*>(tabChild.get())->IsDestroyed()) {
|
|
|
+- return tabChild.forget();
|
|
|
+- }
|
|
|
+-
|
|
|
+- // Otherwise remove the stale weak reference and check the next one
|
|
|
+- mTabChildList.RemoveElementAt(mTabChildList.Length() - 1);
|
|
|
+- }
|
|
|
+-
|
|
|
+- return nullptr;
|
|
|
+-}
|
|
|
+-
|
|
|
+-NS_IMPL_ADDREF(WorkerLoadInfo::InterfaceRequestor)
|
|
|
+-NS_IMPL_RELEASE(WorkerLoadInfo::InterfaceRequestor)
|
|
|
+-NS_IMPL_QUERY_INTERFACE(WorkerLoadInfo::InterfaceRequestor, nsIInterfaceRequestor)
|
|
|
+-
|
|
|
+ struct WorkerPrivate::TimeoutInfo
|
|
|
+ {
|
|
|
+ TimeoutInfo()
|
|
|
+ : mId(0), mIsInterval(false), mCanceled(false)
|
|
|
+ {
|
|
|
+ MOZ_COUNT_CTOR(mozilla::dom::workers::WorkerPrivate::TimeoutInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h
|
|
|
+--- a/dom/workers/WorkerPrivate.h
|
|
|
++++ b/dom/workers/WorkerPrivate.h
|
|
|
+@@ -3,16 +3,17 @@
|
|
|
+ /* 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_workers_workerprivate_h__
|
|
|
+ #define mozilla_dom_workers_workerprivate_h__
|
|
|
+
|
|
|
+ #include "WorkerCommon.h"
|
|
|
++#include "WorkerLoadInfo.h"
|
|
|
+
|
|
|
+ #include "js/CharacterEncoding.h"
|
|
|
+ #include "nsIContentPolicy.h"
|
|
|
+ #include "nsIContentSecurityPolicy.h"
|
|
|
+ #include "nsILoadGroup.h"
|
|
|
+ #include "nsIWorkerDebugger.h"
|
|
|
+ #include "nsPIDOMWindow.h"
|
|
|
+
|
|
|
+diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp
|
|
|
+--- a/dom/workers/WorkerScope.cpp
|
|
|
++++ b/dom/workers/WorkerScope.cpp
|
|
|
+@@ -5,16 +5,17 @@
|
|
|
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
+
|
|
|
+ #include "WorkerScope.h"
|
|
|
+
|
|
|
+ #include "jsapi.h"
|
|
|
+ #include "mozilla/EventListenerManager.h"
|
|
|
+ #include "mozilla/dom/BindingDeclarations.h"
|
|
|
+ #include "mozilla/dom/Clients.h"
|
|
|
++#include "mozilla/dom/ClientState.h"
|
|
|
+ #include "mozilla/dom/Console.h"
|
|
|
+ #include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h"
|
|
|
+ #include "mozilla/dom/DOMPrefs.h"
|
|
|
+ #include "mozilla/dom/Fetch.h"
|
|
|
+ #include "mozilla/dom/FunctionBinding.h"
|
|
|
+ #include "mozilla/dom/IDBFactory.h"
|
|
|
+ #include "mozilla/dom/ImageBitmap.h"
|
|
|
+ #include "mozilla/dom/ImageBitmapBinding.h"
|
|
|
+@@ -29,16 +30,17 @@
|
|
|
+ #include "mozilla/dom/WorkerLocation.h"
|
|
|
+ #include "mozilla/dom/WorkerNavigator.h"
|
|
|
+ #include "mozilla/dom/cache/CacheStorage.h"
|
|
|
+ #include "mozilla/Services.h"
|
|
|
+ #include "nsServiceManagerUtils.h"
|
|
|
+
|
|
|
+ #include "nsIDocument.h"
|
|
|
+ #include "nsIServiceWorkerManager.h"
|
|
|
++#include "nsIScriptError.h"
|
|
|
+ #include "nsIScriptTimeoutHandler.h"
|
|
|
+
|
|
|
+ #ifdef ANDROID
|
|
|
+ #include <android/log.h>
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #include "Crypto.h"
|
|
|
+ #include "Principal.h"
|
|
|
+diff --git a/dom/workers/moz.build b/dom/workers/moz.build
|
|
|
+--- a/dom/workers/moz.build
|
|
|
++++ b/dom/workers/moz.build
|
|
|
+@@ -16,16 +16,17 @@ EXPORTS.mozilla.dom += [
|
|
|
+ 'WorkerRunnable.h',
|
|
|
+ 'WorkerScope.h',
|
|
|
+ ]
|
|
|
+
|
|
|
+ EXPORTS.mozilla.dom.workers += [
|
|
|
+ 'RuntimeService.h',
|
|
|
+ 'WorkerCommon.h',
|
|
|
+ 'WorkerDebuggerManager.h',
|
|
|
++ 'WorkerLoadInfo.h',
|
|
|
+ ]
|
|
|
+
|
|
|
+ # Stuff needed for the bindings, not really public though.
|
|
|
+ EXPORTS.mozilla.dom.workers.bindings += [
|
|
|
+ 'SharedWorker.h',
|
|
|
+ 'WorkerHolder.h',
|
|
|
+ 'WorkerHolderToken.h',
|
|
|
+ ]
|
|
|
+@@ -44,16 +45,17 @@ UNIFIED_SOURCES += [
|
|
|
+ 'Principal.cpp',
|
|
|
+ 'RegisterBindings.cpp',
|
|
|
+ 'RuntimeService.cpp',
|
|
|
+ 'ScriptLoader.cpp',
|
|
|
+ 'SharedWorker.cpp',
|
|
|
+ 'WorkerDebuggerManager.cpp',
|
|
|
+ 'WorkerHolder.cpp',
|
|
|
+ 'WorkerHolderToken.cpp',
|
|
|
++ 'WorkerLoadInfo.cpp',
|
|
|
+ 'WorkerLocation.cpp',
|
|
|
+ 'WorkerNavigator.cpp',
|
|
|
+ 'WorkerPrivate.cpp',
|
|
|
+ 'WorkerRunnable.cpp',
|
|
|
+ 'WorkerScope.cpp',
|
|
|
+ 'WorkerThread.cpp',
|
|
|
+ ]
|
|
|
+
|