Bug 1276887 - webidl "Deprecated" keyword should work in workers, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 01 Jun 2016 12:15:34 +0200
changeset 338933 d6ae3a85ddeed47e7755976a3d6120c6e3ddf8d6
parent 338932 229098e946458eb5587ef80faa1fe2fa83139b01
child 338934 c7b35a3c1e561ba8246a500663ca5a97162ffbd2
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1276887
milestone49.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 1276887 - webidl "Deprecated" keyword should work in workers, r=smaug
dom/bindings/BindingUtils.cpp
dom/bindings/Exceptions.cpp
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -21,16 +21,18 @@
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsIDocShell.h"
 #include "nsIDOMGlobalPropertyInitializer.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
 #include "nsIXPConnect.h"
 #include "nsUTF8Utils.h"
+#include "WorkerPrivate.h"
+#include "WorkerRunnable.h"
 #include "WrapperFactory.h"
 #include "xpcprivate.h"
 #include "XrayWrapper.h"
 #include "nsPrintfCString.h"
 #include "mozilla/Snprintf.h"
 #include "nsGlobalWindow.h"
 
 #include "mozilla/dom/ScriptSettings.h"
@@ -51,16 +53,18 @@
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "nsDOMClassInfo.h"
 #include "ipc/ErrorIPCUtils.h"
 #include "mozilla/UseCounter.h"
 
 namespace mozilla {
 namespace dom {
 
+using namespace workers;
+
 const JSErrorFormatString ErrorFormatString[] = {
 #define MSG_DEF(_name, _argc, _exn, _str) \
   { #_name, _str, _argc, _exn },
 #include "mozilla/dom/Errors.msg"
 #undef MSG_DEF
 };
 
 #define MSG_DEF(_name, _argc, _exn, _str) \
@@ -2496,32 +2500,30 @@ ConvertJSValueToByteString(JSContext* cx
   JS_EncodeStringToBuffer(cx, s, result.BeginWriting(), length);
 
   return true;
 }
 
 bool
 IsInPrivilegedApp(JSContext* aCx, JSObject* aObj)
 {
-  using mozilla::dom::workers::GetWorkerPrivateFromContext;
   if (!NS_IsMainThread()) {
     return GetWorkerPrivateFromContext(aCx)->IsInPrivilegedApp();
   }
 
   nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aObj);
   uint16_t appStatus = principal->GetAppStatus();
   return (appStatus == nsIPrincipal::APP_STATUS_CERTIFIED ||
           appStatus == nsIPrincipal::APP_STATUS_PRIVILEGED) ||
           Preferences::GetBool("dom.ignore_webidl_scope_checks", false);
 }
 
 bool
 IsInCertifiedApp(JSContext* aCx, JSObject* aObj)
 {
-  using mozilla::dom::workers::GetWorkerPrivateFromContext;
   if (!NS_IsMainThread()) {
     return GetWorkerPrivateFromContext(aCx)->IsInCertifiedApp();
   }
 
   nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aObj);
   return principal->GetAppStatus() == nsIPrincipal::APP_STATUS_CERTIFIED ||
          Preferences::GetBool("dom.ignore_webidl_scope_checks", false);
 }
@@ -3280,38 +3282,159 @@ SetDocumentAndPageUseCounter(JSContext* 
                              UseCounter aUseCounter)
 {
   nsGlobalWindow* win = xpc::WindowGlobalOrNull(js::UncheckedUnwrap(aObject));
   if (win && win->GetDocument()) {
     win->GetDocument()->SetDocumentAndPageUseCounter(aUseCounter);
   }
 }
 
+namespace {
+
+// This runnable is used to write a deprecation message from a worker to the
+// console running on the main-thread.
+class DeprecationWarningRunnable final : public Runnable
+                                       , public WorkerFeature
+{
+  WorkerPrivate* mWorkerPrivate;
+  nsIDocument::DeprecatedOperations mOperation;
+
+public:
+  DeprecationWarningRunnable(WorkerPrivate* aWorkerPrivate,
+                             nsIDocument::DeprecatedOperations aOperation)
+    : mWorkerPrivate(aWorkerPrivate)
+    , mOperation(aOperation)
+  {
+    MOZ_ASSERT(aWorkerPrivate);
+  }
+
+  void
+  Dispatch()
+  {
+    if (NS_WARN_IF(!mWorkerPrivate->AddFeature(this))) {
+      return;
+    }
+
+    if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(this)))) {
+      mWorkerPrivate->RemoveFeature(this);
+      return;
+    }
+  }
+
+  virtual bool
+  Notify(Status aStatus) override
+  {
+    // We don't care about the notification. We just want to keep the
+    // mWorkerPrivate alive.
+    return true;
+  }
+
+private:
+
+  NS_IMETHOD
+  Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    // Walk up to our containing page
+    WorkerPrivate* wp = mWorkerPrivate;
+    while (wp->GetParent()) {
+      wp = wp->GetParent();
+    }
+
+    nsPIDOMWindowInner* window = wp->GetWindow();
+    if (window && window->GetExtantDoc()) {
+      window->GetExtantDoc()->WarnOnceAbout(mOperation);
+    }
+
+    ReleaseWorker();
+    return NS_OK;
+  }
+
+  void
+  ReleaseWorker()
+  {
+    class ReleaseRunnable final : public WorkerRunnable
+    {
+      RefPtr<DeprecationWarningRunnable> mRunnable;
+
+    public:
+      ReleaseRunnable(WorkerPrivate* aWorkerPrivate,
+                      DeprecationWarningRunnable* aRunnable)
+        : WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
+        , mRunnable(aRunnable)
+      {}
+
+      virtual bool
+      WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
+      {
+        MOZ_ASSERT(aWorkerPrivate);
+        aWorkerPrivate->AssertIsOnWorkerThread();
+
+        aWorkerPrivate->RemoveFeature(mRunnable);
+        return true;
+      }
+
+      virtual bool
+      PreDispatch(WorkerPrivate* aWorkerPrivate) override
+      {
+        AssertIsOnMainThread();
+        return true;
+      }
+
+      virtual void
+      PostDispatch(WorkerPrivate* aWorkerPrivate,
+                   bool aDispatchResult) override
+      {
+      }
+    };
+
+    RefPtr<ReleaseRunnable> runnable =
+      new ReleaseRunnable(mWorkerPrivate, this);
+    NS_WARN_IF(!runnable->Dispatch());
+  }
+};
+
+} // anonymous namespace
+
 void
 DeprecationWarning(JSContext* aCx, JSObject* aObject,
                    nsIDocument::DeprecatedOperations aOperation)
 {
   GlobalObject global(aCx, aObject);
   if (global.Failed()) {
     NS_ERROR("Could not create global for DeprecationWarning");
     return;
   }
 
-  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global.GetAsSupports());
-  if (window && window->GetExtantDoc()) {
-    window->GetExtantDoc()->WarnOnceAbout(aOperation);
+  if (NS_IsMainThread()) {
+    nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global.GetAsSupports());
+    if (window && window->GetExtantDoc()) {
+      window->GetExtantDoc()->WarnOnceAbout(aOperation);
+    }
+
+    return;
   }
+
+  WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
+  if (!workerPrivate) {
+    return;
+  }
+
+  RefPtr<DeprecationWarningRunnable> runnable =
+    new DeprecationWarningRunnable(workerPrivate, aOperation);
+  runnable->Dispatch();
 }
 
 namespace binding_detail {
 JSObject*
 UnprivilegedJunkScopeOrWorkerGlobal()
 {
   if (NS_IsMainThread()) {
     return xpc::UnprivilegedJunkScope();
   }
 
-  return workers::GetCurrentThreadWorkerGlobal();
+  return GetCurrentThreadWorkerGlobal();
 }
 } // namespace binding_detail
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/bindings/Exceptions.cpp
+++ b/dom/bindings/Exceptions.cpp
@@ -198,17 +198,17 @@ GetCurrentJSStack(int32_t aMaxDepth)
 {
   // is there a current context available?
   JSContext* cx = nsContentUtils::GetCurrentJSContextForThread();
 
   if (!cx || !js::GetContextCompartment(cx)) {
     return nullptr;
   }
 
-  return exceptions::CreateStack(cx, aMaxDepth);
+  return dom::exceptions::CreateStack(cx, aMaxDepth);
 }
 
 AutoForceSetExceptionOnContext::AutoForceSetExceptionOnContext(JSContext* aCx)
   : mCx(aCx)
 {
   mOldValue = JS::ContextOptionsRef(mCx).autoJSAPIOwnsErrorReporting();
   JS::ContextOptionsRef(mCx).setAutoJSAPIOwnsErrorReporting(true);
 }