Bug 1252998 - StorageActivityService - part 1 - Introduce StorageActivityService to monitor origin activities, r=asuth
☠☠ backed out by ca0c739344f2 ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Mon, 08 Jan 2018 08:31:34 +0100
changeset 449957 f4955cf6447f23ced615c6b8855b158e987ae4f8
parent 449956 cb4fd975b8bb668aa5b877386b8cf02f62561107
child 449958 609093736110bbd6b341cbb00f91c1f5f5553ee4
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1252998
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1252998 - StorageActivityService - part 1 - Introduce StorageActivityService to monitor origin activities, r=asuth
dom/interfaces/storage/moz.build
dom/interfaces/storage/nsIStorageActivityService.idl
dom/storage/StorageActivityService.cpp
dom/storage/StorageActivityService.h
dom/storage/moz.build
ipc/glue/BackgroundParentImpl.cpp
ipc/glue/BackgroundParentImpl.h
ipc/glue/PBackground.ipdl
layout/build/nsLayoutCID.h
layout/build/nsLayoutModule.cpp
--- a/dom/interfaces/storage/moz.build
+++ b/dom/interfaces/storage/moz.build
@@ -5,11 +5,12 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM")
 
 XPIDL_SOURCES += [
     'nsIDOMStorage.idl',
     'nsIDOMStorageManager.idl',
+    'nsIStorageActivityService.idl',
 ]
 
 XPIDL_MODULE = 'dom_storage'
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/storage/nsIStorageActivityService.idl
@@ -0,0 +1,25 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "domstubs.idl"
+
+/**
+ * nsIStorageActivityService is a service that can be used to know which
+ * origins have been active in a time range. This information can be used to
+ * implement "Clear Recent History" or similar features.
+ *
+ * If you are implementing a new Storage component, you should use
+ * QuotaManager. But if you don't do it, remember to call
+ * StorageActivityService methods in order to inform this service about
+ * 'writing' operations executed by origins.
+ */
+[scriptable, builtinclass, uuid(fd1310ba-d1be-4327-988e-92b39fcff6f4)]
+interface nsIStorageActivityService : nsISupports
+{
+};
+
+%{ C++
+#define STORAGE_ACTIVITY_SERVICE_CONTRACTID "@mozilla.org/storage/activity-service;1"
+%}
new file mode 100644
--- /dev/null
+++ b/dom/storage/StorageActivityService.cpp
@@ -0,0 +1,209 @@
+/* -*- 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 "StorageActivityService.h"
+
+#include "mozilla/ipc/BackgroundUtils.h"
+#include "mozilla/StaticPtr.h"
+#include "nsXPCOM.h"
+
+// This const is used to know when origin activities should be purged because
+// too old. This value should be in sync with what the UI needs.
+#define TIME_MAX_SECS 86400 /* 24 hours */
+
+namespace mozilla {
+namespace dom {
+
+static StaticRefPtr<StorageActivityService> gStorageActivityService;
+static bool gStorageActivityShutdown = false;
+
+/* static */ void
+StorageActivityService::SendActivity(nsIPrincipal* aPrincipal)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  RefPtr<StorageActivityService> service = GetOrCreate();
+  if (NS_WARN_IF(!service)) {
+    return;
+  }
+
+  service->SendActivityInternal(aPrincipal);
+}
+
+/* static */ void
+StorageActivityService::SendActivity(const mozilla::ipc::PrincipalInfo& aPrincipalInfo)
+{
+  RefPtr<Runnable> r = NS_NewRunnableFunction(
+    "StorageActivityService::SendActivity",
+    [aPrincipalInfo] () {
+      MOZ_ASSERT(NS_IsMainThread());
+
+      nsCOMPtr<nsIPrincipal> principal =
+        mozilla::ipc::PrincipalInfoToPrincipal(aPrincipalInfo);
+
+      StorageActivityService::SendActivity(principal);
+    });
+
+  SystemGroup::Dispatch(TaskCategory::Other, r.forget());
+}
+
+/* static */ already_AddRefed<StorageActivityService>
+StorageActivityService::GetOrCreate()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!gStorageActivityService && !gStorageActivityShutdown) {
+    RefPtr<StorageActivityService> service = new StorageActivityService();
+
+    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+    if (NS_WARN_IF(!obs)) {
+      return nullptr;
+    }
+
+    nsresult rv = obs->AddObserver(service, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return nullptr;
+    }
+
+    gStorageActivityService = service;
+  }
+
+  RefPtr<StorageActivityService> service = gStorageActivityService;
+  return service.forget();
+}
+
+StorageActivityService::StorageActivityService()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+StorageActivityService::~StorageActivityService()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!mTimer);
+}
+
+void
+StorageActivityService::SendActivityInternal(nsIPrincipal* aPrincipal)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aPrincipal);
+
+  if (!XRE_IsParentProcess()) {
+    SendActivityToParent(aPrincipal);
+    return;
+  }
+
+  nsAutoCString origin;
+  nsresult rv = aPrincipal->GetOrigin(origin);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+
+  mActivities.Put(origin, TimeStamp::NowLoRes());
+
+  MaybeStartTimer();
+}
+
+void
+StorageActivityService::SendActivityToParent(nsIPrincipal* aPrincipal)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!XRE_IsParentProcess());
+
+  PBackgroundChild* actor = BackgroundChild::GetOrCreateForCurrentThread();
+  if (NS_WARN_IF(!actor)) {
+    return;
+  }
+
+  mozilla::ipc::PrincipalInfo principalInfo;
+  nsresult rv =
+    mozilla::ipc::PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+
+  actor->SendStorageActivity(principalInfo);
+}
+
+NS_IMETHODIMP
+StorageActivityService::Observe(nsISupports* aSubject, const char* aTopic,
+                                const char16_t* aData)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID));
+
+  MaybeStopTimer();
+
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  if (obs) {
+    obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
+  }
+
+  gStorageActivityShutdown = true;
+  gStorageActivityService = nullptr;
+  return NS_OK;
+}
+
+void
+StorageActivityService::MaybeStartTimer()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!mTimer) {
+    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mTimer->InitWithCallback(this,
+                             1000 * 5 * 60 /* any 5 minutes */,
+                             nsITimer::TYPE_REPEATING_SLACK);
+  }
+}
+
+void
+StorageActivityService::MaybeStopTimer()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (mTimer) {
+    mTimer->Cancel();
+    mTimer = nullptr;
+  }
+}
+
+NS_IMETHODIMP
+StorageActivityService::Notify(nsITimer* aTimer)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mTimer == aTimer);
+
+  TimeStamp now = TimeStamp::NowLoRes();
+
+  for (auto iter = mActivities.Iter(); !iter.Done(); iter.Next()) {
+    if ((now - iter.UserData()).ToSeconds() > TIME_MAX_SECS) {
+      iter.Remove();
+    }
+  }
+
+  // If no activities, let's stop the timer.
+  if (mActivities.Count() == 0) {
+    MaybeStopTimer();
+  }
+
+  return NS_OK;
+}
+
+NS_INTERFACE_MAP_BEGIN(StorageActivityService)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStorageActivityService)
+  NS_INTERFACE_MAP_ENTRY(nsIStorageActivityService)
+  NS_INTERFACE_MAP_ENTRY(nsIObserver)
+  NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(StorageActivityService)
+NS_IMPL_RELEASE(StorageActivityService)
+
+} // dom namespace
+} // mozilla namespace
new file mode 100644
--- /dev/null
+++ b/dom/storage/StorageActivityService.h
@@ -0,0 +1,71 @@
+/* -*- 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_StorageActivityService_h
+#define mozilla_dom_StorageActivityService_h
+
+#include "nsDataHashtable.h"
+#include "nsIStorageActivityService.h"
+#include "nsITimer.h"
+#include "nsWeakReference.h"
+
+namespace mozilla {
+
+namespace ipc {
+class PrincipalInfo;
+} // ipc
+
+namespace dom {
+
+class StorageActivityService final : public nsIStorageActivityService
+                                   , public nsIObserver
+                                   , public nsITimerCallback
+                                   , public nsSupportsWeakReference
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSISTORAGEACTIVITYSERVICE
+  NS_DECL_NSIOBSERVER
+  NS_DECL_NSITIMERCALLBACK
+
+  // Main-thread only.
+  static void
+  SendActivity(nsIPrincipal* aPrincipal);
+
+  // Thread-safe.
+  static void
+  SendActivity(const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
+
+  // Used by XPCOM. Don't use it, use SendActivity() instead.
+  static already_AddRefed<StorageActivityService>
+  GetOrCreate();
+
+private:
+  StorageActivityService();
+  ~StorageActivityService();
+
+  void
+  SendActivityInternal(nsIPrincipal* aPrincipal);
+
+  void
+  SendActivityToParent(nsIPrincipal* aPrincipal);
+
+  void
+  MaybeStartTimer();
+
+  void
+  MaybeStopTimer();
+
+  // Activities grouped by origin (+OriginAttributes).
+  nsDataHashtable<nsCStringHashKey, TimeStamp> mActivities;
+
+  nsCOMPtr<nsITimer> mTimer;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_StorageActivityService_h
--- a/dom/storage/moz.build
+++ b/dom/storage/moz.build
@@ -7,29 +7,31 @@
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM")
 
 EXPORTS.mozilla.dom += [
     'LocalStorage.h',
     'LocalStorageManager.h',
     'SessionStorageManager.h',
     'Storage.h',
+    'StorageActivityService.h',
     'StorageIPC.h',
     'StorageNotifierService.h',
     'StorageUtils.h',
 ]
 
 UNIFIED_SOURCES += [
     'LocalStorage.cpp',
     'LocalStorageCache.cpp',
     'LocalStorageManager.cpp',
     'SessionStorage.cpp',
     'SessionStorageCache.cpp',
     'SessionStorageManager.cpp',
     'Storage.cpp',
+    'StorageActivityService.cpp',
     'StorageDBThread.cpp',
     'StorageDBUpdater.cpp',
     'StorageIPC.cpp',
     'StorageNotifierService.cpp',
     'StorageObserver.cpp',
     'StorageUtils.cpp',
 ]
 
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -19,16 +19,17 @@
 #include "mozilla/dom/FileSystemBase.h"
 #include "mozilla/dom/FileSystemRequestParent.h"
 #include "mozilla/dom/GamepadEventChannelParent.h"
 #include "mozilla/dom/GamepadTestChannelParent.h"
 #include "mozilla/dom/PGamepadEventChannelParent.h"
 #include "mozilla/dom/PGamepadTestChannelParent.h"
 #include "mozilla/dom/MessagePortParent.h"
 #include "mozilla/dom/ServiceWorkerRegistrar.h"
+#include "mozilla/dom/StorageActivityService.h"
 #include "mozilla/dom/asmjscache/AsmJSCache.h"
 #include "mozilla/dom/cache/ActorUtils.h"
 #include "mozilla/dom/indexedDB/ActorsParent.h"
 #include "mozilla/dom/ipc/IPCBlobInputStreamParent.h"
 #include "mozilla/dom/ipc/PendingIPCBlobParent.h"
 #include "mozilla/dom/ipc/TemporaryIPCBlobParent.h"
 #include "mozilla/dom/quota/ActorsParent.h"
 #include "mozilla/dom/StorageIPC.h"
@@ -982,16 +983,23 @@ BackgroundParentImpl::DeallocPClientMana
 
 mozilla::ipc::IPCResult
 BackgroundParentImpl::RecvPClientManagerConstructor(mozilla::dom::PClientManagerParent* aActor)
 {
   mozilla::dom::InitClientManagerParent(aActor);
   return IPC_OK();
 }
 
+IPCResult
+BackgroundParentImpl::RecvStorageActivity(const PrincipalInfo& aPrincipalInfo)
+{
+  dom::StorageActivityService::SendActivity(aPrincipalInfo);
+  return IPC_OK();
+}
+
 } // namespace ipc
 } // namespace mozilla
 
 void
 TestParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   mozilla::ipc::AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
--- a/ipc/glue/BackgroundParentImpl.h
+++ b/ipc/glue/BackgroundParentImpl.h
@@ -266,14 +266,17 @@ protected:
   virtual PClientManagerParent*
   AllocPClientManagerParent() override;
 
   virtual bool
   DeallocPClientManagerParent(PClientManagerParent* aActor) override;
 
   virtual mozilla::ipc::IPCResult
   RecvPClientManagerConstructor(PClientManagerParent* aActor) override;
+
+  virtual mozilla::ipc::IPCResult
+  RecvStorageActivity(const PrincipalInfo& aPrincipalInfo) override;
 };
 
 } // namespace ipc
 } // namespace mozilla
 
 #endif // mozilla_ipc_backgroundparentimpl_h__
--- a/ipc/glue/PBackground.ipdl
+++ b/ipc/glue/PBackground.ipdl
@@ -135,16 +135,20 @@ parent:
   async PHttpBackgroundChannel(uint64_t channelId);
 
   async PWebAuthnTransaction();
 
   async PTemporaryIPCBlob();
 
   async PClientManager();
 
+  // This method is used to propagate storage activities from the child actor
+  // to the parent actor. See StorageActivityService.
+  async StorageActivity(PrincipalInfo principalInfo);
+
 child:
   async PCache();
   async PCacheStreamControl();
 
   async PParentToChildStream();
 
   async PPendingIPCBlob(IPCBlob blob);
 
--- a/layout/build/nsLayoutCID.h
+++ b/layout/build/nsLayoutCID.h
@@ -74,12 +74,16 @@
 // {5a75c25a-5e7e-4d90-8f7c-07eb15cc0aa8}
 #define QUOTAMANAGER_SERVICE_CID \
 { 0x5a75c25a, 0x5e7e, 0x4d90, { 0x8f, 0x7c, 0x07, 0xeb, 0x15, 0xcc, 0x0a, 0xa8 } }
 
 // {c74bde32-bcc7-4840-8430-c733351b212a}
 #define SERVICEWORKERMANAGER_CID \
 { 0xc74bde32, 0xbcc7, 0x4840, { 0x84, 0x30, 0xc7, 0x33, 0x35, 0x1b, 0x21, 0x2a } }
 
+// {69da374a-fda3-4a93-9fbc-d9304f66a7fe}
+#define STORAGEACTIVITYSERVICE_CID \
+{ 0x69da374a, 0xfda3, 0x4a93, { 0x9f, 0xbc, 0xd9, 0x30, 0x4f, 0x66, 0xa7, 0xfe } }
+
 #define NOTIFICATIONTELEMETRYSERVICE_CID \
 { 0x5995b782, 0x6a0e, 0x4066, { 0xaa, 0xc5, 0x27, 0x6f, 0x0a, 0x9a, 0xd8, 0xcf } }
 
 #endif /* nsLayoutCID_h__ */
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -78,16 +78,17 @@
 #include "nsZipArchive.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMRequest.h"
 #include "mozilla/dom/LocalStorageManager.h"
 #include "mozilla/dom/network/UDPSocketChild.h"
 #include "mozilla/dom/quota/QuotaManagerService.h"
 #include "mozilla/dom/SessionStorageManager.h"
+#include "mozilla/dom/StorageActivityService.h"
 #include "mozilla/dom/workers/ServiceWorkerManager.h"
 #include "mozilla/dom/workers/WorkerDebuggerManager.h"
 #include "mozilla/dom/Notification.h"
 #include "mozilla/OSFileConstants.h"
 #include "mozilla/Services.h"
 
 #ifdef MOZ_WEBSPEECH_TEST_BACKEND
 #include "mozilla/dom/FakeSpeechRecognitionService.h"
@@ -247,16 +248,18 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(SessionSt
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(DOMRequestService,
                                          DOMRequestService::FactoryCreate)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(QuotaManagerService,
                                          QuotaManagerService::FactoryCreate)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ServiceWorkerManager,
                                          ServiceWorkerManager::GetInstance)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WorkerDebuggerManager,
                                          WorkerDebuggerManager::GetInstance)
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(StorageActivityService,
+                                         StorageActivityService::GetOrCreate)
 
 #ifdef MOZ_WEBSPEECH
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsSynthVoiceRegistry,
                                          nsSynthVoiceRegistry::GetInstanceForService)
 #endif
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(AudioChannelAgent)
 
@@ -620,16 +623,17 @@ NS_DEFINE_NAMED_CID(NS_HOSTOBJECTURI_CID
 NS_DEFINE_NAMED_CID(NS_XMLHTTPREQUEST_CID);
 NS_DEFINE_NAMED_CID(NS_DOMPARSER_CID);
 NS_DEFINE_NAMED_CID(NS_DOMSESSIONSTORAGEMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_DOMLOCALSTORAGEMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_TEXTEDITOR_CID);
 NS_DEFINE_NAMED_CID(DOMREQUEST_SERVICE_CID);
 NS_DEFINE_NAMED_CID(QUOTAMANAGER_SERVICE_CID);
 NS_DEFINE_NAMED_CID(SERVICEWORKERMANAGER_CID);
+NS_DEFINE_NAMED_CID(STORAGEACTIVITYSERVICE_CID);
 NS_DEFINE_NAMED_CID(NOTIFICATIONTELEMETRYSERVICE_CID);
 NS_DEFINE_NAMED_CID(PUSHNOTIFIER_CID);
 NS_DEFINE_NAMED_CID(WORKERDEBUGGERMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_AUDIOCHANNELAGENT_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLEDITOR_CID);
 NS_DEFINE_NAMED_CID(NS_EDITORCONTROLLER_CID);
 NS_DEFINE_NAMED_CID(NS_EDITINGCONTROLLER_CID);
 NS_DEFINE_NAMED_CID(NS_EDITORCOMMANDTABLE_CID);
@@ -877,16 +881,17 @@ static const mozilla::Module::CIDEntry k
   { &kNS_DOMPARSER_CID, false, nullptr, DOMParserConstructor },
   { &kNS_XPCEXCEPTION_CID, false, nullptr, ExceptionConstructor },
   { &kNS_DOMSESSIONSTORAGEMANAGER_CID, false, nullptr, SessionStorageManagerConstructor },
   { &kNS_DOMLOCALSTORAGEMANAGER_CID, false, nullptr, LocalStorageManagerConstructor },
   { &kNS_TEXTEDITOR_CID, false, nullptr, TextEditorConstructor },
   { &kDOMREQUEST_SERVICE_CID, false, nullptr, DOMRequestServiceConstructor },
   { &kQUOTAMANAGER_SERVICE_CID, false, nullptr, QuotaManagerServiceConstructor },
   { &kSERVICEWORKERMANAGER_CID, false, nullptr, ServiceWorkerManagerConstructor },
+  { &kSTORAGEACTIVITYSERVICE_CID, false, nullptr, StorageActivityServiceConstructor },
   { &kNOTIFICATIONTELEMETRYSERVICE_CID, false, nullptr, NotificationTelemetryServiceConstructor },
   { &kPUSHNOTIFIER_CID, false, nullptr, PushNotifierConstructor },
   { &kWORKERDEBUGGERMANAGER_CID, true, nullptr, WorkerDebuggerManagerConstructor },
   { &kNS_AUDIOCHANNELAGENT_CID, true, nullptr, AudioChannelAgentConstructor },
   { &kNS_HTMLEDITOR_CID, false, nullptr, HTMLEditorConstructor },
   { &kNS_EDITORCONTROLLER_CID, false, nullptr, EditorControllerConstructor },
   { &kNS_EDITINGCONTROLLER_CID, false, nullptr, nsEditingControllerConstructor },
   { &kNS_EDITORCOMMANDTABLE_CID, false, nullptr, nsEditorCommandTableConstructor },
@@ -1002,16 +1007,17 @@ static const mozilla::Module::ContractID
   { "@mozilla.org/dom/localStorage-manager;1", &kNS_DOMLOCALSTORAGEMANAGER_CID },
   // Keeping the old ContractID for backward compatibility
   { "@mozilla.org/dom/storagemanager;1", &kNS_DOMLOCALSTORAGEMANAGER_CID },
   { "@mozilla.org/dom/sessionStorage-manager;1", &kNS_DOMSESSIONSTORAGEMANAGER_CID },
   { "@mozilla.org/editor/texteditor;1", &kNS_TEXTEDITOR_CID },
   { DOMREQUEST_SERVICE_CONTRACTID, &kDOMREQUEST_SERVICE_CID },
   { QUOTAMANAGER_SERVICE_CONTRACTID, &kQUOTAMANAGER_SERVICE_CID },
   { SERVICEWORKERMANAGER_CONTRACTID, &kSERVICEWORKERMANAGER_CID },
+  { STORAGE_ACTIVITY_SERVICE_CONTRACTID, &kSTORAGEACTIVITYSERVICE_CID },
   { NOTIFICATIONTELEMETRYSERVICE_CONTRACTID, &kNOTIFICATIONTELEMETRYSERVICE_CID },
   { PUSHNOTIFIER_CONTRACTID, &kPUSHNOTIFIER_CID },
   { WORKERDEBUGGERMANAGER_CONTRACTID, &kWORKERDEBUGGERMANAGER_CID },
   { NS_AUDIOCHANNELAGENT_CONTRACTID, &kNS_AUDIOCHANNELAGENT_CID },
   { "@mozilla.org/editor/htmleditor;1", &kNS_HTMLEDITOR_CID },
   { "@mozilla.org/editor/editorcontroller;1", &kNS_EDITORCONTROLLER_CID },
   { "@mozilla.org/editor/editingcontroller;1", &kNS_EDITINGCONTROLLER_CID },
   { "@mozilla.org/textservices/textservicesdocument;1", &kNS_TEXTSERVICESDOCUMENT_CID },