Bug 1282410 - part1 : open unsupported type media. r=cpearce
authorAlastor Wu <alwu@mozilla.com>
Wed, 06 Jul 2016 10:34:29 +0800
changeset 332307 c28668cae17e21e43faa53629fb8394fe0f187e0
parent 332306 fa9e9291bfe34c20797978d5d6a8f4168bf961b8
child 332308 cf23addcfa4d9224a7d186481ecfb48194bb37be
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1282410
milestone50.0a1
Bug 1282410 - part1 : open unsupported type media. r=cpearce
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
mobile/android/app/mobile.js
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1026,16 +1026,17 @@ void HTMLMediaElement::NoSupportedMediaS
   NS_ASSERTION(mNetworkState == NETWORK_LOADING,
                "Not loading during source selection?");
 
   mError = new MediaError(this, nsIDOMMediaError::MEDIA_ERR_SRC_NOT_SUPPORTED);
   ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE);
   DispatchAsyncEvent(NS_LITERAL_STRING("error"));
   ChangeDelayLoadStatus(false);
   UpdateAudioChannelPlayingState();
+  OpenUnsupportedMediaWithExtenalAppIfNeeded();
 }
 
 typedef void (HTMLMediaElement::*SyncSectionFn)();
 
 // Runs a "synchronous section", a function that must run once the event loop
 // has reached a "stable state". See:
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section
 class nsSyncSection : public nsMediaEvent
@@ -2701,16 +2702,20 @@ HTMLMediaElement::PlayInternal(bool aCal
 
   // We changed mPaused and mAutoplaying which can affect AddRemoveSelfReference
   // and our preload status.
   AddRemoveSelfReference();
   UpdatePreloadAction();
   UpdateSrcMediaStreamPlaying();
   UpdateAudioChannelPlayingState();
 
+  // The check here is to handle the case that the media element starts playing
+  // after it loaded fail. eg. preload the data before playing.
+  OpenUnsupportedMediaWithExtenalAppIfNeeded();
+
   return NS_OK;
 }
 
 NS_IMETHODIMP HTMLMediaElement::Play()
 {
   return PlayInternal(/* aCallerIsChrome = */ true);
 }
 
@@ -6008,16 +6013,51 @@ HTMLMediaElement::IsAudible() const
   // Silent audio track.
   if (!mIsAudioTrackAudible) {
     return false;
   }
 
   return true;
 }
 
+bool
+HTMLMediaElement::HaveFailedWithSourceNotSupportedError() const
+{
+  if (!mError) {
+    return false;
+  }
+
+  uint16_t errorCode;
+  mError->GetCode(&errorCode);
+  return (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE &&
+          errorCode == nsIDOMMediaError::MEDIA_ERR_SRC_NOT_SUPPORTED);
+}
+
+void
+HTMLMediaElement::OpenUnsupportedMediaWithExtenalAppIfNeeded()
+{
+  if (!Preferences::GetBool("media.openUnsupportedTypeWithExternalApp")) {
+    return;
+  }
+
+  if (!HaveFailedWithSourceNotSupportedError()) {
+    return;
+  }
+
+  // If media doesn't start playing, we don't need to open it.
+  if (mPaused) {
+    return;
+  }
+
+  nsContentUtils::DispatchTrustedEvent(OwnerDoc(), static_cast<nsIContent*>(this),
+                                       NS_LITERAL_STRING("OpenMediaWithExtenalApp"),
+                                       true,
+                                       true);
+}
+
 static const char* VisibilityString(Visibility aVisibility) {
   switch(aVisibility) {
     case Visibility::UNTRACKED: {
       return "UNTRACKED";
     }
     case Visibility::NONVISIBLE: {
       return "NONVISIBLE";
     }
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1188,16 +1188,19 @@ protected:
   void ResumeFromAudioChannelBlocked();
 
   bool IsSuspendedByAudioChannel() const;
   void SetAudioChannelSuspended(SuspendTypes aSuspend);
 
   bool IsAllowedToPlay();
 
   bool IsAudible() const;
+  bool HaveFailedWithSourceNotSupportedError() const;
+
+  void OpenUnsupportedMediaWithExtenalAppIfNeeded();
 
   class nsAsyncEventRunner;
   using nsGenericHTMLElement::DispatchEvent;
   // For nsAsyncEventRunner.
   nsresult DispatchEvent(const nsAString& aName);
 
   // The current decoder. Load() has been called on this decoder.
   // At most one of mDecoder and mSrcStream can be non-null.
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -919,8 +919,10 @@ pref("dom.presentation.discovery.enabled
 pref("dom.presentation.discovery.legacy.enabled", true); // for TV 2.5 backward capability
 
 pref("dom.audiochannel.audioCompeting", true);
 pref("dom.audiochannel.mediaControl", true);
 
 // Space separated list of URLS that are allowed to send objects (instead of
 // only strings) through webchannels. This list is duplicated in browser/app/profile/firefox.js
 pref("webchannel.allowObject.urlWhitelist", "https://accounts.firefox.com https://content.cdn.mozilla.net https://hello.firefox.com https://input.mozilla.org https://support.mozilla.org https://install.mozilla.org");
+
+pref("media.openUnsupportedTypeWithExternalApp", true);