Bug 949325 - C++ wrapper to support DataStore API on the worker (part 2-2, refactor out the common SyncWorkerRunnable from workers/URL.cpp). r=baku,khuey
authorGene Lian <clian@mozilla.com>
Mon, 24 Feb 2014 21:57:03 +0800
changeset 181361 a613090760597ae6319056aa080f9167e4afa97d
parent 181360 b60249fb45ac98f99089b5e0baf709ffbee827f4
child 181362 c5624c2a2d2fbc8565be10e41b2830833a6d07fa
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersbaku, khuey
bugs949325
milestone32.0a1
Bug 949325 - C++ wrapper to support DataStore API on the worker (part 2-2, refactor out the common SyncWorkerRunnable from workers/URL.cpp). r=baku,khuey
dom/workers/URL.cpp
dom/workers/WorkerRunnable.cpp
dom/workers/WorkerRunnable.h
--- a/dom/workers/URL.cpp
+++ b/dom/workers/URL.cpp
@@ -58,158 +58,104 @@ private:
   ~URLProxy()
   {
      MOZ_ASSERT(!mURL);
   }
 
   nsRefPtr<mozilla::dom::URL> mURL;
 };
 
-// Base class for the URL runnable objects.
-class URLRunnable : public nsRunnable
-{
-protected:
-  WorkerPrivate* mWorkerPrivate;
-  nsCOMPtr<nsIEventTarget> mSyncLoopTarget;
-
-protected:
-  URLRunnable(WorkerPrivate* aWorkerPrivate)
-  : mWorkerPrivate(aWorkerPrivate)
-  {
-    mWorkerPrivate->AssertIsOnWorkerThread();
-  }
-
-public:
-  bool
-  Dispatch(JSContext* aCx)
-  {
-    mWorkerPrivate->AssertIsOnWorkerThread();
-
-    AutoSyncLoopHolder syncLoop(mWorkerPrivate);
-
-    mSyncLoopTarget = syncLoop.EventTarget();
-
-    if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
-      JS_ReportError(aCx, "Failed to dispatch to main thread!");
-      return false;
-    }
-
-    return syncLoop.Run();
-  }
-
-private:
-  NS_IMETHOD Run()
-  {
-    AssertIsOnMainThread();
-
-    MainThreadRun();
-
-    nsRefPtr<MainThreadStopSyncLoopRunnable> response =
-      new MainThreadStopSyncLoopRunnable(mWorkerPrivate,
-                                         mSyncLoopTarget.forget(),
-                                         true);
-    if (!response->Dispatch(nullptr)) {
-      NS_WARNING("Failed to dispatch response!");
-    }
-
-    return NS_OK;
-  }
-
-protected:
-  virtual void
-  MainThreadRun() = 0;
-};
-
 // This class creates an URL from a DOM Blob on the main thread.
-class CreateURLRunnable : public URLRunnable
+class CreateURLRunnable : public WorkerMainThreadRunnable
 {
 private:
   nsIDOMBlob* mBlob;
   nsString& mURL;
 
 public:
   CreateURLRunnable(WorkerPrivate* aWorkerPrivate, nsIDOMBlob* aBlob,
                     const mozilla::dom::objectURLOptions& aOptions,
                     nsString& aURL)
-  : URLRunnable(aWorkerPrivate),
+  : WorkerMainThreadRunnable(aWorkerPrivate),
     mBlob(aBlob),
     mURL(aURL)
   {
     MOZ_ASSERT(aBlob);
   }
 
-  void
+  bool
   MainThreadRun()
   {
     AssertIsOnMainThread();
 
     nsCOMPtr<nsIPrincipal> principal;
     nsIDocument* doc = nullptr;
 
     nsCOMPtr<nsPIDOMWindow> window = mWorkerPrivate->GetWindow();
     if (window) {
       doc = window->GetExtantDoc();
       if (!doc) {
         SetDOMStringToNull(mURL);
-        return;
+        return false;
       }
 
       principal = doc->NodePrincipal();
     } else {
       MOZ_ASSERT_IF(!mWorkerPrivate->GetParent(), mWorkerPrivate->IsChromeWorker());
       principal = mWorkerPrivate->GetPrincipal();
     }
 
     nsCString url;
     nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(
         NS_LITERAL_CSTRING(BLOBURI_SCHEME),
         mBlob, principal, url);
 
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to add data entry for the blob!");
       SetDOMStringToNull(mURL);
-      return;
+      return false;
     }
 
     if (doc) {
       doc->RegisterHostObjectUri(url);
     } else {
       mWorkerPrivate->RegisterHostObjectURI(url);
     }
 
     mURL = NS_ConvertUTF8toUTF16(url);
+    return true;
   }
 };
 
 // This class revokes an URL on the main thread.
-class RevokeURLRunnable : public URLRunnable
+class RevokeURLRunnable : public WorkerMainThreadRunnable
 {
 private:
   const nsString mURL;
 
 public:
   RevokeURLRunnable(WorkerPrivate* aWorkerPrivate,
                     const nsAString& aURL)
-  : URLRunnable(aWorkerPrivate),
+  : WorkerMainThreadRunnable(aWorkerPrivate),
     mURL(aURL)
   {}
 
-  void
+  bool
   MainThreadRun()
   {
     AssertIsOnMainThread();
 
     nsCOMPtr<nsIPrincipal> principal;
     nsIDocument* doc = nullptr;
 
     nsCOMPtr<nsPIDOMWindow> window = mWorkerPrivate->GetWindow();
     if (window) {
       doc = window->GetExtantDoc();
       if (!doc) {
-        return;
+        return false;
       }
 
       principal = doc->NodePrincipal();
     } else {
       MOZ_ASSERT_IF(!mWorkerPrivate->GetParent(), mWorkerPrivate->IsChromeWorker());
       principal = mWorkerPrivate->GetPrincipal();
     }
 
@@ -227,88 +173,91 @@ public:
       }
 
       nsHostObjectProtocolHandler::RemoveDataEntry(url);
     }
 
     if (!window) {
       mWorkerPrivate->UnregisterHostObjectURI(url);
     }
+
+    return true;
   }
 };
 
 // This class creates a URL object on the main thread.
-class ConstructorRunnable : public URLRunnable
+class ConstructorRunnable : public WorkerMainThreadRunnable
 {
 private:
   const nsString mURL;
 
   const nsString mBase;
   nsRefPtr<URLProxy> mBaseProxy;
   mozilla::ErrorResult& mRv;
 
   nsRefPtr<URLProxy> mRetval;
 
 public:
   ConstructorRunnable(WorkerPrivate* aWorkerPrivate,
                       const nsAString& aURL, const nsAString& aBase,
                       mozilla::ErrorResult& aRv)
-  : URLRunnable(aWorkerPrivate)
+  : WorkerMainThreadRunnable(aWorkerPrivate)
   , mURL(aURL)
   , mBase(aBase)
   , mRv(aRv)
   {
     mWorkerPrivate->AssertIsOnWorkerThread();
   }
 
   ConstructorRunnable(WorkerPrivate* aWorkerPrivate,
                       const nsAString& aURL, URLProxy* aBaseProxy,
                       mozilla::ErrorResult& aRv)
-  : URLRunnable(aWorkerPrivate)
+  : WorkerMainThreadRunnable(aWorkerPrivate)
   , mURL(aURL)
   , mBaseProxy(aBaseProxy)
   , mRv(aRv)
   {
     mWorkerPrivate->AssertIsOnWorkerThread();
   }
 
-  void
+  bool
   MainThreadRun()
   {
     AssertIsOnMainThread();
 
     nsresult rv;
     nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
     if (NS_FAILED(rv)) {
       mRv.Throw(rv);
-      return;
+      return true;
     }
 
     nsCOMPtr<nsIURI> baseURL;
 
     if (!mBaseProxy) {
       rv = ioService->NewURI(NS_ConvertUTF16toUTF8(mBase), nullptr, nullptr,
                              getter_AddRefs(baseURL));
       if (NS_FAILED(rv)) {
         mRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
-        return;
+        return true;
       }
     } else {
       baseURL = mBaseProxy->URI();
     }
 
     nsCOMPtr<nsIURI> url;
     rv = ioService->NewURI(NS_ConvertUTF16toUTF8(mURL), nullptr, baseURL,
                            getter_AddRefs(url));
     if (NS_FAILED(rv)) {
       mRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
-      return;
+      return true;
     }
 
     mRetval = new URLProxy(new mozilla::dom::URL(url));
+    return true;
   }
 
   URLProxy*
   GetURLProxy()
   {
     return mRetval;
   }
 };
@@ -331,17 +280,17 @@ public:
     return NS_OK;
   }
 
 private:
   nsRefPtr<URLProxy> mURLProxy;
 };
 
 // This class is the generic getter for any URL property.
-class GetterRunnable : public URLRunnable
+class GetterRunnable : public WorkerMainThreadRunnable
 {
 public:
   enum GetterType {
     GetterHref,
     GetterOrigin,
     GetterProtocol,
     GetterUsername,
     GetterPassword,
@@ -351,25 +300,25 @@ public:
     GetterPathname,
     GetterSearch,
     GetterHash,
   };
 
   GetterRunnable(WorkerPrivate* aWorkerPrivate,
                  GetterType aType, nsString& aValue,
                  URLProxy* aURLProxy)
-  : URLRunnable(aWorkerPrivate)
+  : WorkerMainThreadRunnable(aWorkerPrivate)
   , mValue(aValue)
   , mType(aType)
   , mURLProxy(aURLProxy)
   {
     mWorkerPrivate->AssertIsOnWorkerThread();
   }
 
-  void
+  bool
   MainThreadRun()
   {
     AssertIsOnMainThread();
 
     switch (mType) {
       case GetterHref:
         mURLProxy->URL()->GetHref(mValue);
         break;
@@ -409,26 +358,28 @@ public:
       case GetterSearch:
         mURLProxy->URL()->GetSearch(mValue);
         break;
 
       case GetterHash:
         mURLProxy->URL()->GetHash(mValue);
         break;
     }
+
+    return true;
   }
 
 private:
   nsString& mValue;
   GetterType mType;
   nsRefPtr<URLProxy> mURLProxy;
 };
 
 // This class is the generic setter for any URL property.
-class SetterRunnable : public URLRunnable
+class SetterRunnable : public WorkerMainThreadRunnable
 {
 public:
   enum SetterType {
     SetterHref,
     SetterProtocol,
     SetterUsername,
     SetterPassword,
     SetterHost,
@@ -437,26 +388,26 @@ public:
     SetterPathname,
     SetterSearch,
     SetterHash,
   };
 
   SetterRunnable(WorkerPrivate* aWorkerPrivate,
                  SetterType aType, const nsAString& aValue,
                  URLProxy* aURLProxy, mozilla::ErrorResult& aRv)
-  : URLRunnable(aWorkerPrivate)
+  : WorkerMainThreadRunnable(aWorkerPrivate)
   , mValue(aValue)
   , mType(aType)
   , mURLProxy(aURLProxy)
   , mRv(aRv)
   {
     mWorkerPrivate->AssertIsOnWorkerThread();
   }
 
-  void
+  bool
   MainThreadRun()
   {
     AssertIsOnMainThread();
 
     switch (mType) {
       case SetterHref:
         mURLProxy->URL()->SetHref(mValue, mRv);
         break;
@@ -492,16 +443,18 @@ public:
       case SetterSearch:
         mURLProxy->URL()->SetSearch(mValue);
         break;
 
       case SetterHash:
         mURLProxy->URL()->SetHash(mValue);
         break;
     }
+
+    return true;
   }
 
 private:
   const nsString mValue;
   SetterType mType;
   nsRefPtr<URLProxy> mURLProxy;
   mozilla::ErrorResult& mRv;
 };
--- a/dom/workers/WorkerRunnable.cpp
+++ b/dom/workers/WorkerRunnable.cpp
@@ -476,16 +476,56 @@ MainThreadWorkerControlRunnable::PostDis
 
   if (aCx && !aDispatchResult) {
     JS_ReportPendingException(aCx);
   }
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(WorkerControlRunnable, WorkerRunnable)
 
+WorkerMainThreadRunnable::WorkerMainThreadRunnable(WorkerPrivate* aWorkerPrivate)
+: mWorkerPrivate(aWorkerPrivate)
+{
+  mWorkerPrivate->AssertIsOnWorkerThread();
+}
+
+bool
+WorkerMainThreadRunnable::Dispatch(JSContext* aCx)
+{
+  mWorkerPrivate->AssertIsOnWorkerThread();
+
+  AutoSyncLoopHolder syncLoop(mWorkerPrivate);
+
+  mSyncLoopTarget = syncLoop.EventTarget();
+
+  if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
+    JS_ReportError(aCx, "Failed to dispatch to main thread!");
+    return false;
+  }
+
+  return syncLoop.Run();
+}
+
+NS_IMETHODIMP
+WorkerMainThreadRunnable::Run()
+{
+  AssertIsOnMainThread();
+
+  bool runResult = MainThreadRun();
+
+  nsRefPtr<MainThreadStopSyncLoopRunnable> response =
+    new MainThreadStopSyncLoopRunnable(mWorkerPrivate,
+                                       mSyncLoopTarget.forget(),
+                                       runResult);
+
+  MOZ_ALWAYS_TRUE(response->Dispatch(nullptr));
+
+  return NS_OK;
+}
+
 bool
 WorkerSameThreadRunnable::PreDispatch(JSContext* aCx,
                                       WorkerPrivate* aWorkerPrivate)
 {
   aWorkerPrivate->AssertIsOnWorkerThread();
   return true;
 }
 
--- a/dom/workers/WorkerRunnable.h
+++ b/dom/workers/WorkerRunnable.h
@@ -7,16 +7,17 @@
 #define mozilla_dom_workers_workerrunnable_h__
 
 #include "Workers.h"
 
 #include "nsICancelableRunnable.h"
 
 #include "mozilla/Atomics.h"
 #include "nsISupportsImpl.h"
+#include "nsThreadUtils.h" /* nsRunnable */
 
 class JSContext;
 class nsIEventTarget;
 
 BEGIN_WORKERS_NAMESPACE
 
 class WorkerPrivate;
 
@@ -337,11 +338,33 @@ protected:
   PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
                bool aDispatchResult) MOZ_OVERRIDE;
 
   virtual void
   PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
           bool aRunResult) MOZ_OVERRIDE;
 };
 
+// Base class for the runnable objects, which makes a synchronous call to
+// dispatch the tasks from the worker thread to the main thread.
+//
+// Note that the derived class must override MainThreadRun.
+class WorkerMainThreadRunnable : public nsRunnable
+{
+protected:
+  WorkerPrivate* mWorkerPrivate;
+  nsCOMPtr<nsIEventTarget> mSyncLoopTarget;
+
+  WorkerMainThreadRunnable(WorkerPrivate* aWorkerPrivate);
+  ~WorkerMainThreadRunnable() {}
+
+  virtual bool MainThreadRun() = 0;
+
+public:
+  bool Dispatch(JSContext* aCx);
+
+private:
+  NS_IMETHOD Run() MOZ_OVERRIDE;  
+};
+
 END_WORKERS_NAMESPACE
 
 #endif // mozilla_dom_workers_workerrunnable_h__