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.
5 #include "content/browser/media/media_internals_proxy.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "content/browser/media/media_internals_handler.h"
12 #include "content/public/browser/content_browser_client.h"
13 #include "content/public/browser/notification_service.h"
14 #include "content/public/browser/notification_types.h"
15 #include "content/public/browser/render_process_host.h"
16 #include "content/public/browser/web_ui.h"
20 static const int kMediaInternalsProxyEventDelayMilliseconds
= 100;
22 static const net::NetLog::EventType kNetEventTypeFilter
[] = {
23 net::NetLog::TYPE_DISK_CACHE_ENTRY_IMPL
,
24 net::NetLog::TYPE_SPARSE_READ
,
25 net::NetLog::TYPE_SPARSE_WRITE
,
26 net::NetLog::TYPE_URL_REQUEST_START_JOB
,
27 net::NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
30 MediaInternalsProxy::MediaInternalsProxy() {
31 registrar_
.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED
,
32 NotificationService::AllBrowserContextsAndSources());
35 void MediaInternalsProxy::Observe(int type
,
36 const NotificationSource
& source
,
37 const NotificationDetails
& details
) {
38 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
39 DCHECK_EQ(type
, NOTIFICATION_RENDERER_PROCESS_TERMINATED
);
40 RenderProcessHost
* process
= Source
<RenderProcessHost
>(source
).ptr();
41 CallJavaScriptFunctionOnUIThread("media.onRendererTerminated",
42 new base::FundamentalValue(process
->GetID()));
45 void MediaInternalsProxy::Attach(MediaInternalsMessageHandler
* handler
) {
46 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
49 update_callback_
= base::Bind(&MediaInternalsProxy::UpdateUIOnUIThread
, this);
50 MediaInternals::GetInstance()->AddUpdateCallback(update_callback_
);
52 BrowserThread::PostTask(
53 BrowserThread::IO
, FROM_HERE
,
54 base::Bind(&MediaInternalsProxy::ObserveMediaInternalsOnIOThread
, this));
57 void MediaInternalsProxy::Detach() {
58 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
61 MediaInternals::GetInstance()->RemoveUpdateCallback(update_callback_
);
63 BrowserThread::PostTask(
64 BrowserThread::IO
, FROM_HERE
,
66 &MediaInternalsProxy::StopObservingMediaInternalsOnIOThread
, this));
69 void MediaInternalsProxy::GetEverything() {
70 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
72 MediaInternals::GetInstance()->SendHistoricalMediaEvents();
74 // Ask MediaInternals for its data on IO thread.
75 BrowserThread::PostTask(
76 BrowserThread::IO
, FROM_HERE
,
77 base::Bind(&MediaInternalsProxy::GetEverythingOnIOThread
, this));
79 // Send the page names for constants.
80 CallJavaScriptFunctionOnUIThread("media.onReceiveConstants", GetConstants());
83 void MediaInternalsProxy::OnAddEntry(const net::NetLog::Entry
& entry
) {
84 bool is_event_interesting
= false;
85 for (size_t i
= 0; i
< arraysize(kNetEventTypeFilter
); i
++) {
86 if (entry
.type() == kNetEventTypeFilter
[i
]) {
87 is_event_interesting
= true;
92 if (!is_event_interesting
)
95 BrowserThread::PostTask(
96 BrowserThread::UI
, FROM_HERE
,
97 base::Bind(&MediaInternalsProxy::AddNetEventOnUIThread
, this,
101 MediaInternalsProxy::~MediaInternalsProxy() {}
103 base::Value
* MediaInternalsProxy::GetConstants() {
104 base::DictionaryValue
* event_phases
= new base::DictionaryValue();
105 event_phases
->SetInteger(
106 net::NetLog::EventPhaseToString(net::NetLog::PHASE_NONE
),
107 net::NetLog::PHASE_NONE
);
108 event_phases
->SetInteger(
109 net::NetLog::EventPhaseToString(net::NetLog::PHASE_BEGIN
),
110 net::NetLog::PHASE_BEGIN
);
111 event_phases
->SetInteger(
112 net::NetLog::EventPhaseToString(net::NetLog::PHASE_END
),
113 net::NetLog::PHASE_END
);
115 base::DictionaryValue
* constants
= new base::DictionaryValue();
116 constants
->Set("eventTypes", net::NetLog::GetEventTypesAsValue());
117 constants
->Set("eventPhases", event_phases
);
122 void MediaInternalsProxy::ObserveMediaInternalsOnIOThread() {
123 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
124 if (GetContentClient()->browser()->GetNetLog()) {
125 net::NetLog
* net_log
= GetContentClient()->browser()->GetNetLog();
126 net_log
->DeprecatedAddObserver(
127 this, net::NetLogCaptureMode::IncludeCookiesAndCredentials());
131 void MediaInternalsProxy::StopObservingMediaInternalsOnIOThread() {
132 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
133 if (GetContentClient()->browser()->GetNetLog()) {
134 net::NetLog
* net_log
= GetContentClient()->browser()->GetNetLog();
135 net_log
->DeprecatedRemoveObserver(this);
139 void MediaInternalsProxy::GetEverythingOnIOThread() {
140 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
141 // TODO(xhwang): Investigate whether we can update on UI thread directly.
142 MediaInternals::GetInstance()->SendAudioStreamData();
143 MediaInternals::GetInstance()->SendVideoCaptureDeviceCapabilities();
146 void MediaInternalsProxy::UpdateUIOnUIThread(const base::string16
& update
) {
147 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
148 // Don't forward updates to a destructed UI.
150 handler_
->OnUpdate(update
);
153 void MediaInternalsProxy::AddNetEventOnUIThread(base::Value
* entry
) {
154 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
156 // Send the updates to the page in kMediaInternalsProxyEventDelayMilliseconds
157 // if an update is not already pending.
158 if (!pending_net_updates_
) {
159 pending_net_updates_
.reset(new base::ListValue());
160 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
162 base::Bind(&MediaInternalsProxy::SendNetEventsOnUIThread
, this),
163 base::TimeDelta::FromMilliseconds(
164 kMediaInternalsProxyEventDelayMilliseconds
));
166 pending_net_updates_
->Append(entry
);
169 void MediaInternalsProxy::SendNetEventsOnUIThread() {
170 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
171 CallJavaScriptFunctionOnUIThread("media.onNetUpdate",
172 pending_net_updates_
.release());
175 void MediaInternalsProxy::CallJavaScriptFunctionOnUIThread(
176 const std::string
& function
, base::Value
* args
) {
177 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
178 scoped_ptr
<base::Value
> args_value(args
);
179 std::vector
<const base::Value
*> args_vector
;
180 args_vector
.push_back(args_value
.get());
181 base::string16 update
= WebUI::GetJavascriptCall(function
, args_vector
);
182 UpdateUIOnUIThread(update
);
185 } // namespace content