Browse Source

Start node inspector agent when --inspect is present

Kevin Sawicki 8 years ago
parent
commit
a33643c518

+ 5 - 0
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());
 

+ 2 - 0
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<NodeBindings> node_bindings_;
   std::unique_ptr<AtomBindings> atom_bindings_;
   std::unique_ptr<NodeEnvironment> node_env_;
+  std::unique_ptr<NodeDebugger> node_debugger_;
 
   base::Timer gc_timer_;
 

+ 13 - 182
atom/browser/node_debugger.cc

@@ -4,202 +4,33 @@
 
 #include "atom/browser/node_debugger.h"
 
-#include <string>
-
-#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;
-  }
-}
-
-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<const uint16_t*>(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<int>(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<NodeDebugger*>(handle->data);
-  v8::Debug::ProcessDebugMessages(self->isolate_);
-}
-
-// static
-void NodeDebugger::DebugMessageHandler(const v8::Debug::Message& message) {
-  NodeDebugger* self = static_cast<NodeDebugger*>(
-      message.GetIsolate()->GetData(kIsolateSlot));
+  node::DebugOptions options;
+  for (auto& arg : base::CommandLine::ForCurrentProcess()->argv())
+    options.ParseOption(arg);
 
-  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));
-  }
-}
+  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());
 
-void NodeDebugger::DidAccept(
-    net::test_server::StreamListenSocket* server,
-    std::unique_ptr<net::test_server::StreamListenSocket> socket) {
-  // Only accept one session.
-  if (accepted_socket_) {
-    socket->Send(std::string("Remote debugging session already active"), true);
-    return;
+    inspector->Start(platform_.get(), nullptr, options);
   }
-
-  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<size_t>(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

+ 8 - 42
atom/browser/node_debugger.h

@@ -6,56 +6,22 @@
 #define ATOM_BROWSER_NODE_DEBUGGER_H_
 
 #include <memory>
-#include <string>
 
-#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<net::test_server::StreamListenSocket> 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<net::test_server::StreamListenSocket> server_;
-  std::unique_ptr<net::test_server::StreamListenSocket> accepted_socket_;
-
-  std::string buffer_;
-  int content_length_;
-
-  base::WeakPtrFactory<NodeDebugger> weak_factory_;
+  node::Environment* env_;
+  std::unique_ptr<v8::Platform> platform_;
 
   DISALLOW_COPY_AND_ASSIGN(NodeDebugger);
 };

+ 1 - 0
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_