1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/debugger/devtools_http_protocol_handler.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <utility> 872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/compiler_specific.h" 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/json/json_writer.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop_proxy.h" 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h" 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/values.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/debugger/devtools_client_host.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/debugger/devtools_manager.h" 1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/webui/devtools_ui.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/devtools_messages.h" 23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h" 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/io_buffer.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/server/http_server_request_info.h" 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_context.h" 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/url_request/url_request_context_getter.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kBufferSize = 16 * 1024; 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// An internal implementation of DevToolsClientHost that delegates 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// messages sent for DevToolsClient to a DebuggerShell instance. 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass DevToolsClientHostImpl : public DevToolsClientHost { 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DevToolsClientHostImpl( 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::HttpServer* server, 4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int connection_id) 4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen : server_(server), 4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_id_(connection_id) { 4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~DevToolsClientHostImpl() {} 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DevToolsClientHost interface 483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void InspectedTabClosing() { 49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, 513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FROM_HERE, 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NewRunnableMethod(server_, 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &net::HttpServer::Close, 5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_id_)); 553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void SendMessageToClient(const IPC::Message& msg) { 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IPC_BEGIN_MESSAGE_MAP(DevToolsClientHostImpl, msg) 593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend, 603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OnDispatchOnInspectorFrontend); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IPC_MESSAGE_UNHANDLED_ERROR() 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IPC_END_MESSAGE_MAP() 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual void TabReplaced(TabContentsWrapper* new_tab) { 6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void NotifyCloseListener() { 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DevToolsClientHost::NotifyCloseListener(); 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Message handling routines 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void OnDispatchOnInspectorFrontend(const std::string& data) { 7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BrowserThread::PostTask( 7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BrowserThread::IO, 7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FROM_HERE, 7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NewRunnableMethod(server_, 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &net::HttpServer::SendOverWebSocket, 7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_id_, 8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen data)); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual void FrameNavigating(const std::string& url) {} 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::HttpServer* server_; 8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int connection_id_; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} // namespace 8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenscoped_refptr<DevToolsHttpProtocolHandler> DevToolsHttpProtocolHandler::Start( 9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& ip, 9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int port, 9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& frontend_url, 9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen TabContentsProvider* provider) { 9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_refptr<DevToolsHttpProtocolHandler> http_handler = 9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen new DevToolsHttpProtocolHandler(ip, port, frontend_url, provider); 9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen http_handler->Start(); 10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return http_handler; 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDevToolsHttpProtocolHandler::~DevToolsHttpProtocolHandler() { 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Stop() must be called prior to this being called 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(server_.get() == NULL); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsHttpProtocolHandler::Start() { 109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &DevToolsHttpProtocolHandler::Init)); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsHttpProtocolHandler::Stop() { 115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &DevToolsHttpProtocolHandler::Teardown)); 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DevToolsHttpProtocolHandler::OnHttpRequest( 12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int connection_id, 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const net::HttpServerRequestInfo& info) { 1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (info.path == "" || info.path == "/") { 1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Pages discovery request. 125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, 1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FROM_HERE, 1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NewRunnableMethod(this, 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &DevToolsHttpProtocolHandler::OnRootRequestUI, 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen connection_id, 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen info)); 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (info.path == "/json") { 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Pages discovery json request. 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::PostTask( 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::UI, 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FROM_HERE, 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NewRunnableMethod(this, 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &DevToolsHttpProtocolHandler::OnJsonRequestUI, 14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_id, 1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick info)); 1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick size_t pos = info.path.find("/devtools/"); 1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (pos != 0) { 14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_->Send404(connection_id); 1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Proxy static files from chrome-devtools://devtools/*. 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!Profile::GetDefaultRequestContext()) { 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen server_->Send404(connection_id); 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Make sure DevTools data source is registered. 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DevToolsUI::RegisterDevToolsDataSource(); 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 16221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen net::URLRequest* request = new net::URLRequest( 163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL("chrome-devtools:/" + info.path), this); 16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Bind(request, connection_id); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->set_context( 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile::GetDefaultRequestContext()->GetURLRequestContext()); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->Start(); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsHttpProtocolHandler::OnWebSocketRequest( 17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int connection_id, 172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const net::HttpServerRequestInfo& request) { 173731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 174731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, 1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FROM_HERE, 1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NewRunnableMethod( 1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this, 1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &DevToolsHttpProtocolHandler::OnWebSocketRequestUI, 17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_id, 1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request)); 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid DevToolsHttpProtocolHandler::OnWebSocketMessage( 18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int connection_id, 18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& data) { 186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FROM_HERE, 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod( 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &DevToolsHttpProtocolHandler::OnWebSocketMessageUI, 19272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_id, 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data)); 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid DevToolsHttpProtocolHandler::OnClose(int connection_id) { 19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ConnectionToRequestsMap::iterator it = 19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_to_requests_io_.find(connection_id); 19972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (it != connection_to_requests_io_.end()) { 2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Dispose delegating socket. 20121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (std::set<net::URLRequest*>::iterator it2 = it->second.begin(); 2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick it2 != it->second.end(); ++it2) { 20321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen net::URLRequest* request = *it2; 2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request->Cancel(); 20572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen request_to_connection_io_.erase(request); 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_to_buffer_io_.erase(request); 2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete request; 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 20972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_to_requests_io_.erase(connection_id); 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 212731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 213731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FROM_HERE, 2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NewRunnableMethod( 2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this, 2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &DevToolsHttpProtocolHandler::OnCloseUI, 21872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_id)); 2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstruct PageInfo 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen{ 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int id; 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string url; 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool attached; 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string title; 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string favicon_url; 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsentypedef std::vector<PageInfo> PageList; 23072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic PageList GeneratePageList( 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DevToolsHttpProtocolHandler::TabContentsProvider* tab_contents_provider, 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int connection_id, 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const net::HttpServerRequestInfo& info) { 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen typedef DevToolsHttpProtocolHandler::InspectableTabs Tabs; 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Tabs inspectable_tabs = tab_contents_provider->GetInspectableTabs(); 23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PageList page_list; 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (Tabs::iterator it = inspectable_tabs.begin(); 24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen it != inspectable_tabs.end(); ++it) { 24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 24272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen TabContentsWrapper* tab_contents = *it; 24372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NavigationController& controller = tab_contents->controller(); 24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigationEntry* entry = controller.GetActiveEntry(); 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (entry == NULL || !entry->url().is_valid()) 24772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 24872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> 25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GetDevToolsClientHostFor(tab_contents->tab_contents()-> 251201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch render_view_host()); 252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PageInfo page_info; 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen page_info.id = controller.session_id().id(); 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen page_info.attached = client_host != NULL; 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen page_info.url = entry->url().spec(); 256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen page_info.title = UTF16ToUTF8(entry->title()); 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen page_info.favicon_url = entry->favicon().url().spec(); 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen page_list.push_back(page_info); 2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return page_list; 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DevToolsHttpProtocolHandler::OnRootRequestUI( 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int connection_id, 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const net::HttpServerRequestInfo& info) { 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string host = info.headers["Host"]; 267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string response = "<html><body>"; 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PageList page_list = GeneratePageList(tab_contents_provider_.get(), 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen connection_id, info); 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (PageList::iterator i = page_list.begin(); 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen i != page_list.end(); ++i) { 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string frontendURL = StringPrintf("%s?host=%s&page=%d", 274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen overriden_frontend_url_.c_str(), 275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen host.c_str(), 276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen i->id); 277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen response += "<div>"; 278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen response += StringPrintf( 279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "<img style=\"margin-right:5px;width:16px;height:16px\" src=\"%s\">", 280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen i->favicon_url.c_str()); 281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (i->attached) { 283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen response += i->url.c_str(); 284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen response += StringPrintf("<a href=\"%s\">%s</a><br>", 286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen frontendURL.c_str(), 287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen i->url.c_str()); 288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen response += "</div>"; 290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen response += "</body></html>"; 29272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Send200(connection_id, response, "text/html; charset=UTF-8"); 2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DevToolsHttpProtocolHandler::OnJsonRequestUI( 296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int connection_id, 297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const net::HttpServerRequestInfo& info) { 298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PageList page_list = GeneratePageList(tab_contents_provider_.get(), 299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen connection_id, info); 300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListValue json_pages_list; 301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string host = info.headers["Host"]; 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (PageList::iterator i = page_list.begin(); 303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen i != page_list.end(); ++i) { 304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DictionaryValue* page_info = new DictionaryValue; 306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen json_pages_list.Append(page_info); 307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen page_info->SetString("title", i->title); 308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen page_info->SetString("url", i->url); 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen page_info->SetString("faviconUrl", i->favicon_url); 310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!i->attached) { 311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen page_info->SetString("webSocketDebuggerUrl", 312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StringPrintf("ws://%s/devtools/page/%d", 313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen host.c_str(), 314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen i->id)); 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen page_info->SetString( 316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "devtoolsFrontendUrl", 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StringPrintf("http://%s/devtools/devtools.html?page=%d", 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen host.c_str(), 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen i->id)); 320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string response; 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::JSONWriter::Write(&json_pages_list, true, &response); 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Send200(connection_id, response, "application/json; charset=UTF-8"); 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 3283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DevToolsHttpProtocolHandler::OnWebSocketRequestUI( 32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int connection_id, 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const net::HttpServerRequestInfo& request) { 3313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string prefix = "/devtools/page/"; 3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick size_t pos = request.path.find(prefix); 3333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (pos != 0) { 33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Send404(connection_id); 3353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 3363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string page_id = request.path.substr(prefix.length()); 3383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int id = 0; 3393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!base::StringToInt(page_id, &id)) { 34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Send500(connection_id, "Invalid page id: " + page_id); 3413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TabContents* tab_contents = GetTabContents(id); 3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (tab_contents == NULL) { 34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Send500(connection_id, "No such page id: " + page_id); 3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 3483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DevToolsManager* manager = DevToolsManager::GetInstance(); 3513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (manager->GetDevToolsClientHostFor(tab_contents->render_view_host())) { 35272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Send500(connection_id, "Page with given id is being inspected: " + page_id); 3533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 35672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DevToolsClientHostImpl* client_host = 35772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen new DevToolsClientHostImpl(server_, connection_id); 35872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_to_client_host_ui_[connection_id] = client_host; 3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick manager->RegisterDevToolsClientHostFor( 3613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick tab_contents->render_view_host(), 3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick client_host); 36372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen manager->ForwardToDevToolsAgent( 36472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen client_host, 36572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DevToolsAgentMsg_FrontendLoaded()); 36672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 36772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen AcceptWebSocket(connection_id, request); 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DevToolsHttpProtocolHandler::OnWebSocketMessageUI( 37172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int connection_id, 3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& data) { 37372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ConnectionToClientHostMap::iterator it = 37472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_to_client_host_ui_.find(connection_id); 37572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (it == connection_to_client_host_ui_.end()) 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DevToolsManager* manager = DevToolsManager::GetInstance(); 3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick manager->ForwardToDevToolsAgent( 3803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick it->second, 3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DevToolsAgentMsg_DispatchOnInspectorBackend(data)); 3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 38472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid DevToolsHttpProtocolHandler::OnCloseUI(int connection_id) { 38572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ConnectionToClientHostMap::iterator it = 38672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_to_client_host_ui_.find(connection_id); 38772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (it != connection_to_client_host_ui_.end()) { 38821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DevToolsClientHostImpl* client_host = 38921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen static_cast<DevToolsClientHostImpl*>(it->second); 39021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen client_host->NotifyCloseListener(); 39121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete client_host; 39272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_to_client_host_ui_.erase(connection_id); 39321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 39621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid DevToolsHttpProtocolHandler::OnResponseStarted(net::URLRequest* request) { 39772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen RequestToSocketMap::iterator it = request_to_connection_io_.find(request); 39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (it == request_to_connection_io_.end()) 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int connection_id = it->second; 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string content_type; 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->GetMimeType(&content_type); 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->status().is_success()) { 40772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_->Send(connection_id, StringPrintf("HTTP/1.1 200 OK\r\n" 40872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "Content-Type:%s\r\n" 409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "Transfer-Encoding: chunked\r\n" 41072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "\r\n", 411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen content_type.c_str())); 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 41372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_->Send404(connection_id); 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bytes_read = 0; 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Some servers may treat HEAD requests as GET requests. To free up the 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // network connection as soon as possible, signal that the request has 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // completed immediately, without trying to read any data back (all we care 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // about is the response code and headers, which we already have). 4213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net::IOBuffer* buffer = request_to_buffer_io_[request].get(); 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->status().is_success()) 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->Read(buffer, kBufferSize, &bytes_read); 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnReadCompleted(request, bytes_read); 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid DevToolsHttpProtocolHandler::OnReadCompleted(net::URLRequest* request, 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bytes_read) { 42972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen RequestToSocketMap::iterator it = request_to_connection_io_.find(request); 43072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (it == request_to_connection_io_.end()) 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int connection_id = it->second; 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net::IOBuffer* buffer = request_to_buffer_io_[request].get(); 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch do { 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!request->status().is_success() || bytes_read <= 0) 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string chunk_size = StringPrintf("%X\r\n", bytes_read); 440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen server_->Send(connection_id, chunk_size); 44172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_->Send(connection_id, buffer->data(), bytes_read); 442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen server_->Send(connection_id, "\r\n"); 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } while (request->Read(buffer, kBufferSize, &bytes_read)); 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See comments re: HEAD requests in OnResponseStarted(). 447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!request->status().is_io_pending()) { 448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen server_->Send(connection_id, "0\r\n\r\n"); 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RequestCompleted(request); 450ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenDevToolsHttpProtocolHandler::DevToolsHttpProtocolHandler( 45472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& ip, 45572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int port, 45672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& frontend_host, 45772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen TabContentsProvider* provider) 45872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen : ip_(ip), 45972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen port_(port), 46072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen overriden_frontend_url_(frontend_host), 46172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen tab_contents_provider_(provider) { 46272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (overriden_frontend_url_.empty()) 46372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen overriden_frontend_url_ = "/devtools/devtools.html"; 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsHttpProtocolHandler::Init() { 467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen server_ = new net::HttpServer(ip_, port_, this); 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Run on I/O thread 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsHttpProtocolHandler::Teardown() { 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch server_ = NULL; 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid DevToolsHttpProtocolHandler::Bind(net::URLRequest* request, 47672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int connection_id) { 47772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen request_to_connection_io_[request] = connection_id; 47872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ConnectionToRequestsMap::iterator it = 47972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_to_requests_io_.find(connection_id); 48072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (it == connection_to_requests_io_.end()) { 48172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::pair<int, std::set<net::URLRequest*> > value( 48272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_id, 48321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::set<net::URLRequest*>()); 48472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen it = connection_to_requests_io_.insert(value).first; 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it->second.insert(request); 4873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_to_buffer_io_[request] = new net::IOBuffer(kBufferSize); 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid DevToolsHttpProtocolHandler::RequestCompleted(net::URLRequest* request) { 49172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen RequestToSocketMap::iterator it = request_to_connection_io_.find(request); 49272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (it == request_to_connection_io_.end()) 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int connection_id = it->second; 49672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen request_to_connection_io_.erase(request); 49772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ConnectionToRequestsMap::iterator it2 = 49872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_to_requests_io_.find(connection_id); 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it2->second.erase(request); 5003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_to_buffer_io_.erase(request); 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete request; 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 5033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 50472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid DevToolsHttpProtocolHandler::Send200(int connection_id, 5053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& data, 5063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& mime_type) { 507731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 508731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 50972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NewRunnableMethod(server_.get(), 510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &net::HttpServer::Send200, 51172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_id, 5123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick data, 5133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick mime_type)); 5143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 51672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid DevToolsHttpProtocolHandler::Send404(int connection_id) { 517731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 518731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 51972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NewRunnableMethod(server_.get(), 520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &net::HttpServer::Send404, 52172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_id)); 5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 52472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid DevToolsHttpProtocolHandler::Send500(int connection_id, 5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& message) { 526731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 527731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 52872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NewRunnableMethod(server_.get(), 529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &net::HttpServer::Send500, 53072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_id, 5313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick message)); 5323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DevToolsHttpProtocolHandler::AcceptWebSocket( 53572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int connection_id, 536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const net::HttpServerRequestInfo& request) { 537731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 538731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 53972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NewRunnableMethod(server_.get(), 540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &net::HttpServer::AcceptWebSocket, 54172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen connection_id, 5423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request)); 5433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5453345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTabContents* DevToolsHttpProtocolHandler::GetTabContents(int session_id) { 54672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen InspectableTabs inspectable_tabs = 54772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen tab_contents_provider_->GetInspectableTabs(); 54872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 54972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (InspectableTabs::iterator it = inspectable_tabs.begin(); 55072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen it != inspectable_tabs.end(); ++it) { 55172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen TabContentsWrapper* tab_contents = *it; 55272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NavigationController& controller = 55372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen tab_contents->controller(); 55472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (controller.session_id().id() == session_id) 55572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return controller.tab_contents(); 5563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 5573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return NULL; 5583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 559