Chromium Code Reviews| 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/devtools/devtools_http_handler_impl.h" | 5 #include "content/browser/devtools/devtools_http_handler_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
| 13 #include "base/json/json_writer.h" | 13 #include "base/json/json_writer.h" |
| 14 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/message_loop_proxy.h" | 16 #include "base/message_loop_proxy.h" |
| 17 #include "base/string_number_conversions.h" | 17 #include "base/string_number_conversions.h" |
| 18 #include "base/stringprintf.h" | |
| 19 #include "base/threading/thread.h" | 18 #include "base/threading/thread.h" |
| 20 #include "base/utf_string_conversions.h" | |
| 21 #include "base/values.h" | |
| 22 #include "content/browser/devtools/devtools_agent_host_impl.h" | |
| 23 #include "content/browser/devtools/devtools_browser_target.h" | 19 #include "content/browser/devtools/devtools_browser_target.h" |
| 24 #include "content/browser/devtools/devtools_tracing_handler.h" | 20 #include "content/browser/devtools/devtools_tracing_handler.h" |
| 25 #include "content/browser/web_contents/web_contents_impl.h" | 21 #include "content/browser/web_contents/web_contents_impl.h" |
| 26 #include "content/common/devtools_messages.h" | 22 #include "content/common/devtools_messages.h" |
| 27 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
| 28 #include "content/public/browser/devtools_agent_host.h" | 24 #include "content/public/browser/devtools_agent_host.h" |
| 29 #include "content/public/browser/devtools_client_host.h" | 25 #include "content/public/browser/devtools_client_host.h" |
| 30 #include "content/public/browser/devtools_http_handler_delegate.h" | |
| 31 #include "content/public/browser/devtools_manager.h" | 26 #include "content/public/browser/devtools_manager.h" |
| 32 #include "content/public/browser/favicon_status.h" | 27 #include "content/public/browser/devtools_target_list.h" |
| 33 #include "content/public/browser/navigation_entry.h" | |
| 34 #include "content/public/browser/notification_service.h" | 28 #include "content/public/browser/notification_service.h" |
| 35 #include "content/public/browser/notification_types.h" | 29 #include "content/public/browser/notification_types.h" |
| 36 #include "content/public/browser/render_process_host.h" | |
| 37 #include "content/public/browser/render_view_host.h" | 30 #include "content/public/browser/render_view_host.h" |
| 38 #include "content/public/browser/render_widget_host.h" | |
| 39 #include "content/public/common/content_client.h" | 31 #include "content/public/common/content_client.h" |
| 40 #include "content/public/common/url_constants.h" | 32 #include "content/public/common/url_constants.h" |
| 41 #include "googleurl/src/gurl.h" | 33 #include "googleurl/src/gurl.h" |
| 42 #include "grit/devtools_resources_map.h" | 34 #include "grit/devtools_resources_map.h" |
| 43 #include "net/base/escape.h" | |
| 44 #include "net/base/io_buffer.h" | 35 #include "net/base/io_buffer.h" |
| 45 #include "net/base/ip_endpoint.h" | 36 #include "net/base/ip_endpoint.h" |
| 46 #include "net/server/http_server_request_info.h" | 37 #include "net/server/http_server_request_info.h" |
| 47 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" | 38 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" |
| 48 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" | 39 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" |
| 49 #include "ui/base/layout.h" | 40 #include "ui/base/layout.h" |
| 50 #include "webkit/user_agent/user_agent.h" | 41 #include "webkit/user_agent/user_agent.h" |
| 51 #include "webkit/user_agent/user_agent_util.h" | 42 #include "webkit/user_agent/user_agent_util.h" |
| 52 | 43 |
| 53 namespace content { | 44 namespace content { |
| 54 | 45 |
| 55 const int kBufferSize = 16 * 1024; | 46 const int kBufferSize = 16 * 1024; |
| 56 | 47 |
| 57 namespace { | 48 namespace { |
| 58 | 49 |
| 59 static const char* kDevToolsHandlerThreadName = "Chrome_DevToolsHandlerThread"; | 50 static const char* kDevToolsHandlerThreadName = "Chrome_DevToolsHandlerThread"; |
| 60 | 51 |
| 61 class DevToolsDefaultBindingHandler | |
| 62 : public DevToolsHttpHandler::DevToolsAgentHostBinding { | |
| 63 public: | |
| 64 DevToolsDefaultBindingHandler() { | |
| 65 } | |
| 66 | |
| 67 void GarbageCollect() { | |
| 68 AgentsMap::iterator it = agents_map_.begin(); | |
| 69 while (it != agents_map_.end()) { | |
| 70 if (!it->second->GetRenderViewHost()) | |
| 71 agents_map_.erase(it++); | |
| 72 else | |
| 73 ++it; | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 virtual std::string GetIdentifier(DevToolsAgentHost* agent_host) OVERRIDE { | |
| 78 GarbageCollect(); | |
| 79 DevToolsAgentHostImpl* agent_host_impl = | |
| 80 static_cast<DevToolsAgentHostImpl*>(agent_host); | |
| 81 std::string id = base::StringPrintf("%d", agent_host_impl->id()); | |
| 82 agents_map_[id] = agent_host; | |
| 83 return id; | |
| 84 } | |
| 85 | |
| 86 virtual DevToolsAgentHost* ForIdentifier( | |
| 87 const std::string& identifier) OVERRIDE { | |
| 88 GarbageCollect(); | |
| 89 AgentsMap::iterator it = agents_map_.find(identifier); | |
| 90 if (it != agents_map_.end()) | |
| 91 return it->second; | |
| 92 return NULL; | |
| 93 } | |
| 94 | |
| 95 private: | |
| 96 typedef std::map<std::string, scoped_refptr<DevToolsAgentHost> > AgentsMap; | |
| 97 AgentsMap agents_map_; | |
| 98 }; | |
| 99 | |
| 100 // An internal implementation of DevToolsClientHost that delegates | 52 // An internal implementation of DevToolsClientHost that delegates |
| 101 // messages sent for DevToolsClient to a DebuggerShell instance. | 53 // messages sent for DevToolsClient to a DebuggerShell instance. |
| 102 class DevToolsClientHostImpl : public DevToolsClientHost { | 54 class DevToolsClientHostImpl : public DevToolsClientHost { |
| 103 public: | 55 public: |
| 104 DevToolsClientHostImpl( | 56 DevToolsClientHostImpl( |
| 105 MessageLoop* message_loop, | 57 MessageLoop* message_loop, |
| 106 net::HttpServer* server, | 58 net::HttpServer* server, |
| 107 int connection_id) | 59 int connection_id) |
| 108 : message_loop_(message_loop), | 60 : message_loop_(message_loop), |
| 109 server_(server), | 61 server_(server), |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 BrowserThread::FILE, FROM_HERE, | 180 BrowserThread::FILE, FROM_HERE, |
| 229 base::Bind(&DevToolsHttpHandlerImpl::StopHandlerThread, this), | 181 base::Bind(&DevToolsHttpHandlerImpl::StopHandlerThread, this), |
| 230 base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease, this)); | 182 base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease, this)); |
| 231 } | 183 } |
| 232 | 184 |
| 233 void DevToolsHttpHandlerImpl::SetDevToolsAgentHostBinding( | 185 void DevToolsHttpHandlerImpl::SetDevToolsAgentHostBinding( |
| 234 DevToolsAgentHostBinding* binding) { | 186 DevToolsAgentHostBinding* binding) { |
| 235 if (binding) | 187 if (binding) |
| 236 binding_ = binding; | 188 binding_ = binding; |
| 237 else | 189 else |
| 238 binding_ = default_binding_.get(); | 190 binding_ = DevToolsTargetList::GetInstance(); |
|
pfeldman
2013/03/01 08:49:30
It is especially clear here how two concepts are m
Vladislav Kaznacheev
2013/03/01 12:58:35
Rolled back.
On 2013/03/01 08:49:30, pfeldman wrot
| |
| 239 } | 191 } |
| 240 | 192 |
| 241 GURL DevToolsHttpHandlerImpl::GetFrontendURL(DevToolsAgentHost* agent_host) { | 193 GURL DevToolsHttpHandlerImpl::GetFrontendURL(DevToolsAgentHost* agent_host) { |
| 242 net::IPEndPoint ip_address; | 194 net::IPEndPoint ip_address; |
| 243 if (server_->GetLocalAddress(&ip_address)) | 195 if (server_->GetLocalAddress(&ip_address)) |
| 244 return GURL(); | 196 return GURL(); |
| 245 if (!agent_host) { | 197 if (!agent_host) { |
| 246 return GURL(std::string("http://") + ip_address.ToString() + | 198 return GURL(std::string("http://") + ip_address.ToString() + |
| 247 overridden_frontend_url_); | 199 overridden_frontend_url_); |
| 248 } | 200 } |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 void DevToolsHttpHandlerImpl::OnClose(int connection_id) { | 339 void DevToolsHttpHandlerImpl::OnClose(int connection_id) { |
| 388 BrowserThread::PostTask( | 340 BrowserThread::PostTask( |
| 389 BrowserThread::UI, | 341 BrowserThread::UI, |
| 390 FROM_HERE, | 342 FROM_HERE, |
| 391 base::Bind( | 343 base::Bind( |
| 392 &DevToolsHttpHandlerImpl::OnCloseUI, | 344 &DevToolsHttpHandlerImpl::OnCloseUI, |
| 393 this, | 345 this, |
| 394 connection_id)); | 346 connection_id)); |
| 395 } | 347 } |
| 396 | 348 |
| 397 struct DevToolsHttpHandlerImpl::PageInfo { | 349 static base::TimeTicks GetLastSelectedTime(DevToolsAgentHost* agent) { |
| 398 PageInfo() | 350 WebContents* web_contents = |
|
pfeldman
2013/03/01 08:49:30
Once you start operating TargetList, some of your
Vladislav Kaznacheev
2013/03/01 12:58:35
This will not solve the problem from your next com
| |
| 399 : attached(false) { | 351 agent->GetRenderViewHost()->GetDelegate()->GetAsWebContents(); |
| 400 } | 352 return web_contents ? web_contents->GetLastSelectedTime() : base::TimeTicks(); |
| 401 | 353 } |
| 402 std::string id; | |
| 403 std::string url; | |
| 404 std::string type; | |
| 405 bool attached; | |
| 406 std::string title; | |
| 407 std::string thumbnail_url; | |
| 408 std::string favicon_url; | |
| 409 base::TimeTicks last_selected_time; | |
| 410 }; | |
| 411 | 354 |
| 412 // static | 355 // static |
| 413 bool DevToolsHttpHandlerImpl::SortPageListByTime(const PageInfo& info1, | 356 bool DevToolsHttpHandlerImpl::SortPageListByTime(DevToolsAgentHost* agent1, |
| 414 const PageInfo& info2) { | 357 DevToolsAgentHost* agent2) { |
| 415 return info1.last_selected_time > info2.last_selected_time; | 358 return GetLastSelectedTime(agent1) > GetLastSelectedTime(agent2); |
|
pfeldman
2013/03/01 08:49:30
This is scary. GetLastSelectedTime will return dif
Vladislav Kaznacheev
2013/03/01 12:58:35
I am scared too.
On 2013/03/01 08:49:30, pfeldman
| |
| 416 } | 359 } |
| 417 | 360 |
| 418 DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() { | 361 DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() { |
| 419 PageList page_list; | 362 PageList page_list; |
| 420 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); | 363 DevToolsTargetList::AgentsMap& agents_map = |
| 421 !it.IsAtEnd(); it.Advance()) { | 364 DevToolsTargetList::GetInstance()->GetAgentsMap(); |
| 422 RenderProcessHost* render_process_host = it.GetCurrentValue(); | 365 for (DevToolsTargetList::iterator i = agents_map.begin(); |
| 423 DCHECK(render_process_host); | 366 i != agents_map.end(); ++i) |
| 424 | 367 page_list.push_back(i->second); |
| 425 // Ignore processes that don't have a connection, such as crashed contents. | |
| 426 if (!render_process_host->HasConnection()) | |
| 427 continue; | |
| 428 | |
| 429 RenderProcessHost::RenderWidgetHostsIterator rwit( | |
| 430 render_process_host->GetRenderWidgetHostsIterator()); | |
| 431 for (; !rwit.IsAtEnd(); rwit.Advance()) { | |
| 432 const RenderWidgetHost* widget = rwit.GetCurrentValue(); | |
| 433 DCHECK(widget); | |
| 434 if (!widget || !widget->IsRenderView()) | |
| 435 continue; | |
| 436 | |
| 437 RenderViewHost* host = | |
| 438 RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); | |
| 439 page_list.push_back(CreatePageInfo(host, delegate_->GetTargetType(host))); | |
| 440 } | |
| 441 } | |
| 442 std::sort(page_list.begin(), page_list.end(), SortPageListByTime); | 368 std::sort(page_list.begin(), page_list.end(), SortPageListByTime); |
| 443 return page_list; | 369 return page_list; |
| 444 } | 370 } |
| 445 | 371 |
| 446 std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal( | 372 std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal( |
| 447 const std::string rvh_id, | 373 const std::string rvh_id, |
| 448 const std::string& host) { | 374 const std::string& host) { |
| 449 return base::StringPrintf( | 375 return base::StringPrintf( |
| 450 "%s%sws=%s/devtools/page/%s", | 376 "%s%sws=%s/devtools/page/%s", |
| 451 overridden_frontend_url_.c_str(), | 377 overridden_frontend_url_.c_str(), |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 538 if (command == "new") { | 464 if (command == "new") { |
| 539 RenderViewHost* rvh = delegate_->CreateNewTarget(); | 465 RenderViewHost* rvh = delegate_->CreateNewTarget(); |
| 540 if (!rvh) { | 466 if (!rvh) { |
| 541 SendJson(connection_id, | 467 SendJson(connection_id, |
| 542 net::HTTP_INTERNAL_SERVER_ERROR, | 468 net::HTTP_INTERNAL_SERVER_ERROR, |
| 543 NULL, | 469 NULL, |
| 544 "Could not create new page", | 470 "Could not create new page", |
| 545 jsonp); | 471 jsonp); |
| 546 return; | 472 return; |
| 547 } | 473 } |
| 548 PageInfo page_info = | |
| 549 CreatePageInfo(rvh, DevToolsHttpHandlerDelegate::kTargetTypeTab); | |
| 550 std::string host = info.headers["Host"]; | 474 std::string host = info.headers["Host"]; |
| 551 scoped_ptr<base::DictionaryValue> dictionary( | 475 scoped_ptr<base::DictionaryValue> dictionary( |
| 552 SerializePageInfo(page_info, host)); | 476 SerializePageInfo(DevToolsAgentHost::GetFor(rvh), host)); |
| 553 SendJson(connection_id, net::HTTP_OK, dictionary.get(), "", jsonp); | 477 SendJson(connection_id, net::HTTP_OK, dictionary.get(), "", jsonp); |
| 554 return; | 478 return; |
| 555 } | 479 } |
| 556 | 480 |
| 557 if (command == "activate" || command == "close") { | 481 if (command == "activate" || command == "close") { |
| 558 DevToolsAgentHost* agent_host = binding_->ForIdentifier(target_id); | 482 DevToolsAgentHost* agent_host = binding_->ForIdentifier(target_id); |
| 559 RenderViewHost* rvh = agent_host ? agent_host->GetRenderViewHost() : NULL; | 483 RenderViewHost* rvh = agent_host ? agent_host->GetRenderViewHost() : NULL; |
| 560 if (!rvh) { | 484 if (!rvh) { |
| 561 SendJson(connection_id, | 485 SendJson(connection_id, |
| 562 net::HTTP_NOT_FOUND, | 486 net::HTTP_NOT_FOUND, |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 706 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( | 630 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( |
| 707 const net::StreamListenSocketFactory* socket_factory, | 631 const net::StreamListenSocketFactory* socket_factory, |
| 708 const std::string& frontend_url, | 632 const std::string& frontend_url, |
| 709 DevToolsHttpHandlerDelegate* delegate) | 633 DevToolsHttpHandlerDelegate* delegate) |
| 710 : overridden_frontend_url_(frontend_url), | 634 : overridden_frontend_url_(frontend_url), |
| 711 socket_factory_(socket_factory), | 635 socket_factory_(socket_factory), |
| 712 delegate_(delegate) { | 636 delegate_(delegate) { |
| 713 if (overridden_frontend_url_.empty()) | 637 if (overridden_frontend_url_.empty()) |
| 714 overridden_frontend_url_ = "/devtools/devtools.html"; | 638 overridden_frontend_url_ = "/devtools/devtools.html"; |
| 715 | 639 |
| 716 default_binding_.reset(new DevToolsDefaultBindingHandler); | 640 binding_ = DevToolsTargetList::GetInstance(); |
| 717 binding_ = default_binding_.get(); | |
| 718 | 641 |
| 719 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 642 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| 720 NotificationService::AllBrowserContextsAndSources()); | 643 NotificationService::AllBrowserContextsAndSources()); |
| 721 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, | 644 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| 722 NotificationService::AllBrowserContextsAndSources()); | 645 NotificationService::AllBrowserContextsAndSources()); |
| 723 | 646 |
| 724 // Balanced in ResetHandlerThreadAndRelease(). | 647 // Balanced in ResetHandlerThreadAndRelease(). |
| 725 AddRef(); | 648 AddRef(); |
| 726 } | 649 } |
| 727 | 650 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 830 int connection_id, | 753 int connection_id, |
| 831 const net::HttpServerRequestInfo& request) { | 754 const net::HttpServerRequestInfo& request) { |
| 832 if (!thread_.get()) | 755 if (!thread_.get()) |
| 833 return; | 756 return; |
| 834 thread_->message_loop()->PostTask( | 757 thread_->message_loop()->PostTask( |
| 835 FROM_HERE, | 758 FROM_HERE, |
| 836 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), | 759 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), |
| 837 connection_id, request)); | 760 connection_id, request)); |
| 838 } | 761 } |
| 839 | 762 |
| 840 DevToolsHttpHandlerImpl::PageInfo | 763 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializePageInfo( |
| 841 DevToolsHttpHandlerImpl::CreatePageInfo(RenderViewHost* rvh, | 764 DevToolsAgentHost* agent_host, |
| 842 DevToolsHttpHandlerDelegate::TargetType type) { | 765 const std::string& host) { |
| 843 RenderViewHostDelegate* host_delegate = rvh->GetDelegate(); | 766 base::DictionaryValue* dictionary = new base::DictionaryValue; |
| 844 scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetFor(rvh)); | 767 dictionary->SetString("title", agent_host->title()); |
| 845 DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> | 768 dictionary->SetString("url", agent_host->url().spec()); |
| 846 GetDevToolsClientHostFor(agent); | 769 switch (delegate_->GetTargetType(agent_host->GetRenderViewHost())) { |
| 847 PageInfo page_info; | |
| 848 page_info.id = binding_->GetIdentifier(agent); | |
| 849 page_info.attached = client_host != NULL; | |
| 850 page_info.url = host_delegate->GetURL().spec(); | |
| 851 | |
| 852 switch (type) { | |
| 853 case DevToolsHttpHandlerDelegate::kTargetTypeTab: | 770 case DevToolsHttpHandlerDelegate::kTargetTypeTab: |
| 854 page_info.type = "page"; | 771 dictionary->SetString("type", "page"); |
| 855 break; | 772 break; |
| 856 default: | 773 default: |
| 857 page_info.type = "other"; | 774 dictionary->SetString("type", "other"); |
| 858 } | 775 } |
| 859 | 776 std::string id = binding_->GetIdentifier(agent_host); |
| 860 WebContents* web_contents = host_delegate->GetAsWebContents(); | 777 dictionary->SetString("id", id); |
| 861 if (web_contents) { | 778 dictionary->SetString("thumbnailUrl", agent_host->thumbnail_url().spec()); |
| 862 page_info.title = UTF16ToUTF8( | 779 dictionary->SetString("faviconUrl", agent_host->favicon_url().spec()); |
| 863 net::EscapeForHTML(web_contents->GetTitle())); | 780 if (!agent_host->attached()) { |
| 864 page_info.last_selected_time = web_contents->GetLastSelectedTime(); | |
| 865 | |
| 866 NavigationController& controller = web_contents->GetController(); | |
| 867 NavigationEntry* entry = controller.GetActiveEntry(); | |
| 868 if (entry != NULL && entry->GetURL().is_valid()) { | |
| 869 page_info.thumbnail_url = "/thumb/" + entry->GetURL().spec(); | |
| 870 page_info.favicon_url = entry->GetFavicon().url.spec(); | |
| 871 } | |
| 872 } | |
| 873 return page_info; | |
| 874 } | |
| 875 | |
| 876 base::DictionaryValue* DevToolsHttpHandlerImpl::SerializePageInfo( | |
| 877 const PageInfo& page_info, | |
| 878 const std::string& host) { | |
| 879 base::DictionaryValue* dictionary = new base::DictionaryValue; | |
| 880 dictionary->SetString("title", page_info.title); | |
| 881 dictionary->SetString("url", page_info.url); | |
| 882 dictionary->SetString("type", page_info.type); | |
| 883 dictionary->SetString("id", page_info.id); | |
| 884 dictionary->SetString("thumbnailUrl", page_info.thumbnail_url); | |
| 885 dictionary->SetString("faviconUrl", page_info.favicon_url); | |
| 886 if (!page_info.attached) { | |
| 887 dictionary->SetString("webSocketDebuggerUrl", | 781 dictionary->SetString("webSocketDebuggerUrl", |
| 888 base::StringPrintf("ws://%s/devtools/page/%s", | 782 base::StringPrintf("ws://%s/devtools/page/%s", |
| 889 host.c_str(), | 783 host.c_str(), |
| 890 page_info.id.c_str())); | 784 id.c_str())); |
| 891 std::string devtools_frontend_url = GetFrontendURLInternal( | 785 std::string devtools_frontend_url = GetFrontendURLInternal( |
| 892 page_info.id.c_str(), | 786 id.c_str(), |
| 893 host); | 787 host); |
| 894 dictionary->SetString("devtoolsFrontendUrl", devtools_frontend_url); | 788 dictionary->SetString("devtoolsFrontendUrl", devtools_frontend_url); |
| 895 } | 789 } |
| 896 return dictionary; | 790 return dictionary; |
| 897 } | 791 } |
| 898 | 792 |
| 899 } // namespace content | 793 } // namespace content |
| OLD | NEW |