Commit dfe432e1 authored by Eden Chuang's avatar Eden Chuang
Browse files

Bug 1715547 - Remove ServiceWorkerContainer::Inner r=dom-worker-reviewers,asuth

parent 13f1fc0f
Loading
Loading
Loading
Loading
+0 −236
Original line number Diff line number Diff line
/* -*- 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 "RemoteServiceWorkerContainerImpl.h"

#include <utility>

#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "ServiceWorkerContainerChild.h"

namespace mozilla::dom {

using mozilla::ipc::BackgroundChild;
using mozilla::ipc::PBackgroundChild;
using mozilla::ipc::ResponseRejectReason;

RemoteServiceWorkerContainerImpl::~RemoteServiceWorkerContainerImpl() {
  Shutdown();
  MOZ_DIAGNOSTIC_ASSERT(!mOuter);
}

void RemoteServiceWorkerContainerImpl::Shutdown() {
  if (mShutdown) {
    return;
  }
  mShutdown = true;

  if (mActor) {
    mActor->RevokeOwner(this);
    mActor->MaybeStartTeardown();
    mActor = nullptr;
  }
}

void RemoteServiceWorkerContainerImpl::AddContainer(
    ServiceWorkerContainer* aOuter) {
  MOZ_DIAGNOSTIC_ASSERT(aOuter);
  MOZ_DIAGNOSTIC_ASSERT(!mOuter);
  mOuter = aOuter;
}

void RemoteServiceWorkerContainerImpl::RemoveContainer(
    ServiceWorkerContainer* aOuter) {
  MOZ_DIAGNOSTIC_ASSERT(aOuter);
  MOZ_DIAGNOSTIC_ASSERT(mOuter == aOuter);
  mOuter = nullptr;
}

void RemoteServiceWorkerContainerImpl::Register(
    const ClientInfo& aClientInfo, const nsACString& aScopeURL,
    const nsACString& aScriptURL, ServiceWorkerUpdateViaCache aUpdateViaCache,
    ServiceWorkerRegistrationCallback&& aSuccessCB,
    ServiceWorkerFailureCallback&& aFailureCB) const {
  if (!mActor) {
    CopyableErrorResult rv;
    rv.ThrowInvalidStateError("Can't register service worker");
    aFailureCB(std::move(rv));
    return;
  }

  mActor->SendRegister(
      aClientInfo.ToIPC(), nsCString(aScopeURL), nsCString(aScriptURL),
      aUpdateViaCache,
      [successCB = std::move(aSuccessCB), aFailureCB](
          const IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult&
              aResult) {
        if (aResult.type() ==
            IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult::
                TCopyableErrorResult) {
          // application layer error
          auto& rv = aResult.get_CopyableErrorResult();
          MOZ_DIAGNOSTIC_ASSERT(rv.Failed());
          aFailureCB(CopyableErrorResult(rv));
          return;
        }
        // success
        auto& ipcDesc = aResult.get_IPCServiceWorkerRegistrationDescriptor();
        successCB(ServiceWorkerRegistrationDescriptor(ipcDesc));
      },
      [aFailureCB](ResponseRejectReason&& aReason) {
        // IPC layer error
        CopyableErrorResult rv;
        rv.ThrowInvalidStateError("Failed to register service worker");
        aFailureCB(std::move(rv));
      });
}

void RemoteServiceWorkerContainerImpl::GetRegistration(
    const ClientInfo& aClientInfo, const nsACString& aURL,
    ServiceWorkerRegistrationCallback&& aSuccessCB,
    ServiceWorkerFailureCallback&& aFailureCB) const {
  if (!mActor) {
    aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
    return;
  }

  mActor->SendGetRegistration(
      aClientInfo.ToIPC(), nsCString(aURL),
      [successCB = std::move(aSuccessCB), aFailureCB](
          const IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult&
              aResult) {
        if (aResult.type() ==
            IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult::
                TCopyableErrorResult) {
          auto& rv = aResult.get_CopyableErrorResult();
          // If rv is a failure then this is an application layer error.  Note,
          // though, we also reject with NS_OK to indicate that we just didn't
          // find a registration.
          aFailureCB(CopyableErrorResult(rv));
          return;
        }
        // success
        auto& ipcDesc = aResult.get_IPCServiceWorkerRegistrationDescriptor();
        successCB(ServiceWorkerRegistrationDescriptor(ipcDesc));
      },
      [aFailureCB](ResponseRejectReason&& aReason) {
        // IPC layer error
        aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
      });
}

void RemoteServiceWorkerContainerImpl::GetRegistrations(
    const ClientInfo& aClientInfo,
    ServiceWorkerRegistrationListCallback&& aSuccessCB,
    ServiceWorkerFailureCallback&& aFailureCB) const {
  if (!mActor) {
    aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
    return;
  }

  mActor->SendGetRegistrations(
      aClientInfo.ToIPC(),
      [successCB = std::move(aSuccessCB), aFailureCB](
          const IPCServiceWorkerRegistrationDescriptorListOrCopyableErrorResult&
              aResult) {
        if (aResult.type() ==
            IPCServiceWorkerRegistrationDescriptorListOrCopyableErrorResult::
                TCopyableErrorResult) {
          // application layer error
          auto& rv = aResult.get_CopyableErrorResult();
          MOZ_DIAGNOSTIC_ASSERT(rv.Failed());
          aFailureCB(CopyableErrorResult(rv));
          return;
        }
        // success
        auto& ipcList =
            aResult.get_IPCServiceWorkerRegistrationDescriptorList();
        nsTArray<ServiceWorkerRegistrationDescriptor> list(
            ipcList.values().Length());
        for (auto& ipcDesc : ipcList.values()) {
          list.AppendElement(ServiceWorkerRegistrationDescriptor(ipcDesc));
        }
        successCB(std::move(list));
      },
      [aFailureCB](ResponseRejectReason&& aReason) {
        // IPC layer error
        aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
      });
}

void RemoteServiceWorkerContainerImpl::GetReady(
    const ClientInfo& aClientInfo,
    ServiceWorkerRegistrationCallback&& aSuccessCB,
    ServiceWorkerFailureCallback&& aFailureCB) const {
  if (!mActor) {
    aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
    return;
  }

  mActor->SendGetReady(
      aClientInfo.ToIPC(),
      [successCB = std::move(aSuccessCB), aFailureCB](
          const IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult&
              aResult) {
        if (aResult.type() ==
            IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult::
                TCopyableErrorResult) {
          // application layer error
          auto& rv = aResult.get_CopyableErrorResult();
          MOZ_DIAGNOSTIC_ASSERT(rv.Failed());
          aFailureCB(CopyableErrorResult(rv));
          return;
        }
        // success
        auto& ipcDesc = aResult.get_IPCServiceWorkerRegistrationDescriptor();
        successCB(ServiceWorkerRegistrationDescriptor(ipcDesc));
      },
      [aFailureCB](ResponseRejectReason&& aReason) {
        // IPC layer error
        aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
      });
}

RemoteServiceWorkerContainerImpl::RemoteServiceWorkerContainerImpl()
    : mOuter(nullptr), mShutdown(false) {
  PBackgroundChild* parentActor =
      BackgroundChild::GetOrCreateForCurrentThread();
  if (NS_WARN_IF(!parentActor)) {
    Shutdown();
    return;
  }

  RefPtr<ServiceWorkerContainerChild> actor =
      ServiceWorkerContainerChild::Create();
  if (NS_WARN_IF(!actor)) {
    Shutdown();
    return;
  }

  PServiceWorkerContainerChild* sentActor =
      parentActor->SendPServiceWorkerContainerConstructor(actor);
  if (NS_WARN_IF(!sentActor)) {
    Shutdown();
    return;
  }
  MOZ_DIAGNOSTIC_ASSERT(sentActor == actor);

  mActor = std::move(actor);
  mActor->SetOwner(this);
}

void RemoteServiceWorkerContainerImpl::RevokeActor(
    ServiceWorkerContainerChild* aActor) {
  MOZ_DIAGNOSTIC_ASSERT(mActor);
  MOZ_DIAGNOSTIC_ASSERT(mActor == aActor);
  mActor->RevokeOwner(this);
  mActor = nullptr;

  mShutdown = true;
}

}  // namespace mozilla::dom
+0 −61
Original line number Diff line number Diff line
/* -*- 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_remoteserviceworkercontainerimpl_h__
#define mozilla_dom_remoteserviceworkercontainerimpl_h__

#include "ServiceWorkerContainer.h"

namespace mozilla::dom {

class ServiceWorkerContainerChild;

class RemoteServiceWorkerContainerImpl final
    : public ServiceWorkerContainer::Inner {
  RefPtr<ServiceWorkerContainerChild> mActor;
  ServiceWorkerContainer* mOuter;
  bool mShutdown;

  ~RemoteServiceWorkerContainerImpl();

  void Shutdown();

  // ServiceWorkerContainer::Inner implementation
  void AddContainer(ServiceWorkerContainer* aOuter) override;

  void RemoveContainer(ServiceWorkerContainer* aOuter) override;

  void Register(const ClientInfo& aClientInfo, const nsACString& aScopeURL,
                const nsACString& aScriptURL,
                ServiceWorkerUpdateViaCache aUpdateViaCache,
                ServiceWorkerRegistrationCallback&& aSuccessCB,
                ServiceWorkerFailureCallback&& aFailureCB) const override;

  void GetRegistration(
      const ClientInfo& aClientInfo, const nsACString& aURL,
      ServiceWorkerRegistrationCallback&& aSuccessCB,
      ServiceWorkerFailureCallback&& aFailureCB) const override;

  void GetRegistrations(
      const ClientInfo& aClientInfo,
      ServiceWorkerRegistrationListCallback&& aSuccessCB,
      ServiceWorkerFailureCallback&& aFailureCB) const override;

  void GetReady(const ClientInfo& aClientInfo,
                ServiceWorkerRegistrationCallback&& aSuccessCB,
                ServiceWorkerFailureCallback&& aFailureCB) const override;

 public:
  RemoteServiceWorkerContainerImpl();

  void RevokeActor(ServiceWorkerContainerChild* aActor);

  NS_INLINE_DECL_REFCOUNTING(RemoteServiceWorkerContainerImpl, override)
};

}  // namespace mozilla::dom

#endif  // mozilla_dom_remoteserviceworkercontainerimpl_h__
+191 −46
Original line number Diff line number Diff line
@@ -34,10 +34,12 @@
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ServiceWorker.h"
#include "mozilla/dom/ServiceWorkerContainerBinding.h"
#include "mozilla/dom/ServiceWorkerContainerChild.h"
#include "mozilla/dom/ServiceWorkerManager.h"
#include "mozilla/dom/ipc/StructuredCloneData.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"

#include "RemoteServiceWorkerContainerImpl.h"
#include "ServiceWorker.h"
#include "ServiceWorkerRegistration.h"
#include "ServiceWorkerUtils.h"
@@ -49,6 +51,10 @@

namespace mozilla::dom {

using mozilla::ipc::BackgroundChild;
using mozilla::ipc::PBackgroundChild;
using mozilla::ipc::ResponseRejectReason;

NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerContainer)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)

@@ -61,26 +67,44 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper,
// static
already_AddRefed<ServiceWorkerContainer> ServiceWorkerContainer::Create(
    nsIGlobalObject* aGlobal) {
  RefPtr<Inner> inner = new RemoteServiceWorkerContainerImpl();
  RefPtr<ServiceWorkerContainer> ref =
      new ServiceWorkerContainer(aGlobal, inner.forget());
  RefPtr<ServiceWorkerContainer> ref = new ServiceWorkerContainer(aGlobal);
  return ref.forget();
}

ServiceWorkerContainer::ServiceWorkerContainer(
    nsIGlobalObject* aGlobal,
    already_AddRefed<ServiceWorkerContainer::Inner> aInner)
    : DOMEventTargetHelper(aGlobal), mInner(aInner) {
  mInner->AddContainer(this);
ServiceWorkerContainer::ServiceWorkerContainer(nsIGlobalObject* aGlobal)
    : DOMEventTargetHelper(aGlobal), mShutdown(false) {
  PBackgroundChild* parentActor =
      BackgroundChild::GetOrCreateForCurrentThread();
  if (NS_WARN_IF(!parentActor)) {
    Shutdown();
    return;
  }

  RefPtr<ServiceWorkerContainerChild> actor =
      ServiceWorkerContainerChild::Create();
  if (NS_WARN_IF(!actor)) {
    Shutdown();
    return;
  }

  PServiceWorkerContainerChild* sentActor =
      parentActor->SendPServiceWorkerContainerConstructor(actor);
  if (NS_WARN_IF(!sentActor)) {
    Shutdown();
    return;
  }
  MOZ_DIAGNOSTIC_ASSERT(sentActor == actor);

  mActor = std::move(actor);
  mActor->SetOwner(this);

  Maybe<ServiceWorkerDescriptor> controller = aGlobal->GetController();
  if (controller.isSome()) {
    mControllerWorker = aGlobal->GetOrCreateServiceWorker(controller.ref());
  }
}

ServiceWorkerContainer::~ServiceWorkerContainer() {
  mInner->RemoveContainer(this);
}
ServiceWorkerContainer::~ServiceWorkerContainer() { Shutdown(); }

void ServiceWorkerContainer::DisconnectFromOwner() {
  mControllerWorker = nullptr;
@@ -128,6 +152,15 @@ void ServiceWorkerContainer::ReceiveMessage(
  }
}

void ServiceWorkerContainer::RevokeActor(ServiceWorkerContainerChild* aActor) {
  MOZ_DIAGNOSTIC_ASSERT(mActor);
  MOZ_DIAGNOSTIC_ASSERT(mActor == aActor);
  mActor->RevokeOwner(this);
  mActor = nullptr;

  mShutdown = true;
}

JSObject* ServiceWorkerContainer::WrapObject(
    JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
  return ServiceWorkerContainer_Binding::Wrap(aCx, this, aGivenProto);
@@ -331,10 +364,29 @@ already_AddRefed<Promise> ServiceWorkerContainer::Register(

  RefPtr<ServiceWorkerContainer> self = this;

  mInner->Register(
      clientInfo.ref(), cleanedScopeURL, cleanedScriptURL,
      aOptions.mUpdateViaCache,
      [self, outer](const ServiceWorkerRegistrationDescriptor& aDesc) {
  if (!mActor) {
    aRv.ThrowInvalidStateError("Can't register service worker");
    return nullptr;
  }

  mActor->SendRegister(
      clientInfo.ref().ToIPC(), nsCString(cleanedScopeURL),
      nsCString(cleanedScriptURL), aOptions.mUpdateViaCache,
      [self,
       outer](const IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult&
                  aResult) {
        if (aResult.type() ==
            IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult::
                TCopyableErrorResult) {
          // application layer error
          CopyableErrorResult rv = aResult.get_CopyableErrorResult();
          MOZ_DIAGNOSTIC_ASSERT(rv.Failed());
          outer->MaybeReject(std::move(rv));
          return;
        }
        // success
        const auto& ipcDesc =
            aResult.get_IPCServiceWorkerRegistrationDescriptor();
        ErrorResult rv;
        nsIGlobalObject* global = self->GetGlobalIfValid(rv);
        if (rv.Failed()) {
@@ -342,10 +394,16 @@ already_AddRefed<Promise> ServiceWorkerContainer::Register(
          return;
        }
        RefPtr<ServiceWorkerRegistration> reg =
            global->GetOrCreateServiceWorkerRegistration(aDesc);
            global->GetOrCreateServiceWorkerRegistration(
                ServiceWorkerRegistrationDescriptor(ipcDesc));
        outer->MaybeResolve(reg);
      },
      [outer](ErrorResult&& aRv) { outer->MaybeReject(std::move(aRv)); });
      [outer](ResponseRejectReason&& aReason) {
        // IPC layer error
        CopyableErrorResult rv;
        rv.ThrowInvalidStateError("Failed to register service worker");
        outer->MaybeReject(std::move(rv));
      });

  return outer.forget();
}
@@ -381,10 +439,34 @@ already_AddRefed<Promise> ServiceWorkerContainer::GetRegistrations(

  RefPtr<ServiceWorkerContainer> self = this;

  mInner->GetRegistrations(
      clientInfo.ref(),
      [self,
       outer](const nsTArray<ServiceWorkerRegistrationDescriptor>& aDescList) {
  if (!mActor) {
    outer->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
    return outer.forget();
  }

  mActor->SendGetRegistrations(
      clientInfo.ref().ToIPC(),
      [self, outer](
          const IPCServiceWorkerRegistrationDescriptorListOrCopyableErrorResult&
              aResult) {
        if (aResult.type() ==
            IPCServiceWorkerRegistrationDescriptorListOrCopyableErrorResult::
                TCopyableErrorResult) {
          // application layer error
          const auto& rv = aResult.get_CopyableErrorResult();
          MOZ_DIAGNOSTIC_ASSERT(rv.Failed());
          outer->MaybeReject(CopyableErrorResult(rv));
          return;
        }
        // success
        const auto& ipcList =
            aResult.get_IPCServiceWorkerRegistrationDescriptorList();
        nsTArray<ServiceWorkerRegistrationDescriptor> list(
            ipcList.values().Length());
        for (const auto& ipcDesc : ipcList.values()) {
          list.AppendElement(ServiceWorkerRegistrationDescriptor(ipcDesc));
        }

        ErrorResult rv;
        nsIGlobalObject* global = self->GetGlobalIfValid(rv);
        if (rv.Failed()) {
@@ -392,7 +474,7 @@ already_AddRefed<Promise> ServiceWorkerContainer::GetRegistrations(
          return;
        }
        nsTArray<RefPtr<ServiceWorkerRegistration>> regList;
        for (auto& desc : aDescList) {
        for (auto& desc : list) {
          RefPtr<ServiceWorkerRegistration> reg =
              global->GetOrCreateServiceWorkerRegistration(desc);
          if (reg) {
@@ -401,7 +483,10 @@ already_AddRefed<Promise> ServiceWorkerContainer::GetRegistrations(
        }
        outer->MaybeResolve(regList);
      },
      [self, outer](ErrorResult&& aRv) { outer->MaybeReject(std::move(aRv)); });
      [outer](ResponseRejectReason&& aReason) {
        // IPC layer error
        outer->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
      });

  return outer.forget();
}
@@ -457,9 +542,38 @@ already_AddRefed<Promise> ServiceWorkerContainer::GetRegistration(

  RefPtr<ServiceWorkerContainer> self = this;

  mInner->GetRegistration(
      clientInfo.ref(), spec,
      [self, outer](const ServiceWorkerRegistrationDescriptor& aDescriptor) {
  if (!mActor) {
    outer->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
    return outer.forget();
  }

  mActor->SendGetRegistration(
      clientInfo.ref().ToIPC(), spec,
      [self,
       outer](const IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult&
                  aResult) {
        if (aResult.type() ==
            IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult::
                TCopyableErrorResult) {
          CopyableErrorResult ipcRv(aResult.get_CopyableErrorResult());
          ErrorResult rv(std::move(ipcRv));
          if (!rv.Failed()) {
            // ErrorResult rv;
            //  If rv is a failure then this is an application layer error.
            //  Note, though, we also reject with NS_OK to indicate that we just
            //  didn't find a registration.
            Unused << self->GetGlobalIfValid(rv);
            if (!rv.Failed()) {
              outer->MaybeResolveWithUndefined();
              return;
            }
          }
          outer->MaybeReject(std::move(rv));
          return;
        }
        // success
        const auto& ipcDesc =
            aResult.get_IPCServiceWorkerRegistrationDescriptor();
        ErrorResult rv;
        nsIGlobalObject* global = self->GetGlobalIfValid(rv);
        if (rv.Failed()) {
@@ -467,20 +581,14 @@ already_AddRefed<Promise> ServiceWorkerContainer::GetRegistration(
          return;
        }
        RefPtr<ServiceWorkerRegistration> reg =
            global->GetOrCreateServiceWorkerRegistration(aDescriptor);
            global->GetOrCreateServiceWorkerRegistration(
                ServiceWorkerRegistrationDescriptor(ipcDesc));
        outer->MaybeResolve(reg);
      },
      [self, outer](ErrorResult&& aRv) {
        if (!aRv.Failed()) {
          Unused << self->GetGlobalIfValid(aRv);
          if (!aRv.Failed()) {
            outer->MaybeResolveWithUndefined();
            return;
          }
        }
        outer->MaybeReject(std::move(aRv));
      [self, outer](ResponseRejectReason&& aReason) {
        // IPC layer error
        outer->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
      });

  return outer.forget();
}

@@ -510,9 +618,29 @@ Promise* ServiceWorkerContainer::GetReady(ErrorResult& aRv) {
  RefPtr<ServiceWorkerContainer> self = this;
  RefPtr<Promise> outer = mReadyPromise;

  mInner->GetReady(
      clientInfo.ref(),
      [self, outer](const ServiceWorkerRegistrationDescriptor& aDescriptor) {
  if (!mActor) {
    mReadyPromise->MaybeReject(
        CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
    return mReadyPromise;
  }

  mActor->SendGetReady(
      clientInfo.ref().ToIPC(),
      [self,
       outer](const IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult&
                  aResult) {
        if (aResult.type() ==
            IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult::
                TCopyableErrorResult) {
          // application layer error
          CopyableErrorResult rv(aResult.get_CopyableErrorResult());
          MOZ_DIAGNOSTIC_ASSERT(rv.Failed());
          outer->MaybeReject(std::move(rv));
          return;
        }
        // success
        const auto& ipcDesc =
            aResult.get_IPCServiceWorkerRegistrationDescriptor();
        ErrorResult rv;
        nsIGlobalObject* global = self->GetGlobalIfValid(rv);
        if (rv.Failed()) {
@@ -520,17 +648,21 @@ Promise* ServiceWorkerContainer::GetReady(ErrorResult& aRv) {
          return;
        }
        RefPtr<ServiceWorkerRegistration> reg =
            global->GetOrCreateServiceWorkerRegistration(aDescriptor);
            global->GetOrCreateServiceWorkerRegistration(
                ServiceWorkerRegistrationDescriptor(ipcDesc));
        NS_ENSURE_TRUE_VOID(reg);

        // Don't resolve the ready promise until the registration has
        // reached the right version.  This ensures that the active
        // worker property is set correctly on the registration.
        reg->WhenVersionReached(
            aDescriptor.Version(),
            [outer, reg](bool aResult) { outer->MaybeResolve(reg); });
        reg->WhenVersionReached(ipcDesc.version(), [outer, reg](bool aResult) {
          outer->MaybeResolve(reg);
        });
      },
      [self, outer](ErrorResult&& aRv) { outer->MaybeReject(std::move(aRv)); });
      [outer](ResponseRejectReason&& aReason) {
        // IPC layer error
        outer->MaybeReject(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
      });

  return mReadyPromise;
}
@@ -744,4 +876,17 @@ Result<Ok, bool> ServiceWorkerContainer::FillInMessageEventInit(
  return Ok();
}

void ServiceWorkerContainer::Shutdown() {
  if (mShutdown) {
    return;
  }
  mShutdown = true;

  if (mActor) {
    mActor->RevokeOwner(this);
    mActor->MaybeStartTeardown();
    mActor = nullptr;
  }
}

}  // namespace mozilla::dom
+8 −34
Original line number Diff line number Diff line
@@ -20,40 +20,11 @@ struct MessageEventInit;
class Promise;
struct RegistrationOptions;
class ServiceWorker;
class ServiceWorkerContainerChild;

// Lightweight serviceWorker APIs collection.
class ServiceWorkerContainer final : public DOMEventTargetHelper {
 public:
  class Inner {
   public:
    virtual void AddContainer(ServiceWorkerContainer* aOuter) = 0;

    virtual void RemoveContainer(ServiceWorkerContainer* aOuter) = 0;

    virtual void Register(const ClientInfo& aClientInfo,
                          const nsACString& aScopeURL,
                          const nsACString& aScriptURL,
                          ServiceWorkerUpdateViaCache aUpdateViaCache,
                          ServiceWorkerRegistrationCallback&& aSuccessCB,
                          ServiceWorkerFailureCallback&& aFailureCB) const = 0;

    virtual void GetRegistration(
        const ClientInfo& aClientInfo, const nsACString& aURL,
        ServiceWorkerRegistrationCallback&& aSuccessCB,
        ServiceWorkerFailureCallback&& aFailureCB) const = 0;

    virtual void GetRegistrations(
        const ClientInfo& aClientInfo,
        ServiceWorkerRegistrationListCallback&& aSuccessCB,
        ServiceWorkerFailureCallback&& aFailureCB) const = 0;

    virtual void GetReady(const ClientInfo& aClientInfo,
                          ServiceWorkerRegistrationCallback&& aSuccessCB,
                          ServiceWorkerFailureCallback&& aFailureCB) const = 0;

    NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
  };

  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerContainer,
                                           DOMEventTargetHelper)
@@ -109,10 +80,10 @@ class ServiceWorkerContainer final : public DOMEventTargetHelper {

  void ReceiveMessage(const ClientPostMessageArgs& aArgs);

  void RevokeActor(ServiceWorkerContainerChild* aActor);

 private:
  ServiceWorkerContainer(
      nsIGlobalObject* aGlobal,
      already_AddRefed<ServiceWorkerContainer::Inner> aInner);
  explicit ServiceWorkerContainer(nsIGlobalObject* aGlobal);

  ~ServiceWorkerContainer();

@@ -147,7 +118,10 @@ class ServiceWorkerContainer final : public DOMEventTargetHelper {
                                                 MessageEventInit& aInit,
                                                 ErrorResult& aRv);

  RefPtr<Inner> mInner;
  void Shutdown();

  RefPtr<ServiceWorkerContainerChild> mActor;
  bool mShutdown;

  // This only changes when a worker hijacks everything in its scope by calling
  // claim.
+3 −5
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@
#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/dom/WorkerRef.h"

#include "RemoteServiceWorkerContainerImpl.h"
#include "ServiceWorkerContainer.h"
#include "ServiceWorkerContainerChild.h"

namespace mozilla::dom {
@@ -48,15 +48,13 @@ ServiceWorkerContainerChild::Create() {
ServiceWorkerContainerChild::ServiceWorkerContainerChild()
    : mOwner(nullptr), mTeardownStarted(false) {}

void ServiceWorkerContainerChild::SetOwner(
    RemoteServiceWorkerContainerImpl* aOwner) {
void ServiceWorkerContainerChild::SetOwner(ServiceWorkerContainer* aOwner) {
  MOZ_DIAGNOSTIC_ASSERT(!mOwner);
  MOZ_DIAGNOSTIC_ASSERT(aOwner);
  mOwner = aOwner;
}

void ServiceWorkerContainerChild::RevokeOwner(
    RemoteServiceWorkerContainerImpl* aOwner) {
void ServiceWorkerContainerChild::RevokeOwner(ServiceWorkerContainer* aOwner) {
  MOZ_DIAGNOSTIC_ASSERT(mOwner);
  MOZ_DIAGNOSTIC_ASSERT(aOwner == mOwner);
  mOwner = nullptr;
Loading