blob: b5ce81e870db95fe6308354d0b2dba7922acd178 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "android_webview/native/aw_dev_tools_server.h"
#include "android_webview/native/aw_contents.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/json/json_writer.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/public/browser/android/devtools_auth.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/devtools_http_handler_delegate.h"
#include "content/public/browser/devtools_target.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/user_agent.h"
#include "jni/AwDevToolsServer_jni.h"
#include "net/base/net_errors.h"
#include "net/socket/unix_domain_server_socket_posix.h"
using content::DevToolsAgentHost;
using content::RenderViewHost;
using content::WebContents;
namespace {
const char kFrontEndURL[] =
"http://chrome-devtools-frontend.appspot.com/serve_rev/%s/devtools.html";
const char kSocketNameFormat[] = "webview_devtools_remote_%d";
const char kTetheringSocketName[] = "webview_devtools_tethering_%d_%d";
const int kBackLog = 10;
// Delegate implementation for the devtools http handler for WebView. A new
// instance of this gets created each time web debugging is enabled.
class AwDevToolsServerDelegate : public content::DevToolsHttpHandlerDelegate {
public:
AwDevToolsServerDelegate() : last_tethering_socket_(0) {
}
virtual ~AwDevToolsServerDelegate() {}
// DevToolsHttpProtocolHandler::Delegate overrides.
std::string GetDiscoveryPageHTML() override;
bool BundlesFrontendResources() override {
return false;
}
base::FilePath GetDebugFrontendDir() override {
return base::FilePath();
}
scoped_ptr<net::ServerSocket>
CreateSocketForTethering(std::string* name) override {
*name = base::StringPrintf(
kTetheringSocketName, getpid(), ++last_tethering_socket_);
scoped_ptr<net::UnixDomainServerSocket> socket(
new net::UnixDomainServerSocket(
base::Bind(&content::CanUserConnectToDevTools), true));
if (socket->ListenWithAddressAndPort(*name, 0, kBackLog) != net::OK)
return scoped_ptr<net::ServerSocket>();
return socket.Pass();
}
private:
int last_tethering_socket_;
DISALLOW_COPY_AND_ASSIGN(AwDevToolsServerDelegate);
};
std::string AwDevToolsServerDelegate::GetDiscoveryPageHTML() {
const char html[] =
"<html>"
"<head><title>WebView remote debugging</title></head>"
"<body>Please use <a href=\'chrome://inspect\'>chrome://inspect</a>"
"</body>"
"</html>";
return html;
}
// Factory for UnixDomainServerSocket.
class UnixDomainServerSocketFactory
: public content::DevToolsHttpHandler::ServerSocketFactory {
public:
explicit UnixDomainServerSocketFactory(const std::string& socket_name)
: content::DevToolsHttpHandler::ServerSocketFactory(socket_name, 0, 1) {}
private:
// content::DevToolsHttpHandler::ServerSocketFactory.
virtual scoped_ptr<net::ServerSocket> Create() const override {
return scoped_ptr<net::ServerSocket>(
new net::UnixDomainServerSocket(
base::Bind(&content::CanUserConnectToDevTools),
true /* use_abstract_namespace */));
}
DISALLOW_COPY_AND_ASSIGN(UnixDomainServerSocketFactory);
};
} // namespace
namespace android_webview {
AwDevToolsServer::AwDevToolsServer()
: protocol_handler_(NULL) {
}
AwDevToolsServer::~AwDevToolsServer() {
Stop();
}
void AwDevToolsServer::Start() {
if (protocol_handler_)
return;
scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory> factory(
new UnixDomainServerSocketFactory(
base::StringPrintf(kSocketNameFormat, getpid())));
protocol_handler_ = content::DevToolsHttpHandler::Start(
factory.Pass(),
base::StringPrintf(kFrontEndURL, content::GetWebKitRevision().c_str()),
new AwDevToolsServerDelegate(),
base::FilePath());
}
void AwDevToolsServer::Stop() {
if (!protocol_handler_)
return;
// Note that the call to Stop() below takes care of |protocol_handler_|
// deletion.
protocol_handler_->Stop();
protocol_handler_ = NULL;
}
bool AwDevToolsServer::IsStarted() const {
return protocol_handler_;
}
bool RegisterAwDevToolsServer(JNIEnv* env) {
return RegisterNativesImpl(env);
}
static jlong InitRemoteDebugging(JNIEnv* env,
jobject obj) {
AwDevToolsServer* server = new AwDevToolsServer();
return reinterpret_cast<intptr_t>(server);
}
static void DestroyRemoteDebugging(JNIEnv* env, jobject obj, jlong server) {
delete reinterpret_cast<AwDevToolsServer*>(server);
}
static void SetRemoteDebuggingEnabled(JNIEnv* env,
jobject obj,
jlong server,
jboolean enabled) {
AwDevToolsServer* devtools_server =
reinterpret_cast<AwDevToolsServer*>(server);
if (enabled) {
devtools_server->Start();
} else {
devtools_server->Stop();
}
}
} // namespace android_webview