OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/debugger/devtools_http_handler_impl.h" | 5 #include "content/browser/debugger/devtools_http_handler_impl.h" |
6 | 6 |
| 7 #include <algorithm> |
7 #include <utility> | 8 #include <utility> |
8 | 9 |
9 #include "base/bind.h" | 10 #include "base/bind.h" |
10 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
11 #include "base/json/json_writer.h" | 12 #include "base/json/json_writer.h" |
12 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
13 #include "base/logging.h" | 14 #include "base/logging.h" |
14 #include "base/message_loop_proxy.h" | 15 #include "base/message_loop_proxy.h" |
15 #include "base/string_number_conversions.h" | 16 #include "base/string_number_conversions.h" |
16 #include "base/stringprintf.h" | 17 #include "base/stringprintf.h" |
(...skipping 20 matching lines...) Expand all Loading... |
37 #include "net/server/http_server_request_info.h" | 38 #include "net/server/http_server_request_info.h" |
38 #include "net/url_request/url_request_context.h" | 39 #include "net/url_request/url_request_context.h" |
39 #include "net/url_request/url_request_context_getter.h" | 40 #include "net/url_request/url_request_context_getter.h" |
40 | 41 |
41 namespace content { | 42 namespace content { |
42 | 43 |
43 const int kBufferSize = 16 * 1024; | 44 const int kBufferSize = 16 * 1024; |
44 | 45 |
45 namespace { | 46 namespace { |
46 | 47 |
| 48 class DevToolsDefaultBindingHandler |
| 49 : public DevToolsHttpHandler::RenderViewHostBinding { |
| 50 public: |
| 51 DevToolsDefaultBindingHandler() { |
| 52 } |
| 53 |
| 54 virtual std::string GetIdentifier(RenderViewHost* rvh) OVERRIDE { |
| 55 int process_id = rvh->GetProcess()->GetID(); |
| 56 int routing_id = rvh->GetRoutingID(); |
| 57 return base::StringPrintf("%d_%d", process_id, routing_id); |
| 58 } |
| 59 |
| 60 virtual RenderViewHost* ForIdentifier( |
| 61 const std::string& identifier) OVERRIDE { |
| 62 int pos = identifier.find("_"); |
| 63 if (pos == std::string::npos) |
| 64 return NULL; |
| 65 |
| 66 int process_id; |
| 67 if (!base::StringToInt(identifier.substr(0, pos), &process_id)) |
| 68 return NULL; |
| 69 |
| 70 int routing_id; |
| 71 if (!base::StringToInt(identifier.substr(pos+1), &routing_id)) |
| 72 return NULL; |
| 73 |
| 74 return RenderViewHost::FromID(process_id, routing_id); |
| 75 } |
| 76 }; |
| 77 |
| 78 |
47 // An internal implementation of DevToolsClientHost that delegates | 79 // An internal implementation of DevToolsClientHost that delegates |
48 // messages sent for DevToolsClient to a DebuggerShell instance. | 80 // messages sent for DevToolsClient to a DebuggerShell instance. |
49 class DevToolsClientHostImpl : public DevToolsClientHost { | 81 class DevToolsClientHostImpl : public DevToolsClientHost { |
50 public: | 82 public: |
51 DevToolsClientHostImpl( | 83 DevToolsClientHostImpl( |
52 net::HttpServer* server, | 84 net::HttpServer* server, |
53 int connection_id) | 85 int connection_id) |
54 : server_(server), | 86 : server_(server), |
55 connection_id_(connection_id) { | 87 connection_id_(connection_id) { |
56 } | 88 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 BrowserThread::IO, FROM_HERE, | 153 BrowserThread::IO, FROM_HERE, |
122 base::Bind(&DevToolsHttpHandlerImpl::Init, this)); | 154 base::Bind(&DevToolsHttpHandlerImpl::Init, this)); |
123 } | 155 } |
124 | 156 |
125 void DevToolsHttpHandlerImpl::Stop() { | 157 void DevToolsHttpHandlerImpl::Stop() { |
126 BrowserThread::PostTask( | 158 BrowserThread::PostTask( |
127 BrowserThread::IO, FROM_HERE, | 159 BrowserThread::IO, FROM_HERE, |
128 base::Bind(&DevToolsHttpHandlerImpl::TeardownAndRelease, this)); | 160 base::Bind(&DevToolsHttpHandlerImpl::TeardownAndRelease, this)); |
129 } | 161 } |
130 | 162 |
| 163 void DevToolsHttpHandlerImpl::SetRenderViewHostBinding( |
| 164 RenderViewHostBinding* binding) { |
| 165 if (binding) |
| 166 binding_ = binding; |
| 167 else |
| 168 binding_ = default_binding_.get(); |
| 169 } |
| 170 |
131 static std::string PathWithoutParams(const std::string& path) { | 171 static std::string PathWithoutParams(const std::string& path) { |
132 size_t query_position = path.find("?"); | 172 size_t query_position = path.find("?"); |
133 if (query_position != std::string::npos) | 173 if (query_position != std::string::npos) |
134 return path.substr(0, query_position); | 174 return path.substr(0, query_position); |
135 return path; | 175 return path; |
136 } | 176 } |
137 | 177 |
138 static std::string GetMimeType(const std::string& filename) { | 178 static std::string GetMimeType(const std::string& filename) { |
139 if (EndsWith(filename, ".html", false)) { | 179 if (EndsWith(filename, ".html", false)) { |
140 return "text/html"; | 180 return "text/html"; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 | 295 |
256 BrowserThread::PostTask( | 296 BrowserThread::PostTask( |
257 BrowserThread::UI, | 297 BrowserThread::UI, |
258 FROM_HERE, | 298 FROM_HERE, |
259 base::Bind( | 299 base::Bind( |
260 &DevToolsHttpHandlerImpl::OnCloseUI, | 300 &DevToolsHttpHandlerImpl::OnCloseUI, |
261 this, | 301 this, |
262 connection_id)); | 302 connection_id)); |
263 } | 303 } |
264 | 304 |
265 struct DevToolsHttpHandlerImpl::PageInfo | 305 struct DevToolsHttpHandlerImpl::PageInfo { |
266 { | |
267 PageInfo() | 306 PageInfo() |
268 : id(0), | 307 : attached(false) { |
269 attached(false) { | |
270 } | 308 } |
271 | 309 |
272 int id; | 310 std::string id; |
273 std::string url; | 311 std::string url; |
274 bool attached; | 312 bool attached; |
275 std::string title; | 313 std::string title; |
276 std::string thumbnail_url; | 314 std::string thumbnail_url; |
277 std::string favicon_url; | 315 std::string favicon_url; |
278 base::TimeTicks last_selected_time; | 316 base::TimeTicks last_selected_time; |
279 }; | 317 }; |
280 | 318 |
281 // static | 319 // static |
282 bool DevToolsHttpHandlerImpl::SortPageListByTime(const PageInfo& info1, | 320 bool DevToolsHttpHandlerImpl::SortPageListByTime(const PageInfo& info1, |
283 const PageInfo& info2) { | 321 const PageInfo& info2) { |
284 return info1.last_selected_time > info2.last_selected_time; | 322 return info1.last_selected_time > info2.last_selected_time; |
285 } | 323 } |
286 | 324 |
287 DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() { | 325 DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() { |
288 ResetRenderViewHostBinding(); | |
289 PageList page_list; | 326 PageList page_list; |
290 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); | 327 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); |
291 !it.IsAtEnd(); it.Advance()) { | 328 !it.IsAtEnd(); it.Advance()) { |
292 RenderProcessHost* render_process_host = it.GetCurrentValue(); | 329 RenderProcessHost* render_process_host = it.GetCurrentValue(); |
293 DCHECK(render_process_host); | 330 DCHECK(render_process_host); |
294 | 331 |
295 // Ignore processes that don't have a connection, such as crashed contents. | 332 // Ignore processes that don't have a connection, such as crashed contents. |
296 if (!render_process_host->HasConnection()) | 333 if (!render_process_host->HasConnection()) |
297 continue; | 334 continue; |
298 | 335 |
299 RenderProcessHost::RenderWidgetHostsIterator rwit( | 336 RenderProcessHost::RenderWidgetHostsIterator rwit( |
300 render_process_host->GetRenderWidgetHostsIterator()); | 337 render_process_host->GetRenderWidgetHostsIterator()); |
301 for (; !rwit.IsAtEnd(); rwit.Advance()) { | 338 for (; !rwit.IsAtEnd(); rwit.Advance()) { |
302 const RenderWidgetHost* widget = rwit.GetCurrentValue(); | 339 const RenderWidgetHost* widget = rwit.GetCurrentValue(); |
303 DCHECK(widget); | 340 DCHECK(widget); |
304 if (!widget || !widget->IsRenderView()) | 341 if (!widget || !widget->IsRenderView()) |
305 continue; | 342 continue; |
306 | 343 |
307 RenderViewHost* host = | 344 RenderViewHost* host = |
308 RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); | 345 RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); |
309 content::RenderViewHostDelegate* host_delegate = host->GetDelegate(); | 346 content::RenderViewHostDelegate* host_delegate = host->GetDelegate(); |
310 | 347 |
311 DevToolsAgentHost* agent = | 348 DevToolsAgentHost* agent = |
312 DevToolsAgentHostRegistry::GetDevToolsAgentHost(host); | 349 DevToolsAgentHostRegistry::GetDevToolsAgentHost(host); |
313 DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> | 350 DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> |
314 GetDevToolsClientHostFor(agent); | 351 GetDevToolsClientHostFor(agent); |
315 PageInfo page_info; | 352 PageInfo page_info; |
316 page_info.id = BindRenderViewHost(host); | 353 page_info.id = binding_->GetIdentifier(host); |
317 page_info.attached = client_host != NULL; | 354 page_info.attached = client_host != NULL; |
318 page_info.url = host_delegate->GetURL().spec(); | 355 page_info.url = host_delegate->GetURL().spec(); |
319 | 356 |
320 WebContents* web_contents = host_delegate->GetAsWebContents(); | 357 WebContents* web_contents = host_delegate->GetAsWebContents(); |
321 if (web_contents) { | 358 if (web_contents) { |
322 page_info.title = UTF16ToUTF8( | 359 page_info.title = UTF16ToUTF8( |
323 net::EscapeForHTML(web_contents->GetTitle())); | 360 net::EscapeForHTML(web_contents->GetTitle())); |
324 page_info.last_selected_time = web_contents->GetLastSelectedTime(); | 361 page_info.last_selected_time = web_contents->GetLastSelectedTime(); |
325 | 362 |
326 NavigationController& controller = web_contents->GetController(); | 363 NavigationController& controller = web_contents->GetController(); |
(...skipping 11 matching lines...) Expand all Loading... |
338 } | 375 } |
339 | 376 |
340 void DevToolsHttpHandlerImpl::OnJsonRequestUI( | 377 void DevToolsHttpHandlerImpl::OnJsonRequestUI( |
341 int connection_id, | 378 int connection_id, |
342 const net::HttpServerRequestInfo& info) { | 379 const net::HttpServerRequestInfo& info) { |
343 PageList page_list = GeneratePageList(); | 380 PageList page_list = GeneratePageList(); |
344 ListValue json_pages_list; | 381 ListValue json_pages_list; |
345 std::string host = info.headers["Host"]; | 382 std::string host = info.headers["Host"]; |
346 for (PageList::iterator i = page_list.begin(); | 383 for (PageList::iterator i = page_list.begin(); |
347 i != page_list.end(); ++i) { | 384 i != page_list.end(); ++i) { |
348 | |
349 DictionaryValue* page_info = new DictionaryValue; | 385 DictionaryValue* page_info = new DictionaryValue; |
350 json_pages_list.Append(page_info); | 386 json_pages_list.Append(page_info); |
351 page_info->SetString("title", i->title); | 387 page_info->SetString("title", i->title); |
352 page_info->SetString("url", i->url); | 388 page_info->SetString("url", i->url); |
353 page_info->SetString("thumbnailUrl", i->thumbnail_url); | 389 page_info->SetString("thumbnailUrl", i->thumbnail_url); |
354 page_info->SetString("faviconUrl", i->favicon_url); | 390 page_info->SetString("faviconUrl", i->favicon_url); |
355 if (!i->attached) { | 391 if (!i->attached) { |
356 page_info->SetString("webSocketDebuggerUrl", | 392 page_info->SetString("webSocketDebuggerUrl", |
357 base::StringPrintf("ws://%s/devtools/page/%d", | 393 base::StringPrintf("ws://%s/devtools/page/%s", |
358 host.c_str(), | 394 host.c_str(), |
359 i->id)); | 395 i->id.c_str())); |
360 std::string devtools_frontend_url = base::StringPrintf( | 396 std::string devtools_frontend_url = base::StringPrintf( |
361 "%s%sws=%s/devtools/page/%d", | 397 "%s%sws=%s/devtools/page/%s", |
362 overridden_frontend_url_.c_str(), | 398 overridden_frontend_url_.c_str(), |
363 overridden_frontend_url_.find("?") == std::string::npos ? "?" : "&", | 399 overridden_frontend_url_.find("?") == std::string::npos ? "?" : "&", |
364 host.c_str(), | 400 host.c_str(), |
365 i->id); | 401 i->id.c_str()); |
366 page_info->SetString("devtoolsFrontendUrl", devtools_frontend_url); | 402 page_info->SetString("devtoolsFrontendUrl", devtools_frontend_url); |
367 } | 403 } |
368 } | 404 } |
369 | 405 |
370 std::string response; | 406 std::string response; |
371 base::JSONWriter::WriteWithOptions(&json_pages_list, | 407 base::JSONWriter::WriteWithOptions(&json_pages_list, |
372 base::JSONWriter::OPTIONS_PRETTY_PRINT, | 408 base::JSONWriter::OPTIONS_PRETTY_PRINT, |
373 &response); | 409 &response); |
374 Send200(connection_id, response, "application/json; charset=UTF-8"); | 410 Send200(connection_id, response, "application/json; charset=UTF-8"); |
375 } | 411 } |
376 | 412 |
377 void DevToolsHttpHandlerImpl::OnWebSocketRequestUI( | 413 void DevToolsHttpHandlerImpl::OnWebSocketRequestUI( |
378 int connection_id, | 414 int connection_id, |
379 const net::HttpServerRequestInfo& request) { | 415 const net::HttpServerRequestInfo& request) { |
380 std::string prefix = "/devtools/page/"; | 416 std::string prefix = "/devtools/page/"; |
381 size_t pos = request.path.find(prefix); | 417 size_t pos = request.path.find(prefix); |
382 if (pos != 0) { | 418 if (pos != 0) { |
383 Send404(connection_id); | 419 Send404(connection_id); |
384 return; | 420 return; |
385 } | 421 } |
| 422 |
386 std::string page_id = request.path.substr(prefix.length()); | 423 std::string page_id = request.path.substr(prefix.length()); |
387 int id = 0; | 424 RenderViewHost* rvh = binding_->ForIdentifier(page_id); |
388 if (!base::StringToInt(page_id, &id)) { | |
389 Send500(connection_id, "Invalid page id: " + page_id); | |
390 return; | |
391 } | |
392 | |
393 RenderViewHost* rvh = GetBoundRenderViewHost(id); | |
394 if (!rvh) { | 425 if (!rvh) { |
395 Send500(connection_id, "No such target id: " + page_id); | 426 Send500(connection_id, "No such target id: " + page_id); |
396 return; | 427 return; |
397 } | 428 } |
398 | 429 |
399 DevToolsManager* manager = DevToolsManager::GetInstance(); | 430 DevToolsManager* manager = DevToolsManager::GetInstance(); |
400 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( | 431 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( |
401 rvh); | 432 rvh); |
402 if (manager->GetDevToolsClientHostFor(agent)) { | 433 if (manager->GetDevToolsClientHostFor(agent)) { |
403 Send500(connection_id, "Target with given id is being inspected: " + | 434 Send500(connection_id, "Target with given id is being inspected: " + |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 net::URLRequestContextGetter* request_context_getter, | 534 net::URLRequestContextGetter* request_context_getter, |
504 DevToolsHttpHandlerDelegate* delegate) | 535 DevToolsHttpHandlerDelegate* delegate) |
505 : ip_(ip), | 536 : ip_(ip), |
506 port_(port), | 537 port_(port), |
507 overridden_frontend_url_(frontend_url), | 538 overridden_frontend_url_(frontend_url), |
508 request_context_getter_(request_context_getter), | 539 request_context_getter_(request_context_getter), |
509 delegate_(delegate) { | 540 delegate_(delegate) { |
510 if (overridden_frontend_url_.empty()) | 541 if (overridden_frontend_url_.empty()) |
511 overridden_frontend_url_ = "/devtools/devtools.html"; | 542 overridden_frontend_url_ = "/devtools/devtools.html"; |
512 | 543 |
| 544 default_binding_.reset(new DevToolsDefaultBindingHandler); |
| 545 binding_ = default_binding_.get(); |
| 546 |
513 AddRef(); | 547 AddRef(); |
514 } | 548 } |
515 | 549 |
516 void DevToolsHttpHandlerImpl::Init() { | 550 void DevToolsHttpHandlerImpl::Init() { |
517 server_ = new net::HttpServer(ip_, port_, this); | 551 server_ = new net::HttpServer(ip_, port_, this); |
518 } | 552 } |
519 | 553 |
520 // Run on I/O thread | 554 // Run on I/O thread |
521 void DevToolsHttpHandlerImpl::TeardownAndRelease() { | 555 void DevToolsHttpHandlerImpl::TeardownAndRelease() { |
522 server_ = NULL; | 556 server_ = NULL; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 | 616 |
583 void DevToolsHttpHandlerImpl::AcceptWebSocket( | 617 void DevToolsHttpHandlerImpl::AcceptWebSocket( |
584 int connection_id, | 618 int connection_id, |
585 const net::HttpServerRequestInfo& request) { | 619 const net::HttpServerRequestInfo& request) { |
586 BrowserThread::PostTask( | 620 BrowserThread::PostTask( |
587 BrowserThread::IO, FROM_HERE, | 621 BrowserThread::IO, FROM_HERE, |
588 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), | 622 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), |
589 connection_id, request)); | 623 connection_id, request)); |
590 } | 624 } |
591 | 625 |
592 size_t DevToolsHttpHandlerImpl::BindRenderViewHost(RenderViewHost* rvh) { | |
593 Target target = std::make_pair(rvh->GetProcess()->GetID(), | |
594 rvh->GetRoutingID()); | |
595 targets_.push_back(target); | |
596 return targets_.size() - 1; | |
597 } | |
598 | |
599 RenderViewHost* DevToolsHttpHandlerImpl::GetBoundRenderViewHost(size_t id) { | |
600 return RenderViewHost::FromID(targets_[id].first, | |
601 targets_[id].second); | |
602 } | |
603 | |
604 void DevToolsHttpHandlerImpl::ResetRenderViewHostBinding() { | |
605 targets_.clear(); | |
606 } | |
607 | |
608 } // namespace content | 626 } // namespace content |
OLD | NEW |