Bug 1299498 - Keep a main thread only pointer to the underlying nsIURI for ImageURL. r=tnikkel
authorAndrew Osmond <aosmond@mozilla.com>
Mon, 28 Nov 2016 08:40:42 -0500
changeset 324701 f7834b7b40502dc6b0231829b9786e6f37c8e918
parent 324700 19f0a7a2be1425ac8ecede607f29df47471343fc
child 324702 bed1ca42b7b4a29ef1638bee5156ba27ff3c4c7d
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewerstnikkel
bugs1299498
milestone53.0a1
Bug 1299498 - Keep a main thread only pointer to the underlying nsIURI for ImageURL. r=tnikkel
image/ImageURL.h
--- a/image/ImageURL.h
+++ b/image/ImageURL.h
@@ -6,16 +6,17 @@
 #ifndef mozilla_image_ImageURL_h
 #define mozilla_image_ImageURL_h
 
 #include "nsIURI.h"
 #include "MainThreadUtils.h"
 #include "nsNetUtil.h"
 #include "mozilla/HashFunctions.h"
 #include "nsHashKeys.h"
+#include "nsProxyRelease.h"
 
 namespace mozilla {
 namespace image {
 
 class ImageCacheKey;
 
 /** ImageURL
  *
@@ -28,16 +29,17 @@ class ImageCacheKey;
  * By not implementing nsIURI, external code cannot unintentionally be given an
  * nsIURI pointer with this limited class behind it; instead, conversion to a
  * fully implemented nsIURI is required (e.g. through NS_NewURI).
  */
 class ImageURL
 {
 public:
   explicit ImageURL(nsIURI* aURI, nsresult& aRv)
+    : mURI(new nsMainThreadPtrHolder<nsIURI>(aURI))
   {
     MOZ_ASSERT(NS_IsMainThread(), "Cannot use nsIURI off main thread!");
 
     aRv = aURI->GetSpec(mSpec);
     NS_ENSURE_SUCCESS_VOID(aRv);
 
     aRv = aURI->GetScheme(mScheme);
     NS_ENSURE_SUCCESS_VOID(aRv);
@@ -92,20 +94,17 @@ public:
   nsresult GetRef(nsACString& result)
   {
     result = mRef;
     return NS_OK;
   }
 
   already_AddRefed<nsIURI> ToIURI()
   {
-    MOZ_ASSERT(NS_IsMainThread(),
-               "Convert to nsIURI on main thread only; it is not threadsafe.");
-    nsCOMPtr<nsIURI> newURI;
-    NS_NewURI(getter_AddRefs(newURI), mSpec);
+    nsCOMPtr<nsIURI> newURI = mURI.get();
     return newURI.forget();
   }
 
   bool operator==(const ImageURL& aOther) const
   {
     // Note that we don't need to consider mScheme and mRef, because they're
     // already represented in mSpec.
     return mSpec == aOther.mSpec;
@@ -128,16 +127,18 @@ private:
       // requires us to create different Image objects even if the source data is
       // the same.
       return HashGeneric(*aBlobSerial, HashString(mRef));
     }
     // For non-blob URIs, we hash the URI spec.
     return HashString(mSpec);
   }
 
+  nsMainThreadPtrHandle<nsIURI> mURI;
+
   // Since this is a basic storage class, no duplication of spec parsing is
   // included in the functionality. Instead, the class depends upon the
   // parsing implementation in the nsIURI class used in object construction.
   // This means each field is stored separately, but since only a few are
   // required, this small memory tradeoff for threadsafe usage should be ok.
   nsAutoCString mSpec;
   nsAutoCString mScheme;
   nsAutoCString mRef;