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