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

Side by Side Diff: content/browser/debugger/devtools_http_handler_impl.cc

Issue 9113079: DevTools: refactor remote debugging server to enable content_shell debugging. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Patch for landing. Created 8 years, 11 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
OLDNEW
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 <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/json/json_writer.h" 11 #include "base/json/json_writer.h"
12 #include "base/lazy_instance.h" 12 #include "base/lazy_instance.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/message_loop_proxy.h" 14 #include "base/message_loop_proxy.h"
15 #include "base/string_number_conversions.h" 15 #include "base/string_number_conversions.h"
16 #include "base/stringprintf.h" 16 #include "base/stringprintf.h"
17 #include "base/threading/thread.h" 17 #include "base/threading/thread.h"
18 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
19 #include "base/values.h" 19 #include "base/values.h"
20 #include "content/browser/tab_contents/tab_contents.h"
21 #include "content/common/devtools_messages.h" 20 #include "content/common/devtools_messages.h"
22 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/devtools_agent_host_registry.h" 22 #include "content/public/browser/devtools_agent_host_registry.h"
24 #include "content/public/browser/devtools_client_host.h" 23 #include "content/public/browser/devtools_client_host.h"
25 #include "content/public/browser/devtools_http_handler_delegate.h" 24 #include "content/public/browser/devtools_http_handler_delegate.h"
26 #include "content/public/browser/devtools_manager.h" 25 #include "content/public/browser/devtools_manager.h"
27 #include "content/public/browser/favicon_status.h" 26 #include "content/public/browser/favicon_status.h"
28 #include "content/public/browser/navigation_entry.h" 27 #include "content/public/browser/navigation_entry.h"
28 #include "content/public/browser/web_contents.h"
jam 2012/01/26 17:30:08 inside content, we prefer to use the implementatio
pfeldman 2012/01/26 17:34:13 Ok, so you are saying I should revert the tab_cont
29 #include "content/public/browser/web_contents_observer.h" 29 #include "content/public/browser/web_contents_observer.h"
30 #include "content/public/common/content_client.h"
30 #include "googleurl/src/gurl.h" 31 #include "googleurl/src/gurl.h"
32 #include "grit/devtools_resources_map.h"
31 #include "net/base/escape.h" 33 #include "net/base/escape.h"
32 #include "net/base/io_buffer.h" 34 #include "net/base/io_buffer.h"
33 #include "net/server/http_server_request_info.h" 35 #include "net/server/http_server_request_info.h"
34 #include "net/url_request/url_request_context.h" 36 #include "net/url_request/url_request_context.h"
35 37
36 namespace content { 38 namespace content {
37 39
38 const int kBufferSize = 16 * 1024; 40 const int kBufferSize = 16 * 1024;
39 41
40 namespace { 42 namespace {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 } 75 }
74 76
75 private: 77 private:
76 virtual void FrameNavigating(const std::string& url) {} 78 virtual void FrameNavigating(const std::string& url) {}
77 net::HttpServer* server_; 79 net::HttpServer* server_;
78 int connection_id_; 80 int connection_id_;
79 }; 81 };
80 82
81 static int next_id = 1; 83 static int next_id = 1;
82 84
83 class TabContentsIDHelper : public content::WebContentsObserver { 85 class WebContentsIDHelper : public content::WebContentsObserver {
84 public: 86 public:
85 87 static int GetID(WebContents* contents) {
86 static int GetID(TabContents* tab) { 88 WebContentsToIdMap::iterator it = web_contents_to_id_.Get().find(contents);
87 TabContentsToIdMap::iterator it = tabcontents_to_id_.Get().find(tab); 89 if (it != web_contents_to_id_.Get().end())
88 if (it != tabcontents_to_id_.Get().end())
89 return it->second; 90 return it->second;
90 TabContentsIDHelper* wrapper = new TabContentsIDHelper(tab); 91 WebContentsIDHelper* wrapper = new WebContentsIDHelper(contents);
91 return wrapper->id_; 92 return wrapper->id_;
92 } 93 }
93 94
94 static TabContents* GetTabContents(int id) { 95 static WebContents* GetWebContents(int id) {
95 IdToTabContentsMap::iterator it = id_to_tabcontents_.Get().find(id); 96 IdToWebContentsMap::iterator it = id_to_web_contents_.Get().find(id);
96 if (it != id_to_tabcontents_.Get().end()) 97 if (it != id_to_web_contents_.Get().end())
97 return it->second; 98 return it->second;
98 return NULL; 99 return NULL;
99 } 100 }
100 101
101 private: 102 private:
102 explicit TabContentsIDHelper(TabContents* tab) 103 explicit WebContentsIDHelper(WebContents* tab)
103 : content::WebContentsObserver(tab), 104 : content::WebContentsObserver(tab),
104 id_(next_id++) { 105 id_(next_id++) {
105 id_to_tabcontents_.Get()[id_] = tab; 106 id_to_web_contents_.Get()[id_] = tab;
106 tabcontents_to_id_.Get()[tab] = id_; 107 web_contents_to_id_.Get()[tab] = id_;
107 } 108 }
108 109
109 virtual ~TabContentsIDHelper() {} 110 virtual ~WebContentsIDHelper() {}
110 111
111 virtual void WebContentsDestroyed(WebContents* tab) OVERRIDE { 112 virtual void WebContentsDestroyed(WebContents* contents) OVERRIDE {
112 id_to_tabcontents_.Get().erase(id_); 113 id_to_web_contents_.Get().erase(id_);
113 tabcontents_to_id_.Get().erase(static_cast<TabContents*>(tab)); 114 web_contents_to_id_.Get().erase(contents);
114 delete this; 115 delete this;
115 } 116 }
116 117
117 int id_; 118 int id_;
118 typedef std::map<int, TabContents*> IdToTabContentsMap; 119 typedef std::map<int, WebContents*> IdToWebContentsMap;
119 static base::LazyInstance<IdToTabContentsMap>::Leaky 120 static base::LazyInstance<IdToWebContentsMap>::Leaky
120 id_to_tabcontents_; 121 id_to_web_contents_;
121 typedef std::map<TabContents*, int> TabContentsToIdMap; 122 typedef std::map<WebContents*, int> WebContentsToIdMap;
122 static base::LazyInstance<TabContentsToIdMap>::Leaky 123 static base::LazyInstance<WebContentsToIdMap>::Leaky
123 tabcontents_to_id_; 124 web_contents_to_id_;
124 }; 125 };
125 126
126 base::LazyInstance<TabContentsIDHelper::IdToTabContentsMap>::Leaky 127 base::LazyInstance<WebContentsIDHelper::IdToWebContentsMap>::Leaky
127 TabContentsIDHelper::id_to_tabcontents_ = LAZY_INSTANCE_INITIALIZER; 128 WebContentsIDHelper::id_to_web_contents_ = LAZY_INSTANCE_INITIALIZER;
128 base::LazyInstance<TabContentsIDHelper::TabContentsToIdMap>::Leaky 129 base::LazyInstance<WebContentsIDHelper::WebContentsToIdMap>::Leaky
129 TabContentsIDHelper::tabcontents_to_id_ = LAZY_INSTANCE_INITIALIZER; 130 WebContentsIDHelper::web_contents_to_id_ = LAZY_INSTANCE_INITIALIZER;
130 131
131 } // namespace 132 } // namespace
132 133
133 // static 134 // static
135 int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) {
136 for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) {
137 if (name == kDevtoolsResources[i].name)
138 return kDevtoolsResources[i].value;
139 }
140 return -1;
141 }
142
143 // static
134 DevToolsHttpHandler* DevToolsHttpHandler::Start( 144 DevToolsHttpHandler* DevToolsHttpHandler::Start(
135 const std::string& ip, 145 const std::string& ip,
136 int port, 146 int port,
137 const std::string& frontend_url, 147 const std::string& frontend_url,
138 DevToolsHttpHandlerDelegate* delegate) { 148 DevToolsHttpHandlerDelegate* delegate) {
139 DevToolsHttpHandlerImpl* http_handler = 149 DevToolsHttpHandlerImpl* http_handler =
140 new DevToolsHttpHandlerImpl(ip, port, frontend_url, delegate); 150 new DevToolsHttpHandlerImpl(ip, port, frontend_url, delegate);
141 http_handler->Start(); 151 http_handler->Start();
142 return http_handler; 152 return http_handler;
143 } 153 }
144 154
145 DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { 155 DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() {
146 // Stop() must be called prior to this being called 156 // Stop() must be called prior to this being called
147 DCHECK(server_.get() == NULL); 157 DCHECK(server_.get() == NULL);
148 } 158 }
149 159
150 void DevToolsHttpHandlerImpl::Start() { 160 void DevToolsHttpHandlerImpl::Start() {
151 BrowserThread::PostTask( 161 BrowserThread::PostTask(
152 BrowserThread::IO, FROM_HERE, 162 BrowserThread::IO, FROM_HERE,
153 base::Bind(&DevToolsHttpHandlerImpl::Init, this)); 163 base::Bind(&DevToolsHttpHandlerImpl::Init, this));
154 } 164 }
155 165
156 void DevToolsHttpHandlerImpl::Stop() { 166 void DevToolsHttpHandlerImpl::Stop() {
157 BrowserThread::PostTask( 167 BrowserThread::PostTask(
158 BrowserThread::IO, FROM_HERE, 168 BrowserThread::IO, FROM_HERE,
159 base::Bind(&DevToolsHttpHandlerImpl::TeardownAndRelease, this)); 169 base::Bind(&DevToolsHttpHandlerImpl::TeardownAndRelease, this));
160 } 170 }
161 171
172 static std::string PathWithoutParams(const std::string& path) {
173 size_t query_position = path.find("?");
174 if (query_position != std::string::npos)
175 return path.substr(0, query_position);
176 return path;
177 }
178
179 static std::string GetMimeType(const std::string& filename) {
180 if (EndsWith(filename, ".html", false)) {
181 return "text/html";
182 } else if (EndsWith(filename, ".css", false)) {
183 return "text/css";
184 } else if (EndsWith(filename, ".js", false)) {
185 return "application/javascript";
186 } else if (EndsWith(filename, ".png", false)) {
187 return "image/png";
188 } else if (EndsWith(filename, ".gif", false)) {
189 return "image/gif";
190 }
191 NOTREACHED();
192 return "text/plain";
193 }
194
162 void DevToolsHttpHandlerImpl::OnHttpRequest( 195 void DevToolsHttpHandlerImpl::OnHttpRequest(
163 int connection_id, 196 int connection_id,
164 const net::HttpServerRequestInfo& info) { 197 const net::HttpServerRequestInfo& info) {
165 if (info.path == "/json") { 198 if (info.path.find("/json") == 0) {
166 // Pages discovery json request. 199 // Pages discovery json request.
167 BrowserThread::PostTask( 200 BrowserThread::PostTask(
168 BrowserThread::UI, 201 BrowserThread::UI,
169 FROM_HERE, 202 FROM_HERE,
170 base::Bind(&DevToolsHttpHandlerImpl::OnJsonRequestUI, 203 base::Bind(&DevToolsHttpHandlerImpl::OnJsonRequestUI,
171 this, 204 this,
172 connection_id, 205 connection_id,
173 info)); 206 info));
174 return; 207 return;
175 } 208 }
176 209
210 if (info.path == "" || info.path == "/") {
211 std::string response = delegate_->GetDiscoveryPageHTML();
212 server_->Send200(connection_id, response, "text/html; charset=UTF-8");
213 return;
214 }
215
177 // Proxy static files from chrome-devtools://devtools/*. 216 // Proxy static files from chrome-devtools://devtools/*.
178 net::URLRequestContext* request_context = delegate_->GetURLRequestContext(); 217 net::URLRequestContext* request_context = delegate_->GetURLRequestContext();
179 if (!request_context) { 218 if (!request_context) {
180 server_->Send404(connection_id); 219 server_->Send404(connection_id);
181 return; 220 return;
182 } 221 }
183 222
184 if (info.path == "" || info.path == "/") {
185 std::string response = delegate_->GetDiscoveryPageHTML();
186 server_->Send200(connection_id, response, "text/html; charset=UTF-8");
187 return;
188 }
189
190 net::URLRequest* request; 223 net::URLRequest* request;
191 224
192 if (info.path.find("/devtools/") == 0) { 225 if (info.path.find("/devtools/") == 0) {
193 request = new net::URLRequest(GURL("chrome-devtools:/" + info.path), this); 226 // Serve front-end files from resource bundle.
227 std::string filename = PathWithoutParams(info.path.substr(10));
228
229 if (delegate_->BundlesFrontendResources()) {
230 int resource_id = DevToolsHttpHandler::GetFrontendResourceId(filename);
231 if (resource_id != -1) {
232 base::StringPiece data =
233 content::GetContentClient()->GetDataResource(resource_id);
234 server_->Send200(connection_id,
235 data.as_string(),
236 GetMimeType(filename));
237 }
238 return;
239 }
240 std::string base_url = delegate_->GetFrontendResourcesBaseURL();
241 request = new net::URLRequest(GURL(base_url + filename), this);
194 } else if (info.path.find("/thumb/") == 0) { 242 } else if (info.path.find("/thumb/") == 0) {
195 request = new net::URLRequest(GURL("chrome:/" + info.path), this); 243 request = new net::URLRequest(GURL("chrome:/" + info.path), this);
196 } else { 244 } else {
197 server_->Send404(connection_id); 245 server_->Send404(connection_id);
198 return; 246 return;
199 } 247 }
200 248
201 Bind(request, connection_id); 249 Bind(request, connection_id);
202 request->set_context(request_context); 250 request->set_context(request_context);
203 request->Start(); 251 request->Start();
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 334
287 NavigationEntry* entry = controller.GetActiveEntry(); 335 NavigationEntry* entry = controller.GetActiveEntry();
288 if (entry == NULL || !entry->GetURL().is_valid()) 336 if (entry == NULL || !entry->GetURL().is_valid())
289 continue; 337 continue;
290 338
291 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( 339 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost(
292 web_contents->GetRenderViewHost()); 340 web_contents->GetRenderViewHost());
293 DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> 341 DevToolsClientHost* client_host = DevToolsManager::GetInstance()->
294 GetDevToolsClientHostFor(agent); 342 GetDevToolsClientHostFor(agent);
295 PageInfo page_info; 343 PageInfo page_info;
296 page_info.id = TabContentsIDHelper::GetID( 344 page_info.id = WebContentsIDHelper::GetID(web_contents);
297 static_cast<TabContents*>(web_contents));
298 page_info.attached = client_host != NULL; 345 page_info.attached = client_host != NULL;
299 page_info.url = entry->GetURL().spec(); 346 page_info.url = entry->GetURL().spec();
300 page_info.title = UTF16ToUTF8(net::EscapeForHTML(entry->GetTitle())); 347 page_info.title = UTF16ToUTF8(net::EscapeForHTML(entry->GetTitle()));
301 page_info.thumbnail_url = "/thumb/" + entry->GetURL().spec(); 348 page_info.thumbnail_url = "/thumb/" + entry->GetURL().spec();
302 page_info.favicon_url = entry->GetFavicon().url.spec(); 349 page_info.favicon_url = entry->GetFavicon().url.spec();
303 page_info.last_selected_time = web_contents->GetLastSelectedTime(); 350 page_info.last_selected_time = web_contents->GetLastSelectedTime();
304 page_list.push_back(page_info); 351 page_list.push_back(page_info);
305 } 352 }
306 std::sort(page_list.begin(), page_list.end(), SortPageListByTime); 353 std::sort(page_list.begin(), page_list.end(), SortPageListByTime);
307 return page_list; 354 return page_list;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 Send404(connection_id); 399 Send404(connection_id);
353 return; 400 return;
354 } 401 }
355 std::string page_id = request.path.substr(prefix.length()); 402 std::string page_id = request.path.substr(prefix.length());
356 int id = 0; 403 int id = 0;
357 if (!base::StringToInt(page_id, &id)) { 404 if (!base::StringToInt(page_id, &id)) {
358 Send500(connection_id, "Invalid page id: " + page_id); 405 Send500(connection_id, "Invalid page id: " + page_id);
359 return; 406 return;
360 } 407 }
361 408
362 TabContents* tab_contents = TabContentsIDHelper::GetTabContents(id); 409 WebContents* web_contents = WebContentsIDHelper::GetWebContents(id);
363 if (tab_contents == NULL) { 410 if (web_contents == NULL) {
364 Send500(connection_id, "No such page id: " + page_id); 411 Send500(connection_id, "No such page id: " + page_id);
365 return; 412 return;
366 } 413 }
367 414
368 DevToolsManager* manager = DevToolsManager::GetInstance(); 415 DevToolsManager* manager = DevToolsManager::GetInstance();
369 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( 416 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost(
370 tab_contents->GetRenderViewHost()); 417 web_contents->GetRenderViewHost());
371 if (manager->GetDevToolsClientHostFor(agent)) { 418 if (manager->GetDevToolsClientHostFor(agent)) {
372 Send500(connection_id, "Page with given id is being inspected: " + page_id); 419 Send500(connection_id, "Page with given id is being inspected: " + page_id);
373 return; 420 return;
374 } 421 }
375 422
376 DevToolsClientHostImpl* client_host = 423 DevToolsClientHostImpl* client_host =
377 new DevToolsClientHostImpl(server_, connection_id); 424 new DevToolsClientHostImpl(server_, connection_id);
378 connection_to_client_host_ui_[connection_id] = client_host; 425 connection_to_client_host_ui_[connection_id] = client_host;
379 426
380 manager->RegisterDevToolsClientHostFor(agent, client_host); 427 manager->RegisterDevToolsClientHostFor(agent, client_host);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 // See comments re: HEAD requests in OnResponseStarted(). 507 // See comments re: HEAD requests in OnResponseStarted().
461 if (!request->status().is_io_pending()) { 508 if (!request->status().is_io_pending()) {
462 server_->Send(connection_id, "0\r\n\r\n"); 509 server_->Send(connection_id, "0\r\n\r\n");
463 RequestCompleted(request); 510 RequestCompleted(request);
464 } 511 }
465 } 512 }
466 513
467 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( 514 DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl(
468 const std::string& ip, 515 const std::string& ip,
469 int port, 516 int port,
470 const std::string& frontend_host, 517 const std::string& frontend_url,
471 DevToolsHttpHandlerDelegate* delegate) 518 DevToolsHttpHandlerDelegate* delegate)
472 : ip_(ip), 519 : ip_(ip),
473 port_(port), 520 port_(port),
474 overridden_frontend_url_(frontend_host), 521 overridden_frontend_url_(frontend_url),
475 delegate_(delegate) { 522 delegate_(delegate) {
476 if (overridden_frontend_url_.empty()) 523 if (overridden_frontend_url_.empty())
477 overridden_frontend_url_ = "/devtools/devtools.html"; 524 overridden_frontend_url_ = "/devtools/devtools.html";
525
478 AddRef(); 526 AddRef();
479 } 527 }
480 528
481 void DevToolsHttpHandlerImpl::Init() { 529 void DevToolsHttpHandlerImpl::Init() {
482 server_ = new net::HttpServer(ip_, port_, this); 530 server_ = new net::HttpServer(ip_, port_, this);
483 } 531 }
484 532
485 // Run on I/O thread 533 // Run on I/O thread
486 void DevToolsHttpHandlerImpl::TeardownAndRelease() { 534 void DevToolsHttpHandlerImpl::TeardownAndRelease() {
487 server_ = NULL; 535 server_ = NULL;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 mime_type)); 579 mime_type));
532 } 580 }
533 581
534 void DevToolsHttpHandlerImpl::Send404(int connection_id) { 582 void DevToolsHttpHandlerImpl::Send404(int connection_id) {
535 BrowserThread::PostTask( 583 BrowserThread::PostTask(
536 BrowserThread::IO, FROM_HERE, 584 BrowserThread::IO, FROM_HERE,
537 base::Bind(&net::HttpServer::Send404, server_.get(), connection_id)); 585 base::Bind(&net::HttpServer::Send404, server_.get(), connection_id));
538 } 586 }
539 587
540 void DevToolsHttpHandlerImpl::Send500(int connection_id, 588 void DevToolsHttpHandlerImpl::Send500(int connection_id,
541 const std::string& message) { 589 const std::string& message) {
542 BrowserThread::PostTask( 590 BrowserThread::PostTask(
543 BrowserThread::IO, FROM_HERE, 591 BrowserThread::IO, FROM_HERE,
544 base::Bind(&net::HttpServer::Send500, server_.get(), connection_id, 592 base::Bind(&net::HttpServer::Send500, server_.get(), connection_id,
545 message)); 593 message));
546 } 594 }
547 595
548 void DevToolsHttpHandlerImpl::AcceptWebSocket( 596 void DevToolsHttpHandlerImpl::AcceptWebSocket(
549 int connection_id, 597 int connection_id,
550 const net::HttpServerRequestInfo& request) { 598 const net::HttpServerRequestInfo& request) {
551 BrowserThread::PostTask( 599 BrowserThread::PostTask(
552 BrowserThread::IO, FROM_HERE, 600 BrowserThread::IO, FROM_HERE,
553 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(), 601 base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(),
554 connection_id, request)); 602 connection_id, request));
555 } 603 }
556 604
557 } // namespace content 605 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/debugger/devtools_http_handler_impl.h ('k') | content/browser/debugger/devtools_netlog_observer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698