From cc10beffc20b584b206384f28597576b0d634a04 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Thu, 29 May 2014 16:35:03 +0100 Subject: [PATCH] Bug 957086 - patch 3 - DataStoreService in C++ OOP, r=janv --- dom/datastore/DataStoreChangeNotifier.jsm | 3 - dom/datastore/DataStoreDB.cpp | 6 +- dom/datastore/DataStoreRevision.h | 6 +- dom/datastore/DataStoreService.cpp | 159 +++++++++++++++------ dom/datastore/DataStoreService.h | 7 + dom/datastore/DataStoreServiceInternal.jsm | 68 --------- dom/datastore/moz.build | 1 - dom/ipc/ContentChild.cpp | 19 +++ dom/ipc/ContentChild.h | 4 + dom/ipc/ContentParent.cpp | 22 +++ dom/ipc/ContentParent.h | 12 +- dom/ipc/PContent.ipdl | 14 ++ 12 files changed, 198 insertions(+), 123 deletions(-) delete mode 100644 dom/datastore/DataStoreServiceInternal.jsm diff --git a/dom/datastore/DataStoreChangeNotifier.jsm b/dom/datastore/DataStoreChangeNotifier.jsm index 0f9d20d6d93b..19eb287f2d1c 100644 --- a/dom/datastore/DataStoreChangeNotifier.jsm +++ b/dom/datastore/DataStoreChangeNotifier.jsm @@ -12,9 +12,6 @@ function debug(s) { //dump('DEBUG DataStoreChangeNotifier: ' + s + '\n'); } -// DataStoreServiceInternal should not be converted into a lazy getter as it -// runs code during initialization. -Cu.import('resource://gre/modules/DataStoreServiceInternal.jsm'); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); diff --git a/dom/datastore/DataStoreDB.cpp b/dom/datastore/DataStoreDB.cpp index 083a3c5661bc..ecb73926e3b0 100644 --- a/dom/datastore/DataStoreDB.cpp +++ b/dom/datastore/DataStoreDB.cpp @@ -144,7 +144,7 @@ DataStoreDB::UpgradeSchema() } { - IDBObjectStoreParameters params; + RootedDictionary params(cx); params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true }")); nsRefPtr store = database->CreateObjectStore(cx, NS_LITERAL_STRING(DATASTOREDB_NAME), @@ -157,7 +157,7 @@ DataStoreDB::UpgradeSchema() nsRefPtr store; { - IDBObjectStoreParameters params; + RootedDictionary params(cx); params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true, \"keyPath\": \"internalRevisionId\" }")); store = @@ -169,7 +169,7 @@ DataStoreDB::UpgradeSchema() } { - IDBIndexParameters params; + RootedDictionary params(cx); params.Init(NS_LITERAL_STRING("{ \"unique\": true }")); nsRefPtr index = store->CreateIndex(cx, NS_LITERAL_STRING(DATASTOREDB_REVISION_INDEX), diff --git a/dom/datastore/DataStoreRevision.h b/dom/datastore/DataStoreRevision.h index a6377f27aaf1..7162ae949545 100644 --- a/dom/datastore/DataStoreRevision.h +++ b/dom/datastore/DataStoreRevision.h @@ -7,10 +7,10 @@ #ifndef mozilla_dom_DataStoreRevision_h #define mozilla_dom_DataStoreRevision_h -#include "nsIDOMEventListener.h" -#include "nsAutoPtr.h" -#include "nsString.h" #include "jsapi.h" +#include "nsAutoPtr.h" +#include "nsIDOMEventListener.h" +#include "nsString.h" namespace mozilla { namespace dom { diff --git a/dom/datastore/DataStoreService.cpp b/dom/datastore/DataStoreService.cpp index 03b5dd93927a..8afdc445f233 100644 --- a/dom/datastore/DataStoreService.cpp +++ b/dom/datastore/DataStoreService.cpp @@ -10,17 +10,21 @@ #include "DataStoreDB.h" #include "DataStoreRevision.h" #include "mozilla/dom/DataStore.h" +#include "mozilla/dom/DataStoreBinding.h" +#include "mozilla/dom/DataStoreImplBinding.h" #include "nsIDataStore.h" #include "mozilla/Preferences.h" #include "mozilla/Services.h" #include "mozilla/StaticPtr.h" +#include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/DOMError.h" -#include "mozilla/dom/Promise.h" #include "mozilla/dom/indexedDB/IDBCursor.h" #include "mozilla/dom/indexedDB/IDBObjectStore.h" -#include "mozilla/dom/DataStoreBinding.h" -#include "mozilla/dom/DataStoreImplBinding.h" +#include "mozilla/dom/PermissionMessageUtils.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/unused.h" #include "mozIApplication.h" #include "mozIApplicationClearPrivateDataParams.h" @@ -44,7 +48,7 @@ #define ASSERT_PARENT_PROCESS() \ AssertIsInMainProcess(); \ - if (NS_WARN_IF(XRE_GetProcessType() != GeckoProcessType_Default)) { \ + if (NS_WARN_IF(!IsMainProcess())) { \ return NS_ERROR_FAILURE; \ } @@ -57,17 +61,32 @@ using namespace indexedDB; class DataStoreInfo { public: + DataStoreInfo() + : mReadOnly(true) + , mEnabled(false) + {} + DataStoreInfo(const nsAString& aName, const nsAString& aOriginURL, const nsAString& aManifestURL, bool aReadOnly, bool aEnabled) - : mName(aName) - , mOriginURL(aOriginURL) - , mManifestURL(aManifestURL) - , mReadOnly(aReadOnly) - , mEnabled(aEnabled) - {} + { + Init(aName, aOriginURL, aManifestURL, aReadOnly, aEnabled); + } + + void Init(const nsAString& aName, + const nsAString& aOriginURL, + const nsAString& aManifestURL, + bool aReadOnly, + bool aEnabled) + { + mName = aName; + mOriginURL = aOriginURL; + mManifestURL = aManifestURL; + mReadOnly = aReadOnly; + mEnabled = aEnabled; + } void Update(const nsAString& aName, const nsAString& aOriginURL, @@ -341,10 +360,10 @@ GetDataStoreInfosEnumerator(const uint32_t& aAppId, } bool readOnly = aInfo->mReadOnly || accessInfo->mReadOnly; - DataStoreInfo accessStore(aInfo->mName, aInfo->mOriginURL, - aInfo->mManifestURL, readOnly, - aInfo->mEnabled); - data->mStores.AppendElement(accessStore); + DataStoreInfo* accessStore = data->mStores.AppendElement(); + accessStore->Init(aInfo->mName, aInfo->mOriginURL, + aInfo->mManifestURL, readOnly, + aInfo->mEnabled); return PL_DHASH_NEXT; } @@ -428,15 +447,14 @@ AddAccessPermissionsEnumerator(const uint32_t& aAppId, class PendingRequest { public: - PendingRequest(nsPIDOMWindow* aWindow, - Promise* aPromise, - const nsTArray& aStores, - const nsTArray& aPendingDataStores) - : mWindow(aWindow) - , mPromise(aPromise) - , mStores(aStores) - , mPendingDataStores(aPendingDataStores) + void Init(nsPIDOMWindow* aWindow, Promise* aPromise, + const nsTArray& aStores, + const nsTArray& aPendingDataStores) { + mWindow = aWindow; + mPromise = aPromise; + mStores = aStores; + mPendingDataStores = aPendingDataStores; } nsCOMPtr mWindow; @@ -856,15 +874,17 @@ DataStoreService::GetDataStores(nsIDOMWindow* aWindow, nsCOMPtr global = do_QueryInterface(window); nsRefPtr promise = new Promise(global); + nsCOMPtr document = window->GetDoc(); + MOZ_ASSERT(document); + + nsCOMPtr principal = document->NodePrincipal(); + MOZ_ASSERT(principal); + + nsTArray stores; + // If this request comes from the main process, we have access to the // window, so we can skip the ipc communication. if (IsMainProcess()) { - nsCOMPtr document = window->GetDoc(); - MOZ_ASSERT(document); - - nsCOMPtr principal = document->NodePrincipal(); - MOZ_ASSERT(principal); - uint32_t appId; nsresult rv = principal->GetAppId(&appId); if (NS_FAILED(rv)) { @@ -873,25 +893,37 @@ DataStoreService::GetDataStores(nsIDOMWindow* aWindow, return NS_OK; } - nsTArray stores; rv = GetDataStoreInfos(aName, appId, stores); if (NS_FAILED(rv)) { RejectPromise(window, promise, rv); promise.forget(aDataStores); return NS_OK; } - - GetDataStoresCreate(window, promise, stores); - promise.forget(aDataStores); - return NS_OK; } else { // This method can be called in the child so we need to send a request // to the parent and create DataStore object here. - // TODO + ContentChild* contentChild = ContentChild::GetSingleton(); + + nsTArray array; + if (!contentChild->SendDataStoreGetStores(nsAutoString(aName), + IPC::Principal(principal), + &array)) { + RejectPromise(window, promise, NS_ERROR_FAILURE); + promise.forget(aDataStores); + return NS_OK; + } + + for (uint32_t i = 0; i < array.Length(); ++i) { + DataStoreInfo* info = stores.AppendElement(); + info->Init(array[i].name(), array[i].originURL(), + array[i].manifestURL(), array[i].readOnly(), + array[i].enabled()); + } } + GetDataStoresCreate(window, promise, stores); promise.forget(aDataStores); return NS_OK; } @@ -900,7 +932,6 @@ void DataStoreService::GetDataStoresCreate(nsPIDOMWindow* aWindow, Promise* aPromise, const nsTArray& aStores) { - AssertIsInMainProcess(); MOZ_ASSERT(NS_IsMainThread()); if (!aStores.Length()) { @@ -926,8 +957,8 @@ DataStoreService::GetDataStoresCreate(nsPIDOMWindow* aWindow, Promise* aPromise, mPendingRequests.Put(aStores[0].mName, requests); } - PendingRequest request(aWindow, aPromise, aStores, pendingDataStores); - requests->AppendElement(request); + PendingRequest* request = requests->AppendElement(); + request->Init(aWindow, aPromise, aStores, pendingDataStores); } void @@ -935,7 +966,6 @@ DataStoreService::GetDataStoresResolve(nsPIDOMWindow* aWindow, Promise* aPromise, const nsTArray& aStores) { - AssertIsInMainProcess(); MOZ_ASSERT(NS_IsMainThread()); if (!aStores.Length()) { @@ -1045,9 +1075,9 @@ DataStoreService::GetDataStoreInfos(const nsAString& aName, DataStoreInfo* info = nullptr; if (apps->Get(aAppId, &info)) { - DataStoreInfo owned(info->mName, info->mOriginURL, info->mManifestURL, - false, info->mEnabled); - aStores.AppendElement(owned); + DataStoreInfo* owned = aStores.AppendElement(); + owned->Init(info->mName, info->mOriginURL, info->mManifestURL, false, + info->mEnabled); } GetDataStoreInfosData data(mAccessStores, aName, aAppId, aStores); @@ -1195,6 +1225,18 @@ DataStoreService::EnableDataStore(uint32_t aAppId, const nsAString& aName, } } + // Notify the child processes. + if (IsMainProcess()) { + nsTArray children; + ContentParent::GetAll(children); + for (uint32_t i = 0; i < children.Length(); i++) { + if (children[i]->NeedsDataStoreInfos()) { + unused << children[i]->SendDataStoreNotify(aAppId, nsAutoString(aName), + nsAutoString(aManifestURL)); + } + } + } + // Maybe we have some pending request waiting for this DataStore. PendingRequests* requests; if (!mPendingRequests.Get(aName, &requests)) { @@ -1231,7 +1273,6 @@ DataStoreService::EnableDataStore(uint32_t aAppId, const nsAString& aName, already_AddRefed DataStoreService::GetCounter(uint32_t aId) const { - AssertIsInMainProcess(); MOZ_ASSERT(NS_IsMainThread()); nsRefPtr counter; @@ -1242,10 +1283,40 @@ DataStoreService::GetCounter(uint32_t aId) const void DataStoreService::RemoveCounter(uint32_t aId) { - AssertIsInMainProcess(); + MOZ_ASSERT(NS_IsMainThread()); + mPendingCounters.Remove(aId); +} + +nsresult +DataStoreService::GetDataStoresFromIPC(const nsAString& aName, + nsIPrincipal* aPrincipal, + nsTArray* aValue) +{ + MOZ_ASSERT(IsMainProcess()); MOZ_ASSERT(NS_IsMainThread()); - mPendingCounters.Remove(aId); + uint32_t appId; + nsresult rv = aPrincipal->GetAppId(&appId); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + nsTArray stores; + rv = GetDataStoreInfos(aName, appId, stores); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + for (uint32_t i = 0; i < stores.Length(); ++i) { + DataStoreSetting* data = aValue->AppendElement(); + data->name() = stores[i].mName; + data->originURL() = stores[i].mOriginURL; + data->manifestURL() = stores[i].mManifestURL; + data->readOnly() = stores[i].mReadOnly; + data->enabled() = stores[i].mEnabled; + } + + return NS_OK; } nsresult diff --git a/dom/datastore/DataStoreService.h b/dom/datastore/DataStoreService.h index 533c079c99dc..73210ff1d7b4 100644 --- a/dom/datastore/DataStoreService.h +++ b/dom/datastore/DataStoreService.h @@ -7,11 +7,13 @@ #ifndef mozilla_dom_DataStoreService_h #define mozilla_dom_DataStoreService_h +#include "mozilla/dom/PContent.h" #include "nsClassHashtable.h" #include "nsIDataStoreService.h" #include "nsIObserver.h" #include "nsRefPtrHashtable.h" +class nsIPrincipal; class nsIUUIDGenerator; class nsPIDOMWindow; @@ -28,6 +30,7 @@ class RevisionAddedEnableStoreCallback; class DataStoreService MOZ_FINAL : public nsIDataStoreService , public nsIObserver { + friend class ContentChild; friend class FirstRevisionIdCallback; friend class RetrieveRevisionsCounter; friend class RevisionAddedEnableStoreCallback; @@ -47,6 +50,10 @@ public: nsresult GenerateUUID(nsAString& aID); + nsresult GetDataStoresFromIPC(const nsAString& aName, + nsIPrincipal* aPrincipal, + nsTArray* aValue); + private: DataStoreService(); ~DataStoreService(); diff --git a/dom/datastore/DataStoreServiceInternal.jsm b/dom/datastore/DataStoreServiceInternal.jsm deleted file mode 100644 index f301a3793e30..000000000000 --- a/dom/datastore/DataStoreServiceInternal.jsm +++ /dev/null @@ -1,68 +0,0 @@ -/* 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/. */ - -"use strict" - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -this.EXPORTED_SYMBOLS = ["DataStoreServiceInternal"]; - -function debug(s) { - //dump('DEBUG DataStoreServiceInternal: ' + s + '\n'); -} - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "ppmm", - "@mozilla.org/parentprocessmessagemanager;1", - "nsIMessageBroadcaster"); - -XPCOMUtils.defineLazyServiceGetter(this, "dataStoreService", - "@mozilla.org/datastore-service;1", - "nsIDataStoreService"); - -this.DataStoreServiceInternal = { - init: function() { - debug("init"); - - let inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime) - .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; - if (inParent) { - ppmm.addMessageListener("DataStore:Get", this); - } - }, - - receiveMessage: function(aMessage) { - debug("receiveMessage"); - - if (aMessage.name != 'DataStore:Get') { - return; - } - - let prefName = 'dom.testing.datastore_enabled_for_hosted_apps'; - if ((Services.prefs.getPrefType(prefName) == Services.prefs.PREF_INVALID || - !Services.prefs.getBoolPref(prefName)) && - !aMessage.target.assertAppHasStatus(Ci.nsIPrincipal.APP_STATUS_CERTIFIED)) { - return; - } - - let msg = aMessage.data; - - if (!aMessage.principal || - aMessage.principal.appId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) { - aMessage.target.sendAsyncMessage("DataStore:Get:Return:KO"); - return; - } - - msg.stores = dataStoreService.getDataStoresInfo(msg.name, aMessage.principal.appId); - if (msg.stores === null) { - aMessage.target.sendAsyncMessage("DataStore:Get:Return:KO"); - return; - } - aMessage.target.sendAsyncMessage("DataStore:Get:Return:OK", msg); - } -} - -DataStoreServiceInternal.init(); diff --git a/dom/datastore/moz.build b/dom/datastore/moz.build index 630f6cc3da89..b85c7e9bb64a 100644 --- a/dom/datastore/moz.build +++ b/dom/datastore/moz.build @@ -38,7 +38,6 @@ EXTRA_JS_MODULES += [ 'DataStoreChangeNotifier.jsm', 'DataStoreCursorImpl.jsm', 'DataStoreDB.jsm', - 'DataStoreServiceInternal.jsm', ] MOCHITEST_MANIFESTS += ['tests/mochitest.ini'] diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 3fe4a97ab31b..41c12fb3093f 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -142,6 +142,7 @@ #include "nsDeviceStorage.h" #include "AudioChannelService.h" #include "JavaScriptChild.h" +#include "mozilla/dom/DataStoreService.h" #include "mozilla/dom/telephony/PTelephonyChild.h" #include "mozilla/dom/time/DateCacheCleaner.h" #include "mozilla/net/NeckoMessageUtils.h" @@ -768,6 +769,24 @@ ContentChild::RecvAudioChannelNotify() return true; } +bool +ContentChild::RecvDataStoreNotify(const uint32_t& aAppId, + const nsString& aName, + const nsString& aManifestURL) +{ + nsRefPtr service = DataStoreService::GetOrCreate(); + if (NS_WARN_IF(!service)) { + return false; + } + + nsresult rv = service->EnableDataStore(aAppId, aName, aManifestURL); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + + return true; +} + bool ContentChild::DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) { diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 556cbb181773..67c1468b3550 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -157,6 +157,10 @@ public: virtual bool RecvAudioChannelNotify() MOZ_OVERRIDE; + virtual bool + RecvDataStoreNotify(const uint32_t& aAppId, const nsString& aName, + const nsString& aManifestURL) MOZ_OVERRIDE; + virtual PTestShellChild* AllocPTestShellChild() MOZ_OVERRIDE; virtual bool DeallocPTestShellChild(PTestShellChild*) MOZ_OVERRIDE; virtual bool RecvPTestShellConstructor(PTestShellChild*) MOZ_OVERRIDE; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 01115152302d..a0efbeb5df47 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -33,6 +33,7 @@ #include "mozilla/ClearOnShutdown.h" #include "mozilla/dom/asmjscache/AsmJSCache.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/DataStoreService.h" #include "mozilla/dom/ExternalHelperAppParent.h" #include "mozilla/dom/PFileDescriptorSetParent.h" #include "mozilla/dom/PCycleCollectWithLogsParent.h" @@ -1495,6 +1496,7 @@ ContentParent::InitializeMembers() mNumDestroyingTabs = 0; mIsAlive = true; mSendPermissionUpdates = false; + mSendDataStoreInfos = false; mCalledClose = false; mCalledCloseWithError = false; mCalledKillHard = false; @@ -2076,6 +2078,26 @@ ContentParent::RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel, return true; } +bool +ContentParent::RecvDataStoreGetStores( + const nsString& aName, + const IPC::Principal& aPrincipal, + InfallibleTArray* aValue) +{ + nsRefPtr service = DataStoreService::GetOrCreate(); + if (NS_WARN_IF(!service)) { + return false; + } + + nsresult rv = service->GetDataStoresFromIPC(aName, aPrincipal, aValue); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + + mSendDataStoreInfos = true; + return true; +} + bool ContentParent::RecvBroadcastVolume(const nsString& aVolumeName) { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index cc0a8bae25bb..06991e72e8c2 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -160,10 +160,14 @@ public: int32_t Pid(); - bool NeedsPermissionsUpdate() { + bool NeedsPermissionsUpdate() const { return mSendPermissionUpdates; } + bool NeedsDataStoreInfos() const { + return mSendDataStoreInfos; + } + BlobParent* GetOrCreateActorForBlob(nsIDOMBlob* aBlob); /** @@ -526,6 +530,11 @@ private: virtual bool RecvGetSystemMemory(const uint64_t& getterId) MOZ_OVERRIDE; virtual bool RecvBroadcastVolume(const nsString& aVolumeName) MOZ_OVERRIDE; + virtual bool RecvDataStoreGetStores( + const nsString& aName, + const IPC::Principal& aPrincipal, + InfallibleTArray* aValue) MOZ_OVERRIDE; + virtual bool RecvSpeakerManagerGetSpeakerStatus(bool* aValue) MOZ_OVERRIDE; virtual bool RecvSpeakerManagerForceSpeaker(const bool& aEnable) MOZ_OVERRIDE; @@ -600,6 +609,7 @@ private: bool mIsAlive; bool mSendPermissionUpdates; + bool mSendDataStoreInfos; bool mIsForBrowser; bool mIsNuwaProcess; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index c588a0483db1..6d7c44604318 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -262,6 +262,14 @@ struct PrefSetting { MaybePrefValue userValue; }; +struct DataStoreSetting { + nsString name; + nsString originURL; + nsString manifestURL; + bool readOnly; + bool enabled; +}; + intr protocol PContent { parent opens PCompositor; @@ -338,6 +346,9 @@ child: async SpeakerManagerNotify(); + async DataStoreNotify(uint32_t aAppId, nsString aName, + nsString aManifestURL); + /** * Dump this process's GC and CC logs to the provided files. * @@ -550,6 +561,9 @@ parent: async AudioChannelChangedNotification(); async AudioChannelChangeDefVolChannel(int32_t aChannel, bool aHidden); + sync DataStoreGetStores(nsString aName, Principal aPrincipal) + returns (DataStoreSetting[] dataStores); + async FilePathUpdateNotify(nsString aType, nsString aStorageName, nsString aFilepath,