Bug 1351957 - Create URLExtraData for holding base uri, referrer, and principal. r=heycam draft
authorXidorn Quan <me@upsuper.org>
Thu, 30 Mar 2017 18:54:48 +1100
changeset 554859 cae3dba21c916ab0f52056bd9db215249b650cd3
parent 554858 88e9a921844540a18b912bb2a027c00643332346
child 622455 de427a7ce90c91b88d5b66cc966db3d245d5e7f5
push id52072
push userxquan@mozilla.com
push dateMon, 03 Apr 2017 03:42:15 +0000
reviewersheycam
bugs1351957
milestone55.0a1
Bug 1351957 - Create URLExtraData for holding base uri, referrer, and principal. r=heycam MozReview-Commit-ID: 1wqTb3kvvWh
dom/animation/KeyframeUtils.cpp
dom/animation/TimingParams.cpp
dom/base/Element.cpp
dom/base/nsAttrValue.cpp
dom/svg/nsSVGElement.cpp
layout/base/nsCSSFrameConstructor.cpp
layout/style/FontFaceSet.cpp
layout/style/ServoBindingList.h
layout/style/ServoBindingTypes.h
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/ServoDeclarationBlock.cpp
layout/style/ServoDeclarationBlock.h
layout/style/ServoStyleSheet.cpp
layout/style/nsCSSValue.cpp
layout/style/nsCSSValue.h
layout/style/nsDOMCSSDeclaration.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/dom/animation/KeyframeUtils.cpp
+++ b/dom/animation/KeyframeUtils.cpp
@@ -1017,23 +1017,24 @@ MakePropertyValuePair(nsCSSPropertyID aP
 
   if (aDocument->GetStyleBackendType() == StyleBackendType::Servo) {
     nsCString name = nsCSSProps::GetStringValue(aProperty);
 
     NS_ConvertUTF16toUTF8 value(aStringValue);
 
     nsCString baseString;
     // FIXME this is using the wrong base uri (bug 1343919)
-    GeckoParserExtraData data(aDocument->GetDocumentURI(),
-                              aDocument->GetDocumentURI(),
-                              aDocument->NodePrincipal());
+    RefPtr<css::URLExtraData> data =
+      new css::URLExtraData(aDocument->GetDocumentURI(),
+                            aDocument->GetDocumentURI(),
+                            aDocument->NodePrincipal());
     aDocument->GetDocumentURI()->GetSpec(baseString);
 
     RefPtr<RawServoDeclarationBlock> servoDeclarationBlock =
-      Servo_ParseProperty(&name, &value, &baseString, &data).Consume();
+      Servo_ParseProperty(&name, &value, &baseString, data).Consume();
 
     if (servoDeclarationBlock) {
       result.mServoDeclarationBlock = servoDeclarationBlock.forget();
     }
     return result;
   }
 
   nsCSSValue value;
--- a/dom/animation/TimingParams.cpp
+++ b/dom/animation/TimingParams.cpp
@@ -113,21 +113,22 @@ TimingParams::ParseEasing(const nsAStrin
                           ErrorResult& aRv)
 {
   MOZ_ASSERT(aDocument);
 
   if (aDocument->IsStyledByServo()) {
     nsTimingFunction timingFunction;
     nsCString baseString;
     // FIXME this is using the wrong base uri (bug 1343919)
-    GeckoParserExtraData data(aDocument->GetDocumentURI(),
-                              aDocument->GetDocumentURI(),
-                              aDocument->NodePrincipal());
+    RefPtr<css::URLExtraData> data =
+      new css::URLExtraData(aDocument->GetDocumentURI(),
+                            aDocument->GetDocumentURI(),
+                            aDocument->NodePrincipal());
     aDocument->GetDocumentURI()->GetSpec(baseString);
-    if (!Servo_ParseEasing(&aEasing, &baseString, &data, &timingFunction)) {
+    if (!Servo_ParseEasing(&aEasing, &baseString, data, &timingFunction)) {
       aRv.ThrowTypeError<dom::MSG_INVALID_EASING_ERROR>(aEasing);
       return Nothing();
     }
 
     if (timingFunction.mType == nsTimingFunction::Type::Linear) {
       return Nothing();
     }
 
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -545,17 +545,17 @@ Element::WrapObject(JSContext *aCx, JS::
     bool ok = GetBindingURL(doc, getter_AddRefs(bindingURL));
     if (!ok) {
       dom::Throw(aCx, NS_ERROR_FAILURE);
       return nullptr;
     }
 
     if (bindingURL) {
       nsCOMPtr<nsIURI> uri = bindingURL->GetURI();
-      nsCOMPtr<nsIPrincipal> principal = bindingURL->mOriginPrincipal.get();
+      nsCOMPtr<nsIPrincipal> principal = bindingURL->mExtraData->GetPrincipal();
 
       // We have a binding that must be installed.
       bool dummy;
 
       nsXBLService* xblService = nsXBLService::GetInstance();
       if (!xblService) {
         dom::Throw(aCx, NS_ERROR_NOT_AVAILABLE);
         return nullptr;
--- a/dom/base/nsAttrValue.cpp
+++ b/dom/base/nsAttrValue.cpp
@@ -1682,18 +1682,18 @@ nsAttrValue::LoadImage(nsIDocument* aDoc
     NS_ASSERTION(!val.IsEmpty(),
                  "How did we end up with an empty string for eURL");
   }
 #endif
 
   MiscContainer* cont = GetMiscContainer();
   mozilla::css::URLValue* url = cont->mValue.mURL;
   mozilla::css::ImageValue* image =
-    new css::ImageValue(url->GetURI(), url->mString, url->mBaseURI,
-                        url->mReferrer, url->mOriginPrincipal, aDocument);
+    new css::ImageValue(url->GetURI(), url->mString,
+                        do_AddRef(url->mExtraData), aDocument);
 
   NS_ADDREF(image);
   cont->mValue.mImage = image;
   NS_RELEASE(url);
   cont->mType = eImage;
 }
 
 bool
@@ -1720,17 +1720,18 @@ nsAttrValue::ParseStyleAttribute(const n
       NS_ADDREF(cont);
       SetPtrValueAndType(cont, eOtherBase);
       return true;
     }
   }
 
   RefPtr<DeclarationBlock> decl;
   if (ownerDoc->GetStyleBackendType() == StyleBackendType::Servo) {
-    GeckoParserExtraData data(baseURI, docURI, aElement->NodePrincipal());
+    RefPtr<css::URLExtraData> data =
+      new css::URLExtraData(baseURI, docURI, aElement->NodePrincipal());
     decl = ServoDeclarationBlock::FromCssText(aString, data);
   } else {
     css::Loader* cssLoader = ownerDoc->CSSLoader();
     nsCSSParser cssParser(cssLoader);
     decl = cssParser.ParseStyleAttribute(aString, docURI, baseURI,
                                          aElement->NodePrincipal());
   }
   if (!decl) {
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -1230,21 +1230,22 @@ MappedAttrParser::ParseMappedAttrValue(n
     bool changed = false; // outparam for ParseProperty.
     if (mBackend == StyleBackendType::Gecko) {
       mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
                             mElement->NodePrincipal(), mDecl->AsGecko(), &changed, false, true);
     } else {
       NS_ConvertUTF16toUTF8 value(aMappedAttrValue);
       // FIXME (bug 1343964): Figure out a better solution for sending the base uri to servo
       nsCString baseString;
-      GeckoParserExtraData data(mBaseURI, mDocURI, mElement->NodePrincipal());
+      RefPtr<css::URLExtraData> data =
+        new css::URLExtraData(mBaseURI, mDocURI, mElement->NodePrincipal());
       mBaseURI->GetSpec(baseString);
       // FIXME (bug 1342559): Set SVG parsing mode for lengths
       changed = Servo_DeclarationBlock_SetPropertyById(mDecl->AsServo()->Raw(), propertyID,
-                                                       &value, false, &baseString, &data);
+                                                       &value, false, &baseString, data);
     }
 
     if (changed) {
       // The normal reporting of use counters by the nsCSSParser won't happen
       // since it doesn't have a sheet.
       if (nsCSSProps::IsShorthand(propertyID)) {
         CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subprop, propertyID,
                                              CSSEnabledState::eForAllContent) {
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -2470,17 +2470,17 @@ nsCSSFrameConstructor::ConstructDocEleme
 
     nsXBLService* xblService = nsXBLService::GetInstance();
     if (!xblService) {
       return nullptr;
     }
 
     RefPtr<nsXBLBinding> binding;
     rv = xblService->LoadBindings(aDocElement, display->mBinding->GetURI(),
-                                  display->mBinding->mOriginPrincipal,
+                                  display->mBinding->mExtraData->GetPrincipal(),
                                   getter_AddRefs(binding), &resolveStyle);
     if (NS_FAILED(rv) && rv != NS_ERROR_XBL_BLOCKED)
       return nullptr; // Binding will load asynchronously.
 
     if (binding) {
       // For backwards compat, keep firing the root's constructor
       // after all of its kids' constructors.  So tell the binding
       // manager about it right now.
@@ -5774,20 +5774,20 @@ nsCSSFrameConstructor::AddFrameConstruct
       nsXBLService* xblService = nsXBLService::GetInstance();
       if (!xblService)
         return;
 
       bool resolveStyle;
 
       nsAutoPtr<PendingBinding> newPendingBinding(new PendingBinding());
 
-      nsresult rv = xblService->LoadBindings(aContent, display->mBinding->GetURI(),
-                                             display->mBinding->mOriginPrincipal,
-                                             getter_AddRefs(newPendingBinding->mBinding),
-                                             &resolveStyle);
+      nsresult rv = xblService->LoadBindings(
+        aContent, display->mBinding->GetURI(),
+        display->mBinding->mExtraData->GetPrincipal(),
+        getter_AddRefs(newPendingBinding->mBinding), &resolveStyle);
       if (NS_FAILED(rv) && rv != NS_ERROR_XBL_BLOCKED)
         return;
 
       if (newPendingBinding->mBinding) {
         pendingBinding = newPendingBinding;
         // aState takes over owning newPendingBinding
         aState.AddPendingBinding(newPendingBinding.forget());
       }
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -1093,22 +1093,23 @@ FontFaceSet::FindOrCreateUserFontEntryFr
         switch (unit) {
 
         case eCSSUnit_Local_Font:
           val.GetStringValue(face->mLocalName);
           face->mSourceType = gfxFontFaceSrc::eSourceType_Local;
           face->mURI = nullptr;
           face->mFormatFlags = 0;
           break;
-        case eCSSUnit_URL:
+        case eCSSUnit_URL: {
           face->mSourceType = gfxFontFaceSrc::eSourceType_URL;
           face->mURI = val.GetURLValue();
-          face->mReferrer = val.GetURLStructValue()->mReferrer;
+          URLValue* url = val.GetURLStructValue();
+          face->mReferrer = url->mExtraData->GetReferrer();
           face->mReferrerPolicy = mDocument->GetReferrerPolicy();
-          face->mOriginPrincipal = val.GetURLStructValue()->mOriginPrincipal;
+          face->mOriginPrincipal = url->mExtraData->GetPrincipal();
           NS_ASSERTION(face->mOriginPrincipal, "null origin principal in @font-face rule");
 
           // agent and user stylesheets are treated slightly differently,
           // the same-site origin check and access control headers are
           // enforced against the sheet principal rather than the document
           // principal to allow user stylesheets to include @font-face rules
           face->mUseOriginPrincipal = (aSheetType == SheetType::User ||
                                        aSheetType == SheetType::Agent);
@@ -1142,16 +1143,17 @@ FontFaceSet::FindOrCreateUserFontEntryFr
           }
           if (!face->mURI) {
             // if URI not valid, omit from src array
             srcArray.RemoveElementAt(srcArray.Length() - 1);
             NS_WARNING("null url in @font-face rule");
             continue;
           }
           break;
+        }
         default:
           NS_ASSERTION(unit == eCSSUnit_Local_Font || unit == eCSSUnit_URL,
                        "strange unit type in font-face src array");
           break;
         }
        }
     } else {
       NS_ASSERTION(unit == eCSSUnit_Null, "@font-face src has unexpected unit");
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -25,31 +25,27 @@ SERVO_BINDING_FUNC(Servo_Element_ClearDa
 SERVO_BINDING_FUNC(Servo_StyleSheet_Empty, RawServoStyleSheetStrong,
                    mozilla::css::SheetParsingMode parsing_mode)
 SERVO_BINDING_FUNC(Servo_StyleSheet_FromUTF8Bytes, RawServoStyleSheetStrong,
                    mozilla::css::Loader* loader,
                    mozilla::ServoStyleSheet* gecko_stylesheet,
                    const nsACString* data,
                    mozilla::css::SheetParsingMode parsing_mode,
                    const nsACString* base_url,
-                   ThreadSafeURIHolder* base,
-                   ThreadSafeURIHolder* referrer,
-                   ThreadSafePrincipalHolder* principal)
+                   RawGeckoURLExtraData* extra_data)
 SERVO_BINDING_FUNC(Servo_ImportRule_GetSheet,
                    RawServoStyleSheetStrong,
                    const RawServoImportRuleBorrowed import_rule)
 SERVO_BINDING_FUNC(Servo_StyleSheet_ClearAndUpdate,
                    void,
                    RawServoStyleSheetBorrowed stylesheet,
                    mozilla::css::Loader* loader,
                    mozilla::ServoStyleSheet* gecko_stylesheet,
                    const nsACString* data,
-                   ThreadSafeURIHolder* base,
-                   ThreadSafeURIHolder* referrer,
-                   ThreadSafePrincipalHolder* principal)
+                   RawGeckoURLExtraData* extra_data)
 SERVO_BINDING_FUNC(Servo_StyleSheet_HasRules, bool,
                    RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSheet_GetRules, ServoCssRulesStrong,
                    RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSet_Init, RawServoStyleSetOwned, RawGeckoPresContextOwned pres_context)
 SERVO_BINDING_FUNC(Servo_StyleSet_RebuildData, void,
                    RawServoStyleSetBorrowed set)
 SERVO_BINDING_FUNC(Servo_StyleSet_Drop, void, RawServoStyleSetOwned set)
@@ -117,21 +113,21 @@ SERVO_BINDING_FUNC(Servo_NamespaceRule_G
 SERVO_BINDING_FUNC(Servo_NamespaceRule_GetURI, nsIAtom*,
                    RawServoNamespaceRuleBorrowed rule)
 
 // Animations API
 SERVO_BINDING_FUNC(Servo_ParseProperty,
                    RawServoDeclarationBlockStrong,
                    const nsACString* property, const nsACString* value,
                    const nsACString* base,
-                   const GeckoParserExtraData* data)
+                   RawGeckoURLExtraData* data)
 SERVO_BINDING_FUNC(Servo_ParseEasing, bool,
                    const nsAString* easing,
                    const nsACString* base,
-                   const GeckoParserExtraData* data,
+                   RawGeckoURLExtraData* data,
                    nsTimingFunctionBorrowedMut output)
 SERVO_BINDING_FUNC(Servo_GetComputedKeyframeValues, void,
                    RawGeckoKeyframeListBorrowed keyframes,
                    ServoComputedValuesBorrowed style,
                    ServoComputedValuesBorrowedOrNull parent_style,
                    RawServoStyleSetBorrowed set,
                    RawGeckoComputedKeyframeValuesListBorrowedMut result)
 SERVO_BINDING_FUNC(Servo_AnimationValueMap_Push, void,
@@ -157,17 +153,17 @@ SERVO_BINDING_FUNC(Servo_AnimationValue_
 SERVO_BINDING_FUNC(Servo_AnimationValue_DeepEqual, bool,
                    RawServoAnimationValueBorrowed,
                    RawServoAnimationValueBorrowed)
 
 // Style attribute
 SERVO_BINDING_FUNC(Servo_ParseStyleAttribute, RawServoDeclarationBlockStrong,
                    const nsACString* data,
                    const nsACString* base,
-                   const GeckoParserExtraData* extraData)
+                   RawGeckoURLExtraData* extra_data)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_CreateEmpty,
                    RawServoDeclarationBlockStrong)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_Clone, RawServoDeclarationBlockStrong,
                    RawServoDeclarationBlockBorrowed declarations)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_Equals, bool,
                    RawServoDeclarationBlockBorrowed a,
                    RawServoDeclarationBlockBorrowed b)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_GetCssText, void,
@@ -190,23 +186,23 @@ SERVO_BINDING_FUNC(Servo_DeclarationBloc
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_GetPropertyIsImportant, bool,
                    RawServoDeclarationBlockBorrowed declarations,
                    const nsACString* property)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_SetProperty, bool,
                    RawServoDeclarationBlockBorrowed declarations,
                    const nsACString* property,
                    const nsACString* value, bool is_important,
                    const nsACString* base,
-                   const GeckoParserExtraData* data)
+                   RawGeckoURLExtraData* data)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_SetPropertyById, bool,
                    RawServoDeclarationBlockBorrowed declarations,
                    nsCSSPropertyID property,
                    const nsACString* value, bool is_important,
                    const nsACString* base,
-                   const GeckoParserExtraData* data)
+                   RawGeckoURLExtraData* data)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_RemoveProperty, void,
                    RawServoDeclarationBlockBorrowed declarations,
                    const nsACString* property)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_RemovePropertyById, void,
                    RawServoDeclarationBlockBorrowed declarations,
                    nsCSSPropertyID property)
 
 // presentation attributes
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -17,16 +17,19 @@ struct RawServoStyleSet;
 
 #define SERVO_ARC_TYPE(name_, type_) struct type_;
 #include "mozilla/ServoArcTypeList.h"
 #undef SERVO_ARC_TYPE
 
 namespace mozilla {
   class ServoElementSnapshot;
   struct StyleAnimation;
+namespace css {
+struct URLExtraData;
+} // namespace css
 namespace dom {
 class Element;
 class StyleChildrenIterator;
 } // namespace dom
 struct Keyframe;
 struct PropertyStyleAnimationValuePair;
 using ComputedKeyframeValues = nsTArray<PropertyStyleAnimationValuePair>;
 } // namespace mozilla
@@ -40,16 +43,17 @@ struct nsTimingFunction;
 
 using mozilla::dom::StyleChildrenIterator;
 using mozilla::ServoElementSnapshot;
 
 typedef nsINode RawGeckoNode;
 typedef mozilla::dom::Element RawGeckoElement;
 typedef nsIDocument RawGeckoDocument;
 typedef nsPresContext RawGeckoPresContext;
+typedef mozilla::css::URLExtraData RawGeckoURLExtraData;
 typedef nsTArray<mozilla::Keyframe> RawGeckoKeyframeList;
 typedef nsTArray<mozilla::ComputedKeyframeValues> RawGeckoComputedKeyframeValuesList;
 typedef nsTArray<mozilla::PropertyStyleAnimationValuePair> RawGeckoAnimationValueList;
 typedef nsStyleAutoArray<mozilla::StyleAnimation> RawGeckoStyleAnimationList;
 typedef nsTArray<nsFontFaceRuleContainer> RawGeckoFontFaceRuleList;
 
 // We have these helper types so that we can directly generate
 // things like &T or Borrowed<T> on the Rust side in the function, providing
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -867,52 +867,37 @@ Gecko_SetListStyleType(nsStyleList* styl
 }
 
 void
 Gecko_CopyListStyleTypeFrom(nsStyleList* dst, const nsStyleList* src)
 {
   dst->SetCounterStyle(src->GetCounterStyle());
 }
 
-NS_IMPL_HOLDER_FFI_REFCOUNTING(nsIPrincipal, Principal)
-NS_IMPL_HOLDER_FFI_REFCOUNTING(nsIURI, URI)
-
 already_AddRefed<css::URLValue>
 ServoBundledURI::IntoCssUrl()
 {
   if (!mURLString) {
     return nullptr;
   }
 
-  MOZ_ASSERT(mBaseURI);
-  MOZ_ASSERT(mReferrer);
-  MOZ_ASSERT(mPrincipal);
+  MOZ_ASSERT(mExtraData->GetReferrer());
+  MOZ_ASSERT(mExtraData->GetPrincipal());
 
   nsString url;
   nsDependentCSubstring urlString(reinterpret_cast<const char*>(mURLString),
                                   mURLStringLength);
   AppendUTF8toUTF16(urlString, url);
   RefPtr<nsStringBuffer> urlBuffer = nsCSSValue::BufferFromString(url);
 
-  RefPtr<css::URLValue> urlValue = new css::URLValue(urlBuffer,
-                                                     do_AddRef(mBaseURI),
-                                                     do_AddRef(mReferrer),
-                                                     do_AddRef(mPrincipal));
+  RefPtr<css::URLValue> urlValue =
+    new css::URLValue(urlBuffer, do_AddRef(mExtraData));
   return urlValue.forget();
 }
 
-GeckoParserExtraData::GeckoParserExtraData(nsIURI* aBaseURI,
-                                           nsIURI* aReferrer,
-                                           nsIPrincipal* aPrincipal)
-    : mBaseURI(new ThreadSafeURIHolder(aBaseURI)),
-      mReferrer(new ThreadSafeURIHolder(aReferrer)),
-      mPrincipal(new ThreadSafePrincipalHolder(aPrincipal))
-{
-}
-
 void
 Gecko_SetNullImageValue(nsStyleImage* aImage)
 {
   MOZ_ASSERT(aImage);
   aImage->SetNull();
 }
 
 void
@@ -922,29 +907,27 @@ Gecko_SetGradientImageValue(nsStyleImage
   aImage->SetGradientData(aGradient);
 }
 
 static already_AddRefed<nsStyleImageRequest>
 CreateStyleImageRequest(nsStyleImageRequest::Mode aModeFlags,
                         ServoBundledURI aURI)
 {
   MOZ_ASSERT(aURI.mURLString);
-  MOZ_ASSERT(aURI.mBaseURI);
-  MOZ_ASSERT(aURI.mReferrer);
-  MOZ_ASSERT(aURI.mPrincipal);
+  MOZ_ASSERT(aURI.mExtraData->GetReferrer());
+  MOZ_ASSERT(aURI.mExtraData->GetPrincipal());
 
   nsString url;
   nsDependentCSubstring urlString(reinterpret_cast<const char*>(aURI.mURLString),
                                   aURI.mURLStringLength);
   AppendUTF8toUTF16(urlString, url);
   RefPtr<nsStringBuffer> urlBuffer = nsCSSValue::BufferFromString(url);
 
   RefPtr<nsStyleImageRequest> req =
-    new nsStyleImageRequest(aModeFlags, urlBuffer, do_AddRef(aURI.mBaseURI),
-                            do_AddRef(aURI.mReferrer), do_AddRef(aURI.mPrincipal));
+    new nsStyleImageRequest(aModeFlags, urlBuffer, do_AddRef(aURI.mExtraData));
   return req.forget();
 }
 
 void
 Gecko_SetUrlImageValue(nsStyleImage* aImage, ServoBundledURI aURI)
 {
   RefPtr<nsStyleImageRequest> req =
     CreateStyleImageRequest(nsStyleImageRequest::Mode::Track, aURI);
@@ -1315,16 +1298,18 @@ css::URLValue*
 Gecko_NewURLValue(ServoBundledURI aURI)
 {
   RefPtr<css::URLValue> url = aURI.IntoCssUrl();
   return url.forget().take();
 }
 
 NS_IMPL_THREADSAFE_FFI_REFCOUNTING(css::URLValue, CSSURLValue);
 
+NS_IMPL_THREADSAFE_FFI_REFCOUNTING(css::URLExtraData, URLExtraData);
+
 NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsStyleCoord::Calc, Calc);
 
 nsCSSShadowArray*
 Gecko_NewCSSShadowArray(uint32_t aLen)
 {
   RefPtr<nsCSSShadowArray> arr = new(aLen) nsCSSShadowArray(aLen);
   return arr.forget().take();
 }
@@ -1547,43 +1532,44 @@ Gecko_nsStyleFont_GetBaseSize(const nsSt
 {
   return aPresContext->GetDefaultFont(aFont->mGenericID, aFont->mLanguage)->size;
 }
 
 void
 Gecko_LoadStyleSheet(css::Loader* aLoader,
                      ServoStyleSheet* aParent,
                      RawServoImportRuleBorrowed aImportRule,
-                     nsIURI* aBaseURI,
+                     RawGeckoURLExtraData* aBaseURLData,
                      const uint8_t* aURLString,
                      uint32_t aURLStringLength,
                      const uint8_t* aMediaString,
                      uint32_t aMediaStringLength)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aLoader, "Should've catched this before");
   MOZ_ASSERT(aParent, "Only used for @import, so parent should exist!");
   MOZ_ASSERT(aURLString, "Invalid URLs shouldn't be loaded!");
-  MOZ_ASSERT(aBaseURI, "Need a base URI");
+  MOZ_ASSERT(aBaseURLData, "Need base URL data");
   RefPtr<nsMediaList> media = new nsMediaList();
   if (aMediaStringLength) {
     MOZ_ASSERT(aMediaString);
     // TODO(emilio, bug 1325878): This is not great, though this is going away
     // soon anyway, when we can have a Servo-backed nsMediaList.
     nsDependentCSubstring medium(reinterpret_cast<const char*>(aMediaString),
                                  aMediaStringLength);
     nsCSSParser mediumParser(aLoader);
     mediumParser.ParseMediaList(
         NS_ConvertUTF8toUTF16(medium), nullptr, 0, media);
   }
 
   nsDependentCSubstring urlSpec(reinterpret_cast<const char*>(aURLString),
                                 aURLStringLength);
   nsCOMPtr<nsIURI> uri;
-  nsresult rv = NS_NewURI(getter_AddRefs(uri), urlSpec, nullptr, aBaseURI);
+  nsresult rv = NS_NewURI(getter_AddRefs(uri), urlSpec, nullptr,
+                          aBaseURLData->BaseURI());
 
   if (NS_FAILED(rv)) {
     // Servo and Gecko have different ideas of what a valid URL is, so we might
     // get in here with a URL string that NS_NewURI can't handle.  If so,
     // silently do nothing.  Eventually we should be able to assert that the
     // NS_NewURI succeeds, here.
     return;
   }
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -59,69 +59,41 @@ struct nsStyleDisplay;
   static_assert(class_::HasThreadSafeRefCnt::value,                           \
                 "NS_DECL_THREADSAFE_FFI_REFCOUNTING can only be used with "   \
                 "classes that have thread-safe refcounting");                 \
   void Gecko_AddRef##name_##ArbitraryThread(class_* aPtr)                     \
   { NS_ADDREF(aPtr); }                                                        \
   void Gecko_Release##name_##ArbitraryThread(class_* aPtr)                    \
   { NS_RELEASE(aPtr); }
 
-#define NS_DECL_HOLDER_FFI_REFCOUNTING(class_, name_)                         \
-  typedef nsMainThreadPtrHolder<class_> ThreadSafe##name_##Holder;            \
-  void Gecko_AddRef##name_##ArbitraryThread(ThreadSafe##name_##Holder* aPtr); \
-  void Gecko_Release##name_##ArbitraryThread(ThreadSafe##name_##Holder* aPtr);
-#define NS_IMPL_HOLDER_FFI_REFCOUNTING(class_, name_)                         \
-  void Gecko_AddRef##name_##ArbitraryThread(ThreadSafe##name_##Holder* aPtr)  \
-  { NS_ADDREF(aPtr); }                                                        \
-  void Gecko_Release##name_##ArbitraryThread(ThreadSafe##name_##Holder* aPtr) \
-  { NS_RELEASE(aPtr); }                                                       \
-
 #define NS_DECL_FFI_REFCOUNTING(class_, name_)  \
   void Gecko_##name_##_AddRef(class_* aPtr);    \
   void Gecko_##name_##_Release(class_* aPtr);
 #define NS_IMPL_FFI_REFCOUNTING(class_, name_)                    \
   void Gecko_##name_##_AddRef(class_* aPtr) { NS_ADDREF(aPtr); }  \
   void Gecko_##name_##_Release(class_* aPtr) { NS_RELEASE(aPtr); }
 
-
 #define DEFINE_ARRAY_TYPE_FOR(type_)                                \
   struct nsTArrayBorrowed_##type_ {                                 \
     nsTArray<type_>* mArray;                                        \
     MOZ_IMPLICIT nsTArrayBorrowed_##type_(nsTArray<type_>* aArray)  \
       : mArray(aArray) {}                                           \
   }
 DEFINE_ARRAY_TYPE_FOR(uintptr_t);
 #undef DEFINE_ARRAY_TYPE_FOR
 
 extern "C" {
 
-// Object refcounting.
-NS_DECL_HOLDER_FFI_REFCOUNTING(nsIPrincipal, Principal)
-NS_DECL_HOLDER_FFI_REFCOUNTING(nsIURI, URI)
-
 class ServoBundledURI
 {
 public:
   already_AddRefed<mozilla::css::URLValue> IntoCssUrl();
   const uint8_t* mURLString;
   uint32_t mURLStringLength;
-  ThreadSafeURIHolder* mBaseURI;
-  ThreadSafeURIHolder* mReferrer;
-  ThreadSafePrincipalHolder* mPrincipal;
-};
-
-class GeckoParserExtraData
-{
-public:
-  GeckoParserExtraData(nsIURI* aBaseURI,
-                       nsIURI* aReferrer,
-                       nsIPrincipal* aPrincipal);
-  RefPtr<ThreadSafeURIHolder> mBaseURI;
-  RefPtr<ThreadSafeURIHolder> mReferrer;
-  RefPtr<ThreadSafePrincipalHolder> mPrincipal;
+  mozilla::css::URLExtraData* mExtraData;
 };
 
 // DOM Traversal.
 uint32_t Gecko_ChildrenCount(RawGeckoNodeBorrowed node);
 bool Gecko_NodeIsElement(RawGeckoNodeBorrowed node);
 bool Gecko_IsInDocument(RawGeckoNodeBorrowed node);
 bool Gecko_FlattenedTreeParentIsParent(RawGeckoNodeBorrowed node);
 bool Gecko_IsSignificantChild(RawGeckoNodeBorrowed node,
@@ -135,17 +107,17 @@ RawGeckoNodeBorrowedOrNull Gecko_GetNext
 RawGeckoElementBorrowedOrNull Gecko_GetFirstChildElement(RawGeckoElementBorrowed element);
 RawGeckoElementBorrowedOrNull Gecko_GetLastChildElement(RawGeckoElementBorrowed element);
 RawGeckoElementBorrowedOrNull Gecko_GetPrevSiblingElement(RawGeckoElementBorrowed element);
 RawGeckoElementBorrowedOrNull Gecko_GetNextSiblingElement(RawGeckoElementBorrowed element);
 RawGeckoElementBorrowedOrNull Gecko_GetDocumentElement(RawGeckoDocumentBorrowed document);
 void Gecko_LoadStyleSheet(mozilla::css::Loader* loader,
                           mozilla::ServoStyleSheet* parent,
                           RawServoImportRuleBorrowed import_rule,
-                          nsIURI* base_uri,
+                          RawGeckoURLExtraData* base_url_data,
                           const uint8_t* url_bytes,
                           uint32_t url_length,
                           const uint8_t* media_bytes,
                           uint32_t media_length);
 
 // By default, Servo walks the DOM by traversing the siblings of the DOM-view
 // first child. This generally works, but misses anonymous children, which we
 // want to traverse during styling. To support these cases, we create an
@@ -341,16 +313,17 @@ void Gecko_nsStyleSVGPaint_CopyFrom(nsSt
 void Gecko_nsStyleSVGPaint_SetURLValue(nsStyleSVGPaint* paint, ServoBundledURI uri);
 void Gecko_nsStyleSVGPaint_Reset(nsStyleSVGPaint* paint);
 
 void Gecko_nsStyleSVG_SetDashArrayLength(nsStyleSVG* svg, uint32_t len);
 void Gecko_nsStyleSVG_CopyDashArray(nsStyleSVG* dst, const nsStyleSVG* src);
 
 mozilla::css::URLValue* Gecko_NewURLValue(ServoBundledURI uri);
 NS_DECL_THREADSAFE_FFI_REFCOUNTING(mozilla::css::URLValue, CSSURLValue);
+NS_DECL_THREADSAFE_FFI_REFCOUNTING(RawGeckoURLExtraData, URLExtraData);
 
 void Gecko_FillAllBackgroundLists(nsStyleImageLayers* layers, uint32_t max_len);
 void Gecko_FillAllMaskLists(nsStyleImageLayers* layers, uint32_t max_len);
 NS_DECL_THREADSAFE_FFI_REFCOUNTING(nsStyleCoord::Calc, Calc);
 
 nsCSSShadowArray* Gecko_NewCSSShadowArray(uint32_t len);
 NS_DECL_THREADSAFE_FFI_REFCOUNTING(nsCSSShadowArray, CSSShadowArray);
 
--- a/layout/style/ServoDeclarationBlock.cpp
+++ b/layout/style/ServoDeclarationBlock.cpp
@@ -8,24 +8,24 @@
 #include "mozilla/ServoBindings.h"
 
 #include "nsCSSProps.h"
 
 namespace mozilla {
 
 /* static */ already_AddRefed<ServoDeclarationBlock>
 ServoDeclarationBlock::FromCssText(const nsAString& aCssText,
-                                   const GeckoParserExtraData& aExtraData)
+                                   css::URLExtraData* aExtraData)
 {
   NS_ConvertUTF16toUTF8 value(aCssText);
   nsCString baseString;
   // FIXME (bug 1343964): Figure out a better solution for sending the base uri to servo
-  aExtraData.mBaseURI->get()->GetSpec(baseString);
+  aExtraData->BaseURI()->GetSpec(baseString);
   RefPtr<RawServoDeclarationBlock>
-    raw = Servo_ParseStyleAttribute(&value, &baseString, &aExtraData).Consume();
+    raw = Servo_ParseStyleAttribute(&value, &baseString, aExtraData).Consume();
   RefPtr<ServoDeclarationBlock> decl = new ServoDeclarationBlock(raw.forget());
   return decl.forget();
 }
 
 void
 ServoDeclarationBlock::GetPropertyValue(const nsAString& aProperty,
                                         nsAString& aValue) const
 {
--- a/layout/style/ServoDeclarationBlock.h
+++ b/layout/style/ServoDeclarationBlock.h
@@ -23,18 +23,17 @@ public:
 
   ServoDeclarationBlock(const ServoDeclarationBlock& aCopy)
     : DeclarationBlock(aCopy)
     , mRaw(Servo_DeclarationBlock_Clone(aCopy.mRaw).Consume()) {}
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ServoDeclarationBlock)
 
   static already_AddRefed<ServoDeclarationBlock>
-  FromCssText(const nsAString& aCssText,
-              const GeckoParserExtraData& aExtraData);
+  FromCssText(const nsAString& aCssText, css::URLExtraData* aExtraData);
 
   RawServoDeclarationBlock* Raw() const { return mRaw; }
   RawServoDeclarationBlock* const* RefRaw() const {
     static_assert(sizeof(RefPtr<RawServoDeclarationBlock>) ==
                   sizeof(RawServoDeclarationBlock*),
                   "RefPtr should just be a pointer");
     return reinterpret_cast<RawServoDeclarationBlock* const*>(&mRaw);
   }
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -82,34 +82,31 @@ ServoStyleSheet::HasRules() const
 nsresult
 ServoStyleSheet::ParseSheet(css::Loader* aLoader,
                             const nsAString& aInput,
                             nsIURI* aSheetURI,
                             nsIURI* aBaseURI,
                             nsIPrincipal* aSheetPrincipal,
                             uint32_t aLineNumber)
 {
-  RefPtr<ThreadSafeURIHolder> base = new ThreadSafeURIHolder(aBaseURI);
-  RefPtr<ThreadSafeURIHolder> referrer = new ThreadSafeURIHolder(aSheetURI);
-  RefPtr<ThreadSafePrincipalHolder> principal =
-    new ThreadSafePrincipalHolder(aSheetPrincipal);
+  RefPtr<css::URLExtraData> extraData =
+    new css::URLExtraData(aBaseURI, aSheetURI, aSheetPrincipal);
 
   nsCString baseString;
   nsresult rv = aBaseURI->GetSpec(baseString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ConvertUTF16toUTF8 input(aInput);
   if (!Inner()->mSheet) {
     Inner()->mSheet =
       Servo_StyleSheet_FromUTF8Bytes(aLoader, this, &input, mParsingMode,
-                                     &baseString, base, referrer,
-                                     principal).Consume();
+                                     &baseString, extraData).Consume();
   } else {
-    Servo_StyleSheet_ClearAndUpdate(Inner()->mSheet, aLoader, this, &input, base,
-                                    referrer, principal);
+    Servo_StyleSheet_ClearAndUpdate(Inner()->mSheet, aLoader,
+                                    this, &input, extraData);
   }
 
   return NS_OK;
 }
 
 void
 ServoStyleSheet::LoadFailed()
 {
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -896,19 +896,17 @@ nsCSSValue::GetCalcValue() const
 }
 
 void nsCSSValue::StartImageLoad(nsIDocument* aDocument) const
 {
   MOZ_ASSERT(eCSSUnit_URL == mUnit, "Not a URL value!");
   mozilla::css::ImageValue* image =
     new mozilla::css::ImageValue(mValue.mURL->GetURI(),
                                  mValue.mURL->mString,
-                                 mValue.mURL->mBaseURI,
-                                 mValue.mURL->mReferrer,
-                                 mValue.mURL->mOriginPrincipal,
+                                 do_AddRef(mValue.mURL->mExtraData),
                                  aDocument);
 
   nsCSSValue* writable = const_cast<nsCSSValue*>(this);
   writable->SetImageValue(image);
 }
 
 nscolor nsCSSValue::GetColorValue() const
 {
@@ -2780,103 +2778,102 @@ nsCSSValue::Array::SizeOfIncludingThis(m
 {
   size_t n = aMallocSizeOf(this);
   for (size_t i = 0; i < mCount; i++) {
     n += mArray[i].SizeOfExcludingThis(aMallocSizeOf);
   }
   return n;
 }
 
+css::URLExtraData::~URLExtraData()
+{
+  if (!NS_IsMainThread()) {
+    NS_ReleaseOnMainThread(mBaseURI.forget());
+    NS_ReleaseOnMainThread(mReferrer.forget());
+    NS_ReleaseOnMainThread(mPrincipal.forget());
+  }
+}
+
 css::URLValueData::URLValueData(already_AddRefed<PtrHolder<nsIURI>> aURI,
                                 nsStringBuffer* aString,
-                                already_AddRefed<PtrHolder<nsIURI>> aBaseURI,
-                                already_AddRefed<PtrHolder<nsIURI>> aReferrer,
-                                already_AddRefed<PtrHolder<nsIPrincipal>>
-                                  aOriginPrincipal)
+                                already_AddRefed<URLExtraData> aExtraData)
   : mURI(Move(aURI))
-  , mBaseURI(Move(aBaseURI))
   , mString(aString)
-  , mReferrer(Move(aReferrer))
-  , mOriginPrincipal(Move(aOriginPrincipal))
+  , mExtraData(Move(aExtraData))
   , mURIResolved(true)
   , mIsLocalRef(IsLocalRefURL(aString))
 {
   MOZ_ASSERT(mString);
-  MOZ_ASSERT(mBaseURI);
-  MOZ_ASSERT(mOriginPrincipal);
+  MOZ_ASSERT(mExtraData);
+  MOZ_ASSERT(mExtraData->GetPrincipal());
 }
 
 css::URLValueData::URLValueData(nsStringBuffer* aString,
-                                already_AddRefed<PtrHolder<nsIURI>> aBaseURI,
-                                already_AddRefed<PtrHolder<nsIURI>> aReferrer,
-                                already_AddRefed<PtrHolder<nsIPrincipal>>
-                                  aOriginPrincipal)
-  : mBaseURI(Move(aBaseURI))
-  , mString(aString)
-  , mReferrer(Move(aReferrer))
-  , mOriginPrincipal(Move(aOriginPrincipal))
+                                already_AddRefed<URLExtraData> aExtraData)
+  : mString(aString)
+  , mExtraData(Move(aExtraData))
   , mURIResolved(false)
   , mIsLocalRef(IsLocalRefURL(aString))
 {
   MOZ_ASSERT(aString);
-  MOZ_ASSERT(mBaseURI);
-  MOZ_ASSERT(mOriginPrincipal);
+  MOZ_ASSERT(mExtraData);
+  MOZ_ASSERT(mExtraData->GetPrincipal());
 }
 
 bool
 css::URLValueData::Equals(const URLValueData& aOther) const
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   bool eq;
   // Cast away const so we can call nsIPrincipal::Equals.
-  auto& self = *const_cast<URLValueData*>(this);
-  auto& other = const_cast<URLValueData&>(aOther);
+  const URLExtraData* self = mExtraData;
+  const URLExtraData* other = aOther.mExtraData;
   return NS_strcmp(nsCSSValue::GetBufferValue(mString),
                    nsCSSValue::GetBufferValue(aOther.mString)) == 0 &&
           (GetURI() == aOther.GetURI() || // handles null == null
            (mURI && aOther.mURI &&
             NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) &&
             eq)) &&
-          (mBaseURI == aOther.mBaseURI ||
-           (NS_SUCCEEDED(self.mBaseURI.get()->Equals(other.mBaseURI.get(), &eq)) &&
+          (self->BaseURI() == other->BaseURI() ||
+           (NS_SUCCEEDED(self->BaseURI()->Equals(other->BaseURI(), &eq)) &&
             eq)) &&
-          (mOriginPrincipal == aOther.mOriginPrincipal ||
-           self.mOriginPrincipal.get()->Equals(other.mOriginPrincipal.get())) &&
+          (self->GetPrincipal() == other->GetPrincipal() ||
+           self->GetPrincipal()->Equals(other->GetPrincipal())) &&
           mIsLocalRef == aOther.mIsLocalRef;
 }
 
 bool
 css::URLValueData::DefinitelyEqualURIs(const URLValueData& aOther) const
 {
-  return mBaseURI == aOther.mBaseURI &&
+  return mExtraData->BaseURI() == aOther.mExtraData->BaseURI() &&
          (mString == aOther.mString ||
           NS_strcmp(nsCSSValue::GetBufferValue(mString),
                     nsCSSValue::GetBufferValue(aOther.mString)) == 0);
 }
 
 bool
 css::URLValueData::DefinitelyEqualURIsAndPrincipal(
     const URLValueData& aOther) const
 {
-  return mOriginPrincipal == aOther.mOriginPrincipal &&
+  return mExtraData->GetPrincipal() == aOther.mExtraData->GetPrincipal() &&
          DefinitelyEqualURIs(aOther);
 }
 
 nsIURI*
 css::URLValueData::GetURI() const
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mURIResolved) {
     MOZ_ASSERT(!mURI);
     nsCOMPtr<nsIURI> newURI;
     NS_NewURI(getter_AddRefs(newURI),
               NS_ConvertUTF16toUTF8(nsCSSValue::GetBufferValue(mString)),
-              nullptr, const_cast<nsIURI*>(mBaseURI.get()));
+              nullptr, mExtraData->BaseURI());
     mURI = new PtrHolder<nsIURI>(newURI.forget());
     mURIResolved = true;
   }
 
   return mURI;
 }
 
 bool
@@ -2967,38 +2964,34 @@ size_t
 css::URLValueData::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t n = 0;
   n += mString->SizeOfIncludingThisIfUnshared(aMallocSizeOf);
 
   // Measurement of the following members may be added later if DMD finds it
   // is worthwhile:
   // - mURI
-  // - mReferrer
-  // - mOriginPrincipal
+  // - mExtraData
   return n;
 }
 
 URLValue::URLValue(nsStringBuffer* aString, nsIURI* aBaseURI, nsIURI* aReferrer,
                    nsIPrincipal* aOriginPrincipal)
-  : URLValueData(aString,
-                 do_AddRef(new PtrHolder<nsIURI>(aBaseURI)),
-                 do_AddRef(new PtrHolder<nsIURI>(aReferrer)),
-                 do_AddRef(new PtrHolder<nsIPrincipal>(aOriginPrincipal)))
+  : URLValueData(aString, do_AddRef(new URLExtraData(aBaseURI, aReferrer,
+                                                     aOriginPrincipal)))
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 URLValue::URLValue(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aBaseURI,
                    nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal)
   : URLValueData(do_AddRef(new PtrHolder<nsIURI>(aURI)),
                  aString,
-                 do_AddRef(new PtrHolder<nsIURI>(aBaseURI)),
-                 do_AddRef(new PtrHolder<nsIURI>(aReferrer)),
-                 do_AddRef(new PtrHolder<nsIPrincipal>(aOriginPrincipal)))
+                 do_AddRef(new URLExtraData(aBaseURI, aReferrer,
+                                            aOriginPrincipal)))
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 size_t
 css::URLValue::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   // Only measure it if it's unshared, to avoid double-counting.
@@ -3006,35 +2999,27 @@ css::URLValue::SizeOfIncludingThis(mozil
   if (mRefCnt <= 1) {
     n += aMallocSizeOf(this);
     n += URLValueData::SizeOfExcludingThis(aMallocSizeOf);
   }
   return n;
 }
 
 css::ImageValue::ImageValue(nsIURI* aURI, nsStringBuffer* aString,
-                            nsIURI* aBaseURI, nsIURI* aReferrer,
-                            nsIPrincipal* aOriginPrincipal,
+                            already_AddRefed<URLExtraData> aExtraData,
                             nsIDocument* aDocument)
   : URLValueData(do_AddRef(new PtrHolder<nsIURI>(aURI)),
-                 aString,
-                 do_AddRef(new PtrHolder<nsIURI>(aBaseURI, false)),
-                 do_AddRef(new PtrHolder<nsIURI>(aReferrer)),
-                 do_AddRef(new PtrHolder<nsIPrincipal>(aOriginPrincipal)))
+                 aString, Move(aExtraData))
 {
   Initialize(aDocument);
 }
 
-css::ImageValue::ImageValue(
-    nsStringBuffer* aString,
-    already_AddRefed<PtrHolder<nsIURI>> aBaseURI,
-    already_AddRefed<PtrHolder<nsIURI>> aReferrer,
-    already_AddRefed<PtrHolder<nsIPrincipal>> aOriginPrincipal)
-  : URLValueData(aString, Move(aBaseURI), Move(aReferrer),
-                 Move(aOriginPrincipal))
+css::ImageValue::ImageValue(nsStringBuffer* aString,
+                            already_AddRefed<URLExtraData> aExtraData)
+  : URLValueData(aString, Move(aExtraData))
 {
 }
 
 void
 css::ImageValue::Initialize(nsIDocument* aDocument)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mInitialized);
@@ -3042,18 +3027,19 @@ css::ImageValue::Initialize(nsIDocument*
   // NB: If aDocument is not the original document, we may not be able to load
   // images from aDocument.  Instead we do the image load from the original doc
   // and clone it to aDocument.
   nsIDocument* loadingDoc = aDocument->GetOriginalDocument();
   if (!loadingDoc) {
     loadingDoc = aDocument;
   }
 
-  loadingDoc->StyleImageLoader()->LoadImage(GetURI(), mOriginPrincipal,
-                                            mReferrer, this);
+  loadingDoc->StyleImageLoader()->LoadImage(GetURI(),
+                                            mExtraData->GetPrincipal(),
+                                            mExtraData->GetReferrer(), this);
 
   if (loadingDoc != aDocument) {
     aDocument->StyleImageLoader()->MaybeRegisterCSSImage(this);
   }
 
 #ifdef DEBUG
   mInitialized = true;
 #endif
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -88,37 +88,64 @@ class CSSStyleSheet;
       dest->member_ = clm_clone;                                               \
       dest = clm_clone;                                                        \
     }                                                                          \
   }
 
 namespace mozilla {
 namespace css {
 
+struct URLExtraData
+{
+  URLExtraData(already_AddRefed<nsIURI> aBaseURI,
+               already_AddRefed<nsIURI> aReferrer,
+               already_AddRefed<nsIPrincipal> aPrincipal)
+    : mBaseURI(Move(aBaseURI))
+    , mReferrer(Move(aReferrer))
+    , mPrincipal(Move(aPrincipal))
+  {
+    MOZ_ASSERT(mBaseURI);
+  }
+
+  URLExtraData(nsIURI* aBaseURI, nsIURI* aReferrer, nsIPrincipal* aPrincipal)
+    : URLExtraData(do_AddRef(aBaseURI),
+                   do_AddRef(aReferrer),
+                   do_AddRef(aPrincipal)) {}
+
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(URLExtraData)
+
+  nsIURI* BaseURI() const { return mBaseURI; }
+  nsIURI* GetReferrer() const { return mReferrer; }
+  nsIPrincipal* GetPrincipal() const { return mPrincipal; }
+
+private:
+  ~URLExtraData();
+
+  RefPtr<nsIURI> mBaseURI;
+  RefPtr<nsIURI> mReferrer;
+  RefPtr<nsIPrincipal> mPrincipal;
+};
+
 struct URLValueData
 {
 protected:
   // Methods are not inline because using an nsIPrincipal means requiring
   // caps, which leads to REQUIRES hell, since this header is included all
   // over.
 
   // For both constructors aString must not be null.
-  // For both constructors aOriginPrincipal must not be null.
+  // For both constructors principal of aExtraData must not be null.
   // Construct with a base URI; this will create the actual URI lazily from
-  // aString and aBaseURI.
+  // aString and aExtraData.
   URLValueData(nsStringBuffer* aString,
-               already_AddRefed<PtrHolder<nsIURI>> aBaseURI,
-               already_AddRefed<PtrHolder<nsIURI>> aReferrer,
-               already_AddRefed<PtrHolder<nsIPrincipal>> aOriginPricinpal);
+               already_AddRefed<URLExtraData> aExtraData);
   // Construct with the actual URI.
   URLValueData(already_AddRefed<PtrHolder<nsIURI>> aURI,
                nsStringBuffer* aString,
-               already_AddRefed<PtrHolder<nsIURI>> aBaseURI,
-               already_AddRefed<PtrHolder<nsIURI>> aReferrer,
-               already_AddRefed<PtrHolder<nsIPrincipal>> aOriginPrincipal);
+               already_AddRefed<URLExtraData> aExtraData);
 
 public:
   // Returns true iff all fields of the two URLValueData objects are equal.
   //
   // Only safe to call on the main thread, since this will call Equals on the
   // nsIURI and nsIPrincipal objects stored on the URLValueData objects.
   bool Equals(const URLValueData& aOther) const;
 
@@ -154,20 +181,18 @@ public:
 
   bool EqualsExceptRef(nsIURI* aURI) const;
 
 private:
   // mURI stores the lazily resolved URI.  This may be null if the URI is
   // invalid, even once resolved.
   mutable PtrHandle<nsIURI> mURI;
 public:
-  PtrHandle<nsIURI> mBaseURI;
   RefPtr<nsStringBuffer> mString;
-  PtrHandle<nsIURI> mReferrer;
-  PtrHandle<nsIPrincipal> mOriginPrincipal;
+  RefPtr<URLExtraData> mExtraData;
 private:
   mutable bool mURIResolved;
   // mIsLocalRef is set when url starts with a U+0023 number sign(#) character.
   bool mIsLocalRef;
 
 protected:
   virtual ~URLValueData() = default;
 
@@ -183,46 +208,41 @@ struct URLValue final : public URLValueD
   // These two constructors are safe to call only on the main thread.
   URLValue(nsStringBuffer* aString, nsIURI* aBaseURI, nsIURI* aReferrer,
            nsIPrincipal* aOriginPrincipal);
   URLValue(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aBaseURI,
            nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal);
 
   // This constructor is safe to call from any thread.
   URLValue(nsStringBuffer* aString,
-           already_AddRefed<PtrHolder<nsIURI>> aBaseURI,
-           already_AddRefed<PtrHolder<nsIURI>> aReferrer,
-           already_AddRefed<PtrHolder<nsIPrincipal>> aOriginPrincipal)
-    : URLValueData(aString, Move(aBaseURI), Move(aReferrer),
-                   Move(aOriginPrincipal)) {}
+           already_AddRefed<URLExtraData> aExtraData)
+    : URLValueData(aString, Move(aExtraData)) {}
 
   URLValue(const URLValue&) = delete;
   URLValue& operator=(const URLValue&) = delete;
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 };
 
 struct ImageValue final : public URLValueData
 {
   // Not making the constructor and destructor inline because that would
   // force us to include imgIRequest.h, which leads to REQUIRES hell, since
   // this header is included all over.
   // aString must not be null.
   //
   // This constructor is only safe to call from the main thread.
-  ImageValue(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aBaseURI,
-             nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal,
+  ImageValue(nsIURI* aURI, nsStringBuffer* aString,
+             already_AddRefed<URLExtraData> aExtraData,
              nsIDocument* aDocument);
 
   // This constructor is safe to call from any thread, but Initialize
   // must be called later for the object to be useful.
   ImageValue(nsStringBuffer* aString,
-             already_AddRefed<PtrHolder<nsIURI>> aBaseURI,
-             already_AddRefed<PtrHolder<nsIURI>> aReferrer,
-             already_AddRefed<PtrHolder<nsIPrincipal>> aOriginPrincipal);
+             already_AddRefed<URLExtraData> aExtraData);
 
   ImageValue(const ImageValue&) = delete;
   ImageValue& operator=(const ImageValue&) = delete;
 
   void Initialize(nsIDocument* aDocument);
 
   // XXXheycam We should have our own SizeOfIncludingThis method.
 
--- a/layout/style/nsDOMCSSDeclaration.cpp
+++ b/layout/style/nsDOMCSSDeclaration.cpp
@@ -126,17 +126,18 @@ nsDOMCSSDeclaration::SetCssText(const ns
   // Attribute setting code, which leads in turn to BeginUpdate.  We
   // need to start the update now so that the old rule doesn't get used
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
   mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
 
   RefPtr<DeclarationBlock> newdecl;
   if (olddecl->IsServo()) {
-    GeckoParserExtraData data(env.mBaseURI, env.mSheetURI, env.mPrincipal);
+    RefPtr<css::URLExtraData> data =
+      new css::URLExtraData(env.mBaseURI, env.mSheetURI, env.mPrincipal);
     newdecl = ServoDeclarationBlock::FromCssText(aCssText, data);
   } else {
     RefPtr<css::Declaration> decl(new css::Declaration());
     decl->InitializeEmpty();
     nsCSSParser cssParser(env.mCSSLoader);
     bool changed;
     nsresult result = cssParser.ParseDeclarations(aCssText, env.mSheetURI,
                                                   env.mBaseURI, env.mPrincipal,
@@ -302,22 +303,23 @@ nsDOMCSSDeclaration::ParsePropertyValue(
   bool changed;
   if (decl->IsGecko()) {
     nsCSSParser cssParser(env.mCSSLoader);
     cssParser.ParseProperty(aPropID, aPropValue,
                             env.mSheetURI, env.mBaseURI, env.mPrincipal,
                             decl->AsGecko(), &changed, aIsImportant);
   } else {
     NS_ConvertUTF16toUTF8 value(aPropValue);
-    GeckoParserExtraData data(env.mBaseURI, env.mSheetURI, env.mPrincipal);
+    RefPtr<css::URLExtraData> data =
+      new css::URLExtraData(env.mBaseURI, env.mSheetURI, env.mPrincipal);
     nsCString baseString;
     // FIXME (bug 1343964): Figure out a better solution for sending the base uri to servo
     env.mBaseURI->GetSpec(baseString);
     changed = Servo_DeclarationBlock_SetPropertyById(
-      decl->AsServo()->Raw(), aPropID, &value, aIsImportant, &baseString, &data);
+      decl->AsServo()->Raw(), aPropID, &value, aIsImportant, &baseString, data);
   }
   if (!changed) {
     // Parsing failed -- but we don't throw an exception for that.
     return NS_OK;
   }
 
   return SetCSSDeclaration(decl);
 }
@@ -353,21 +355,22 @@ nsDOMCSSDeclaration::ParseCustomProperty
     nsCSSParser cssParser(env.mCSSLoader);
     auto propName = Substring(aPropertyName, CSS_CUSTOM_NAME_PREFIX_LENGTH);
     cssParser.ParseVariable(propName, aPropValue, env.mSheetURI,
                             env.mBaseURI, env.mPrincipal, decl->AsGecko(),
                             &changed, aIsImportant);
   } else {
     NS_ConvertUTF16toUTF8 property(aPropertyName);
     NS_ConvertUTF16toUTF8 value(aPropValue);
-    GeckoParserExtraData data(env.mBaseURI, env.mSheetURI, env.mPrincipal);
+    RefPtr<css::URLExtraData> data =
+      new css::URLExtraData(env.mBaseURI, env.mSheetURI, env.mPrincipal);
     nsCString baseString;
     env.mBaseURI->GetSpec(baseString);
     changed = Servo_DeclarationBlock_SetProperty(
-      decl->AsServo()->Raw(), &property, &value, aIsImportant, &baseString, &data);
+      decl->AsServo()->Raw(), &property, &value, aIsImportant, &baseString, data);
   }
   if (!changed) {
     // Parsing failed -- but we don't throw an exception for that.
     return NS_OK;
   }
 
   return SetCSSDeclaration(decl);
 }
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1994,24 +1994,21 @@ nsStyleImageRequest::nsStyleImageRequest
   if (mRequestProxy) {
     MaybeTrackAndLock();
   }
 }
 
 nsStyleImageRequest::nsStyleImageRequest(
     Mode aModeFlags,
     nsStringBuffer* aURLBuffer,
-    already_AddRefed<PtrHolder<nsIURI>> aBaseURI,
-    already_AddRefed<PtrHolder<nsIURI>> aReferrer,
-    already_AddRefed<PtrHolder<nsIPrincipal>> aPrincipal)
-  : mModeFlags(aModeFlags)
+    already_AddRefed<css::URLExtraData> aExtraData)
+  : mImageValue(new css::ImageValue(aURLBuffer, Move(aExtraData)))
+  , mModeFlags(aModeFlags)
   , mResolved(false)
 {
-  mImageValue = new css::ImageValue(aURLBuffer, Move(aBaseURI),
-                                    Move(aReferrer), Move(aPrincipal));
 }
 
 nsStyleImageRequest::~nsStyleImageRequest()
 {
   // We may or may not be being destroyed on the main thread.  To clean
   // up, we must untrack and unlock the image (depending on mModeFlags),
   // and release mRequestProxy and mImageValue, all on the main thread.
   {
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -334,19 +334,17 @@ public:
                       mozilla::css::ImageValue* aImageValue,
                       mozilla::dom::ImageTracker* aImageTracker);
 
   // Can be called from any thread, but Resolve() must be called later
   // on the main thread before get() can be used.
   nsStyleImageRequest(
       Mode aModeFlags,
       nsStringBuffer* aURLBuffer,
-      already_AddRefed<mozilla::PtrHolder<nsIURI>> aBaseURI,
-      already_AddRefed<mozilla::PtrHolder<nsIURI>> aReferrer,
-      already_AddRefed<mozilla::PtrHolder<nsIPrincipal>> aPrincipal);
+      already_AddRefed<mozilla::css::URLExtraData> aExtraData);
 
   bool Resolve(nsPresContext* aPresContext);
   bool IsResolved() const { return mResolved; }
 
   imgRequestProxy* get() {
     MOZ_ASSERT(IsResolved(), "Resolve() must be called first");
     MOZ_ASSERT(NS_IsMainThread());
     return mRequestProxy.get();