blob: 6d5ab981c68a4a8b052e8b0d03b560cc36ef80eb [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/browser/aw_devtools_server.h"
#include <utility>
#include "android_webview/browser_jni_headers/AwDevToolsServer_jni.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/string_number_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_socket_factory.h"
#include "content/public/common/content_switches.h"
#include "net/base/net_errors.h"
#include "net/socket/tcp_server_socket.h"
#include "net/socket/unix_domain_server_socket_posix.h"
using base::android::JavaParamRef;
using content::DevToolsAgentHost;
namespace {
const char kSocketNameFormat[] = "webview_devtools_remote_%d";
const char kTetheringSocketName[] = "webview_devtools_tethering_%d_%d";
const int kBackLog = 10;
// Factory for UnixDomainServerSocket.
class UnixDomainServerSocketFactory : public content::DevToolsSocketFactory {
public:
explicit UnixDomainServerSocketFactory(const std::string& socket_name)
: socket_name_(socket_name), last_tethering_socket_(0) {}
private:
// content::DevToolsAgentHost::ServerSocketFactory.
std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
std::unique_ptr<net::UnixDomainServerSocket> socket(
new net::UnixDomainServerSocket(
base::BindRepeating(&content::CanUserConnectToDevTools),
true /* use_abstract_namespace */));
if (socket->BindAndListen(socket_name_, kBackLog) != net::OK)
return nullptr;
return std::move(socket);
}
std::unique_ptr<net::ServerSocket> CreateForTethering(
std::string* name) override {
*name = base::StringPrintf(kTetheringSocketName, getpid(),
++last_tethering_socket_);
std::unique_ptr<net::UnixDomainServerSocket> socket(
new net::UnixDomainServerSocket(
base::BindRepeating(&content::CanUserConnectToDevTools),
true /* use_abstract_namespace */));
if (socket->BindAndListen(*name, kBackLog) != net::OK)
return nullptr;
return std::move(socket);
}
std::string socket_name_;
int last_tethering_socket_;
DISALLOW_COPY_AND_ASSIGN(UnixDomainServerSocketFactory);
};
class TCPServerSocketFactory : public content::DevToolsSocketFactory {
public:
TCPServerSocketFactory(const std::string& address, uint16_t port)
: address_(address), port_(port) {}
private:
// content::DevToolsSocketFactory.
std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
std::unique_ptr<net::ServerSocket> socket(
new net::TCPServerSocket(nullptr, net::NetLogSource()));
if (socket->ListenWithAddressAndPort(address_, port_, kBackLog) != net::OK)
return nullptr;
net::IPEndPoint endpoint;
return socket;
}
std::unique_ptr<net::ServerSocket> CreateForTethering(
std::string* out_name) override {
return nullptr;
}
std::string address_;
uint16_t port_;
DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory);
};
std::unique_ptr<content::DevToolsSocketFactory> CreateSocketFactory() {
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
uint16_t port = 0;
int temp_port;
std::string port_str =
command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort);
if (base::StringToInt(port_str, &temp_port) && temp_port >= 1024 &&
temp_port < 65535) {
port = static_cast<uint16_t>(temp_port);
} else {
DLOG(WARNING) << "Invalid http debugger port number " << temp_port;
}
return std::make_unique<TCPServerSocketFactory>("127.0.0.1", port);
}
return std::make_unique<UnixDomainServerSocketFactory>(
base::StringPrintf(kSocketNameFormat, getpid()));
}
} // namespace
namespace android_webview {
AwDevToolsServer::AwDevToolsServer() : is_started_(false) {}
AwDevToolsServer::~AwDevToolsServer() {
Stop();
}
void AwDevToolsServer::Start() {
if (is_started_)
return;
is_started_ = true;
DevToolsAgentHost::StartRemoteDebuggingServer(
CreateSocketFactory(), base::FilePath(), base::FilePath());
}
void AwDevToolsServer::Stop() {
DevToolsAgentHost::StopRemoteDebuggingServer();
is_started_ = false;
}
bool AwDevToolsServer::IsStarted() const {
return is_started_;
}
static jlong JNI_AwDevToolsServer_InitRemoteDebugging(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
AwDevToolsServer* server = new AwDevToolsServer();
return reinterpret_cast<intptr_t>(server);
}
static void JNI_AwDevToolsServer_DestroyRemoteDebugging(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jlong server) {
delete reinterpret_cast<AwDevToolsServer*>(server);
}
static void JNI_AwDevToolsServer_SetRemoteDebuggingEnabled(
JNIEnv* env,
const JavaParamRef<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