Bug 1000199 - Enable web components for certified apps. r=gabor, r=smaug, r=lmandel
authorWilliam Chen <wchen@mozilla.com>
Mon, 07 Jul 2014 19:02:03 -0700
changeset 207855 936ff3b9a5cece84235fd762ac6038bcfc5e31f7
parent 207854 75e513227fed2f9907f90478956cad8960593266
child 207856 529c1ec49ed098f6c4d4c92dbf4254926281c81f
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgabor, smaug, lmandel
bugs1000199
milestone32.0a2
Bug 1000199 - Enable web components for certified apps. r=gabor, r=smaug, r=lmandel
content/base/src/nsContentSink.cpp
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/base/src/nsStyleLinkElement.cpp
content/base/src/nsStyleLinkElement.h
content/html/content/src/HTMLLinkElement.cpp
content/xml/document/src/nsXMLContentSink.cpp
dom/webidl/Document.webidl
dom/webidl/Element.webidl
dom/webidl/HTMLLinkElement.webidl
dom/webidl/ShadowRoot.webidl
parser/html/nsHtml5DocumentBuilder.cpp
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -660,17 +660,18 @@ nsContentSink::ProcessLinkHeader(const n
 }
 
 
 nsresult
 nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref,
                            const nsSubstring& aRel, const nsSubstring& aTitle,
                            const nsSubstring& aType, const nsSubstring& aMedia)
 {
-  uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(aRel);
+  uint32_t linkTypes =
+    nsStyleLinkElement::ParseLinkTypes(aRel, mDocument->NodePrincipal());
 
   // The link relation may apply to a different resource, specified
   // in the anchor parameter. For the link relations supported so far,
   // we simply abort if the link applies to a resource different to the
   // one we've loaded
   if (!LinkContextIsOurDocument(aAnchor)) {
     return NS_OK;
   }
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -5500,17 +5500,17 @@ nsDocument::CustomElementConstructor(JSC
 
   rv = nsContentUtils::WrapNative(aCx, newElement, newElement, args.rval());
   NS_ENSURE_SUCCESS(rv, true);
 
   return true;
 }
 
 bool
-nsDocument::IsRegisterElementEnabled(JSContext* aCx, JSObject* aObject)
+nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
 {
   JS::Rooted<JSObject*> obj(aCx, aObject);
   return Preferences::GetBool("dom.webcomponents.enabled") ||
     IsInCertifiedApp(aCx, obj);
 }
 
 nsresult
 nsDocument::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName)
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1462,17 +1462,17 @@ public:
   static void ProcessBaseElementQueue();
 
   // Modify the prototype and "is" attribute of newly created custom elements.
   virtual void SwizzleCustomElement(Element* aElement,
                                     const nsAString& aTypeExtension,
                                     uint32_t aNamespaceID,
                                     mozilla::ErrorResult& rv);
 
-  static bool IsRegisterElementEnabled(JSContext* aCx, JSObject* aObject);
+  static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject);
 
   // The "registry" from the web components spec.
   nsRefPtr<mozilla::dom::Registry> mRegistry;
 
   nsRefPtr<mozilla::EventListenerManager> mListenerManager;
   nsRefPtr<mozilla::dom::StyleSheetList> mDOMStyleSheets;
   nsRefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
   nsRefPtr<nsScriptLoader> mScriptLoader;
--- a/content/base/src/nsStyleLinkElement.cpp
+++ b/content/base/src/nsStyleLinkElement.cpp
@@ -117,80 +117,90 @@ nsStyleLinkElement::OverrideBaseURI(nsIU
 
 /* virtual */ void
 nsStyleLinkElement::SetLineNumber(uint32_t aLineNumber)
 {
   mLineNumber = aLineNumber;
 }
 
 /* static */ bool
-nsStyleLinkElement::IsImportEnabled()
+nsStyleLinkElement::IsImportEnabled(nsIPrincipal* aPrincipal)
 {
   static bool sAdded = false;
-  static bool sImportEnabled;
+  static bool sWebComponentsEnabled;
   if (!sAdded) {
     // This part runs only once because of the static flag.
-    Preferences::AddBoolVarCache(&sImportEnabled,
+    Preferences::AddBoolVarCache(&sWebComponentsEnabled,
                                  "dom.webcomponents.enabled",
                                  false);
     sAdded = true;
   }
-  return sImportEnabled;
+
+  if (sWebComponentsEnabled) {
+    return true;
+  }
+
+  // If the web components pref is not enabled, check
+  // if we are in a certified app because imports is enabled
+  // for certified apps.
+  return aPrincipal &&
+    aPrincipal->GetAppStatus() == nsIPrincipal::APP_STATUS_CERTIFIED;
 }
 
-static uint32_t ToLinkMask(const nsAString& aLink)
+static uint32_t ToLinkMask(const nsAString& aLink, nsIPrincipal* aPrincipal)
 { 
   if (aLink.EqualsLiteral("prefetch"))
     return nsStyleLinkElement::ePREFETCH;
   else if (aLink.EqualsLiteral("dns-prefetch"))
     return nsStyleLinkElement::eDNS_PREFETCH;
   else if (aLink.EqualsLiteral("stylesheet"))
     return nsStyleLinkElement::eSTYLESHEET;
   else if (aLink.EqualsLiteral("next"))
     return nsStyleLinkElement::eNEXT;
   else if (aLink.EqualsLiteral("alternate"))
     return nsStyleLinkElement::eALTERNATE;
-  else if (aLink.EqualsLiteral("import") && nsStyleLinkElement::IsImportEnabled())
+  else if (aLink.EqualsLiteral("import") && aPrincipal &&
+           nsStyleLinkElement::IsImportEnabled(aPrincipal))
     return nsStyleLinkElement::eHTMLIMPORT;
   else 
     return 0;
 }
 
-uint32_t nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes)
+uint32_t nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes, nsIPrincipal* aPrincipal)
 {
   uint32_t linkMask = 0;
   nsAString::const_iterator start, done;
   aTypes.BeginReading(start);
   aTypes.EndReading(done);
   if (start == done)
     return linkMask;
 
   nsAString::const_iterator current(start);
   bool inString = !nsContentUtils::IsHTMLWhitespace(*current);
   nsAutoString subString;
   
   while (current != done) {
     if (nsContentUtils::IsHTMLWhitespace(*current)) {
       if (inString) {
         nsContentUtils::ASCIIToLower(Substring(start, current), subString);
-        linkMask |= ToLinkMask(subString);
+        linkMask |= ToLinkMask(subString, aPrincipal);
         inString = false;
       }
     }
     else {
       if (!inString) {
         start = current;
         inString = true;
       }
     }
     ++current;
   }
   if (inString) {
     nsContentUtils::ASCIIToLower(Substring(start, current), subString);
-    linkMask |= ToLinkMask(subString);
+    linkMask |= ToLinkMask(subString, aPrincipal);
   }
   return linkMask;
 }
 
 NS_IMETHODIMP
 nsStyleLinkElement::UpdateStyleSheet(nsICSSLoaderObserver* aObserver,
                                      bool* aWillNotify,
                                      bool* aIsAlternate)
--- a/content/base/src/nsStyleLinkElement.h
+++ b/content/base/src/nsStyleLinkElement.h
@@ -56,20 +56,23 @@ public:
     ePREFETCH =     0x00000001,
     eDNS_PREFETCH = 0x00000002,
     eSTYLESHEET =   0x00000004,
     eNEXT =         0x00000008,
     eALTERNATE =    0x00000010,
     eHTMLIMPORT =   0x00000020
   };
 
-  // The return value is a bitwise or of 0 or more RelValues
-  static uint32_t ParseLinkTypes(const nsAString& aTypes);
+  // The return value is a bitwise or of 0 or more RelValues.
+  // aPrincipal is used to check if HTML imports is enabled for the
+  // provided principal.
+  static uint32_t ParseLinkTypes(const nsAString& aTypes,
+                                 nsIPrincipal* aPrincipal);
 
-  static bool IsImportEnabled();
+  static bool IsImportEnabled(nsIPrincipal* aPrincipal);
   
   void UpdateStyleSheetInternal()
   {
     UpdateStyleSheetInternal(nullptr, nullptr);
   }
 protected:
   /**
    * @param aOldDocument should be non-null only if we're updating because we
--- a/content/html/content/src/HTMLLinkElement.cpp
+++ b/content/html/content/src/HTMLLinkElement.cpp
@@ -272,29 +272,29 @@ HTMLLinkElement::UpdateImport()
       NS_LITERAL_STRING("Nested imports are not supported yet"),
       "Imports");
     return;
   }
 
   // 2. rel type should be import.
   nsAutoString rel;
   GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel);
-  uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel);
+  uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel, NodePrincipal());
   if (!(linkTypes & eHTMLIMPORT)) {
     mImportLoader = nullptr;
     return;
   }
 
   nsCOMPtr<nsIURI> uri = GetHrefURI();
   if (!uri) {
     mImportLoader = nullptr;
     return;
   }
 
-  if (!nsStyleLinkElement::IsImportEnabled()) {
+  if (!nsStyleLinkElement::IsImportEnabled(NodePrincipal())) {
     // For now imports are hidden behind a pref...
     return;
   }
 
   nsRefPtr<ImportManager> manager = doc->ImportManager();
   MOZ_ASSERT(manager, "ImportManager should be created lazily when needed");
 
   {
@@ -326,17 +326,18 @@ HTMLLinkElement::SetAttr(int32_t aNameSp
   if (NS_SUCCEEDED(rv) && aNameSpaceID == kNameSpaceID_None &&
       (aName == nsGkAtoms::href ||
        aName == nsGkAtoms::rel ||
        aName == nsGkAtoms::title ||
        aName == nsGkAtoms::media ||
        aName == nsGkAtoms::type)) {
     bool dropSheet = false;
     if (aName == nsGkAtoms::rel) {
-      uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(aValue);
+      uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(aValue,
+                                                              NodePrincipal());
       if (GetSheet()) {
         dropSheet = !(linkTypes & nsStyleLinkElement::eSTYLESHEET);
       } else if (linkTypes & eHTMLIMPORT) {
         UpdateImport();
       }
     }
 
     if (aName == nsGkAtoms::href) {
@@ -452,17 +453,17 @@ HTMLLinkElement::GetStyleSheetInfo(nsASt
   aTitle.Truncate();
   aType.Truncate();
   aMedia.Truncate();
   *aIsScoped = false;
   *aIsAlternate = false;
 
   nsAutoString rel;
   GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel);
-  uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel);
+  uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel, NodePrincipal());
   // Is it a stylesheet link?
   if (!(linkTypes & nsStyleLinkElement::eSTYLESHEET)) {
     return;
   }
 
   nsAutoString title;
   GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
   title.CompressWhitespace();
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -601,17 +601,18 @@ nsXMLContentSink::CloseElement(nsIConten
       }
     }
     // Look for <link rel="dns-prefetch" href="hostname">
     // and look for <link rel="next" href="hostname"> like in HTML sink
     if (nodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML)) {
       nsAutoString relVal;
       aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relVal);
       if (!relVal.IsEmpty()) {
-        uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(relVal);
+        uint32_t linkTypes =
+          nsStyleLinkElement::ParseLinkTypes(relVal, aContent->NodePrincipal());
         bool hasPrefetch = linkTypes & nsStyleLinkElement::ePREFETCH;
         if (hasPrefetch || (linkTypes & nsStyleLinkElement::eNEXT)) {
           nsAutoString hrefVal;
           aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
           if (!hrefVal.IsEmpty()) {
             PrefetchHref(hrefVal, aContent, hasPrefetch);
           }
         }
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -224,17 +224,17 @@ partial interface Document {
 // http://dvcs.w3.org/hg/pointerlock/raw-file/default/index.html#extensions-to-the-document-interface
 partial interface Document {
     readonly attribute Element? mozPointerLockElement;
     void mozExitPointerLock ();
 };
 
 //http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#dfn-document-register
 partial interface Document {
-    [Throws, Func="nsDocument::IsRegisterElementEnabled"]
+    [Throws, Func="nsDocument::IsWebComponentsEnabled"]
     object registerElement(DOMString name, optional ElementRegistrationOptions options);
 };
 
 //http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#dfn-document-register
 partial interface Document {
     [NewObject, Throws]
     Element createElement(DOMString localName, DOMString typeExtension);
     [NewObject, Throws]
--- a/dom/webidl/Element.webidl
+++ b/dom/webidl/Element.webidl
@@ -196,19 +196,19 @@ partial interface Element {
   [Throws, Pure]
   Element?  querySelector(DOMString selectors);
   [Throws, Pure]
   NodeList  querySelectorAll(DOMString selectors);
 };
 
 // http://w3c.github.io/webcomponents/spec/shadow/#extensions-to-element-interface
 partial interface Element {
-  [Throws,Pref="dom.webcomponents.enabled"]
+  [Throws,Func="nsDocument::IsWebComponentsEnabled"]
   ShadowRoot createShadowRoot();
-  [Pref="dom.webcomponents.enabled"]
+  [Func="nsDocument::IsWebComponentsEnabled"]
   NodeList getDestinationInsertionPoints();
-  [Pref="dom.webcomponents.enabled"]
+  [Func="nsDocument::IsWebComponentsEnabled"]
   readonly attribute ShadowRoot? shadowRoot;
 };
 
 Element implements ChildNode;
 Element implements NonDocumentTypeChildNode;
 Element implements ParentNode;
--- a/dom/webidl/HTMLLinkElement.webidl
+++ b/dom/webidl/HTMLLinkElement.webidl
@@ -39,12 +39,12 @@ partial interface HTMLLinkElement {
   [SetterThrows, Pure]
            attribute DOMString rev;
   [SetterThrows, Pure]
            attribute DOMString target;
 };
 
 // http://w3c.github.io/webcomponents/spec/imports/#interface-import
 partial interface HTMLLinkElement {
-    [Pref="dom.webcomponents.enabled"]
+    [Func="nsDocument::IsWebComponentsEnabled"]
     readonly attribute Document? import;
 };
 
--- a/dom/webidl/ShadowRoot.webidl
+++ b/dom/webidl/ShadowRoot.webidl
@@ -5,17 +5,17 @@
  *
  * The origin of this IDL file is
  * https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
-[Pref="dom.webcomponents.enabled"]
+[Func="nsDocument::IsWebComponentsEnabled"]
 interface ShadowRoot : DocumentFragment
 {
   Element? getElementById(DOMString elementId);
   HTMLCollection getElementsByTagName(DOMString localName);
   HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
   HTMLCollection getElementsByClassName(DOMString classNames);
   [SetterThrows,TreatNullAs=EmptyString]
   attribute DOMString innerHTML;
--- a/parser/html/nsHtml5DocumentBuilder.cpp
+++ b/parser/html/nsHtml5DocumentBuilder.cpp
@@ -81,17 +81,18 @@ nsHtml5DocumentBuilder::UpdateStyleSheet
     mScriptLoader->AddExecuteBlocker();
   }
 
   if (aElement->IsHTML(nsGkAtoms::link)) {
     // look for <link rel="next" href="url">
     nsAutoString relVal;
     aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relVal);
     if (!relVal.IsEmpty()) {
-      uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(relVal);
+      uint32_t linkTypes =
+        nsStyleLinkElement::ParseLinkTypes(relVal, aElement->NodePrincipal());
       bool hasPrefetch = linkTypes & nsStyleLinkElement::ePREFETCH;
       if (hasPrefetch || (linkTypes & nsStyleLinkElement::eNEXT)) {
         nsAutoString hrefVal;
         aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
         if (!hrefVal.IsEmpty()) {
           PrefetchHref(hrefVal, aElement, hasPrefetch);
         }
       }