summaryrefslogtreecommitdiffstats
path: root/dom/workers/ServiceWorkerInfo.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /dom/workers/ServiceWorkerInfo.cpp
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/workers/ServiceWorkerInfo.cpp')
-rw-r--r--dom/workers/ServiceWorkerInfo.cpp229
1 files changed, 229 insertions, 0 deletions
diff --git a/dom/workers/ServiceWorkerInfo.cpp b/dom/workers/ServiceWorkerInfo.cpp
new file mode 100644
index 000000000..fa08b97a6
--- /dev/null
+++ b/dom/workers/ServiceWorkerInfo.cpp
@@ -0,0 +1,229 @@
+/* -*- 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 "ServiceWorkerInfo.h"
+
+#include "ServiceWorkerScriptCache.h"
+
+BEGIN_WORKERS_NAMESPACE
+
+static_assert(nsIServiceWorkerInfo::STATE_INSTALLING == static_cast<uint16_t>(ServiceWorkerState::Installing),
+ "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
+static_assert(nsIServiceWorkerInfo::STATE_INSTALLED == static_cast<uint16_t>(ServiceWorkerState::Installed),
+ "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
+static_assert(nsIServiceWorkerInfo::STATE_ACTIVATING == static_cast<uint16_t>(ServiceWorkerState::Activating),
+ "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
+static_assert(nsIServiceWorkerInfo::STATE_ACTIVATED == static_cast<uint16_t>(ServiceWorkerState::Activated),
+ "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
+static_assert(nsIServiceWorkerInfo::STATE_REDUNDANT == static_cast<uint16_t>(ServiceWorkerState::Redundant),
+ "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
+static_assert(nsIServiceWorkerInfo::STATE_UNKNOWN == static_cast<uint16_t>(ServiceWorkerState::EndGuard_),
+ "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
+
+NS_IMPL_ISUPPORTS(ServiceWorkerInfo, nsIServiceWorkerInfo)
+
+NS_IMETHODIMP
+ServiceWorkerInfo::GetScriptSpec(nsAString& aScriptSpec)
+{
+ AssertIsOnMainThread();
+ CopyUTF8toUTF16(mScriptSpec, aScriptSpec);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ServiceWorkerInfo::GetCacheName(nsAString& aCacheName)
+{
+ AssertIsOnMainThread();
+ aCacheName = mCacheName;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ServiceWorkerInfo::GetState(uint16_t* aState)
+{
+ MOZ_ASSERT(aState);
+ AssertIsOnMainThread();
+ *aState = static_cast<uint16_t>(mState);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ServiceWorkerInfo::GetDebugger(nsIWorkerDebugger** aResult)
+{
+ if (NS_WARN_IF(!aResult)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return mServiceWorkerPrivate->GetDebugger(aResult);
+}
+
+NS_IMETHODIMP
+ServiceWorkerInfo::AttachDebugger()
+{
+ return mServiceWorkerPrivate->AttachDebugger();
+}
+
+NS_IMETHODIMP
+ServiceWorkerInfo::DetachDebugger()
+{
+ return mServiceWorkerPrivate->DetachDebugger();
+}
+
+void
+ServiceWorkerInfo::AppendWorker(ServiceWorker* aWorker)
+{
+ MOZ_ASSERT(aWorker);
+#ifdef DEBUG
+ nsAutoString workerURL;
+ aWorker->GetScriptURL(workerURL);
+ MOZ_ASSERT(workerURL.Equals(NS_ConvertUTF8toUTF16(mScriptSpec)));
+#endif
+ MOZ_ASSERT(!mInstances.Contains(aWorker));
+
+ mInstances.AppendElement(aWorker);
+ aWorker->SetState(State());
+}
+
+void
+ServiceWorkerInfo::RemoveWorker(ServiceWorker* aWorker)
+{
+ MOZ_ASSERT(aWorker);
+#ifdef DEBUG
+ nsAutoString workerURL;
+ aWorker->GetScriptURL(workerURL);
+ MOZ_ASSERT(workerURL.Equals(NS_ConvertUTF8toUTF16(mScriptSpec)));
+#endif
+ MOZ_ASSERT(mInstances.Contains(aWorker));
+
+ mInstances.RemoveElement(aWorker);
+}
+
+namespace {
+
+class ChangeStateUpdater final : public Runnable
+{
+public:
+ ChangeStateUpdater(const nsTArray<ServiceWorker*>& aInstances,
+ ServiceWorkerState aState)
+ : mState(aState)
+ {
+ for (size_t i = 0; i < aInstances.Length(); ++i) {
+ mInstances.AppendElement(aInstances[i]);
+ }
+ }
+
+ NS_IMETHOD Run() override
+ {
+ // We need to update the state of all instances atomically before notifying
+ // them to make sure that the observed state for all instances inside
+ // statechange event handlers is correct.
+ for (size_t i = 0; i < mInstances.Length(); ++i) {
+ mInstances[i]->SetState(mState);
+ }
+ for (size_t i = 0; i < mInstances.Length(); ++i) {
+ mInstances[i]->DispatchStateChange(mState);
+ }
+
+ return NS_OK;
+ }
+
+private:
+ AutoTArray<RefPtr<ServiceWorker>, 1> mInstances;
+ ServiceWorkerState mState;
+};
+
+}
+
+void
+ServiceWorkerInfo::UpdateState(ServiceWorkerState aState)
+{
+ AssertIsOnMainThread();
+#ifdef DEBUG
+ // Any state can directly transition to redundant, but everything else is
+ // ordered.
+ if (aState != ServiceWorkerState::Redundant) {
+ MOZ_ASSERT_IF(mState == ServiceWorkerState::EndGuard_, aState == ServiceWorkerState::Installing);
+ MOZ_ASSERT_IF(mState == ServiceWorkerState::Installing, aState == ServiceWorkerState::Installed);
+ MOZ_ASSERT_IF(mState == ServiceWorkerState::Installed, aState == ServiceWorkerState::Activating);
+ MOZ_ASSERT_IF(mState == ServiceWorkerState::Activating, aState == ServiceWorkerState::Activated);
+ }
+ // Activated can only go to redundant.
+ MOZ_ASSERT_IF(mState == ServiceWorkerState::Activated, aState == ServiceWorkerState::Redundant);
+#endif
+ // Flush any pending functional events to the worker when it transitions to the
+ // activated state.
+ // TODO: Do we care that these events will race with the propagation of the
+ // state change?
+ if (aState == ServiceWorkerState::Activated && mState != aState) {
+ mServiceWorkerPrivate->Activated();
+ }
+ mState = aState;
+ nsCOMPtr<nsIRunnable> r = new ChangeStateUpdater(mInstances, mState);
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r.forget()));
+ if (mState == ServiceWorkerState::Redundant) {
+ serviceWorkerScriptCache::PurgeCache(mPrincipal, mCacheName);
+ }
+}
+
+ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal,
+ const nsACString& aScope,
+ const nsACString& aScriptSpec,
+ const nsAString& aCacheName)
+ : mPrincipal(aPrincipal)
+ , mScope(aScope)
+ , mScriptSpec(aScriptSpec)
+ , mCacheName(aCacheName)
+ , mState(ServiceWorkerState::EndGuard_)
+ , mServiceWorkerID(GetNextID())
+ , mServiceWorkerPrivate(new ServiceWorkerPrivate(this))
+ , mSkipWaitingFlag(false)
+{
+ MOZ_ASSERT(mPrincipal);
+ // cache origin attributes so we can use them off main thread
+ mOriginAttributes = BasePrincipal::Cast(mPrincipal)->OriginAttributesRef();
+ MOZ_ASSERT(!mScope.IsEmpty());
+ MOZ_ASSERT(!mScriptSpec.IsEmpty());
+ MOZ_ASSERT(!mCacheName.IsEmpty());
+}
+
+ServiceWorkerInfo::~ServiceWorkerInfo()
+{
+ MOZ_ASSERT(mServiceWorkerPrivate);
+ mServiceWorkerPrivate->NoteDeadServiceWorkerInfo();
+}
+
+static uint64_t gServiceWorkerInfoCurrentID = 0;
+
+uint64_t
+ServiceWorkerInfo::GetNextID() const
+{
+ return ++gServiceWorkerInfoCurrentID;
+}
+
+already_AddRefed<ServiceWorker>
+ServiceWorkerInfo::GetOrCreateInstance(nsPIDOMWindowInner* aWindow)
+{
+ AssertIsOnMainThread();
+ MOZ_ASSERT(aWindow);
+
+ RefPtr<ServiceWorker> ref;
+
+ for (uint32_t i = 0; i < mInstances.Length(); ++i) {
+ MOZ_ASSERT(mInstances[i]);
+ if (mInstances[i]->GetOwner() == aWindow) {
+ ref = mInstances[i];
+ break;
+ }
+ }
+
+ if (!ref) {
+ ref = new ServiceWorker(aWindow, this);
+ }
+
+ return ref.forget();
+}
+
+END_WORKERS_NAMESPACE