зеркало из https://github.com/mozilla/gecko-dev.git
Bug 949325 - C++ wrapper to support DataStore API on the worker (part 2-3, dispatch tasks on the worker to the main thread). r=baku,khuey f=nsm
This commit is contained in:
Родитель
64b55aecf9
Коммит
1268aa20e8
|
@ -1410,10 +1410,12 @@ Navigator::GetBattery(ErrorResult& aRv)
|
|||
return mBatteryManager;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Navigator::GetDataStores(const nsAString& aName, ErrorResult& aRv)
|
||||
/* static */ already_AddRefed<Promise>
|
||||
Navigator::GetDataStores(nsPIDOMWindow* aWindow,
|
||||
const nsAString& aName,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (!mWindow || !mWindow->GetDocShell()) {
|
||||
if (!aWindow || !aWindow->GetDocShell()) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1426,12 +1428,18 @@ Navigator::GetDataStores(const nsAString& aName, ErrorResult& aRv)
|
|||
}
|
||||
|
||||
nsCOMPtr<nsISupports> promise;
|
||||
aRv = service->GetDataStores(mWindow, aName, getter_AddRefs(promise));
|
||||
aRv = service->GetDataStores(aWindow, aName, getter_AddRefs(promise));
|
||||
|
||||
nsRefPtr<Promise> p = static_cast<Promise*>(promise.get());
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Navigator::GetDataStores(const nsAString& aName, ErrorResult& aRv)
|
||||
{
|
||||
return GetDataStores(mWindow, aName, aRv);
|
||||
}
|
||||
|
||||
PowerManager*
|
||||
Navigator::GetMozPower(ErrorResult& aRv)
|
||||
{
|
||||
|
|
|
@ -156,6 +156,11 @@ public:
|
|||
// The XPCOM GetDoNotTrack is ok
|
||||
Geolocation* GetGeolocation(ErrorResult& aRv);
|
||||
battery::BatteryManager* GetBattery(ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Promise> GetDataStores(nsPIDOMWindow* aWindow,
|
||||
const nsAString& aName,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> GetDataStores(const nsAString &aName,
|
||||
ErrorResult& aRv);
|
||||
bool Vibrate(uint32_t aDuration);
|
||||
|
|
|
@ -288,9 +288,24 @@ DOMInterfaces = {
|
|||
'nativeType': 'nsDOMDataChannel',
|
||||
},
|
||||
|
||||
'DataStoreCursor': {
|
||||
'DataStore': [{
|
||||
'workers': False
|
||||
}, {
|
||||
'workers': True,
|
||||
'nativeType': 'mozilla::dom::workers::WorkerDataStore',
|
||||
'implicitJSContext': ['name', 'owner', 'readOnly', 'get', 'remove',
|
||||
'clear', 'revisionId', 'getLength', 'sync']
|
||||
}],
|
||||
|
||||
'DataStoreCursor': [{
|
||||
'workers': False,
|
||||
'wrapperCache': False
|
||||
}, {
|
||||
'workers': True,
|
||||
'nativeType': 'mozilla::dom::workers::WorkerDataStoreCursor',
|
||||
'wrapperCache': False,
|
||||
},
|
||||
'implicitJSContext': ['store', 'next', 'close']
|
||||
}],
|
||||
|
||||
'DedicatedWorkerGlobalScope': {
|
||||
'headerFile': 'mozilla/dom/WorkerScope.h',
|
||||
|
@ -1545,6 +1560,7 @@ DOMInterfaces = {
|
|||
'WorkerNavigator': {
|
||||
'headerFile': 'mozilla/dom/workers/bindings/Navigator.h',
|
||||
'workers': True,
|
||||
'implicitJSContext': ['getDataStores'],
|
||||
},
|
||||
|
||||
'XMLHttpRequest': [
|
||||
|
|
|
@ -82,9 +82,6 @@ public:
|
|||
// target of DataStore, so that it can know where to fire the events.
|
||||
void SetDataStoreImpl(DataStoreImpl& aStore, ErrorResult& aRv);
|
||||
|
||||
protected:
|
||||
virtual ~DataStore() {}
|
||||
|
||||
private:
|
||||
nsRefPtr<DataStoreImpl> mStore;
|
||||
};
|
||||
|
|
|
@ -13,8 +13,12 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(DataStoreCursor, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(DataStoreCursor, Release)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(DataStoreCursor)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(DataStoreCursor)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DataStoreCursor)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(DataStoreCursor, mCursor)
|
||||
|
||||
|
|
|
@ -22,11 +22,11 @@ class DataStore;
|
|||
class GlobalObject;
|
||||
class DataStoreCursorImpl;
|
||||
|
||||
class DataStoreCursor MOZ_FINAL
|
||||
class DataStoreCursor MOZ_FINAL : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(DataStoreCursor)
|
||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(DataStoreCursor)
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(DataStoreCursor)
|
||||
|
||||
// WebIDL (internal functions)
|
||||
|
||||
|
@ -48,9 +48,6 @@ public:
|
|||
// API's logic in JS.
|
||||
void SetDataStoreCursorImpl(DataStoreCursorImpl& aCursor);
|
||||
|
||||
protected:
|
||||
virtual ~DataStoreCursor() {}
|
||||
|
||||
private:
|
||||
nsRefPtr<DataStoreCursorImpl> mCursor;
|
||||
};
|
||||
|
|
|
@ -7,3 +7,4 @@ interface WorkerNavigator {
|
|||
|
||||
WorkerNavigator implements NavigatorID;
|
||||
WorkerNavigator implements NavigatorOnLine;
|
||||
WorkerNavigator implements NavigatorDataStore;
|
||||
|
|
|
@ -0,0 +1,712 @@
|
|||
/* 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 "DataStore.h"
|
||||
#include "DataStoreCursor.h"
|
||||
|
||||
#include "mozilla/dom/DataStore.h"
|
||||
#include "mozilla/dom/DataStoreCursor.h"
|
||||
#include "mozilla/dom/DataStoreBinding.h"
|
||||
#include "mozilla/dom/DataStoreImplBinding.h"
|
||||
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseWorkerProxy.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
#include "WorkerScope.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(WorkerDataStore, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(WorkerDataStore, DOMEventTargetHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(WorkerDataStore)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
WorkerDataStore::WorkerDataStore(WorkerGlobalScope* aScope)
|
||||
: DOMEventTargetHelper(aScope)
|
||||
{}
|
||||
|
||||
already_AddRefed<WorkerDataStore>
|
||||
WorkerDataStore::Constructor(GlobalObject& aGlobal, ErrorResult& aRv)
|
||||
{
|
||||
JSContext* cx = aGlobal.GetContext();
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<WorkerDataStore> store =
|
||||
new WorkerDataStore(workerPrivate->GlobalScope());
|
||||
return store.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
WorkerDataStore::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return DataStoreBinding_workers::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
// A WorkerMainThreadRunnable which holds a reference to WorkerDataStore.
|
||||
class DataStoreRunnable : public WorkerMainThreadRunnable
|
||||
{
|
||||
protected:
|
||||
nsMainThreadPtrHandle<DataStore> mBackingStore;
|
||||
|
||||
public:
|
||||
DataStoreRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStore>& aBackingStore)
|
||||
: WorkerMainThreadRunnable(aWorkerPrivate)
|
||||
, mBackingStore(aBackingStore)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
};
|
||||
|
||||
// A DataStoreRunnable to run:
|
||||
// - DataStore::GetName(...)
|
||||
// - DataStore::GetOwner(...)
|
||||
// - DataStore::GetRevisionId(...)
|
||||
// on the main thread.
|
||||
class DataStoreGetStringRunnable MOZ_FINAL : public DataStoreRunnable
|
||||
{
|
||||
typedef void
|
||||
(DataStore::*FuncType)(nsAString&, ErrorResult&);
|
||||
|
||||
FuncType mFunc;
|
||||
nsAString& mString;
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
DataStoreGetStringRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStore>& aBackingStore,
|
||||
FuncType aFunc,
|
||||
nsAString& aString,
|
||||
ErrorResult& aRv)
|
||||
: DataStoreRunnable(aWorkerPrivate, aBackingStore)
|
||||
, mFunc(aFunc)
|
||||
, mString(aString)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsString string;
|
||||
(mBackingStore.get()->*mFunc)(string, mRv);
|
||||
mString.Assign(string);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// A DataStoreRunnable to run DataStore::GetReadOnly(...) on the main
|
||||
// thread.
|
||||
class DataStoreGetReadOnlyRunnable MOZ_FINAL : public DataStoreRunnable
|
||||
{
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
bool mReadOnly;
|
||||
|
||||
public:
|
||||
DataStoreGetReadOnlyRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStore>& aBackingStore,
|
||||
ErrorResult& aRv)
|
||||
: DataStoreRunnable(aWorkerPrivate, aBackingStore)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
mReadOnly = mBackingStore->GetReadOnly(mRv);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// A DataStoreRunnable to run DataStore::Get(...) on the main thread.
|
||||
class DataStoreGetRunnable MOZ_FINAL : public DataStoreRunnable
|
||||
{
|
||||
nsRefPtr<PromiseWorkerProxy> mPromiseWorkerProxy;
|
||||
Sequence<OwningStringOrUnsignedLong> mId;
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
DataStoreGetRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStore>& aBackingStore,
|
||||
Promise* aWorkerPromise,
|
||||
const Sequence<OwningStringOrUnsignedLong>& aId,
|
||||
ErrorResult& aRv)
|
||||
: DataStoreRunnable(aWorkerPrivate, aBackingStore)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
if (!mId.AppendElements(aId)) {
|
||||
mRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
mPromiseWorkerProxy =
|
||||
new PromiseWorkerProxy(aWorkerPrivate, aWorkerPromise);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsRefPtr<Promise> promise = mBackingStore->Get(mId, mRv);
|
||||
promise->AppendNativeHandler(mPromiseWorkerProxy);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// A DataStoreRunnable to run DataStore::Put(...) on the main thread.
|
||||
class DataStorePutRunnable MOZ_FINAL : public DataStoreRunnable
|
||||
{
|
||||
nsRefPtr<PromiseWorkerProxy> mPromiseWorkerProxy;
|
||||
JSAutoStructuredCloneBuffer mObjBuffer;
|
||||
const StringOrUnsignedLong& mId;
|
||||
const nsString mRevisionId;
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
DataStorePutRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStore>& aBackingStore,
|
||||
Promise* aWorkerPromise,
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aObj,
|
||||
const StringOrUnsignedLong& aId,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv)
|
||||
: DataStoreRunnable(aWorkerPrivate, aBackingStore)
|
||||
, mId(aId)
|
||||
, mRevisionId(aRevisionId)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
// This needs to be structured cloned while it's still on the worker thread.
|
||||
if (!mObjBuffer.write(aCx, aObj)) {
|
||||
JS_ClearPendingException(aCx);
|
||||
mRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
}
|
||||
|
||||
mPromiseWorkerProxy =
|
||||
new PromiseWorkerProxy(aWorkerPrivate, aWorkerPromise);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// Get the JSContext for the target window
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo =
|
||||
do_QueryInterface(static_cast<DOMEventTargetHelper*>
|
||||
(mBackingStore.get())->GetOwner());
|
||||
MOZ_ASSERT(sgo);
|
||||
|
||||
nsCOMPtr<nsIScriptContext> scriptContext = sgo->GetContext();
|
||||
AutoPushJSContext cx(scriptContext ? scriptContext->GetNativeContext()
|
||||
: nsContentUtils::GetSafeJSContext());
|
||||
MOZ_ASSERT(cx);
|
||||
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
if (!mObjBuffer.read(cx, &value)) {
|
||||
JS_ClearPendingException(cx);
|
||||
mRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = mBackingStore->Put(cx,
|
||||
value,
|
||||
mId,
|
||||
mRevisionId,
|
||||
mRv);
|
||||
promise->AppendNativeHandler(mPromiseWorkerProxy);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// A DataStoreRunnable to run DataStore::Add(...) on the main thread.
|
||||
class DataStoreAddRunnable MOZ_FINAL : public DataStoreRunnable
|
||||
{
|
||||
nsRefPtr<PromiseWorkerProxy> mPromiseWorkerProxy;
|
||||
JSAutoStructuredCloneBuffer mObjBuffer;
|
||||
const Optional<StringOrUnsignedLong>& mId;
|
||||
const nsString mRevisionId;
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
DataStoreAddRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStore>& aBackingStore,
|
||||
Promise* aWorkerPromise,
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aObj,
|
||||
const Optional<StringOrUnsignedLong>& aId,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv)
|
||||
: DataStoreRunnable(aWorkerPrivate, aBackingStore)
|
||||
, mId(aId)
|
||||
, mRevisionId(aRevisionId)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
// This needs to be structured cloned while it's still on the worker thread.
|
||||
if (!mObjBuffer.write(aCx, aObj)) {
|
||||
JS_ClearPendingException(aCx);
|
||||
mRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
}
|
||||
|
||||
mPromiseWorkerProxy =
|
||||
new PromiseWorkerProxy(aWorkerPrivate, aWorkerPromise);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// Get the JSContext for the target window
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo =
|
||||
do_QueryInterface(static_cast<DOMEventTargetHelper*>
|
||||
(mBackingStore.get())->GetOwner());
|
||||
MOZ_ASSERT(sgo);
|
||||
|
||||
nsCOMPtr<nsIScriptContext> scriptContext = sgo->GetContext();
|
||||
AutoPushJSContext cx(scriptContext ? scriptContext->GetNativeContext()
|
||||
: nsContentUtils::GetSafeJSContext());
|
||||
MOZ_ASSERT(cx);
|
||||
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
if (!mObjBuffer.read(cx, &value)) {
|
||||
JS_ClearPendingException(cx);
|
||||
mRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = mBackingStore->Add(cx,
|
||||
value,
|
||||
mId,
|
||||
mRevisionId,
|
||||
mRv);
|
||||
promise->AppendNativeHandler(mPromiseWorkerProxy);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// A DataStoreRunnable to run DataStore::Remove(...) on the main
|
||||
// thread.
|
||||
class DataStoreRemoveRunnable MOZ_FINAL : public DataStoreRunnable
|
||||
{
|
||||
nsRefPtr<PromiseWorkerProxy> mPromiseWorkerProxy;
|
||||
const StringOrUnsignedLong& mId;
|
||||
const nsString mRevisionId;
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
DataStoreRemoveRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStore>& aBackingStore,
|
||||
Promise* aWorkerPromise,
|
||||
const StringOrUnsignedLong& aId,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv)
|
||||
: DataStoreRunnable(aWorkerPrivate, aBackingStore)
|
||||
, mId(aId)
|
||||
, mRevisionId(aRevisionId)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
mPromiseWorkerProxy =
|
||||
new PromiseWorkerProxy(aWorkerPrivate, aWorkerPromise);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsRefPtr<Promise> promise = mBackingStore->Remove(mId, mRevisionId, mRv);
|
||||
promise->AppendNativeHandler(mPromiseWorkerProxy);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// A DataStoreRunnable to run DataStore::Sync(...) on the main thread.
|
||||
class DataStoreSyncStoreRunnable MOZ_FINAL : public DataStoreRunnable
|
||||
{
|
||||
WorkerDataStoreCursor* mWorkerCursor;
|
||||
const nsString mRevisionId;
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
DataStoreSyncStoreRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStore>& aBackingStore,
|
||||
WorkerDataStoreCursor* aWorkerCursor,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv)
|
||||
: DataStoreRunnable(aWorkerPrivate, aBackingStore)
|
||||
, mWorkerCursor(aWorkerCursor)
|
||||
, mRevisionId(aRevisionId)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// Point WorkerDataStoreCursor to DataStoreCursor.
|
||||
nsRefPtr<DataStoreCursor> cursor = mBackingStore->Sync(mRevisionId, mRv);
|
||||
nsMainThreadPtrHandle<DataStoreCursor> backingCursor =
|
||||
new nsMainThreadPtrHolder<DataStoreCursor>(cursor);
|
||||
mWorkerCursor->SetBackingDataStoreCursor(backingCursor);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
WorkerDataStore::GetName(JSContext* aCx, nsAString& aName, ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<DataStoreGetStringRunnable> runnable =
|
||||
new DataStoreGetStringRunnable(workerPrivate,
|
||||
mBackingStore,
|
||||
&DataStore::GetName,
|
||||
aName,
|
||||
aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDataStore::GetOwner(JSContext* aCx, nsAString& aOwner, ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<DataStoreGetStringRunnable> runnable =
|
||||
new DataStoreGetStringRunnable(workerPrivate,
|
||||
mBackingStore,
|
||||
&DataStore::GetOwner,
|
||||
aOwner,
|
||||
aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerDataStore::GetReadOnly(JSContext* aCx, ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<DataStoreGetReadOnlyRunnable> runnable =
|
||||
new DataStoreGetReadOnlyRunnable(workerPrivate, mBackingStore, aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
|
||||
return runnable->mReadOnly;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
WorkerDataStore::Get(JSContext* aCx,
|
||||
const Sequence<OwningStringOrUnsignedLong>& aId,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
|
||||
|
||||
nsRefPtr<DataStoreGetRunnable> runnable =
|
||||
new DataStoreGetRunnable(workerPrivate,
|
||||
mBackingStore,
|
||||
promise,
|
||||
aId,
|
||||
aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
WorkerDataStore::Put(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aObj,
|
||||
const StringOrUnsignedLong& aId,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
|
||||
|
||||
nsRefPtr<DataStorePutRunnable> runnable =
|
||||
new DataStorePutRunnable(workerPrivate,
|
||||
mBackingStore,
|
||||
promise,
|
||||
aCx,
|
||||
aObj,
|
||||
aId,
|
||||
aRevisionId,
|
||||
aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
WorkerDataStore::Add(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aObj,
|
||||
const Optional<StringOrUnsignedLong>& aId,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
|
||||
|
||||
nsRefPtr<DataStoreAddRunnable> runnable =
|
||||
new DataStoreAddRunnable(workerPrivate,
|
||||
mBackingStore,
|
||||
promise,
|
||||
aCx,
|
||||
aObj,
|
||||
aId,
|
||||
aRevisionId,
|
||||
aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
WorkerDataStore::Remove(JSContext* aCx,
|
||||
const StringOrUnsignedLong& aId,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
|
||||
|
||||
nsRefPtr<DataStoreRemoveRunnable> runnable =
|
||||
new DataStoreRemoveRunnable(workerPrivate,
|
||||
mBackingStore,
|
||||
promise,
|
||||
aId,
|
||||
aRevisionId,
|
||||
aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// A DataStoreRunnable to run DataStore::Clear(...) on the main thread.
|
||||
class DataStoreClearRunnable MOZ_FINAL : public DataStoreRunnable
|
||||
{
|
||||
nsRefPtr<PromiseWorkerProxy> mPromiseWorkerProxy;
|
||||
const nsString mRevisionId;
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
DataStoreClearRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStore>& aBackingStore,
|
||||
Promise* aWorkerPromise,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv)
|
||||
: DataStoreRunnable(aWorkerPrivate, aBackingStore)
|
||||
, mRevisionId(aRevisionId)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
mPromiseWorkerProxy =
|
||||
new PromiseWorkerProxy(aWorkerPrivate, aWorkerPromise);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsRefPtr<Promise> promise = mBackingStore->Clear(mRevisionId, mRv);
|
||||
promise->AppendNativeHandler(mPromiseWorkerProxy);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
already_AddRefed<Promise>
|
||||
WorkerDataStore::Clear(JSContext* aCx,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
|
||||
|
||||
nsRefPtr<DataStoreClearRunnable> runnable =
|
||||
new DataStoreClearRunnable(workerPrivate,
|
||||
mBackingStore,
|
||||
promise,
|
||||
aRevisionId,
|
||||
aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDataStore::GetRevisionId(JSContext* aCx,
|
||||
nsAString& aRevisionId,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<DataStoreGetStringRunnable> runnable =
|
||||
new DataStoreGetStringRunnable(workerPrivate,
|
||||
mBackingStore,
|
||||
&DataStore::GetRevisionId,
|
||||
aRevisionId,
|
||||
aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
}
|
||||
|
||||
// A DataStoreRunnable to run DataStore::GetLength(...) on the main thread.
|
||||
class DataStoreGetLengthRunnable MOZ_FINAL : public DataStoreRunnable
|
||||
{
|
||||
nsRefPtr<PromiseWorkerProxy> mPromiseWorkerProxy;
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
DataStoreGetLengthRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStore>& aBackingStore,
|
||||
Promise* aWorkerPromise,
|
||||
ErrorResult& aRv)
|
||||
: DataStoreRunnable(aWorkerPrivate, aBackingStore)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
mPromiseWorkerProxy =
|
||||
new PromiseWorkerProxy(aWorkerPrivate, aWorkerPromise);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsRefPtr<Promise> promise = mBackingStore->GetLength(mRv);
|
||||
promise->AppendNativeHandler(mPromiseWorkerProxy);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
already_AddRefed<Promise>
|
||||
WorkerDataStore::GetLength(JSContext* aCx, ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
|
||||
|
||||
nsRefPtr<DataStoreGetLengthRunnable> runnable =
|
||||
new DataStoreGetLengthRunnable(workerPrivate,
|
||||
mBackingStore,
|
||||
promise,
|
||||
aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<WorkerDataStoreCursor>
|
||||
WorkerDataStore::Sync(JSContext* aCx,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// Create a WorkerDataStoreCursor on the worker. DataStoreSyncStoreRunnable
|
||||
// will point that to the DataStoreCursor created on the main thread.
|
||||
nsRefPtr<WorkerDataStoreCursor> workerCursor = new WorkerDataStoreCursor();
|
||||
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<DataStoreSyncStoreRunnable> runnable =
|
||||
new DataStoreSyncStoreRunnable(workerPrivate,
|
||||
mBackingStore,
|
||||
workerCursor,
|
||||
aRevisionId,
|
||||
aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
|
||||
return workerCursor.forget();
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDataStore::SetDataStoreImpl(DataStoreImpl& aStore, ErrorResult& aRv)
|
||||
{
|
||||
NS_NOTREACHED("We don't use this for the WorkerDataStore!");
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDataStore::SetBackingDataStore(
|
||||
const nsMainThreadPtrHandle<DataStore>& aBackingStore)
|
||||
{
|
||||
mBackingStore = aBackingStore;
|
||||
}
|
||||
|
||||
// TODO How to handle the event? Will fix this in my later patch.
|
||||
|
||||
END_WORKERS_NAMESPACE
|
|
@ -0,0 +1,102 @@
|
|||
/* 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_workers_DataStore_h
|
||||
#define mozilla_dom_workers_DataStore_h
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class Promise;
|
||||
class DataStore;
|
||||
class DataStoreImpl;
|
||||
class StringOrUnsignedLong;
|
||||
class OwningStringOrUnsignedLong;
|
||||
|
||||
namespace workers {
|
||||
|
||||
class WorkerDataStoreCursor;
|
||||
class WorkerGlobalScope;
|
||||
|
||||
class WorkerDataStore MOZ_FINAL : public DOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
WorkerDataStore(WorkerGlobalScope* aScope);
|
||||
|
||||
// WebIDL (internal functions)
|
||||
|
||||
static already_AddRefed<WorkerDataStore> Constructor(GlobalObject& aGlobal,
|
||||
ErrorResult& aRv);
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *aCx) MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL (public APIs)
|
||||
|
||||
void GetName(JSContext* aCx, nsAString& aName, ErrorResult& aRv);
|
||||
|
||||
void GetOwner(JSContext* aCx, nsAString& aOwner, ErrorResult& aRv);
|
||||
|
||||
bool GetReadOnly(JSContext* aCx, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> Get(JSContext* aCx,
|
||||
const Sequence<OwningStringOrUnsignedLong>& aId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> Put(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aObj,
|
||||
const StringOrUnsignedLong& aId,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> Add(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aObj,
|
||||
const Optional<StringOrUnsignedLong>& aId,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> Remove(JSContext* aCx,
|
||||
const StringOrUnsignedLong& aId,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> Clear(JSContext* aCx,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void GetRevisionId(JSContext* aCx, nsAString& aRevisionId, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> GetLength(JSContext* aCx, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<WorkerDataStoreCursor> Sync(JSContext* aCx,
|
||||
const nsAString& aRevisionId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
IMPL_EVENT_HANDLER(change)
|
||||
|
||||
// We don't use this for the WorkerDataStore.
|
||||
void SetDataStoreImpl(DataStoreImpl& aStore, ErrorResult& aRv);
|
||||
|
||||
void SetBackingDataStore(
|
||||
const nsMainThreadPtrHandle<DataStore>& aBackingStore);
|
||||
|
||||
protected:
|
||||
virtual ~WorkerDataStore() {}
|
||||
|
||||
private:
|
||||
nsMainThreadPtrHandle<DataStore> mBackingStore;
|
||||
};
|
||||
|
||||
} //namespace workers
|
||||
} //namespace dom
|
||||
} //namespace mozilla
|
||||
|
||||
#endif
|
|
@ -0,0 +1,218 @@
|
|||
/* 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 "DataStore.h"
|
||||
#include "DataStoreCursor.h"
|
||||
|
||||
#include "mozilla/dom/DataStore.h"
|
||||
#include "mozilla/dom/DataStoreCursor.h"
|
||||
#include "mozilla/dom/DataStoreBinding.h"
|
||||
#include "mozilla/dom/DataStoreImplBinding.h"
|
||||
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseWorkerProxy.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
#include "WorkerScope.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
already_AddRefed<WorkerDataStoreCursor>
|
||||
WorkerDataStoreCursor::Constructor(GlobalObject& aGlobal, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
nsRefPtr<WorkerDataStoreCursor> workerCursor = new WorkerDataStoreCursor();
|
||||
return workerCursor.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
WorkerDataStoreCursor::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return DataStoreCursorBinding_workers::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
// A WorkerMainThreadRunnable which holds a reference to DataStoreCursor.
|
||||
class DataStoreCursorRunnable : public WorkerMainThreadRunnable
|
||||
{
|
||||
protected:
|
||||
nsMainThreadPtrHandle<DataStoreCursor> mBackingCursor;
|
||||
|
||||
public:
|
||||
DataStoreCursorRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStoreCursor>& aBackingCursor)
|
||||
: WorkerMainThreadRunnable(aWorkerPrivate)
|
||||
, mBackingCursor(aBackingCursor)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
};
|
||||
|
||||
// A DataStoreCursorRunnable to run DataStoreCursor::GetStore(...) on the main
|
||||
// thread.
|
||||
class DataStoreCursorGetStoreRunnable MOZ_FINAL : public DataStoreCursorRunnable
|
||||
{
|
||||
WorkerDataStore* mWorkerStore;
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
DataStoreCursorGetStoreRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStoreCursor>& aBackingCursor,
|
||||
WorkerDataStore* aWorkerStore,
|
||||
ErrorResult& aRv)
|
||||
: DataStoreCursorRunnable(aWorkerPrivate, aBackingCursor)
|
||||
, mWorkerStore(aWorkerStore)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// Point WorkerDataStore to DataStore.
|
||||
nsRefPtr<DataStore> store = mBackingCursor->GetStore(mRv);
|
||||
nsMainThreadPtrHandle<DataStore> backingStore =
|
||||
new nsMainThreadPtrHolder<DataStore>(store);
|
||||
mWorkerStore->SetBackingDataStore(backingStore);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// A DataStoreCursorRunnable to run DataStoreCursor::Next(...) on the main
|
||||
// thread.
|
||||
class DataStoreCursorNextRunnable MOZ_FINAL : public DataStoreCursorRunnable
|
||||
{
|
||||
nsRefPtr<PromiseWorkerProxy> mPromiseWorkerProxy;
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
DataStoreCursorNextRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStoreCursor>& aBackingCursor,
|
||||
Promise* aWorkerPromise,
|
||||
ErrorResult& aRv)
|
||||
: DataStoreCursorRunnable(aWorkerPrivate, aBackingCursor)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
mPromiseWorkerProxy =
|
||||
new PromiseWorkerProxy(aWorkerPrivate, aWorkerPromise);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsRefPtr<Promise> promise = mBackingCursor->Next(mRv);
|
||||
promise->AppendNativeHandler(mPromiseWorkerProxy);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// A DataStoreCursorRunnable to run DataStoreCursor::Close(...) on the main
|
||||
// thread.
|
||||
class DataStoreCursorCloseRunnable MOZ_FINAL : public DataStoreCursorRunnable
|
||||
{
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
DataStoreCursorCloseRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<DataStoreCursor>& aBackingCursor,
|
||||
ErrorResult& aRv)
|
||||
: DataStoreCursorRunnable(aWorkerPrivate, aBackingCursor)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
mBackingCursor->Close(mRv);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
already_AddRefed<WorkerDataStore>
|
||||
WorkerDataStoreCursor::GetStore(JSContext* aCx, ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
// Create a WorkerDataStore on the worker. DataStoreCursorGetStoreRunnable
|
||||
// will point that to the DataStore created on the main thread.
|
||||
nsRefPtr<WorkerDataStore> workerStore =
|
||||
new WorkerDataStore(workerPrivate->GlobalScope());
|
||||
|
||||
nsRefPtr<DataStoreCursorGetStoreRunnable> runnable =
|
||||
new DataStoreCursorGetStoreRunnable(workerPrivate,
|
||||
mBackingCursor,
|
||||
workerStore,
|
||||
aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
|
||||
return workerStore.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
WorkerDataStoreCursor::Next(JSContext* aCx, ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
|
||||
|
||||
nsRefPtr<DataStoreCursorNextRunnable> runnable =
|
||||
new DataStoreCursorNextRunnable(workerPrivate,
|
||||
mBackingCursor,
|
||||
promise,
|
||||
aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDataStoreCursor::Close(JSContext* aCx, ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<DataStoreCursorCloseRunnable> runnable =
|
||||
new DataStoreCursorCloseRunnable(workerPrivate, mBackingCursor, aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDataStoreCursor::SetDataStoreCursorImpl(DataStoreCursorImpl& aCursor)
|
||||
{
|
||||
NS_NOTREACHED("We don't use this for the WorkerDataStoreCursor!");
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDataStoreCursor::SetBackingDataStoreCursor(
|
||||
const nsMainThreadPtrHandle<DataStoreCursor>& aBackingCursor)
|
||||
{
|
||||
mBackingCursor = aBackingCursor;
|
||||
}
|
||||
|
||||
END_WORKERS_NAMESPACE
|
|
@ -0,0 +1,62 @@
|
|||
/* 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_workers_DataStoreCursor_h
|
||||
#define mozilla_dom_workers_DataStoreCursor_h
|
||||
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class Promise;
|
||||
class GlobalObject;
|
||||
class DataStoreCursor;
|
||||
class DataStoreCursorImpl;
|
||||
|
||||
namespace workers {
|
||||
|
||||
class WorkerDataStore;
|
||||
|
||||
class WorkerDataStoreCursor MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(WorkerDataStoreCursor)
|
||||
|
||||
// WebIDL (internal functions)
|
||||
|
||||
static already_AddRefed<WorkerDataStoreCursor> Constructor(GlobalObject& aGlobal,
|
||||
ErrorResult& aRv);
|
||||
|
||||
JSObject* WrapObject(JSContext *aCx);
|
||||
|
||||
// WebIDL (public APIs)
|
||||
|
||||
already_AddRefed<WorkerDataStore> GetStore(JSContext *aCx, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> Next(JSContext *aCx, ErrorResult& aRv);
|
||||
|
||||
void Close(JSContext *aCx, ErrorResult& aRv);
|
||||
|
||||
// We don't use this for the WorkerDataStore.
|
||||
void SetDataStoreCursorImpl(DataStoreCursorImpl& aCursor);
|
||||
|
||||
void SetBackingDataStoreCursor(
|
||||
const nsMainThreadPtrHandle<DataStoreCursor>& aBackingCursor);
|
||||
|
||||
protected:
|
||||
virtual ~WorkerDataStoreCursor() {}
|
||||
|
||||
private:
|
||||
nsMainThreadPtrHandle<DataStoreCursor> mBackingCursor;
|
||||
};
|
||||
|
||||
} //namespace workers
|
||||
} //namespace dom
|
||||
} //namespace mozilla
|
||||
|
||||
#endif
|
|
@ -3,12 +3,22 @@
|
|||
* 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 "Navigator.h"
|
||||
#include "DataStore.h"
|
||||
|
||||
#include "mozilla/dom/DataStore.h"
|
||||
#include "mozilla/dom/DataStoreBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseWorkerProxy.h"
|
||||
#include "mozilla/dom/WorkerNavigatorBinding.h"
|
||||
|
||||
#include "Navigator.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "RuntimeService.h"
|
||||
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
#include "WorkerScope.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WorkerNavigator)
|
||||
|
@ -39,4 +49,169 @@ WorkerNavigator::WrapObject(JSContext* aCx)
|
|||
return WorkerNavigatorBinding_workers::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
#define WORKER_DATA_STORES_TAG JS_SCTAG_USER_MIN
|
||||
|
||||
static JSObject*
|
||||
GetDataStoresStructuredCloneCallbacksRead(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
uint32_t aData,
|
||||
void* aClosure)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
if (aTag != WORKER_DATA_STORES_TAG) {
|
||||
MOZ_ASSERT(false, "aTag must be WORKER_DATA_STORES_TAG!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!aData, "aData should be empty");
|
||||
|
||||
// Read the holder from the buffer, which points to the data store.
|
||||
nsMainThreadPtrHolder<DataStore>* dataStoreholder;
|
||||
if (!JS_ReadBytes(aReader, &dataStoreholder, sizeof(dataStoreholder))) {
|
||||
MOZ_ASSERT(false, "cannot read bytes for dataStoreholder!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Point WorkerDataStore to DataStore.
|
||||
nsRefPtr<WorkerDataStore> workerStore =
|
||||
new WorkerDataStore(workerPrivate->GlobalScope());
|
||||
nsMainThreadPtrHandle<DataStore> backingStore = dataStoreholder;
|
||||
workerStore->SetBackingDataStore(backingStore);
|
||||
|
||||
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
|
||||
if (!global) {
|
||||
MOZ_ASSERT(false, "cannot get global!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> workerStoreObj(aCx, workerStore->WrapObject(aCx));
|
||||
if (!JS_WrapObject(aCx, &workerStoreObj)) {
|
||||
MOZ_ASSERT(false, "cannot wrap object for workerStoreObj!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return workerStoreObj;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetDataStoresStructuredCloneCallbacksWrite(JSContext* aCx,
|
||||
JSStructuredCloneWriter* aWriter,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
void* aClosure)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
PromiseWorkerProxy* proxy = static_cast<PromiseWorkerProxy*>(aClosure);
|
||||
NS_ASSERTION(proxy, "must have proxy!");
|
||||
|
||||
if (!JS_WriteUint32Pair(aWriter, WORKER_DATA_STORES_TAG, 0)) {
|
||||
MOZ_ASSERT(false, "cannot write pair for WORKER_DATA_STORES_TAG!");
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> storeObj(aCx, aObj);
|
||||
|
||||
DataStore* store = nullptr;
|
||||
nsresult rv = UNWRAP_OBJECT(DataStore, storeObj, store);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_ASSERT(false, "cannot unwrap the DataStore object!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// We keep the data store alive here.
|
||||
proxy->StoreISupports(store);
|
||||
|
||||
// Construct the nsMainThreadPtrHolder pointing to the data store.
|
||||
nsMainThreadPtrHolder<DataStore>* dataStoreholder =
|
||||
new nsMainThreadPtrHolder<DataStore>(store);
|
||||
|
||||
// And write the dataStoreholder into the buffer.
|
||||
if (!JS_WriteBytes(aWriter, &dataStoreholder, sizeof(dataStoreholder))) {
|
||||
MOZ_ASSERT(false, "cannot write bytes for dataStoreholder!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSStructuredCloneCallbacks kGetDataStoresStructuredCloneCallbacks = {
|
||||
GetDataStoresStructuredCloneCallbacksRead,
|
||||
GetDataStoresStructuredCloneCallbacksWrite,
|
||||
nullptr
|
||||
};
|
||||
|
||||
// A WorkerMainThreadRunnable to run WorkerNavigator::GetDataStores(...) on the
|
||||
// main thread.
|
||||
class NavigatorGetDataStoresRunnable MOZ_FINAL : public WorkerMainThreadRunnable
|
||||
{
|
||||
nsRefPtr<PromiseWorkerProxy> mPromiseWorkerProxy;
|
||||
const nsString mName;
|
||||
ErrorResult& mRv;
|
||||
|
||||
public:
|
||||
NavigatorGetDataStoresRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
Promise* aWorkerPromise,
|
||||
const nsAString& aName,
|
||||
ErrorResult& aRv)
|
||||
: WorkerMainThreadRunnable(aWorkerPrivate)
|
||||
, mName(aName)
|
||||
, mRv(aRv)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
mPromiseWorkerProxy =
|
||||
new PromiseWorkerProxy(aWorkerPrivate,
|
||||
aWorkerPromise,
|
||||
&kGetDataStoresStructuredCloneCallbacks);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
MainThreadRun() MOZ_OVERRIDE
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// Walk up to the containing window.
|
||||
WorkerPrivate* wp = mWorkerPrivate;
|
||||
while (wp->GetParent()) {
|
||||
wp = wp->GetParent();
|
||||
}
|
||||
nsPIDOMWindow* window = wp->GetWindow();
|
||||
|
||||
// TODO SharedWorker has null window. Don't need to worry about at this
|
||||
// point, though.
|
||||
if (!window) {
|
||||
mRv.Throw(NS_ERROR_FAILURE);
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = Navigator::GetDataStores(window, mName, mRv);
|
||||
promise->AppendNativeHandler(mPromiseWorkerProxy);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
already_AddRefed<Promise>
|
||||
WorkerNavigator::GetDataStores(JSContext* aCx,
|
||||
const nsAString& aName,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
workerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsRefPtr<Promise> promise = new Promise(workerPrivate->GlobalScope());
|
||||
|
||||
nsRefPtr<NavigatorGetDataStoresRunnable> runnable =
|
||||
new NavigatorGetDataStoresRunnable(workerPrivate, promise, aName, aRv);
|
||||
runnable->Dispatch(aCx);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
|
|
@ -10,6 +10,16 @@
|
|||
#include "nsString.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
// Need this to use Navigator::HasDataStoreSupport() in
|
||||
// WorkerNavigatorBinding.cpp
|
||||
#include "mozilla/dom/Navigator.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Promise;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class WorkerNavigator MOZ_FINAL : public nsWrapperCache
|
||||
|
@ -97,6 +107,10 @@ public:
|
|||
{
|
||||
mOnline = aOnline;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> GetDataStores(JSContext* aCx,
|
||||
const nsAString& aName,
|
||||
ErrorResult& aRv);
|
||||
};
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
|
|
@ -19,6 +19,8 @@ EXPORTS.mozilla.dom.workers += [
|
|||
|
||||
# Stuff needed for the bindings, not really public though.
|
||||
EXPORTS.mozilla.dom.workers.bindings += [
|
||||
'DataStore.h',
|
||||
'DataStoreCursor.h',
|
||||
'FileReaderSync.h',
|
||||
'Location.h',
|
||||
'MessagePort.h',
|
||||
|
@ -32,6 +34,8 @@ EXPORTS.mozilla.dom.workers.bindings += [
|
|||
|
||||
SOURCES += [
|
||||
'ChromeWorkerScope.cpp',
|
||||
'DataStore.cpp',
|
||||
'DataStoreCursor.cpp',
|
||||
'File.cpp',
|
||||
'FileReaderSync.cpp',
|
||||
'Location.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче