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:
Gene Lian 2014-02-24 21:57:15 +08:00
Родитель 64b55aecf9
Коммит 1268aa20e8
14 изменённых файлов: 1333 добавлений и 18 удалений

Просмотреть файл

@ -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;

712
dom/workers/DataStore.cpp Normal file
Просмотреть файл

@ -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

102
dom/workers/DataStore.h Normal file
Просмотреть файл

@ -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',