12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/devtools/devtools_http_handler_impl.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <utility> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_writer.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/stl_util.h" 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/devtools/devtools_browser_target.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/devtools/devtools_manager.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/browser/devtools/devtools_protocol.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/browser/devtools/devtools_protocol_constants.h" 243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/browser/devtools/devtools_system_info_handler.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/devtools/devtools_tracing_handler.h" 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/browser/devtools/tethering_handler.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/devtools_messages.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/devtools_agent_host.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/devtools_http_handler_delegate.h" 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/devtools_target.h" 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_client.h" 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/url_constants.h" 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/common/user_agent.h" 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "grit/devtools_resources_map.h" 361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/base/escape.h" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h" 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/ip_endpoint.h" 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/base/net_errors.h" 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/server/http_server_request_info.h" 41a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "net/server/http_server_response_info.h" 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/socket/server_socket.h" 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_ANDROID) 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/android/build_info.h" 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const base::FilePath::CharType kDevToolsActivePortFileName[] = 5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FILE_PATH_LITERAL("DevToolsActivePort"); 5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kDevToolsHandlerThreadName[] = "Chrome_DevToolsHandlerThread"; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kThumbUrlPrefix[] = "/thumb/"; 5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kPageUrlPrefix[] = "/devtools/page/"; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kTargetIdField[] = "id"; 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kTargetParentIdField[] = "parentId"; 6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kTargetTypeField[] = "type"; 6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kTargetTitleField[] = "title"; 6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kTargetDescriptionField[] = "description"; 6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kTargetUrlField[] = "url"; 6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kTargetThumbnailUrlField[] = "thumbnailUrl"; 6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kTargetFaviconUrlField[] = "faviconUrl"; 6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kTargetWebSocketDebuggerUrlField[] = "webSocketDebuggerUrl"; 6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kTargetDevtoolsFrontendUrlField[] = "devtoolsFrontendUrl"; 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Maximum write buffer size of devtools http/websocket connectinos. 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int32 kSendBufferSizeForDevTools = 100 * 1024 * 1024; // 100Mb 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// An internal implementation of DevToolsAgentHostClient that delegates 7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// messages sent to a DebuggerShell instance. 7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class DevToolsAgentHostClientImpl : public DevToolsAgentHostClient { 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DevToolsAgentHostClientImpl(base::MessageLoop* message_loop, 7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) net::HttpServer* server, 8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int connection_id, 8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DevToolsAgentHost* agent_host) 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : message_loop_(message_loop), 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) server_(server), 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_id_(connection_id), 8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) agent_host_(agent_host) { 8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) agent_host_->AttachClient(this); 8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual ~DevToolsAgentHostClientImpl() { 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (agent_host_.get()) 9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) agent_host_->DetachClient(); 9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual void AgentHostClosed( 9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DevToolsAgentHost* agent_host, 9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool replaced_with_another_client) OVERRIDE { 9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(agent_host == agent_host_.get()); 9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) agent_host_ = NULL; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue notification; 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) notification.SetString( 10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) devtools::Inspector::detached::kParamReason, 10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) replaced_with_another_client ? 10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) "replaced_with_devtools" : "target_closed"); 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string response = DevToolsProtocol::CreateNotification( 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) devtools::Inspector::detached::kName, 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) notification.DeepCopy())->Serialize(); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_loop_->PostTask( 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&net::HttpServer::SendOverWebSocket, 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(server_), 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_id_, 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response)); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_loop_->PostTask( 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&net::HttpServer::Close, 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(server_), 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci connection_id_)); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual void DispatchProtocolMessage( 12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DevToolsAgentHost* agent_host, const std::string& message) OVERRIDE { 12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(agent_host == agent_host_.get()); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_loop_->PostTask( 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&net::HttpServer::SendOverWebSocket, 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(server_), 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_id_, 13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) message)); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void OnMessage(const std::string& message) { 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (agent_host_.get()) 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) agent_host_->DispatchProtocolMessage(message); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::MessageLoop* const message_loop_; 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci net::HttpServer* const server_; 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const int connection_id_; 14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<DevToolsAgentHost> agent_host_; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static bool TimeComparator(const DevToolsTarget* target1, 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const DevToolsTarget* target2) { 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return target1->GetLastActivityTime() > target2->GetLastActivityTime(); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool DevToolsHttpHandler::IsSupportedProtocolVersion( 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& version) { 1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return devtools::IsSupportedProtocolVersion(version); 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) { 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name == kDevtoolsResources[i].name) 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kDevtoolsResources[i].value; 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevToolsHttpHandler* DevToolsHttpHandler::Start( 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<ServerSocketFactory> server_socket_factory, 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& frontend_url, 17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DevToolsHttpHandlerDelegate* delegate, 17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const base::FilePath& active_port_output_directory) { 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DevToolsHttpHandlerImpl* http_handler = 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new DevToolsHttpHandlerImpl(server_socket_factory.Pass(), 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frontend_url, 17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) delegate, 17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) active_port_output_directory); 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) http_handler->Start(); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return http_handler; 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciDevToolsHttpHandler::ServerSocketFactory::ServerSocketFactory( 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& address, 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int port, 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int backlog) 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : address_(address), 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci port_(port), 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci backlog_(backlog) { 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciDevToolsHttpHandler::ServerSocketFactory::~ServerSocketFactory() { 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<net::ServerSocket> 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciDevToolsHttpHandler::ServerSocketFactory::CreateAndListen() const { 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<net::ServerSocket> socket = Create(); 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (socket && 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci socket->ListenWithAddressAndPort(address_, port_, backlog_) == net::OK) { 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return socket.Pass(); 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return scoped_ptr<net::ServerSocket>(); 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() { 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Stop() must be called prior to destruction. 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(server_.get() == NULL); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_.get() == NULL); 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) STLDeleteValues(&target_map_); 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::Start() { 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (thread_) 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thread_.reset(new base::Thread(kDevToolsHandlerThreadName)); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::FILE, FROM_HERE, 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DevToolsHttpHandlerImpl::StartHandlerThread, this)); 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Runs on FILE thread. 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::StartHandlerThread() { 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Thread::Options options; 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) options.message_loop_type = base::MessageLoop::TYPE_IO; 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!thread_->StartWithOptions(options)) { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::UI, FROM_HERE, 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThread, this)); 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thread_->message_loop()->PostTask( 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DevToolsHttpHandlerImpl::Init, this)); 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::ResetHandlerThread() { 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thread_.reset(); 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease() { 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ResetHandlerThread(); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Release(); 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::Stop() { 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!thread_) 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTaskAndReply( 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::FILE, FROM_HERE, 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DevToolsHttpHandlerImpl::StopHandlerThread, this), 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease, this)); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid DevToolsHttpHandlerImpl::StopWithoutRelease() { 2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!thread_) 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserThread::PostTaskAndReply( 2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserThread::FILE, FROM_HERE, 2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&DevToolsHttpHandlerImpl::StopHandlerThread, this), 2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThread, this)); 2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)GURL DevToolsHttpHandlerImpl::GetFrontendURL() { 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::IPEndPoint ip_address; 2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (server_ && server_->GetLocalAddress(&ip_address)) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GURL(); 268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return GURL(std::string("http://") + ip_address.ToString() + frontend_url_); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static std::string PathWithoutParams(const std::string& path) { 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t query_position = path.find("?"); 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (query_position != std::string::npos) 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return path.substr(0, query_position); 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return path; 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static std::string GetMimeType(const std::string& filename) { 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (EndsWith(filename, ".html", false)) { 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "text/html"; 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (EndsWith(filename, ".css", false)) { 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "text/css"; 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (EndsWith(filename, ".js", false)) { 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "application/javascript"; 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (EndsWith(filename, ".png", false)) { 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "image/png"; 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (EndsWith(filename, ".gif", false)) { 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "image/gif"; 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (EndsWith(filename, ".json", false)) { 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return "application/json"; 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LOG(ERROR) << "GetMimeType doesn't know mime type for: " 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << filename 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << " text/plain will be returned"; 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "text/plain"; 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::OnHttpRequest( 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int connection_id, 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const net::HttpServerRequestInfo& info) { 3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools); 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (info.path.find("/json") == 0) { 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::UI, 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DevToolsHttpHandlerImpl::OnJsonRequestUI, 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_id, 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info)); 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (info.path.find(kThumbUrlPrefix) == 0) { 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Thumbnail request. 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string target_id = info.path.substr(strlen(kThumbUrlPrefix)); 3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DevToolsTarget* target = GetTarget(target_id); 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL page_url; 3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (target) 321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) page_url = target->GetURL(); 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::UI, 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DevToolsHttpHandlerImpl::OnThumbnailRequestUI, 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_id, 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_url)); 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (info.path == "" || info.path == "/") { 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Discovery page request. 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::UI, 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI, 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_id)); 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (info.path.find("/devtools/") != 0) { 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) server_->Send404(connection_id); 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string filename = PathWithoutParams(info.path.substr(10)); 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string mime_type = GetMimeType(filename); 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath frontend_dir = delegate_->GetDebugFrontendDir(); 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!frontend_dir.empty()) { 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = frontend_dir.AppendASCII(filename); 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string data; 35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::ReadFileToString(path, &data); 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) server_->Send200(connection_id, data, mime_type); 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delegate_->BundlesFrontendResources()) { 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int resource_id = DevToolsHttpHandler::GetFrontendResourceId(filename); 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (resource_id != -1) { 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StringPiece data = GetContentClient()->GetDataResource( 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resource_id, ui::SCALE_FACTOR_NONE); 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) server_->Send200(connection_id, data.as_string(), mime_type); 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) server_->Send404(connection_id); 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::OnWebSocketRequest( 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int connection_id, 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const net::HttpServerRequestInfo& request) { 3747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string browser_prefix = "/devtools/browser"; 3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t browser_pos = request.path.find(browser_prefix); 3767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (browser_pos == 0) { 377116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<DevToolsBrowserTarget> browser_target = 378116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new DevToolsBrowserTarget(server_.get(), connection_id); 379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_target->RegisterDomainHandler( 3802385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch devtools::Tracing::kName, 381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) new DevToolsTracingHandler(DevToolsTracingHandler::Browser), 3822385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch true /* handle on UI thread */); 383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_target->RegisterDomainHandler( 3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci devtools::Tethering::kName, 3852385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch new TetheringHandler(delegate_.get()), 3862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch false /* handle on this thread */); 387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_target->RegisterDomainHandler( 3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) devtools::SystemInfo::kName, 3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) new DevToolsSystemInfoHandler(), 3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) true /* handle on UI thread */); 391116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_targets_[connection_id] = browser_target; 3927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools); 3947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch server_->AcceptWebSocket(connection_id, request); 3957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 3977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::UI, 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind( 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &DevToolsHttpHandlerImpl::OnWebSocketRequestUI, 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_id, 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request)); 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::OnWebSocketMessage( 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int connection_id, 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& data) { 411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BrowserTargets::iterator it = browser_targets_.find(connection_id); 412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (it != browser_targets_.end()) { 413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it->second->HandleMessage(data); 4147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 4157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::UI, 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind( 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &DevToolsHttpHandlerImpl::OnWebSocketMessageUI, 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_id, 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data)); 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::OnClose(int connection_id) { 428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BrowserTargets::iterator it = browser_targets_.find(connection_id); 429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (it != browser_targets_.end()) { 430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it->second->Detach(); 431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_targets_.erase(it); 4327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 4337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::UI, 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind( 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &DevToolsHttpHandlerImpl::OnCloseUI, 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_id)); 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal( 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string id, 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& host) { 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::StringPrintf( 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "%s%sws=%s%s%s", 449a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) frontend_url_.c_str(), 450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) frontend_url_.find("?") == std::string::npos ? "?" : "&", 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host.c_str(), 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kPageUrlPrefix, 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) id.c_str()); 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static bool ParseJsonPath( 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& path, 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string* command, 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string* target_id) { 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Fall back to list in case of empty query. 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (path.empty()) { 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *command = "list"; 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (path.find("/") != 0) { 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Malformed command. 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *command = path.substr(1); 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t separator_pos = command->find("/"); 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (separator_pos != std::string::npos) { 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *target_id = command->substr(separator_pos + 1); 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *command = command->substr(0, separator_pos); 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::OnJsonRequestUI( 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int connection_id, 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const net::HttpServerRequestInfo& info) { 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Trim /json 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string path = info.path.substr(5); 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Trim fragment and query 4881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string query; 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t query_pos = path.find("?"); 4901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (query_pos != std::string::npos) { 4911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) query = path.substr(query_pos + 1); 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path = path.substr(0, query_pos); 4931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t fragment_pos = path.find("#"); 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (fragment_pos != std::string::npos) 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path = path.substr(0, fragment_pos); 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string command; 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string target_id; 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ParseJsonPath(path, &command, &target_id)) { 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendJson(connection_id, 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::HTTP_NOT_FOUND, 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL, 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Malformed query: " + info.path); 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (command == "version") { 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue version; 5110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version.SetString("Protocol-Version", devtools::kProtocolVersion); 512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) version.SetString("WebKit-Version", GetWebKitVersion()); 513a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) version.SetString("Browser", GetContentClient()->GetProduct()); 514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) version.SetString("User-Agent", GetContentClient()->GetUserAgent()); 515f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_ANDROID) 516f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) version.SetString("Android-Package", 517f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::android::BuildInfo::GetInstance()->package_name()); 518f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif 519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SendJson(connection_id, net::HTTP_OK, &version, std::string()); 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (command == "list") { 524a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) std::string host = info.headers["host"]; 5254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AddRef(); // Balanced in OnTargetListReceived. 5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManagerDelegate* manager_delegate = 5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManager::GetInstance()->delegate(); 5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (manager_delegate) { 5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manager_delegate->EnumerateTargets( 5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&DevToolsHttpHandlerImpl::OnTargetListReceived, 5311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this, connection_id, host)); 5321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 5331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManagerDelegate::TargetList empty_list; 5341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnTargetListReceived(connection_id, host, empty_list); 5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (command == "new") { 5401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) GURL url(net::UnescapeURLComponent( 5411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) query, net::UnescapeRule::URL_SPECIAL_CHARS)); 5421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!url.is_valid()) 543f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) url = GURL(url::kAboutBlankURL); 5441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<DevToolsTarget> target; 5451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManagerDelegate* manager_delegate = 5461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManager::GetInstance()->delegate(); 5471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (manager_delegate) 5481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci target = manager_delegate->CreateNewTarget(url); 5494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!target) { 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendJson(connection_id, 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::HTTP_INTERNAL_SERVER_ERROR, 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL, 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Could not create new page"); 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 556a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) std::string host = info.headers["host"]; 5574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<base::DictionaryValue> dictionary( 5584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SerializeTarget(*target.get(), host)); 559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SendJson(connection_id, net::HTTP_OK, dictionary.get(), std::string()); 5604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string target_id = target->GetId(); 5614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) target_map_[target_id] = target.release(); 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (command == "activate" || command == "close") { 5664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DevToolsTarget* target = GetTarget(target_id); 5674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!target) { 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendJson(connection_id, 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::HTTP_NOT_FOUND, 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL, 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "No such target id: " + target_id); 5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (command == "activate") { 5764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (target->Activate()) { 5774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SendJson(connection_id, net::HTTP_OK, NULL, "Target activated"); 5784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 5794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SendJson(connection_id, 5804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) net::HTTP_INTERNAL_SERVER_ERROR, 5814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NULL, 5824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "Could not activate target id: " + target_id); 5834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (command == "close") { 5884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (target->Close()) { 5894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SendJson(connection_id, net::HTTP_OK, NULL, "Target is closing"); 5904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 5914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SendJson(connection_id, 5924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) net::HTTP_INTERNAL_SERVER_ERROR, 5934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NULL, 5944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "Could not close target id: " + target_id); 5954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendJson(connection_id, 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::HTTP_NOT_FOUND, 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL, 6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Unknown command: " + command); 6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DevToolsHttpHandlerImpl::OnTargetListReceived( 6074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int connection_id, 6084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& host, 6091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const DevToolsManagerDelegate::TargetList& targets) { 6101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManagerDelegate::TargetList sorted_targets = targets; 6114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::sort(sorted_targets.begin(), sorted_targets.end(), TimeComparator); 6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) STLDeleteValues(&target_map_); 6144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ListValue list_value; 6151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (DevToolsManagerDelegate::TargetList::const_iterator it = 6164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sorted_targets.begin(); it != sorted_targets.end(); ++it) { 6174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DevToolsTarget* target = *it; 6184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) target_map_[target->GetId()] = target; 6194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) list_value.Append(SerializeTarget(*target, host)); 6204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 6214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SendJson(connection_id, net::HTTP_OK, &list_value, std::string()); 6224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Release(); // Balanced in OnJsonRequestUI. 6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DevToolsTarget* DevToolsHttpHandlerImpl::GetTarget(const std::string& id) { 6264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) TargetMap::const_iterator it = target_map_.find(id); 6274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (it == target_map_.end()) 6284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return NULL; 6294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return it->second; 6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::OnThumbnailRequestUI( 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int connection_id, const GURL& page_url) { 6341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManagerDelegate* manager_delegate = 6351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManager::GetInstance()->delegate(); 6361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string data = 6371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manager_delegate ? manager_delegate->GetPageThumbnailData(page_url) : ""; 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!data.empty()) 6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Send200(connection_id, data, "image/png"); 6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Send404(connection_id); 6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::OnDiscoveryPageRequestUI(int connection_id) { 6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string response = delegate_->GetDiscoveryPageHTML(); 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Send200(connection_id, response, "text/html; charset=UTF-8"); 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::OnWebSocketRequestUI( 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int connection_id, 6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const net::HttpServerRequestInfo& request) { 652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!thread_) 6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t pos = request.path.find(kPageUrlPrefix); 6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pos != 0) { 6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Send404(connection_id); 6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string page_id = request.path.substr(strlen(kPageUrlPrefix)); 6624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DevToolsTarget* target = GetTarget(page_id); 6634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_refptr<DevToolsAgentHost> agent = 6644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) target ? target->GetAgentHost() : NULL; 6651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!agent.get()) { 6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Send500(connection_id, "No such target id: " + page_id); 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (agent->IsAttached()) { 6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Send500(connection_id, 6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Target with given id is being inspected: " + page_id); 6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsAgentHostClientImpl* client_host = new DevToolsAgentHostClientImpl( 6771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci thread_->message_loop(), server_.get(), connection_id, agent.get()); 67803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) connection_to_client_ui_[connection_id] = client_host; 6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AcceptWebSocket(connection_id, request); 6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::OnWebSocketMessageUI( 6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int connection_id, 6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& data) { 68603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ConnectionToClientMap::iterator it = 68703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) connection_to_client_ui_.find(connection_id); 68803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (it == connection_to_client_ui_.end()) 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 69103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DevToolsAgentHostClientImpl* client = 69203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static_cast<DevToolsAgentHostClientImpl*>(it->second); 69303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client->OnMessage(data); 6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::OnCloseUI(int connection_id) { 69703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ConnectionToClientMap::iterator it = 69803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) connection_to_client_ui_.find(connection_id); 69903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (it != connection_to_client_ui_.end()) { 70003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DevToolsAgentHostClientImpl* client = 70103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static_cast<DevToolsAgentHostClientImpl*>(it->second); 70203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) delete client; 70303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) connection_to_client_ui_.erase(connection_id); 7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl( 7081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<ServerSocketFactory> server_socket_factory, 7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& frontend_url, 71046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DevToolsHttpHandlerDelegate* delegate, 71146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const base::FilePath& active_port_output_directory) 712a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : frontend_url_(frontend_url), 7131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci server_socket_factory_(server_socket_factory.Pass()), 71446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) delegate_(delegate), 71546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) active_port_output_directory_(active_port_output_directory) { 716a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (frontend_url_.empty()) 7171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci frontend_url_ = "/devtools/devtools.html"; 7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Balanced in ResetHandlerThreadAndRelease(). 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddRef(); 7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Runs on the handler thread 7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::Init() { 7251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<net::ServerSocket> server_socket = 7261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci server_socket_factory_->CreateAndListen(); 7271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!server_socket) { 7281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LOG(ERROR) << "Cannot start http server for devtools. Stop devtools."; 7291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserThread::PostTask( 7301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserThread::UI, FROM_HERE, 7311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&DevToolsHttpHandlerImpl::StopWithoutRelease, this)); 7321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 7331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 7341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci server_.reset(new net::HttpServer(server_socket.Pass(), this)); 73646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!active_port_output_directory_.empty()) 73746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WriteActivePortToUserProfile(); 7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Runs on the handler thread 7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::Teardown() { 7421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci server_.reset(NULL); 7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Runs on FILE thread to make sure that it is serialized against 7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// {Start|Stop}HandlerThread and to allow calling pthread_join. 7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::StopHandlerThread() { 7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!thread_->message_loop()) 7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thread_->message_loop()->PostTask( 7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DevToolsHttpHandlerImpl::Teardown, this)); 7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Thread::Stop joins the thread. 7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thread_->Stop(); 7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void DevToolsHttpHandlerImpl::WriteActivePortToUserProfile() { 75846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(!active_port_output_directory_.empty()); 75946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) net::IPEndPoint endpoint; 76046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int err; 76146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if ((err = server_->GetLocalAddress(&endpoint)) != net::OK) { 76246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) LOG(ERROR) << "Error " << err << " getting local address"; 76346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 76446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 76546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 76646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Write this port to a well-known file in the profile directory 76746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // so Telemetry can pick it up. 76846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::FilePath path = active_port_output_directory_.Append( 76946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) kDevToolsActivePortFileName); 770f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string port_string = base::IntToString(endpoint.port()); 771f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (base::WriteFile(path, port_string.c_str(), port_string.length()) < 0) { 77246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) LOG(ERROR) << "Error writing DevTools active port to file"; 77346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 77446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 77546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::SendJson(int connection_id, 7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::HttpStatusCode status_code, 7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Value* value, 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& message) { 780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!thread_) 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Serialize value and message. 7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string json_value; 7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (value) { 7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::JSONWriter::WriteWithOptions(value, 7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::JSONWriter::OPTIONS_PRETTY_PRINT, 7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &json_value); 7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string json_message; 7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> message_object(new base::StringValue(message)); 7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::JSONWriter::Write(message_object.get(), &json_message); 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 794a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch net::HttpServerResponseInfo response(status_code); 795a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch response.SetBody(json_value + message, "application/json; charset=UTF-8"); 7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thread_->message_loop()->PostTask( 7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 799a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch base::Bind(&net::HttpServer::SendResponse, 8001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(server_.get()), 8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_id, 802a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch response)); 8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::Send200(int connection_id, 8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& data, 8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& mime_type) { 808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!thread_) 8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thread_->message_loop()->PostTask( 8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&net::HttpServer::Send200, 8131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(server_.get()), 8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_id, 8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data, 8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mime_type)); 8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::Send404(int connection_id) { 820c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!thread_) 8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thread_->message_loop()->PostTask( 8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 8241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&net::HttpServer::Send404, 8251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(server_.get()), 8261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci connection_id)); 8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::Send500(int connection_id, 8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& message) { 831c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!thread_) 8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thread_->message_loop()->PostTask( 8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 8351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&net::HttpServer::Send500, 8361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(server_.get()), 8371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci connection_id, 8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message)); 8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsHttpHandlerImpl::AcceptWebSocket( 8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int connection_id, 8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const net::HttpServerRequestInfo& request) { 844c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!thread_) 8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thread_->message_loop()->PostTask( 8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 8481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&net::HttpServer::SetSendBufferSize, 8491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(server_.get()), 8501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci connection_id, 8511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kSendBufferSizeForDevTools)); 8521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci thread_->message_loop()->PostTask( 8531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 8541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&net::HttpServer::AcceptWebSocket, 8551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(server_.get()), 8561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci connection_id, 8571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci request)); 8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget( 8614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const DevToolsTarget& target, 8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& host) { 8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dictionary = new base::DictionaryValue; 8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string id = target.GetId(); 8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dictionary->SetString(kTargetIdField, id); 86746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::string parent_id = target.GetParentId(); 86846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!parent_id.empty()) 86946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) dictionary->SetString(kTargetParentIdField, parent_id); 8704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) dictionary->SetString(kTargetTypeField, target.GetType()); 8711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) dictionary->SetString(kTargetTitleField, 8721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) net::EscapeForHTML(target.GetTitle())); 8734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) dictionary->SetString(kTargetDescriptionField, target.GetDescription()); 8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 875010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) GURL url = target.GetURL(); 8764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) dictionary->SetString(kTargetUrlField, url.spec()); 8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 878010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) GURL favicon_url = target.GetFaviconURL(); 8794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (favicon_url.is_valid()) 8804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) dictionary->SetString(kTargetFaviconUrlField, favicon_url.spec()); 8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManagerDelegate* manager_delegate = 8831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DevToolsManager::GetInstance()->delegate(); 8841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (manager_delegate && 8851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !manager_delegate->GetPageThumbnailData(url).empty()) { 8864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) dictionary->SetString(kTargetThumbnailUrlField, 8874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string(kThumbUrlPrefix) + id); 8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!target.IsAttached()) { 8914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) dictionary->SetString(kTargetWebSocketDebuggerUrlField, 8924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::StringPrintf("ws://%s%s%s", 8934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) host.c_str(), 8944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kPageUrlPrefix, 8954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) id.c_str())); 8964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string devtools_frontend_url = GetFrontendURLInternal( 8974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) id.c_str(), 8984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) host); 8994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) dictionary->SetString( 9004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kTargetDevtoolsFrontendUrlField, devtools_frontend_url); 9014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return dictionary; 9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace content 907