diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 713c195e6d8e..f3d4391c70b1 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -810,7 +810,7 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@ #endif @BINPATH@/components/DataStore.manifest -@BINPATH@/components/DataStoreImpl.js +@BINPATH@/components/DataStoreService.js @BINPATH@/components/dom_datastore.xpt #ifdef MOZ_WEBSPEECH diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index bd7ca8a40c29..c3dad6ebe666 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -857,7 +857,7 @@ bin/libfreebl_32int64_3.so #endif @BINPATH@/components/DataStore.manifest -@BINPATH@/components/DataStoreImpl.js +@BINPATH@/components/DataStoreService.js @BINPATH@/components/dom_datastore.xpt diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index f0b18c263e47..393dd9f251be 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -82,7 +82,7 @@ #endif #include "nsIDOMGlobalPropertyInitializer.h" -#include "mozilla/dom/DataStoreService.h" +#include "nsIDataStoreService.h" #include "nsJSUtils.h" #include "nsScriptNameSpaceManager.h" @@ -1466,7 +1466,8 @@ Navigator::GetDataStores(nsPIDOMWindow* aWindow, return nullptr; } - nsRefPtr service = DataStoreService::GetOrCreate(); + nsCOMPtr service = + do_GetService("@mozilla.org/datastore-service;1"); if (!service) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; diff --git a/dom/datastore/DataStore.manifest b/dom/datastore/DataStore.manifest index 409bcdc9586e..204682d116dd 100644 --- a/dom/datastore/DataStore.manifest +++ b/dom/datastore/DataStore.manifest @@ -1,2 +1,2 @@ -component {db5c9602-030f-4bff-a3de-881a8de370f2} DataStoreImpl.js -contract @mozilla.org/dom/datastore;1 {db5c9602-030f-4bff-a3de-881a8de370f2} +component {d193d0e2-c677-4a7b-bb0a-19155b470f2e} DataStoreService.js +contract @mozilla.org/datastore-service;1 {d193d0e2-c677-4a7b-bb0a-19155b470f2e} diff --git a/dom/datastore/DataStoreCallbacks.h b/dom/datastore/DataStoreCallbacks.h deleted file mode 100644 index 44ed587b1663..000000000000 --- a/dom/datastore/DataStoreCallbacks.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=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_DataStoreCallbacks_h -#define mozilla_dom_DataStoreCallbacks_h - -#include "nsISupports.h" - -namespace mozilla { -namespace dom { - -class DataStoreDB; - -class DataStoreDBCallback -{ -public: - NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0; - NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0; - - virtual void Run(DataStoreDB* aDb, bool aSuccess) = 0; - -protected: - virtual ~DataStoreDBCallback() - { - } -}; - -class DataStoreRevisionCallback -{ -public: - NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0; - NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0; - - virtual void Run(const nsAString& aRevisionID) = 0; - -protected: - virtual ~DataStoreRevisionCallback() - { - } -}; - -} // dom namespace -} // mozilla namespace - -#endif // mozilla_dom_DataStoreCallbacks_h diff --git a/dom/datastore/DataStoreChangeNotifier.jsm b/dom/datastore/DataStoreChangeNotifier.jsm index 19eb287f2d1c..0f9d20d6d93b 100644 --- a/dom/datastore/DataStoreChangeNotifier.jsm +++ b/dom/datastore/DataStoreChangeNotifier.jsm @@ -12,6 +12,9 @@ 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 deleted file mode 100644 index ecb73926e3b0..000000000000 --- a/dom/datastore/DataStoreDB.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=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 "DataStoreDB.h" - -#include "DataStoreCallbacks.h" -#include "mozilla/dom/IDBDatabaseBinding.h" -#include "mozilla/dom/IDBFactoryBinding.h" -#include "mozilla/dom/indexedDB/IDBDatabase.h" -#include "mozilla/dom/indexedDB/IDBFactory.h" -#include "mozilla/dom/indexedDB/IDBIndex.h" -#include "mozilla/dom/indexedDB/IDBObjectStore.h" -#include "mozilla/dom/indexedDB/IDBRequest.h" -#include "nsIDOMEvent.h" - -#define DATASTOREDB_VERSION 1 -#define DATASTOREDB_NAME "DataStoreDB" -#define DATASTOREDB_REVISION_INDEX "revisionIndex" - -using namespace mozilla::dom::indexedDB; - -namespace mozilla { -namespace dom { - -NS_IMPL_ISUPPORTS(DataStoreDB, nsIDOMEventListener) - -DataStoreDB::DataStoreDB(const nsAString& aManifestURL, const nsAString& aName) - : mState(Inactive) -{ - mDatabaseName.Assign(aName); - mDatabaseName.AppendASCII("|"); - mDatabaseName.Append(aManifestURL); -} - -DataStoreDB::~DataStoreDB() -{ -} - -nsresult -DataStoreDB::CreateFactoryIfNeeded() -{ - if (!mFactory) { - nsresult rv = IDBFactory::Create(nullptr, getter_AddRefs(mFactory)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - return NS_OK; -} - -nsresult -DataStoreDB::Open(IDBTransactionMode aMode, const Sequence& aDbs, - DataStoreDBCallback* aCallback) -{ - MOZ_ASSERT(mState == Inactive); - - nsresult rv = CreateFactoryIfNeeded(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - ErrorResult error; - mRequest = mFactory->Open(mDatabaseName, DATASTOREDB_VERSION, error); - if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); - } - - rv = AddEventListeners(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - mState = Active; - mTransactionMode = aMode; - mObjectStores = aDbs; - mCallback = aCallback; - return NS_OK; -} - -NS_IMETHODIMP -DataStoreDB::HandleEvent(nsIDOMEvent* aEvent) -{ - nsString type; - nsresult rv = aEvent->GetType(type); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (type.EqualsASCII("success")) { - RemoveEventListeners(); - mState = Inactive; - - rv = DatabaseOpened(); - if (NS_WARN_IF(NS_FAILED(rv))) { - mCallback->Run(this, false); - } else { - mCallback->Run(this, true); - } - - mRequest = nullptr; - return NS_OK; - } - - if (type.EqualsASCII("upgradeneeded")) { - return UpgradeSchema(); - } - - if (type.EqualsASCII("error") || type.EqualsASCII("blocked")) { - RemoveEventListeners(); - mState = Inactive; - mCallback->Run(this, false); - mRequest = nullptr; - return NS_OK; - } - - MOZ_ASSUME_UNREACHABLE("This should not happen"); - return NS_OK; -} - -nsresult -DataStoreDB::UpgradeSchema() -{ - MOZ_ASSERT(NS_IsMainThread()); - - AutoSafeJSContext cx; - - ErrorResult error; - JS::Rooted result(cx, mRequest->GetResult(error)); - if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); - } - - MOZ_ASSERT(result.isObject()); - - IDBDatabase* database = nullptr; - nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), database); - if (NS_FAILED(rv)) { - NS_WARNING("Didn't get the object we expected!"); - return rv; - } - - { - RootedDictionary params(cx); - params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true }")); - nsRefPtr store = - database->CreateObjectStore(cx, NS_LITERAL_STRING(DATASTOREDB_NAME), - params, error); - if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); - } - } - - nsRefPtr store; - - { - RootedDictionary params(cx); - params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true, \"keyPath\": \"internalRevisionId\" }")); - - store = - database->CreateObjectStore(cx, NS_LITERAL_STRING(DATASTOREDB_REVISION), - params, error); - if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); - } - } - - { - RootedDictionary params(cx); - params.Init(NS_LITERAL_STRING("{ \"unique\": true }")); - nsRefPtr index = - store->CreateIndex(cx, NS_LITERAL_STRING(DATASTOREDB_REVISION_INDEX), - NS_LITERAL_STRING("revisionId"), params, error); - if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); - } - } - - return NS_OK; -} - -nsresult -DataStoreDB::DatabaseOpened() -{ - MOZ_ASSERT(NS_IsMainThread()); - - AutoSafeJSContext cx; - - ErrorResult error; - JS::Rooted result(cx, mRequest->GetResult(error)); - if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); - } - - MOZ_ASSERT(result.isObject()); - - nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), mDatabase); - if (NS_FAILED(rv)) { - NS_WARNING("Didn't get the object we expected!"); - return rv; - } - - nsRefPtr txn = mDatabase->Transaction(mObjectStores, - mTransactionMode, - error); - if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); - } - - mTransaction = txn.forget(); - return NS_OK; -} - -nsresult -DataStoreDB::Delete() -{ - MOZ_ASSERT(mState == Inactive); - - nsresult rv = CreateFactoryIfNeeded(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - mTransaction = nullptr; - - if (mDatabase) { - rv = mDatabase->Close(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - mDatabase = nullptr; - } - - ErrorResult error; - nsRefPtr request = - mFactory->DeleteDatabase(mDatabaseName, IDBOpenDBOptions(), error); - if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); - } - - return NS_OK; -} - -indexedDB::IDBTransaction* -DataStoreDB::Transaction() const -{ - MOZ_ASSERT(mTransaction); - MOZ_ASSERT(mTransaction->IsOpen()); - return mTransaction; -} - -nsresult -DataStoreDB::AddEventListeners() -{ - nsresult rv; - rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("upgradeneeded"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("error"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("blocked"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -nsresult -DataStoreDB::RemoveEventListeners() -{ - nsresult rv; - rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("success"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("upgradeneeded"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("error"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("blocked"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/datastore/DataStoreDB.h b/dom/datastore/DataStoreDB.h deleted file mode 100644 index 9a782b7d0799..000000000000 --- a/dom/datastore/DataStoreDB.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=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_DataStoreDB_h -#define mozilla_dom_DataStoreDB_h - -#include "mozilla/dom/IDBTransactionBinding.h" -#include "nsAutoPtr.h" -#include "nsIDOMEventListener.h" -#include "nsISupportsImpl.h" -#include "nsString.h" - -#define DATASTOREDB_REVISION "revision" - -namespace mozilla { -namespace dom { - -namespace indexedDB { -class IDBDatabase; -class IDBFactory; -class IDBObjectStore; -class IDBOpenDBRequest; -class IDBTransaction; -} - -class DataStoreDBCallback; - -class DataStoreDB MOZ_FINAL : public nsIDOMEventListener -{ -public: - NS_DECL_ISUPPORTS - - DataStoreDB(const nsAString& aManifestURL, const nsAString& aName); - ~DataStoreDB(); - - nsresult Open(IDBTransactionMode aMode, const Sequence& aDb, - DataStoreDBCallback* aCallback); - - nsresult Delete(); - - indexedDB::IDBTransaction* Transaction() const; - - // nsIDOMEventListener - NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); - -private: - nsresult CreateFactoryIfNeeded(); - - nsresult UpgradeSchema(); - - nsresult DatabaseOpened(); - - nsresult AddEventListeners(); - - nsresult RemoveEventListeners(); - - nsString mDatabaseName; - - nsRefPtr mFactory; - nsRefPtr mRequest; - nsRefPtr mDatabase; - nsRefPtr mTransaction; - - nsRefPtr mCallback; - - // Internal state to avoid strange use of this class. - enum StateType { - Inactive, - Active - } mState; - - IDBTransactionMode mTransactionMode; - Sequence mObjectStores; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_DataStoreDB_h diff --git a/dom/datastore/DataStoreImpl.js b/dom/datastore/DataStoreImpl.jsm similarity index 97% rename from dom/datastore/DataStoreImpl.js rename to dom/datastore/DataStoreImpl.jsm index 21285ccda499..c8825e5f5e61 100644 --- a/dom/datastore/DataStoreImpl.js +++ b/dom/datastore/DataStoreImpl.jsm @@ -6,6 +6,8 @@ 'use strict' +this.EXPORTED_SYMBOLS = ["DataStore"]; + function debug(s) { //dump('DEBUG DataStore: ' + s + '\n'); } @@ -57,16 +59,17 @@ function validateId(aId) { } /* DataStore object */ -function DataStore() { +this.DataStore = function(aWindow, aName, aOwner, aReadOnly) { debug("DataStore created"); + this.init(aWindow, aName, aOwner, aReadOnly); } -DataStore.prototype = { +this.DataStore.prototype = { classDescription: "DataStore XPCOM Component", classID: Components.ID("{db5c9602-030f-4bff-a3de-881a8de370f2}"), contractID: "@mozilla.org/dom/datastore-impl;1", - QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataStore, Ci.nsISupports, - Ci.nsIObserver]), + QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISupports, + Components.interfaces.nsIObserver]), callbacks: [], @@ -533,5 +536,3 @@ DataStore.prototype = { return exposedCursor; } }; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataStore]); diff --git a/dom/datastore/DataStoreRevision.cpp b/dom/datastore/DataStoreRevision.cpp deleted file mode 100644 index daa4f99cf177..000000000000 --- a/dom/datastore/DataStoreRevision.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=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 "DataStoreRevision.h" - -#include "DataStoreCallbacks.h" -#include "DataStoreService.h" -#include "mozilla/dom/DataStoreBinding.h" -#include "mozilla/dom/indexedDB/IDBObjectStore.h" -#include "nsIDOMEvent.h" - -namespace mozilla { -namespace dom { - -using namespace indexedDB; - -NS_IMPL_ISUPPORTS(DataStoreRevision, nsIDOMEventListener) - -// Note: this code in it must not assume anything about the compartment cx is -// in. -nsresult -DataStoreRevision::AddRevision(JSContext* aCx, - IDBObjectStore* aStore, - uint32_t aObjectId, - RevisionType aRevisionType, - DataStoreRevisionCallback* aCallback) -{ - MOZ_ASSERT(aStore); - MOZ_ASSERT(aCallback); - - nsRefPtr service = DataStoreService::Get(); - if (!service) { - return NS_ERROR_FAILURE; - } - - nsString id; - nsresult rv = service->GenerateUUID(mRevisionID); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - DataStoreRevisionData data; - data.mRevisionId = mRevisionID; - data.mObjectId = aObjectId; - - switch (aRevisionType) { - case RevisionVoid: - data.mOperation = NS_LITERAL_STRING("void"); - break; - - default: - MOZ_ASSUME_UNREACHABLE("This should not happen"); - break; - } - - JS::Rooted value(aCx); - if (!data.ToObject(aCx, &value)) { - return NS_ERROR_FAILURE; - } - - ErrorResult error; - mRequest = aStore->Put(aCx, value, JS::UndefinedHandleValue, error); - if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); - } - - rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"), - this, false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - mCallback = aCallback; - return NS_OK; -} - -NS_IMETHODIMP -DataStoreRevision::HandleEvent(nsIDOMEvent* aEvent) -{ - nsString type; - nsresult rv = aEvent->GetType(type); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (!type.EqualsASCII("success")) { - MOZ_ASSUME_UNREACHABLE("This should not happen"); - return NS_ERROR_FAILURE; - } - - mRequest->RemoveEventListener(NS_LITERAL_STRING("success"), this, false); - mRequest = nullptr; - - mCallback->Run(mRevisionID); - return NS_OK; -} - -} // dom namespace -} // mozilla namespace diff --git a/dom/datastore/DataStoreRevision.h b/dom/datastore/DataStoreRevision.h deleted file mode 100644 index 7162ae949545..000000000000 --- a/dom/datastore/DataStoreRevision.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=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_DataStoreRevision_h -#define mozilla_dom_DataStoreRevision_h - -#include "jsapi.h" -#include "nsAutoPtr.h" -#include "nsIDOMEventListener.h" -#include "nsString.h" - -namespace mozilla { -namespace dom { - -namespace indexedDB { -class IDBObjectStore; -class IDBRequest; -} - -class DataStoreRevisionCallback; - -class DataStoreRevision MOZ_FINAL : public nsIDOMEventListener -{ -public: - NS_DECL_ISUPPORTS - - enum RevisionType { - RevisionVoid - }; - - nsresult AddRevision(JSContext* aCx, - indexedDB::IDBObjectStore* aStore, - uint32_t aObjectId, - RevisionType aRevisionType, - DataStoreRevisionCallback* aCallback); - - // nsIDOMEventListener - NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); - -private: - nsRefPtr mCallback; - nsRefPtr mRequest; - nsString mRevisionID; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_DataStoreRevision_h diff --git a/dom/datastore/DataStoreService.cpp b/dom/datastore/DataStoreService.cpp deleted file mode 100644 index b26e8b47af99..000000000000 --- a/dom/datastore/DataStoreService.cpp +++ /dev/null @@ -1,1347 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=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 "DataStoreService.h" - -#include "DataStoreCallbacks.h" -#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/indexedDB/IDBCursor.h" -#include "mozilla/dom/indexedDB/IDBObjectStore.h" -#include "mozilla/dom/PermissionMessageUtils.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/unused.h" - -#include "mozIApplication.h" -#include "mozIApplicationClearPrivateDataParams.h" -#include "nsIAppsService.h" -#include "nsIDOMEvent.h" -#include "nsIDocument.h" -#include "nsIDOMGlobalPropertyInitializer.h" -#include "nsIIOService.h" -#include "nsIObserverService.h" -#include "nsIPermissionManager.h" -#include "nsIScriptSecurityManager.h" -#include "nsIUUIDGenerator.h" -#include "nsPIDOMWindow.h" -#include "nsIURI.h" - -#include "nsContentUtils.h" -#include "nsNetCID.h" -#include "nsServiceManagerUtils.h" -#include "nsThreadUtils.h" -#include "nsXULAppAPI.h" - -#define ASSERT_PARENT_PROCESS() \ - AssertIsInMainProcess(); \ - if (NS_WARN_IF(!IsMainProcess())) { \ - return NS_ERROR_FAILURE; \ - } - -namespace mozilla { -namespace dom { - -using namespace indexedDB; - -// This class contains all the information about a DataStore. -class DataStoreInfo -{ -public: - DataStoreInfo() - : mReadOnly(true) - , mEnabled(false) - {} - - DataStoreInfo(const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly, - bool 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, - const nsAString& aManifestURL, - bool aReadOnly) - { - mName = aName; - mOriginURL = aOriginURL; - mManifestURL = aManifestURL; - mReadOnly = aReadOnly; - } - - void Enable() - { - mEnabled = true; - } - - nsString mName; - nsString mOriginURL; - nsString mManifestURL; - bool mReadOnly; - - // A DataStore is enabled when it has its first revision. - bool mEnabled; -}; - -namespace { - -// Singleton for DataStoreService. -StaticRefPtr gDataStoreService; -static uint64_t gCounterID = 0; - -typedef nsClassHashtable HashApp; - -bool -IsMainProcess() -{ - static const bool isMainProcess = - XRE_GetProcessType() == GeckoProcessType_Default; - return isMainProcess; -} - -void -AssertIsInMainProcess() -{ - MOZ_ASSERT(IsMainProcess()); -} - -void -RejectPromise(nsPIDOMWindow* aWindow, Promise* aPromise, nsresult aRv) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(NS_FAILED(aRv)); - - nsRefPtr error; - if (aRv == NS_ERROR_DOM_SECURITY_ERR) { - error = new DOMError(aWindow, NS_LITERAL_STRING("SecurityError"), - NS_LITERAL_STRING("Access denied")); - } else { - error = new DOMError(aWindow, NS_LITERAL_STRING("InternalError"), - NS_LITERAL_STRING("An error occurred")); - } - - aPromise->MaybeReject(error); -} - -void -DeleteDatabase(const nsAString& aName, - const nsAString& aManifestURL) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - nsRefPtr db = new DataStoreDB(aManifestURL, aName); - db->Delete(); -} - -PLDHashOperator -DeleteDataStoresAppEnumerator( - const uint32_t& aAppId, - nsAutoPtr& aInfo, - void* aUserData) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - auto* appId = static_cast(aUserData); - if (*appId != aAppId) { - return PL_DHASH_NEXT; - } - - DeleteDatabase(aInfo->mName, aInfo->mManifestURL); - return PL_DHASH_REMOVE; -} - -PLDHashOperator -DeleteDataStoresEnumerator(const nsAString& aName, - nsAutoPtr& aApps, - void* aUserData) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - aApps->Enumerate(DeleteDataStoresAppEnumerator, aUserData); - return aApps->Count() ? PL_DHASH_NEXT : PL_DHASH_REMOVE; -} - -void -GeneratePermissionName(nsAString& aPermission, - const nsAString& aName, - const nsAString& aManifestURL) -{ - aPermission.AssignASCII("indexedDB-chrome-"); - aPermission.Append(aName); - aPermission.AppendASCII("|"); - aPermission.Append(aManifestURL); -} - -nsresult -ResetPermission(uint32_t aAppId, const nsAString& aOriginURL, - const nsAString& aManifestURL, - const nsAString& aPermission, - bool aReadOnly) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - nsresult rv; - nsCOMPtr ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsCOMPtr uri; - rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aOriginURL), nullptr, nullptr, - getter_AddRefs(uri)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); - if (!ssm) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr principal; - rv = ssm->GetAppCodebasePrincipal(uri, aAppId, false, - getter_AddRefs(principal)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsCOMPtr pm = - do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); - if (!pm) { - return NS_ERROR_FAILURE; - } - - nsCString basePermission; - basePermission.Append(NS_ConvertUTF16toUTF8(aPermission)); - - // Write permission - { - nsCString permission; - permission.Append(basePermission); - permission.AppendASCII("-write"); - - uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION; - rv = pm->TestExactPermissionFromPrincipal(principal, permission.get(), - &perm); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (aReadOnly && perm == nsIPermissionManager::ALLOW_ACTION) { - rv = pm->RemoveFromPrincipal(principal, permission.get()); - } - else if (!aReadOnly && perm != nsIPermissionManager::ALLOW_ACTION) { - rv = pm->AddFromPrincipal(principal, permission.get(), - nsIPermissionManager::ALLOW_ACTION, - nsIPermissionManager::EXPIRE_NEVER, 0); - } - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - // Read permission - { - nsCString permission; - permission.Append(basePermission); - permission.AppendASCII("-read"); - - uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION; - rv = pm->TestExactPermissionFromPrincipal(principal, permission.get(), - &perm); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (perm != nsIPermissionManager::ALLOW_ACTION) { - rv = pm->AddFromPrincipal(principal, permission.get(), - nsIPermissionManager::ALLOW_ACTION, - nsIPermissionManager::EXPIRE_NEVER, 0); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - } - - // Generic permission - uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION; - rv = pm->TestExactPermissionFromPrincipal(principal, basePermission.get(), - &perm); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (perm != nsIPermissionManager::ALLOW_ACTION) { - rv = pm->AddFromPrincipal(principal, basePermission.get(), - nsIPermissionManager::ALLOW_ACTION, - nsIPermissionManager::EXPIRE_NEVER, 0); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - return NS_OK; -} - -class MOZ_STACK_CLASS GetDataStoreInfosData -{ -public: - GetDataStoreInfosData(nsClassHashtable& aAccessStores, - const nsAString& aName, uint32_t aAppId, - nsTArray& aStores) - : mAccessStores(aAccessStores) - , mName(aName) - , mAppId(aAppId) - , mStores(aStores) - {} - - nsClassHashtable& mAccessStores; - nsString mName; - uint32_t mAppId; - nsTArray& mStores; -}; - -PLDHashOperator -GetDataStoreInfosEnumerator(const uint32_t& aAppId, - DataStoreInfo* aInfo, - void* aUserData) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - auto* data = static_cast(aUserData); - if (aAppId == data->mAppId) { - return PL_DHASH_NEXT; - } - - HashApp* apps; - if (!data->mAccessStores.Get(data->mName, &apps)) { - return PL_DHASH_NEXT; - } - - DataStoreInfo* accessInfo = nullptr; - if (!apps->Get(data->mAppId, &accessInfo)) { - return PL_DHASH_NEXT; - } - - bool readOnly = aInfo->mReadOnly || accessInfo->mReadOnly; - DataStoreInfo* accessStore = data->mStores.AppendElement(); - accessStore->Init(aInfo->mName, aInfo->mOriginURL, - aInfo->mManifestURL, readOnly, - aInfo->mEnabled); - - return PL_DHASH_NEXT; -} - -// This class is useful to enumerate the add permissions for each app. -class MOZ_STACK_CLASS AddPermissionsData -{ -public: - AddPermissionsData(const nsAString& aPermission, bool aReadOnly) - : mPermission(aPermission) - , mReadOnly(aReadOnly) - , mResult(NS_OK) - {} - - nsString mPermission; - bool mReadOnly; - nsresult mResult; -}; - -PLDHashOperator -AddPermissionsEnumerator(const uint32_t& aAppId, - DataStoreInfo* aInfo, - void* userData) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - auto* data = static_cast(userData); - - // ReadOnly is decided by the owner first. - bool readOnly = data->mReadOnly || aInfo->mReadOnly; - - data->mResult = ResetPermission(aAppId, aInfo->mOriginURL, - aInfo->mManifestURL, - data->mPermission, - readOnly); - return NS_FAILED(data->mResult) ? PL_DHASH_STOP : PL_DHASH_NEXT; -} - -// This class is useful to enumerate the add permissions for each app. -class MOZ_STACK_CLASS AddAccessPermissionsData -{ -public: - AddAccessPermissionsData(const nsAString& aName, bool aReadOnly) - : mName(aName) - , mReadOnly(aReadOnly) - , mResult(NS_OK) - {} - - nsString mName; - bool mReadOnly; - nsresult mResult; -}; - -PLDHashOperator -AddAccessPermissionsEnumerator(const uint32_t& aAppId, - DataStoreInfo* aInfo, - void* userData) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - auto* data = static_cast(userData); - - nsString permission; - GeneratePermissionName(permission, data->mName, aInfo->mManifestURL); - - // ReadOnly is decided by the owner first. - bool readOnly = aInfo->mReadOnly || data->mReadOnly; - - data->mResult = ResetPermission(aAppId, aInfo->mOriginURL, - aInfo->mManifestURL, - permission, readOnly); - return NS_FAILED(data->mResult) ? PL_DHASH_STOP : PL_DHASH_NEXT; -} - -} /* anonymous namespace */ - -// A PendingRequest is created when a content code wants a list of DataStores -// but some of them are not enabled yet. -class PendingRequest -{ -public: - void Init(nsPIDOMWindow* aWindow, Promise* aPromise, - const nsTArray& aStores, - const nsTArray& aPendingDataStores) - { - mWindow = aWindow; - mPromise = aPromise; - mStores = aStores; - mPendingDataStores = aPendingDataStores; - } - - nsCOMPtr mWindow; - nsRefPtr mPromise; - nsTArray mStores; - - // This array contains the list of manifestURLs of the DataStores that are - // not enabled yet. - nsTArray mPendingDataStores; -}; - -// This callback is used to enable a DataStore when its first revisionID is -// created. -class RevisionAddedEnableStoreCallback MOZ_FINAL : - public DataStoreRevisionCallback -{ -public: - NS_INLINE_DECL_REFCOUNTING(RevisionAddedEnableStoreCallback); - - RevisionAddedEnableStoreCallback(uint32_t aAppId, - const nsAString& aName, - const nsAString& aManifestURL) - : mAppId(aAppId) - , mName(aName) - , mManifestURL(aManifestURL) - { - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - } - - void - Run(const nsAString& aRevisionId) - { - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - nsRefPtr service = DataStoreService::Get(); - MOZ_ASSERT(service); - - service->EnableDataStore(mAppId, mName, mManifestURL); - } - -private: - uint32_t mAppId; - nsString mName; - nsString mManifestURL; -}; - -// This DataStoreDBCallback is called when DataStoreDB opens the DataStore DB. -// Then the first revision will be created if it doesn't exist yet. -class FirstRevisionIdCallback MOZ_FINAL : public DataStoreDBCallback - , public nsIDOMEventListener -{ -public: - NS_DECL_ISUPPORTS - - FirstRevisionIdCallback(uint32_t aAppId, const nsAString& aName, - const nsAString& aManifestURL) - : mAppId(aAppId) - , mName(aName) - , mManifestURL(aManifestURL) - { - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - } - - void - Run(DataStoreDB* aDb, bool aSuccess) - { - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(aDb); - - if (!aSuccess) { - NS_WARNING("Failed to create the first revision."); - return; - } - - mTxn = aDb->Transaction(); - - ErrorResult rv; - nsRefPtr store = - mTxn->ObjectStore(NS_LITERAL_STRING(DATASTOREDB_REVISION), rv); - if (NS_WARN_IF(rv.Failed())) { - return; - } - - // a Null JSContext is ok because OpenCursor ignores it if the range is - // undefined. - mRequest = store->OpenCursor(nullptr, JS::UndefinedHandleValue, - IDBCursorDirection::Prev, rv); - if (NS_WARN_IF(rv.Failed())) { - return; - } - - nsresult res; - res = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"), - this, false); - if (NS_WARN_IF(NS_FAILED(res))) { - return; - } - } - - // nsIDOMEventListener - NS_IMETHOD - HandleEvent(nsIDOMEvent* aEvent) - { - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - nsString type; - nsresult rv = aEvent->GetType(type); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (!type.EqualsASCII("success")) { - return NS_ERROR_FAILURE; - } - - mRequest->RemoveEventListener(NS_LITERAL_STRING("success"), this, false); - - // Note: this cx is only used for rooting and AddRevision, neither of which - // actually care which compartment we're in. - AutoSafeJSContext cx; - - ErrorResult error; - JS::Rooted result(cx, mRequest->GetResult(error)); - if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); - } - - // This means that the content is a IDBCursor, so the first revision already - // exists. - if (result.isObject()) { - nsRefPtr service = DataStoreService::Get(); - MOZ_ASSERT(service); - - return service->EnableDataStore(mAppId, mName, mManifestURL); - } - - MOZ_ASSERT(mTxn); - nsRefPtr store = - mTxn->ObjectStore(NS_LITERAL_STRING(DATASTOREDB_REVISION), error); - if (NS_WARN_IF(error.Failed())) { - return error.ErrorCode(); - } - MOZ_ASSERT(store); - - nsRefPtr callback = - new RevisionAddedEnableStoreCallback(mAppId, mName, mManifestURL); - - // If the revision doesn't exist, let's create it. - nsRefPtr mRevision = new DataStoreRevision(); - return mRevision->AddRevision(cx, store, 0, DataStoreRevision::RevisionVoid, - callback); - } - -private: - nsRefPtr mRequest; - - nsRefPtr mTxn; - nsRefPtr mRevision; - - uint32_t mAppId; - nsString mName; - nsString mManifestURL; -}; - -NS_IMPL_ISUPPORTS(FirstRevisionIdCallback, nsIDOMEventListener) - -// This class calls the 'retrieveRevisionId' method of the DataStore object for -// any DataStore in the 'mResults' array. When all of them are called, the -// promise is resolved with 'mResults'. -// The reson why this has to be done is because DataStore are object that can be -// created in any thread and in any process. The first revision has been -// created, but they don't know its value yet. -class RetrieveRevisionsCounter -{ -public: - NS_INLINE_DECL_REFCOUNTING(RetrieveRevisionsCounter); - - RetrieveRevisionsCounter(uint32_t aId, Promise* aPromise, uint32_t aCount) - : mPromise(aPromise) - , mId(aId) - , mCount(aCount) - { - MOZ_ASSERT(NS_IsMainThread()); - } - - void - AppendDataStore(JSContext* aCx, DataStore* aDataStore, - nsIDataStore* aDataStoreIf) - { - MOZ_ASSERT(NS_IsMainThread()); - - mResults.AppendElement(aDataStore); - - // DataStore will run this callback when the revisionID is retrieved. - JSFunction* func = js::NewFunctionWithReserved(aCx, JSCallback, - 0 /* nargs */, 0 /* flags */, - nullptr, nullptr); - if (!func) { - return; - } - - JS::Rooted obj(aCx, JS_GetFunctionObject(func)); - if (!obj) { - return; - } - - // We use the ID to know which counter is this. The service keeps all of - // these counters alive with their own IDs in an hashtable. - js::SetFunctionNativeReserved(obj, 0, JS::Int32Value(mId)); - - JS::Rooted value(aCx, JS::ObjectValue(*obj)); - nsresult rv = aDataStoreIf->RetrieveRevisionId(value); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - } - -private: - static bool - JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp) - { - MOZ_ASSERT(NS_IsMainThread()); - - JS::CallArgs args = CallArgsFromVp(aArgc, aVp); - - JS::Rooted value(aCx, - js::GetFunctionNativeReserved(&args.callee(), 0)); - uint32_t id = value.toInt32(); - - nsRefPtr service = DataStoreService::Get(); - MOZ_ASSERT(service); - - nsRefPtr counter = service->GetCounter(id); - MOZ_ASSERT(counter); - - // When all the callbacks are called, we can resolve the promise and remove - // the counter from the service. - --counter->mCount; - if (!counter->mCount) { - service->RemoveCounter(id); - counter->mPromise->MaybeResolve(counter->mResults); - } - - return true; - } - - nsRefPtr mPromise; - nsTArray> mResults; - - uint32_t mId; - uint32_t mCount; -}; - -/* static */ already_AddRefed -DataStoreService::GetOrCreate() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!gDataStoreService) { - nsRefPtr service = new DataStoreService(); - if (NS_WARN_IF(NS_FAILED(service->Init()))) { - return nullptr; - } - - gDataStoreService = service; - } - - nsRefPtr service = gDataStoreService.get(); - return service.forget(); -} - -/* static */ already_AddRefed -DataStoreService::Get() -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsRefPtr service = gDataStoreService.get(); - return service.forget(); -} - -/* static */ void -DataStoreService::Shutdown() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (gDataStoreService) { - if (IsMainProcess()) { - nsCOMPtr obs = mozilla::services::GetObserverService(); - if (obs) { - obs->RemoveObserver(gDataStoreService, "webapps-clear-data"); - } - } - - gDataStoreService = nullptr; - } -} - -NS_INTERFACE_MAP_BEGIN(DataStoreService) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDataStoreService) - NS_INTERFACE_MAP_ENTRY(nsIDataStoreService) - NS_INTERFACE_MAP_ENTRY(nsIObserver) -NS_INTERFACE_MAP_END - -NS_IMPL_ADDREF(DataStoreService) -NS_IMPL_RELEASE(DataStoreService) - -DataStoreService::DataStoreService() -{ - MOZ_ASSERT(NS_IsMainThread()); -} - -DataStoreService::~DataStoreService() -{ - MOZ_ASSERT(NS_IsMainThread()); -} - -nsresult -DataStoreService::Init() -{ - if (!IsMainProcess()) { - return NS_OK; - } - - nsCOMPtr obs = mozilla::services::GetObserverService(); - if (!obs) { - return NS_ERROR_FAILURE; - } - - nsresult rv = obs->AddObserver(this, "webapps-clear-data", false); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -NS_IMETHODIMP -DataStoreService::InstallDataStore(uint32_t aAppId, - const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly) -{ - ASSERT_PARENT_PROCESS() - MOZ_ASSERT(NS_IsMainThread()); - - HashApp* apps = nullptr; - if (!mStores.Get(aName, &apps)) { - apps = new HashApp(); - mStores.Put(aName, apps); - } - - DataStoreInfo* info = nullptr; - if (!apps->Get(aAppId, &info)) { - info = new DataStoreInfo(aName, aOriginURL, aManifestURL, aReadOnly, false); - apps->Put(aAppId, info); - } else { - info->Update(aName, aOriginURL, aManifestURL, aReadOnly); - } - - nsresult rv = AddPermissions(aAppId, aName, aOriginURL, aManifestURL, - aReadOnly); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // Immediately create the first revision. - return CreateFirstRevisionId(aAppId, aName, aManifestURL); -} - -NS_IMETHODIMP -DataStoreService::InstallAccessDataStore(uint32_t aAppId, - const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly) -{ - ASSERT_PARENT_PROCESS() - MOZ_ASSERT(NS_IsMainThread()); - - HashApp* apps = nullptr; - if (!mAccessStores.Get(aName, &apps)) { - apps = new HashApp(); - mAccessStores.Put(aName, apps); - } - - DataStoreInfo* info = nullptr; - if (!apps->Get(aAppId, &info)) { - info = new DataStoreInfo(aName, aOriginURL, aManifestURL, aReadOnly, false); - apps->Put(aAppId, info); - } else { - info->Update(aName, aOriginURL, aManifestURL, aReadOnly); - } - - return AddAccessPermissions(aAppId, aName, aOriginURL, aManifestURL, - aReadOnly); -} - -NS_IMETHODIMP -DataStoreService::GetDataStores(nsIDOMWindow* aWindow, - const nsAString& aName, - nsISupports** aDataStores) -{ - // FIXME This will be a thread-safe method. - MOZ_ASSERT(NS_IsMainThread()); - - nsCOMPtr window = do_QueryInterface(aWindow); - if (!window) { - return NS_ERROR_FAILURE; - } - - 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()) { - uint32_t appId; - nsresult rv = principal->GetAppId(&appId); - if (NS_FAILED(rv)) { - RejectPromise(window, promise, rv); - promise.forget(aDataStores); - return NS_OK; - } - - rv = GetDataStoreInfos(aName, appId, stores); - if (NS_FAILED(rv)) { - RejectPromise(window, promise, rv); - 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. - 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; -} - -void -DataStoreService::GetDataStoresCreate(nsPIDOMWindow* aWindow, Promise* aPromise, - const nsTArray& aStores) -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!aStores.Length()) { - GetDataStoresResolve(aWindow, aPromise, aStores); - return; - } - - nsTArray pendingDataStores; - for (uint32_t i = 0; i < aStores.Length(); ++i) { - if (!aStores[i].mEnabled) { - pendingDataStores.AppendElement(aStores[i].mManifestURL); - } - } - - if (!pendingDataStores.Length()) { - GetDataStoresResolve(aWindow, aPromise, aStores); - return; - } - - PendingRequests* requests; - if (!mPendingRequests.Get(aStores[0].mName, &requests)) { - requests = new PendingRequests(); - mPendingRequests.Put(aStores[0].mName, requests); - } - - PendingRequest* request = requests->AppendElement(); - request->Init(aWindow, aPromise, aStores, pendingDataStores); -} - -void -DataStoreService::GetDataStoresResolve(nsPIDOMWindow* aWindow, - Promise* aPromise, - const nsTArray& aStores) -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!aStores.Length()) { - nsTArray> results; - aPromise->MaybeResolve(results); - return; - } - - AutoSafeJSContext cx; - - // The counter will finish this task once all the DataStores will know their - // first revision Ids. - nsRefPtr counter = - new RetrieveRevisionsCounter(++gCounterID, aPromise, aStores.Length()); - mPendingCounters.Put(gCounterID, counter); - - for (uint32_t i = 0; i < aStores.Length(); ++i) { - nsCOMPtr dataStore = - do_CreateInstance("@mozilla.org/dom/datastore;1"); - if (NS_WARN_IF(!dataStore)) { - return; - } - - nsresult rv = dataStore->Init(aWindow, aStores[i].mName, - aStores[i].mManifestURL, - aStores[i].mReadOnly); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - nsCOMPtr xpcwrappedjs = do_QueryInterface(dataStore); - if (NS_WARN_IF(!xpcwrappedjs)) { - return; - } - - JS::Rooted dataStoreJS(cx, xpcwrappedjs->GetJSObject()); - if (NS_WARN_IF(!dataStoreJS)) { - return; - } - - JSAutoCompartment ac(cx, dataStoreJS); - nsRefPtr dataStoreObj = new DataStoreImpl(dataStoreJS, - aWindow); - - nsRefPtr exposedStore = new DataStore(aWindow); - - ErrorResult error; - exposedStore->SetDataStoreImpl(*dataStoreObj, error); - if (error.Failed()) { - return; - } - - JS::Rooted obj(cx, exposedStore->WrapObject(cx)); - MOZ_ASSERT(obj); - - JS::Rooted exposedObject(cx, JS::ObjectValue(*obj)); - dataStore->SetExposedObject(exposedObject); - - counter->AppendDataStore(cx, exposedStore, dataStore); - } -} - -// Thie method populates 'aStores' with the list of DataStores with 'aName' as -// name and available for this 'aAppId'. -nsresult -DataStoreService::GetDataStoreInfos(const nsAString& aName, - uint32_t aAppId, - nsTArray& aStores) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - nsCOMPtr appsService = - do_GetService("@mozilla.org/AppsService;1"); - if (NS_WARN_IF(!appsService)) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr app; - nsresult rv = appsService->GetAppByLocalId(aAppId, getter_AddRefs(app)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (!app) { - return NS_ERROR_DOM_SECURITY_ERR; - } - - uint16_t status; - rv = app->GetAppStatus(&status); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (status != nsIPrincipal::APP_STATUS_CERTIFIED && - !Preferences::GetBool("dom.testing.datastore_enabled_for_hosted_apps", - false)) { - return NS_ERROR_DOM_SECURITY_ERR; - } - - aStores.Clear(); - - HashApp* apps = nullptr; - if (!mStores.Get(aName, &apps)) { - return NS_OK; - } - - DataStoreInfo* info = nullptr; - if (apps->Get(aAppId, &info)) { - DataStoreInfo* owned = aStores.AppendElement(); - owned->Init(info->mName, info->mOriginURL, info->mManifestURL, false, - info->mEnabled); - } - - GetDataStoreInfosData data(mAccessStores, aName, aAppId, aStores); - apps->EnumerateRead(GetDataStoreInfosEnumerator, &data); - return NS_OK; -} - -// This method is called when an app with DataStores is deleted. -void -DataStoreService::DeleteDataStores(uint32_t aAppId) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - mStores.Enumerate(DeleteDataStoresEnumerator, &aAppId); - mAccessStores.Enumerate(DeleteDataStoresEnumerator, &aAppId); -} - -NS_IMETHODIMP -DataStoreService::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - if (strcmp(aTopic, "webapps-clear-data")) { - return NS_OK; - } - - nsCOMPtr params = - do_QueryInterface(aSubject); - MOZ_ASSERT(params); - - // DataStore is explosed to apps, not browser content. - bool browserOnly; - nsresult rv = params->GetBrowserOnly(&browserOnly); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (browserOnly) { - return NS_OK; - } - - uint32_t appId; - rv = params->GetAppId(&appId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - DeleteDataStores(appId); - - return NS_OK; -} - -nsresult -DataStoreService::AddPermissions(uint32_t aAppId, - const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - // This is the permission name. - nsString permission; - GeneratePermissionName(permission, aName, aManifestURL); - - // When a new DataStore is installed, the permissions must be set for the - // owner app. - nsresult rv = ResetPermission(aAppId, aOriginURL, aManifestURL, permission, - aReadOnly); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // For any app that wants to have access to this DataStore we add the - // permissions. - HashApp* apps; - if (!mAccessStores.Get(aName, &apps)) { - return NS_OK; - } - - AddPermissionsData data(permission, aReadOnly); - apps->EnumerateRead(AddPermissionsEnumerator, &data); - return data.mResult; -} - -nsresult -DataStoreService::AddAccessPermissions(uint32_t aAppId, const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - // When an app wants to have access to a DataStore, the permissions must be - // set. - HashApp* apps = nullptr; - if (!mStores.Get(aName, &apps)) { - return NS_OK; - } - - AddAccessPermissionsData data(aName, aReadOnly); - apps->EnumerateRead(AddAccessPermissionsEnumerator, &data); - return data.mResult; -} - -// This method starts the operation to create the first revision for a DataStore -// if needed. -nsresult -DataStoreService::CreateFirstRevisionId(uint32_t aAppId, - const nsAString& aName, - const nsAString& aManifestURL) -{ - AssertIsInMainProcess(); - MOZ_ASSERT(NS_IsMainThread()); - - nsRefPtr db = new DataStoreDB(aManifestURL, aName); - - nsRefPtr callback = - new FirstRevisionIdCallback(aAppId, aName, aManifestURL); - - Sequence dbs; - dbs.AppendElement(NS_LITERAL_STRING(DATASTOREDB_REVISION)); - - return db->Open(IDBTransactionMode::Readwrite, dbs, callback); -} - -nsresult -DataStoreService::EnableDataStore(uint32_t aAppId, const nsAString& aName, - const nsAString& aManifestURL) -{ - MOZ_ASSERT(NS_IsMainThread()); - - { - HashApp* apps = nullptr; - DataStoreInfo* info = nullptr; - if (mStores.Get(aName, &apps) && apps->Get(aAppId, &info)) { - info->Enable(); - } - } - - // 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)) { - return NS_OK; - } - - for (uint32_t i = 0; i < requests->Length();) { - PendingRequest& request = requests->ElementAt(i); - nsTArray::index_type pos = - request.mPendingDataStores.IndexOf(aManifestURL); - if (pos != request.mPendingDataStores.NoIndex) { - request.mPendingDataStores.RemoveElementAt(pos); - - // No other pending dataStores. - if (request.mPendingDataStores.IsEmpty()) { - GetDataStoresResolve(request.mWindow, request.mPromise, - request.mStores); - requests->RemoveElementAt(i); - continue; - } - } - - ++i; - } - - // No other pending requests for this name. - if (requests->IsEmpty()) { - mPendingRequests.Remove(aName); - } - - return NS_OK; -} - -already_AddRefed -DataStoreService::GetCounter(uint32_t aId) const -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsRefPtr counter; - return mPendingCounters.Get(aId, getter_AddRefs(counter)) - ? counter.forget() : nullptr; -} - -void -DataStoreService::RemoveCounter(uint32_t aId) -{ - MOZ_ASSERT(NS_IsMainThread()); - mPendingCounters.Remove(aId); -} - -nsresult -DataStoreService::GetDataStoresFromIPC(const nsAString& aName, - nsIPrincipal* aPrincipal, - nsTArray* aValue) -{ - MOZ_ASSERT(IsMainProcess()); - MOZ_ASSERT(NS_IsMainThread()); - - 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 -DataStoreService::GenerateUUID(nsAString& aID) -{ - nsresult rv; - - if (!mUUIDGenerator) { - mUUIDGenerator = do_GetService("@mozilla.org/uuid-generator;1", &rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - nsID id; - rv = mUUIDGenerator->GenerateUUIDInPlace(&id); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - char chars[NSID_LENGTH]; - id.ToProvidedString(chars); - CopyASCIItoUTF16(chars, aID); - - return NS_OK; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/datastore/DataStoreService.h b/dom/datastore/DataStoreService.h deleted file mode 100644 index 73210ff1d7b4..000000000000 --- a/dom/datastore/DataStoreService.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=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_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; - -namespace mozilla { -namespace dom { - -class DataStoreInfo; -class FirstRevisionIdCallback; -class PendingRequest; -class Promise; -class RetrieveRevisionsCounter; -class RevisionAddedEnableStoreCallback; - -class DataStoreService MOZ_FINAL : public nsIDataStoreService - , public nsIObserver -{ - friend class ContentChild; - friend class FirstRevisionIdCallback; - friend class RetrieveRevisionsCounter; - friend class RevisionAddedEnableStoreCallback; - -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIOBSERVER - NS_DECL_NSIDATASTORESERVICE - - // Returns the DataStoreService singleton. Only to be called from main - // thread. - static already_AddRefed GetOrCreate(); - - static already_AddRefed Get(); - - static void Shutdown(); - - nsresult GenerateUUID(nsAString& aID); - - nsresult GetDataStoresFromIPC(const nsAString& aName, - nsIPrincipal* aPrincipal, - nsTArray* aValue); - -private: - DataStoreService(); - ~DataStoreService(); - - nsresult Init(); - - typedef nsClassHashtable HashApp; - - nsresult AddPermissions(uint32_t aAppId, const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly); - - nsresult AddAccessPermissions(uint32_t aAppId, const nsAString& aName, - const nsAString& aOriginURL, - const nsAString& aManifestURL, - bool aReadOnly); - - nsresult CreateFirstRevisionId(uint32_t aAppId, const nsAString& aName, - const nsAString& aManifestURL); - - void GetDataStoresCreate(nsPIDOMWindow* aWindow, Promise* aPromise, - const nsTArray& aStores); - - void GetDataStoresResolve(nsPIDOMWindow* aWindow, Promise* aPromise, - const nsTArray& aStores); - - nsresult GetDataStoreInfos(const nsAString& aName, uint32_t aAppId, - nsTArray& aStores); - - void DeleteDataStores(uint32_t aAppId); - - nsresult EnableDataStore(uint32_t aAppId, const nsAString& aName, - const nsAString& aManifestURL); - - already_AddRefed GetCounter(uint32_t aId) const; - - void RemoveCounter(uint32_t aId); - - nsClassHashtable mStores; - nsClassHashtable mAccessStores; - - typedef nsTArray PendingRequests; - nsClassHashtable mPendingRequests; - - nsRefPtrHashtable mPendingCounters; - - nsCOMPtr mUUIDGenerator; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_DataStoreService_h diff --git a/dom/datastore/DataStoreService.js b/dom/datastore/DataStoreService.js new file mode 100644 index 000000000000..fd8faafca758 --- /dev/null +++ b/dom/datastore/DataStoreService.js @@ -0,0 +1,522 @@ +/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */ +/* vim: set ft=javascript ts=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/. */ + +'use strict' + +/* static functions */ + +function debug(s) { + //dump('DEBUG DataStoreService: ' + s + '\n'); +} + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +Cu.import('resource://gre/modules/XPCOMUtils.jsm'); +Cu.import('resource://gre/modules/Services.jsm'); +Cu.import('resource://gre/modules/DataStoreImpl.jsm'); +Cu.import("resource://gre/modules/DataStoreDB.jsm"); +Cu.import("resource://gre/modules/DOMRequestHelper.jsm"); + +XPCOMUtils.defineLazyServiceGetter(this, "cpmm", + "@mozilla.org/childprocessmessagemanager;1", + "nsIMessageSender"); + +XPCOMUtils.defineLazyServiceGetter(this, "ppmm", + "@mozilla.org/parentprocessmessagemanager;1", + "nsIMessageBroadcaster"); + +XPCOMUtils.defineLazyServiceGetter(this, "permissionManager", + "@mozilla.org/permissionmanager;1", + "nsIPermissionManager"); + +XPCOMUtils.defineLazyServiceGetter(this, "secMan", + "@mozilla.org/scriptsecuritymanager;1", + "nsIScriptSecurityManager"); + +/* DataStoreService */ + +const DATASTORESERVICE_CID = Components.ID('{d193d0e2-c677-4a7b-bb0a-19155b470f2e}'); +const REVISION_VOID = "void"; + +function DataStoreService() { + debug('DataStoreService Constructor'); + + this.inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime) + .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; + + if (this.inParent) { + let obs = Services.obs; + if (!obs) { + debug("DataStore Error: observer-service is null!"); + return; + } + + obs.addObserver(this, 'webapps-clear-data', false); + } + + let self = this; + cpmm.addMessageListener("datastore-first-revision-created", + function(aMsg) { self.receiveMessage(aMsg); }); +} + +DataStoreService.prototype = { + inParent: false, + + // Hash of DataStores + stores: {}, + accessStores: {}, + pendingRequests: {}, + + installDataStore: function(aAppId, aName, aOrigin, aOwner, aReadOnly) { + debug('installDataStore - appId: ' + aAppId + ', aName: ' + + aName + ', aOrigin: ' + aOrigin + ', aOwner:' + aOwner + + ', aReadOnly: ' + aReadOnly); + + this.checkIfInParent(); + + if (aName in this.stores && aAppId in this.stores[aName]) { + debug('This should not happen'); + return; + } + + if (!(aName in this.stores)) { + this.stores[aName] = {}; + } + + // A DataStore is enabled when it has a first valid revision. + this.stores[aName][aAppId] = { origin: aOrigin, owner: aOwner, + readOnly: aReadOnly, enabled: false }; + + this.addPermissions(aAppId, aName, aOrigin, aOwner, aReadOnly); + + this.createFirstRevisionId(aAppId, aName, aOwner); + }, + + installAccessDataStore: function(aAppId, aName, aOrigin, aOwner, aReadOnly) { + debug('installAccessDataStore - appId: ' + aAppId + ', aName: ' + + aName + ', aOrigin: ' + aOrigin + ', aOwner:' + aOwner + + ', aReadOnly: ' + aReadOnly); + + this.checkIfInParent(); + + if (aName in this.accessStores && aAppId in this.accessStores[aName]) { + debug('This should not happen'); + return; + } + + if (!(aName in this.accessStores)) { + this.accessStores[aName] = {}; + } + + this.accessStores[aName][aAppId] = { origin: aOrigin, owner: aOwner, + readOnly: aReadOnly }; + this.addAccessPermissions(aAppId, aName, aOrigin, aOwner, aReadOnly); + }, + + checkIfInParent: function() { + if (!this.inParent) { + throw "DataStore can execute this operation just in the parent process"; + } + }, + + createFirstRevisionId: function(aAppId, aName, aOwner) { + debug("createFirstRevisionId database: " + aName); + + let self = this; + let db = new DataStoreDB(); + db.init(aOwner, aName); + db.revisionTxn( + 'readwrite', + function(aTxn, aRevisionStore) { + debug("createFirstRevisionId - transaction success"); + + let request = aRevisionStore.openCursor(null, 'prev'); + request.onsuccess = function(aEvent) { + let cursor = aEvent.target.result; + if (cursor) { + debug("First revision already created."); + self.enableDataStore(aAppId, aName, aOwner); + } else { + // If the revision doesn't exist, let's create the first one. + db.addRevision(aRevisionStore, 0, REVISION_VOID, function() { + debug("First revision created."); + self.enableDataStore(aAppId, aName, aOwner); + }); + } + }; + } + ); + }, + + enableDataStore: function(aAppId, aName, aOwner) { + if (aName in this.stores && aAppId in this.stores[aName]) { + this.stores[aName][aAppId].enabled = true; + ppmm.broadcastAsyncMessage('datastore-first-revision-created', + { name: aName, owner: aOwner }); + } + }, + + addPermissions: function(aAppId, aName, aOrigin, aOwner, aReadOnly) { + // When a new DataStore is installed, the permissions must be set for the + // owner app. + let permission = "indexedDB-chrome-" + aName + '|' + aOwner; + this.resetPermissions(aAppId, aOrigin, aOwner, permission, aReadOnly); + + // For any app that wants to have access to this DataStore we add the + // permissions. + if (aName in this.accessStores) { + for (let appId in this.accessStores[aName]) { + // ReadOnly is decided by the owner first. + let readOnly = aReadOnly || this.accessStores[aName][appId].readOnly; + this.resetPermissions(appId, this.accessStores[aName][appId].origin, + this.accessStores[aName][appId].owner, + permission, readOnly); + } + } + }, + + addAccessPermissions: function(aAppId, aName, aOrigin, aOwner, aReadOnly) { + // When an app wants to have access to a DataStore, the permissions must be + // set. + if (!(aName in this.stores)) { + return; + } + + for (let appId in this.stores[aName]) { + let permission = "indexedDB-chrome-" + aName + '|' + this.stores[aName][appId].owner; + // The ReadOnly is decied by the owenr first. + let readOnly = this.stores[aName][appId].readOnly || aReadOnly; + this.resetPermissions(aAppId, aOrigin, aOwner, permission, readOnly); + } + }, + + resetPermissions: function(aAppId, aOrigin, aOwner, aPermission, aReadOnly) { + debug("ResetPermissions - appId: " + aAppId + " - origin: " + aOrigin + + " - owner: " + aOwner + " - permissions: " + aPermission + + " - readOnly: " + aReadOnly); + + let uri = Services.io.newURI(aOrigin, null, null); + let principal = secMan.getAppCodebasePrincipal(uri, aAppId, false); + + let result = permissionManager.testExactPermissionFromPrincipal(principal, + aPermission + '-write'); + + if (aReadOnly && result == Ci.nsIPermissionManager.ALLOW_ACTION) { + debug("Write permission removed"); + permissionManager.removeFromPrincipal(principal, aPermission + '-write'); + } else if (!aReadOnly && result != Ci.nsIPermissionManager.ALLOW_ACTION) { + debug("Write permission added"); + permissionManager.addFromPrincipal(principal, aPermission + '-write', + Ci.nsIPermissionManager.ALLOW_ACTION); + } + + result = permissionManager.testExactPermissionFromPrincipal(principal, + aPermission + '-read'); + if (result != Ci.nsIPermissionManager.ALLOW_ACTION) { + debug("Read permission added"); + permissionManager.addFromPrincipal(principal, aPermission + '-read', + Ci.nsIPermissionManager.ALLOW_ACTION); + } + + result = permissionManager.testExactPermissionFromPrincipal(principal, aPermission); + if (result != Ci.nsIPermissionManager.ALLOW_ACTION) { + debug("Generic permission added"); + permissionManager.addFromPrincipal(principal, aPermission, + Ci.nsIPermissionManager.ALLOW_ACTION); + } + }, + + getDataStores: function(aWindow, aName) { + debug('getDataStores - aName: ' + aName); + + let self = this; + return new aWindow.Promise(function(resolve, reject) { + // If this request comes from the main process, we have access to the + // window, so we can skip the ipc communication. + if (self.inParent) { + let stores = self.getDataStoresInfo(aName, aWindow.document.nodePrincipal.appId); + if (stores === null) { + reject(new aWindow.DOMError("SecurityError", "Access denied")); + return; + } + self.getDataStoreCreate(aWindow, resolve, stores); + } else { + // This method can be called in the child so we need to send a request + // to the parent and create DataStore object here. + new DataStoreServiceChild(aWindow, aName, function(aStores) { + debug("DataStoreServiceChild success callback!"); + self.getDataStoreCreate(aWindow, resolve, aStores); + }, function() { + debug("DataStoreServiceChild error callback!"); + reject(new aWindow.DOMError("SecurityError", "Access denied")); + }); + } + }); + }, + + getDataStoresInfo: function(aName, aAppId) { + debug('GetDataStoresInfo'); + + let appsService = Cc["@mozilla.org/AppsService;1"] + .getService(Ci.nsIAppsService); + let app = appsService.getAppByLocalId(aAppId); + if (!app) { + return null; + } + + let prefName = "dom.testing.datastore_enabled_for_hosted_apps"; + if (app.appStatus != Ci.nsIPrincipal.APP_STATUS_CERTIFIED && + (Services.prefs.getPrefType(prefName) == Services.prefs.PREF_INVALID || + !Services.prefs.getBoolPref(prefName))) { + return null; + } + + let results = []; + + if (aName in this.stores) { + if (aAppId in this.stores[aName]) { + results.push({ name: aName, + owner: this.stores[aName][aAppId].owner, + readOnly: false, + enabled: this.stores[aName][aAppId].enabled }); + } + + for (var i in this.stores[aName]) { + if (i == aAppId) { + continue; + } + + let access = this.getDataStoreAccess(aName, aAppId); + if (!access) { + continue; + } + + let readOnly = this.stores[aName][i].readOnly || access.readOnly; + results.push({ name: aName, + owner: this.stores[aName][i].owner, + readOnly: readOnly, + enabled: this.stores[aName][i].enabled }); + } + } + + return results; + }, + + getDataStoreCreate: function(aWindow, aResolve, aStores) { + debug("GetDataStoreCreate"); + + let results = new aWindow.Array(); + + if (!aStores.length) { + aResolve(results); + return; + } + + let pendingDataStores = []; + + for (let i = 0; i < aStores.length; ++i) { + if (!aStores[i].enabled) { + pendingDataStores.push(aStores[i].owner); + } + } + + if (!pendingDataStores.length) { + this.getDataStoreResolve(aWindow, aResolve, aStores); + return; + } + + if (!(aStores[0].name in this.pendingRequests)) { + this.pendingRequests[aStores[0].name] = []; + } + + this.pendingRequests[aStores[0].name].push({ window: aWindow, + resolve: aResolve, + stores: aStores, + pendingDataStores: pendingDataStores }); + }, + + getDataStoreResolve: function(aWindow, aResolve, aStores) { + debug("GetDataStoreResolve"); + + let callbackPending = aStores.length; + let results = new aWindow.Array(); + + if (!callbackPending) { + aResolve(results); + return; + } + + for (let i = 0; i < aStores.length; ++i) { + let obj = new DataStore(aWindow, aStores[i].name, + aStores[i].owner, aStores[i].readOnly); + + let storeImpl = aWindow.DataStoreImpl._create(aWindow, obj); + + let exposedStore = new aWindow.DataStore(); + exposedStore.setDataStoreImpl(storeImpl); + + obj.exposedObject = exposedStore; + + results.push(exposedStore); + + obj.retrieveRevisionId( + function() { + --callbackPending; + if (!callbackPending) { + aResolve(results); + } + } + ); + } + }, + + getDataStoreAccess: function(aName, aAppId) { + if (!(aName in this.accessStores) || + !(aAppId in this.accessStores[aName])) { + return null; + } + + return this.accessStores[aName][aAppId]; + }, + + observe: function observe(aSubject, aTopic, aData) { + debug('observe - aTopic: ' + aTopic); + if (aTopic != 'webapps-clear-data') { + return; + } + + let params = + aSubject.QueryInterface(Ci.mozIApplicationClearPrivateDataParams); + + // DataStore is explosed to apps, not browser content. + if (params.browserOnly) { + return; + } + + function isEmpty(aMap) { + for (var key in aMap) { + if (aMap.hasOwnProperty(key)) { + return false; + } + } + return true; + } + + for (let key in this.stores) { + if (params.appId in this.stores[key]) { + this.deleteDatabase(key, this.stores[key][params.appId].owner); + delete this.stores[key][params.appId]; + } + + if (isEmpty(this.stores[key])) { + delete this.stores[key]; + } + } + + for (let key in this.accessStores) { + if (params.appId in this.accessStores[key]) { + delete this.accessStores[key][params.appId]; + } + + if (isEmpty(this.accessStores[key])) { + delete this.accessStores[key]; + } + } + }, + + deleteDatabase: function(aName, aOwner) { + debug("delete database: " + aName); + + let db = new DataStoreDB(); + db.init(aOwner, aName); + db.delete(); + }, + + receiveMessage: function(aMsg) { + debug("receiveMessage"); + let data = aMsg.json; + + if (!(data.name in this.pendingRequests)) { + return; + } + + for (let i = 0; i < this.pendingRequests[data.name].length;) { + let pos = this.pendingRequests[data.name][i].pendingDataStores.indexOf(data.owner); + if (pos != -1) { + this.pendingRequests[data.name][i].pendingDataStores.splice(pos, 1); + if (!this.pendingRequests[data.name][i].pendingDataStores.length) { + this.getDataStoreResolve(this.pendingRequests[data.name][i].window, + this.pendingRequests[data.name][i].resolve, + this.pendingRequests[data.name][i].stores); + this.pendingRequests[data.name].splice(i, 1); + continue; + } + } + + ++i; + } + + if (!this.pendingRequests[data.name].length) { + delete this.pendingRequests[data.name]; + } + }, + + classID : DATASTORESERVICE_CID, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataStoreService, + Ci.nsIObserver]), + classInfo: XPCOMUtils.generateCI({ + classID: DATASTORESERVICE_CID, + contractID: '@mozilla.org/datastore-service;1', + interfaces: [Ci.nsIDataStoreService, Ci.nsIObserver], + flags: Ci.nsIClassInfo.SINGLETON + }) +}; + +/* DataStoreServiceChild */ + +function DataStoreServiceChild(aWindow, aName, aSuccessCb, aErrorCb) { + debug("DataStoreServiceChild created"); + this.init(aWindow, aName, aSuccessCb, aErrorCb); +} + +DataStoreServiceChild.prototype = { + __proto__: DOMRequestIpcHelper.prototype, + + init: function(aWindow, aName, aSuccessCb, aErrorCb) { + debug("DataStoreServiceChild init"); + this._successCb = aSuccessCb; + this._errorCb = aErrorCb; + this._name = aName; + + this.initDOMRequestHelper(aWindow, [ "DataStore:Get:Return:OK", + "DataStore:Get:Return:KO" ]); + + cpmm.sendAsyncMessage("DataStore:Get", + { name: aName }, null, aWindow.document.nodePrincipal ); + }, + + receiveMessage: function(aMessage) { + debug("DataStoreServiceChild receiveMessage"); + + if (aMessage.data.name != this._name) { + return; + } + + switch (aMessage.name) { + case 'DataStore:Get:Return:OK': + this.destroyDOMRequestHelper(); + this._successCb(aMessage.data.stores); + break; + + case 'DataStore:Get:Return:KO': + this.destroyDOMRequestHelper(); + this._errorCb(); + break; + } + } +} + +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataStoreService]); diff --git a/dom/datastore/DataStoreServiceInternal.jsm b/dom/datastore/DataStoreServiceInternal.jsm new file mode 100644 index 000000000000..f301a3793e30 --- /dev/null +++ b/dom/datastore/DataStoreServiceInternal.jsm @@ -0,0 +1,68 @@ +/* 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 b85c7e9bb64a..092fc75e4795 100644 --- a/dom/datastore/moz.build +++ b/dom/datastore/moz.build @@ -5,7 +5,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. XPIDL_SOURCES += [ - 'nsIDataStore.idl', 'nsIDataStoreService.idl', ] @@ -14,15 +13,11 @@ XPIDL_MODULE = 'dom_datastore' EXPORTS.mozilla.dom += [ 'DataStore.h', 'DataStoreCursor.h', - 'DataStoreService.h', ] SOURCES += [ 'DataStore.cpp', 'DataStoreCursor.cpp', - 'DataStoreDB.cpp', - 'DataStoreRevision.cpp', - 'DataStoreService.cpp', ] LOCAL_INCLUDES += [ @@ -31,18 +26,17 @@ LOCAL_INCLUDES += [ EXTRA_COMPONENTS += [ 'DataStore.manifest', - 'DataStoreImpl.js', + 'DataStoreService.js', ] EXTRA_JS_MODULES += [ 'DataStoreChangeNotifier.jsm', 'DataStoreCursorImpl.jsm', 'DataStoreDB.jsm', + 'DataStoreImpl.jsm', + 'DataStoreServiceInternal.jsm', ] MOCHITEST_MANIFESTS += ['tests/mochitest.ini'] -include('/ipc/chromium/chromium-config.mozbuild') - FINAL_LIBRARY = 'xul' -FAIL_ON_WARNINGS = True diff --git a/dom/datastore/nsIDataStore.idl b/dom/datastore/nsIDataStore.idl deleted file mode 100644 index fc3d82598874..000000000000 --- a/dom/datastore/nsIDataStore.idl +++ /dev/null @@ -1,23 +0,0 @@ -/* -*- Mode: C++; 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 "nsISupports.idl" - -interface nsIDOMWindow; - -// NOTE: This is a temporary interface. -// It will be removed in the next patches for rewriting DataStore in C++. -[scriptable, uuid(0b41fef5-14ba-48b0-923c-3d8fb64692ae)] -interface nsIDataStore : nsISupports -{ - void init(in nsIDOMWindow window, - in DOMString name, - in DOMString manifestURL, - in boolean readOnly); - - attribute jsval exposedObject; - - void retrieveRevisionId(in jsval cb); -}; diff --git a/dom/datastore/nsIDataStoreService.idl b/dom/datastore/nsIDataStoreService.idl index 1157164f3809..a3fc914d0520 100644 --- a/dom/datastore/nsIDataStoreService.idl +++ b/dom/datastore/nsIDataStoreService.idl @@ -7,7 +7,7 @@ interface nsIDOMWindow; -[scriptable, uuid(0a050c4f-d292-4a14-8712-09bc1019840a)] +[scriptable, uuid(bd02d09c-41ab-47b7-9319-57aa8e5059b0)] interface nsIDataStoreService : nsISupports { void installDataStore(in unsigned long appId, @@ -24,4 +24,12 @@ interface nsIDataStoreService : nsISupports nsISupports getDataStores(in nsIDOMWindow window, in DOMString name); + + // This is an array of objects composed by: + // - readOnly: boolean + // - name: DOMString + // - owner: DOMString + // - enabled: true/false - true if this dataStore is ready to be used. + jsval getDataStoresInfo(in DOMString name, + in unsigned long appId); }; diff --git a/dom/indexedDB/IDBFactory.cpp b/dom/indexedDB/IDBFactory.cpp index c9e5aec67ebb..3eb8e99f8468 100644 --- a/dom/indexedDB/IDBFactory.cpp +++ b/dom/indexedDB/IDBFactory.cpp @@ -235,6 +235,9 @@ IDBFactory::Create(ContentParent* aContentParent, NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!"); NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!"); + NS_ASSERTION(aContentParent, "Null ContentParent!"); + + NS_ASSERTION(!nsContentUtils::GetCurrentJSContext(), "Should be called from C++"); // We need to get this information before we push a null principal to avoid // IsCallerChrome() assertion in quota manager. diff --git a/dom/indexedDB/IDBFactory.h b/dom/indexedDB/IDBFactory.h index 7bf8ff6e325b..e51d0900fdf1 100644 --- a/dom/indexedDB/IDBFactory.h +++ b/dom/indexedDB/IDBFactory.h @@ -75,7 +75,7 @@ public: IDBFactory** aFactory); // Called when using IndexedDB from a JS component or a JSM in a different - // process or from a C++ component. + // process. static nsresult Create(ContentParent* aContentParent, IDBFactory** aFactory); diff --git a/dom/indexedDB/IDBRequest.cpp b/dom/indexedDB/IDBRequest.cpp index dff6ce7218b0..d27b0559afad 100644 --- a/dom/indexedDB/IDBRequest.cpp +++ b/dom/indexedDB/IDBRequest.cpp @@ -327,7 +327,7 @@ IDBRequest::WrapObject(JSContext* aCx) } JS::Value -IDBRequest::GetResult(mozilla::ErrorResult& aRv) const +IDBRequest::GetResult(JSContext* aCx, mozilla::ErrorResult& aRv) const { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); diff --git a/dom/indexedDB/IDBRequest.h b/dom/indexedDB/IDBRequest.h index 34504db644b3..e0ca44837000 100644 --- a/dom/indexedDB/IDBRequest.h +++ b/dom/indexedDB/IDBRequest.h @@ -132,13 +132,7 @@ public: } JS::Value - GetResult(ErrorResult& aRv) const; - - JS::Value - GetResult(JSContext* aCx, ErrorResult& aRv) const - { - return GetResult(aRv); - } + GetResult(JSContext* aCx, ErrorResult& aRv) const; IDBTransaction* GetTransaction() const diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 41c12fb3093f..3fe4a97ab31b 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -142,7 +142,6 @@ #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" @@ -769,24 +768,6 @@ 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 67c1468b3550..556cbb181773 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -157,10 +157,6 @@ 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 6f9343d89142..1013f636835b 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -33,7 +33,6 @@ #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" @@ -1505,7 +1504,6 @@ ContentParent::InitializeMembers() mNumDestroyingTabs = 0; mIsAlive = true; mSendPermissionUpdates = false; - mSendDataStoreInfos = false; mCalledClose = false; mCalledCloseWithError = false; mCalledKillHard = false; @@ -2087,26 +2085,6 @@ 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 47d03b0c9f1d..86a3303b3414 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -162,14 +162,10 @@ public: int32_t Pid(); - bool NeedsPermissionsUpdate() const { + bool NeedsPermissionsUpdate() { return mSendPermissionUpdates; } - bool NeedsDataStoreInfos() const { - return mSendDataStoreInfos; - } - BlobParent* GetOrCreateActorForBlob(nsIDOMBlob* aBlob); /** @@ -536,11 +532,6 @@ 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; @@ -615,7 +606,6 @@ private: bool mIsAlive; bool mSendPermissionUpdates; - bool mSendDataStoreInfos; bool mIsForBrowser; bool mIsNuwaProcess; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 6d7c44604318..c588a0483db1 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -262,14 +262,6 @@ struct PrefSetting { MaybePrefValue userValue; }; -struct DataStoreSetting { - nsString name; - nsString originURL; - nsString manifestURL; - bool readOnly; - bool enabled; -}; - intr protocol PContent { parent opens PCompositor; @@ -346,9 +338,6 @@ child: async SpeakerManagerNotify(); - async DataStoreNotify(uint32_t aAppId, nsString aName, - nsString aManifestURL); - /** * Dump this process's GC and CC logs to the provided files. * @@ -561,9 +550,6 @@ 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, diff --git a/dom/webidl/DataStore.webidl b/dom/webidl/DataStore.webidl index 9694371833be..dca5f69a7554 100644 --- a/dom/webidl/DataStore.webidl +++ b/dom/webidl/DataStore.webidl @@ -108,10 +108,3 @@ dictionary DataStoreTask { DataStoreKey? id; any data; }; - -// For internal use. -dictionary DataStoreRevisionData { - DOMString revisionId = ""; - unsigned long objectId = 0; - DOMString operation = ""; -}; diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 8b1dc98c2390..40630b72bdff 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -230,8 +230,6 @@ static void Shutdown(); #include "AudioChannelService.h" -#include "mozilla/dom/DataStoreService.h" - #include "mozilla/dom/power/PowerManagerService.h" #include "mozilla/dom/alarm/AlarmHalService.h" #include "mozilla/dom/time/TimeService.h" @@ -591,15 +589,10 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(Geolocation, Init) #define NS_AUDIOCHANNEL_SERVICE_CID \ { 0xf712e983, 0x048a, 0x443f, { 0x88, 0x02, 0xfc, 0xc3, 0xd9, 0x27, 0xce, 0xac }} -#define NS_DATASTORE_SERVICE_CID \ - { 0x0d4285fe, 0xf1b3, 0x49fa, { 0xbc, 0x51, 0xa4, 0xa8, 0x3f, 0x0a, 0xaf, 0x85 }} - NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsGeolocationService, nsGeolocationService::GetGeolocationService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AudioChannelService, AudioChannelService::GetAudioChannelService) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(DataStoreService, DataStoreService::GetOrCreate) - #ifdef MOZ_WEBSPEECH NS_GENERIC_FACTORY_CONSTRUCTOR(FakeSpeechRecognitionService) #endif @@ -749,7 +742,6 @@ NS_DEFINE_NAMED_CID(NS_TEXTSERVICESDOCUMENT_CID); NS_DEFINE_NAMED_CID(NS_GEOLOCATION_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_GEOLOCATION_CID); NS_DEFINE_NAMED_CID(NS_AUDIOCHANNEL_SERVICE_CID); -NS_DEFINE_NAMED_CID(NS_DATASTORE_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_FOCUSMANAGER_CID); NS_DEFINE_NAMED_CID(CSPSERVICE_CID); NS_DEFINE_NAMED_CID(NS_CSPCONTEXT_CID); @@ -1038,7 +1030,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { { &kNS_GEOLOCATION_SERVICE_CID, false, nullptr, nsGeolocationServiceConstructor }, { &kNS_GEOLOCATION_CID, false, nullptr, GeolocationConstructor }, { &kNS_AUDIOCHANNEL_SERVICE_CID, false, nullptr, AudioChannelServiceConstructor }, - { &kNS_DATASTORE_SERVICE_CID, false, nullptr, DataStoreServiceConstructor }, { &kNS_FOCUSMANAGER_CID, false, nullptr, CreateFocusManager }, #ifdef MOZ_WEBSPEECH { &kNS_FAKE_SPEECH_RECOGNITION_SERVICE_CID, false, nullptr, FakeSpeechRecognitionServiceConstructor }, @@ -1194,7 +1185,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { "@mozilla.org/geolocation/service;1", &kNS_GEOLOCATION_SERVICE_CID }, { "@mozilla.org/geolocation;1", &kNS_GEOLOCATION_CID }, { "@mozilla.org/audiochannel/service;1", &kNS_AUDIOCHANNEL_SERVICE_CID }, - { "@mozilla.org/datastore-service;1", &kNS_DATASTORE_SERVICE_CID }, { "@mozilla.org/focus-manager;1", &kNS_FOCUSMANAGER_CID }, #ifdef MOZ_WEBSPEECH { NS_SPEECH_RECOGNITION_SERVICE_CONTRACTID_PREFIX "fake", &kNS_FAKE_SPEECH_RECOGNITION_SERVICE_CID }, diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index e1b5e7f53ce6..892c92278555 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -65,7 +65,6 @@ #include "ActiveLayerTracker.h" #include "AudioChannelService.h" -#include "mozilla/dom/DataStoreService.h" #ifdef MOZ_XUL #include "nsXULPopupManager.h" @@ -412,8 +411,6 @@ nsLayoutStatics::Shutdown() AudioChannelService::Shutdown(); - DataStoreService::Shutdown(); - ContentParent::ShutDown(); nsRefreshDriver::Shutdown(); diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in index fd1e4e010c3a..da3eac84192a 100644 --- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -624,5 +624,5 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@ #endif @BINPATH@/components/DataStore.manifest -@BINPATH@/components/DataStoreImpl.js +@BINPATH@/components/DataStoreService.js @BINPATH@/components/dom_datastore.xpt