Bug 910797, make Event.isTrusted to work in workers, r=khuey
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Fri, 30 Aug 2013 12:47:19 +0300
changeset 157994 f60c6188a889fcd63946c3554cab51ff77b85ee3
parent 157993 5dbaea63ac14f015c4288da180bcd3433a7d76b8
child 157995 f243d7aa43200744f0c958260c9107f9985fc519
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs910797
milestone26.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 910797, make Event.isTrusted to work in workers, r=khuey
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
content/events/src/nsDOMEvent.cpp
content/events/src/nsEventDispatcher.cpp
dom/workers/RuntimeService.cpp
dom/workers/WorkerPrivate.h
js/xpconnect/src/xpcprivate.h
xpcom/base/CycleCollectedJSRuntime.h
xpcom/base/nsCycleCollector.cpp
xpcom/base/nsCycleCollector.h
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -184,16 +184,17 @@ public:
   static nsresult Init();
 
   /**
    * Get a JSContext from the document's scope object.
    */
   static JSContext* GetContextFromDocument(nsIDocument *aDocument);
 
   static bool     IsCallerChrome();
+  static bool     ThreadsafeIsCallerChrome();
   static bool     IsCallerXBL();
 
   static bool     IsImageSrcSetDisabled();
 
   static bool LookupBindingMember(JSContext* aCx, nsIContent *aContent,
                                   JS::HandleId aId, JS::MutableHandle<JSPropertyDescriptor> aDesc);
 
   /**
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -1741,29 +1741,46 @@ nsContentUtils::GetDocumentFromContext()
   }
 
   return nullptr;
 }
 
 bool
 nsContentUtils::IsCallerChrome()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   bool is_caller_chrome = false;
   nsresult rv = sSecurityManager->SubjectPrincipalIsSystem(&is_caller_chrome);
   if (NS_FAILED(rv)) {
     return false;
   }
   if (is_caller_chrome) {
     return true;
   }
 
   // If the check failed, look for UniversalXPConnect on the cx compartment.
   return xpc::IsUniversalXPConnectEnabled(GetCurrentJSContext());
 }
 
+namespace mozilla {
+namespace dom {
+namespace workers {
+extern bool IsCurrentThreadRunningChromeWorker();
+}
+}
+}
+
+bool
+nsContentUtils::ThreadsafeIsCallerChrome()
+{
+  return NS_IsMainThread() ?
+    IsCallerChrome() :
+    mozilla::dom::workers::IsCurrentThreadRunningChromeWorker();
+}
+
 bool
 nsContentUtils::IsCallerXBL()
 {
     JSContext *cx = GetCurrentJSContext();
     if (!cx)
         return false;
 
     JSCompartment *c = js::GetContextCompartment(cx);
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -318,16 +318,19 @@ NS_IMETHODIMP_(void)
 nsDOMEvent::SetTrusted(bool aTrusted)
 {
   mEvent->mFlags.mIsTrusted = aTrusted;
 }
 
 bool
 nsDOMEvent::Init(mozilla::dom::EventTarget* aGlobal)
 {
+  if (!mIsMainThreadEvent) {
+    return nsContentUtils::ThreadsafeIsCallerChrome();
+  }
   bool trusted = false;
   nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal);
   if (w) {
     nsCOMPtr<nsIDocument> d = w->GetExtantDoc();
     if (d) {
       trusted = nsContentUtils::IsChromeDoc(d);
       nsIPresShell* s = d->GetShell();
       if (s) {
@@ -463,17 +466,17 @@ nsDOMEvent::SetEventType(const nsAString
 NS_IMETHODIMP
 nsDOMEvent::InitEvent(const nsAString& aEventTypeArg, bool aCanBubbleArg, bool aCancelableArg)
 {
   // Make sure this event isn't already being dispatched.
   NS_ENSURE_TRUE(!mEvent->mFlags.mIsBeingDispatched, NS_OK);
 
   if (IsTrusted()) {
     // Ensure the caller is permitted to dispatch trusted DOM events.
-    if (!nsContentUtils::IsCallerChrome()) {
+    if (!nsContentUtils::ThreadsafeIsCallerChrome()) {
       SetTrusted(false);
     }
   }
 
   SetEventType(aEventTypeArg);
 
   mEvent->mFlags.mBubbles = aCanBubbleArg;
   mEvent->mFlags.mCancelable = aCancelableArg;
--- a/content/events/src/nsEventDispatcher.cpp
+++ b/content/events/src/nsEventDispatcher.cpp
@@ -655,17 +655,17 @@ nsEventDispatcher::DispatchDOMEvent(nsIS
       innerEvent->target = nullptr;
       innerEvent->originalTarget = nullptr;
     } else {
       aDOMEvent->GetIsTrusted(&dontResetTrusted);
     }
 
     if (!dontResetTrusted) {
       //Check security state to determine if dispatcher is trusted
-      aDOMEvent->SetTrusted(nsContentUtils::IsCallerChrome());
+      aDOMEvent->SetTrusted(nsContentUtils::ThreadsafeIsCallerChrome());
     }
 
     return nsEventDispatcher::Dispatch(aTarget, aPresContext, innerEvent,
                                        aDOMEvent, aEventStatus);
   } else if (aEvent) {
     return nsEventDispatcher::Dispatch(aTarget, aPresContext, aEvent,
                                        aDOMEvent, aEventStatus);
   }
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -859,23 +859,16 @@ public:
 
     // The CC is shutdown, and this will GC, so make sure we don't try to CC
     // again.
     mWorkerPrivate = nullptr;
     JS_DestroyContext(mLastJSContext);
     mLastJSContext = nullptr;
   }
 
-  // Make this public for now.  Ideally we'd hide the JSRuntime inside.
-  JSRuntime*
-  Runtime() const
-  {
-    return mozilla::CycleCollectedJSRuntime::Runtime();
-  }
-
   void
   DispatchDeferredDeletion(bool aContinuation) MOZ_OVERRIDE
   {
     MOZ_ASSERT(!aContinuation);
 
     // Do it immediately, no need for asynchronous behavior here.
     nsCycleCollector_doDeferredDeletion();
   }
@@ -1115,16 +1108,30 @@ WorkerCrossThreadDispatcher::PostTask(Wo
 
 WorkerPrivate*
 GetWorkerPrivateFromContext(JSContext* aCx)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   return static_cast<WorkerThreadRuntimePrivate*>(JS_GetRuntimePrivate(JS_GetRuntime(aCx)))->mWorkerPrivate;
 }
 
+bool
+IsCurrentThreadRunningChromeWorker()
+{
+  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  CycleCollectedJSRuntime* ccrt = nsCycleCollector_currentJSRuntime();
+  if (!ccrt) {
+    return false;
+  }
+
+  JSRuntime* rt = ccrt->Runtime();
+  return static_cast<WorkerThreadRuntimePrivate*>(JS_GetRuntimePrivate(rt))->
+    mWorkerPrivate->UsesSystemPrincipal();
+}
+
 END_WORKERS_NAMESPACE
 
 // This is only touched on the main thread. Initialized in Init() below.
 JSSettings RuntimeService::sDefaultJSSettings;
 
 RuntimeService::RuntimeService()
 : mMutex("RuntimeService::mMutex"), mObserved(false),
   mShuttingDown(false), mNavigatorStringsLoaded(false)
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -963,16 +963,19 @@ private:
 
   static bool
   CheckXHRParamsAllowed(nsPIDOMWindow* aWindow);
 };
 
 WorkerPrivate*
 GetWorkerPrivateFromContext(JSContext* aCx);
 
+bool
+IsCurrentThreadRunningChromeWorker();
+
 enum WorkerStructuredDataType
 {
   DOMWORKER_SCTAG_FILE = SCTAG_DOM_MAX,
   DOMWORKER_SCTAG_BLOB,
 
   DOMWORKER_SCTAG_END
 };
 
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -600,22 +600,16 @@ enum WatchdogTimestampCategory
 class AsyncFreeSnowWhite;
 
 class XPCJSRuntime : public mozilla::CycleCollectedJSRuntime
 {
 public:
     static XPCJSRuntime* newXPCJSRuntime(nsXPConnect* aXPConnect);
     static XPCJSRuntime* Get() { return nsXPConnect::XPConnect()->GetRuntime(); }
 
-    // Make this public for now.  Ideally we'd hide the JSRuntime inside.
-    JSRuntime* Runtime() const
-    {
-      return mozilla::CycleCollectedJSRuntime::Runtime();
-    }
-
     XPCJSContextStack* GetJSContextStack() {return mJSContextStack;}
     void DestroyJSContextStack();
 
     XPCCallContext*  GetCallContext() const {return mCallContext;}
     XPCCallContext*  SetCallContext(XPCCallContext* ccx)
         {XPCCallContext* old = mCallContext; mCallContext = ccx; return old;}
 
     jsid GetResolveName() const {return mResolveName;}
--- a/xpcom/base/CycleCollectedJSRuntime.h
+++ b/xpcom/base/CycleCollectedJSRuntime.h
@@ -82,22 +82,16 @@ class CycleCollectedJSRuntime
   friend class JSZoneParticipant;
   friend class IncrementalFinalizeRunnable;
 protected:
   CycleCollectedJSRuntime(uint32_t aMaxbytes,
                           JSUseHelperThreads aUseHelperThreads,
                           bool aExpectUnrootedGlobals);
   virtual ~CycleCollectedJSRuntime();
 
-  JSRuntime* Runtime() const
-  {
-    MOZ_ASSERT(mJSRuntime);
-    return mJSRuntime;
-  }
-
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   void UnmarkSkippableJSHolders();
 
   virtual void TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback& aCb) {}
   virtual void TraceAdditionalNativeGrayRoots(JSTracer* aTracer) {}
 
   virtual void CustomGCCallback(JSGCStatus aStatus) {}
   virtual bool CustomContextCallback(JSContext* aCx, unsigned aOperation)
@@ -203,16 +197,21 @@ public:
                         DeferredFinalizeFunction aFunc,
                         void* aThing);
   void DeferredFinalize(nsISupports* aSupports);
 
   void DumpJSHeap(FILE* aFile);
   
   virtual void DispatchDeferredDeletion(bool aContinuation) = 0;
 
+  JSRuntime* Runtime() const
+  {
+    MOZ_ASSERT(mJSRuntime);
+    return mJSRuntime;
+  }
 private:
   JSGCThingParticipant mGCThingCycleCollectorGlobal;
 
   JSZoneParticipant mJSZoneCycleCollectorGlobal;
 
   JSRuntime* mJSRuntime;
 
   nsDataHashtable<nsPtrHashKey<void>, nsScriptObjectTracer*> mJSHolders;
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -2928,16 +2928,26 @@ nsCycleCollector_forgetJSRuntime()
         data->mRuntime = nullptr;
     } else {
         data->mRuntime = nullptr;
         delete data;
         sCollectorData.set(nullptr);
     }
 }
 
+mozilla::CycleCollectedJSRuntime*
+nsCycleCollector_currentJSRuntime()
+{
+    CollectorData* data = sCollectorData.get();
+    if (data) {
+        return data->mRuntime;
+    }
+    return nullptr;
+}
+
 void
 cyclecollector::AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer)
 {
     CollectorData *data = sCollectorData.get();
 
     // We should have started the cycle collector by now.
     MOZ_ASSERT(data);
     MOZ_ASSERT(data->mCollector);
--- a/xpcom/base/nsCycleCollector.h
+++ b/xpcom/base/nsCycleCollector.h
@@ -59,16 +59,17 @@ void nsCycleCollector_collect(bool aManu
                               nsCycleCollectorResults *aResults,
                               nsICycleCollectorListener *aListener);
 uint32_t nsCycleCollector_suspectedCount();
 void nsCycleCollector_shutdown();
 
 // Helpers for interacting with JS
 void nsCycleCollector_registerJSRuntime(mozilla::CycleCollectedJSRuntime *aRt);
 void nsCycleCollector_forgetJSRuntime();
+mozilla::CycleCollectedJSRuntime* nsCycleCollector_currentJSRuntime();
 
 #define NS_CYCLE_COLLECTOR_LOGGER_CID \
 { 0x58be81b4, 0x39d2, 0x437c, \
 { 0x94, 0xea, 0xae, 0xde, 0x2c, 0x62, 0x08, 0xd3 } }
 
 extern nsresult
 nsCycleCollectorLoggerConstructor(nsISupports* outer,
                                   const nsIID& aIID,