mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1225121 - [B2G] All the rest of content processes crash if user tries to run app that uses Service Workers after restart. r=baku
This commit is contained in:
parent
e70ec2d790
commit
a3d950d1bd
@ -150,6 +150,7 @@ private:
|
||||
ServiceWorkerManagerParent::ServiceWorkerManagerParent()
|
||||
: mService(ServiceWorkerManagerService::GetOrCreate())
|
||||
, mID(++sServiceWorkerManagerParentID)
|
||||
, mActorDestroyed(false)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
mService->RegisterActor(this);
|
||||
@ -160,6 +161,17 @@ ServiceWorkerManagerParent::~ServiceWorkerManagerParent()
|
||||
AssertIsOnBackgroundThread();
|
||||
}
|
||||
|
||||
already_AddRefed<ContentParent>
|
||||
ServiceWorkerManagerParent::GetContentParent() const
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
// This object must be released on main-thread.
|
||||
RefPtr<ContentParent> parent =
|
||||
BackgroundParent::GetContentParent(Manager());
|
||||
return parent.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceWorkerManagerParent::RecvRegister(
|
||||
const ServiceWorkerRegistrationData& aData)
|
||||
@ -306,6 +318,8 @@ ServiceWorkerManagerParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
mActorDestroyed = true;
|
||||
|
||||
if (mService) {
|
||||
// This object is about to be released and with it, also mService will be
|
||||
// released too.
|
||||
|
@ -27,11 +27,19 @@ class ServiceWorkerManagerParent final : public PServiceWorkerManagerParent
|
||||
friend class mozilla::ipc::BackgroundParentImpl;
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ServiceWorkerManagerParent)
|
||||
|
||||
bool ActorDestroyed() const
|
||||
{
|
||||
return mActorDestroyed;
|
||||
}
|
||||
|
||||
uint64_t ID() const
|
||||
{
|
||||
return mID;
|
||||
}
|
||||
|
||||
already_AddRefed<ContentParent> GetContentParent() const;
|
||||
private:
|
||||
ServiceWorkerManagerParent();
|
||||
~ServiceWorkerManagerParent();
|
||||
@ -61,6 +69,8 @@ private:
|
||||
// We use this ID in the Service in order to avoid the sending of messages to
|
||||
// ourself.
|
||||
uint64_t mID;
|
||||
|
||||
bool mActorDestroyed;
|
||||
};
|
||||
|
||||
} // namespace workers
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "ServiceWorkerManagerService.h"
|
||||
#include "ServiceWorkerManagerParent.h"
|
||||
#include "ServiceWorkerRegistrar.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
@ -21,6 +22,84 @@ namespace {
|
||||
|
||||
ServiceWorkerManagerService* sInstance = nullptr;
|
||||
|
||||
struct NotifySoftUpdateData
|
||||
{
|
||||
RefPtr<ServiceWorkerManagerParent> mParent;
|
||||
RefPtr<ContentParent> mContentParent;
|
||||
|
||||
~NotifySoftUpdateData()
|
||||
{
|
||||
MOZ_ASSERT(!mContentParent);
|
||||
}
|
||||
};
|
||||
|
||||
class NotifySoftUpdateIfPrincipalOkRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
NotifySoftUpdateIfPrincipalOkRunnable(
|
||||
nsAutoPtr<nsTArray<NotifySoftUpdateData>>& aData,
|
||||
const PrincipalOriginAttributes& aOriginAttributes,
|
||||
const nsAString& aScope)
|
||||
: mData(aData)
|
||||
, mOriginAttributes(aOriginAttributes)
|
||||
, mScope(aScope)
|
||||
, mBackgroundThread(NS_GetCurrentThread())
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
MOZ_ASSERT(mData && !aData);
|
||||
MOZ_ASSERT(mBackgroundThread);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Run() override
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
for (uint32_t i = 0; i < mData->Length(); ++i) {
|
||||
NotifySoftUpdateData& data = mData->ElementAt(i);
|
||||
nsTArray<TabContext> contextArray =
|
||||
data.mContentParent->GetManagedTabContext();
|
||||
// mContentParent needs to be released in the main thread.
|
||||
data.mContentParent = nullptr;
|
||||
// We only send the notification about the soft update to the
|
||||
// tabs/apps with the same appId and inBrowser values.
|
||||
// Sending a notification to the wrong process will make the process
|
||||
// to be killed.
|
||||
for (uint32_t j = 0; j < contextArray.Length(); ++j) {
|
||||
if ((contextArray[j].OwnOrContainingAppId() == mOriginAttributes.mAppId) &&
|
||||
(contextArray[j].IsBrowserElement() == mOriginAttributes.mInBrowser)) {
|
||||
continue;
|
||||
}
|
||||
// Array entries with no mParent won't receive any notification.
|
||||
data.mParent = nullptr;
|
||||
}
|
||||
}
|
||||
nsresult rv = mBackgroundThread->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
for (uint32_t i = 0; i < mData->Length(); ++i) {
|
||||
NotifySoftUpdateData& data = mData->ElementAt(i);
|
||||
MOZ_ASSERT(!(data.mContentParent));
|
||||
ServiceWorkerManagerParent* parent = data.mParent;
|
||||
if (parent && !parent->ActorDestroyed()) {
|
||||
Unused << parent->SendNotifySoftUpdate(mOriginAttributes, mScope);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<nsTArray<NotifySoftUpdateData>> mData;
|
||||
PrincipalOriginAttributes mOriginAttributes;
|
||||
nsString mScope;
|
||||
nsCOMPtr<nsIThread> mBackgroundThread;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
ServiceWorkerManagerService::ServiceWorkerManagerService()
|
||||
@ -91,7 +170,7 @@ ServiceWorkerManagerService::PropagateRegistration(
|
||||
|
||||
DebugOnly<bool> parentFound = false;
|
||||
for (auto iter = mAgents.Iter(); !iter.Done(); iter.Next()) {
|
||||
ServiceWorkerManagerParent* parent = iter.Get()->GetKey();
|
||||
RefPtr<ServiceWorkerManagerParent> parent = iter.Get()->GetKey();
|
||||
MOZ_ASSERT(parent);
|
||||
|
||||
if (parent->ID() != aParentID) {
|
||||
@ -116,21 +195,44 @@ ServiceWorkerManagerService::PropagateSoftUpdate(
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
nsAutoPtr<nsTArray<NotifySoftUpdateData>> notifySoftUpdateDataArray(
|
||||
new nsTArray<NotifySoftUpdateData>());
|
||||
DebugOnly<bool> parentFound = false;
|
||||
for (auto iter = mAgents.Iter(); !iter.Done(); iter.Next()) {
|
||||
ServiceWorkerManagerParent* parent = iter.Get()->GetKey();
|
||||
RefPtr<ServiceWorkerManagerParent> parent = iter.Get()->GetKey();
|
||||
MOZ_ASSERT(parent);
|
||||
|
||||
nsString scope(aScope);
|
||||
Unused << parent->SendNotifySoftUpdate(aOriginAttributes,
|
||||
scope);
|
||||
#ifdef DEBUG
|
||||
if (parent->ID() == aParentID) {
|
||||
parentFound = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
RefPtr<ContentParent> contentParent = parent->GetContentParent();
|
||||
|
||||
// If the ContentParent is null we are dealing with a same-process actor.
|
||||
if (!contentParent) {
|
||||
Unused << parent->SendNotifySoftUpdate(aOriginAttributes,
|
||||
nsString(aScope));
|
||||
continue;
|
||||
}
|
||||
|
||||
NotifySoftUpdateData* data = notifySoftUpdateDataArray->AppendElement();
|
||||
data->mContentParent.swap(contentParent);
|
||||
data->mParent.swap(parent);
|
||||
}
|
||||
|
||||
if (notifySoftUpdateDataArray->IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<NotifySoftUpdateIfPrincipalOkRunnable> runnable =
|
||||
new NotifySoftUpdateIfPrincipalOkRunnable(notifySoftUpdateDataArray,
|
||||
aOriginAttributes, aScope);
|
||||
MOZ_ASSERT(!notifySoftUpdateDataArray);
|
||||
nsresult rv = NS_DispatchToMainThread(runnable);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(parentFound);
|
||||
#endif
|
||||
@ -155,7 +257,7 @@ ServiceWorkerManagerService::PropagateUnregister(
|
||||
|
||||
DebugOnly<bool> parentFound = false;
|
||||
for (auto iter = mAgents.Iter(); !iter.Done(); iter.Next()) {
|
||||
ServiceWorkerManagerParent* parent = iter.Get()->GetKey();
|
||||
RefPtr<ServiceWorkerManagerParent> parent = iter.Get()->GetKey();
|
||||
MOZ_ASSERT(parent);
|
||||
|
||||
if (parent->ID() != aParentID) {
|
||||
@ -181,7 +283,7 @@ ServiceWorkerManagerService::PropagateRemove(uint64_t aParentID,
|
||||
|
||||
DebugOnly<bool> parentFound = false;
|
||||
for (auto iter = mAgents.Iter(); !iter.Done(); iter.Next()) {
|
||||
ServiceWorkerManagerParent* parent = iter.Get()->GetKey();
|
||||
RefPtr<ServiceWorkerManagerParent> parent = iter.Get()->GetKey();
|
||||
MOZ_ASSERT(parent);
|
||||
|
||||
if (parent->ID() != aParentID) {
|
||||
@ -212,7 +314,7 @@ ServiceWorkerManagerService::PropagateRemoveAll(uint64_t aParentID)
|
||||
|
||||
DebugOnly<bool> parentFound = false;
|
||||
for (auto iter = mAgents.Iter(); !iter.Done(); iter.Next()) {
|
||||
ServiceWorkerManagerParent* parent = iter.Get()->GetKey();
|
||||
RefPtr<ServiceWorkerManagerParent> parent = iter.Get()->GetKey();
|
||||
MOZ_ASSERT(parent);
|
||||
|
||||
if (parent->ID() != aParentID) {
|
||||
|
@ -569,7 +569,9 @@ BackgroundParentImpl::AllocPServiceWorkerManagerParent()
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
return new ServiceWorkerManagerParent();
|
||||
RefPtr<dom::workers::ServiceWorkerManagerParent> agent =
|
||||
new dom::workers::ServiceWorkerManagerParent();
|
||||
return agent.forget().take();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -580,7 +582,9 @@ BackgroundParentImpl::DeallocPServiceWorkerManagerParent(
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
delete static_cast<ServiceWorkerManagerParent*>(aActor);
|
||||
RefPtr<dom::workers::ServiceWorkerManagerParent> parent =
|
||||
dont_AddRef(static_cast<dom::workers::ServiceWorkerManagerParent*>(aActor));
|
||||
MOZ_ASSERT(parent);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user