1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "android_webview/native/aw_dev_tools_server.h" 6 7 #include "android_webview/native/aw_contents.h" 8 #include "base/bind.h" 9 #include "base/files/file_path.h" 10 #include "base/json/json_writer.h" 11 #include "base/strings/stringprintf.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "base/values.h" 14 #include "content/public/browser/android/devtools_auth.h" 15 #include "content/public/browser/devtools_agent_host.h" 16 #include "content/public/browser/devtools_http_handler.h" 17 #include "content/public/browser/devtools_http_handler_delegate.h" 18 #include "content/public/browser/devtools_target.h" 19 #include "content/public/browser/web_contents.h" 20 #include "content/public/common/user_agent.h" 21 #include "jni/AwDevToolsServer_jni.h" 22 #include "net/socket/unix_domain_server_socket_posix.h" 23 24 using content::DevToolsAgentHost; 25 using content::RenderViewHost; 26 using content::WebContents; 27 28 namespace { 29 30 const char kFrontEndURL[] = 31 "http://chrome-devtools-frontend.appspot.com/serve_rev/%s/devtools.html"; 32 const char kSocketNameFormat[] = "webview_devtools_remote_%d"; 33 34 // Delegate implementation for the devtools http handler for WebView. A new 35 // instance of this gets created each time web debugging is enabled. 36 class AwDevToolsServerDelegate : public content::DevToolsHttpHandlerDelegate { 37 public: 38 AwDevToolsServerDelegate() {} 39 virtual ~AwDevToolsServerDelegate() {} 40 41 // DevToolsHttpProtocolHandler::Delegate overrides. 42 virtual std::string GetDiscoveryPageHTML() OVERRIDE; 43 44 virtual bool BundlesFrontendResources() OVERRIDE { 45 return false; 46 } 47 48 virtual base::FilePath GetDebugFrontendDir() OVERRIDE { 49 return base::FilePath(); 50 } 51 52 virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering( 53 net::StreamListenSocket::Delegate* delegate, 54 std::string* name) OVERRIDE { 55 return scoped_ptr<net::StreamListenSocket>(); 56 } 57 58 private: 59 DISALLOW_COPY_AND_ASSIGN(AwDevToolsServerDelegate); 60 }; 61 62 63 std::string AwDevToolsServerDelegate::GetDiscoveryPageHTML() { 64 const char html[] = 65 "<html>" 66 "<head><title>WebView remote debugging</title></head>" 67 "<body>Please use <a href=\'chrome://inspect\'>chrome://inspect</a>" 68 "</body>" 69 "</html>"; 70 return html; 71 } 72 73 // Factory for UnixDomainServerSocket. 74 class UnixDomainServerSocketFactory 75 : public content::DevToolsHttpHandler::ServerSocketFactory { 76 public: 77 explicit UnixDomainServerSocketFactory(const std::string& socket_name) 78 : content::DevToolsHttpHandler::ServerSocketFactory(socket_name, 0, 1) {} 79 80 private: 81 // content::DevToolsHttpHandler::ServerSocketFactory. 82 virtual scoped_ptr<net::ServerSocket> Create() const OVERRIDE { 83 return scoped_ptr<net::ServerSocket>( 84 new net::UnixDomainServerSocket( 85 base::Bind(&content::CanUserConnectToDevTools), 86 true /* use_abstract_namespace */)); 87 } 88 89 DISALLOW_COPY_AND_ASSIGN(UnixDomainServerSocketFactory); 90 }; 91 92 } // namespace 93 94 namespace android_webview { 95 96 AwDevToolsServer::AwDevToolsServer() 97 : protocol_handler_(NULL) { 98 } 99 100 AwDevToolsServer::~AwDevToolsServer() { 101 Stop(); 102 } 103 104 void AwDevToolsServer::Start() { 105 if (protocol_handler_) 106 return; 107 108 scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory> factory( 109 new UnixDomainServerSocketFactory( 110 base::StringPrintf(kSocketNameFormat, getpid()))); 111 protocol_handler_ = content::DevToolsHttpHandler::Start( 112 factory.Pass(), 113 base::StringPrintf(kFrontEndURL, content::GetWebKitRevision().c_str()), 114 new AwDevToolsServerDelegate(), 115 base::FilePath()); 116 } 117 118 void AwDevToolsServer::Stop() { 119 if (!protocol_handler_) 120 return; 121 // Note that the call to Stop() below takes care of |protocol_handler_| 122 // deletion. 123 protocol_handler_->Stop(); 124 protocol_handler_ = NULL; 125 } 126 127 bool AwDevToolsServer::IsStarted() const { 128 return protocol_handler_; 129 } 130 131 bool RegisterAwDevToolsServer(JNIEnv* env) { 132 return RegisterNativesImpl(env); 133 } 134 135 static jlong InitRemoteDebugging(JNIEnv* env, 136 jobject obj) { 137 AwDevToolsServer* server = new AwDevToolsServer(); 138 return reinterpret_cast<intptr_t>(server); 139 } 140 141 static void DestroyRemoteDebugging(JNIEnv* env, jobject obj, jlong server) { 142 delete reinterpret_cast<AwDevToolsServer*>(server); 143 } 144 145 static void SetRemoteDebuggingEnabled(JNIEnv* env, 146 jobject obj, 147 jlong server, 148 jboolean enabled) { 149 AwDevToolsServer* devtools_server = 150 reinterpret_cast<AwDevToolsServer*>(server); 151 if (enabled) { 152 devtools_server->Start(); 153 } else { 154 devtools_server->Stop(); 155 } 156 } 157 158 } // namespace android_webview 159