Bug 944407 - Allow scripts for an XBL binding if and only if the XBL document comes from a scriptable domain. r=bz, a=lsblakk
authorBobby Holley <bobbyholley@gmail.com>
Fri, 13 Dec 2013 08:54:04 -0800
changeset 175492 c80a5475fb2583aedb31ad0bbed9c6bd8d3ba008
parent 175491 87a3450489c7c4a1fea0aa526b1e476d51fbcb1f
child 175493 e73905e8ca8b13ace366bed4a63ebcb865b37ff1
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, lsblakk
bugs944407
milestone28.0a2
Bug 944407 - Allow scripts for an XBL binding if and only if the XBL document comes from a scriptable domain. r=bz, a=lsblakk
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLBinding.h
content/xbl/src/nsXBLDocumentInfo.cpp
content/xbl/src/nsXBLDocumentInfo.h
content/xbl/src/nsXBLPrototypeBinding.cpp
content/xbl/src/nsXBLPrototypeBinding.h
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -1077,38 +1077,17 @@ nsXBLBinding::DoInitJSClass(JSContext *c
   }
 
   return NS_OK;
 }
 
 bool
 nsXBLBinding::AllowScripts()
 {
-  if (!mPrototypeBinding->GetAllowScripts())
-    return false;
-
-  // Nasty hack.  Use the JSContext of the bound node, since the
-  // security manager API expects to get the docshell type from
-  // that.  But use the nsIPrincipal of our document.
-  nsIScriptSecurityManager* mgr = nsContentUtils::GetSecurityManager();
-  if (!mgr) {
-    return false;
-  }
-
-  nsIDocument* doc = mBoundElement ? mBoundElement->OwnerDoc() : nullptr;
-  if (!doc) {
-    return false;
-  }
-
-  nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(doc->GetInnerWindow());
-  if (!global || !global->GetGlobalJSObject()) {
-    return false;
-  }
-
-  return mgr->ScriptAllowed(global->GetGlobalJSObject());
+  return mPrototypeBinding->GetAllowScripts();
 }
 
 nsXBLBinding*
 nsXBLBinding::RootBinding()
 {
   if (mNextBinding)
     return mNextBinding->RootBinding();
 
--- a/content/xbl/src/nsXBLBinding.h
+++ b/content/xbl/src/nsXBLBinding.h
@@ -136,17 +136,17 @@ public:
 
   static nsresult DoInitJSClass(JSContext *cx, JS::Handle<JSObject*> global,
                                 JS::Handle<JSObject*> obj,
                                 const nsAFlatCString& aClassName,
                                 nsXBLPrototypeBinding* aProtoBinding,
                                 JS::MutableHandle<JSObject*> aClassObject,
                                 bool* aNew);
 
-  bool AllowScripts();  // XXX make const
+  bool AllowScripts();
 
   mozilla::dom::XBLChildrenElement* FindInsertionPointFor(nsIContent* aChild);
 
   bool HasFilteredInsertionPoints()
   {
     return !mInsertionPoints.IsEmpty();
   }
 
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -398,16 +398,34 @@ nsXBLDocumentInfo::nsXBLDocumentInfo(nsI
     nsCOMPtr<nsIXULChromeRegistry> reg =
       mozilla::services::GetXULChromeRegistryService();
     if (reg) {
       bool allow = true;
       reg->AllowScriptsForPackage(uri, &allow);
       mScriptAccess = allow;
     }
     mIsChrome = true;
+  } else {
+    // If this binding isn't running with system principal, then it's running
+    // from a remote-XUL whitelisted domain. This is already a not-really-
+    // supported configuration (among other things, we don't use XBL scopes in
+    // that configuration for compatibility reasons). But we should still at
+    // least make an effort to prevent binding code from running if content
+    // script is disabled or if the source domain is blacklisted (since the
+    // source domain for remote XBL must always be the same as the source domain
+    // of the bound content).
+    //
+    // If we just ask the binding document if script is enabled, it will
+    // discover that it has no inner window, and return false. So instead, we
+    // short-circuit the normal compartment-managed script-disabling machinery,
+    // and query the policy for the URI directly.
+    bool allow;
+    nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
+    nsresult rv = ssm->PolicyAllowsScript(uri, &allow);
+    mScriptAccess = NS_SUCCEEDED(rv) && allow;
   }
 }
 
 nsXBLDocumentInfo::~nsXBLDocumentInfo()
 {
   /* destructor code */
   if (mGlobalObject) {
     mGlobalObject->ClearGlobalObjectOwner(); // just in case
--- a/content/xbl/src/nsXBLDocumentInfo.h
+++ b/content/xbl/src/nsXBLDocumentInfo.h
@@ -22,17 +22,17 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   nsXBLDocumentInfo(nsIDocument* aDocument);
   virtual ~nsXBLDocumentInfo();
 
   already_AddRefed<nsIDocument> GetDocument()
     { nsCOMPtr<nsIDocument> copy = mDocument; return copy.forget(); }
 
-  bool GetScriptAccess() { return mScriptAccess; }
+  bool GetScriptAccess() const { return mScriptAccess; }
 
   nsIURI* DocumentURI() { return mDocument->GetDocumentURI(); }
 
   nsXBLPrototypeBinding* GetPrototypeBinding(const nsACString& aRef);
   nsresult SetPrototypeBinding(const nsACString& aRef,
                                nsXBLPrototypeBinding* aBinding);
 
   // This removes the binding without deleting it
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp
+++ b/content/xbl/src/nsXBLPrototypeBinding.cpp
@@ -209,17 +209,17 @@ nsXBLPrototypeBinding::SetBindingElement
     mInheritStyle = false;
 
   mChromeOnlyContent = mBinding->AttrValueIs(kNameSpaceID_None,
                                              nsGkAtoms::chromeOnlyContent,
                                              nsGkAtoms::_true, eCaseMatters);
 }
 
 bool
-nsXBLPrototypeBinding::GetAllowScripts()
+nsXBLPrototypeBinding::GetAllowScripts() const
 {
   return mXBLDocInfoWeak->GetScriptAccess();
 }
 
 bool
 nsXBLPrototypeBinding::LoadResources()
 {
   if (mResources) {
--- a/content/xbl/src/nsXBLPrototypeBinding.h
+++ b/content/xbl/src/nsXBLPrototypeBinding.h
@@ -43,17 +43,17 @@ public:
   nsIURI* AlternateBindingURI() const { return mAlternateBindingURI; }
   nsIURI* DocURI() const { return mXBLDocInfoWeak->DocumentURI(); }
   nsIURI* GetBaseBindingURI() const { return mBaseBindingURI; }
 
   // Checks if aURI refers to this binding by comparing to both possible
   // binding URIs.
   bool CompareBindingURI(nsIURI* aURI) const;
 
-  bool GetAllowScripts();
+  bool GetAllowScripts() const;
 
   nsresult BindingAttached(nsIContent* aBoundElement);
   nsresult BindingDetached(nsIContent* aBoundElement);
 
   bool LoadResources();
   nsresult AddResource(nsIAtom* aResourceType, const nsAString& aSrc);
 
   bool InheritsStyle() const { return mInheritStyle; }