зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1252998 - StorageActivityService - part 1 - Introduce StorageActivityService to monitor origin activities, r=asuth
This commit is contained in:
Родитель
b4db81eb44
Коммит
1ac04372e5
|
@ -10,6 +10,7 @@ with Files("**"):
|
|||
XPIDL_SOURCES += [
|
||||
'nsIDOMStorage.idl',
|
||||
'nsIDOMStorageManager.idl',
|
||||
'nsIStorageActivityService.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_storage'
|
||||
|
|
|
@ -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"
|
||||
%}
|
|
@ -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
|
|
@ -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
|
|
@ -12,6 +12,7 @@ EXPORTS.mozilla.dom += [
|
|||
'LocalStorageManager.h',
|
||||
'SessionStorageManager.h',
|
||||
'Storage.h',
|
||||
'StorageActivityService.h',
|
||||
'StorageIPC.h',
|
||||
'StorageNotifierService.h',
|
||||
'StorageUtils.h',
|
||||
|
@ -25,6 +26,7 @@ UNIFIED_SOURCES += [
|
|||
'SessionStorageCache.cpp',
|
||||
'SessionStorageManager.cpp',
|
||||
'Storage.cpp',
|
||||
'StorageActivityService.cpp',
|
||||
'StorageDBThread.cpp',
|
||||
'StorageDBUpdater.cpp',
|
||||
'StorageIPC.cpp',
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#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"
|
||||
|
@ -987,6 +988,13 @@ BackgroundParentImpl::RecvPClientManagerConstructor(mozilla::dom::PClientManager
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
BackgroundParentImpl::RecvStorageActivity(const PrincipalInfo& aPrincipalInfo)
|
||||
{
|
||||
dom::StorageActivityService::SendActivity(aPrincipalInfo);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -271,6 +271,9 @@ protected:
|
|||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvPClientManagerConstructor(PClientManagerParent* aActor) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvStorageActivity(const PrincipalInfo& aPrincipalInfo) override;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
|
|
|
@ -140,6 +140,10 @@ parent:
|
|||
|
||||
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();
|
||||
|
|
|
@ -79,6 +79,10 @@
|
|||
#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 } }
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
#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"
|
||||
|
@ -252,6 +253,8 @@ 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,
|
||||
|
@ -625,6 +628,7 @@ 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);
|
||||
|
@ -882,6 +886,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
|
|||
{ &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 },
|
||||
|
@ -1007,6 +1012,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
|
|||
{ 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 },
|
||||
|
|
Загрузка…
Ссылка в новой задаче