Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: chrome/browser/dom_ui/net_internals_ui.cc

Issue 1036001: Add a DOMUI datasource that will handle the net-internals page.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: address mbelshe comments Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 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/dom_ui/net_internals_ui.h"
6
7 #include "app/resource_bundle.h"
8 #include "base/singleton.h"
9 #include "base/string_piece.h"
10 #include "base/values.h"
11 #include "chrome/browser/dom_ui/chrome_url_data_manager.h"
12 #include "chrome/browser/chrome_thread.h"
13 #include "chrome/common/url_constants.h"
14
15 #include "grit/browser_resources.h"
16
17 namespace {
18
19 class NetInternalsHTMLSource : public ChromeURLDataManager::DataSource {
20 public:
21 NetInternalsHTMLSource();
22
23 // Called when the network layer has requested a resource underneath
24 // the path we registered.
25 virtual void StartDataRequest(const std::string& path,
26 bool is_off_the_record,
27 int request_id);
28 virtual std::string GetMimeType(const std::string&) const;
29
30 private:
31 ~NetInternalsHTMLSource() {}
32 DISALLOW_COPY_AND_ASSIGN(NetInternalsHTMLSource);
33 };
34
35 // This class receives javascript messages from the renderer.
36 // Note that the DOMUI infrastructure runs on the UI thread, therefore all of
37 // this class's methods are expected to run on the UI thread.
38 //
39 // Since the network code we want to run lives on the IO thread, we proxy
40 // everything over to NetInternalsMessageHandler::IOThreadImpl, which runs
41 // on the IO thread.
42 //
43 // TODO(eroman): Can we start on the IO thread to begin with?
44 class NetInternalsMessageHandler
45 : public DOMMessageHandler,
46 public base::SupportsWeakPtr<NetInternalsMessageHandler> {
47 public:
48 NetInternalsMessageHandler();
49 virtual ~NetInternalsMessageHandler();
50
51 // DOMMessageHandler implementation.
52 virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
53 virtual void RegisterMessages();
54
55 // Executes the javascript function |function_name| in the renderer, passing
56 // it the argument |value|.
57 void CallJavascriptFunction(const std::wstring& function_name,
58 const Value& value);
59
60 private:
61 class IOThreadImpl;
62
63 // This is the "real" message handler, which lives on the IO thread.
64 scoped_refptr<IOThreadImpl> proxy_;
65
66 DISALLOW_COPY_AND_ASSIGN(NetInternalsMessageHandler);
67 };
68
69 // This class is the "real" message handler. With the exception of being
70 // allocated and destroyed on the UI thread, its methods are expected to be
71 // called from the IO thread.
72 class NetInternalsMessageHandler::IOThreadImpl
73 : public base::RefCountedThreadSafe<
74 NetInternalsMessageHandler::IOThreadImpl,
75 ChromeThread::DeleteOnUIThread> {
76 public:
77 // Type for methods that can be used as MessageHandler callbacks.
78 typedef void (IOThreadImpl::*MessageHandler)(const Value*);
79
80 // Creates a proxy for |handler| that will live on the IO thread.
81 // |handler| is a weak pointer, since it is possible for the DOMMessageHandler
82 // to be deleted on the UI thread while we were executing on the IO thread.
83 explicit IOThreadImpl(
84 const base::WeakPtr<NetInternalsMessageHandler>& handler);
85
86 ~IOThreadImpl();
87
88 // Creates a callback that will run |method| on the IO thread.
89 //
90 // This can be used with DOMUI::RegisterMessageCallback() to bind to a method
91 // on the IO thread.
92 DOMUI::MessageCallback* CreateCallback(MessageHandler method);
93
94 // Called once the DOMUI has attached to the renderer, on the IO thread.
95 void Attach();
96
97 // Called once the DOMUI has been deleted (i.e. renderer went away), on the
98 // IO thread.
99 void Detach();
100
101 //--------------------------------
102 // Javascript message handlers:
103 //--------------------------------
104
105 // TODO(eroman): This is temporary!
106 void OnTestMessage(const Value* value);
107
108 private:
109 class CallbackHelper;
110
111 // Helper that runs |method| with |arg|, and deletes |arg| on completion.
112 void DispatchToMessageHandler(Value* arg, MessageHandler method);
113
114 // Helper that executes |function_name| in the attached renderer.
115 // The function takes ownership of |arg|.
116 void CallJavascriptFunction(const std::wstring& function_name,
117 Value* arg);
118
119 private:
120 // Pointer to the UI-thread message handler. Only access this from
121 // the UI thread.
122 base::WeakPtr<NetInternalsMessageHandler> handler_;
123 friend class base::RefCountedThreadSafe<IOThreadImpl>;
124 };
125
126 // Helper class for a DOMUI::MessageCallback which when excuted calls
127 // instance->*method(value) on the IO thread.
128 class NetInternalsMessageHandler::IOThreadImpl::CallbackHelper
129 : public DOMUI::MessageCallback {
130 public:
131 CallbackHelper(IOThreadImpl* instance, IOThreadImpl::MessageHandler method)
132 : instance_(instance),
133 method_(method) {
134 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
135 }
136
137 virtual void RunWithParams(const Tuple1<const Value*>& params) {
138 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
139
140 // We need to make a copy of the value in order to pass it over to the IO
141 // thread. We will delete this in IOThreadImpl::DispatchMessageHandler().
142 Value* value_copy = params.a ? params.a->DeepCopy() : NULL;
143
144 if (!ChromeThread::PostTask(
145 ChromeThread::IO, FROM_HERE,
146 NewRunnableMethod(instance_.get(),
147 &IOThreadImpl::DispatchToMessageHandler,
148 value_copy, method_))) {
149 // Failed posting the task, avoid leaking |value_copy|.
150 delete value_copy;
151 }
152 }
153
154 private:
155 scoped_refptr<IOThreadImpl> instance_;
156 IOThreadImpl::MessageHandler method_;
157 };
158
159 ////////////////////////////////////////////////////////////////////////////////
160 //
161 // NetInternalsHTMLSource
162 //
163 ////////////////////////////////////////////////////////////////////////////////
164
165 NetInternalsHTMLSource::NetInternalsHTMLSource()
166 : DataSource(chrome::kChromeUINetInternalsHost, MessageLoop::current()) {
167 }
168
169 void NetInternalsHTMLSource::StartDataRequest(const std::string& path,
170 bool is_off_the_record,
171 int request_id) {
172 // Serve up the HTML contained in the resource bundle.
173 base::StringPiece html(
174 ResourceBundle::GetSharedInstance().GetRawDataResource(
175 IDR_NET_INTERNALS_HTML));
176
177 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
178 html_bytes->data.resize(html.size());
179 std::copy(html.begin(), html.end(), html_bytes->data.begin());
180
181 SendResponse(request_id, html_bytes);
182 }
183
184 std::string NetInternalsHTMLSource::GetMimeType(const std::string&) const {
185 return "text/html";
186 }
187
188 ////////////////////////////////////////////////////////////////////////////////
189 //
190 // NetInternalsMessageHandler
191 //
192 ////////////////////////////////////////////////////////////////////////////////
193
194 NetInternalsMessageHandler::NetInternalsMessageHandler() {}
195
196 NetInternalsMessageHandler::~NetInternalsMessageHandler() {
197 if (proxy_) {
198 // Notify the handler on the IO thread that the renderer is gone.
199 ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
200 NewRunnableMethod(proxy_.get(), &IOThreadImpl::Detach));
201 }
202 }
203
204 DOMMessageHandler* NetInternalsMessageHandler::Attach(DOMUI* dom_ui) {
205 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
206 proxy_ = new IOThreadImpl(this->AsWeakPtr());
207
208 DOMMessageHandler* result = DOMMessageHandler::Attach(dom_ui);
209
210 // Notify the handler on the IO thread that a renderer is attached.
211 ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
212 NewRunnableMethod(proxy_.get(), &IOThreadImpl::Attach));
213
214 return result;
215 }
216
217 void NetInternalsMessageHandler::RegisterMessages() {
218 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
219
220 // TODO(eroman): Register message handlers here.
221 dom_ui_->RegisterMessageCallback("testMessage",
222 proxy_->CreateCallback(&IOThreadImpl::OnTestMessage));
223 }
224
225 void NetInternalsMessageHandler::CallJavascriptFunction(
226 const std::wstring& function_name,
227 const Value& value) {
228 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
229 dom_ui_->CallJavascriptFunction(function_name, value);
230 }
231
232 ////////////////////////////////////////////////////////////////////////////////
233 //
234 // NetInternalsMessageHandler::IOThreadImpl
235 //
236 ////////////////////////////////////////////////////////////////////////////////
237
238 NetInternalsMessageHandler::IOThreadImpl::IOThreadImpl(
239 const base::WeakPtr<NetInternalsMessageHandler>& handler)
240 : handler_(handler) {
241 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
242 }
243
244 NetInternalsMessageHandler::IOThreadImpl::~IOThreadImpl() {
245 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
246 }
247
248 DOMUI::MessageCallback*
249 NetInternalsMessageHandler::IOThreadImpl::CreateCallback(
250 MessageHandler method) {
251 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
252 return new CallbackHelper(this, method);
253 }
254
255 void NetInternalsMessageHandler::IOThreadImpl::Attach() {
256 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
257 // TODO(eroman): Register with network stack to observe events.
258 }
259
260 void NetInternalsMessageHandler::IOThreadImpl::Detach() {
261 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
262 // TODO(eroman): Unregister with network stack to observe events.
263 }
264
265 void NetInternalsMessageHandler::IOThreadImpl::OnTestMessage(
266 const Value* value) {
267 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
268
269 // TODO(eroman): This is just a temporary method, to see something in
270 // action. We expect to have been called with an array
271 // containing 1 string, and print it to the screen.
272 std::string str;
273 if (value && value->GetType() == Value::TYPE_LIST) {
274 const ListValue* list_value = static_cast<const ListValue*>(value);
275 Value* list_member;
276 if (list_value->Get(0, &list_member) &&
277 list_member->GetType() == Value::TYPE_STRING) {
278 const StringValue* string_value =
279 static_cast<const StringValue*>(list_member);
280 string_value->GetAsString(&str);
281 }
282 }
283
284 CallJavascriptFunction(
285 L"log",
286 Value::CreateStringValue("Browser received testMessage: " + str));
287 }
288
289 void NetInternalsMessageHandler::IOThreadImpl::DispatchToMessageHandler(
290 Value* arg, MessageHandler method) {
291 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
292 (this->*method)(arg);
293 delete arg;
294 }
295
296 void NetInternalsMessageHandler::IOThreadImpl::CallJavascriptFunction(
297 const std::wstring& function_name,
298 Value* arg) {
299 if (ChromeThread::CurrentlyOn(ChromeThread::UI)) {
300 if (handler_) {
301 // We check |handler_| in case it was deleted on the UI thread earlier
302 // while we were running on the IO thread.
303 handler_->CallJavascriptFunction(function_name, *arg);
304 }
305 delete arg;
306 return;
307 }
308
309
310 // Otherwise if we were called from the IO thread, bridge the request over to
311 // the UI thread.
312
313 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
314 if (!ChromeThread::PostTask(
315 ChromeThread::UI, FROM_HERE,
316 NewRunnableMethod(
317 this,
318 &IOThreadImpl::CallJavascriptFunction,
319 function_name, arg))) {
320 // Failed posting the task, avoid leaking.
321 delete arg;
322 }
323
324 }
325
326 } // namespace
327
328
329 ////////////////////////////////////////////////////////////////////////////////
330 //
331 // NetInternalsUI
332 //
333 ////////////////////////////////////////////////////////////////////////////////
334
335 NetInternalsUI::NetInternalsUI(TabContents* contents) : DOMUI(contents) {
336 AddMessageHandler((new NetInternalsMessageHandler())->Attach(this));
337
338 NetInternalsHTMLSource* html_source = new NetInternalsHTMLSource();
339
340 // Set up the chrome://net-internals/ source.
341 ChromeThread::PostTask(
342 ChromeThread::IO, FROM_HERE,
343 NewRunnableMethod(
344 Singleton<ChromeURLDataManager>::get(),
345 &ChromeURLDataManager::AddDataSource,
346 make_scoped_refptr(html_source)));
347 }
OLDNEW
« no previous file with comments | « chrome/browser/dom_ui/net_internals_ui.h ('k') | chrome/browser/resources/net_internals/index.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698