Bug 1240365 - FileReader should use the global scope correctly in ChromeWorkers, r=smaug, r=khuey
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 20 Jan 2016 18:17:57 +0000
changeset 280752 b67a5343e79fef3d6e949e1c437c9a0e5435e3e7
parent 280751 ababaae69ec618ed9740dd898c65be77cb37b8db
child 280753 b8dfc7fb1398fbc20994ba73fee89a1a9fe9935c
push id70567
push useramarchesini@mozilla.com
push dateWed, 20 Jan 2016 18:26:27 +0000
treeherdermozilla-inbound@b67a5343e79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, khuey
bugs1240365
milestone46.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1240365 - FileReader should use the global scope correctly in ChromeWorkers, r=smaug, r=khuey
dom/base/FileReader.cpp
dom/base/FileReader.h
dom/workers/test/xpcshell/data/worker_fileReader.js
dom/workers/test/xpcshell/test_fileReader.js
dom/workers/test/xpcshell/xpcshell.ini
--- a/dom/base/FileReader.cpp
+++ b/dom/base/FileReader.cpp
@@ -93,64 +93,56 @@ public:
 void
 FileReader::RootResultArrayBuffer()
 {
   mozilla::HoldJSObjects(this);
 }
 
 //FileReader constructors/initializers
 
-FileReader::FileReader(nsPIDOMWindow* aWindow,
+FileReader::FileReader(nsIGlobalObject* aGlobal,
                        WorkerPrivate* aWorkerPrivate)
-  : DOMEventTargetHelper(aWindow)
+  : DOMEventTargetHelper(aGlobal)
   , mFileData(nullptr)
   , mDataLen(0)
   , mDataFormat(FILE_AS_BINARY)
   , mResultArrayBuffer(nullptr)
   , mProgressEventWasDelayed(false)
   , mTimerIsActive(false)
   , mReadyState(EMPTY)
   , mTotal(0)
   , mTransferred(0)
   , mTarget(do_GetCurrentThread())
   , mBusyCount(0)
   , mWorkerPrivate(aWorkerPrivate)
 {
-  MOZ_ASSERT_IF(!NS_IsMainThread(), mWorkerPrivate && !aWindow);
-  MOZ_ASSERT_IF(NS_IsMainThread(), !mWorkerPrivate);
+  MOZ_ASSERT(aGlobal);
+  MOZ_ASSERT(NS_IsMainThread() == !mWorkerPrivate);
   SetDOMStringToNull(mResult);
 }
 
 FileReader::~FileReader()
 {
   Shutdown();
   DropJSObjects(this);
 }
 
 /* static */ already_AddRefed<FileReader>
 FileReader::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
 {
-  // The owner can be null when this object is used by chrome code.
-  nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(aGlobal.GetAsSupports());
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
   WorkerPrivate* workerPrivate = nullptr;
 
   if (!NS_IsMainThread()) {
     JSContext* cx = aGlobal.Context();
     workerPrivate = GetWorkerPrivateFromContext(cx);
     MOZ_ASSERT(workerPrivate);
   }
 
-  RefPtr<FileReader> fileReader = new FileReader(owner, workerPrivate);
-
-  if (!owner && nsContentUtils::ThreadsafeIsCallerChrome()) {
-    // Instead of grabbing some random global from the context stack,
-    // let's use the default one (junk scope) for now.
-    // We should move away from this Init...
-    fileReader->BindToOwner(xpc::NativeGlobal(xpc::PrivilegedJunkScope()));
-  }
+  RefPtr<FileReader> fileReader = new FileReader(global, workerPrivate);
 
   return fileReader.forget();
 }
 
 // nsIInterfaceRequestor
 
 NS_IMETHODIMP
 FileReader::GetInterface(const nsIID & aIID, void **aResult)
@@ -237,27 +229,17 @@ FileReader::DoOnLoadEnd(nsresult aStatus
 
   aSuccessEvent = NS_LITERAL_STRING(LOAD_STR);
   aTerminationEvent = NS_LITERAL_STRING(LOADEND_STR);
 
   nsresult rv = NS_OK;
   switch (mDataFormat) {
     case FILE_AS_ARRAYBUFFER: {
       AutoJSAPI jsapi;
-      nsCOMPtr<nsIGlobalObject> globalObject;
-
-      if (NS_IsMainThread()) {
-        globalObject = do_QueryInterface(GetParentObject());
-      } else {
-        MOZ_ASSERT(mWorkerPrivate);
-        MOZ_ASSERT(mBusyCount);
-        globalObject = mWorkerPrivate->GlobalScope();
-      }
-
-      if (!globalObject || !jsapi.Init(globalObject)) {
+      if (!jsapi.Init(GetParentObject())) {
         FreeFileData();
         return NS_ERROR_FAILURE;
       }
 
       RootResultArrayBuffer();
       mResultArrayBuffer = JS_NewArrayBufferWithContents(jsapi.cx(), mDataLen, mFileData);
       if (!mResultArrayBuffer) {
         JS_ClearPendingException(jsapi.cx());
--- a/dom/base/FileReader.h
+++ b/dom/base/FileReader.h
@@ -41,17 +41,17 @@ class FileReader final : public DOMEvent
                          public nsSupportsWeakReference,
                          public nsIInputStreamCallback,
                          public nsITimerCallback,
                          public workers::WorkerFeature
 {
   friend class FileReaderDecreaseBusyCounter;
 
 public:
-  FileReader(nsPIDOMWindow* aWindow,
+  FileReader(nsIGlobalObject* aGlobal,
              workers::WorkerPrivate* aWorkerPrivate);
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_NSITIMERCALLBACK
   NS_DECL_NSIINPUTSTREAMCALLBACK
   NS_DECL_NSIINTERFACEREQUESTOR
 
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/xpcshell/data/worker_fileReader.js
@@ -0,0 +1,8 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+
+self.onmessage = function(msg) {
+  var fr = new FileReader();
+  self.postMessage("OK");
+};
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/xpcshell/test_fileReader.js
@@ -0,0 +1,40 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+Components.utils.import("resource://gre/modules/Promise.jsm");
+
+// Worker must be loaded from a chrome:// uri, not a file://
+// uri, so we first need to load it.
+var WORKER_SOURCE_URI = "chrome://workers/content/worker_fileReader.js";
+do_load_manifest("data/chrome.manifest");
+
+function run_test() {
+  run_next_test();
+}
+
+function talk_with_worker(worker) {
+  let deferred = Promise.defer();
+  worker.onmessage = function(event) {
+    let success = true;
+    if (event.data == "OK") {
+      deferred.resolve();
+    } else {
+      success = false;
+      deferred.reject(event);
+    }
+    do_check_true(success);
+    worker.terminate();
+  };
+  worker.onerror = function(event) {
+    let error = new Error(event.message, event.filename, event.lineno);
+    worker.terminate();
+    deferred.reject(error);
+  };
+  worker.postMessage("START");
+  return deferred.promise;
+}
+
+
+add_task(function test_chrome_worker() {
+  return talk_with_worker(new ChromeWorker(WORKER_SOURCE_URI));
+});
--- a/dom/workers/test/xpcshell/xpcshell.ini
+++ b/dom/workers/test/xpcshell/xpcshell.ini
@@ -1,9 +1,11 @@
 [DEFAULT]
 head =
 tail =
 skip-if = toolkit == 'android' || toolkit == 'gonk'
 support-files =
   data/worker.js
+  data/worker_fileReader.js
   data/chrome.manifest
 
 [test_workers.js]
+[test_fileReader.js]