OLD | NEW |
| (Empty) |
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 "chrome/browser/ui/webui/media/media_internals_proxy.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "chrome/browser/browser_process.h" | |
9 #include "chrome/browser/io_thread.h" | |
10 #include "chrome/browser/media/media_internals.h" | |
11 #include "chrome/browser/net/chrome_net_log.h" | |
12 #include "chrome/browser/ui/webui/media/media_internals_handler.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" | |
17 | |
18 using content::BrowserThread; | |
19 | |
20 static const int kMediaInternalsProxyEventDelayMilliseconds = 100; | |
21 | |
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, | |
28 }; | |
29 | |
30 MediaInternalsProxy::MediaInternalsProxy() { | |
31 io_thread_ = g_browser_process->io_thread(); | |
32 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | |
33 content::NotificationService::AllBrowserContextsAndSources()); | |
34 } | |
35 | |
36 void MediaInternalsProxy::Observe(int type, | |
37 const content::NotificationSource& source, | |
38 const content::NotificationDetails& details) { | |
39 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
40 DCHECK_EQ(type, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); | |
41 content::RenderProcessHost* process = | |
42 content::Source<content::RenderProcessHost>(source).ptr(); | |
43 CallJavaScriptFunctionOnUIThread("media.onRendererTerminated", | |
44 base::Value::CreateIntegerValue(process->GetID())); | |
45 } | |
46 | |
47 void MediaInternalsProxy::Attach(MediaInternalsMessageHandler* handler) { | |
48 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
49 handler_ = handler; | |
50 BrowserThread::PostTask( | |
51 BrowserThread::IO, FROM_HERE, | |
52 base::Bind(&MediaInternalsProxy::ObserveMediaInternalsOnIOThread, this)); | |
53 } | |
54 | |
55 void MediaInternalsProxy::Detach() { | |
56 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
57 handler_ = NULL; | |
58 BrowserThread::PostTask( | |
59 BrowserThread::IO, FROM_HERE, | |
60 base::Bind( | |
61 &MediaInternalsProxy::StopObservingMediaInternalsOnIOThread, this)); | |
62 } | |
63 | |
64 void MediaInternalsProxy::GetEverything() { | |
65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
66 | |
67 // Ask MediaInternals for all its data. | |
68 BrowserThread::PostTask( | |
69 BrowserThread::IO, FROM_HERE, | |
70 base::Bind(&MediaInternalsProxy::GetEverythingOnIOThread, this)); | |
71 | |
72 // Send the page names for constants. | |
73 CallJavaScriptFunctionOnUIThread("media.onReceiveConstants", GetConstants()); | |
74 } | |
75 | |
76 void MediaInternalsProxy::OnUpdate(const string16& update) { | |
77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
78 BrowserThread::PostTask( | |
79 BrowserThread::UI, FROM_HERE, | |
80 base::Bind(&MediaInternalsProxy::UpdateUIOnUIThread, this, update)); | |
81 } | |
82 | |
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; | |
88 break; | |
89 } | |
90 } | |
91 | |
92 if (!is_event_interesting) | |
93 return; | |
94 | |
95 BrowserThread::PostTask( | |
96 BrowserThread::UI, FROM_HERE, | |
97 base::Bind(&MediaInternalsProxy::AddNetEventOnUIThread, this, | |
98 entry.ToValue())); | |
99 } | |
100 | |
101 MediaInternalsProxy::~MediaInternalsProxy() {} | |
102 | |
103 Value* MediaInternalsProxy::GetConstants() { | |
104 DictionaryValue* event_phases = new 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); | |
114 | |
115 DictionaryValue* constants = new DictionaryValue(); | |
116 constants->Set("eventTypes", net::NetLog::GetEventTypesAsValue()); | |
117 constants->Set("eventPhases", event_phases); | |
118 | |
119 return constants; | |
120 } | |
121 | |
122 void MediaInternalsProxy::ObserveMediaInternalsOnIOThread() { | |
123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
124 MediaInternals::GetInstance()->AddObserver(this); | |
125 io_thread_->net_log()->AddThreadSafeObserver(this, | |
126 net::NetLog::LOG_ALL_BUT_BYTES); | |
127 } | |
128 | |
129 void MediaInternalsProxy::StopObservingMediaInternalsOnIOThread() { | |
130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
131 MediaInternals::GetInstance()->RemoveObserver(this); | |
132 io_thread_->net_log()->RemoveThreadSafeObserver(this); | |
133 } | |
134 | |
135 void MediaInternalsProxy::GetEverythingOnIOThread() { | |
136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
137 MediaInternals::GetInstance()->SendEverything(); | |
138 } | |
139 | |
140 void MediaInternalsProxy::UpdateUIOnUIThread(const string16& update) { | |
141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
142 // Don't forward updates to a destructed UI. | |
143 if (handler_) | |
144 handler_->OnUpdate(update); | |
145 } | |
146 | |
147 void MediaInternalsProxy::AddNetEventOnUIThread(Value* entry) { | |
148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
149 | |
150 // Send the updates to the page in kMediaInternalsProxyEventDelayMilliseconds | |
151 // if an update is not already pending. | |
152 if (!pending_net_updates_.get()) { | |
153 pending_net_updates_.reset(new ListValue()); | |
154 MessageLoop::current()->PostDelayedTask( | |
155 FROM_HERE, | |
156 base::Bind( | |
157 &MediaInternalsProxy::SendNetEventsOnUIThread, this), | |
158 base::TimeDelta::FromMilliseconds( | |
159 kMediaInternalsProxyEventDelayMilliseconds)); | |
160 } | |
161 pending_net_updates_->Append(entry); | |
162 } | |
163 | |
164 void MediaInternalsProxy::SendNetEventsOnUIThread() { | |
165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
166 CallJavaScriptFunctionOnUIThread("media.onNetUpdate", | |
167 pending_net_updates_.release()); | |
168 } | |
169 | |
170 void MediaInternalsProxy::CallJavaScriptFunctionOnUIThread( | |
171 const std::string& function, Value* args) { | |
172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
173 scoped_ptr<Value> args_value(args); | |
174 std::vector<const Value*> args_vector; | |
175 args_vector.push_back(args_value.get()); | |
176 string16 update = content::WebUI::GetJavascriptCall(function, args_vector); | |
177 UpdateUIOnUIThread(update); | |
178 } | |
OLD | NEW |