mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 1350637 - Part 5: Factor out the parent actor observer sink to work on the PBackground thread, fix the rest of observer handling to use IPC; r=asuth
This commit is contained in:
parent
75c214b7ea
commit
3acd1f5628
@ -6,6 +6,11 @@
|
||||
|
||||
include protocol PBackground;
|
||||
|
||||
include "mozilla/dom/quota/SerializationHelpers.h";
|
||||
|
||||
using mozilla::OriginAttributesPattern
|
||||
from "mozilla/OriginAttributes.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@ -35,7 +40,17 @@ parent:
|
||||
nsString key);
|
||||
async AsyncClear(nsCString originSuffix, nsCString originNoSuffix);
|
||||
async AsyncFlush();
|
||||
|
||||
|
||||
// These are privileged operations for use only by the observer API for
|
||||
// delayed initialization and clearing origins and will never be used from
|
||||
// content process children. Ideally these would be guarded by checks or
|
||||
// exist on a separate, privileged interface, but PBackgroundStorage is
|
||||
// already insecure.
|
||||
async Startup();
|
||||
async ClearAll();
|
||||
async ClearMatchingOrigin(nsCString originNoSuffix);
|
||||
async ClearMatchingOriginAttributes(OriginAttributesPattern pattern);
|
||||
|
||||
child:
|
||||
async Observe(nsCString topic,
|
||||
nsString originAttributesPattern,
|
||||
|
@ -303,6 +303,8 @@ StorageDBChild::RecvObserve(const nsCString& aTopic,
|
||||
const nsString& aOriginAttributesPattern,
|
||||
const nsCString& aOriginScope)
|
||||
{
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
|
||||
StorageObserver::Self()->Notify(
|
||||
aTopic.get(), aOriginAttributesPattern, aOriginScope);
|
||||
return IPC_OK();
|
||||
@ -406,6 +408,52 @@ ShutdownObserver::Observe(nsISupports* aSubject,
|
||||
// Parent
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class StorageDBParent::ObserverSink
|
||||
: public StorageObserverSink
|
||||
{
|
||||
nsCOMPtr<nsIEventTarget> mOwningEventTarget;
|
||||
|
||||
// Only touched on the PBackground thread.
|
||||
StorageDBParent* MOZ_NON_OWNING_REF mActor;
|
||||
|
||||
public:
|
||||
explicit ObserverSink(StorageDBParent* aActor)
|
||||
: mOwningEventTarget(GetCurrentThreadEventTarget())
|
||||
, mActor(aActor)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aActor);
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StorageDBParent::ObserverSink);
|
||||
|
||||
void
|
||||
Start();
|
||||
|
||||
void
|
||||
Stop();
|
||||
|
||||
private:
|
||||
~ObserverSink() = default;
|
||||
|
||||
void
|
||||
AddSink();
|
||||
|
||||
void
|
||||
RemoveSink();
|
||||
|
||||
void
|
||||
Notify(const nsCString& aTopic,
|
||||
const nsString& aOriginAttributesPattern,
|
||||
const nsCString& aOriginScope);
|
||||
|
||||
// StorageObserverSink
|
||||
nsresult
|
||||
Observe(const char* aTopic,
|
||||
const nsAString& aOriginAttrPattern,
|
||||
const nsACString& aOriginScope) override;
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF(StorageDBParent)
|
||||
NS_IMPL_RELEASE(StorageDBParent)
|
||||
|
||||
@ -442,6 +490,8 @@ private:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mParent->Init();
|
||||
|
||||
StorageDBThread* storageThread = StorageDBThread::Get();
|
||||
if (storageThread) {
|
||||
InfallibleTArray<nsCString> scopes;
|
||||
@ -479,10 +529,7 @@ private:
|
||||
StorageDBParent::StorageDBParent()
|
||||
: mIPCOpen(false)
|
||||
{
|
||||
StorageObserver* observer = StorageObserver::Self();
|
||||
if (observer) {
|
||||
observer->AddSink(this);
|
||||
}
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
// We are always open by IPC only
|
||||
AddIPDLReference();
|
||||
@ -496,9 +543,25 @@ StorageDBParent::StorageDBParent()
|
||||
|
||||
StorageDBParent::~StorageDBParent()
|
||||
{
|
||||
StorageObserver* observer = StorageObserver::Self();
|
||||
if (observer) {
|
||||
observer->RemoveSink(this);
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
if (mObserverSink) {
|
||||
mObserverSink->Stop();
|
||||
mObserverSink = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StorageDBParent::Init()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
PBackgroundParent* actor = Manager();
|
||||
MOZ_ASSERT(actor);
|
||||
|
||||
if (BackgroundParent::IsOtherProcessActor(actor)) {
|
||||
mObserverSink = new ObserverSink(this);
|
||||
mObserverSink->Start();
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,20 +807,66 @@ StorageDBParent::RecvAsyncFlush()
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// StorageObserverSink
|
||||
|
||||
nsresult
|
||||
StorageDBParent::Observe(const char* aTopic,
|
||||
const nsAString& aOriginAttributesPattern,
|
||||
const nsACString& aOriginScope)
|
||||
mozilla::ipc::IPCResult
|
||||
StorageDBParent::RecvStartup()
|
||||
{
|
||||
if (mIPCOpen) {
|
||||
mozilla::Unused << SendObserve(nsDependentCString(aTopic),
|
||||
nsString(aOriginAttributesPattern),
|
||||
nsCString(aOriginScope));
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate();
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
StorageDBParent::RecvClearAll()
|
||||
{
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate();
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
storageThread->AsyncClearAll();
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
StorageDBParent::RecvClearMatchingOrigin(const nsCString& aOriginNoSuffix)
|
||||
{
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate();
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
storageThread->AsyncClearMatchingOrigin(aOriginNoSuffix);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
StorageDBParent::RecvClearMatchingOriginAttributes(
|
||||
const OriginAttributesPattern& aPattern)
|
||||
{
|
||||
StorageDBThread* storageThread = StorageDBThread::GetOrCreate();
|
||||
if (!storageThread) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
storageThread->AsyncClearMatchingOriginAttributes(aPattern);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
StorageDBParent::Observe(const nsCString& aTopic,
|
||||
const nsString& aOriginAttributesPattern,
|
||||
const nsCString& aOriginScope)
|
||||
{
|
||||
if (mIPCOpen) {
|
||||
mozilla::Unused <<
|
||||
SendObserve(aTopic, aOriginAttributesPattern, aOriginScope);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -1000,6 +1109,96 @@ StorageDBParent::UsageParentBridge::Destroy()
|
||||
NS_DISPATCH_NORMAL));
|
||||
}
|
||||
|
||||
void
|
||||
StorageDBParent::
|
||||
ObserverSink::Start()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
RefPtr<Runnable> runnable =
|
||||
NewRunnableMethod("StorageDBParent::ObserverSink::AddSink",
|
||||
this,
|
||||
&StorageDBParent::ObserverSink::AddSink);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
|
||||
}
|
||||
|
||||
void
|
||||
StorageDBParent::
|
||||
ObserverSink::Stop()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
mActor = nullptr;
|
||||
|
||||
RefPtr<Runnable> runnable =
|
||||
NewRunnableMethod("StorageDBParent::ObserverSink::RemoveSink",
|
||||
this,
|
||||
&StorageDBParent::ObserverSink::RemoveSink);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
|
||||
}
|
||||
|
||||
void
|
||||
StorageDBParent::
|
||||
ObserverSink::AddSink()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
StorageObserver* observer = StorageObserver::Self();
|
||||
if (observer) {
|
||||
observer->AddSink(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StorageDBParent::
|
||||
ObserverSink::RemoveSink()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
StorageObserver* observer = StorageObserver::Self();
|
||||
if (observer) {
|
||||
observer->RemoveSink(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StorageDBParent::
|
||||
ObserverSink::Notify(const nsCString& aTopic,
|
||||
const nsString& aOriginAttributesPattern,
|
||||
const nsCString& aOriginScope)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
if (mActor) {
|
||||
mActor->Observe(aTopic, aOriginAttributesPattern, aOriginScope);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
StorageDBParent::
|
||||
ObserverSink::Observe(const char* aTopic,
|
||||
const nsAString& aOriginAttributesPattern,
|
||||
const nsACString& aOriginScope)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<Runnable> runnable =
|
||||
NewRunnableMethod<nsCString, nsString, nsCString>(
|
||||
"StorageDBParent::ObserverSink::Observe2",
|
||||
this,
|
||||
&StorageDBParent::ObserverSink::Notify,
|
||||
aTopic,
|
||||
aOriginAttributesPattern,
|
||||
aOriginScope);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
mOwningEventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Exported functions
|
||||
******************************************************************************/
|
||||
|
@ -137,13 +137,17 @@ private:
|
||||
// Also responsible for forwardning all chrome operation notifications
|
||||
// such as cookie cleaning etc to the child process.
|
||||
class StorageDBParent final : public PBackgroundStorageParent
|
||||
, public StorageObserverSink
|
||||
{
|
||||
class ObserverSink;
|
||||
|
||||
virtual ~StorageDBParent();
|
||||
|
||||
public:
|
||||
StorageDBParent();
|
||||
|
||||
void
|
||||
Init();
|
||||
|
||||
NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
|
||||
NS_IMETHOD_(MozExternalRefCountType) Release(void);
|
||||
|
||||
@ -250,15 +254,23 @@ private:
|
||||
const nsCString& aOriginNoSuffix) override;
|
||||
mozilla::ipc::IPCResult RecvAsyncFlush() override;
|
||||
|
||||
// StorageObserverSink
|
||||
virtual nsresult Observe(const char* aTopic,
|
||||
const nsAString& aOriginAttrPattern,
|
||||
const nsACString& aOriginScope) override;
|
||||
mozilla::ipc::IPCResult RecvStartup() override;
|
||||
mozilla::ipc::IPCResult RecvClearAll() override;
|
||||
mozilla::ipc::IPCResult RecvClearMatchingOrigin(
|
||||
const nsCString& aOriginNoSuffix) override;
|
||||
mozilla::ipc::IPCResult RecvClearMatchingOriginAttributes(
|
||||
const OriginAttributesPattern& aPattern) override;
|
||||
|
||||
void Observe(const nsCString& aTopic,
|
||||
const nsString& aOriginAttrPattern,
|
||||
const nsCString& aOriginScope);
|
||||
|
||||
private:
|
||||
CacheParentBridge* NewCache(const nsACString& aOriginSuffix,
|
||||
const nsACString& aOriginNoSuffix);
|
||||
|
||||
RefPtr<ObserverSink> mObserverSink;
|
||||
|
||||
ThreadSafeAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
|
@ -161,6 +161,8 @@ StorageObserver::Observe(nsISupports* aSubject,
|
||||
|
||||
// Start the thread that opens the database.
|
||||
if (!strcmp(aTopic, kStartupTopic)) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->RemoveObserver(this, kStartupTopic);
|
||||
|
||||
@ -176,6 +178,8 @@ StorageObserver::Observe(nsISupports* aSubject,
|
||||
|
||||
// Timer callback used to start the database a short timer after startup
|
||||
if (!strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC)) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
nsCOMPtr<nsITimer> timer = do_QueryInterface(aSubject);
|
||||
if (!timer) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
@ -184,11 +188,12 @@ StorageObserver::Observe(nsISupports* aSubject,
|
||||
if (timer == mDBThreadStartDelayTimer) {
|
||||
mDBThreadStartDelayTimer = nullptr;
|
||||
|
||||
// XXX Fix me!
|
||||
#if 0
|
||||
StorageDBBridge* db = LocalStorageCache::StartDatabase();
|
||||
NS_ENSURE_TRUE(db, NS_ERROR_FAILURE);
|
||||
#endif
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
storageChild->SendStartup();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -200,13 +205,16 @@ StorageObserver::Observe(nsISupports* aSubject,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX Fix me!
|
||||
#if 0
|
||||
StorageDBBridge* db = LocalStorageCache::StartDatabase();
|
||||
NS_ENSURE_TRUE(db, NS_ERROR_FAILURE);
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
db->AsyncClearAll();
|
||||
#endif
|
||||
storageChild->AsyncClearAll();
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
storageChild->SendClearAll();
|
||||
}
|
||||
|
||||
Notify("cookie-cleared");
|
||||
|
||||
@ -267,13 +275,16 @@ StorageObserver::Observe(nsISupports* aSubject,
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "extension:purge-localStorage")) {
|
||||
// XXX Fix me!
|
||||
#if 0
|
||||
StorageDBBridge* db = LocalStorageCache::StartDatabase();
|
||||
NS_ENSURE_TRUE(db, NS_ERROR_FAILURE);
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
db->AsyncClearAll();
|
||||
#endif
|
||||
storageChild->AsyncClearAll();
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
storageChild->SendClearAll();
|
||||
}
|
||||
|
||||
Notify("extension:purge-localStorage-caches");
|
||||
|
||||
@ -303,13 +314,14 @@ StorageObserver::Observe(nsISupports* aSubject,
|
||||
rv = CreateReversedDomain(aceDomain, originScope);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// XXX Fix me!
|
||||
#if 0
|
||||
StorageDBBridge* db = LocalStorageCache::StartDatabase();
|
||||
NS_ENSURE_TRUE(db, NS_ERROR_FAILURE);
|
||||
if (XRE_IsParentProcess()) {
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
db->AsyncClearMatchingOrigin(originScope);
|
||||
#endif
|
||||
storageChild->SendClearMatchingOrigin(originScope);
|
||||
}
|
||||
|
||||
Notify("domain-data-cleared", EmptyString(), originScope);
|
||||
|
||||
@ -325,19 +337,20 @@ StorageObserver::Observe(nsISupports* aSubject,
|
||||
|
||||
// Clear data of the origins whose prefixes will match the suffix.
|
||||
if (!strcmp(aTopic, "clear-origin-attributes-data")) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
OriginAttributesPattern pattern;
|
||||
if (!pattern.Init(nsDependentString(aData))) {
|
||||
NS_ERROR("Cannot parse origin attributes pattern");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// XXX Fix me!
|
||||
#if 0
|
||||
StorageDBBridge* db = LocalStorageCache::StartDatabase();
|
||||
NS_ENSURE_TRUE(db, NS_ERROR_FAILURE);
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
db->AsyncClearMatchingOriginAttributes(pattern);
|
||||
#endif
|
||||
storageChild->SendClearMatchingOriginAttributes(pattern);
|
||||
|
||||
Notify("origin-attr-pattern-cleared", nsDependentString(aData));
|
||||
|
||||
@ -381,13 +394,12 @@ StorageObserver::Observe(nsISupports* aSubject,
|
||||
|
||||
#ifdef DOM_STORAGE_TESTS
|
||||
if (!strcmp(aTopic, "domstorage-test-flush-force")) {
|
||||
// XXX Fix me!
|
||||
#if 0
|
||||
StorageDBBridge* db = LocalStorageCache::GetDatabase();
|
||||
if (db) {
|
||||
db->AsyncFlush();
|
||||
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
|
||||
if (NS_WARN_IF(!storageChild)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
storageChild->SendAsyncFlush();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user