12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/media/media_internals.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_ui.h"
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/audio/audio_parameters.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/media_log.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/media_log_event.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static base::LazyInstance<content::MediaInternals>::Leaky g_media_internals =
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 SerializeUpdate(const std::string& function,
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               const base::Value* value) {
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return content::WebUI::GetJavascriptCall(
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      function, std::vector<const base::Value*>(1, value));
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::string EffectsToString(int effects) {
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (effects == media::AudioParameters::NO_EFFECTS)
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return "NO_EFFECTS";
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  struct {
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int flag;
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const char* name;
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } flags[] = {
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    { media::AudioParameters::ECHO_CANCELLER, "ECHO_CANCELLER" },
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    { media::AudioParameters::DUCKING, "DUCKING" },
3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    { media::AudioParameters::KEYBOARD_MIC, "KEYBOARD_MIC" },
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  };
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string ret;
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flags); ++i) {
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (effects & flags[i].flag) {
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (!ret.empty())
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ret += " | ";
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ret += flags[i].name;
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      effects &= ~flags[i].flag;
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (effects) {
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!ret.empty())
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ret += " | ";
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ret += base::IntToString(effects);
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return ret;
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kAudioLogStatusKey[] = "status";
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kAudioLogUpdateFunction[] = "media.updateAudioComponent";
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace content {
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class AudioLogImpl : public media::AudioLog {
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AudioLogImpl(int owner_id,
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               media::AudioLogFactory::AudioComponent component,
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               content::MediaInternals* media_internals);
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~AudioLogImpl();
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnCreated(int component_id,
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         const media::AudioParameters& params,
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         const std::string& device_id) OVERRIDE;
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnStarted(int component_id) OVERRIDE;
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnStopped(int component_id) OVERRIDE;
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnClosed(int component_id) OVERRIDE;
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnError(int component_id) OVERRIDE;
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnSetVolume(int component_id, double volume) OVERRIDE;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void SendSingleStringUpdate(int component_id,
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              const std::string& key,
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              const std::string& value);
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void StoreComponentMetadata(int component_id, base::DictionaryValue* dict);
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string FormatCacheKey(int component_id);
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int owner_id_;
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const media::AudioLogFactory::AudioComponent component_;
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  content::MediaInternals* const media_internals_;
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AudioLogImpl);
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)AudioLogImpl::AudioLogImpl(int owner_id,
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           media::AudioLogFactory::AudioComponent component,
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           content::MediaInternals* media_internals)
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : owner_id_(owner_id),
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      component_(component),
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      media_internals_(media_internals) {}
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)AudioLogImpl::~AudioLogImpl() {}
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AudioLogImpl::OnCreated(int component_id,
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             const media::AudioParameters& params,
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const std::string& device_id) {
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::DictionaryValue dict;
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StoreComponentMetadata(component_id, &dict);
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dict.SetString(kAudioLogStatusKey, "created");
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dict.SetString("device_id", device_id);
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dict.SetInteger("frames_per_buffer", params.frames_per_buffer());
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dict.SetInteger("sample_rate", params.sample_rate());
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dict.SetInteger("channels", params.channels());
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dict.SetString("channel_layout",
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 ChannelLayoutToString(params.channel_layout()));
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  dict.SetString("effects", EffectsToString(params.effects()));
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  media_internals_->SendUpdateAndCache(
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FormatCacheKey(component_id), kAudioLogUpdateFunction, &dict);
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AudioLogImpl::OnStarted(int component_id) {
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SendSingleStringUpdate(component_id, kAudioLogStatusKey, "started");
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AudioLogImpl::OnStopped(int component_id) {
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SendSingleStringUpdate(component_id, kAudioLogStatusKey, "stopped");
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AudioLogImpl::OnClosed(int component_id) {
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::DictionaryValue dict;
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StoreComponentMetadata(component_id, &dict);
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dict.SetString(kAudioLogStatusKey, "closed");
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  media_internals_->SendUpdateAndPurgeCache(
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FormatCacheKey(component_id), kAudioLogUpdateFunction, &dict);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AudioLogImpl::OnError(int component_id) {
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SendSingleStringUpdate(component_id, "error_occurred", "true");
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AudioLogImpl::OnSetVolume(int component_id, double volume) {
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::DictionaryValue dict;
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StoreComponentMetadata(component_id, &dict);
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dict.SetDouble("volume", volume);
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  media_internals_->SendUpdateAndCache(
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FormatCacheKey(component_id), kAudioLogUpdateFunction, &dict);
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string AudioLogImpl::FormatCacheKey(int component_id) {
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return base::StringPrintf("%d:%d:%d", owner_id_, component_, component_id);
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AudioLogImpl::SendSingleStringUpdate(int component_id,
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          const std::string& key,
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          const std::string& value) {
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::DictionaryValue dict;
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StoreComponentMetadata(component_id, &dict);
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dict.SetString(key, value);
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  media_internals_->SendUpdateAndCache(
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FormatCacheKey(component_id), kAudioLogUpdateFunction, &dict);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AudioLogImpl::StoreComponentMetadata(int component_id,
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          base::DictionaryValue* dict) {
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dict->SetInteger("owner_id", owner_id_);
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dict->SetInteger("component_id", component_id);
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dict->SetInteger("component_type", component_);
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)MediaInternals* MediaInternals::GetInstance() {
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return g_media_internals.Pointer();
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)MediaInternals::MediaInternals() : owner_ids_() {}
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)MediaInternals::~MediaInternals() {}
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MediaInternals::OnMediaEvents(
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int render_process_id, const std::vector<media::MediaLogEvent>& events) {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Notify observers that |event| has occurred.
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (std::vector<media::MediaLogEvent>::const_iterator event = events.begin();
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       event != events.end(); ++event) {
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::DictionaryValue dict;
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dict.SetInteger("renderer", render_process_id);
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dict.SetInteger("player", event->id);
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dict.SetString("type", media::MediaLog::EventTypeToString(event->type));
190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // TODO(dalecurtis): This is technically not correct.  TimeTicks "can't" be
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // converted to to a human readable time format.  See base/time/time.h.
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const double ticks = event->time.ToInternalValue();
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const double ticks_millis = ticks / base::Time::kMicrosecondsPerMillisecond;
195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict.SetDouble("ticksMillis", ticks_millis);
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dict.Set("params", event->params.DeepCopy());
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    SendUpdate(SerializeUpdate("media.onMediaEvent", &dict));
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) {
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  update_callbacks_.push_back(callback);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) {
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < update_callbacks_.size(); ++i) {
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (update_callbacks_[i].Equals(callback)) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      update_callbacks_.erase(update_callbacks_.begin() + i);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED();
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternals::SendEverything() {
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 everything_update;
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::AutoLock auto_lock(lock_);
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    everything_update = SerializeUpdate(
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        "media.onReceiveEverything", &cached_data_);
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SendUpdate(everything_update);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaInternals::SendUpdate(const base::string16& update) {
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // SendUpdate() may be called from any thread, but must run on the IO thread.
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // TODO(dalecurtis): This is pretty silly since the update callbacks simply
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // forward the calls to the UI thread.  We should avoid the extra hop.
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        &MediaInternals::SendUpdate, base::Unretained(this), update));
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (size_t i = 0; i < update_callbacks_.size(); i++)
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    update_callbacks_[i].Run(update);
2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)scoped_ptr<media::AudioLog> MediaInternals::CreateAudioLog(
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    AudioComponent component) {
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::AutoLock auto_lock(lock_);
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return scoped_ptr<media::AudioLog>(new AudioLogImpl(
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      owner_ids_[component]++, component, this));
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaInternals::SendUpdateAndCache(const std::string& cache_key,
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        const std::string& function,
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        const base::DictionaryValue* value) {
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SendUpdate(SerializeUpdate(function, value));
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::AutoLock auto_lock(lock_);
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!cached_data_.HasKey(cache_key)) {
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    cached_data_.Set(cache_key, value->DeepCopy());
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::DictionaryValue* existing_dict = NULL;
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  CHECK(cached_data_.GetDictionary(cache_key, &existing_dict));
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  existing_dict->MergeDictionary(value);
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaInternals::SendUpdateAndPurgeCache(
265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& cache_key,
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& function,
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const base::DictionaryValue* value) {
268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SendUpdate(SerializeUpdate(function, value));
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::AutoLock auto_lock(lock_);
271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<base::Value> out_value;
272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  CHECK(cached_data_.Remove(cache_key, &out_value));
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
276