Bug 1419536 P4 Allow ClientSource objects to be frozen while in bfcache. r=baku

This commit is contained in:
Ben Kelly 2017-11-21 15:13:05 -05:00
parent 3935375a57
commit 9af975dbfd
8 changed files with 99 additions and 1 deletions

View File

@ -1532,6 +1532,8 @@ nsGlobalWindowInner::EnsureClientSource()
{
MOZ_DIAGNOSTIC_ASSERT(mDoc);
bool newClientSource = false;
nsCOMPtr<nsIChannel> channel = mDoc->GetChannel();
nsCOMPtr<nsILoadInfo> loadInfo = channel ? channel->GetLoadInfo() : nullptr;
@ -1544,6 +1546,7 @@ nsGlobalWindowInner::EnsureClientSource()
if (reservedClient) {
mClientSource.reset();
mClientSource = Move(reservedClient);
newClientSource = true;
}
}
@ -1557,6 +1560,9 @@ nsGlobalWindowInner::EnsureClientSource()
nsIDocShell* docshell = GetDocShell();
if (docshell) {
mClientSource = docshell->TakeInitialClientSource();
if (mClientSource) {
newClientSource = true;
}
}
}
@ -1572,6 +1578,13 @@ nsGlobalWindowInner::EnsureClientSource()
if (NS_WARN_IF(!mClientSource)) {
return NS_ERROR_FAILURE;
}
newClientSource = true;
}
// Its possible that we got a client just after being frozen in
// the bfcache. In that case freeze the client immediately.
if (newClientSource && IsFrozen()) {
mClientSource->Freeze();
}
return NS_OK;
@ -6063,6 +6076,9 @@ nsGlobalWindowInner::FreezeInternal()
mozilla::dom::workers::FreezeWorkersForWindow(this);
mTimeoutManager->Freeze();
if (mClientSource) {
mClientSource->Freeze();
}
if (IsInnerWindow()) {
NotifyDOMWindowFrozen(this);
@ -6094,6 +6110,9 @@ nsGlobalWindowInner::ThawInternal()
return;
}
if (mClientSource) {
mClientSource->Thaw();
}
mTimeoutManager->Thaw();
mozilla::dom::workers::ThawWorkersForWindow(this);

View File

@ -126,7 +126,8 @@ ClientManagerService::FindSource(const nsID& aID, const PrincipalInfo& aPrincipa
}
ClientSourceParent* source = entry.Data();
if (!MatchPrincipalInfo(source->Info().PrincipalInfo(), aPrincipalInfo)) {
if (source->IsFrozen() ||
!MatchPrincipalInfo(source->Info().PrincipalInfo(), aPrincipalInfo)) {
return nullptr;
}

View File

@ -235,6 +235,22 @@ ClientSource::DocShellExecutionReady(nsIDocShell* aDocShell)
return NS_OK;
}
void
ClientSource::Freeze()
{
MaybeExecute([](PClientSourceChild* aActor) {
aActor->SendFreeze();
});
}
void
ClientSource::Thaw()
{
MaybeExecute([](PClientSourceChild* aActor) {
aActor->SendThaw();
});
}
const ClientInfo&
ClientSource::Info() const
{

View File

@ -82,6 +82,12 @@ public:
nsresult
DocShellExecutionReady(nsIDocShell* aDocShell);
void
Freeze();
void
Thaw();
const ClientInfo&
Info() const;

View File

@ -111,6 +111,30 @@ ClientSourceParent::RecvExecutionReady(const ClientSourceExecutionReadyArgs& aAr
return IPC_OK();
};
IPCResult
ClientSourceParent::RecvFreeze()
{
MOZ_DIAGNOSTIC_ASSERT(!mFrozen);
mFrozen = true;
// Frozen clients should not be observable. Act as if the client has
// been destroyed.
nsTArray<ClientHandleParent*> handleList(mHandleList);
for (ClientHandleParent* handle : handleList) {
Unused << ClientHandleParent::Send__delete__(handle);
}
return IPC_OK();
}
IPCResult
ClientSourceParent::RecvThaw()
{
MOZ_DIAGNOSTIC_ASSERT(mFrozen);
mFrozen = false;
return IPC_OK();
}
void
ClientSourceParent::ActorDestroy(ActorDestroyReason aReason)
{
@ -144,6 +168,7 @@ ClientSourceParent::ClientSourceParent(const ClientSourceConstructorArgs& aArgs)
: mClientInfo(aArgs.id(), aArgs.type(), aArgs.principalInfo(), aArgs.creationTime())
, mService(ClientManagerService::GetOrCreateInstance())
, mExecutionReady(false)
, mFrozen(false)
{
}
@ -178,10 +203,17 @@ ClientSourceParent::Info() const
return mClientInfo;
}
bool
ClientSourceParent::IsFrozen() const
{
return mFrozen;
}
void
ClientSourceParent::AttachHandle(ClientHandleParent* aClientHandle)
{
MOZ_DIAGNOSTIC_ASSERT(aClientHandle);
MOZ_DIAGNOSTIC_ASSERT(!mFrozen);
MOZ_ASSERT(!mHandleList.Contains(aClientHandle));
mHandleList.AppendElement(aClientHandle);
}

View File

@ -21,6 +21,7 @@ class ClientSourceParent final : public PClientSourceParent
RefPtr<ClientManagerService> mService;
nsTArray<ClientHandleParent*> mHandleList;
bool mExecutionReady;
bool mFrozen;
void
KillInvalidChild();
@ -32,6 +33,12 @@ class ClientSourceParent final : public PClientSourceParent
mozilla::ipc::IPCResult
RecvExecutionReady(const ClientSourceExecutionReadyArgs& aArgs) override;
mozilla::ipc::IPCResult
RecvFreeze() override;
mozilla::ipc::IPCResult
RecvThaw() override;
void
ActorDestroy(ActorDestroyReason aReason) override;
@ -51,6 +58,9 @@ public:
const ClientInfo&
Info() const;
bool
IsFrozen() const;
void
AttachHandle(ClientHandleParent* aClientSource);

View File

@ -22,6 +22,8 @@ sync protocol PClientSource
parent:
async Teardown();
async ExecutionReady(ClientSourceExecutionReadyArgs aArgs);
async Freeze();
async Thaw();
child:
async PClientSourceOp(ClientOpConstructorArgs aArgs);

View File

@ -5323,6 +5323,9 @@ WorkerPrivate::EnsureClientSource()
mClientSource = ClientManager::CreateSource(type, mWorkerHybridEventTarget,
GetPrincipalInfo());
if (mFrozen) {
mClientSource->Freeze();
}
}
const ClientInfo&
@ -5680,6 +5683,10 @@ WorkerPrivate::FreezeInternal()
NS_ASSERTION(!mFrozen, "Already frozen!");
if (mClientSource) {
mClientSource->Freeze();
}
mFrozen = true;
for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
@ -5701,6 +5708,11 @@ WorkerPrivate::ThawInternal()
}
mFrozen = false;
if (mClientSource) {
mClientSource->Thaw();
}
return true;
}