Bug 1235183. Part 4 - create channel asynchronously. draft
authorJW Wang <jwwang@mozilla.com>
Fri, 24 Jun 2016 13:45:01 +0800
changeset 381740 d76d5e254a30d17ead477c4a5726d76b33badb26
parent 381739 d883487f94862647ba4d4856d352125a848a31d5
child 382157 4658663620723a72b1539761070a8047f021457b
push id21537
push userjwwang@mozilla.com
push dateTue, 28 Jun 2016 03:05:11 +0000
bugs1235183
milestone50.0a1
Bug 1235183. Part 4 - create channel asynchronously. MozReview-Commit-ID: 9JVuHhhMFoa
dom/html/HTMLMediaElement.cpp
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -464,18 +464,21 @@ void HTMLMediaElement::ReportLoadError(c
                                   aParams,
                                   aParamCount);
 }
 
 class HTMLMediaElement::ChannelLoader final {
 public:
   NS_INLINE_DECL_REFCOUNTING(ChannelLoader);
 
-  nsresult Load(HTMLMediaElement* aElement)
+  void LoadInternal(HTMLMediaElement* aElement)
   {
+    if (mCancelled) {
+      return;
+    }
 
     // determine what security checks need to be performed in AsyncOpen2().
     nsSecurityFlags securityFlags = aElement->ShouldCheckAllowOrigin()
       ? nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS :
         nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
 
     if (aElement->GetCORSMode() == CORS_USE_CREDENTIALS) {
       securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
@@ -506,17 +509,19 @@ public:
                                 loadGroup,
                                 nullptr,   // aCallbacks
                                 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
                                 nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE |
                                 nsIChannel::LOAD_CLASSIFY_URI |
                                 nsIChannel::LOAD_CALL_CONTENT_SNIFFERS);
 
     if (NS_FAILED(rv)) {
-      return rv;
+      // Notify load error so the element will try next resource candidate.
+      aElement->NotifyLoadError();
+      return;
     }
 
     // This is a workaround and it will be fix in bug 1264230.
     nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
     if (loadInfo) {
       NeckoOriginAttributes originAttrs;
       NS_GetOriginAttributes(channel, originAttrs);
       loadInfo->SetOriginAttributes(originAttrs);
@@ -540,37 +545,50 @@ public:
       hc->SetRequestHeader(NS_LITERAL_CSTRING("Range"),
                            NS_LITERAL_CSTRING("bytes=0-"),
                            false);
       aElement->SetRequestHeaders(hc);
     }
 
     rv = channel->AsyncOpen2(loadListener);
     if (NS_FAILED(rv)) {
-      return rv;
+      // Notify load error so the element will try next resource candidate.
+      aElement->NotifyLoadError();
+      return;
     }
 
     // Else the channel must be open and starting to download. If it encounters
     // a non-catastrophic failure, it will set a new task to continue loading
     // another candidate.  It's safe to set it as mChannel now.
     mChannel = channel;
 
     // loadListener will be unregistered either on shutdown or when
     // OnStartRequest for the channel we just opened fires.
     nsContentUtils::RegisterShutdownObserver(loadListener);
-    return NS_OK;
+  }
+
+  nsresult Load(HTMLMediaElement* aElement)
+  {
+    // Per bug 1235183 comment 8, we can't spin the event loop from stable
+    // state. Defer NS_NewChannel() to a new regular runnable.
+    return NS_DispatchToMainThread(NewRunnableMethod<HTMLMediaElement*>(
+      this, &ChannelLoader::LoadInternal, aElement));
   }
 
   void Cancel()
   {
-    mChannel->Cancel(NS_BINDING_ABORTED);
-    mChannel = nullptr;
+    mCancelled = true;
+    if (mChannel) {
+      mChannel->Cancel(NS_BINDING_ABORTED);
+      mChannel = nullptr;
+    }
   }
 
   void Done() {
+    MOZ_ASSERT(mChannel);
     // Decoder successfully created, the decoder now owns the MediaResource
     // which owns the channel.
     mChannel = nullptr;
   }
 
   nsresult Redirect(nsIChannel* aChannel,
                     nsIChannel* aNewChannel,
                     uint32_t aFlags)
@@ -604,16 +622,18 @@ private:
   {
     MOZ_ASSERT(!mChannel);
   }
   // Holds a reference to the first channel we open to the media resource.
   // Once the decoder is created, control over the channel passes to the
   // decoder, and we null out this reference. We must store this in case
   // we need to cancel the channel before control of it passes to the decoder.
   nsCOMPtr<nsIChannel> mChannel;
+
+  bool mCancelled = false;
 };
 
 NS_IMPL_ADDREF_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
 NS_IMPL_RELEASE_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLMediaElement)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLElement)