Bug 1282407 - Implement nsIURIWithBlobImpl to support blobURL after revoking them, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Sun, 17 Jul 2016 16:32:02 +0200
changeset 305240 a1b20019c22d1a1f177387c754ec2eed74aced1b
parent 305239 d8201a97184f2f6cdcd70f19d8d6fc90e5589f33
child 305241 dd77af0226275b8c5f312379411f11d130de0734
push id79521
push useramarchesini@mozilla.com
push dateSun, 17 Jul 2016 14:32:18 +0000
treeherdermozilla-inbound@a1b20019c22d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1282407
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1282407 - Implement nsIURIWithBlobImpl to support blobURL after revoking them, r=smaug
dom/base/nsHostObjectProtocolHandler.cpp
dom/base/nsHostObjectURI.cpp
dom/base/nsHostObjectURI.h
netwerk/base/moz.build
netwerk/base/nsIURIWithBlobImpl.idl
--- a/dom/base/nsHostObjectProtocolHandler.cpp
+++ b/dom/base/nsHostObjectProtocolHandler.cpp
@@ -504,18 +504,23 @@ nsHostObjectProtocolHandler::NewURI(cons
                                     nsIURI *aBaseURI,
                                     nsIURI **aResult)
 {
   *aResult = nullptr;
   nsresult rv;
 
   DataInfo* info = GetDataInfo(aSpec);
 
-  RefPtr<nsHostObjectURI> uri =
-    new nsHostObjectURI(info ? info->mPrincipal.get() : nullptr);
+  RefPtr<nsHostObjectURI> uri;
+  if (info) {
+    nsCOMPtr<BlobImpl> blob = do_QueryInterface(info->mObject);
+    uri = new nsHostObjectURI(info->mPrincipal, blob);
+  } else {
+    uri = new nsHostObjectURI(nullptr, nullptr);
+  }
 
   rv = uri->SetSpec(aSpec);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_TryToSetImmutable(uri);
   uri.forget(aResult);
 
   return NS_OK;
@@ -523,67 +528,71 @@ nsHostObjectProtocolHandler::NewURI(cons
 
 NS_IMETHODIMP
 nsHostObjectProtocolHandler::NewChannel2(nsIURI* uri,
                                          nsILoadInfo* aLoadInfo,
                                          nsIChannel** result)
 {
   *result = nullptr;
 
+  nsCOMPtr<nsIURIWithBlobImpl> uriBlobImpl = do_QueryInterface(uri);
+  if (!uriBlobImpl) {
+    return NS_ERROR_DOM_BAD_URI;
+  }
+
+  nsCOMPtr<nsISupports> tmp;
+  MOZ_ALWAYS_SUCCEEDS(uriBlobImpl->GetBlobImpl(getter_AddRefs(tmp)));
+  nsCOMPtr<BlobImpl> blobImpl = do_QueryInterface(tmp);
+  if (!blobImpl) {
+    return NS_ERROR_DOM_BAD_URI;
+  }
+
+#ifdef DEBUG
   nsCString spec;
   uri->GetSpec(spec);
 
   DataInfo* info = GetDataInfo(spec);
 
-  if (!info) {
-    return NS_ERROR_DOM_BAD_URI;
-  }
-
-  nsCOMPtr<BlobImpl> blob = do_QueryInterface(info->mObject);
-  if (!blob) {
-    return NS_ERROR_DOM_BAD_URI;
-  }
-
-#ifdef DEBUG
-  {
+  // Info can be null, in case this blob URL has been revoked already.
+  if (info) {
     nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(uri);
     nsCOMPtr<nsIPrincipal> principal;
     uriPrinc->GetPrincipal(getter_AddRefs(principal));
     NS_ASSERTION(info->mPrincipal == principal, "Wrong principal!");
   }
 #endif
 
   ErrorResult rv;
   nsCOMPtr<nsIInputStream> stream;
-  blob->GetInternalStream(getter_AddRefs(stream), rv);
+  blobImpl->GetInternalStream(getter_AddRefs(stream), rv);
   if (NS_WARN_IF(rv.Failed())) {
     return rv.StealNSResult();
   }
 
   nsAutoString contentType;
-  blob->GetType(contentType);
+  blobImpl->GetType(contentType);
 
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
                                         uri,
                                         stream,
                                         NS_ConvertUTF16toUTF8(contentType),
                                         EmptyCString(), // aContentCharset
                                         aLoadInfo);
   if (NS_WARN_IF(rv.Failed())) {
     return rv.StealNSResult();
   }
 
-  if (blob->IsFile()) {
+  if (blobImpl->IsFile()) {
     nsString filename;
-    blob->GetName(filename);
+    blobImpl->GetName(filename);
     channel->SetContentDispositionFilename(filename);
   }
 
-  uint64_t size = blob->GetSize(rv);
+  uint64_t size = blobImpl->GetSize(rv);
   if (NS_WARN_IF(rv.Failed())) {
     return rv.StealNSResult();
   }
 
   channel->SetOriginalURI(uri);
   channel->SetContentType(NS_ConvertUTF16toUTF8(contentType));
   channel->SetContentLength(size);
 
--- a/dom/base/nsHostObjectURI.cpp
+++ b/dom/base/nsHostObjectURI.cpp
@@ -16,29 +16,40 @@ static NS_DEFINE_CID(kHOSTOBJECTURICID, 
 
 static NS_DEFINE_CID(kThisSimpleURIImplementationCID,
                      NS_THIS_SIMPLEURI_IMPLEMENTATION_CID);
 
 NS_IMPL_ADDREF_INHERITED(nsHostObjectURI, mozilla::net::nsSimpleURI)
 NS_IMPL_RELEASE_INHERITED(nsHostObjectURI, mozilla::net::nsSimpleURI)
 
 NS_INTERFACE_MAP_BEGIN(nsHostObjectURI)
+  NS_INTERFACE_MAP_ENTRY(nsIURIWithBlobImpl)
   NS_INTERFACE_MAP_ENTRY(nsIURIWithPrincipal)
   if (aIID.Equals(kHOSTOBJECTURICID))
     foundInterface = static_cast<nsIURI*>(this);
   else if (aIID.Equals(kThisSimpleURIImplementationCID)) {
     // Need to return explicitly here, because if we just set foundInterface
     // to null the NS_INTERFACE_MAP_END_INHERITING will end up calling into
     // nsSimplURI::QueryInterface and finding something for this CID.
     *aInstancePtr = nullptr;
     return NS_NOINTERFACE;
   }
   else
 NS_INTERFACE_MAP_END_INHERITING(mozilla::net::nsSimpleURI)
 
+// nsIURIWithBlobImpl methods:
+
+NS_IMETHODIMP
+nsHostObjectURI::GetBlobImpl(nsISupports** aBlobImpl)
+{
+  RefPtr<BlobImpl> blobImpl(mBlobImpl);
+  blobImpl.forget(aBlobImpl);
+  return NS_OK;
+}
+
 // nsIURIWithPrincipal methods:
 
 NS_IMETHODIMP
 nsHostObjectURI::GetPrincipal(nsIPrincipal** aPrincipal)
 {
   NS_IF_ADDREF(*aPrincipal = mPrincipal);
 
   return NS_OK;
@@ -121,16 +132,20 @@ nsHostObjectURI::Deserialize(const mozil
       return false;
   }
 
   const HostObjectURIParams& hostParams = aParams.get_HostObjectURIParams();
 
   if (!mozilla::net::nsSimpleURI::Deserialize(hostParams.simpleParams())) {
     return false;
   }
+
+  // XXXbaku: when we will have shared blobURL maps, we can populate mBlobImpl
+  // here asll well.
+
   if (hostParams.principal().type() == OptionalPrincipalInfo::Tvoid_t) {
     return true;
   }
 
   mPrincipal = PrincipalInfoToPrincipal(hostParams.principal().get_PrincipalInfo());
   return mPrincipal != nullptr;
 }
 
@@ -157,16 +172,17 @@ nsHostObjectURI::CloneInternal(mozilla::
   RefPtr<nsHostObjectURI> uriCheck;
   rv = simpleClone->QueryInterface(kHOSTOBJECTURICID, getter_AddRefs(uriCheck));
   MOZ_ASSERT(NS_SUCCEEDED(rv) && uriCheck);
 #endif
 
   nsHostObjectURI* u = static_cast<nsHostObjectURI*>(simpleClone.get());
 
   u->mPrincipal = mPrincipal;
+  u->mBlobImpl = mBlobImpl;
 
   simpleClone.forget(aClone);
   return NS_OK;
 }
 
 /* virtual */ nsresult
 nsHostObjectURI::EqualsInternal(nsIURI* aOther,
                                 mozilla::net::nsSimpleURI::RefHandlingEnum aRefHandlingMode,
@@ -185,17 +201,20 @@ nsHostObjectURI::EqualsInternal(nsIURI* 
   }
 
   // Compare the member data that our base class knows about.
   if (!mozilla::net::nsSimpleURI::EqualsInternal(otherUri, aRefHandlingMode)) {
     *aResult = false;
     return NS_OK;
   }
 
-  // Compare the piece of additional member data that we add to base class.
+  // Compare the piece of additional member data that we add to base class,
+  // but we cannot compare BlobImpl. This should not be a problem, because we
+  // don't support changing the underlying mBlobImpl.
+
   if (mPrincipal && otherUri->mPrincipal) {
     // Both of us have mPrincipals. Compare them.
     return mPrincipal->Equals(otherUri->mPrincipal, aResult);
   }
   // else, at least one of us lacks a principal; only equal if *both* lack it.
   *aResult = (!mPrincipal && !otherUri->mPrincipal);
   return NS_OK;
 }
--- a/dom/base/nsHostObjectURI.h
+++ b/dom/base/nsHostObjectURI.h
@@ -3,41 +3,48 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsHostObjectURI_h
 #define nsHostObjectURI_h
 
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/File.h"
 #include "nsCOMPtr.h"
 #include "nsIClassInfo.h"
 #include "nsIPrincipal.h"
 #include "nsISerializable.h"
+#include "nsIURIWithBlobImpl.h"
 #include "nsIURIWithPrincipal.h"
 #include "nsSimpleURI.h"
 #include "nsIIPCSerializableURI.h"
 
 /**
  * These URIs refer to host objects: Blobs, with scheme "blob",
  * MediaStreams, with scheme "mediastream", and MediaSources, with scheme
  * "mediasource".
  */
-class nsHostObjectURI : public mozilla::net::nsSimpleURI,
-                        public nsIURIWithPrincipal
+class nsHostObjectURI : public mozilla::net::nsSimpleURI
+                      , public nsIURIWithPrincipal
+                      , public nsIURIWithBlobImpl
 {
 public:
-  explicit nsHostObjectURI(nsIPrincipal* aPrincipal) :
-      mozilla::net::nsSimpleURI(), mPrincipal(aPrincipal)
+  nsHostObjectURI(nsIPrincipal* aPrincipal,
+                  mozilla::dom::BlobImpl* aBlobImpl)
+    : mozilla::net::nsSimpleURI()
+    , mPrincipal(aPrincipal)
+    , mBlobImpl(aBlobImpl)
   {}
 
   // For use only from deserialization
   nsHostObjectURI() : mozilla::net::nsSimpleURI() {}
 
   NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIURIWITHBLOBIMPL
   NS_DECL_NSIURIWITHPRINCIPAL
   NS_DECL_NSISERIALIZABLE
   NS_DECL_NSICLASSINFO
   NS_DECL_NSIIPCSERIALIZABLEURI
 
   NS_IMETHOD SetScheme(const nsACString &aProtocol) override;
 
   // Override CloneInternal() and EqualsInternal()
@@ -47,16 +54,17 @@ public:
                                   RefHandlingEnum aRefHandlingMode,
                                   bool* aResult) override;
 
   // Override StartClone to hand back a nsHostObjectURI
   virtual mozilla::net::nsSimpleURI* StartClone(RefHandlingEnum /* unused */) override
   { return new nsHostObjectURI(); }
 
   nsCOMPtr<nsIPrincipal> mPrincipal;
+  RefPtr<mozilla::dom::BlobImpl> mBlobImpl;
 
 protected:
   virtual ~nsHostObjectURI() {}
 };
 
 #define NS_HOSTOBJECTURI_CID \
 { 0xf5475c51, 0x59a7, 0x4757, \
   { 0xb3, 0xd9, 0xe2, 0x11, 0xa9, 0x41, 0x08, 0x72 } }
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -130,16 +130,17 @@ XPIDL_SOURCES += [
     'nsITraceableChannel.idl',
     'nsITransport.idl',
     'nsIUDPSocket.idl',
     'nsIUnicharStreamLoader.idl',
     'nsIUploadChannel.idl',
     'nsIUploadChannel2.idl',
     'nsIURI.idl',
     'nsIURIClassifier.idl',
+    'nsIURIWithBlobImpl.idl',
     'nsIURIWithPrincipal.idl',
     'nsIURL.idl',
     'nsIURLParser.idl',
     'nsPILoadGroupInternal.idl',
     'nsPISocketTransportService.idl',
 ]
 
 if CONFIG['MOZ_TOOLKIT_SEARCH']:
new file mode 100644
--- /dev/null
+++ b/netwerk/base/nsIURIWithBlobImpl.idl
@@ -0,0 +1,20 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+interface nsIURI;
+
+/**
+ * nsIURIWithBlobImpl is implemented by URIs which are associated with a
+ * specific BlobImpl.
+ */
+[builtinclass, uuid(331b41d3-3506-4ab5-bef9-aab41e3202a3)]
+interface nsIURIWithBlobImpl : nsISupports
+{
+    /**
+     * The BlobImpl associated with the resource returned when loading this uri.
+     */
+    readonly attribute nsISupports blobImpl;
+};