Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / media / media_internals_proxy.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/media/media_internals_proxy.h"
6
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "content/browser/media/media_internals_handler.h"
10 #include "content/public/browser/content_browser_client.h"
11 #include "content/public/browser/notification_service.h"
12 #include "content/public/browser/notification_types.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/browser/web_ui.h"
15
16 namespace content {
17
18 static const int kMediaInternalsProxyEventDelayMilliseconds = 100;
19
20 static const net::NetLog::EventType kNetEventTypeFilter[] = {
21   net::NetLog::TYPE_DISK_CACHE_ENTRY_IMPL,
22   net::NetLog::TYPE_SPARSE_READ,
23   net::NetLog::TYPE_SPARSE_WRITE,
24   net::NetLog::TYPE_URL_REQUEST_START_JOB,
25   net::NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
26 };
27
28 MediaInternalsProxy::MediaInternalsProxy() {
29   registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
30                  NotificationService::AllBrowserContextsAndSources());
31 }
32
33 void MediaInternalsProxy::Observe(int type,
34                                   const NotificationSource& source,
35                                   const NotificationDetails& details) {
36   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
37   DCHECK_EQ(type, NOTIFICATION_RENDERER_PROCESS_TERMINATED);
38   RenderProcessHost* process = Source<RenderProcessHost>(source).ptr();
39   CallJavaScriptFunctionOnUIThread("media.onRendererTerminated",
40       new base::FundamentalValue(process->GetID()));
41 }
42
43 void MediaInternalsProxy::Attach(MediaInternalsMessageHandler* handler) {
44   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
45   handler_ = handler;
46   BrowserThread::PostTask(
47       BrowserThread::IO, FROM_HERE,
48       base::Bind(&MediaInternalsProxy::ObserveMediaInternalsOnIOThread, this));
49 }
50
51 void MediaInternalsProxy::Detach() {
52   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
53   handler_ = NULL;
54   BrowserThread::PostTask(
55       BrowserThread::IO, FROM_HERE,
56       base::Bind(
57           &MediaInternalsProxy::StopObservingMediaInternalsOnIOThread, this));
58 }
59
60 void MediaInternalsProxy::GetEverything() {
61   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
62
63   // Ask MediaInternals for all its data.
64   BrowserThread::PostTask(
65       BrowserThread::IO, FROM_HERE,
66       base::Bind(&MediaInternalsProxy::GetEverythingOnIOThread, this));
67
68   // Send the page names for constants.
69   CallJavaScriptFunctionOnUIThread("media.onReceiveConstants", GetConstants());
70 }
71
72 void MediaInternalsProxy::OnUpdate(const base::string16& update) {
73   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
74   BrowserThread::PostTask(
75       BrowserThread::UI, FROM_HERE,
76       base::Bind(&MediaInternalsProxy::UpdateUIOnUIThread, this, update));
77 }
78
79 void MediaInternalsProxy::OnAddEntry(const net::NetLog::Entry& entry) {
80   bool is_event_interesting = false;
81   for (size_t i = 0; i < arraysize(kNetEventTypeFilter); i++) {
82     if (entry.type() == kNetEventTypeFilter[i]) {
83       is_event_interesting = true;
84       break;
85     }
86   }
87
88   if (!is_event_interesting)
89     return;
90
91   BrowserThread::PostTask(
92       BrowserThread::UI, FROM_HERE,
93       base::Bind(&MediaInternalsProxy::AddNetEventOnUIThread, this,
94                  entry.ToValue()));
95 }
96
97 MediaInternalsProxy::~MediaInternalsProxy() {}
98
99 base::Value* MediaInternalsProxy::GetConstants() {
100   base::DictionaryValue* event_phases = new base::DictionaryValue();
101   event_phases->SetInteger(
102       net::NetLog::EventPhaseToString(net::NetLog::PHASE_NONE),
103       net::NetLog::PHASE_NONE);
104   event_phases->SetInteger(
105       net::NetLog::EventPhaseToString(net::NetLog::PHASE_BEGIN),
106       net::NetLog::PHASE_BEGIN);
107   event_phases->SetInteger(
108       net::NetLog::EventPhaseToString(net::NetLog::PHASE_END),
109       net::NetLog::PHASE_END);
110
111   base::DictionaryValue* constants = new base::DictionaryValue();
112   constants->Set("eventTypes", net::NetLog::GetEventTypesAsValue());
113   constants->Set("eventPhases", event_phases);
114
115   return constants;
116 }
117
118 void MediaInternalsProxy::ObserveMediaInternalsOnIOThread() {
119   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
120   update_callback_ = base::Bind(&MediaInternalsProxy::OnUpdate,
121                                 base::Unretained(this));
122   MediaInternals::GetInstance()->AddUpdateCallback(update_callback_);
123   if (GetContentClient()->browser()->GetNetLog()) {
124     net::NetLog* net_log = GetContentClient()->browser()->GetNetLog();
125     net_log->AddThreadSafeObserver(this, net::NetLog::LOG_ALL_BUT_BYTES);
126   }
127 }
128
129 void MediaInternalsProxy::StopObservingMediaInternalsOnIOThread() {
130   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
131   MediaInternals::GetInstance()->RemoveUpdateCallback(update_callback_);
132   if (GetContentClient()->browser()->GetNetLog()) {
133     net::NetLog* net_log = GetContentClient()->browser()->GetNetLog();
134     net_log->RemoveThreadSafeObserver(this);
135   }
136 }
137
138 void MediaInternalsProxy::GetEverythingOnIOThread() {
139   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
140   MediaInternals::GetInstance()->SendAudioStreamData();
141   MediaInternals::GetInstance()->SendVideoCaptureDeviceCapabilities();
142 }
143
144 void MediaInternalsProxy::UpdateUIOnUIThread(const base::string16& update) {
145   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
146   // Don't forward updates to a destructed UI.
147   if (handler_)
148     handler_->OnUpdate(update);
149 }
150
151 void MediaInternalsProxy::AddNetEventOnUIThread(base::Value* entry) {
152   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
153
154   // Send the updates to the page in kMediaInternalsProxyEventDelayMilliseconds
155   // if an update is not already pending.
156   if (!pending_net_updates_) {
157     pending_net_updates_.reset(new base::ListValue());
158     base::MessageLoop::current()->PostDelayedTask(
159         FROM_HERE,
160         base::Bind(&MediaInternalsProxy::SendNetEventsOnUIThread, this),
161         base::TimeDelta::FromMilliseconds(
162             kMediaInternalsProxyEventDelayMilliseconds));
163   }
164   pending_net_updates_->Append(entry);
165 }
166
167 void MediaInternalsProxy::SendNetEventsOnUIThread() {
168   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
169   CallJavaScriptFunctionOnUIThread("media.onNetUpdate",
170                                    pending_net_updates_.release());
171 }
172
173 void MediaInternalsProxy::CallJavaScriptFunctionOnUIThread(
174     const std::string& function, base::Value* args) {
175   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
176   scoped_ptr<base::Value> args_value(args);
177   std::vector<const base::Value*> args_vector;
178   args_vector.push_back(args_value.get());
179   base::string16 update = WebUI::GetJavascriptCall(function, args_vector);
180   UpdateUIOnUIThread(update);
181 }
182
183 }  // namespace content