Bug 1350637 - Part 9: Move Local Storage event broadcasting from PContent to PBackground. r=asuth, a=lizzard
authorJan Varga <jan.varga@gmail.com>
Tue, 08 Aug 2017 23:02:28 +0200
changeset 421302 4a23be8a70898109206ba683aaaeec61d61b32fe
parent 421301 e78fed3a2212b824729b86b0ae917b745be98c81
child 421303 a8582d18b511da750ab9b5b6ee2ba80089321d16
push id7647
push userryanvm@gmail.com
push dateMon, 21 Aug 2017 19:15:39 +0000
treeherdermozilla-beta@6a2167880016 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth, lizzard
bugs1350637
milestone56.0
Bug 1350637 - Part 9: Move Local Storage event broadcasting from PContent to PBackground. r=asuth, a=lizzard
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/storage/LocalStorage.cpp
ipc/glue/BackgroundChildImpl.cpp
ipc/glue/BackgroundChildImpl.h
ipc/glue/BackgroundParentImpl.cpp
ipc/glue/BackgroundParentImpl.h
ipc/glue/PBackground.ipdl
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -30,17 +30,16 @@
 #include "mozilla/dom/ExternalHelperAppChild.h"
 #include "mozilla/dom/FileCreatorHelper.h"
 #include "mozilla/dom/FlyWebPublishedServerIPC.h"
 #include "mozilla/dom/GetFilesHelper.h"
 #include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/dom/ProcessGlobal.h"
 #include "mozilla/dom/PushNotifier.h"
-#include "mozilla/dom/LocalStorage.h"
 #include "mozilla/dom/TabGroup.h"
 #include "mozilla/dom/workers/ServiceWorkerManager.h"
 #include "mozilla/dom/nsIContentChild.h"
 #include "mozilla/dom/URLClassifierChild.h"
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/psm/PSMContentListener.h"
 #include "mozilla/hal_sandbox/PHalChild.h"
 #include "mozilla/ipc/BackgroundChild.h"
@@ -3203,29 +3202,16 @@ ContentChild::RecvBlobURLRegistration(co
 mozilla::ipc::IPCResult
 ContentChild::RecvBlobURLUnregistration(const nsCString& aURI)
 {
   nsHostObjectProtocolHandler::RemoveDataEntry(aURI,
                                                /* aBroadcastToOtherProcesses = */ false);
   return IPC_OK();
 }
 
-mozilla::ipc::IPCResult
-ContentChild::RecvDispatchLocalStorageChange(const nsString& aDocumentURI,
-                                             const nsString& aKey,
-                                             const nsString& aOldValue,
-                                             const nsString& aNewValue,
-                                             const IPC::Principal& aPrincipal,
-                                             const bool& aIsPrivate)
-{
-  LocalStorage::DispatchStorageEvent(aDocumentURI, aKey, aOldValue, aNewValue,
-                                     aPrincipal, aIsPrivate, nullptr, true);
-  return IPC_OK();
-}
-
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
 bool
 ContentChild::SendGetA11yContentId()
 {
   return PContentChild::SendGetA11yContentId(&mMsaaID);
 }
 #endif // defined(XP_WIN) && defined(ACCESSIBILITY)
 
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -400,24 +400,16 @@ public:
   const nsAString& GetRemoteType() const;
 
   virtual mozilla::ipc::IPCResult
   RecvInitServiceWorkers(const ServiceWorkerConfiguration& aConfig) override;
 
   virtual mozilla::ipc::IPCResult
   RecvInitBlobURLs(nsTArray<BlobURLRegistrationData>&& aRegistations) override;
 
-  virtual mozilla::ipc::IPCResult
-  RecvDispatchLocalStorageChange(const nsString& aDocumentURI,
-                                 const nsString& aKey,
-                                 const nsString& aOldValue,
-                                 const nsString& aNewValue,
-                                 const IPC::Principal& aPrincipal,
-                                 const bool& aIsPrivate) override;
-
   virtual mozilla::ipc::IPCResult RecvLastPrivateDocShellDestroyed() override;
 
   virtual mozilla::ipc::IPCResult
   RecvNotifyProcessPriorityChanged(const hal::ProcessPriority& aPriority) override;
 
   virtual mozilla::ipc::IPCResult RecvMinimizeMemoryUsage() override;
 
   virtual mozilla::ipc::IPCResult RecvLoadAndRegisterSheet(const URIParams& aURI,
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -4942,35 +4942,16 @@ ContentParent::RecvUnstoreAndBroadcastBl
                                                false /* Don't broadcast */);
   BroadcastBlobURLUnregistration(aURI, this);
   mBlobURLs.RemoveElement(aURI);
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-ContentParent::RecvBroadcastLocalStorageChange(const nsString& aDocumentURI,
-                                               const nsString& aKey,
-                                               const nsString& aOldValue,
-                                               const nsString& aNewValue,
-                                               const Principal& aPrincipal,
-                                               const bool& aIsPrivate)
-{
-  for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
-    if (cp != this) {
-      Unused << cp->SendDispatchLocalStorageChange(
-        nsString(aDocumentURI), nsString(aKey), nsString(aOldValue),
-        nsString(aNewValue), IPC::Principal(aPrincipal), aIsPrivate);
-    }
-  }
-
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
 ContentParent::RecvGetA11yContentId(uint32_t* aContentId)
 {
 #if defined(XP_WIN32) && defined(ACCESSIBILITY)
   *aContentId = a11y::AccessibleWrap::GetContentProcessIdFor(ChildID());
   MOZ_ASSERT(*aContentId);
   return IPC_OK();
 #else
   return IPC_FAIL_NO_REASON(this);
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -557,24 +557,16 @@ public:
   RecvStoreAndBroadcastBlobURLRegistration(const nsCString& aURI,
                                            const IPCBlob& aBlob,
                                            const Principal& aPrincipal) override;
 
   virtual mozilla::ipc::IPCResult
   RecvUnstoreAndBroadcastBlobURLUnregistration(const nsCString& aURI) override;
 
   virtual mozilla::ipc::IPCResult
-  RecvBroadcastLocalStorageChange(const nsString& aDocumentURI,
-                                  const nsString& aKey,
-                                  const nsString& aOldValue,
-                                  const nsString& aNewValue,
-                                  const IPC::Principal& aPrincipal,
-                                  const bool& aIsPrivate) override;
-
-  virtual mozilla::ipc::IPCResult
   RecvGetA11yContentId(uint32_t* aContentId) override;
 
   virtual mozilla::ipc::IPCResult
   RecvA11yHandlerControl(const uint32_t& aPid,
                          const IHandlerControlHolder& aHandlerControl) override;
 
   virtual int32_t Pid() const override;
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -557,23 +557,16 @@ child:
 
     async GetFilesResponse(nsID aID, GetFilesResponseResult aResult);
 
     async BlobURLRegistration(nsCString aURI, IPCBlob aBlob,
                               Principal aPrincipal);
 
     async BlobURLUnregistration(nsCString aURI);
 
-    async DispatchLocalStorageChange(nsString documentURI,
-                                     nsString key,
-                                     nsString oldValue,
-                                     nsString newValue,
-                                     Principal principal,
-                                     bool isPrivate);
-
     async GMPsChanged(GMPCapabilityData[] capabilities);
 
 
     async FileCreationResponse(nsID aID, FileCreationResult aResult);
 
     /**
      * Sending an activate message moves focus to the child.
      */
@@ -1037,23 +1030,16 @@ parent:
                                int64_t lastModified, bool aExistenceCheck,
                                bool aIsFromNsIFile);
 
      async StoreAndBroadcastBlobURLRegistration(nsCString url, IPCBlob blob,
                                                 Principal principal);
 
      async UnstoreAndBroadcastBlobURLUnregistration(nsCString url);
 
-     async BroadcastLocalStorageChange(nsString documentURI,
-                                       nsString key,
-                                       nsString oldValue,
-                                       nsString newValue,
-                                       Principal principal,
-                                       bool isPrivate);
-
     /**
      * Messages for communicating child Telemetry to the parent process
      */
     async AccumulateChildHistograms(Accumulation[] accumulations);
     async AccumulateChildKeyedHistograms(KeyedAccumulation[] accumulations);
     async UpdateChildScalars(ScalarAction[] updates);
     async UpdateChildKeyedScalars(KeyedScalarAction[] updates);
     async RecordChildEvents(ChildEventData[] events);
--- a/dom/storage/LocalStorage.cpp
+++ b/dom/storage/LocalStorage.cpp
@@ -16,16 +16,18 @@
 #include "nsICookiePermission.h"
 
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/StorageBinding.h"
 #include "mozilla/dom/StorageEvent.h"
 #include "mozilla/dom/StorageEventBinding.h"
+#include "mozilla/ipc/BackgroundChild.h"
+#include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/Services.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/EnumSet.h"
 #include "nsThreadUtils.h"
 #include "nsContentUtils.h"
 #include "nsServiceManagerUtils.h"
 
 namespace mozilla {
@@ -174,23 +176,30 @@ LocalStorage::Clear(nsIPrincipal& aSubje
   }
 }
 
 void
 LocalStorage::BroadcastChangeNotification(const nsAString& aKey,
                                           const nsAString& aOldValue,
                                           const nsAString& aNewValue)
 {
-  if (!XRE_IsParentProcess() && Principal()) {
-    // If we are in a child process, we want to send a message to the parent in
-    // order to broadcast the StorageEvent correctly to any child process.
-    dom::ContentChild* cc = dom::ContentChild::GetSingleton();
-    Unused << NS_WARN_IF(!cc->SendBroadcastLocalStorageChange(
-      mDocumentURI, nsString(aKey), nsString(aOldValue), nsString(aNewValue),
-      IPC::Principal(Principal()), mIsPrivate));
+  if (Principal()) {
+    // We want to send a message to the parent in order to broadcast the
+    // StorageEvent correctly to any child process.
+
+    PBackgroundChild* actor = BackgroundChild::GetForCurrentThread();
+    MOZ_ASSERT(actor);
+
+    PrincipalInfo principalInfo;
+    nsresult rv = PrincipalToPrincipalInfo(Principal(), &principalInfo);
+    if (!NS_WARN_IF(NS_FAILED(rv))) {
+      Unused << NS_WARN_IF(!actor->SendBroadcastLocalStorageChange(
+        mDocumentURI, nsString(aKey), nsString(aOldValue), nsString(aNewValue),
+        principalInfo, mIsPrivate));
+    }
   }
 
   DispatchStorageEvent(mDocumentURI, aKey, aOldValue, aNewValue,
                        Principal(), mIsPrivate, this, false);
 }
 
 /* static */ void
 LocalStorage::DispatchStorageEvent(const nsAString& aDocumentURI,
@@ -199,26 +208,16 @@ LocalStorage::DispatchStorageEvent(const
                                    const nsAString& aNewValue,
                                    nsIPrincipal* aPrincipal,
                                    bool aIsPrivate,
                                    Storage* aStorage,
                                    bool aImmediateDispatch)
 {
   NotifyChange(aStorage, aPrincipal, aKey, aOldValue, aNewValue,
                u"localStorage", aDocumentURI, aIsPrivate, aImmediateDispatch);
-
-  // If we are in the parent process and we have the principal, we want to
-  // broadcast this event to every other process.
-  if (XRE_IsParentProcess() && aPrincipal) {
-    for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
-      Unused << cp->SendDispatchLocalStorageChange(
-        nsString(aDocumentURI), nsString(aKey), nsString(aOldValue),
-        nsString(aNewValue), IPC::Principal(aPrincipal), aIsPrivate);
-    }
-  }
 }
 
 void
 LocalStorage::ApplyEvent(StorageEvent* aStorageEvent)
 {
   MOZ_ASSERT(aStorageEvent);
 
   nsAutoString key;
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -24,16 +24,17 @@
 #include "mozilla/dom/indexedDB/PBackgroundIndexedDBUtilsChild.h"
 #include "mozilla/dom/ipc/IPCBlobInputStreamChild.h"
 #include "mozilla/dom/ipc/PendingIPCBlobChild.h"
 #include "mozilla/dom/quota/PQuotaChild.h"
 #include "mozilla/dom/StorageIPC.h"
 #include "mozilla/dom/GamepadEventChannelChild.h"
 #include "mozilla/dom/GamepadTestChannelChild.h"
 #include "mozilla/dom/MessagePortChild.h"
+#include "mozilla/dom/LocalStorage.h"
 #include "mozilla/ipc/IPCStreamAlloc.h"
 #include "mozilla/ipc/PBackgroundTestChild.h"
 #include "mozilla/ipc/PChildToParentStreamChild.h"
 #include "mozilla/ipc/PParentToChildStreamChild.h"
 #include "mozilla/layout/VsyncChild.h"
 #include "mozilla/net/HttpBackgroundChannelChild.h"
 #include "mozilla/net/PUDPSocketChild.h"
 #include "mozilla/dom/network/UDPSocketChild.h"
@@ -73,16 +74,17 @@ namespace ipc {
 
 using mozilla::dom::UDPSocketChild;
 using mozilla::net::PUDPSocketChild;
 
 using mozilla::dom::asmjscache::PAsmJSCacheEntryChild;
 using mozilla::dom::cache::PCacheChild;
 using mozilla::dom::cache::PCacheStorageChild;
 using mozilla::dom::cache::PCacheStreamControlChild;
+using mozilla::dom::LocalStorage;
 using mozilla::dom::StorageDBChild;
 
 using mozilla::dom::WebAuthnTransactionChild;
 
 // -----------------------------------------------------------------------------
 // BackgroundChildImpl::ThreadLocal
 // -----------------------------------------------------------------------------
 
@@ -592,16 +594,42 @@ BackgroundChildImpl::DeallocPHttpBackgro
   // The reference is increased in BackgroundChannelCreateCallback::ActorCreated
   // of HttpBackgroundChannelChild.cpp. We should decrease it after IPC
   // destroyed.
   RefPtr<net::HttpBackgroundChannelChild> child =
     dont_AddRef(static_cast<net::HttpBackgroundChannelChild*>(aActor));
   return true;
 }
 
+mozilla::ipc::IPCResult
+BackgroundChildImpl::RecvDispatchLocalStorageChange(
+                                            const nsString& aDocumentURI,
+                                            const nsString& aKey,
+                                            const nsString& aOldValue,
+                                            const nsString& aNewValue,
+                                            const PrincipalInfo& aPrincipalInfo,
+                                            const bool& aIsPrivate)
+{
+  if (!NS_IsMainThread()) {
+    return IPC_OK();
+  }
+
+  nsresult rv;
+  nsCOMPtr<nsIPrincipal> principal =
+    PrincipalInfoToPrincipal(aPrincipalInfo, &rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  LocalStorage::DispatchStorageEvent(aDocumentURI, aKey, aOldValue, aNewValue,
+                                     principal, aIsPrivate, nullptr, true);
+
+  return IPC_OK();
+}
+
 } // namespace ipc
 } // namespace mozilla
 
 mozilla::ipc::IPCResult
 TestChild::Recv__delete__(const nsCString& aTestArg)
 {
   MOZ_RELEASE_ASSERT(aTestArg == mTestArg,
                      "BackgroundTest message was corrupted!");
--- a/ipc/glue/BackgroundChildImpl.h
+++ b/ipc/glue/BackgroundChildImpl.h
@@ -209,16 +209,24 @@ protected:
   virtual bool
   DeallocPWebAuthnTransactionChild(PWebAuthnTransactionChild* aActor) override;
 
   virtual PHttpBackgroundChannelChild*
   AllocPHttpBackgroundChannelChild(const uint64_t& aChannelId) override;
 
   virtual bool
   DeallocPHttpBackgroundChannelChild(PHttpBackgroundChannelChild* aActor) override;
+
+  virtual mozilla::ipc::IPCResult
+  RecvDispatchLocalStorageChange(const nsString& aDocumentURI,
+                                 const nsString& aKey,
+                                 const nsString& aOldValue,
+                                 const nsString& aNewValue,
+                                 const PrincipalInfo& aPrincipalInfo,
+                                 const bool& aIsPrivate) override;
 };
 
 class BackgroundChildImpl::ThreadLocal final
 {
   friend class nsAutoPtr<ThreadLocal>;
 
 public:
   nsAutoPtr<mozilla::dom::indexedDB::ThreadLocal> mIndexedDBThreadLocal;
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -271,16 +271,41 @@ BackgroundParentImpl::DeallocPBackground
 {
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   return mozilla::dom::DeallocPBackgroundStorageParent(aActor);
 }
 
+mozilla::ipc::IPCResult
+BackgroundParentImpl::RecvBroadcastLocalStorageChange(
+                                            const nsString& aDocumentURI,
+                                            const nsString& aKey,
+                                            const nsString& aOldValue,
+                                            const nsString& aNewValue,
+                                            const PrincipalInfo& aPrincipalInfo,
+                                            const bool& aIsPrivate)
+{
+  nsTArray<PBackgroundParent*> liveActorArray;
+  if (NS_WARN_IF(!BackgroundParent::GetLiveActorArray(this, liveActorArray))) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  for (auto* liveActor : liveActorArray) {
+    if (liveActor != this) {
+      Unused << liveActor->SendDispatchLocalStorageChange(
+        nsString(aDocumentURI), nsString(aKey), nsString(aOldValue),
+        nsString(aNewValue), aPrincipalInfo, aIsPrivate);
+    }
+  }
+
+  return IPC_OK();
+}
+
 PPendingIPCBlobParent*
 BackgroundParentImpl::AllocPPendingIPCBlobParent(const IPCBlob& aBlob)
 {
   MOZ_CRASH("PPendingIPCBlobParent actors should be manually constructed!");
 }
 
 bool
 BackgroundParentImpl::DeallocPPendingIPCBlobParent(PPendingIPCBlobParent* aActor)
--- a/ipc/glue/BackgroundParentImpl.h
+++ b/ipc/glue/BackgroundParentImpl.h
@@ -68,16 +68,24 @@ protected:
 
   virtual mozilla::ipc::IPCResult
   RecvPBackgroundStorageConstructor(PBackgroundStorageParent* aActor,
                                     const nsString& aProfilePath) override;
 
   virtual bool
   DeallocPBackgroundStorageParent(PBackgroundStorageParent* aActor) override;
 
+  virtual mozilla::ipc::IPCResult
+  RecvBroadcastLocalStorageChange(const nsString& aDocumentURI,
+                                  const nsString& aKey,
+                                  const nsString& aOldValue,
+                                  const nsString& aNewValue,
+                                  const PrincipalInfo& aPrincipalInfo,
+                                  const bool& aIsPrivate) override;
+
   virtual PPendingIPCBlobParent*
   AllocPPendingIPCBlobParent(const IPCBlob& aBlob) override;
 
   virtual bool
   DeallocPPendingIPCBlobParent(PPendingIPCBlobParent* aActor) override;
 
   virtual PIPCBlobInputStreamParent*
   AllocPIPCBlobInputStreamParent(const nsID& aID,
--- a/ipc/glue/PBackground.ipdl
+++ b/ipc/glue/PBackground.ipdl
@@ -85,16 +85,23 @@ parent:
 
   async PBackgroundIndexedDBUtils();
 
   // Use only for testing!
   async FlushPendingFileDeletions();
 
   async PBackgroundStorage(nsString profilePath);
 
+  async BroadcastLocalStorageChange(nsString documentURI,
+                                    nsString key,
+                                    nsString oldValue,
+                                    nsString newValue,
+                                    PrincipalInfo principalInfo,
+                                    bool isPrivate);
+
   async PVsync();
 
   async PCameras();
 
   async PUDPSocket(OptionalPrincipalInfo pInfo, nsCString filter);
   async PBroadcastChannel(PrincipalInfo pInfo, nsCString origin, nsString channel);
 
   async PServiceWorkerManager();
@@ -128,16 +135,23 @@ parent:
 child:
   async PCache();
   async PCacheStreamControl();
 
   async PParentToChildStream();
 
   async PPendingIPCBlob(IPCBlob blob);
 
+  async DispatchLocalStorageChange(nsString documentURI,
+                                   nsString key,
+                                   nsString oldValue,
+                                   nsString newValue,
+                                   PrincipalInfo principalInfo,
+                                   bool isPrivate);
+
 both:
   // PIPCBlobInputStream is created on the parent side only if the child starts
   // a migration.
   async PIPCBlobInputStream(nsID aID, uint64_t aSize);
 
   async PFileDescriptorSet(FileDescriptor fd);
 };