static bool
AllowDecodeIssue(const MediaResult& aDecodeIssue, bool aDecodeIssueIsError)
{
  if (aDecodeIssue == NS_OK) {
    // 'NS_OK' means we are not actually reporting a decode issue, so we
    // allow the report.
    return true;
  }

  // "media.decoder-doctor.decode-{errors,warnings}-allowed" controls which
  // decode issues may be dispatched to the front-end. It either contains:
  // - '*' -> Allow everything.
  // - Comma-separater list of ids -> Allow if the issue name is one of them.
  // - Nothing (missing or empty) -> Disable everything.
  nsAutoCString filter;
  Preferences::GetCString(aDecodeIssueIsError
                          ? "media.decoder-doctor.decode-errors-allowed"
                          : "media.decoder-doctor.decode-warnings-allowed",
                          filter);
  if (filter.EqualsLiteral("*")) {
    return true;
  }

  nsCString decodeIssueName;
  GetErrorName(aDecodeIssue.Code(), static_cast<nsACString&>(decodeIssueName));
  return StringListContains(filter, decodeIssueName);
}
static bool
AllowNotification(const NotificationAndReportStringId& aNotification)
{
  // "media.decoder-doctor.notifications-allowed" controls which notifications
  // may be dispatched to the front-end. It either contains:
  // - '*' -> Allow everything.
  // - Comma-separater list of ids -> Allow if aReportStringId (from
  //                                  dom.properties) is one of them.
  // - Nothing (missing or empty) -> Disable everything.
  nsAutoCString filter;
  Preferences::GetCString("media.decoder-doctor.notifications-allowed", filter);
  return filter.EqualsLiteral("*") ||
         StringListContains(filter, aNotification.mReportStringId);
}
void
DecoderDoctorDocumentWatcher::ReportAnalysis(
  const NotificationAndReportStringId& aNotification,
  bool aIsSolved,
  const nsAString& aParams)
{
  MOZ_ASSERT(NS_IsMainThread());

  if (!mDocument) {
    return;
  }

  // Report non-solved issues to console.
  if (!aIsSolved) {
    // 'params' will only be forwarded for non-empty strings.
    const char16_t* params[1] = { aParams.Data() };
    DD_DEBUG("DecoderDoctorDocumentWatcher[%p, doc=%p]::ReportAnalysis() ReportToConsole - aMsg='%s' params[0]='%s'",
             this, mDocument, aNotification.mReportStringId,
             aParams.IsEmpty() ? "<no params>" : NS_ConvertUTF16toUTF8(params[0]).get());
    nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                    NS_LITERAL_CSTRING("Media"),
                                    mDocument,
                                    nsContentUtils::eDOM_PROPERTIES,
                                    aNotification.mReportStringId,
                                    aParams.IsEmpty() ? nullptr : params,
                                    aParams.IsEmpty() ? 0 : 1);
  }

  // "media.decoder-doctor.notifications-allowed" controls which notifications
  // may be dispatched to the front-end. It either contains:
  // - '*' -> Allow everything.
  // - Comma-separater list of ids -> Allow if aReportStringId (from
  //                                  dom.properties) is one of them.
  // - Nothing (missing or empty) -> Disable everything.
  nsAdoptingCString filter =
    Preferences::GetCString("media.decoder-doctor.notifications-allowed");
  filter.StripWhitespace();
  if (filter.EqualsLiteral("*")
      || StringListContains(filter, aNotification.mReportStringId)) {
    DispatchNotification(
      mDocument->GetInnerWindow(), aNotification, aIsSolved, aParams);
  }
}
static bool
FormatsListContains(const nsAString& aList, const nsAString& aItem)
{
  return StringListContains(aList, CleanItemForFormatsList(aItem));
}