Bug 1275698. Get rid of nsScriptSecurityManager::ScriptAllowed and replace it with xpc::Scriptability::Get(obj).Allowed() for better performance and less indirection. r=khuey
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 27 May 2016 20:26:56 -0400
changeset 299426 9c3411213ac7e9fec81f44c97655dfa4ea814eb9
parent 299425 d9db24868efdf51ed6b518d7befe6a124c23d6a3
child 299427 eb35c54faae8e690d7c9cbffe1c94b845951ada5
push id30297
push usercbook@mozilla.com
push dateMon, 30 May 2016 13:29:51 +0000
treeherdermozilla-central@3435dd7ad71f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs1275698
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 1275698. Get rid of nsScriptSecurityManager::ScriptAllowed and replace it with xpc::Scriptability::Get(obj).Allowed() for better performance and less indirection. r=khuey
caps/nsIScriptSecurityManager.idl
caps/nsScriptSecurityManager.cpp
dom/base/nsDocument.cpp
dom/base/nsJSUtils.cpp
dom/bindings/CallbackObject.cpp
dom/xbl/nsXBLProtoImplMethod.cpp
dom/xul/XULDocument.cpp
parser/html/nsHtml5TreeOpExecutor.cpp
--- a/caps/nsIScriptSecurityManager.idl
+++ b/caps/nsIScriptSecurityManager.idl
@@ -121,21 +121,16 @@ interface nsIScriptSecurityManager : nsI
      * hence will check whether fixed-up versions of the URI are allowed to
      * load as well); if any of the versions of this URI is not allowed, this
      * function will return error code NS_ERROR_DOM_BAD_URI.
      */
     void checkLoadURIStrWithPrincipal(in nsIPrincipal aPrincipal,
                                       in AUTF8String uri,
                                       in unsigned long flags);
 
-    /**
-     * Return true if scripts may be executed in the scope of the given global.
-     */
-    [noscript,notxpcom] boolean scriptAllowed(in JSObjectPtr aGlobal);
-
     ///////////////// Principals ///////////////////////
 
     /**
      * Return the all-powerful system principal.
      */
     nsIPrincipal getSystemPrincipal();
 
     /**
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -1093,26 +1093,16 @@ nsScriptSecurityManager::CheckLoadURIStr
             return rv;
         }
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     return rv;
 }
 
-bool
-nsScriptSecurityManager::ScriptAllowed(JSObject *aGlobal)
-{
-    MOZ_ASSERT(aGlobal);
-    MOZ_ASSERT(JS_IsGlobalObject(aGlobal) || js::IsWindowProxy(aGlobal));
-
-    // Check the bits on the compartment private.
-    return xpc::Scriptability::Get(aGlobal).Allowed();
-}
-
 ///////////////// Principals ///////////////////////
 
 NS_IMETHODIMP
 nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result)
 {
     NS_ADDREF(*result = mSystemPrincipal);
 
     return NS_OK;
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -133,16 +133,17 @@
 #include "nsIDateTimeFormat.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "nsDOMCID.h"
 
 #include "jsapi.h"
 #include "nsIXPConnect.h"
+#include "xpcpublic.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsICategoryManager.h"
 #include "nsIDocumentLoaderFactory.h"
 #include "nsIDocumentLoader.h"
 #include "nsIContentViewer.h"
 #include "nsIXMLContentSink.h"
@@ -8467,28 +8468,25 @@ bool
 nsDocument::IsScriptEnabled()
 {
   // If this document is sandboxed without 'allow-scripts'
   // script is not enabled
   if (mSandboxFlags & SANDBOXED_SCRIPTS) {
     return false;
   }
 
-  nsCOMPtr<nsIScriptSecurityManager> sm(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
-  NS_ENSURE_TRUE(sm, false);
-
   nsCOMPtr<nsIScriptGlobalObject> globalObject = do_QueryInterface(GetInnerWindow());
   if (!globalObject && mMasterDocument) {
     globalObject = do_QueryInterface(mMasterDocument->GetInnerWindow());
   }
   if (!globalObject || !globalObject->GetGlobalJSObject()) {
     return false;
   }
 
-  return sm->ScriptAllowed(globalObject->GetGlobalJSObject());
+  return xpc::Scriptability::Get(globalObject->GetGlobalJSObject()).Allowed();
 }
 
 nsRadioGroupStruct*
 nsDocument::GetRadioGroupInternal(const nsAString& aName) const
 {
 #ifdef DEBUG
   if (IsHTMLDocument()) {
     nsAutoString lcName;
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -169,18 +169,17 @@ nsJSUtils::EvaluateString(JSContext* aCx
   // cases.  So we need to be explicitly told whether the caller cares about the
   // return value.  Callers can do this by calling the other overload of
   // EvaluateString() which calls this function with
   // aCompileOptions.noScriptRval set to true.
   aRetValue.setUndefined();
 
   nsresult rv = NS_OK;
 
-  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-  NS_ENSURE_TRUE(ssm->ScriptAllowed(aEvaluationGlobal), NS_OK);
+  NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK);
 
   bool ok = true;
   // Scope the JSAutoCompartment so that we can later wrap the return value
   // into the caller's cx.
   {
     JSAutoCompartment ac(aCx, aEvaluationGlobal);
 
     // Now make sure to wrap the scope chain into the right compartment.
@@ -289,18 +288,17 @@ nsJSUtils::CompileModule(JSContext* aCx,
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   MOZ_ASSERT(aSrcBuf.get());
   MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(aEvaluationGlobal) ==
              aEvaluationGlobal);
   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx) == aEvaluationGlobal);
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(nsContentUtils::IsInMicroTask());
 
-  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-  NS_ENSURE_TRUE(ssm->ScriptAllowed(aEvaluationGlobal), NS_OK);
+  NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK);
 
   if (!JS::CompileModule(aCx, aCompileOptions, aSrcBuf, aModule)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
@@ -311,19 +309,17 @@ nsJSUtils::ModuleDeclarationInstantiatio
     js::ProfileEntry::Category::JS);
 
   MOZ_ASSERT(JS::ContextOptionsRef(aCx).autoJSAPIOwnsErrorReporting(),
              "Caller must own error reporting");
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(nsContentUtils::IsInMicroTask());
 
-  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-  JSObject* global = JS_GetGlobalForObject(aCx, aModule);
-  NS_ENSURE_TRUE(ssm->ScriptAllowed(global), NS_OK);
+  NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
 
   if (!JS::ModuleDeclarationInstantiation(aCx, aModule)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
@@ -334,19 +330,17 @@ nsJSUtils::ModuleEvaluation(JSContext* a
     js::ProfileEntry::Category::JS);
 
   MOZ_ASSERT(JS::ContextOptionsRef(aCx).autoJSAPIOwnsErrorReporting(),
              "Caller must own error reporting");
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(nsContentUtils::IsInMicroTask());
 
-  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-  JSObject* global = JS_GetGlobalForObject(aCx, aModule);
-  NS_ENSURE_TRUE(ssm->ScriptAllowed(global), NS_OK);
+  NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
 
   if (!JS::ModuleEvaluation(aCx, aModule)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -7,17 +7,16 @@
 #include "mozilla/dom/CallbackObject.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "jsfriendapi.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIXPConnect.h"
 #include "nsIScriptContext.h"
 #include "nsPIDOMWindow.h"
 #include "nsJSUtils.h"
-#include "nsIScriptSecurityManager.h"
 #include "xpcprivate.h"
 #include "WorkerPrivate.h"
 #include "nsGlobalWindow.h"
 #include "WorkerScope.h"
 #include "jsapi.h"
 #include "nsJSPrincipals.h"
 
 namespace mozilla {
@@ -172,18 +171,17 @@ CallbackObject::CallSetup::CallSetup(Cal
   }
 
   // JS-implemented WebIDL is always OK to run, since it runs with Chrome
   // privileges anyway.
   if (mIsMainThread && !aIsJSImplementedWebIDL) {
     // Check that it's ok to run this callback at all.
     // Make sure to use realCallback to get the global of the callback object,
     // not the wrapper.
-    bool allowed = nsContentUtils::GetSecurityManager()->
-      ScriptAllowed(js::GetGlobalForObjectCrossCompartment(realCallback));
+    bool allowed = xpc::Scriptability::Get(realCallback).Allowed();
 
     if (!allowed) {
       aRv.ThrowDOMException(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
         NS_LITERAL_CSTRING("Refusing to execute function from global in which "
                            "script is disabled."));
       return;
     }
   }
--- a/dom/xbl/nsXBLProtoImplMethod.cpp
+++ b/dom/xbl/nsXBLProtoImplMethod.cpp
@@ -311,18 +311,17 @@ nsXBLProtoImplAnonymousMethod::Execute(n
   JS::Rooted<JSObject*> method(cx, JS::CloneFunctionObject(cx, jsMethodObject,
                                                            scopeChain));
   if (!method)
     return NS_ERROR_OUT_OF_MEMORY;
 
   // Now call the method
 
   // Check whether script is enabled.
-  bool scriptAllowed = nsContentUtils::GetSecurityManager()->
-                         ScriptAllowed(js::GetGlobalForObjectCrossCompartment(method));
+  bool scriptAllowed = xpc::Scriptability::Get(method).Allowed();
 
   if (scriptAllowed) {
     JS::Rooted<JS::Value> retval(cx);
     JS::Rooted<JS::Value> methodVal(cx, JS::ObjectValue(*method));
     // No need to check the return here as AutoEntryScript has taken ownership
     // of error reporting.
     ::JS::Call(cx, scopeChain[0], methodVal, JS::HandleValueArray::empty(), &retval);
   }
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -88,16 +88,17 @@
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/Preferences.h"
 #include "nsTextNode.h"
 #include "nsJSUtils.h"
 #include "mozilla/dom/URL.h"
 #include "nsIContentPolicy.h"
 #include "mozAutoDocUpdate.h"
+#include "xpcpublic.h"
 #include "mozilla/StyleSheetHandle.h"
 #include "mozilla/StyleSheetHandleInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 //
@@ -3506,17 +3507,17 @@ XULDocument::ExecuteScript(nsXULPrototyp
     // Execute the precompiled script with the given version
     nsAutoMicroTask mt;
 
     // We're about to run script via JS::CloneAndExecuteScript, so we need an
     // AutoEntryScript. This is Gecko specific and not in any spec.
     AutoEntryScript aes(mScriptGlobalObject, "precompiled XUL <script> element");
     JSContext* cx = aes.cx();
     JS::Rooted<JSObject*> baseGlobal(cx, JS::CurrentGlobalOrNull(cx));
-    NS_ENSURE_TRUE(nsContentUtils::GetSecurityManager()->ScriptAllowed(baseGlobal), NS_OK);
+    NS_ENSURE_TRUE(xpc::Scriptability::Get(baseGlobal).Allowed(), NS_OK);
 
     JSAddonId* addonId = mCurrentPrototype ? MapURIToAddonID(mCurrentPrototype->GetURI()) : nullptr;
     JS::Rooted<JSObject*> global(cx, xpc::GetAddonScope(cx, baseGlobal, addonId));
     NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
 
     JS::ExposeObjectToActiveJS(global);
     xpc_UnmarkGrayScript(scriptObject);
     JSAutoCompartment ac(cx, global);
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -12,32 +12,32 @@
 #include "nsHtml5TreeOpExecutor.h"
 #include "nsScriptLoader.h"
 #include "nsIContentViewer.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShell.h"
 #include "nsIDOMDocument.h"
 #include "nsIScriptGlobalObject.h"
-#include "nsIScriptSecurityManager.h"
 #include "nsIWebShellServices.h"
 #include "nsContentUtils.h"
 #include "mozAutoDocUpdate.h"
 #include "nsNetUtil.h"
 #include "nsHtml5Parser.h"
 #include "nsHtml5Tokenizer.h"
 #include "nsHtml5TreeBuilder.h"
 #include "nsHtml5StreamParser.h"
 #include "mozilla/css/Loader.h"
 #include "GeckoProfiler.h"
 #include "nsIScriptError.h"
 #include "nsIScriptContext.h"
 #include "mozilla/Preferences.h"
 #include "nsIHTMLDocument.h"
 #include "nsIViewSourceChannel.h"
+#include "xpcpublic.h"
 
 using namespace mozilla;
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHtml5TreeOpExecutor)
   NS_INTERFACE_TABLE_INHERITED(nsHtml5TreeOpExecutor,
                                nsIContentSink)
 NS_INTERFACE_TABLE_TAIL_INHERITING(nsHtml5DocumentBuilder)
 
@@ -576,28 +576,29 @@ nsHtml5TreeOpExecutor::FlushDocumentWrit
   }
   return rv;
 }
 
 // copied from HTML content sink
 bool
 nsHtml5TreeOpExecutor::IsScriptEnabled()
 {
+  // Note that if we have no document or no docshell or no global or whatnot we
+  // want to claim script _is_ enabled, so we don't parse the contents of
+  // <noscript> tags!
   if (!mDocument || !mDocShell)
     return true;
   nsCOMPtr<nsIScriptGlobalObject> globalObject = do_QueryInterface(mDocument->GetInnerWindow());
   // Getting context is tricky if the document hasn't had its
   // GlobalObject set yet
   if (!globalObject) {
     globalObject = mDocShell->GetScriptGlobalObject();
-    NS_ENSURE_TRUE(globalObject, true);
   }
   NS_ENSURE_TRUE(globalObject && globalObject->GetGlobalJSObject(), true);
-  return nsContentUtils::GetSecurityManager()->
-           ScriptAllowed(globalObject->GetGlobalJSObject());
+  return xpc::Scriptability::Get(globalObject->GetGlobalJSObject()).Allowed();
 }
 
 void
 nsHtml5TreeOpExecutor::StartLayout() {
   if (mLayoutStarted || !mDocument) {
     return;
   }