--- 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