c514b1bfedbec5b005fbdaaa8feab43266226cfc
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / browser / android / xwalk_dev_tools_server.cc
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.
5
6 #include "xwalk/runtime/browser/android/xwalk_dev_tools_server.h"
7
8 #include <sys/types.h>
9 #include <unistd.h>
10 #include <vector>
11
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 "grit/xwalk_resources.h"
30 #include "jni/XWalkDevToolsServer_jni.h"
31 #include "net/socket/unix_domain_socket_posix.h"
32 #include "ui/base/resource/resource_bundle.h"
33 #include "webkit/common/user_agent/user_agent_util.h"
34
35 using content::DevToolsAgentHost;
36 using content::RenderViewHost;
37 using content::WebContents;
38
39 namespace {
40
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";
47
48 class Target : public content::DevToolsTarget {
49  public:
50   explicit Target(WebContents* web_contents);
51
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_;
61   }
62   virtual bool IsAttached() const OVERRIDE {
63     return agent_host_->IsAttached();
64   }
65   virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const OVERRIDE {
66     return agent_host_;
67   }
68   virtual bool Activate() const OVERRIDE { return false; }
69   virtual bool Close() const OVERRIDE { return false; }
70
71  private:
72   scoped_refptr<DevToolsAgentHost> agent_host_;
73   std::string id_;
74   std::string title_;
75   GURL url_;
76   base::TimeTicks last_activity_time_;
77 };
78
79 Target::Target(WebContents* web_contents) {
80   agent_host_ =
81       DevToolsAgentHost::GetOrCreateFor(web_contents->GetRenderViewHost());
82   id_ = agent_host_->GetId();
83   title_ = UTF16ToUTF8(web_contents->GetTitle());
84   url_ = web_contents->GetURL();
85   last_activity_time_ = web_contents->GetLastActiveTime();
86 }
87
88 // Delegate implementation for the devtools http handler on android. A new
89 // instance of this gets created each time devtools is enabled.
90 class XWalkDevToolsServerDelegate
91   : public content::DevToolsHttpHandlerDelegate {
92  public:
93   explicit XWalkDevToolsServerDelegate() {
94   }
95
96   virtual std::string GetDiscoveryPageHTML() OVERRIDE {
97     return ResourceBundle::GetSharedInstance().GetRawDataResource(
98         IDR_DEVTOOLS_FRONTEND_PAGE_HTML).as_string();
99   }
100
101   virtual bool BundlesFrontendResources() OVERRIDE {
102     return false;
103   }
104
105   virtual base::FilePath GetDebugFrontendDir() OVERRIDE {
106     return base::FilePath();
107   }
108
109   virtual std::string GetPageThumbnailData(const GURL& url) OVERRIDE {
110     return std::string();
111   }
112
113   virtual scoped_ptr<content::DevToolsTarget> CreateNewTarget(
114       const GURL&) OVERRIDE {
115     return scoped_ptr<content::DevToolsTarget>();
116   }
117
118   virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(
119       net::StreamListenSocket::Delegate* delegate,
120       std::string* name) OVERRIDE {
121     return scoped_ptr<net::StreamListenSocket>();
122   }
123
124   virtual void EnumerateTargets(TargetCallback callback) OVERRIDE {
125     TargetList targets;
126     std::vector<RenderViewHost*> rvh_list =
127         DevToolsAgentHost::GetValidRenderViewHosts();
128     for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin();
129          it != rvh_list.end(); ++it) {
130       WebContents* web_contents = WebContents::FromRenderViewHost(*it);
131       if (web_contents)
132         targets.push_back(new Target(web_contents));
133     }
134     callback.Run(targets);
135   }
136
137  private:
138   DISALLOW_COPY_AND_ASSIGN(XWalkDevToolsServerDelegate);
139 };
140
141 }  // namespace
142
143 namespace xwalk {
144
145 XWalkDevToolsServer::XWalkDevToolsServer(const std::string& socket_name)
146     : socket_name_(socket_name),
147       protocol_handler_(NULL),
148       allowed_uid_(0) {
149 }
150
151 XWalkDevToolsServer::~XWalkDevToolsServer() {
152   Stop();
153 }
154
155 // Allow connection from uid specified using AllowConnectionFromUid to devtools
156 // server. This supports the XDK usage: debug bridge wrapper runs in a separate
157 // process and connects to the devtools server.
158 bool XWalkDevToolsServer::CanUserConnectToDevTools(uid_t uid, gid_t gid) {
159   if (uid == allowed_uid_)
160     return true;
161
162   return content::CanUserConnectToDevTools(uid, gid);
163 }
164
165 void XWalkDevToolsServer::Start() {
166   if (protocol_handler_)
167     return;
168
169   protocol_handler_ = content::DevToolsHttpHandler::Start(
170       new net::UnixDomainSocketWithAbstractNamespaceFactory(
171           socket_name_,
172           "",  // fallback socket name
173           base::Bind(&XWalkDevToolsServer::CanUserConnectToDevTools,
174               base::Unretained(this))),
175       base::StringPrintf(kFrontEndURL,
176                          webkit_glue::GetWebKitRevision().c_str()),
177       new XWalkDevToolsServerDelegate());
178 }
179
180 void XWalkDevToolsServer::Stop() {
181   if (!protocol_handler_)
182     return;
183   // Note that the call to Stop() below takes care of |protocol_handler_|
184   // deletion.
185   protocol_handler_->Stop();
186   protocol_handler_ = NULL;
187 }
188
189 bool XWalkDevToolsServer::IsStarted() const {
190   return protocol_handler_;
191 }
192
193 void XWalkDevToolsServer::AllowConnectionFromUid(uid_t uid) {
194   allowed_uid_ = uid;
195 }
196
197 bool RegisterXWalkDevToolsServer(JNIEnv* env) {
198   return RegisterNativesImpl(env);
199 }
200
201 static jint InitRemoteDebugging(JNIEnv* env,
202                                 jobject obj,
203                                 jstring socketName) {
204   XWalkDevToolsServer* server = new XWalkDevToolsServer(
205       base::android::ConvertJavaStringToUTF8(env, socketName));
206   return reinterpret_cast<jint>(server);
207 }
208
209 static void DestroyRemoteDebugging(JNIEnv* env, jobject obj, jint server) {
210   delete reinterpret_cast<XWalkDevToolsServer*>(server);
211 }
212
213 static jboolean IsRemoteDebuggingEnabled(JNIEnv* env,
214                                          jobject obj,
215                                          jint server) {
216   return reinterpret_cast<XWalkDevToolsServer*>(server)->IsStarted();
217 }
218
219 static void SetRemoteDebuggingEnabled(JNIEnv* env,
220                                       jobject obj,
221                                       jint server,
222                                       jboolean enabled) {
223   XWalkDevToolsServer* devtools_server =
224       reinterpret_cast<XWalkDevToolsServer*>(server);
225   if (enabled) {
226     devtools_server->Start();
227   } else {
228     devtools_server->Stop();
229   }
230 }
231
232 static void AllowConnectionFromUid(JNIEnv* env,
233                                     jobject obj,
234                                     jint server,
235                                     jint uid) {
236   XWalkDevToolsServer* devtools_server =
237       reinterpret_cast<XWalkDevToolsServer*>(server);
238   devtools_server->AllowConnectionFromUid((uid_t) uid);
239 }
240
241 }  // namespace xwalk