From a33643c51849d6026b65a5641ff6dda4ffcd55ba Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 May 2017 09:30:55 -0700 Subject: [PATCH] Start node inspector agent when --inspect is present --- atom/browser/atom_browser_main_parts.cc | 5 + atom/browser/atom_browser_main_parts.h | 2 + atom/browser/node_debugger.cc | 201 ++---------------------- atom/browser/node_debugger.h | 50 +----- atom/common/node_includes.h | 1 + 5 files changed, 32 insertions(+), 227 deletions(-) diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index cc760b46b19..190898fdef9 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -12,6 +12,7 @@ #include "atom/browser/bridge_task_runner.h" #include "atom/browser/browser.h" #include "atom/browser/javascript_environment.h" +#include "atom/browser/node_debugger.h" #include "atom/common/api/atom_bindings.h" #include "atom/common/asar/asar_util.h" #include "atom/common/node_bindings.h" @@ -133,6 +134,10 @@ void AtomBrowserMainParts::PostEarlyInitialization() { node_bindings_->CreateEnvironment(js_env_->context()); node_env_.reset(new NodeEnvironment(env)); + // Enable support for v8 inspector + node_debugger_.reset(new NodeDebugger(env)); + node_debugger_->Start(); + // Add Electron extended APIs. atom_bindings_->BindTo(js_env_->isolate(), env->process_object()); diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index 4067f542b42..2ba7d341f43 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -21,6 +21,7 @@ class AtomBindings; class Browser; class JavascriptEnvironment; class NodeBindings; +class NodeDebugger; class NodeEnvironment; class BridgeTaskRunner; @@ -82,6 +83,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { std::unique_ptr node_bindings_; std::unique_ptr atom_bindings_; std::unique_ptr node_env_; + std::unique_ptr node_debugger_; base::Timer gc_timer_; diff --git a/atom/browser/node_debugger.cc b/atom/browser/node_debugger.cc index 9fdeb6099e6..31898d4c251 100644 --- a/atom/browser/node_debugger.cc +++ b/atom/browser/node_debugger.cc @@ -4,202 +4,33 @@ #include "atom/browser/node_debugger.h" -#include - -#include "base/bind.h" #include "base/command_line.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "content/public/browser/browser_thread.h" -#include "net/test/embedded_test_server/tcp_listen_socket.h" - -#include "atom/common/node_includes.h" +#include "libplatform/libplatform.h" namespace atom { -namespace { - -// NodeDebugger is stored in Isolate's data, slots 0, 1, 3 have already been -// taken by gin, blink and node, using 2 is a safe option for now. -const int kIsolateSlot = 2; - -const char* kContentLength = "Content-Length"; - -} // namespace - -NodeDebugger::NodeDebugger(v8::Isolate* isolate) - : isolate_(isolate), - thread_("NodeDebugger"), - content_length_(-1), - weak_factory_(this) { - bool use_debug_agent = false; - int port = 5858; - - std::string port_str; - base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); - if (cmd->HasSwitch("debug")) { - use_debug_agent = true; - port_str = cmd->GetSwitchValueASCII("debug"); - } else if (cmd->HasSwitch("debug-brk")) { - use_debug_agent = true; - port_str = cmd->GetSwitchValueASCII("debug-brk"); - } - - if (use_debug_agent) { - if (!port_str.empty()) - base::StringToInt(port_str, &port); - - isolate_->SetData(kIsolateSlot, this); - v8::Debug::SetMessageHandler(isolate_, DebugMessageHandler); - - weak_up_ui_handle_.data = this; - uv_async_init(uv_default_loop(), &weak_up_ui_handle_, ProcessMessageInUI); - - // Start a new IO thread. - base::Thread::Options options; - options.message_loop_type = base::MessageLoop::TYPE_IO; - if (!thread_.StartWithOptions(options)) { - LOG(ERROR) << "Unable to start debugger thread"; - return; - } - - // Start the server in new IO thread. - thread_.task_runner()->PostTask( - FROM_HERE, - base::Bind(&NodeDebugger::StartServer, weak_factory_.GetWeakPtr(), - port)); - } +NodeDebugger::NodeDebugger(node::Environment* env) : env_(env) { } NodeDebugger::~NodeDebugger() { - thread_.Stop(); } -bool NodeDebugger::IsRunning() const { - return thread_.IsRunning(); -} - -void NodeDebugger::StartServer(int port) { - server_ = net::test_server::TCPListenSocket::CreateAndListen( - "127.0.0.1", port, this); - if (!server_) { - LOG(ERROR) << "Cannot start debugger server"; +void NodeDebugger::Start() { + auto inspector = env_->inspector_agent(); + if (inspector == nullptr) return; + + node::DebugOptions options; + for (auto& arg : base::CommandLine::ForCurrentProcess()->argv()) + options.ParseOption(arg); + + if (options.inspector_enabled()) { + // Use custom platform since the gin platform does not work correctly + // with node's inspector agent + platform_.reset(v8::platform::CreateDefaultPlatform()); + + inspector->Start(platform_.get(), nullptr, options); } } -void NodeDebugger::CloseSession() { - accepted_socket_.reset(); -} - -void NodeDebugger::OnMessage(const std::string& message) { - if (message.find("\"type\":\"request\",\"command\":\"disconnect\"}") != - std::string::npos) - CloseSession(); - - base::string16 message16 = base::UTF8ToUTF16(message); - v8::Debug::SendCommand( - isolate_, - reinterpret_cast(message16.data()), message16.size()); - - uv_async_send(&weak_up_ui_handle_); -} - -void NodeDebugger::SendMessage(const std::string& message) { - if (accepted_socket_) { - std::string header = base::StringPrintf( - "%s: %d\r\n\r\n", kContentLength, static_cast(message.size())); - accepted_socket_->Send(header); - accepted_socket_->Send(message); - } -} - -void NodeDebugger::SendConnectMessage() { - accepted_socket_->Send(base::StringPrintf( - "Type: connect\r\n" - "V8-Version: %s\r\n" - "Protocol-Version: 1\r\n" - "Embedding-Host: %s\r\n" - "%s: 0\r\n", - v8::V8::GetVersion(), ATOM_PRODUCT_NAME, kContentLength), true); -} - -// static -void NodeDebugger::ProcessMessageInUI(uv_async_t* handle) { - NodeDebugger* self = static_cast(handle->data); - v8::Debug::ProcessDebugMessages(self->isolate_); -} - -// static -void NodeDebugger::DebugMessageHandler(const v8::Debug::Message& message) { - NodeDebugger* self = static_cast( - message.GetIsolate()->GetData(kIsolateSlot)); - - if (self) { - std::string message8(*v8::String::Utf8Value(message.GetJSON())); - self->thread_.task_runner()->PostTask( - FROM_HERE, - base::Bind(&NodeDebugger::SendMessage, self->weak_factory_.GetWeakPtr(), - message8)); - } -} - -void NodeDebugger::DidAccept( - net::test_server::StreamListenSocket* server, - std::unique_ptr socket) { - // Only accept one session. - if (accepted_socket_) { - socket->Send(std::string("Remote debugging session already active"), true); - return; - } - - accepted_socket_ = std::move(socket); - SendConnectMessage(); -} - -void NodeDebugger::DidRead(net::test_server::StreamListenSocket* socket, - const char* data, - int len) { - buffer_.append(data, len); - - do { - if (buffer_.empty()) - return; - - // Read the "Content-Length" header. - if (content_length_ < 0) { - size_t pos = buffer_.find("\r\n\r\n"); - if (pos == std::string::npos) - return; - - // We can be sure that the header is "Content-Length: xxx\r\n". - std::string content_length = buffer_.substr(16, pos - 16); - if (!base::StringToInt(content_length, &content_length_)) { - DidClose(accepted_socket_.get()); - return; - } - - // Strip header from buffer. - buffer_ = buffer_.substr(pos + 4); - } - - // Read the message. - if (buffer_.size() >= static_cast(content_length_)) { - std::string message = buffer_.substr(0, content_length_); - buffer_ = buffer_.substr(content_length_); - - OnMessage(message); - - // Get ready for next message. - content_length_ = -1; - } - } while (true); -} - -void NodeDebugger::DidClose(net::test_server::StreamListenSocket* socket) { - // If we lost the connection, then simulate a disconnect msg: - OnMessage("{\"seq\":1,\"type\":\"request\",\"command\":\"disconnect\"}"); -} - } // namespace atom diff --git a/atom/browser/node_debugger.h b/atom/browser/node_debugger.h index 118812a139a..a3553192b4e 100644 --- a/atom/browser/node_debugger.h +++ b/atom/browser/node_debugger.h @@ -6,56 +6,22 @@ #define ATOM_BROWSER_NODE_DEBUGGER_H_ #include -#include -#include "base/memory/weak_ptr.h" -#include "base/threading/thread.h" -#include "net/test/embedded_test_server/stream_listen_socket.h" -#include "v8/include/v8-debug.h" -#include "vendor/node/deps/uv/include/uv.h" +#include "atom/common/node_includes.h" namespace atom { -// Add support for node's "--debug" switch. -class NodeDebugger : public net::test_server::StreamListenSocket::Delegate { +// Add support for node's "--inspect" switch. +class NodeDebugger { public: - explicit NodeDebugger(v8::Isolate* isolate); - virtual ~NodeDebugger(); + explicit NodeDebugger(node::Environment* env); + ~NodeDebugger(); - bool IsRunning() const; + void Start(); private: - void StartServer(int port); - void CloseSession(); - void OnMessage(const std::string& message); - void SendMessage(const std::string& message); - void SendConnectMessage(); - - static void ProcessMessageInUI(uv_async_t* handle); - - static void DebugMessageHandler(const v8::Debug::Message& message); - - // net::test_server::StreamListenSocket::Delegate: - void DidAccept( - net::test_server::StreamListenSocket* server, - std::unique_ptr socket) override; - void DidRead(net::test_server::StreamListenSocket* socket, - const char* data, - int len) override; - void DidClose(net::test_server::StreamListenSocket* socket) override; - - v8::Isolate* isolate_; - - uv_async_t weak_up_ui_handle_; - - base::Thread thread_; - std::unique_ptr server_; - std::unique_ptr accepted_socket_; - - std::string buffer_; - int content_length_; - - base::WeakPtrFactory weak_factory_; + node::Environment* env_; + std::unique_ptr platform_; DISALLOW_COPY_AND_ASSIGN(NodeDebugger); }; diff --git a/atom/common/node_includes.h b/atom/common/node_includes.h index b6cbf36090c..5e9c3fdbec8 100644 --- a/atom/common/node_includes.h +++ b/atom/common/node_includes.h @@ -29,6 +29,7 @@ #include "vendor/node/src/env-inl.h" #include "vendor/node/src/node.h" #include "vendor/node/src/node_buffer.h" +#include "vendor/node/src/node_debug_options.h" #include "vendor/node/src/node_internals.h" #endif // ATOM_COMMON_NODE_INCLUDES_H_