Bug 1343964 part 4 - Have document and svg:use element own URLExtraData. r=bholley,bz
authorXidorn Quan <me@upsuper.org>
Thu, 06 Apr 2017 16:51:29 +1000
changeset 558302 a37bb4a37b0176dc2f914c2f097270567f84f622
parent 558301 cb21e116df504976cc9921b90000f4b327216d97
child 558303 78aed6715e29dd37b34cd32ec6d51dad1b2816fa
push id52860
push userbmo:walkingice0204@gmail.com
push dateFri, 07 Apr 2017 13:29:26 +0000
reviewersbholley, bz
bugs1343964
milestone55.0a1
Bug 1343964 part 4 - Have document and svg:use element own URLExtraData. r=bholley,bz MozReview-Commit-ID: 8451L5qJvEx
dom/base/FragmentOrElement.cpp
dom/base/nsDocument.cpp
dom/base/nsIContent.h
dom/base/nsIDocument.h
dom/svg/SVGUseElement.cpp
dom/svg/SVGUseElement.h
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -19,16 +19,17 @@
 
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/EffectSet.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/ServoRestyleManager.h"
+#include "mozilla/URLExtraData.h"
 #include "mozilla/dom/Attr.h"
 #include "nsDOMAttributeMap.h"
 #include "nsIAtom.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "mozilla/dom/Event.h"
 #include "nsIDocumentInlines.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIDOMNodeList.h"
@@ -343,17 +344,17 @@ nsIContent::LookupNamespaceURIInternal(c
 already_AddRefed<nsIURI>
 nsIContent::GetBaseURI(bool aTryUseXHRDocBaseURI) const
 {
   if (IsInAnonymousSubtree() && IsAnonymousContentInSVGUseSubtree()) {
     nsIContent* bindingParent = GetBindingParent();
     MOZ_ASSERT(bindingParent);
     SVGUseElement* useElement = static_cast<SVGUseElement*>(bindingParent);
     // XXX Ignore xml:base as we are removing it.
-    return do_AddRef(useElement->GetContentBaseURI());
+    return do_AddRef(useElement->GetContentURLData()->BaseURI());
   }
 
   nsIDocument* doc = OwnerDoc();
   // Start with document base
   nsCOMPtr<nsIURI> base = doc->GetBaseURI(aTryUseXHRDocBaseURI);
 
   // Collect array of xml:base attribute values up the parent chain. This
   // is slightly slower for the case when there are xml:base attributes, but
@@ -413,17 +414,17 @@ nsIContent::GetBaseURI(bool aTryUseXHRDo
 
 nsIURI*
 nsIContent::GetBaseURIWithoutXMLBase() const
 {
   if (IsInAnonymousSubtree() && IsAnonymousContentInSVGUseSubtree()) {
     nsIContent* bindingParent = GetBindingParent();
     MOZ_ASSERT(bindingParent);
     SVGUseElement* useElement = static_cast<SVGUseElement*>(bindingParent);
-    return useElement->GetContentBaseURI();
+    return useElement->GetContentURLData()->BaseURI();
   }
   // This also ignores the case that SVG inside XBL binding.
   // But it is probably fine.
   return OwnerDoc()->GetDocBaseURI();
 }
 
 already_AddRefed<nsIURI>
 nsIContent::GetBaseURIForStyleAttr() const
@@ -440,16 +441,33 @@ nsIContent::GetBaseURIForStyleAttr() con
     if (!isEqual) {
       doc->WarnOnceAbout(nsIDocument::eXMLBaseAttributeForStyleAttr);
     }
   }
   return nsLayoutUtils::StyleAttrWithXMLBaseDisabled()
     ? do_AddRef(baseWithoutXMLBase) : base.forget();
 }
 
+URLExtraData*
+nsIContent::GetURLDataForStyleAttr() const
+{
+  if (IsInAnonymousSubtree() && IsAnonymousContentInSVGUseSubtree()) {
+    nsIContent* bindingParent = GetBindingParent();
+    MOZ_ASSERT(bindingParent);
+    SVGUseElement* useElement = static_cast<SVGUseElement*>(bindingParent);
+    return useElement->GetContentURLData();
+  }
+  // We are not going to support xml:base for stylo, but we want to
+  // ensure we unship that support before we enabling stylo.
+  MOZ_ASSERT(nsLayoutUtils::StyleAttrWithXMLBaseDisabled());
+  // This also ignores the case that SVG inside XBL binding.
+  // But it is probably fine.
+  return OwnerDoc()->DefaultStyleAttrURLData();
+}
+
 //----------------------------------------------------------------------
 
 static inline JSObject*
 GetJSObjectChild(nsWrapperCache* aCache)
 {
   return aCache->PreservingWrapper() ? aCache->GetWrapperPreserveColor() : nullptr;
 }
 
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -16,16 +16,17 @@
 #include "mozilla/AutoRestore.h"
 #include "mozilla/BinarySearch.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/EffectSet.h"
 #include "mozilla/IntegerRange.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Likely.h"
 #include "mozilla/PresShell.h"
+#include "mozilla/URLExtraData.h"
 #include <algorithm>
 
 #include "mozilla/Logging.h"
 #include "plstr.h"
 #include "mozilla/Sprintf.h"
 
 #include "mozilla/Telemetry.h"
 #include "nsIInterfaceRequestor.h"
@@ -3578,16 +3579,37 @@ nsDocument::SetBaseURI(nsIURI* aURI)
   if (aURI) {
     mDocumentBaseURI = NS_TryToMakeImmutable(aURI);
   } else {
     mDocumentBaseURI = nullptr;
   }
   RefreshLinkHrefs();
 }
 
+URLExtraData*
+nsIDocument::DefaultStyleAttrURLData()
+{
+#ifdef MOZ_STYLO
+  MOZ_ASSERT(NS_IsMainThread());
+  nsIURI* baseURI = GetDocBaseURI();
+  nsIURI* docURI = GetDocumentURI();
+  nsIPrincipal* principal = NodePrincipal();
+  if (!mCachedURLData ||
+      mCachedURLData->BaseURI() != baseURI ||
+      mCachedURLData->GetReferrer() != docURI ||
+      mCachedURLData->GetPrincipal() != principal) {
+    mCachedURLData = new URLExtraData(baseURI, docURI, principal);
+  }
+  return mCachedURLData;
+#else
+  MOZ_CRASH("Should not be called for non-stylo build");
+  return nullptr;
+#endif
+}
+
 void
 nsDocument::GetBaseTarget(nsAString &aBaseTarget)
 {
   aBaseTarget = mBaseTarget;
 }
 
 void
 nsDocument::SetDocumentCharacterSet(const nsACString& aCharSetID)
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -19,16 +19,17 @@ class nsRuleWalker;
 class nsAttrValue;
 class nsAttrName;
 class nsTextFragment;
 class nsIFrame;
 class nsXBLBinding;
 
 namespace mozilla {
 class EventChainPreVisitor;
+struct URLExtraData;
 namespace dom {
 class ShadowRoot;
 } // namespace dom
 namespace widget {
 struct IMEState;
 } // namespace widget
 } // namespace mozilla
 
@@ -956,16 +957,19 @@ public:
   }
 
   // Overloaded from nsINode
   virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
 
   // Returns base URI for style attribute.
   already_AddRefed<nsIURI> GetBaseURIForStyleAttr() const;
 
+  // Returns the URL data for style attribute.
+  mozilla::URLExtraData* GetURLDataForStyleAttr() const;
+
   virtual nsresult GetEventTargetParent(
                      mozilla::EventChainPreVisitor& aVisitor) override;
 
   virtual bool IsPurple() = 0;
   virtual void RemovePurple() = 0;
 
   virtual bool OwnedOnlyByTheDOMTree() { return false; }
 protected:
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -105,16 +105,17 @@ struct nsCSSSelectorList;
 namespace mozilla {
 class AbstractThread;
 class CSSStyleSheet;
 class ErrorResult;
 class EventStates;
 class PendingAnimationTracker;
 class StyleSetHandle;
 template<typename> class OwningNonNull;
+struct URLExtraData;
 
 namespace css {
 class Loader;
 class ImageLoader;
 class Rule;
 } // namespace css
 
 namespace dom {
@@ -480,16 +481,25 @@ public:
     }
     return GetFallbackBaseURI();
   }
   virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
 
   virtual void SetBaseURI(nsIURI* aURI) = 0;
 
   /**
+   * Return the URL data which style system needs for resolving url value.
+   * This method attempts to use the cached object in mCachedURLData, but
+   * if the base URI, document URI, or principal has changed since last
+   * call to this function, or the function is called the first time for
+   * the document, a new one is created.
+   */
+  mozilla::URLExtraData* DefaultStyleAttrURLData();
+
+  /**
    * Get/Set the base target of a link in a document.
    */
   virtual void GetBaseTarget(nsAString &aBaseTarget) = 0;
   void SetBaseTarget(const nsString& aBaseTarget) {
     mBaseTarget = aBaseTarget;
   }
 
   /**
@@ -2979,16 +2989,21 @@ protected:
   nsString mLastModified;
 
   nsCOMPtr<nsIURI> mDocumentURI;
   nsCOMPtr<nsIURI> mOriginalURI;
   nsCOMPtr<nsIURI> mChromeXHRDocURI;
   nsCOMPtr<nsIURI> mDocumentBaseURI;
   nsCOMPtr<nsIURI> mChromeXHRDocBaseURI;
 
+#ifdef MOZ_STYLO
+  // A lazily-constructed URL data for style system to resolve URL value.
+  RefPtr<mozilla::URLExtraData> mCachedURLData;
+#endif
+
   nsWeakPtr mDocumentLoadGroup;
 
   bool mReferrerPolicySet;
   ReferrerPolicyEnum mReferrerPolicy;
 
   bool mBlockAllMixedContent;
   bool mBlockAllMixedContentPreloads;
   bool mUpgradeInsecureRequests;
--- a/dom/svg/SVGUseElement.cpp
+++ b/dom/svg/SVGUseElement.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/dom/SVGUseElementBinding.h"
 #include "nsGkAtoms.h"
 #include "mozilla/dom/SVGSVGElement.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "mozilla/dom/Element.h"
 #include "nsContentUtils.h"
 #include "nsIURI.h"
+#include "mozilla/URLExtraData.h"
 
 NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Use)
 
 namespace mozilla {
 namespace dom {
 
 JSObject*
 SVGUseElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
@@ -322,20 +323,23 @@ SVGUseElement::CreateAnonymousContent()
 
     if (mLengthAttributes[ATTR_WIDTH].IsExplicitlySet())
       newElement->SetLength(nsGkAtoms::width, mLengthAttributes[ATTR_WIDTH]);
     if (mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet())
       newElement->SetLength(nsGkAtoms::height, mLengthAttributes[ATTR_HEIGHT]);
   }
 
   // Store the base URI
-  mContentBaseURI = targetContent->GetBaseURI();
-  if (!mContentBaseURI) {
+  nsCOMPtr<nsIURI> baseURI = targetContent->GetBaseURI();
+  if (!baseURI) {
     return nullptr;
   }
+  mContentURLData = new URLExtraData(baseURI.forget(),
+                                     do_AddRef(OwnerDoc()->GetDocumentURI()),
+                                     do_AddRef(NodePrincipal()));
 
   targetContent->AddMutationObserver(this);
   mClone = newcontent;
 
 #ifdef DEBUG
   // Our anonymous clone can get restyled by various things
   // (e.g. SMIL).  Reconstructing its frame is OK, though, because
   // it's going to be our _only_ child in the frame tree, so can't get
--- a/dom/svg/SVGUseElement.h
+++ b/dom/svg/SVGUseElement.h
@@ -21,16 +21,18 @@ class nsSVGUseFrame;
 nsresult
 NS_NewSVGSVGElement(nsIContent **aResult,
                     already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
                     mozilla::dom::FromParser aFromParser);
 nsresult NS_NewSVGUseElement(nsIContent **aResult,
                              already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
 
 namespace mozilla {
+struct URLExtraData;
+
 namespace dom {
 
 typedef SVGGraphicsElement SVGUseElementBase;
 
 class SVGUseElement final : public SVGUseElementBase,
                             public nsStubMutationObserver
 {
   friend class ::nsSVGUseFrame;
@@ -72,17 +74,17 @@ public:
   // WebIDL
   already_AddRefed<SVGAnimatedString> Href();
   already_AddRefed<SVGAnimatedLength> X();
   already_AddRefed<SVGAnimatedLength> Y();
   already_AddRefed<SVGAnimatedLength> Width();
   already_AddRefed<SVGAnimatedLength> Height();
 
   nsIURI* GetSourceDocURI();
-  nsIURI* GetContentBaseURI() const { return mContentBaseURI; }
+  URLExtraData* GetContentURLData() const { return mContentURLData; }
 
 protected:
   class SourceReference : public nsReferencedElement {
   public:
     explicit SourceReference(SVGUseElement* aContainer) : mContainer(aContainer) {}
   protected:
     virtual void ElementChanged(Element* aFrom, Element* aTo) override {
       nsReferencedElement::ElementChanged(aFrom, aTo);
@@ -115,15 +117,15 @@ protected:
 
   enum { HREF, XLINK_HREF };
   nsSVGString mStringAttributes[2];
   static StringInfo sStringInfo[2];
 
   nsCOMPtr<nsIContent> mOriginal; // if we've been cloned, our "real" copy
   nsCOMPtr<nsIContent> mClone;    // cloned tree
   SourceReference      mSource;   // observed element
-  nsCOMPtr<nsIURI> mContentBaseURI; // Base URI for its anonymous content
+  RefPtr<URLExtraData> mContentURLData; // URL data for its anonymous content
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_SVGUseElement_h