// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/media/media_internals.h"

#include <stddef.h>

#include <tuple>
#include <utility>

#include "base/macros.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "content/browser/media/mojo_audio_logging_adapter.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "media/base/audio_parameters.h"
#include "media/base/media_log_event.h"
#include "media/filters/gpu_video_decoder.h"
#include "mojo/public/cpp/bindings/strong_binding.h"

#if !defined(OS_ANDROID)
#include "media/filters/decrypting_video_decoder.h"
#endif

namespace {

base::string16 SerializeUpdate(const std::string& function,
                               const base::Value* value) {
  return content::WebUI::GetJavascriptCall(
      function, std::vector<const base::Value*>(1, value));
}

std::string EffectsToString(int effects) {
  if (effects == media::AudioParameters::NO_EFFECTS)
    return "NO_EFFECTS";

  struct {
    int flag;
    const char* name;
  } flags[] = {
      {media::AudioParameters::ECHO_CANCELLER, "ECHO_CANCELLER"},
      {media::AudioParameters::DUCKING, "DUCKING"},
      {media::AudioParameters::KEYBOARD_MIC, "KEYBOARD_MIC"},
      {media::AudioParameters::HOTWORD, "HOTWORD"},
  };

  std::string ret;
  for (size_t i = 0; i < arraysize(flags); ++i) {
    if (effects & flags[i].flag) {
      if (!ret.empty())
        ret += " | ";
      ret += flags[i].name;
      effects &= ~flags[i].flag;
    }
  }

  if (effects) {
    if (!ret.empty())
      ret += " | ";
    ret += base::IntToString(effects);
  }

  return ret;
}

std::string FormatToString(media::AudioParameters::Format format) {
  switch (format) {
    case media::AudioParameters::AUDIO_PCM_LINEAR:
      return "pcm_linear";
    case media::AudioParameters::AUDIO_PCM_LOW_LATENCY:
      return "pcm_low_latency";
    case media::AudioParameters::AUDIO_BITSTREAM_AC3:
      return "ac3";
    case media::AudioParameters::AUDIO_BITSTREAM_EAC3:
      return "eac3";
    case media::AudioParameters::AUDIO_FAKE:
      return "fake";
  }

  NOTREACHED();
  return "unknown";
}

// Whether the player is in incognito mode or ChromeOS guest mode.
bool IsIncognito(int render_process_id) {
  content::RenderProcessHost* render_process_host =
      content::RenderProcessHost::FromID(render_process_id);
  if (!render_process_host) {
    // This could happen in tests.
    LOG(ERROR) << "Cannot get RenderProcessHost";
    return false;
  }

  content::BrowserContext* browser_context =
      render_process_host->GetBrowserContext();
  DCHECK(browser_context);

  return browser_context->IsOffTheRecord();
}

const char kAudioLogStatusKey[] = "status";
const char kAudioLogUpdateFunction[] = "media.updateAudioComponent";

}  // namespace

namespace content {

class AudioLogImpl : public media::mojom::AudioLog {
 public:
  AudioLogImpl(int owner_id,
               media::AudioLogFactory::AudioComponent component,
               content::MediaInternals* media_internals,
               int component_id,
               int render_process_id,
               int render_frame_id);
  ~AudioLogImpl() override;

  void OnCreated(const media::AudioParameters& params,
                 const std::string& device_id) override;
  void OnStarted() override;
  void OnStopped() override;
  void OnClosed() override;
  void OnError() override;
  void OnSetVolume(double volume) override;
  void OnLogMessage(const std::string& message) override;

 private:
  // If possible, i.e. a WebContents exists for the given RenderFrameHostID,
  // tells an existing AudioLogEntry the WebContents title for easier
  // differentiation on the UI. Note that the log entry must be created (by
  // calling OnCreated() before calling this method.
  void SetWebContentsTitle();

  void SendSingleStringUpdate(const std::string& key, const std::string& value);
  void StoreComponentMetadata(base::DictionaryValue* dict);
  std::string FormatCacheKey();

  static void SendWebContentsTitleHelper(
      const std::string& cache_key,
      std::unique_ptr<base::DictionaryValue> dict,
      int render_process_id,
      int render_frame_id);

  const int owner_id_;
  const media::AudioLogFactory::AudioComponent component_;
  content::MediaInternals* const media_internals_;
  const int component_id_;
  const int render_process_id_;
  const int render_frame_id_;

  DISALLOW_COPY_AND_ASSIGN(AudioLogImpl);
};

AudioLogImpl::AudioLogImpl(int owner_id,
                           media::AudioLogFactory::AudioComponent component,
                           content::MediaInternals* media_internals,
                           int component_id,
                           int render_process_id,
                           int render_frame_id)
    : owner_id_(owner_id),
      component_(component),
      media_internals_(media_internals),
      component_id_(component_id),
      render_process_id_(render_process_id),
      render_frame_id_(render_frame_id) {}

AudioLogImpl::~AudioLogImpl() {}

void AudioLogImpl::OnCreated(const media::AudioParameters& params,
                             const std::string& device_id) {
  base::DictionaryValue dict;
  StoreComponentMetadata(&dict);

  dict.SetString(kAudioLogStatusKey, "created");
  dict.SetString("device_id", device_id);
  dict.SetString("device_type", FormatToString(params.format()));
  dict.SetInteger("frames_per_buffer", params.frames_per_buffer());
  dict.SetInteger("sample_rate", params.sample_rate());
  dict.SetInteger("channels", params.channels());
  dict.SetString("channel_layout",
                 ChannelLayoutToString(params.channel_layout()));
  dict.SetString("effects", EffectsToString(params.effects()));

  media_internals_->UpdateAudioLog(MediaInternals::CREATE, FormatCacheKey(),
                                   kAudioLogUpdateFunction, &dict);
  SetWebContentsTitle();
}

void AudioLogImpl::OnStarted() {
  SendSingleStringUpdate(kAudioLogStatusKey, "started");
}

void AudioLogImpl::OnStopped() {
  SendSingleStringUpdate(kAudioLogStatusKey, "stopped");
}

void AudioLogImpl::OnClosed() {
  base::DictionaryValue dict;
  StoreComponentMetadata(&dict);
  dict.SetString(kAudioLogStatusKey, "closed");
  media_internals_->UpdateAudioLog(MediaInternals::UPDATE_AND_DELETE,
                                   FormatCacheKey(), kAudioLogUpdateFunction,
                                   &dict);
}

void AudioLogImpl::OnError() {
  SendSingleStringUpdate("error_occurred", "true");
}

void AudioLogImpl::OnSetVolume(double volume) {
  base::DictionaryValue dict;
  StoreComponentMetadata(&dict);
  dict.SetDouble("volume", volume);
  media_internals_->UpdateAudioLog(MediaInternals::UPDATE_IF_EXISTS,
                                   FormatCacheKey(), kAudioLogUpdateFunction,
                                   &dict);
}

void AudioLogImpl::OnLogMessage(const std::string& message) {
  MediaStreamManager::SendMessageToNativeLog(message);
}

void AudioLogImpl::SetWebContentsTitle() {
  if (render_process_id_ < 0 || render_frame_id_ < 0)
    return;
  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
  StoreComponentMetadata(dict.get());
  SendWebContentsTitleHelper(FormatCacheKey(), std::move(dict),
                             render_process_id_, render_frame_id_);
}

std::string AudioLogImpl::FormatCacheKey() {
  return base::StringPrintf("%d:%d:%d", owner_id_, component_, component_id_);
}

// static
void AudioLogImpl::SendWebContentsTitleHelper(
    const std::string& cache_key,
    std::unique_ptr<base::DictionaryValue> dict,
    int render_process_id,
    int render_frame_id) {
  // Page title information can only be retrieved from the UI thread.
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::BindOnce(&SendWebContentsTitleHelper, cache_key, std::move(dict),
                       render_process_id, render_frame_id));
    return;
  }

  const WebContents* web_contents = WebContents::FromRenderFrameHost(
      RenderFrameHost::FromID(render_process_id, render_frame_id));
  if (!web_contents)
    return;

  // Note: by this point the given audio log entry could have been destroyed, so
  // we use UPDATE_IF_EXISTS to discard such instances.
  dict->SetInteger("render_process_id", render_process_id);
  dict->SetString("web_contents_title", web_contents->GetTitle());
  MediaInternals::GetInstance()->UpdateAudioLog(
      MediaInternals::UPDATE_IF_EXISTS, cache_key, kAudioLogUpdateFunction,
      dict.get());
}

void AudioLogImpl::SendSingleStringUpdate(const std::string& key,
                                          const std::string& value) {
  base::DictionaryValue dict;
  StoreComponentMetadata(&dict);
  dict.SetString(key, value);
  media_internals_->UpdateAudioLog(MediaInternals::UPDATE_IF_EXISTS,
                                   FormatCacheKey(), kAudioLogUpdateFunction,
                                   &dict);
}

void AudioLogImpl::StoreComponentMetadata(base::DictionaryValue* dict) {
  dict->SetInteger("owner_id", owner_id_);
  dict->SetInteger("component_id", component_id_);
  dict->SetInteger("component_type", component_);
}

// This class lives on the browser UI thread.
class MediaInternals::MediaInternalsUMAHandler {
 public:
  MediaInternalsUMAHandler();

  // Called when a render process is terminated. Reports the pipeline status to
  // UMA for every player associated with the renderer process and then deletes
  // the player state.
  void OnProcessTerminated(int render_process_id);

  // Helper function to save the event payload to RendererPlayerMap.
  void SavePlayerState(int render_process_id,
                       const media::MediaLogEvent& event);

 private:
  struct PipelineInfo {
    explicit PipelineInfo(bool is_incognito) : is_incognito(is_incognito) {}

    bool has_pipeline = false;
    bool has_ever_played = false;
    bool has_reached_have_enough = false;
    media::PipelineStatus last_pipeline_status = media::PIPELINE_OK;
    bool has_audio = false;
    bool has_video = false;
    bool video_dds = false;
    bool video_decoder_changed = false;
    bool has_cdm = false;
    bool is_incognito = false;
    std::string audio_codec_name;
    std::string video_codec_name;
    std::string video_decoder;
    GURL origin_url;
  };

  // Helper function to report PipelineStatus associated with a player to UMA.
  void ReportUMAForPipelineStatus(const PipelineInfo& player_info);

  // Helper to generate PipelineStatus UMA name for AudioVideo streams.
  std::string GetUMANameForAVStream(const PipelineInfo& player_info);

  // Key is player id.
  typedef std::map<int, PipelineInfo> PlayerInfoMap;

  // Key is renderer id.
  typedef std::map<int, PlayerInfoMap> RendererPlayerMap;

  // Stores player information per renderer.
  RendererPlayerMap renderer_info_;

  DISALLOW_COPY_AND_ASSIGN(MediaInternalsUMAHandler);
};

MediaInternals::MediaInternalsUMAHandler::MediaInternalsUMAHandler() {}

void MediaInternals::MediaInternalsUMAHandler::SavePlayerState(
    int render_process_id,
    const media::MediaLogEvent& event) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  PlayerInfoMap& player_info_map = renderer_info_[render_process_id];

  auto it = player_info_map.find(event.id);
  if (it == player_info_map.end()) {
    bool success = false;
    std::tie(it, success) = player_info_map.emplace(
        std::make_pair(event.id, PipelineInfo(IsIncognito(render_process_id))));
    if (!success) {
      LOG(ERROR) << "Failed to insert a new PipelineInfo.";
      return;
    }
  }

  PipelineInfo& player_info = it->second;

  switch (event.type) {
    case media::MediaLogEvent::Type::WEBMEDIAPLAYER_CREATED: {
      std::string origin_url;
      event.params.GetString("origin_url", &origin_url);
      player_info.origin_url = GURL(origin_url);
      break;
    }
    case media::MediaLogEvent::PLAY: {
      player_info.has_ever_played = true;
      break;
    }
    case media::MediaLogEvent::PIPELINE_STATE_CHANGED: {
      player_info.has_pipeline = true;
      break;
    }
    case media::MediaLogEvent::PIPELINE_ERROR: {
      int status = static_cast<media::PipelineStatus>(media::PIPELINE_OK);
      event.params.GetInteger("pipeline_error", &status);
      player_info.last_pipeline_status =
          static_cast<media::PipelineStatus>(status);
      break;
    }
    case media::MediaLogEvent::PROPERTY_CHANGE:
      if (event.params.HasKey("found_audio_stream")) {
        event.params.GetBoolean("found_audio_stream", &player_info.has_audio);
      }
      if (event.params.HasKey("found_video_stream")) {
        event.params.GetBoolean("found_video_stream", &player_info.has_video);
      }
      if (event.params.HasKey("audio_codec_name")) {
        event.params.GetString("audio_codec_name",
                               &player_info.audio_codec_name);
      }
      if (event.params.HasKey("video_codec_name")) {
        event.params.GetString("video_codec_name",
                               &player_info.video_codec_name);
      }
      if (event.params.HasKey("video_decoder")) {
        std::string previous_video_decoder(player_info.video_decoder);
        event.params.GetString("video_decoder", &player_info.video_decoder);
        if (!previous_video_decoder.empty() &&
            previous_video_decoder != player_info.video_decoder) {
          player_info.video_decoder_changed = true;
        }
      }
      if (event.params.HasKey("video_dds")) {
        event.params.GetBoolean("video_dds", &player_info.video_dds);
      }
      if (event.params.HasKey("has_cdm")) {
        event.params.GetBoolean("has_cdm", &player_info.has_cdm);
      }
      if (event.params.HasKey("pipeline_buffering_state")) {
        std::string buffering_state;
        event.params.GetString("pipeline_buffering_state", &buffering_state);

        bool for_suspended_start;
        event.params.GetBoolean("for_suspended_start", &for_suspended_start);

        // Ignore the BUFFERING_HAVE_ENOUGH event if it was for a suspended
        // start. Otherwise we won't reflect reductions to the HasEverPlayed
        // statistic.
        if (buffering_state == "BUFFERING_HAVE_ENOUGH" && !for_suspended_start)
          player_info.has_reached_have_enough = true;
      }
      break;
    case media::MediaLogEvent::Type::WEBMEDIAPLAYER_DESTROYED: {
      // Upon player destruction report UMA data; if the player is not torn down
      // before process exit, it will be logged during OnProcessTerminated().
      ReportUMAForPipelineStatus(player_info);
      player_info_map.erase(it);
      break;
    }
    default:
      break;
  }
  return;
}

std::string MediaInternals::MediaInternalsUMAHandler::GetUMANameForAVStream(
    const PipelineInfo& player_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  static const char kPipelineUmaPrefix[] = "Media.PipelineStatus.AudioVideo.";
  std::string uma_name = kPipelineUmaPrefix;
  if (player_info.video_codec_name == "vp8") {
    uma_name += "VP8.";
  } else if (player_info.video_codec_name == "vp9") {
    uma_name += "VP9.";
  } else if (player_info.video_codec_name == "h264") {
    uma_name += "H264.";
  } else {
    return uma_name + "Other";
  }

#if !defined(OS_ANDROID)
  if (player_info.video_decoder ==
      media::DecryptingVideoDecoder::kDecoderName) {
    return uma_name + "DVD";
  }
#endif

  if (player_info.video_dds) {
    uma_name += "DDS.";
  }

  if (player_info.video_decoder == media::GpuVideoDecoder::kDecoderName ||
      player_info.video_decoder == "MojoVideoDecoder") {
    uma_name += "HW";
  } else {
    uma_name += "SW";
  }
  return uma_name;
}

// TODO(xhwang): This function reports more metrics than just pipeline status
// and should be renamed. Similarly, PipelineInfo should be PlayerInfo.
void MediaInternals::MediaInternalsUMAHandler::ReportUMAForPipelineStatus(
    const PipelineInfo& player_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Don't log pipeline status for players which don't actually have a pipeline;
  // e.g., the Android MediaSourcePlayer implementation.
  if (!player_info.has_pipeline)
    return;

  if (player_info.has_video && player_info.has_audio) {
    base::UmaHistogramExactLinear(GetUMANameForAVStream(player_info),
                                  player_info.last_pipeline_status,
                                  media::PIPELINE_STATUS_MAX);
  } else if (player_info.has_audio) {
    UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.AudioOnly",
                              player_info.last_pipeline_status,
                              media::PIPELINE_STATUS_MAX + 1);
  } else if (player_info.has_video) {
    UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.VideoOnly",
                              player_info.last_pipeline_status,
                              media::PIPELINE_STATUS_MAX + 1);
  } else {
    // Note: This metric can be recorded as a result of normal operation with
    // Media Source Extensions. If a site creates a MediaSource object but never
    // creates a source buffer or appends data, PIPELINE_OK will be recorded.
    UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.Unsupported",
                              player_info.last_pipeline_status,
                              media::PIPELINE_STATUS_MAX + 1);
  }
  // Report whether video decoder fallback happened, but only if a video decoder
  // was reported.
  if (!player_info.video_decoder.empty()) {
    UMA_HISTOGRAM_BOOLEAN("Media.VideoDecoderFallback",
                          player_info.video_decoder_changed);
  }

  // Report whether this player ever saw a playback event. Used to measure the
  // effectiveness of efforts to reduce loaded-but-never-used players.
  if (player_info.has_reached_have_enough)
    UMA_HISTOGRAM_BOOLEAN("Media.HasEverPlayed", player_info.has_ever_played);

  // Report whether an encrypted playback is in incognito window, excluding
  // never-used players.
  if (player_info.has_cdm && player_info.has_ever_played)
    UMA_HISTOGRAM_BOOLEAN("Media.EME.IsIncognito", player_info.is_incognito);
}

void MediaInternals::MediaInternalsUMAHandler::OnProcessTerminated(
    int render_process_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  auto players_it = renderer_info_.find(render_process_id);
  if (players_it == renderer_info_.end())
    return;
  auto it = players_it->second.begin();
  while (it != players_it->second.end()) {
    ReportUMAForPipelineStatus(it->second);
    players_it->second.erase(it++);
  }
  renderer_info_.erase(players_it);
}

MediaInternals* MediaInternals::GetInstance() {
  static content::MediaInternals* internals = new content::MediaInternals();
  return internals;
}

MediaInternals::MediaInternals()
    : can_update_(false),
      owner_ids_(),
      uma_handler_(new MediaInternalsUMAHandler()) {
  // TODO(sandersd): Is there ever a relevant case where TERMINATED is sent
  // without CLOSED also being sent?
  registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED,
                 NotificationService::AllBrowserContextsAndSources());
  registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
                 NotificationService::AllBrowserContextsAndSources());
}

MediaInternals::~MediaInternals() {}

void MediaInternals::Observe(int type,
                             const NotificationSource& source,
                             const NotificationDetails& details) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  RenderProcessHost* process = Source<RenderProcessHost>(source).ptr();
  uma_handler_->OnProcessTerminated(process->GetID());
  // TODO(sandersd): Send a termination event before clearing the log.
  saved_events_by_process_.erase(process->GetID());
}

// Converts the |event| to a |update|. Returns whether the conversion succeeded.
static bool ConvertEventToUpdate(int render_process_id,
                                 const media::MediaLogEvent& event,
                                 base::string16* update) {
  DCHECK(update);

  base::DictionaryValue dict;
  dict.SetInteger("renderer", render_process_id);
  dict.SetInteger("player", event.id);
  dict.SetString("type", media::MediaLog::EventTypeToString(event.type));

  // TODO(dalecurtis): This is technically not correct.  TimeTicks "can't" be
  // converted to to a human readable time format.  See base/time/time.h.
  const double ticks = event.time.ToInternalValue();
  const double ticks_millis = ticks / base::Time::kMicrosecondsPerMillisecond;
  dict.SetDouble("ticksMillis", ticks_millis);

  // Convert PipelineStatus to human readable string
  if (event.type == media::MediaLogEvent::PIPELINE_ERROR) {
    int status;
    if (!event.params.GetInteger("pipeline_error", &status) ||
        status < static_cast<int>(media::PIPELINE_OK) ||
        status > static_cast<int>(media::PIPELINE_STATUS_MAX)) {
      return false;
    }
    media::PipelineStatus error = static_cast<media::PipelineStatus>(status);
    dict.SetString("params.pipeline_error",
                   media::MediaLog::PipelineStatusToString(error));
  } else {
    dict.SetKey("params", event.params.Clone());
  }

  *update = SerializeUpdate("media.onMediaEvent", &dict);
  return true;
}

void MediaInternals::OnMediaEvents(
    int render_process_id,
    const std::vector<media::MediaLogEvent>& events) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  // Notify observers that |event| has occurred.
  for (const auto& event : events) {
    if (CanUpdate()) {
      base::string16 update;
      if (ConvertEventToUpdate(render_process_id, event, &update))
        SendUpdate(update);
    }
    SaveEvent(render_process_id, event);
    uma_handler_->SavePlayerState(render_process_id, event);
  }
}

void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  update_callbacks_.push_back(callback);

  base::AutoLock auto_lock(lock_);
  can_update_ = true;
}

void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  for (size_t i = 0; i < update_callbacks_.size(); ++i) {
    if (update_callbacks_[i].Equals(callback)) {
      update_callbacks_.erase(update_callbacks_.begin() + i);
      break;
    }
  }

  base::AutoLock auto_lock(lock_);
  can_update_ = !update_callbacks_.empty();
}

bool MediaInternals::CanUpdate() {
  base::AutoLock auto_lock(lock_);
  return can_update_;
}

void MediaInternals::SendHistoricalMediaEvents() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  for (const auto& saved_events : saved_events_by_process_) {
    for (const auto& event : saved_events.second) {
      base::string16 update;
      if (ConvertEventToUpdate(saved_events.first, event, &update))
        SendUpdate(update);
    }
  }
  // Do not clear the map/list here so that refreshing the UI or opening a
  // second UI still works nicely!
}

void MediaInternals::SendAudioStreamData() {
  base::string16 audio_stream_update;
  {
    base::AutoLock auto_lock(lock_);
    audio_stream_update = SerializeUpdate("media.onReceiveAudioStreamData",
                                          &audio_streams_cached_data_);
  }
  SendUpdate(audio_stream_update);
}

void MediaInternals::SendVideoCaptureDeviceCapabilities() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (!CanUpdate())
    return;

  SendUpdate(SerializeUpdate("media.onReceiveVideoCaptureCapabilities",
                             &video_capture_capabilities_cached_data_));
}

void MediaInternals::UpdateVideoCaptureDeviceCapabilities(
    const std::vector<std::tuple<media::VideoCaptureDeviceDescriptor,
                                 media::VideoCaptureFormats>>&
        descriptors_and_formats) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  video_capture_capabilities_cached_data_.Clear();

  for (const auto& device_format_pair : descriptors_and_formats) {
    auto format_list = std::make_unique<base::ListValue>();
    // TODO(nisse): Representing format information as a string, to be
    // parsed by the javascript handler, is brittle. Consider passing
    // a list of mappings instead.

    const media::VideoCaptureDeviceDescriptor& descriptor =
        std::get<0>(device_format_pair);
    const media::VideoCaptureFormats& supported_formats =
        std::get<1>(device_format_pair);
    for (const auto& format : supported_formats)
      format_list->AppendString(media::VideoCaptureFormat::ToString(format));

    std::unique_ptr<base::DictionaryValue> device_dict(
        new base::DictionaryValue());
    device_dict->SetString("id", descriptor.device_id);
    device_dict->SetString("name", descriptor.GetNameAndModel());
    device_dict->Set("formats", std::move(format_list));
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
    defined(OS_ANDROID)
    device_dict->SetString("captureApi", descriptor.GetCaptureApiTypeString());
#endif
    video_capture_capabilities_cached_data_.Append(std::move(device_dict));
  }

  SendVideoCaptureDeviceCapabilities();
}

std::unique_ptr<media::AudioLog> MediaInternals::CreateAudioLog(
    AudioComponent component,
    int component_id) {
  return std::make_unique<MojoAudioLogAdapter>(
      CreateMojoAudioLog(component, component_id));
}

media::mojom::AudioLogPtr MediaInternals::CreateMojoAudioLog(
    media::AudioLogFactory::AudioComponent component,
    int component_id,
    int render_process_id,
    int render_frame_id) {
  base::AutoLock auto_lock(lock_);
  media::mojom::AudioLogPtr audio_log_ptr;
  mojo::MakeStrongBinding(std::make_unique<AudioLogImpl>(
                              owner_ids_[component]++, component, this,
                              component_id, render_process_id, render_frame_id),
                          mojo::MakeRequest(&audio_log_ptr));
  return audio_log_ptr;
}

void MediaInternals::OnProcessTerminatedForTesting(int process_id) {
  uma_handler_->OnProcessTerminated(process_id);
}

void MediaInternals::SendUpdate(const base::string16& update) {
  // SendUpdate() may be called from any thread, but must run on the UI thread.
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                            base::BindOnce(&MediaInternals::SendUpdate,
                                           base::Unretained(this), update));
    return;
  }

  for (size_t i = 0; i < update_callbacks_.size(); i++)
    update_callbacks_[i].Run(update);
}

void MediaInternals::SaveEvent(int process_id,
                               const media::MediaLogEvent& event) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

// Save the event and limit the total number per renderer. At the time of
// writing, 512 events of the kind: { "property": value } together consume
// ~88kb of memory on linux.
#if defined(OS_ANDROID)
  const size_t kEventLimit = 128;
#else
  const size_t kEventLimit = 512;
#endif

  auto& saved_events = saved_events_by_process_[process_id];
  saved_events.push_back(event);
  if (saved_events.size() > kEventLimit) {
    // Remove all events for a given player as soon as we have to remove a
    // single event for that player to avoid showing incomplete players.
    const int id_to_remove = saved_events.front().id;
    saved_events.erase(std::remove_if(saved_events.begin(), saved_events.end(),
                                      [&](const media::MediaLogEvent& event) {
                                        return event.id == id_to_remove;
                                      }),
                       saved_events.end());
  }
}

void MediaInternals::UpdateAudioLog(AudioLogUpdateType type,
                                    const std::string& cache_key,
                                    const std::string& function,
                                    const base::DictionaryValue* value) {
  {
    base::AutoLock auto_lock(lock_);
    const bool has_entry = audio_streams_cached_data_.HasKey(cache_key);
    if ((type == UPDATE_IF_EXISTS || type == UPDATE_AND_DELETE) && !has_entry) {
      return;
    } else if (!has_entry) {
      DCHECK_EQ(type, CREATE);
      audio_streams_cached_data_.Set(
          cache_key, std::make_unique<base::Value>(value->Clone()));
    } else if (type == UPDATE_AND_DELETE) {
      std::unique_ptr<base::Value> out_value;
      CHECK(audio_streams_cached_data_.Remove(cache_key, &out_value));
    } else {
      base::DictionaryValue* existing_dict = nullptr;
      CHECK(
          audio_streams_cached_data_.GetDictionary(cache_key, &existing_dict));
      existing_dict->MergeDictionary(value);
    }
  }

  if (CanUpdate())
    SendUpdate(SerializeUpdate(function, value));
}

}  // namespace content
