Bug 1248507 - p7. Notify decoder-doctor-notification listeners - r=jya,bz
authorGerald Squelart <gsquelart@mozilla.com>
Tue, 19 Apr 2016 17:36:19 +1000
changeset 331699 240b08fad81c31661796e634dae1d5ba02eb4596
parent 331698 5f476afcc5f0f3fa8bf1b6bc1d1ed9c43d7d3131
child 331700 3616775208baa8f91e637d176f4f52aed703a69b
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya, bz
bugs1248507
milestone48.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 1248507 - p7. Notify decoder-doctor-notification listeners - r=jya,bz If the Decoder Doctor analysis needs to report something, a notification is sent to listeners of "decoder-doctor-notification", with data identifying the type of notification along with the media format(s) that could not be decoded. In this patch, there are only two notification types: "cannot-play", or "can-play-but-some-missing-decoders" (if pref "media.decoderdoctor.verbose" is true). In a future bug, the Firefox front-end will handle this notification and then optionally display a user notification. Note: "can-play-but-some-missing-decoders" should be useful to help implement the front-end side (as sites like YouTube will probably have some formats we don't handle); it may be removed later on if it has no further use. MozReview-Commit-ID: GL3JRqLxzxL
dom/media/DecoderDoctorDiagnostics.cpp
--- a/dom/media/DecoderDoctorDiagnostics.cpp
+++ b/dom/media/DecoderDoctorDiagnostics.cpp
@@ -1,19 +1,21 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "DecoderDoctorDiagnostics.h"
 
+#include "mozilla/dom/DecoderDoctorNotificationBinding.h"
 #include "mozilla/Logging.h"
 #include "nsGkAtoms.h"
 #include "nsIDocument.h"
+#include "nsIObserverService.h"
 #include "nsITimer.h"
 #include "nsIWeakReference.h"
 
 static mozilla::LazyLogModule sDecoderDoctorLog("DecoderDoctor");
 #define DD_LOG(level, arg, ...) MOZ_LOG(sDecoderDoctorLog, level, (arg, ##__VA_ARGS__))
 #define DD_DEBUG(arg, ...) DD_LOG(mozilla::LogLevel::Debug, arg, ##__VA_ARGS__)
 #define DD_INFO(arg, ...) DD_LOG(mozilla::LogLevel::Info, arg, ##__VA_ARGS__)
 #define DD_WARN(arg, ...) DD_LOG(mozilla::LogLevel::Warning, arg, ##__VA_ARGS__)
@@ -58,17 +60,18 @@ private:
   static void DestroyPropertyCallback(void* aObject,
                                       nsIAtom* aPropertyName,
                                       void* aPropertyValue,
                                       void* aData);
 
   static const uint32_t sAnalysisPeriod_ms = 1000;
   void EnsureTimerIsStarted();
 
-  void ReportAnalysis(const char* aReportStringId,
+  void ReportAnalysis(dom::DecoderDoctorNotificationType aNotificationType,
+                      const char* aReportStringId,
                       const nsAString& aFormats);
 
   void SynthesizeAnalysis();
 
   // Raw pointer to an nsIDocument.
   // Must be non-null during construction.
   // Nulled when we want to stop watching, because either:
   // 1. The document has been destroyed (notified through
@@ -230,19 +233,49 @@ DecoderDoctorDocumentWatcher::EnsureTime
     if (NS_WARN_IF(NS_FAILED(
           mTimer->InitWithCallback(
             this, sAnalysisPeriod_ms, nsITimer::TYPE_ONE_SHOT)))) {
       mTimer = nullptr;
     }
   }
 }
 
+static void
+DispatchNotification(nsISupports* aSubject,
+                     dom::DecoderDoctorNotificationType aNotificationType,
+                     const nsAString& aFormats)
+{
+  if (!aSubject) {
+    return;
+  }
+  dom::DecoderDoctorNotification data;
+  data.mType = aNotificationType;
+  if (!aFormats.IsEmpty()) {
+    data.mFormats.Construct(aFormats);
+  }
+  nsAutoString json;
+  data.ToJSON(json);
+  if (json.IsEmpty()) {
+    DD_WARN("DecoderDoctorDiagnostics/DispatchEvent() - Could not create json for dispatch");
+    // No point in dispatching this notification without data, the front-end
+    // wouldn't know what to display.
+    return;
+  }
+  DD_DEBUG("DecoderDoctorDiagnostics/DispatchEvent() %s", NS_ConvertUTF16toUTF8(json).get());
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  if (obs) {
+    obs->NotifyObservers(aSubject, "decoder-doctor-notification", json.get());
+  }
+}
+
 void
-DecoderDoctorDocumentWatcher::ReportAnalysis(const char* aReportStringId,
-                                             const nsAString& aFormats)
+DecoderDoctorDocumentWatcher::ReportAnalysis(
+  dom::DecoderDoctorNotificationType aNotificationType,
+  const char* aReportStringId,
+  const nsAString& aFormats)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mDocument) {
     return;
   }
 
   const char16_t* params[] = { aFormats.Data() };
@@ -251,16 +284,18 @@ DecoderDoctorDocumentWatcher::ReportAnal
            NS_ConvertUTF16toUTF8(params[0]).get());
   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                   NS_LITERAL_CSTRING("Media"),
                                   mDocument,
                                   nsContentUtils::eDOM_PROPERTIES,
                                   aReportStringId,
                                   params,
                                   ArrayLength(params));
+
+  DispatchNotification(mDocument->GetInnerWindow(), aNotificationType, aFormats);
 }
 
 void
 DecoderDoctorDocumentWatcher::SynthesizeAnalysis()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   bool canPlay = false;
@@ -273,22 +308,25 @@ DecoderDoctorDocumentWatcher::Synthesize
         formats += NS_LITERAL_STRING(", ");
       }
       formats += diag.mFormat;
     }
   }
   if (!canPlay) {
     DD_WARN("DecoderDoctorDocumentWatcher[%p, doc=%p]::Notify() - Cannot play media, formats: %s",
             this, mDocument, NS_ConvertUTF16toUTF8(formats).get());
-    ReportAnalysis("MediaCannotPlayNoDecoders", formats);
+    ReportAnalysis(dom::DecoderDoctorNotificationType::Cannot_play,
+                   "MediaCannotPlayNoDecoders", formats);
   } else if (!formats.IsEmpty()) {
     DD_INFO("DecoderDoctorDocumentWatcher[%p, doc=%p]::Notify() - Can play media, but no decoders for some requested formats: %s",
             this, mDocument, NS_ConvertUTF16toUTF8(formats).get());
     if (Preferences::GetBool("media.decoderdoctor.verbose", false)) {
-      ReportAnalysis("MediaNoDecoders", formats);
+      ReportAnalysis(
+        dom::DecoderDoctorNotificationType::Can_play_but_some_missing_decoders,
+        "MediaNoDecoders", formats);
     }
   } else {
     DD_DEBUG("DecoderDoctorDocumentWatcher[%p, doc=%p]::Notify() - Can play media, decoders available for all requested formats",
              this, mDocument);
   }
 }
 
 void