aw_dev_tools_server.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// found in the LICENSE file.
468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "android_webview/native/aw_dev_tools_server.h"
668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "android_webview/browser/in_process_view_renderer.h"
868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/bind.h"
968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/json/json_writer.h"
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/strings/stringprintf.h"
1168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/values.h"
1268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/public/browser/android/devtools_auth.h"
1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/public/browser/devtools_http_handler.h"
1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/public/browser/devtools_http_handler_delegate.h"
1568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/public/browser/web_contents.h"
1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "jni/AwDevToolsServer_jni.h"
1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "net/socket/unix_domain_socket_posix.h"
1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "webkit/common/user_agent/user_agent_util.h"
1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace {
2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kFrontEndURL[] =
2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "http://chrome-devtools-frontend.appspot.com/serve_rev/%s/devtools.html";
2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kSocketNameFormat[] = "webview_devtools_remote_%d";
2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Delegate implementation for the devtools http handler for WebView. A new
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// instance of this gets created each time web debugging is enabled.
2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class AwDevToolsServerDelegate : public content::DevToolsHttpHandlerDelegate {
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public:
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  AwDevToolsServerDelegate() {}
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual ~AwDevToolsServerDelegate() {}
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // DevToolsHttpProtocolHandler::Delegate overrides.
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual std::string GetDiscoveryPageHTML() OVERRIDE;
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual bool BundlesFrontendResources() OVERRIDE {
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual base::FilePath GetDebugFrontendDir() OVERRIDE {
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return base::FilePath();
4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual std::string GetPageThumbnailData(const GURL&) OVERRIDE {
4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return "";
4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual content::RenderViewHost* CreateNewTarget() OVERRIDE {
4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return NULL;
5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual TargetType GetTargetType(content::RenderViewHost*) OVERRIDE {
5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return kTargetTypeTab;
5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual std::string GetViewDescription(content::RenderViewHost*) OVERRIDE;
5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(
5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      net::StreamListenSocket::Delegate* delegate,
6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      std::string* name) OVERRIDE {
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return scoped_ptr<net::StreamListenSocket>();
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) private:
6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AwDevToolsServerDelegate);
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string AwDevToolsServerDelegate::GetDiscoveryPageHTML() {
7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const char html[] =
7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      "<html>"
7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      "<head><title>WebView remote debugging</title></head>"
7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      "<body>Please use <a href=\'chrome://inspect\'>chrome://inspect</a>"
7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      "</body>"
7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      "</html>";
7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return html;
7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string AwDevToolsServerDelegate::GetViewDescription(
8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    content::RenderViewHost* rvh) {
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  content::WebContents* web_contents =
8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      content::WebContents::FromRenderViewHost(rvh);
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!web_contents) return "";
8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  android_webview::BrowserViewRenderer* bvr
8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      = android_webview::InProcessViewRenderer::FromWebContents(web_contents);
8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!bvr) return "";
8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base::DictionaryValue description;
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  description.SetBoolean("attached", bvr->IsAttachedToWindow());
9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  description.SetBoolean("visible", bvr->IsVisible());
9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::Rect screen_rect = bvr->GetScreenRect();
9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  description.SetInteger("screenX", screen_rect.x());
9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  description.SetInteger("screenY", screen_rect.y());
9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  description.SetBoolean("empty", screen_rect.size().IsEmpty());
9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!screen_rect.size().IsEmpty()) {
9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    description.SetInteger("width", screen_rect.width());
9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    description.SetInteger("height", screen_rect.height());
9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::string json;
10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base::JSONWriter::Write(&description, &json);
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return json;
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace android_webview {
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)AwDevToolsServer::AwDevToolsServer()
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : protocol_handler_(NULL) {
11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)AwDevToolsServer::~AwDevToolsServer() {
11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Stop();
11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void AwDevToolsServer::Start() {
11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (protocol_handler_)
11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  protocol_handler_ = content::DevToolsHttpHandler::Start(
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      new net::UnixDomainSocketWithAbstractNamespaceFactory(
12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          base::StringPrintf(kSocketNameFormat, getpid()),
12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          "",
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          base::Bind(&content::CanUserConnectToDevTools)),
12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      base::StringPrintf(kFrontEndURL,
12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                         webkit_glue::GetWebKitRevision().c_str()),
12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      new AwDevToolsServerDelegate());
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void AwDevToolsServer::Stop() {
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!protocol_handler_)
13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Note that the call to Stop() below takes care of |protocol_handler_|
13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // deletion.
13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  protocol_handler_->Stop();
13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  protocol_handler_ = NULL;
13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool AwDevToolsServer::IsStarted() const {
14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return protocol_handler_;
14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool RegisterAwDevToolsServer(JNIEnv* env) {
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return RegisterNativesImpl(env);
14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)static jint InitRemoteDebugging(JNIEnv* env,
14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                jobject obj) {
14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  AwDevToolsServer* server = new AwDevToolsServer();
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return reinterpret_cast<jint>(server);
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)static void DestroyRemoteDebugging(JNIEnv* env, jobject obj, jint server) {
15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  delete reinterpret_cast<AwDevToolsServer*>(server);
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)static void SetRemoteDebuggingEnabled(JNIEnv* env,
15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                      jobject obj,
15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                      jint server,
16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                      jboolean enabled) {
16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  AwDevToolsServer* devtools_server =
16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      reinterpret_cast<AwDevToolsServer*>(server);
16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (enabled) {
16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    devtools_server->Start();
16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else {
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    devtools_server->Stop();
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace android_webview
171