1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Copyright 2013 The Chromium Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
6 #include "xwalk/runtime/browser/android/xwalk_dev_tools_server.h"
12 #include "base/android/jni_string.h"
13 #include "base/basictypes.h"
14 #include "base/bind.h"
15 #include "base/callback.h"
16 #include "base/compiler_specific.h"
17 #include "base/logging.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "content/public/browser/android/devtools_auth.h"
21 #include "content/public/browser/devtools_agent_host.h"
22 #include "content/public/browser/devtools_http_handler.h"
23 #include "content/public/browser/devtools_http_handler_delegate.h"
24 #include "content/public/browser/devtools_target.h"
25 #include "content/public/browser/favicon_status.h"
26 #include "content/public/browser/navigation_entry.h"
27 #include "content/public/browser/render_view_host.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/common/user_agent.h"
30 #include "grit/xwalk_resources.h"
31 #include "jni/XWalkDevToolsServer_jni.h"
32 #include "net/socket/unix_domain_socket_posix.h"
33 #include "ui/base/resource/resource_bundle.h"
35 using content::DevToolsAgentHost;
36 using content::RenderViewHost;
37 using content::WebContents;
41 // FIXME(girish): The frontend URL needs to be served from the domain below
42 // for remote debugging to work in chrome (see chrome's devtools_ui.cc).
43 // Currently, the chrome version is hardcoded because of this dependancy.
44 const char kFrontEndURL[] =
45 "http://chrome-devtools-frontend.appspot.com/serve_rev/%s/devtools.html";
46 const char kTargetTypePage[] = "page";
48 class Target : public content::DevToolsTarget {
50 explicit Target(WebContents* web_contents);
52 virtual std::string GetId() const OVERRIDE { return id_; }
53 virtual std::string GetType() const OVERRIDE { return kTargetTypePage; }
54 virtual std::string GetTitle() const OVERRIDE { return title_; }
55 // TODO(hmin): Get the description about web contents view.
56 virtual std::string GetDescription() const OVERRIDE { return std::string(); }
57 virtual GURL GetURL() const OVERRIDE { return url_; }
58 virtual GURL GetFaviconURL() const OVERRIDE { return GURL(); }
59 virtual base::TimeTicks GetLastActivityTime() const OVERRIDE {
60 return last_activity_time_;
62 virtual std::string GetParentId() const OVERRIDE { return std::string(); }
63 virtual bool IsAttached() const OVERRIDE {
64 return agent_host_->IsAttached();
66 virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const OVERRIDE {
69 virtual bool Activate() const OVERRIDE { return false; }
70 virtual bool Close() const OVERRIDE { return false; }
73 scoped_refptr<DevToolsAgentHost> agent_host_;
77 base::TimeTicks last_activity_time_;
80 Target::Target(WebContents* web_contents) {
82 DevToolsAgentHost::GetOrCreateFor(web_contents->GetRenderViewHost());
83 id_ = agent_host_->GetId();
84 title_ = UTF16ToUTF8(web_contents->GetTitle());
85 url_ = web_contents->GetURL();
86 last_activity_time_ = web_contents->GetLastActiveTime();
89 // Delegate implementation for the devtools http handler on android. A new
90 // instance of this gets created each time devtools is enabled.
91 class XWalkDevToolsServerDelegate
92 : public content::DevToolsHttpHandlerDelegate {
94 explicit XWalkDevToolsServerDelegate() {
97 virtual std::string GetDiscoveryPageHTML() OVERRIDE {
98 return ResourceBundle::GetSharedInstance().GetRawDataResource(
99 IDR_DEVTOOLS_FRONTEND_PAGE_HTML).as_string();
102 virtual bool BundlesFrontendResources() OVERRIDE {
106 virtual base::FilePath GetDebugFrontendDir() OVERRIDE {
107 return base::FilePath();
110 virtual std::string GetPageThumbnailData(const GURL& url) OVERRIDE {
111 return std::string();
114 virtual scoped_ptr<content::DevToolsTarget> CreateNewTarget(
115 const GURL&) OVERRIDE {
116 return scoped_ptr<content::DevToolsTarget>();
119 virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(
120 net::StreamListenSocket::Delegate* delegate,
121 std::string* name) OVERRIDE {
122 return scoped_ptr<net::StreamListenSocket>();
125 virtual void EnumerateTargets(TargetCallback callback) OVERRIDE {
127 std::vector<RenderViewHost*> rvh_list =
128 DevToolsAgentHost::GetValidRenderViewHosts();
129 for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin();
130 it != rvh_list.end(); ++it) {
131 WebContents* web_contents = WebContents::FromRenderViewHost(*it);
133 targets.push_back(new Target(web_contents));
135 callback.Run(targets);
139 DISALLOW_COPY_AND_ASSIGN(XWalkDevToolsServerDelegate);
146 XWalkDevToolsServer::XWalkDevToolsServer(const std::string& socket_name)
147 : socket_name_(socket_name),
148 protocol_handler_(NULL),
152 XWalkDevToolsServer::~XWalkDevToolsServer() {
156 // Allow connection from uid specified using AllowConnectionFromUid to devtools
157 // server. This supports the XDK usage: debug bridge wrapper runs in a separate
158 // process and connects to the devtools server.
159 bool XWalkDevToolsServer::CanUserConnectToDevTools(uid_t uid, gid_t gid) {
160 if (uid == allowed_uid_)
163 return content::CanUserConnectToDevTools(uid, gid);
166 void XWalkDevToolsServer::Start() {
167 if (protocol_handler_)
170 protocol_handler_ = content::DevToolsHttpHandler::Start(
171 new net::UnixDomainSocketWithAbstractNamespaceFactory(
173 "", // fallback socket name
174 base::Bind(&XWalkDevToolsServer::CanUserConnectToDevTools,
175 base::Unretained(this))),
176 base::StringPrintf(kFrontEndURL, content::GetWebKitRevision().c_str()),
177 new XWalkDevToolsServerDelegate(), base::FilePath());
180 void XWalkDevToolsServer::Stop() {
181 if (!protocol_handler_)
183 // Note that the call to Stop() below takes care of |protocol_handler_|
185 protocol_handler_->Stop();
186 protocol_handler_ = NULL;
189 bool XWalkDevToolsServer::IsStarted() const {
190 return protocol_handler_;
193 void XWalkDevToolsServer::AllowConnectionFromUid(uid_t uid) {
197 bool RegisterXWalkDevToolsServer(JNIEnv* env) {
198 return RegisterNativesImpl(env);
201 static jlong InitRemoteDebugging(JNIEnv* env,
203 jstring socketName) {
204 XWalkDevToolsServer* server = new XWalkDevToolsServer(
205 base::android::ConvertJavaStringToUTF8(env, socketName));
206 return reinterpret_cast<intptr_t>(server);
209 static void DestroyRemoteDebugging(JNIEnv* env, jobject obj, jlong server) {
210 delete reinterpret_cast<XWalkDevToolsServer*>(server);
213 static jboolean IsRemoteDebuggingEnabled(JNIEnv* env,
216 return reinterpret_cast<XWalkDevToolsServer*>(server)->IsStarted();
219 static void SetRemoteDebuggingEnabled(JNIEnv* env,
223 XWalkDevToolsServer* devtools_server =
224 reinterpret_cast<XWalkDevToolsServer*>(server);
226 devtools_server->Start();
228 devtools_server->Stop();
232 static void AllowConnectionFromUid(JNIEnv* env,
236 XWalkDevToolsServer* devtools_server =
237 reinterpret_cast<XWalkDevToolsServer*>(server);
238 devtools_server->AllowConnectionFromUid((uid_t) uid);