Bug 1312272 - Marquee event handlers to adhere CSP. r=smaug
authorFrederik Braun <fbraun+gh@mozilla.com>
Fri, 04 Nov 2016 22:54:59 -0400
changeset 347965 87ae1185df39806f84a0b6069eddcc24febf2bd2
parent 347964 fc8665420489fe577191a430798cf494f8b762af
child 347966 6c8fa338a908091cabd38345bc765c0eb3f3516f
push id10298
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:33:03 +0000
treeherdermozilla-aurora@7e29173b1641 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1312272
milestone52.0a1
Bug 1312272 - Marquee event handlers to adhere CSP. r=smaug MozReview-Commit-ID: 6MxGnFAIhMP
dom/base/nsDocument.cpp
dom/base/nsIDocument.h
dom/webidl/Document.webidl
layout/style/xbl-marquee/xbl-marquee.xml
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -12253,16 +12253,34 @@ nsIDocument::SetPageUseCounter(UseCounte
 }
 
 bool
 nsIDocument::HasScriptsBlockedBySandbox()
 {
   return mSandboxFlags & SANDBOXED_SCRIPTS;
 }
 
+bool
+nsIDocument::InlineScriptAllowedByCSP()
+{
+  nsCOMPtr<nsIContentSecurityPolicy> csp;
+  nsresult rv = NodePrincipal()->GetCsp(getter_AddRefs(csp));
+  NS_ENSURE_SUCCESS(rv, true);
+  bool allowsInlineScript = true;
+  if (csp) {
+    nsresult rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT,
+                                       EmptyString(), // aNonce
+                                       EmptyString(), // FIXME get script sample (bug 1314567)
+                                       0,             // aLineNumber
+                                       &allowsInlineScript);
+    NS_ENSURE_SUCCESS(rv, true);
+  }
+  return allowsInlineScript;
+}
+
 static bool
 MightBeAboutOrChromeScheme(nsIURI* aURI)
 {
   MOZ_ASSERT(aURI);
   bool isAbout = true;
   bool isChrome = true;
   aURI->SchemeIs("about", &isAbout);
   aURI->SchemeIs("chrome", &isChrome);
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2835,16 +2835,18 @@ public:
 
   bool UserHasInteracted()
   {
     return mUserHasInteracted;
   }
 
   bool HasScriptsBlockedBySandbox();
 
+  bool InlineScriptAllowedByCSP();
+
   void ReportHasScrollLinkedEffect();
   bool HasScrollLinkedEffect() const
   {
     return mHasScrollLinkedEffect;
   }
 
   mozilla::dom::DocGroup* GetDocGroup();
 
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -431,19 +431,21 @@ partial interface Document {
 
 // Extension to give chrome JS the ability to determine whether
 // the user has interacted with the document or not.
 partial interface Document {
   [ChromeOnly] readonly attribute boolean userHasInteracted;
 };
 
 // Extension to give chrome and XBL JS the ability to determine whether
-// the document is sandboxed without permission to run scripts.
+// the document is sandboxed without permission to run scripts
+// and whether inline scripts are blocked by the document's CSP.
 partial interface Document {
   [Func="IsChromeOrXBL"] readonly attribute boolean hasScriptsBlockedBySandbox;
+  [Func="IsChromeOrXBL"] readonly attribute boolean inlineScriptAllowedByCSP;
 };
 
 Document implements XPathEvaluator;
 Document implements GlobalEventHandlers;
 Document implements TouchEventHandlers;
 Document implements ParentNode;
 Document implements OnErrorEventHandlerForNodes;
 Document implements GeometryUtils;
--- a/layout/style/xbl-marquee/xbl-marquee.xml
+++ b/layout/style/xbl-marquee/xbl-marquee.xml
@@ -280,16 +280,22 @@
           <![CDATA[
           // _setEventListener is only used for setting the attribute event
           // handlers, which we want to ignore if our document is sandboxed
           // without the allow-scripts keyword.
           if (document.hasScriptsBlockedBySandbox) {
             return true;
           }
 
+          // attribute event handlers should only be added if the
+          // document's CSP allows it.
+          if (!document.inlineScriptAllowedByCSP) {
+            return true;
+          }
+
           if (this._ignoreNextCall) {
             return this._ignoreNextCall = false;
           }
 
           if (aIgnoreNextCall) {
             this._ignoreNextCall = true;
           }