mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 20:30:41 +00:00
merge mozilla-central to mozilla-inbound. r=merge a=merge
This commit is contained in:
commit
485b73669c
@ -3,4 +3,4 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MOZ_APP_DISPLAYNAME="Firefox Nightly"
|
||||
MOZ_MACBUNDLE_ID=nightly
|
||||
MOZ_MACBUNDLE_ID=firefoxnightly
|
||||
|
@ -155,7 +155,6 @@
|
||||
#include "mozIAsyncFavicons.h"
|
||||
#endif
|
||||
#include "nsINetworkPredictor.h"
|
||||
#include "nsIServiceWorkerManager.h"
|
||||
|
||||
// Editor-related
|
||||
#include "nsIEditingSession.h"
|
||||
@ -3418,7 +3417,7 @@ nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal)
|
||||
// Don't pre-allocate the client when we are sandboxed. The inherited
|
||||
// principal does not take sandboxing into account.
|
||||
// TODO: Refactor sandboxing principal code out so we can use it here.
|
||||
if (!aPrincipal && mSandboxFlags) {
|
||||
if (!aPrincipal && (mSandboxFlags & SANDBOXED_ORIGIN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3460,35 +3459,18 @@ nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal)
|
||||
return;
|
||||
}
|
||||
|
||||
// We're done if there is no parent controller. Also, don't inherit
|
||||
// the controller if we're sandboxed. This matches our behavior in
|
||||
// ShouldPrepareForIntercept(),
|
||||
Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController());
|
||||
if (controller.isNothing() || mSandboxFlags) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
|
||||
if (!swm) {
|
||||
if (controller.isNothing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the parent is controlled then propagate that controller to the
|
||||
// initial about:blank client as well. This will set the controller
|
||||
// in the ClientManagerService in the parent.
|
||||
//
|
||||
// Note: If the registration is missing from the SWM we avoid setting
|
||||
// the controller on the client. We can do this synchronously
|
||||
// for now since SWM is in the child process. In the future
|
||||
// when SWM is in the parent process we will probably have to
|
||||
// always set the initial client source and then somehow clear
|
||||
// it if we find the registration is acutally gone. Its also
|
||||
// possible this race only occurs in cases where the resulting
|
||||
// window is no longer exposed. For example, in theory the SW
|
||||
// should not go away if our parent window is controlled.
|
||||
if (!swm->StartControlling(mInitialClientSource->Info(), controller.ref())) {
|
||||
return;
|
||||
}
|
||||
RefPtr<ClientHandle> handle =
|
||||
ClientManager::CreateHandle(mInitialClientSource->Info(),
|
||||
parentInner->EventTargetFor(TaskCategory::Other));
|
||||
handle->Control(controller.ref());
|
||||
|
||||
// Also mark the ClientSource as controlled directly in case script
|
||||
// immediately accesses navigator.serviceWorker.controller.
|
||||
|
@ -5599,10 +5599,7 @@ nsDocument::DispatchContentLoadedEvents()
|
||||
using mozilla::dom::workers::ServiceWorkerManager;
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (swm) {
|
||||
Maybe<ClientInfo> clientInfo = GetClientInfo();
|
||||
if (clientInfo.isSome()) {
|
||||
swm->MaybeCheckNavigationUpdate(clientInfo.ref());
|
||||
}
|
||||
swm->MaybeCheckNavigationUpdate(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1786,34 +1786,11 @@ nsGlobalWindowInner::EnsureClientSource()
|
||||
}
|
||||
}
|
||||
|
||||
// Verify the final ClientSource principal matches the final document
|
||||
// principal. The ClientChannelHelper handles things like network
|
||||
// redirects, but there are other ways the document principal can change.
|
||||
// For example, if something sets the nsIChannel.owner property, then
|
||||
// the final channel principal can be anything. Unfortunately there is
|
||||
// no good way to detect this until after the channel completes loading.
|
||||
//
|
||||
// For now we handle this just by reseting the ClientSource. This will
|
||||
// result in a new ClientSource with the correct principal being created.
|
||||
// To APIs like ServiceWorker and Clients API it will look like there was
|
||||
// an initial content page created that was then immediately replaced.
|
||||
// This is pretty close to what we are actually doing.
|
||||
if (mClientSource) {
|
||||
nsCOMPtr<nsIPrincipal> clientPrincipal(mClientSource->Info().GetPrincipal());
|
||||
if (!clientPrincipal || !clientPrincipal->Equals(mDoc->NodePrincipal())) {
|
||||
mClientSource.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't have a reserved client or an initial client, then create
|
||||
// one now. This can happen in certain cases where we avoid preallocating
|
||||
// the client in the docshell. This mainly occurs in situations where
|
||||
// the principal is not clearly inherited from the parent; e.g. sandboxed
|
||||
// iframes, window.open(), etc.
|
||||
//
|
||||
// We also do this late ClientSource creation if the final document ended
|
||||
// up with a different principal.
|
||||
//
|
||||
// TODO: We may not be marking initial about:blank documents created
|
||||
// this way as controlled by a service worker properly. The
|
||||
// controller should be coming from the same place as the inheritted
|
||||
@ -1827,23 +1804,13 @@ nsGlobalWindowInner::EnsureClientSource()
|
||||
mDoc->NodePrincipal());
|
||||
MOZ_DIAGNOSTIC_ASSERT(mClientSource);
|
||||
newClientSource = true;
|
||||
|
||||
// Note, we don't apply the loadinfo controller below if we create
|
||||
// the ClientSource here.
|
||||
}
|
||||
|
||||
// The load may have started controlling the Client as well. If
|
||||
// so, mark it as controlled immediately here. The actor may
|
||||
// or may not have been notified by the parent side about being
|
||||
// controlled yet.
|
||||
//
|
||||
// Note: We should be careful not to control a client that was created late.
|
||||
// These clients were not seen by the ServiceWorkerManager when it
|
||||
// marked the LoadInfo controlled and it won't know about them. Its
|
||||
// also possible we are creating the client late due to the final
|
||||
// principal changing and these clients should definitely not be
|
||||
// controlled by a service worker with a different principal.
|
||||
else if (loadInfo) {
|
||||
if (loadInfo) {
|
||||
const Maybe<ServiceWorkerDescriptor> controller = loadInfo->GetController();
|
||||
if (controller.isSome()) {
|
||||
mClientSource->SetController(controller.ref());
|
||||
|
@ -65,16 +65,6 @@ ClientHandle::StartOp(const ClientOpConstructorArgs& aArgs)
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ClientHandle::OnShutdownThing()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ClientHandle);
|
||||
if (!mDetachPromise) {
|
||||
return;
|
||||
}
|
||||
mDetachPromise->Resolve(true, __func__);
|
||||
}
|
||||
|
||||
ClientHandle::ClientHandle(ClientManager* aManager,
|
||||
nsISerialEventTarget* aSerialEventTarget,
|
||||
const ClientInfo& aClientInfo)
|
||||
@ -192,21 +182,5 @@ ClientHandle::PostMessage(StructuredCloneData& aData,
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RefPtr<GenericPromise>
|
||||
ClientHandle::OnDetach()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ClientSource);
|
||||
|
||||
if (!mDetachPromise) {
|
||||
mDetachPromise = new GenericPromise::Private(__func__);
|
||||
if (IsShutdown()) {
|
||||
mDetachPromise->Resolve(true, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<GenericPromise> ref(mDetachPromise);
|
||||
return Move(ref);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -42,7 +42,6 @@ class ClientHandle final : public ClientThing<ClientHandleChild>
|
||||
|
||||
RefPtr<ClientManager> mManager;
|
||||
nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
|
||||
RefPtr<GenericPromise::Private> mDetachPromise;
|
||||
ClientInfo mClientInfo;
|
||||
|
||||
~ClientHandle();
|
||||
@ -53,10 +52,6 @@ class ClientHandle final : public ClientThing<ClientHandleChild>
|
||||
already_AddRefed<ClientOpPromise>
|
||||
StartOp(const ClientOpConstructorArgs& aArgs);
|
||||
|
||||
// ClientThing interface
|
||||
void
|
||||
OnShutdownThing() override;
|
||||
|
||||
// Private methods called by ClientHandleChild
|
||||
void
|
||||
ExecutionReady(const ClientInfo& aClientInfo);
|
||||
@ -95,17 +90,6 @@ public:
|
||||
PostMessage(ipc::StructuredCloneData& aData,
|
||||
const ServiceWorkerDescriptor& aSource);
|
||||
|
||||
// Return a Promise that resolves when the ClientHandle object is detached
|
||||
// from its remote actors. This will happen if the ClientSource is destroyed
|
||||
// and triggers the cleanup of the handle actors. It will also naturally
|
||||
// happen when the ClientHandle is de-referenced and tears down its own
|
||||
// actors.
|
||||
//
|
||||
// Note: This method can only be called on the ClientHandle owning thread,
|
||||
// but the MozPromise lets you Then() to another thread.
|
||||
RefPtr<GenericPromise>
|
||||
OnDetach();
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(ClientHandle);
|
||||
};
|
||||
|
||||
|
@ -7,13 +7,11 @@
|
||||
#include "ClientInfo.h"
|
||||
|
||||
#include "mozilla/dom/ClientIPCTypes.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using mozilla::ipc::PrincipalInfo;
|
||||
using mozilla::ipc::PrincipalInfoToPrincipal;
|
||||
|
||||
ClientInfo::ClientInfo(const nsID& aId,
|
||||
ClientType aType,
|
||||
@ -140,13 +138,5 @@ ClientInfo::IsPrivateBrowsing() const
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal>
|
||||
ClientInfo::GetPrincipal() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIPrincipal> ref = PrincipalInfoToPrincipal(PrincipalInfo());
|
||||
return Move(ref);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -95,11 +95,6 @@ public:
|
||||
// Determine if the client is in private browsing mode.
|
||||
bool
|
||||
IsPrivateBrowsing() const;
|
||||
|
||||
// Get a main-thread nsIPrincipal for the client. This may return nullptr
|
||||
// if the PrincipalInfo() fails to deserialize for some reason.
|
||||
nsCOMPtr<nsIPrincipal>
|
||||
GetPrincipal() const;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -206,14 +206,6 @@ ClientSource::WorkerExecutionReady(WorkerPrivate* aWorkerPrivate)
|
||||
return;
|
||||
}
|
||||
|
||||
// A client without access to storage should never be controlled by
|
||||
// a service worker. Check this here in case we were controlled before
|
||||
// execution ready. We can't reliably determine what our storage policy
|
||||
// is before execution ready, unfortunately.
|
||||
if (mController.isSome()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate->IsStorageAllowed());
|
||||
}
|
||||
|
||||
// Its safe to store the WorkerPrivate* here because the ClientSource
|
||||
// is explicitly destroyed by WorkerPrivate before exiting its run loop.
|
||||
MOZ_DIAGNOSTIC_ASSERT(mOwner.is<Nothing>());
|
||||
@ -243,15 +235,6 @@ ClientSource::WindowExecutionReady(nsPIDOMWindowInner* aInnerWindow)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// A client without access to storage should never be controlled by
|
||||
// a service worker. Check this here in case we were controlled before
|
||||
// execution ready. We can't reliably determine what our storage policy
|
||||
// is before execution ready, unfortunately.
|
||||
if (mController.isSome()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::StorageAllowedForWindow(aInnerWindow) ==
|
||||
nsContentUtils::StorageAccess::eAllow);
|
||||
}
|
||||
|
||||
// Don't use nsAutoCString here since IPC requires a full nsCString anyway.
|
||||
nsCString spec;
|
||||
|
||||
@ -307,10 +290,6 @@ ClientSource::DocShellExecutionReady(nsIDocShell* aDocShell)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Note: We don't assert storage access for a controlled client. If
|
||||
// the about:blank actually gets used then WindowExecutionReady() will
|
||||
// get called which asserts storage access.
|
||||
|
||||
// TODO: dedupe this with WindowExecutionReady
|
||||
FrameType frameType = FrameType::Top_level;
|
||||
if (!outer->IsTopLevelWindow()) {
|
||||
@ -381,16 +360,6 @@ ClientSource::SetController(const ServiceWorkerDescriptor& aServiceWorker)
|
||||
// this invariant.
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mClientInfo.IsPrivateBrowsing());
|
||||
|
||||
// A client without access to storage should never be controlled a
|
||||
// a service worker. If we are already execution ready with a real
|
||||
// window or worker, then verify assert the storage policy is correct.
|
||||
if (GetInnerWindow()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::StorageAllowedForWindow(GetInnerWindow()) ==
|
||||
nsContentUtils::StorageAccess::eAllow);
|
||||
} else if (GetWorkerPrivate()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(GetWorkerPrivate()->IsStorageAllowed());
|
||||
}
|
||||
|
||||
if (mController.isSome() && mController.ref() == aServiceWorker) {
|
||||
return;
|
||||
}
|
||||
|
@ -90,15 +90,6 @@ protected:
|
||||
mActor->MaybeStartTeardown();
|
||||
mActor = nullptr;
|
||||
}
|
||||
|
||||
OnShutdownThing();
|
||||
}
|
||||
|
||||
// Allow extending classes to take action when shutdown.
|
||||
virtual void
|
||||
OnShutdownThing()
|
||||
{
|
||||
// by default do nothing
|
||||
}
|
||||
|
||||
public:
|
||||
@ -115,8 +106,6 @@ public:
|
||||
// instead of calling ShutdownThing() to avoid calling MaybeStartTeardown()
|
||||
// on the destroyed actor.
|
||||
mShutdown = true;
|
||||
|
||||
OnShutdownThing();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -15,17 +15,6 @@ interface nsIInterceptedChannel;
|
||||
interface nsIPrincipal;
|
||||
interface nsIRunnable;
|
||||
interface nsIURI;
|
||||
%{C++
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ClientInfo;
|
||||
class ServiceWorkerDescriptor;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
%}
|
||||
|
||||
[ref] native const_ClientInfoRef(const mozilla::dom::ClientInfo);
|
||||
[ref] native const_ServiceWorkerDescriptorRef(const mozilla::dom::ServiceWorkerDescriptor);
|
||||
|
||||
[scriptable, uuid(52ee2c9d-ee87-4caf-9588-23ae77ff8798)]
|
||||
interface nsIServiceWorkerUnregisterCallback : nsISupports
|
||||
@ -161,9 +150,6 @@ interface nsIServiceWorkerManager : nsISupports
|
||||
*/
|
||||
[notxpcom,nostdcall] void MaybeStartControlling(in nsIDocument aDoc);
|
||||
|
||||
[notxpcom, nostdcall] bool StartControlling(in const_ClientInfoRef aClientInfo,
|
||||
in const_ServiceWorkerDescriptorRef aServiceWorker);
|
||||
|
||||
/**
|
||||
* Documents that have called MaybeStartControlling() should call this when
|
||||
* they are destroyed. This function may be called multiple times, and is
|
||||
|
@ -313,75 +313,6 @@ ServiceWorkerManager::Init(ServiceWorkerRegistrar* aRegistrar)
|
||||
mActor = static_cast<ServiceWorkerManagerChild*>(actor);
|
||||
}
|
||||
|
||||
RefPtr<GenericPromise>
|
||||
ServiceWorkerManager::StartControllingClient(const ClientInfo& aClientInfo,
|
||||
ServiceWorkerRegistrationInfo* aRegistrationInfo)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aRegistrationInfo->GetActive());
|
||||
|
||||
RefPtr<GenericPromise> ref;
|
||||
|
||||
const ServiceWorkerDescriptor& active =
|
||||
aRegistrationInfo->GetActive()->Descriptor();
|
||||
|
||||
auto entry = mControlledClients.LookupForAdd(aClientInfo.Id());
|
||||
if (entry) {
|
||||
RefPtr<ServiceWorkerRegistrationInfo> old =
|
||||
entry.Data()->mRegistrationInfo.forget();
|
||||
|
||||
ref = Move(entry.Data()->mClientHandle->Control(active));
|
||||
entry.Data()->mRegistrationInfo = aRegistrationInfo;
|
||||
|
||||
if (old != aRegistrationInfo) {
|
||||
StopControllingRegistration(old);
|
||||
aRegistrationInfo->StartControllingClient();
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_CONTROLLED_DOCUMENTS, 1);
|
||||
|
||||
return Move(ref);
|
||||
}
|
||||
|
||||
RefPtr<ClientHandle> clientHandle =
|
||||
ClientManager::CreateHandle(aClientInfo,
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other));
|
||||
|
||||
ref = Move(clientHandle->Control(active));
|
||||
|
||||
aRegistrationInfo->StartControllingClient();
|
||||
|
||||
entry.OrInsert([&] {
|
||||
return new ControlledClientData(clientHandle, aRegistrationInfo);
|
||||
});
|
||||
|
||||
RefPtr<ServiceWorkerManager> self(this);
|
||||
clientHandle->OnDetach()->Then(
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other), __func__,
|
||||
[self = Move(self), aClientInfo] {
|
||||
self->StopControllingClient(aClientInfo);
|
||||
});
|
||||
|
||||
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_CONTROLLED_DOCUMENTS, 1);
|
||||
|
||||
return Move(ref);
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::StopControllingClient(const ClientInfo& aClientInfo)
|
||||
{
|
||||
auto entry = mControlledClients.Lookup(aClientInfo.Id());
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> reg =
|
||||
entry.Data()->mRegistrationInfo.forget();
|
||||
|
||||
entry.Remove();
|
||||
|
||||
StopControllingRegistration(reg);
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::MaybeStartShutdown()
|
||||
{
|
||||
@ -1501,13 +1432,8 @@ ServiceWorkerManager::GetActiveWorkerInfoForDocument(nsIDocument* aDocument)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
Maybe<ClientInfo> clientInfo(aDocument->GetClientInfo());
|
||||
if (clientInfo.isNothing()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration;
|
||||
GetClientRegistration(clientInfo.ref(), getter_AddRefs(registration));
|
||||
GetDocumentRegistration(aDocument, getter_AddRefs(registration));
|
||||
|
||||
if (!registration) {
|
||||
return nullptr;
|
||||
@ -1652,7 +1578,7 @@ ServiceWorkerManager::WorkerIsIdle(ServiceWorkerInfo* aWorker)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!reg->IsControllingClients() && reg->mPendingUninstall) {
|
||||
if (!reg->IsControllingDocuments() && reg->mPendingUninstall) {
|
||||
RemoveRegistration(reg);
|
||||
return;
|
||||
}
|
||||
@ -2343,25 +2269,15 @@ ServiceWorkerManager::RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo*
|
||||
entry.Remove();
|
||||
}
|
||||
|
||||
// Verify there are no controlled clients for the purged registration.
|
||||
for (auto iter = swm->mControlledClients.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto& reg = iter.UserData()->mRegistrationInfo;
|
||||
if (reg->mScope.Equals(aRegistration->mScope)) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(false,
|
||||
"controlled client when removing registration");
|
||||
iter.Remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Registration lifecycle is managed via mControlledClients now. Do not
|
||||
// assert on on mControlledDocuments as races may cause this to still be
|
||||
// set when the registration is destroyed.
|
||||
// The registration should generally only be removed if there are no controlled
|
||||
// documents, but mControlledDocuments can contain references to potentially
|
||||
// controlled docs. This happens when the service worker is not active yet.
|
||||
// We must purge these references since we are evicting the registration.
|
||||
for (auto iter = swm->mControlledDocuments.Iter(); !iter.Done(); iter.Next()) {
|
||||
ServiceWorkerRegistrationInfo* reg = iter.UserData();
|
||||
MOZ_ASSERT(reg);
|
||||
if (reg->mScope.Equals(aRegistration->mScope)) {
|
||||
iter.Remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2392,49 +2308,32 @@ ServiceWorkerManager::MaybeStartControlling(nsIDocument* aDoc)
|
||||
MOZ_ASSERT(aDoc);
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetServiceWorkerRegistrationInfo(aDoc);
|
||||
if (registration && registration->GetActive() &&
|
||||
aDoc->GetSandboxFlags() == 0) {
|
||||
if (registration) {
|
||||
MOZ_ASSERT(!mControlledDocuments.Contains(aDoc));
|
||||
StartControllingADocument(registration, aDoc);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceWorkerManager::StartControlling(const ClientInfo& aClientInfo,
|
||||
const ServiceWorkerDescriptor& aServiceWorker)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
PrincipalInfoToPrincipal(aServiceWorker.PrincipalInfo());
|
||||
NS_ENSURE_TRUE(principal, false);
|
||||
|
||||
nsCOMPtr<nsIURI> scope;
|
||||
nsresult rv =
|
||||
NS_NewURI(getter_AddRefs(scope), aServiceWorker.Scope(), nullptr, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetServiceWorkerRegistrationInfo(principal, scope);
|
||||
NS_ENSURE_TRUE(registration, false);
|
||||
|
||||
StartControllingClient(aClientInfo, registration);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::MaybeStopControlling(nsIDocument* aDoc)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aDoc);
|
||||
mControlledDocuments.Remove(aDoc);
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration;
|
||||
mControlledDocuments.Remove(aDoc, getter_AddRefs(registration));
|
||||
// A document which was uncontrolled does not maintain that state itself, so
|
||||
// it will always call MaybeStopControlling() even if there isn't an
|
||||
// associated registration. So this check is required.
|
||||
if (registration) {
|
||||
StopControllingADocument(registration);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::MaybeCheckNavigationUpdate(const ClientInfo& aClientInfo)
|
||||
ServiceWorkerManager::MaybeCheckNavigationUpdate(nsIDocument* aDoc)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aDoc);
|
||||
// We perform these success path navigation update steps when the
|
||||
// document tells us its more or less done loading. This avoids
|
||||
// slowing down page load and also lets pages consistently get
|
||||
@ -2444,27 +2343,52 @@ ServiceWorkerManager::MaybeCheckNavigationUpdate(const ClientInfo& aClientInfo)
|
||||
// 9.8.22 Else: (respondWith was entered and succeeded)
|
||||
// If request is a non-subresource request, then: Invoke Soft Update
|
||||
// algorithm.
|
||||
ControlledClientData* data = mControlledClients.Get(aClientInfo.Id());
|
||||
if (data && data->mRegistrationInfo) {
|
||||
data->mRegistrationInfo->MaybeScheduleUpdate();
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration;
|
||||
mControlledDocuments.Get(aDoc, getter_AddRefs(registration));
|
||||
if (registration) {
|
||||
registration->MaybeScheduleUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RefPtr<GenericPromise>
|
||||
ServiceWorkerManager::StartControllingADocument(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
nsIDocument* aDoc)
|
||||
{
|
||||
MOZ_ASSERT(aRegistration);
|
||||
MOZ_ASSERT(aDoc);
|
||||
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
auto storageAllowed = nsContentUtils::StorageAllowedForDocument(aDoc);
|
||||
MOZ_DIAGNOSTIC_ASSERT(storageAllowed == nsContentUtils::StorageAccess::eAllow);
|
||||
#endif // MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
|
||||
RefPtr<GenericPromise> ref = GenericPromise::CreateAndResolve(true, __func__);
|
||||
|
||||
aRegistration->StartControllingADocument();
|
||||
mControlledDocuments.Put(aDoc, aRegistration);
|
||||
|
||||
// Mark the document's ClientSource as controlled using the ClientHandle
|
||||
// interface. While we could get at the ClientSource directly from the
|
||||
// document here, our goal is to move ServiceWorkerManager to a separate
|
||||
// process. Using the ClientHandle supports this remote operation.
|
||||
ServiceWorkerInfo* activeWorker = aRegistration->GetActive();
|
||||
Maybe<ClientInfo> clientInfo = aDoc->GetClientInfo();
|
||||
if (activeWorker && clientInfo.isSome()) {
|
||||
RefPtr<ClientHandle> clientHandle =
|
||||
ClientManager::CreateHandle(clientInfo.ref(),
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other));
|
||||
ref = Move(clientHandle->Control(activeWorker->Descriptor()));
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_CONTROLLED_DOCUMENTS, 1);
|
||||
return Move(ref);
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::StopControllingRegistration(ServiceWorkerRegistrationInfo* aRegistration)
|
||||
ServiceWorkerManager::StopControllingADocument(ServiceWorkerRegistrationInfo* aRegistration)
|
||||
{
|
||||
aRegistration->StopControllingClient();
|
||||
if (aRegistration->IsControllingClients() || !aRegistration->IsIdle()) {
|
||||
aRegistration->StopControllingADocument();
|
||||
if (aRegistration->IsControllingDocuments() || !aRegistration->IsIdle()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2794,7 +2718,10 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
|
||||
// First, attempt to mark the reserved client controlled directly. This
|
||||
// will update the controlled status in the ClientManagerService in the
|
||||
// parent. It will also eventually propagate back to the ClientSource.
|
||||
StartControllingClient(clientInfo.ref(), registration);
|
||||
RefPtr<ClientHandle> clientHandle =
|
||||
ClientManager::CreateHandle(clientInfo.ref(),
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other));
|
||||
clientHandle->Control(serviceWorker->Descriptor());
|
||||
}
|
||||
|
||||
// But we also note the reserved state on the LoadInfo. This allows the
|
||||
@ -2858,21 +2785,20 @@ ServiceWorkerManager::IsAvailable(nsIPrincipal* aPrincipal,
|
||||
}
|
||||
|
||||
nsresult
|
||||
ServiceWorkerManager::GetClientRegistration(const ClientInfo& aClientInfo,
|
||||
ServiceWorkerRegistrationInfo** aRegistrationInfo)
|
||||
ServiceWorkerManager::GetDocumentRegistration(nsIDocument* aDoc,
|
||||
ServiceWorkerRegistrationInfo** aRegistrationInfo)
|
||||
{
|
||||
ControlledClientData* data = mControlledClients.Get(aClientInfo.Id());
|
||||
if (!data || !data->mRegistrationInfo) {
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration;
|
||||
if (!mControlledDocuments.Get(aDoc, getter_AddRefs(registration))) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// If the document is controlled, the current worker MUST be non-null.
|
||||
if (!data->mRegistrationInfo->GetActive()) {
|
||||
if (!registration->GetActive()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> ref = data->mRegistrationInfo;
|
||||
ref.forget(aRegistrationInfo);
|
||||
registration.forget(aRegistrationInfo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3243,21 +3169,13 @@ ServiceWorkerManager::MaybeClaimClient(nsIDocument* aDocument,
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
Maybe<ClientInfo> clientInfo(aDocument->GetClientInfo());
|
||||
if (NS_WARN_IF(clientInfo.isNothing())) {
|
||||
ref = GenericPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
__func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
// The registration that should be controlling the client
|
||||
RefPtr<ServiceWorkerRegistrationInfo> matchingRegistration =
|
||||
GetServiceWorkerRegistrationInfo(aDocument);
|
||||
|
||||
// The registration currently controlling the client
|
||||
RefPtr<ServiceWorkerRegistrationInfo> controllingRegistration;
|
||||
GetClientRegistration(clientInfo.ref(),
|
||||
getter_AddRefs(controllingRegistration));
|
||||
GetDocumentRegistration(aDocument, getter_AddRefs(controllingRegistration));
|
||||
|
||||
if (aWorkerRegistration != matchingRegistration ||
|
||||
aWorkerRegistration == controllingRegistration) {
|
||||
@ -3265,8 +3183,11 @@ ServiceWorkerManager::MaybeClaimClient(nsIDocument* aDocument,
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
StartControllingADocument(aWorkerRegistration, aDocument);
|
||||
ref = StartControllingClient(clientInfo.ref(), aWorkerRegistration);
|
||||
if (controllingRegistration) {
|
||||
StopControllingADocument(controllingRegistration);
|
||||
}
|
||||
|
||||
ref = StartControllingADocument(aWorkerRegistration, aDocument);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
@ -3327,19 +3248,31 @@ ServiceWorkerManager::UpdateClientControllers(ServiceWorkerRegistrationInfo* aRe
|
||||
RefPtr<ServiceWorkerInfo> activeWorker = aRegistration->GetActive();
|
||||
MOZ_DIAGNOSTIC_ASSERT(activeWorker);
|
||||
|
||||
AutoTArray<RefPtr<ClientHandle>, 16> handleList;
|
||||
for (auto iter = mControlledClients.Iter(); !iter.Done(); iter.Next()) {
|
||||
if (iter.UserData()->mRegistrationInfo != aRegistration) {
|
||||
AutoTArray<nsCOMPtr<nsIDocument>, 16> docList;
|
||||
for (auto iter = mControlledDocuments.Iter(); !iter.Done(); iter.Next()) {
|
||||
if (iter.UserData() != aRegistration) {
|
||||
continue;
|
||||
}
|
||||
|
||||
handleList.AppendElement(iter.UserData()->mClientHandle);
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(iter.Key());
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
docList.AppendElement(doc.forget());
|
||||
}
|
||||
|
||||
// Fire event after iterating mControlledClients is done to prevent
|
||||
// Fire event after iterating mControlledDocuments is done to prevent
|
||||
// modification by reentering from the event handlers during iteration.
|
||||
for (auto& handle : handleList) {
|
||||
handle->Control(activeWorker->Descriptor());
|
||||
for (auto& doc : docList) {
|
||||
Maybe<ClientInfo> clientInfo = doc->GetClientInfo();
|
||||
if (clientInfo.isNothing()) {
|
||||
continue;
|
||||
}
|
||||
RefPtr<ClientHandle> clientHandle =
|
||||
ClientManager::CreateHandle(clientInfo.ref(),
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other));
|
||||
clientHandle->Control(activeWorker->Descriptor());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/ClientHandle.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/ServiceWorkerCommon.h"
|
||||
#include "mozilla/dom/ServiceWorkerRegistrar.h"
|
||||
@ -106,21 +105,6 @@ public:
|
||||
|
||||
nsRefPtrHashtable<nsISupportsHashKey, ServiceWorkerRegistrationInfo> mControlledDocuments;
|
||||
|
||||
struct ControlledClientData
|
||||
{
|
||||
RefPtr<ClientHandle> mClientHandle;
|
||||
RefPtr<ServiceWorkerRegistrationInfo> mRegistrationInfo;
|
||||
|
||||
ControlledClientData(ClientHandle* aClientHandle,
|
||||
ServiceWorkerRegistrationInfo* aRegistrationInfo)
|
||||
: mClientHandle(aClientHandle)
|
||||
, mRegistrationInfo(aRegistrationInfo)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
nsClassHashtable<nsIDHashKey, ControlledClientData> mControlledClients;
|
||||
|
||||
// Track all documents that have attempted to register a service worker for a
|
||||
// given scope.
|
||||
typedef nsTArray<nsCOMPtr<nsIWeakReference>> WeakDocumentList;
|
||||
@ -320,7 +304,7 @@ public:
|
||||
ServiceWorkerRegistrationListener* aListener);
|
||||
|
||||
void
|
||||
MaybeCheckNavigationUpdate(const ClientInfo& aClientInfo);
|
||||
MaybeCheckNavigationUpdate(nsIDocument* aDoc);
|
||||
|
||||
nsresult
|
||||
SendPushEvent(const nsACString& aOriginAttributes,
|
||||
@ -344,13 +328,6 @@ private:
|
||||
void
|
||||
Init(ServiceWorkerRegistrar* aRegistrar);
|
||||
|
||||
RefPtr<GenericPromise>
|
||||
StartControllingClient(const ClientInfo& aClientInfo,
|
||||
ServiceWorkerRegistrationInfo* aRegistrationInfo);
|
||||
|
||||
void
|
||||
StopControllingClient(const ClientInfo& aClientInfo);
|
||||
|
||||
void
|
||||
MaybeStartShutdown();
|
||||
|
||||
@ -372,8 +349,8 @@ private:
|
||||
Update(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
nsresult
|
||||
GetClientRegistration(const ClientInfo& aClientInfo,
|
||||
ServiceWorkerRegistrationInfo** aRegistrationInfo);
|
||||
GetDocumentRegistration(nsIDocument* aDoc,
|
||||
ServiceWorkerRegistrationInfo** aRegistrationInfo);
|
||||
|
||||
nsresult
|
||||
GetServiceWorkerForScope(nsPIDOMWindowInner* aWindow,
|
||||
@ -398,12 +375,12 @@ private:
|
||||
void
|
||||
NotifyServiceWorkerRegistrationRemoved(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
void
|
||||
RefPtr<GenericPromise>
|
||||
StartControllingADocument(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
nsIDocument* aDoc);
|
||||
|
||||
void
|
||||
StopControllingRegistration(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
StopControllingADocument(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetServiceWorkerRegistrationInfo(nsPIDOMWindowInner* aWindow);
|
||||
|
@ -81,7 +81,7 @@ ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(
|
||||
const nsACString& aScope,
|
||||
nsIPrincipal* aPrincipal,
|
||||
ServiceWorkerUpdateViaCache aUpdateViaCache)
|
||||
: mControlledClientsCounter(0)
|
||||
: mControlledDocumentsCounter(0)
|
||||
, mUpdateState(NoUpdate)
|
||||
, mCreationTime(PR_Now())
|
||||
, mCreationTimeStamp(TimeStamp::Now())
|
||||
@ -94,7 +94,9 @@ ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(
|
||||
|
||||
ServiceWorkerRegistrationInfo::~ServiceWorkerRegistrationInfo()
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsControllingClients());
|
||||
if (IsControllingDocuments()) {
|
||||
NS_WARNING("ServiceWorkerRegistrationInfo is still controlling documents. This can be a bug or a leak in ServiceWorker API or in any other API that takes the document alive.");
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(ServiceWorkerRegistrationInfo, nsIServiceWorkerRegistrationInfo)
|
||||
@ -246,7 +248,7 @@ void
|
||||
ServiceWorkerRegistrationInfo::TryToActivate()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
bool controlling = IsControllingClients();
|
||||
bool controlling = IsControllingDocuments();
|
||||
bool skipWaiting = mWaitingWorker && mWaitingWorker->SkipWaitingFlag();
|
||||
bool idle = IsIdle();
|
||||
if (idle && (!controlling || skipWaiting)) {
|
||||
|
@ -17,7 +17,7 @@ namespace workers {
|
||||
class ServiceWorkerRegistrationInfo final
|
||||
: public nsIServiceWorkerRegistrationInfo
|
||||
{
|
||||
uint32_t mControlledClientsCounter;
|
||||
uint32_t mControlledDocumentsCounter;
|
||||
|
||||
enum
|
||||
{
|
||||
@ -79,22 +79,22 @@ public:
|
||||
GetServiceWorkerInfoById(uint64_t aId);
|
||||
|
||||
void
|
||||
StartControllingClient()
|
||||
StartControllingADocument()
|
||||
{
|
||||
++mControlledClientsCounter;
|
||||
++mControlledDocumentsCounter;
|
||||
}
|
||||
|
||||
void
|
||||
StopControllingClient()
|
||||
StopControllingADocument()
|
||||
{
|
||||
MOZ_ASSERT(mControlledClientsCounter);
|
||||
--mControlledClientsCounter;
|
||||
MOZ_ASSERT(mControlledDocumentsCounter);
|
||||
--mControlledDocumentsCounter;
|
||||
}
|
||||
|
||||
bool
|
||||
IsControllingClients() const
|
||||
IsControllingDocuments() const
|
||||
{
|
||||
return mActiveWorker && mControlledClientsCounter;
|
||||
return mActiveWorker && mControlledDocumentsCounter;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -138,7 +138,7 @@ ServiceWorkerUnregisterJob::Unregister()
|
||||
InvokeResultCallbacks(NS_OK);
|
||||
|
||||
// "If no service worker client is using registration..."
|
||||
if (!registration->IsControllingClients() && registration->IsIdle()) {
|
||||
if (!registration->IsControllingDocuments() && registration->IsIdle()) {
|
||||
// "Invoke [[Clear Registration]]..."
|
||||
swm->RemoveRegistration(registration);
|
||||
}
|
||||
|
@ -19,6 +19,10 @@
|
||||
info("skip_waiting_scope/index.html shouldn't be launched directly!");
|
||||
}
|
||||
|
||||
navigator.serviceWorker.ready.then(function() {
|
||||
parent.postMessage("READY", "*");
|
||||
});
|
||||
|
||||
navigator.serviceWorker.oncontrollerchange = function() {
|
||||
parent.postMessage({
|
||||
event: "controllerchange",
|
||||
|
@ -13,7 +13,6 @@
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script src="utils.js"></script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
var registration, iframe, content;
|
||||
|
||||
@ -22,9 +21,19 @@
|
||||
{scope: "./skip_waiting_scope/"});
|
||||
}
|
||||
|
||||
async function waitForActivated(swr) {
|
||||
function waitForActivated(swr) {
|
||||
registration = swr;
|
||||
await waitForState(registration.installing, "activated")
|
||||
var promise = new Promise(function(resolve, reject) {
|
||||
window.onmessage = function(e) {
|
||||
if (e.data === "READY") {
|
||||
ok(true, "Active worker is activated now");
|
||||
resolve();
|
||||
} else {
|
||||
ok(false, "Wrong value. Somenting went wrong");
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
iframe = document.createElement("iframe");
|
||||
iframe.setAttribute("src", "skip_waiting_scope/index.html");
|
||||
@ -32,7 +41,7 @@
|
||||
content = document.getElementById("content");
|
||||
content.appendChild(iframe);
|
||||
|
||||
await new Promise(resolve => iframe.onload = resolve);
|
||||
return promise;
|
||||
}
|
||||
|
||||
function checkWhetherItSkippedWaiting() {
|
||||
|
@ -13,15 +13,14 @@
|
||||
<p id="display"></p>
|
||||
<div id="content"></div>
|
||||
<pre id="test"></pre>
|
||||
<script src="utils.js"></script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
var registration;
|
||||
var promise;
|
||||
|
||||
async function start() {
|
||||
registration = await navigator.serviceWorker.register("worker_updatefoundevent.js",
|
||||
{ scope: "./updatefoundevent.html" })
|
||||
await waitForState(registration.installing, 'activated');
|
||||
function start() {
|
||||
return navigator.serviceWorker.register("worker_updatefoundevent.js",
|
||||
{ scope: "./updatefoundevent.html" })
|
||||
.then((swr) => registration = swr);
|
||||
}
|
||||
|
||||
function startWaitForUpdateFound() {
|
||||
|
@ -3,16 +3,21 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
registration.onupdatefound = function(e) {
|
||||
clients.matchAll().then(function(clients) {
|
||||
if (!clients.length) {
|
||||
reject("No clients found");
|
||||
}
|
||||
onactivate = function(e) {
|
||||
e.waitUntil(new Promise(function(resolve, reject) {
|
||||
registration.onupdatefound = function(e) {
|
||||
clients.matchAll().then(function(clients) {
|
||||
if (!clients.length) {
|
||||
reject("No clients found");
|
||||
}
|
||||
|
||||
if (registration.scope.match(/updatefoundevent\.html$/)) {
|
||||
clients[0].postMessage("finish");
|
||||
} else {
|
||||
dump("Scope did not match");
|
||||
if (registration.scope.match(/updatefoundevent\.html$/)) {
|
||||
clients[0].postMessage("finish");
|
||||
resolve();
|
||||
} else {
|
||||
dump("Scope did not match");
|
||||
}
|
||||
}, reject);
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
@ -90,12 +90,9 @@ async_test(function(t) {
|
||||
return registration.unregister();
|
||||
})
|
||||
.then(function() {
|
||||
// Step 5.1 of Register clears the uninstall flag before fetching
|
||||
// the script:
|
||||
//
|
||||
// https://w3c.github.io/ServiceWorker/#register-algorithm
|
||||
var promise = navigator.serviceWorker.register('this-will-404',
|
||||
{ scope: scope });
|
||||
iframe.remove();
|
||||
return promise;
|
||||
})
|
||||
.then(
|
||||
@ -103,28 +100,17 @@ async_test(function(t) {
|
||||
assert_unreached('register should reject the promise');
|
||||
},
|
||||
function() {
|
||||
assert_equals(registration.installing, null,
|
||||
'registration.installing');
|
||||
assert_equals(registration.waiting, null,
|
||||
'registration.waiting');
|
||||
assert_equals(registration.active.scriptURL, normalizeURL(worker_url),
|
||||
'registration.active');
|
||||
iframe.remove();
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(function(frame) {
|
||||
assert_equals(
|
||||
frame.contentWindow.navigator.serviceWorker.controller.scriptURL,
|
||||
normalizeURL(worker_url),
|
||||
'the original worker should control a new document');
|
||||
assert_equals(frame.contentWindow.navigator.serviceWorker.controller,
|
||||
null,
|
||||
'document should not load with a controller');
|
||||
frame.remove();
|
||||
return registration.unregister();
|
||||
})
|
||||
.then(function() {
|
||||
t.done();
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Registering a new script URL that 404s does resurrect an ' +
|
||||
}, 'Registering a new script URL that 404s does not resurrect an ' +
|
||||
'unregistered registration');
|
||||
|
||||
async_test(function(t) {
|
||||
@ -145,12 +131,9 @@ async_test(function(t) {
|
||||
return registration.unregister();
|
||||
})
|
||||
.then(function() {
|
||||
// Step 5.1 of Register clears the uninstall flag before firing
|
||||
// the install event:
|
||||
//
|
||||
// https://w3c.github.io/ServiceWorker/#register-algorithm
|
||||
var promise = navigator.serviceWorker.register(
|
||||
'resources/reject-install-worker.js', { scope: scope });
|
||||
iframe.remove();
|
||||
return promise;
|
||||
})
|
||||
.then(function(r) {
|
||||
@ -158,20 +141,12 @@ async_test(function(t) {
|
||||
return wait_for_state(t, r.installing, 'redundant');
|
||||
})
|
||||
.then(function() {
|
||||
assert_equals(registration.installing, null,
|
||||
'registration.installing');
|
||||
assert_equals(registration.waiting, null,
|
||||
'registration.waiting');
|
||||
assert_equals(registration.active.scriptURL, normalizeURL(worker_url),
|
||||
'registration.active');
|
||||
iframe.remove();
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(function(frame) {
|
||||
assert_equals(
|
||||
frame.contentWindow.navigator.serviceWorker.controller.scriptURL,
|
||||
normalizeURL(worker_url),
|
||||
'the original worker should control a new document');
|
||||
assert_equals(frame.contentWindow.navigator.serviceWorker.controller,
|
||||
null,
|
||||
'document should not load with a controller');
|
||||
frame.remove();
|
||||
return registration.unregister();
|
||||
})
|
||||
@ -179,6 +154,6 @@ async_test(function(t) {
|
||||
t.done();
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Registering a new script URL that fails to install does resurrect ' +
|
||||
}, 'Registering a new script URL that fails to install does not resurrect ' +
|
||||
'an unregistered registration');
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user