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/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"
18 static const int kMediaInternalsProxyEventDelayMilliseconds
= 100;
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
,
28 MediaInternalsProxy::MediaInternalsProxy() {
29 registrar_
.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED
,
30 NotificationService::AllBrowserContextsAndSources());
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()));
43 void MediaInternalsProxy::Attach(MediaInternalsMessageHandler
* handler
) {
44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
46 BrowserThread::PostTask(
47 BrowserThread::IO
, FROM_HERE
,
48 base::Bind(&MediaInternalsProxy::ObserveMediaInternalsOnIOThread
, this));
51 void MediaInternalsProxy::Detach() {
52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
54 BrowserThread::PostTask(
55 BrowserThread::IO
, FROM_HERE
,
57 &MediaInternalsProxy::StopObservingMediaInternalsOnIOThread
, this));
60 void MediaInternalsProxy::GetEverything() {
61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
63 // Ask MediaInternals for all its data.
64 BrowserThread::PostTask(
65 BrowserThread::IO
, FROM_HERE
,
66 base::Bind(&MediaInternalsProxy::GetEverythingOnIOThread
, this));
68 // Send the page names for constants.
69 CallJavaScriptFunctionOnUIThread("media.onReceiveConstants", GetConstants());
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
));
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;
88 if (!is_event_interesting
)
91 BrowserThread::PostTask(
92 BrowserThread::UI
, FROM_HERE
,
93 base::Bind(&MediaInternalsProxy::AddNetEventOnUIThread
, this,
97 MediaInternalsProxy::~MediaInternalsProxy() {}
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
);
111 base::DictionaryValue
* constants
= new base::DictionaryValue();
112 constants
->Set("eventTypes", net::NetLog::GetEventTypesAsValue());
113 constants
->Set("eventPhases", event_phases
);
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
);
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);
138 void MediaInternalsProxy::GetEverythingOnIOThread() {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
140 MediaInternals::GetInstance()->SendEverything();
143 void MediaInternalsProxy::UpdateUIOnUIThread(const base::string16
& update
) {
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
145 // Don't forward updates to a destructed UI.
147 handler_
->OnUpdate(update
);
150 void MediaInternalsProxy::AddNetEventOnUIThread(base::Value
* entry
) {
151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
153 // Send the updates to the page in kMediaInternalsProxyEventDelayMilliseconds
154 // if an update is not already pending.
155 if (!pending_net_updates_
) {
156 pending_net_updates_
.reset(new base::ListValue());
157 base::MessageLoop::current()->PostDelayedTask(
159 base::Bind(&MediaInternalsProxy::SendNetEventsOnUIThread
, this),
160 base::TimeDelta::FromMilliseconds(
161 kMediaInternalsProxyEventDelayMilliseconds
));
163 pending_net_updates_
->Append(entry
);
166 void MediaInternalsProxy::SendNetEventsOnUIThread() {
167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
168 CallJavaScriptFunctionOnUIThread("media.onNetUpdate",
169 pending_net_updates_
.release());
172 void MediaInternalsProxy::CallJavaScriptFunctionOnUIThread(
173 const std::string
& function
, base::Value
* args
) {
174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
175 scoped_ptr
<base::Value
> args_value(args
);
176 std::vector
<const base::Value
*> args_vector
;
177 args_vector
.push_back(args_value
.get());
178 base::string16 update
= WebUI::GetJavascriptCall(function
, args_vector
);
179 UpdateUIOnUIThread(update
);
182 } // namespace content