11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
31cb0ef41Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
41cb0ef41Sopenharmony_ci * you may not use this file except in compliance with the License.
51cb0ef41Sopenharmony_ci * You may obtain a copy of the License at
61cb0ef41Sopenharmony_ci *
71cb0ef41Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
81cb0ef41Sopenharmony_ci *
91cb0ef41Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
101cb0ef41Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
111cb0ef41Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121cb0ef41Sopenharmony_ci * See the License for the specific language governing permissions and
131cb0ef41Sopenharmony_ci * limitations under the License.
141cb0ef41Sopenharmony_ci */
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci#include "js_native_api_v8_inspector.h"
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci#include "js_native_api_v8.h"
191cb0ef41Sopenharmony_ci#include "inspector_socket_server.h"
201cb0ef41Sopenharmony_ci#include "inspector/main_thread_interface.h"
211cb0ef41Sopenharmony_ci#include "inspector/node_string.h"
221cb0ef41Sopenharmony_ci#include "inspector/runtime_agent.h"
231cb0ef41Sopenharmony_ci#include "inspector/tracing_agent.h"
241cb0ef41Sopenharmony_ci#include "inspector/worker_agent.h"
251cb0ef41Sopenharmony_ci#include "inspector/worker_inspector.h"
261cb0ef41Sopenharmony_ci#include "crypto/crypto_util.h"
271cb0ef41Sopenharmony_ci#include "node/inspector/protocol/Protocol.h"
281cb0ef41Sopenharmony_ci#include "node_errors.h"
291cb0ef41Sopenharmony_ci#include "node_internals.h"
301cb0ef41Sopenharmony_ci#include "node_mutex.h"
311cb0ef41Sopenharmony_ci#include "node_options-inl.h"
321cb0ef41Sopenharmony_ci#include "node_process-inl.h"
331cb0ef41Sopenharmony_ci#include "node_url.h"
341cb0ef41Sopenharmony_ci#include "permission/permission.h"
351cb0ef41Sopenharmony_ci#include "util-inl.h"
361cb0ef41Sopenharmony_ci#include "v8-inspector.h"
371cb0ef41Sopenharmony_ci#include "v8-platform.h"
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci#include "libplatform/libplatform.h"
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci#ifdef __POSIX__
421cb0ef41Sopenharmony_ci#include <pthread.h>
431cb0ef41Sopenharmony_ci#include <climits>  // PTHREAD_STACK_MIN
441cb0ef41Sopenharmony_ci#endif  // __POSIX__
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci#include <algorithm>
471cb0ef41Sopenharmony_ci#include <cstring>
481cb0ef41Sopenharmony_ci#include <sstream>
491cb0ef41Sopenharmony_ci#include <unordered_map>
501cb0ef41Sopenharmony_ci#include <vector>
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_cinamespace v8impl {
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_cinamespace {
551cb0ef41Sopenharmony_ciusing node::ConditionVariable;
561cb0ef41Sopenharmony_ciusing node::Mutex;
571cb0ef41Sopenharmony_ciusing node::inspector::Utf8ToStringView;
581cb0ef41Sopenharmony_ciusing v8_inspector::StringBuffer;
591cb0ef41Sopenharmony_ciusing v8_inspector::StringView;
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ciclass MainThreadInterface;
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ciclass Request {
641cb0ef41Sopenharmony_ci public:
651cb0ef41Sopenharmony_ci  virtual void Call(MainThreadInterface*) = 0;
661cb0ef41Sopenharmony_ci  virtual ~Request() = default;
671cb0ef41Sopenharmony_ci};
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ciclass Deletable {
701cb0ef41Sopenharmony_ci public:
711cb0ef41Sopenharmony_ci  virtual ~Deletable() = default;
721cb0ef41Sopenharmony_ci};
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ciusing MessageQueue = std::deque<std::unique_ptr<Request>>;
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ciclass MainThreadHandle : public std::enable_shared_from_this<MainThreadHandle> {
771cb0ef41Sopenharmony_ci public:
781cb0ef41Sopenharmony_ci  explicit MainThreadHandle(MainThreadInterface* main_thread)
791cb0ef41Sopenharmony_ci                            : main_thread_(main_thread) {
801cb0ef41Sopenharmony_ci  }
811cb0ef41Sopenharmony_ci  ~MainThreadHandle() {
821cb0ef41Sopenharmony_ci    Mutex::ScopedLock scoped_lock(block_lock_);
831cb0ef41Sopenharmony_ci    CHECK_NULL(main_thread_);  // main_thread_ should have called Reset
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci  std::unique_ptr<InspectorSession> Connect(
861cb0ef41Sopenharmony_ci      std::unique_ptr<InspectorSessionDelegate> delegate,
871cb0ef41Sopenharmony_ci      bool prevent_shutdown);
881cb0ef41Sopenharmony_ci  int newObjectId() {
891cb0ef41Sopenharmony_ci    return ++next_object_id_;
901cb0ef41Sopenharmony_ci  }
911cb0ef41Sopenharmony_ci  bool Post(std::unique_ptr<Request> request);
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci private:
941cb0ef41Sopenharmony_ci  void Reset();
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  MainThreadInterface* main_thread_;
971cb0ef41Sopenharmony_ci  Mutex block_lock_;
981cb0ef41Sopenharmony_ci  int next_session_id_ = 0;
991cb0ef41Sopenharmony_ci  std::atomic_int next_object_id_ = {1};
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  friend class MainThreadInterface;
1021cb0ef41Sopenharmony_ci};
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ciclass MainThreadInterface :
1051cb0ef41Sopenharmony_ci    public std::enable_shared_from_this<MainThreadInterface> {
1061cb0ef41Sopenharmony_ci public:
1071cb0ef41Sopenharmony_ci  explicit MainThreadInterface(Agent* agent);
1081cb0ef41Sopenharmony_ci  ~MainThreadInterface();
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  void DispatchMessages();
1111cb0ef41Sopenharmony_ci  void Post(std::unique_ptr<Request> request);
1121cb0ef41Sopenharmony_ci  bool WaitForFrontendEvent();
1131cb0ef41Sopenharmony_ci  std::shared_ptr<MainThreadHandle> GetHandle();
1141cb0ef41Sopenharmony_ci  Agent* inspector_agent() {
1151cb0ef41Sopenharmony_ci    return agent_;
1161cb0ef41Sopenharmony_ci  }
1171cb0ef41Sopenharmony_ci  void AddObject(int handle, std::unique_ptr<Deletable> object);
1181cb0ef41Sopenharmony_ci  Deletable* GetObject(int id);
1191cb0ef41Sopenharmony_ci  Deletable* GetObjectIfExists(int id);
1201cb0ef41Sopenharmony_ci  void RemoveObject(int handle);
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci private:
1231cb0ef41Sopenharmony_ci  MessageQueue requests_;
1241cb0ef41Sopenharmony_ci  Mutex requests_lock_;   // requests_ live across threads
1251cb0ef41Sopenharmony_ci  // This queue is to maintain the order of the messages for the cases
1261cb0ef41Sopenharmony_ci  // when we reenter the DispatchMessages function.
1271cb0ef41Sopenharmony_ci  MessageQueue dispatching_message_queue_;
1281cb0ef41Sopenharmony_ci  bool dispatching_messages_ = false;
1291cb0ef41Sopenharmony_ci  ConditionVariable incoming_message_cond_;
1301cb0ef41Sopenharmony_ci  // Used from any thread
1311cb0ef41Sopenharmony_ci  Agent* const agent_;
1321cb0ef41Sopenharmony_ci  std::shared_ptr<MainThreadHandle> handle_;
1331cb0ef41Sopenharmony_ci  std::unordered_map<int, std::unique_ptr<Deletable>> managed_objects_;
1341cb0ef41Sopenharmony_ci};
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_citemplate <typename T>
1371cb0ef41Sopenharmony_ciclass DeletableWrapper : public Deletable {
1381cb0ef41Sopenharmony_ci public:
1391cb0ef41Sopenharmony_ci  explicit DeletableWrapper(std::unique_ptr<T> object)
1401cb0ef41Sopenharmony_ci                        : object_(std::move(object)) {}
1411cb0ef41Sopenharmony_ci  ~DeletableWrapper() override = default;
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  static T* get(MainThreadInterface* thread, int id) {
1441cb0ef41Sopenharmony_ci    return
1451cb0ef41Sopenharmony_ci        static_cast<DeletableWrapper<T>*>(thread->GetObject(id))->object_.get();
1461cb0ef41Sopenharmony_ci  }
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci private:
1491cb0ef41Sopenharmony_ci  std::unique_ptr<T> object_;
1501cb0ef41Sopenharmony_ci};
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_citemplate <typename T>
1531cb0ef41Sopenharmony_cistd::unique_ptr<Deletable> WrapInDeletable(std::unique_ptr<T> object) {
1541cb0ef41Sopenharmony_ci  return std::unique_ptr<DeletableWrapper<T>>(
1551cb0ef41Sopenharmony_ci      new DeletableWrapper<T>(std::move(object)));
1561cb0ef41Sopenharmony_ci}
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_citemplate <typename Factory>
1591cb0ef41Sopenharmony_ciclass CreateObjectRequest : public Request {
1601cb0ef41Sopenharmony_ci public:
1611cb0ef41Sopenharmony_ci  CreateObjectRequest(int object_id, Factory factory)
1621cb0ef41Sopenharmony_ci                      : object_id_(object_id), factory_(std::move(factory)) {}
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  void Call(MainThreadInterface* thread) override {
1651cb0ef41Sopenharmony_ci    thread->AddObject(object_id_, WrapInDeletable(factory_(thread)));
1661cb0ef41Sopenharmony_ci  }
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci private:
1691cb0ef41Sopenharmony_ci  int object_id_;
1701cb0ef41Sopenharmony_ci  Factory factory_;
1711cb0ef41Sopenharmony_ci};
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_citemplate <typename Factory>
1741cb0ef41Sopenharmony_cistd::unique_ptr<Request> NewCreateRequest(int object_id, Factory factory) {
1751cb0ef41Sopenharmony_ci  return std::unique_ptr<Request>(
1761cb0ef41Sopenharmony_ci      new CreateObjectRequest<Factory>(object_id, std::move(factory)));
1771cb0ef41Sopenharmony_ci}
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ciclass DeleteRequest : public Request {
1801cb0ef41Sopenharmony_ci public:
1811cb0ef41Sopenharmony_ci  explicit DeleteRequest(int object_id) : object_id_(object_id) {}
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci  void Call(MainThreadInterface* thread) override {
1841cb0ef41Sopenharmony_ci    thread->RemoveObject(object_id_);
1851cb0ef41Sopenharmony_ci  }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci private:
1881cb0ef41Sopenharmony_ci  int object_id_;
1891cb0ef41Sopenharmony_ci};
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_citemplate <typename Target, typename Fn>
1921cb0ef41Sopenharmony_ciclass CallRequest : public Request {
1931cb0ef41Sopenharmony_ci public:
1941cb0ef41Sopenharmony_ci  CallRequest(int id, Fn fn) : id_(id), fn_(std::move(fn)) {}
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci  void Call(MainThreadInterface* thread) override {
1971cb0ef41Sopenharmony_ci    fn_(DeletableWrapper<Target>::get(thread, id_));
1981cb0ef41Sopenharmony_ci  }
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci private:
2011cb0ef41Sopenharmony_ci  int id_;
2021cb0ef41Sopenharmony_ci  Fn fn_;
2031cb0ef41Sopenharmony_ci};
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_citemplate <typename T>
2061cb0ef41Sopenharmony_ciclass AnotherThreadObjectReference {
2071cb0ef41Sopenharmony_ci public:
2081cb0ef41Sopenharmony_ci  AnotherThreadObjectReference(
2091cb0ef41Sopenharmony_ci      std::shared_ptr<MainThreadHandle> thread, int object_id)
2101cb0ef41Sopenharmony_ci      : thread_(thread), object_id_(object_id) {}
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci  template <typename Factory>
2131cb0ef41Sopenharmony_ci  AnotherThreadObjectReference(
2141cb0ef41Sopenharmony_ci      std::shared_ptr<MainThreadHandle> thread, Factory factory)
2151cb0ef41Sopenharmony_ci      : AnotherThreadObjectReference(thread, thread->newObjectId()) {
2161cb0ef41Sopenharmony_ci    thread_->Post(NewCreateRequest(object_id_, std::move(factory)));
2171cb0ef41Sopenharmony_ci  }
2181cb0ef41Sopenharmony_ci  AnotherThreadObjectReference(AnotherThreadObjectReference&) = delete;
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci  ~AnotherThreadObjectReference() {
2211cb0ef41Sopenharmony_ci    // Disappearing thread may cause a memory leak
2221cb0ef41Sopenharmony_ci    thread_->Post(std::make_unique<DeleteRequest>(object_id_));
2231cb0ef41Sopenharmony_ci  }
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci  template <typename Fn>
2261cb0ef41Sopenharmony_ci  void Call(Fn fn) const {
2271cb0ef41Sopenharmony_ci    using Request = CallRequest<T, Fn>;
2281cb0ef41Sopenharmony_ci    thread_->Post(std::unique_ptr<Request>(
2291cb0ef41Sopenharmony_ci        new Request(object_id_, std::move(fn))));
2301cb0ef41Sopenharmony_ci  }
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci  template <typename Arg>
2331cb0ef41Sopenharmony_ci  void Call(void (T::*fn)(Arg), Arg argument) const {
2341cb0ef41Sopenharmony_ci    Call(std::bind(Apply<Arg>, std::placeholders::_1, fn, std::move(argument)));
2351cb0ef41Sopenharmony_ci  }
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci private:
2381cb0ef41Sopenharmony_ci  // This has to use non-const reference to support std::bind with non-copyable
2391cb0ef41Sopenharmony_ci  // types
2401cb0ef41Sopenharmony_ci  template <typename Argument>
2411cb0ef41Sopenharmony_ci  static void Apply(T* target, void (T::*fn)(Argument),
2421cb0ef41Sopenharmony_ci    /* NOLINT (runtime/references) */ Argument& argument) {
2431cb0ef41Sopenharmony_ci    (target->*fn)(std::move(argument));
2441cb0ef41Sopenharmony_ci  }
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci  std::shared_ptr<MainThreadHandle> thread_;
2471cb0ef41Sopenharmony_ci  const int object_id_;
2481cb0ef41Sopenharmony_ci};
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ciclass MainThreadSessionState {
2511cb0ef41Sopenharmony_ci public:
2521cb0ef41Sopenharmony_ci  MainThreadSessionState(MainThreadInterface* thread, bool prevent_shutdown)
2531cb0ef41Sopenharmony_ci                         : thread_(thread),
2541cb0ef41Sopenharmony_ci                           prevent_shutdown_(prevent_shutdown) {}
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci  static std::unique_ptr<MainThreadSessionState> Create(
2571cb0ef41Sopenharmony_ci      MainThreadInterface* thread, bool prevent_shutdown) {
2581cb0ef41Sopenharmony_ci    return std::make_unique<MainThreadSessionState>(thread, prevent_shutdown);
2591cb0ef41Sopenharmony_ci  }
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ci  void Connect(std::unique_ptr<InspectorSessionDelegate> delegate) {
2621cb0ef41Sopenharmony_ci    Agent* agent = thread_->inspector_agent();
2631cb0ef41Sopenharmony_ci    if (agent != nullptr)
2641cb0ef41Sopenharmony_ci      session_ = agent->Connect(std::move(delegate), prevent_shutdown_);
2651cb0ef41Sopenharmony_ci  }
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci  void Dispatch(std::unique_ptr<StringBuffer> message) {
2681cb0ef41Sopenharmony_ci    session_->Dispatch(message->string());
2691cb0ef41Sopenharmony_ci  }
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci private:
2721cb0ef41Sopenharmony_ci  MainThreadInterface* thread_;
2731cb0ef41Sopenharmony_ci  bool prevent_shutdown_;
2741cb0ef41Sopenharmony_ci  std::unique_ptr<InspectorSession> session_;
2751cb0ef41Sopenharmony_ci};
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ciclass CrossThreadInspectorSession : public InspectorSession {
2781cb0ef41Sopenharmony_ci public:
2791cb0ef41Sopenharmony_ci  CrossThreadInspectorSession(
2801cb0ef41Sopenharmony_ci      int id,
2811cb0ef41Sopenharmony_ci      std::shared_ptr<MainThreadHandle> thread,
2821cb0ef41Sopenharmony_ci      std::unique_ptr<InspectorSessionDelegate> delegate,
2831cb0ef41Sopenharmony_ci      bool prevent_shutdown)
2841cb0ef41Sopenharmony_ci      : state_(thread, std::bind(MainThreadSessionState::Create,
2851cb0ef41Sopenharmony_ci                                 std::placeholders::_1,
2861cb0ef41Sopenharmony_ci                                 prevent_shutdown)) {
2871cb0ef41Sopenharmony_ci    state_.Call(&MainThreadSessionState::Connect, std::move(delegate));
2881cb0ef41Sopenharmony_ci  }
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci  void Dispatch(const StringView& message) override {
2911cb0ef41Sopenharmony_ci    state_.Call(&MainThreadSessionState::Dispatch,
2921cb0ef41Sopenharmony_ci                StringBuffer::create(message));
2931cb0ef41Sopenharmony_ci  }
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci private:
2961cb0ef41Sopenharmony_ci  AnotherThreadObjectReference<MainThreadSessionState> state_;
2971cb0ef41Sopenharmony_ci};
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ciclass ThreadSafeDelegate : public InspectorSessionDelegate {
3001cb0ef41Sopenharmony_ci public:
3011cb0ef41Sopenharmony_ci  ThreadSafeDelegate(std::shared_ptr<MainThreadHandle> thread, int object_id)
3021cb0ef41Sopenharmony_ci                     : thread_(thread), delegate_(thread, object_id) {}
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_ci  void SendMessageToFrontend(const v8_inspector::StringView& message) override {
3051cb0ef41Sopenharmony_ci    delegate_.Call(
3061cb0ef41Sopenharmony_ci        [m = StringBuffer::create(message)]
3071cb0ef41Sopenharmony_ci        (InspectorSessionDelegate* delegate) {
3081cb0ef41Sopenharmony_ci      delegate->SendMessageToFrontend(m->string());
3091cb0ef41Sopenharmony_ci    });
3101cb0ef41Sopenharmony_ci  }
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ci private:
3131cb0ef41Sopenharmony_ci  std::shared_ptr<MainThreadHandle> thread_;
3141cb0ef41Sopenharmony_ci  AnotherThreadObjectReference<InspectorSessionDelegate> delegate_;
3151cb0ef41Sopenharmony_ci};
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ciMainThreadInterface::MainThreadInterface(Agent* agent) : agent_(agent) {}
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ciMainThreadInterface::~MainThreadInterface() {
3201cb0ef41Sopenharmony_ci  if (handle_)
3211cb0ef41Sopenharmony_ci    handle_->Reset();
3221cb0ef41Sopenharmony_ci}
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_civoid MainThreadInterface::Post(std::unique_ptr<Request> request) {
3251cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(agent_);
3261cb0ef41Sopenharmony_ci  Mutex::ScopedLock scoped_lock(requests_lock_);
3271cb0ef41Sopenharmony_ci  bool needs_notify = requests_.empty();
3281cb0ef41Sopenharmony_ci  requests_.push_back(std::move(request));
3291cb0ef41Sopenharmony_ci  if (needs_notify) {
3301cb0ef41Sopenharmony_ci    std::weak_ptr<MainThreadInterface> weak_self {shared_from_this()};
3311cb0ef41Sopenharmony_ci    agent_->env()->RequestInterrupt([weak_self](Environment*) {
3321cb0ef41Sopenharmony_ci      if (auto iface = weak_self.lock()) iface->DispatchMessages();
3331cb0ef41Sopenharmony_ci    });
3341cb0ef41Sopenharmony_ci  }
3351cb0ef41Sopenharmony_ci  incoming_message_cond_.Broadcast(scoped_lock);
3361cb0ef41Sopenharmony_ci}
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_cibool MainThreadInterface::WaitForFrontendEvent() {
3391cb0ef41Sopenharmony_ci  // We allow DispatchMessages reentry as we enter the pause. This is important
3401cb0ef41Sopenharmony_ci  // to support debugging the code invoked by an inspector call, such
3411cb0ef41Sopenharmony_ci  // as Runtime.evaluate
3421cb0ef41Sopenharmony_ci  dispatching_messages_ = false;
3431cb0ef41Sopenharmony_ci  if (dispatching_message_queue_.empty()) {
3441cb0ef41Sopenharmony_ci    Mutex::ScopedLock scoped_lock(requests_lock_);
3451cb0ef41Sopenharmony_ci    while (requests_.empty()) incoming_message_cond_.Wait(scoped_lock);
3461cb0ef41Sopenharmony_ci  }
3471cb0ef41Sopenharmony_ci  return true;
3481cb0ef41Sopenharmony_ci}
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_civoid MainThreadInterface::DispatchMessages() {
3511cb0ef41Sopenharmony_ci  if (dispatching_messages_)
3521cb0ef41Sopenharmony_ci    return;
3531cb0ef41Sopenharmony_ci  dispatching_messages_ = true;
3541cb0ef41Sopenharmony_ci  bool had_messages = false;
3551cb0ef41Sopenharmony_ci  do {
3561cb0ef41Sopenharmony_ci    if (dispatching_message_queue_.empty()) {
3571cb0ef41Sopenharmony_ci      Mutex::ScopedLock scoped_lock(requests_lock_);
3581cb0ef41Sopenharmony_ci      requests_.swap(dispatching_message_queue_);
3591cb0ef41Sopenharmony_ci    }
3601cb0ef41Sopenharmony_ci    had_messages = !dispatching_message_queue_.empty();
3611cb0ef41Sopenharmony_ci    while (!dispatching_message_queue_.empty()) {
3621cb0ef41Sopenharmony_ci      MessageQueue::value_type task;
3631cb0ef41Sopenharmony_ci      std::swap(dispatching_message_queue_.front(), task);
3641cb0ef41Sopenharmony_ci      dispatching_message_queue_.pop_front();
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci      v8::SealHandleScope seal_handle_scope(agent_->env()->isolate);
3671cb0ef41Sopenharmony_ci      task->Call(this);
3681cb0ef41Sopenharmony_ci    }
3691cb0ef41Sopenharmony_ci  } while (had_messages);
3701cb0ef41Sopenharmony_ci  dispatching_messages_ = false;
3711cb0ef41Sopenharmony_ci}
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_cistd::shared_ptr<MainThreadHandle> MainThreadInterface::GetHandle() {
3741cb0ef41Sopenharmony_ci  if (handle_ == nullptr)
3751cb0ef41Sopenharmony_ci    handle_ = std::make_shared<MainThreadHandle>(this);
3761cb0ef41Sopenharmony_ci  return handle_;
3771cb0ef41Sopenharmony_ci}
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_civoid MainThreadInterface::AddObject(int id,
3801cb0ef41Sopenharmony_ci                                    std::unique_ptr<Deletable> object) {
3811cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(object);
3821cb0ef41Sopenharmony_ci  managed_objects_[id] = std::move(object);
3831cb0ef41Sopenharmony_ci}
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_civoid MainThreadInterface::RemoveObject(int id) {
3861cb0ef41Sopenharmony_ci  CHECK_EQ(1, managed_objects_.erase(id));
3871cb0ef41Sopenharmony_ci}
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ciDeletable* MainThreadInterface::GetObject(int id) {
3901cb0ef41Sopenharmony_ci  Deletable* pointer = GetObjectIfExists(id);
3911cb0ef41Sopenharmony_ci  // This would mean the object is requested after it was disposed, which is
3921cb0ef41Sopenharmony_ci  // a coding error.
3931cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(pointer);
3941cb0ef41Sopenharmony_ci  return pointer;
3951cb0ef41Sopenharmony_ci}
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ciDeletable* MainThreadInterface::GetObjectIfExists(int id) {
3981cb0ef41Sopenharmony_ci  auto iterator = managed_objects_.find(id);
3991cb0ef41Sopenharmony_ci  if (iterator == managed_objects_.end()) {
4001cb0ef41Sopenharmony_ci    return nullptr;
4011cb0ef41Sopenharmony_ci  }
4021cb0ef41Sopenharmony_ci  return iterator->second.get();
4031cb0ef41Sopenharmony_ci}
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_cistd::unique_ptr<InspectorSession> MainThreadHandle::Connect(
4061cb0ef41Sopenharmony_ci    std::unique_ptr<InspectorSessionDelegate> delegate,
4071cb0ef41Sopenharmony_ci    bool prevent_shutdown) {
4081cb0ef41Sopenharmony_ci  return std::unique_ptr<InspectorSession>(
4091cb0ef41Sopenharmony_ci      new CrossThreadInspectorSession(++next_session_id_,
4101cb0ef41Sopenharmony_ci                                      shared_from_this(),
4111cb0ef41Sopenharmony_ci                                      std::move(delegate),
4121cb0ef41Sopenharmony_ci                                      prevent_shutdown));
4131cb0ef41Sopenharmony_ci}
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_cibool MainThreadHandle::Post(std::unique_ptr<Request> request) {
4161cb0ef41Sopenharmony_ci  Mutex::ScopedLock scoped_lock(block_lock_);
4171cb0ef41Sopenharmony_ci  if (!main_thread_)
4181cb0ef41Sopenharmony_ci    return false;
4191cb0ef41Sopenharmony_ci  main_thread_->Post(std::move(request));
4201cb0ef41Sopenharmony_ci  return true;
4211cb0ef41Sopenharmony_ci}
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_civoid MainThreadHandle::Reset() {
4241cb0ef41Sopenharmony_ci  Mutex::ScopedLock scoped_lock(block_lock_);
4251cb0ef41Sopenharmony_ci  main_thread_ = nullptr;
4261cb0ef41Sopenharmony_ci}
4271cb0ef41Sopenharmony_ci}  // namespace
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_cinamespace {
4301cb0ef41Sopenharmony_ciusing node::CheckedUvLoopClose;
4311cb0ef41Sopenharmony_ciusing node::GetHumanReadableProcessName;
4321cb0ef41Sopenharmony_ciusing node::InspectPublishUid;
4331cb0ef41Sopenharmony_ciusing node::RegisterSignalHandler;
4341cb0ef41Sopenharmony_ciusing node::inspector::FormatWsAddress;
4351cb0ef41Sopenharmony_ciusing node::inspector::InspectorSocketServer;
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_cinamespace crypto = node::crypto;
4381cb0ef41Sopenharmony_cinamespace protocol = node::inspector::protocol;
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ci// kKill closes connections and stops the server, kStop only stops the server
4411cb0ef41Sopenharmony_cienum class TransportAction { kKill, kSendMessage, kStop };
4421cb0ef41Sopenharmony_ci
4431cb0ef41Sopenharmony_cistd::string ScriptPath(uv_loop_t* loop, const std::string& script_name) {
4441cb0ef41Sopenharmony_ci  std::string script_path;
4451cb0ef41Sopenharmony_ci
4461cb0ef41Sopenharmony_ci  if (!script_name.empty()) {
4471cb0ef41Sopenharmony_ci    uv_fs_t req;
4481cb0ef41Sopenharmony_ci    req.ptr = nullptr;
4491cb0ef41Sopenharmony_ci    if (0 == uv_fs_realpath(loop, &req, script_name.c_str(), nullptr)) {
4501cb0ef41Sopenharmony_ci      CHECK_NOT_NULL(req.ptr);
4511cb0ef41Sopenharmony_ci      script_path = std::string(static_cast<char*>(req.ptr));
4521cb0ef41Sopenharmony_ci    }
4531cb0ef41Sopenharmony_ci    uv_fs_req_cleanup(&req);
4541cb0ef41Sopenharmony_ci  }
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  return script_path;
4571cb0ef41Sopenharmony_ci}
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci// UUID RFC: https://www.ietf.org/rfc/rfc4122.txt
4601cb0ef41Sopenharmony_ci// Used ver 4 - with numbers
4611cb0ef41Sopenharmony_cistd::string GenerateID() {
4621cb0ef41Sopenharmony_ci  uint16_t buffer[8];
4631cb0ef41Sopenharmony_ci  CHECK(crypto::CSPRNG(buffer, sizeof(buffer)).is_ok());
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ci  char uuid[256];
4661cb0ef41Sopenharmony_ci  snprintf(uuid, sizeof(uuid), "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
4671cb0ef41Sopenharmony_ci           buffer[0],  // time_low
4681cb0ef41Sopenharmony_ci           buffer[1],  // time_mid
4691cb0ef41Sopenharmony_ci           buffer[2],  // time_low
4701cb0ef41Sopenharmony_ci           (buffer[3] & 0x0fff) | 0x4000,  // time_hi_and_version
4711cb0ef41Sopenharmony_ci           (buffer[4] & 0x3fff) | 0x8000,  // clk_seq_hi clk_seq_low
4721cb0ef41Sopenharmony_ci           buffer[5],  // node
4731cb0ef41Sopenharmony_ci           buffer[6],
4741cb0ef41Sopenharmony_ci           buffer[7]);
4751cb0ef41Sopenharmony_ci  return uuid;
4761cb0ef41Sopenharmony_ci}
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ciclass RequestToServer {
4791cb0ef41Sopenharmony_ci public:
4801cb0ef41Sopenharmony_ci  RequestToServer(TransportAction action,
4811cb0ef41Sopenharmony_ci                  int session_id,
4821cb0ef41Sopenharmony_ci                  std::unique_ptr<v8_inspector::StringBuffer> message)
4831cb0ef41Sopenharmony_ci                  : action_(action),
4841cb0ef41Sopenharmony_ci                    session_id_(session_id),
4851cb0ef41Sopenharmony_ci                    message_(std::move(message)) {}
4861cb0ef41Sopenharmony_ci
4871cb0ef41Sopenharmony_ci  void Dispatch(InspectorSocketServer* server) const {
4881cb0ef41Sopenharmony_ci    switch (action_) {
4891cb0ef41Sopenharmony_ci      case TransportAction::kKill:
4901cb0ef41Sopenharmony_ci        server->TerminateConnections();
4911cb0ef41Sopenharmony_ci        [[fallthrough]];
4921cb0ef41Sopenharmony_ci      case TransportAction::kStop:
4931cb0ef41Sopenharmony_ci        server->Stop();
4941cb0ef41Sopenharmony_ci        break;
4951cb0ef41Sopenharmony_ci      case TransportAction::kSendMessage:
4961cb0ef41Sopenharmony_ci        server->Send(
4971cb0ef41Sopenharmony_ci            session_id_,
4981cb0ef41Sopenharmony_ci            protocol::StringUtil::StringViewToUtf8(message_->string()));
4991cb0ef41Sopenharmony_ci        break;
5001cb0ef41Sopenharmony_ci    }
5011cb0ef41Sopenharmony_ci  }
5021cb0ef41Sopenharmony_ci
5031cb0ef41Sopenharmony_ci private:
5041cb0ef41Sopenharmony_ci  TransportAction action_;
5051cb0ef41Sopenharmony_ci  int session_id_;
5061cb0ef41Sopenharmony_ci  std::unique_ptr<v8_inspector::StringBuffer> message_;
5071cb0ef41Sopenharmony_ci};
5081cb0ef41Sopenharmony_ci
5091cb0ef41Sopenharmony_ciclass RequestQueue;
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_ciclass RequestQueueData {
5121cb0ef41Sopenharmony_ci public:
5131cb0ef41Sopenharmony_ci  using MessageQueue = std::deque<RequestToServer>;
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_ci  explicit RequestQueueData(uv_loop_t* loop)
5161cb0ef41Sopenharmony_ci                            : handle_(std::make_shared<RequestQueue>(this)) {
5171cb0ef41Sopenharmony_ci    int err = uv_async_init(loop, &async_, [](uv_async_t* async) {
5181cb0ef41Sopenharmony_ci      RequestQueueData* wrapper =
5191cb0ef41Sopenharmony_ci          node::ContainerOf(&RequestQueueData::async_, async);
5201cb0ef41Sopenharmony_ci      wrapper->DoDispatch();
5211cb0ef41Sopenharmony_ci    });
5221cb0ef41Sopenharmony_ci    CHECK_EQ(0, err);
5231cb0ef41Sopenharmony_ci  }
5241cb0ef41Sopenharmony_ci
5251cb0ef41Sopenharmony_ci  static void CloseAndFree(RequestQueueData* queue);
5261cb0ef41Sopenharmony_ci
5271cb0ef41Sopenharmony_ci  void Post(int session_id,
5281cb0ef41Sopenharmony_ci            TransportAction action,
5291cb0ef41Sopenharmony_ci            std::unique_ptr<StringBuffer> message) {
5301cb0ef41Sopenharmony_ci    Mutex::ScopedLock scoped_lock(state_lock_);
5311cb0ef41Sopenharmony_ci    bool notify = messages_.empty();
5321cb0ef41Sopenharmony_ci    messages_.emplace_back(action, session_id, std::move(message));
5331cb0ef41Sopenharmony_ci    if (notify) {
5341cb0ef41Sopenharmony_ci      CHECK_EQ(0, uv_async_send(&async_));
5351cb0ef41Sopenharmony_ci      incoming_message_cond_.Broadcast(scoped_lock);
5361cb0ef41Sopenharmony_ci    }
5371cb0ef41Sopenharmony_ci  }
5381cb0ef41Sopenharmony_ci
5391cb0ef41Sopenharmony_ci  void Wait() {
5401cb0ef41Sopenharmony_ci    Mutex::ScopedLock scoped_lock(state_lock_);
5411cb0ef41Sopenharmony_ci    if (messages_.empty()) {
5421cb0ef41Sopenharmony_ci      incoming_message_cond_.Wait(scoped_lock);
5431cb0ef41Sopenharmony_ci    }
5441cb0ef41Sopenharmony_ci  }
5451cb0ef41Sopenharmony_ci
5461cb0ef41Sopenharmony_ci  void SetServer(InspectorSocketServer* server) {
5471cb0ef41Sopenharmony_ci    server_ = server;
5481cb0ef41Sopenharmony_ci  }
5491cb0ef41Sopenharmony_ci
5501cb0ef41Sopenharmony_ci  std::shared_ptr<RequestQueue> handle() {
5511cb0ef41Sopenharmony_ci    return handle_;
5521cb0ef41Sopenharmony_ci  }
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci private:
5551cb0ef41Sopenharmony_ci  ~RequestQueueData() = default;
5561cb0ef41Sopenharmony_ci
5571cb0ef41Sopenharmony_ci  MessageQueue GetMessages() {
5581cb0ef41Sopenharmony_ci    Mutex::ScopedLock scoped_lock(state_lock_);
5591cb0ef41Sopenharmony_ci    MessageQueue messages;
5601cb0ef41Sopenharmony_ci    messages_.swap(messages);
5611cb0ef41Sopenharmony_ci    return messages;
5621cb0ef41Sopenharmony_ci  }
5631cb0ef41Sopenharmony_ci
5641cb0ef41Sopenharmony_ci  void DoDispatch() {
5651cb0ef41Sopenharmony_ci    if (server_ == nullptr)
5661cb0ef41Sopenharmony_ci      return;
5671cb0ef41Sopenharmony_ci    for (const auto& request : GetMessages()) {
5681cb0ef41Sopenharmony_ci      request.Dispatch(server_);
5691cb0ef41Sopenharmony_ci    }
5701cb0ef41Sopenharmony_ci  }
5711cb0ef41Sopenharmony_ci
5721cb0ef41Sopenharmony_ci  std::shared_ptr<RequestQueue> handle_;
5731cb0ef41Sopenharmony_ci  uv_async_t async_;
5741cb0ef41Sopenharmony_ci  InspectorSocketServer* server_ = nullptr;
5751cb0ef41Sopenharmony_ci  MessageQueue messages_;
5761cb0ef41Sopenharmony_ci  Mutex state_lock_;  // Locked before mutating the queue.
5771cb0ef41Sopenharmony_ci  ConditionVariable incoming_message_cond_;
5781cb0ef41Sopenharmony_ci};
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ciclass RequestQueue {
5811cb0ef41Sopenharmony_ci public:
5821cb0ef41Sopenharmony_ci  explicit RequestQueue(RequestQueueData* data) : data_(data) {}
5831cb0ef41Sopenharmony_ci
5841cb0ef41Sopenharmony_ci  void Reset() {
5851cb0ef41Sopenharmony_ci    Mutex::ScopedLock scoped_lock(lock_);
5861cb0ef41Sopenharmony_ci    data_ = nullptr;
5871cb0ef41Sopenharmony_ci  }
5881cb0ef41Sopenharmony_ci
5891cb0ef41Sopenharmony_ci  void Post(int session_id,
5901cb0ef41Sopenharmony_ci            TransportAction action,
5911cb0ef41Sopenharmony_ci            std::unique_ptr<StringBuffer> message) {
5921cb0ef41Sopenharmony_ci    Mutex::ScopedLock scoped_lock(lock_);
5931cb0ef41Sopenharmony_ci    if (data_ != nullptr)
5941cb0ef41Sopenharmony_ci      data_->Post(session_id, action, std::move(message));
5951cb0ef41Sopenharmony_ci  }
5961cb0ef41Sopenharmony_ci
5971cb0ef41Sopenharmony_ci  bool Expired() {
5981cb0ef41Sopenharmony_ci    Mutex::ScopedLock scoped_lock(lock_);
5991cb0ef41Sopenharmony_ci    return data_ == nullptr;
6001cb0ef41Sopenharmony_ci  }
6011cb0ef41Sopenharmony_ci
6021cb0ef41Sopenharmony_ci private:
6031cb0ef41Sopenharmony_ci  RequestQueueData* data_;
6041cb0ef41Sopenharmony_ci  Mutex lock_;
6051cb0ef41Sopenharmony_ci};
6061cb0ef41Sopenharmony_ci
6071cb0ef41Sopenharmony_ciclass IoSessionDelegate : public InspectorSessionDelegate {
6081cb0ef41Sopenharmony_ci public:
6091cb0ef41Sopenharmony_ci  explicit IoSessionDelegate(std::shared_ptr<RequestQueue> queue, int id)
6101cb0ef41Sopenharmony_ci                             : request_queue_(queue), id_(id) { }
6111cb0ef41Sopenharmony_ci  void SendMessageToFrontend(const v8_inspector::StringView& message) override {
6121cb0ef41Sopenharmony_ci    request_queue_->Post(id_, TransportAction::kSendMessage,
6131cb0ef41Sopenharmony_ci                         StringBuffer::create(message));
6141cb0ef41Sopenharmony_ci  }
6151cb0ef41Sopenharmony_ci
6161cb0ef41Sopenharmony_ci private:
6171cb0ef41Sopenharmony_ci  std::shared_ptr<RequestQueue> request_queue_;
6181cb0ef41Sopenharmony_ci  int id_;
6191cb0ef41Sopenharmony_ci};
6201cb0ef41Sopenharmony_ci
6211cb0ef41Sopenharmony_ci// Passed to InspectorSocketServer to handle WS inspector protocol events,
6221cb0ef41Sopenharmony_ci// mostly session start, message received, and session end.
6231cb0ef41Sopenharmony_ciclass InspectorIoDelegate: public node::inspector::SocketServerDelegate {
6241cb0ef41Sopenharmony_ci public:
6251cb0ef41Sopenharmony_ci  InspectorIoDelegate(std::shared_ptr<RequestQueueData> queue,
6261cb0ef41Sopenharmony_ci                      std::shared_ptr<MainThreadHandle> main_thread,
6271cb0ef41Sopenharmony_ci                      const std::string& target_id,
6281cb0ef41Sopenharmony_ci                      const std::string& script_path,
6291cb0ef41Sopenharmony_ci                      const std::string& script_name);
6301cb0ef41Sopenharmony_ci  ~InspectorIoDelegate() override = default;
6311cb0ef41Sopenharmony_ci
6321cb0ef41Sopenharmony_ci  void StartSession(int session_id, const std::string& target_id) override;
6331cb0ef41Sopenharmony_ci  void MessageReceived(int session_id, const std::string& message) override;
6341cb0ef41Sopenharmony_ci  void EndSession(int session_id) override;
6351cb0ef41Sopenharmony_ci
6361cb0ef41Sopenharmony_ci  std::vector<std::string> GetTargetIds() override;
6371cb0ef41Sopenharmony_ci  std::string GetTargetTitle(const std::string& id) override;
6381cb0ef41Sopenharmony_ci  std::string GetTargetUrl(const std::string& id) override;
6391cb0ef41Sopenharmony_ci  void AssignServer(InspectorSocketServer* server) override {
6401cb0ef41Sopenharmony_ci    request_queue_->SetServer(server);
6411cb0ef41Sopenharmony_ci  }
6421cb0ef41Sopenharmony_ci
6431cb0ef41Sopenharmony_ci private:
6441cb0ef41Sopenharmony_ci  std::shared_ptr<RequestQueueData> request_queue_;
6451cb0ef41Sopenharmony_ci  std::shared_ptr<MainThreadHandle> main_thread_;
6461cb0ef41Sopenharmony_ci  std::unordered_map<int, std::unique_ptr<InspectorSession>> sessions_;
6471cb0ef41Sopenharmony_ci  const std::string script_name_;
6481cb0ef41Sopenharmony_ci  const std::string script_path_;
6491cb0ef41Sopenharmony_ci  const std::string target_id_;
6501cb0ef41Sopenharmony_ci};
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_ciInspectorIoDelegate::InspectorIoDelegate(
6531cb0ef41Sopenharmony_ci    std::shared_ptr<RequestQueueData> queue,
6541cb0ef41Sopenharmony_ci    std::shared_ptr<MainThreadHandle> main_thread,
6551cb0ef41Sopenharmony_ci    const std::string& target_id,
6561cb0ef41Sopenharmony_ci    const std::string& script_path,
6571cb0ef41Sopenharmony_ci    const std::string& script_name)
6581cb0ef41Sopenharmony_ci    : request_queue_(queue), main_thread_(main_thread),
6591cb0ef41Sopenharmony_ci      script_name_(script_name), script_path_(script_path),
6601cb0ef41Sopenharmony_ci      target_id_(target_id) {}
6611cb0ef41Sopenharmony_ci
6621cb0ef41Sopenharmony_civoid InspectorIoDelegate::StartSession(int session_id,
6631cb0ef41Sopenharmony_ci                                       const std::string& target_id) {
6641cb0ef41Sopenharmony_ci  auto session = main_thread_->Connect(
6651cb0ef41Sopenharmony_ci      std::unique_ptr<InspectorSessionDelegate>(
6661cb0ef41Sopenharmony_ci          new IoSessionDelegate(request_queue_->handle(), session_id)), true);
6671cb0ef41Sopenharmony_ci  if (session) {
6681cb0ef41Sopenharmony_ci    sessions_[session_id] = std::move(session);
6691cb0ef41Sopenharmony_ci    fprintf(stderr, "Debugger attached.\n");
6701cb0ef41Sopenharmony_ci  }
6711cb0ef41Sopenharmony_ci}
6721cb0ef41Sopenharmony_ci
6731cb0ef41Sopenharmony_civoid InspectorIoDelegate::MessageReceived(int session_id,
6741cb0ef41Sopenharmony_ci                                          const std::string& message) {
6751cb0ef41Sopenharmony_ci  auto session = sessions_.find(session_id);
6761cb0ef41Sopenharmony_ci  if (session != sessions_.end())
6771cb0ef41Sopenharmony_ci    session->second->Dispatch(Utf8ToStringView(message)->string());
6781cb0ef41Sopenharmony_ci}
6791cb0ef41Sopenharmony_ci
6801cb0ef41Sopenharmony_civoid InspectorIoDelegate::EndSession(int session_id) {
6811cb0ef41Sopenharmony_ci  sessions_.erase(session_id);
6821cb0ef41Sopenharmony_ci}
6831cb0ef41Sopenharmony_ci
6841cb0ef41Sopenharmony_cistd::vector<std::string> InspectorIoDelegate::GetTargetIds() {
6851cb0ef41Sopenharmony_ci  return { target_id_ };
6861cb0ef41Sopenharmony_ci}
6871cb0ef41Sopenharmony_ci
6881cb0ef41Sopenharmony_cistd::string InspectorIoDelegate::GetTargetTitle(const std::string& id) {
6891cb0ef41Sopenharmony_ci  return script_name_.empty() ? GetHumanReadableProcessName() : script_name_;
6901cb0ef41Sopenharmony_ci}
6911cb0ef41Sopenharmony_ci
6921cb0ef41Sopenharmony_cistd::string InspectorIoDelegate::GetTargetUrl(const std::string& id) {
6931cb0ef41Sopenharmony_ci  return "file://" + script_path_;
6941cb0ef41Sopenharmony_ci}
6951cb0ef41Sopenharmony_ci
6961cb0ef41Sopenharmony_ci// static
6971cb0ef41Sopenharmony_civoid RequestQueueData::CloseAndFree(RequestQueueData* queue) {
6981cb0ef41Sopenharmony_ci  queue->handle_->Reset();
6991cb0ef41Sopenharmony_ci  queue->handle_.reset();
7001cb0ef41Sopenharmony_ci  uv_close(reinterpret_cast<uv_handle_t*>(&queue->async_),
7011cb0ef41Sopenharmony_ci           [](uv_handle_t* handle) {
7021cb0ef41Sopenharmony_ci    uv_async_t* async = reinterpret_cast<uv_async_t*>(handle);
7031cb0ef41Sopenharmony_ci    RequestQueueData* wrapper =
7041cb0ef41Sopenharmony_ci        node::ContainerOf(&RequestQueueData::async_, async);
7051cb0ef41Sopenharmony_ci    delete wrapper;
7061cb0ef41Sopenharmony_ci  });
7071cb0ef41Sopenharmony_ci}
7081cb0ef41Sopenharmony_ci}  // namespace
7091cb0ef41Sopenharmony_ci
7101cb0ef41Sopenharmony_ciclass InspectorIo {
7111cb0ef41Sopenharmony_ci public:
7121cb0ef41Sopenharmony_ci  // Start the inspector agent thread, waiting for it to initialize
7131cb0ef41Sopenharmony_ci  // bool Start();
7141cb0ef41Sopenharmony_ci  // Returns empty pointer if thread was not started
7151cb0ef41Sopenharmony_ci  static std::unique_ptr<InspectorIo> Start(
7161cb0ef41Sopenharmony_ci      std::shared_ptr<MainThreadHandle> main_thread,
7171cb0ef41Sopenharmony_ci      const std::string& path,
7181cb0ef41Sopenharmony_ci      std::shared_ptr<ExclusiveAccess<HostPort>> host_port,
7191cb0ef41Sopenharmony_ci      const node::InspectPublishUid& inspect_publish_uid);
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci  // Will block till the transport thread shuts down
7221cb0ef41Sopenharmony_ci  ~InspectorIo();
7231cb0ef41Sopenharmony_ci
7241cb0ef41Sopenharmony_ci  void StopAcceptingNewConnections();
7251cb0ef41Sopenharmony_ci  std::string GetWsUrl() const;
7261cb0ef41Sopenharmony_ci
7271cb0ef41Sopenharmony_ci private:
7281cb0ef41Sopenharmony_ci  InspectorIo(std::shared_ptr<MainThreadHandle> handle,
7291cb0ef41Sopenharmony_ci              const std::string& path,
7301cb0ef41Sopenharmony_ci              std::shared_ptr<ExclusiveAccess<HostPort>> host_port,
7311cb0ef41Sopenharmony_ci              const node::InspectPublishUid& inspect_publish_uid);
7321cb0ef41Sopenharmony_ci
7331cb0ef41Sopenharmony_ci  // Wrapper for agent->ThreadMain()
7341cb0ef41Sopenharmony_ci  static void ThreadMain(void* agent);
7351cb0ef41Sopenharmony_ci
7361cb0ef41Sopenharmony_ci  // Runs a uv_loop_t
7371cb0ef41Sopenharmony_ci  void ThreadMain();
7381cb0ef41Sopenharmony_ci
7391cb0ef41Sopenharmony_ci  // This is a thread-safe object that will post async tasks. It lives as long
7401cb0ef41Sopenharmony_ci  // as an Inspector object lives (almost as long as an Isolate).
7411cb0ef41Sopenharmony_ci  std::shared_ptr<MainThreadHandle> main_thread_;
7421cb0ef41Sopenharmony_ci  // Used to post on a frontend interface thread, lives while the server is
7431cb0ef41Sopenharmony_ci  // running
7441cb0ef41Sopenharmony_ci  std::shared_ptr<RequestQueue> request_queue_;
7451cb0ef41Sopenharmony_ci  std::shared_ptr<ExclusiveAccess<HostPort>> host_port_;
7461cb0ef41Sopenharmony_ci  node::InspectPublishUid inspect_publish_uid_;
7471cb0ef41Sopenharmony_ci
7481cb0ef41Sopenharmony_ci  // The IO thread runs its own uv_loop to implement the TCP server off
7491cb0ef41Sopenharmony_ci  // the main thread.
7501cb0ef41Sopenharmony_ci  uv_thread_t thread_;
7511cb0ef41Sopenharmony_ci
7521cb0ef41Sopenharmony_ci  // For setting up interthread communications
7531cb0ef41Sopenharmony_ci  Mutex thread_start_lock_;
7541cb0ef41Sopenharmony_ci  node::ConditionVariable thread_start_condition_;
7551cb0ef41Sopenharmony_ci  std::string script_name_;
7561cb0ef41Sopenharmony_ci  // May be accessed from any thread
7571cb0ef41Sopenharmony_ci  const std::string id_;
7581cb0ef41Sopenharmony_ci};
7591cb0ef41Sopenharmony_ci
7601cb0ef41Sopenharmony_ci// static
7611cb0ef41Sopenharmony_cistd::unique_ptr<InspectorIo> InspectorIo::Start(
7621cb0ef41Sopenharmony_ci    std::shared_ptr<MainThreadHandle> main_thread,
7631cb0ef41Sopenharmony_ci    const std::string& path,
7641cb0ef41Sopenharmony_ci    std::shared_ptr<ExclusiveAccess<HostPort>> host_port,
7651cb0ef41Sopenharmony_ci    const InspectPublishUid& inspect_publish_uid) {
7661cb0ef41Sopenharmony_ci  auto io = std::unique_ptr<InspectorIo>(
7671cb0ef41Sopenharmony_ci      new InspectorIo(main_thread,
7681cb0ef41Sopenharmony_ci                      path,
7691cb0ef41Sopenharmony_ci                      host_port,
7701cb0ef41Sopenharmony_ci                      inspect_publish_uid));
7711cb0ef41Sopenharmony_ci  if (io->request_queue_->Expired()) {  // Thread is not running
7721cb0ef41Sopenharmony_ci    return nullptr;
7731cb0ef41Sopenharmony_ci  }
7741cb0ef41Sopenharmony_ci  return io;
7751cb0ef41Sopenharmony_ci}
7761cb0ef41Sopenharmony_ci
7771cb0ef41Sopenharmony_ciInspectorIo::InspectorIo(std::shared_ptr<MainThreadHandle> main_thread,
7781cb0ef41Sopenharmony_ci                         const std::string& path,
7791cb0ef41Sopenharmony_ci                         std::shared_ptr<ExclusiveAccess<HostPort>> host_port,
7801cb0ef41Sopenharmony_ci                         const InspectPublishUid& inspect_publish_uid)
7811cb0ef41Sopenharmony_ci    : main_thread_(main_thread),
7821cb0ef41Sopenharmony_ci      host_port_(host_port),
7831cb0ef41Sopenharmony_ci      inspect_publish_uid_(inspect_publish_uid),
7841cb0ef41Sopenharmony_ci      thread_(),
7851cb0ef41Sopenharmony_ci      script_name_(path),
7861cb0ef41Sopenharmony_ci      id_(GenerateID()) {
7871cb0ef41Sopenharmony_ci  Mutex::ScopedLock scoped_lock(thread_start_lock_);
7881cb0ef41Sopenharmony_ci  CHECK_EQ(uv_thread_create(&thread_, InspectorIo::ThreadMain, this), 0);
7891cb0ef41Sopenharmony_ci  thread_start_condition_.Wait(scoped_lock);
7901cb0ef41Sopenharmony_ci}
7911cb0ef41Sopenharmony_ci
7921cb0ef41Sopenharmony_ciInspectorIo::~InspectorIo() {
7931cb0ef41Sopenharmony_ci  request_queue_->Post(0, TransportAction::kKill, nullptr);
7941cb0ef41Sopenharmony_ci  int err = uv_thread_join(&thread_);
7951cb0ef41Sopenharmony_ci  CHECK_EQ(err, 0);
7961cb0ef41Sopenharmony_ci}
7971cb0ef41Sopenharmony_ci
7981cb0ef41Sopenharmony_civoid InspectorIo::StopAcceptingNewConnections() {
7991cb0ef41Sopenharmony_ci  request_queue_->Post(0, TransportAction::kStop, nullptr);
8001cb0ef41Sopenharmony_ci}
8011cb0ef41Sopenharmony_ci
8021cb0ef41Sopenharmony_ci// static
8031cb0ef41Sopenharmony_civoid InspectorIo::ThreadMain(void* io) {
8041cb0ef41Sopenharmony_ci  static_cast<InspectorIo*>(io)->ThreadMain();
8051cb0ef41Sopenharmony_ci}
8061cb0ef41Sopenharmony_ci
8071cb0ef41Sopenharmony_civoid InspectorIo::ThreadMain() {
8081cb0ef41Sopenharmony_ci  uv_loop_t loop;
8091cb0ef41Sopenharmony_ci  loop.data = nullptr;
8101cb0ef41Sopenharmony_ci  int err = uv_loop_init(&loop);
8111cb0ef41Sopenharmony_ci  CHECK_EQ(err, 0);
8121cb0ef41Sopenharmony_ci  std::shared_ptr<RequestQueueData> queue(new RequestQueueData(&loop),
8131cb0ef41Sopenharmony_ci                                          RequestQueueData::CloseAndFree);
8141cb0ef41Sopenharmony_ci  std::string script_path = ScriptPath(&loop, script_name_);
8151cb0ef41Sopenharmony_ci  std::unique_ptr<InspectorIoDelegate> delegate(
8161cb0ef41Sopenharmony_ci      new InspectorIoDelegate(queue, main_thread_, id_,
8171cb0ef41Sopenharmony_ci                              script_path, script_name_));
8181cb0ef41Sopenharmony_ci  std::string host;
8191cb0ef41Sopenharmony_ci  int port;
8201cb0ef41Sopenharmony_ci  int pid;
8211cb0ef41Sopenharmony_ci  {
8221cb0ef41Sopenharmony_ci    ExclusiveAccess<HostPort>::Scoped host_port(host_port_);
8231cb0ef41Sopenharmony_ci    host = host_port->host();
8241cb0ef41Sopenharmony_ci    port = host_port->port();
8251cb0ef41Sopenharmony_ci    pid = host_port->pid();
8261cb0ef41Sopenharmony_ci  }
8271cb0ef41Sopenharmony_ci  InspectorSocketServer server(std::move(delegate),
8281cb0ef41Sopenharmony_ci                               &loop,
8291cb0ef41Sopenharmony_ci                               std::move(host),
8301cb0ef41Sopenharmony_ci                               port,
8311cb0ef41Sopenharmony_ci                               inspect_publish_uid_,
8321cb0ef41Sopenharmony_ci                               stderr,
8331cb0ef41Sopenharmony_ci                               pid);
8341cb0ef41Sopenharmony_ci  request_queue_ = queue->handle();
8351cb0ef41Sopenharmony_ci  // Its lifetime is now that of the server delegate
8361cb0ef41Sopenharmony_ci  queue.reset();
8371cb0ef41Sopenharmony_ci  {
8381cb0ef41Sopenharmony_ci    Mutex::ScopedLock scoped_lock(thread_start_lock_);
8391cb0ef41Sopenharmony_ci    if (server.Start()) {
8401cb0ef41Sopenharmony_ci      ExclusiveAccess<HostPort>::Scoped host_port(host_port_);
8411cb0ef41Sopenharmony_ci      host_port->set_port(server.Port());
8421cb0ef41Sopenharmony_ci    }
8431cb0ef41Sopenharmony_ci    thread_start_condition_.Broadcast(scoped_lock);
8441cb0ef41Sopenharmony_ci  }
8451cb0ef41Sopenharmony_ci  uv_run(&loop, UV_RUN_DEFAULT);
8461cb0ef41Sopenharmony_ci  CheckedUvLoopClose(&loop);
8471cb0ef41Sopenharmony_ci}
8481cb0ef41Sopenharmony_ci
8491cb0ef41Sopenharmony_cistd::string InspectorIo::GetWsUrl() const {
8501cb0ef41Sopenharmony_ci  ExclusiveAccess<HostPort>::Scoped host_port(host_port_);
8511cb0ef41Sopenharmony_ci  return FormatWsAddress(host_port->host(), host_port->port(), id_, true);
8521cb0ef41Sopenharmony_ci}
8531cb0ef41Sopenharmony_ci
8541cb0ef41Sopenharmony_cinamespace {
8551cb0ef41Sopenharmony_ci
8561cb0ef41Sopenharmony_ciusing node::DebugCategory;
8571cb0ef41Sopenharmony_ciusing node::TwoByteValue;
8581cb0ef41Sopenharmony_ci
8591cb0ef41Sopenharmony_ciusing v8::Context;
8601cb0ef41Sopenharmony_ciusing v8::Function;
8611cb0ef41Sopenharmony_ciusing v8::HandleScope;
8621cb0ef41Sopenharmony_ciusing v8::Isolate;
8631cb0ef41Sopenharmony_ciusing v8::Local;
8641cb0ef41Sopenharmony_ciusing v8::Message;
8651cb0ef41Sopenharmony_ciusing v8::Object;
8661cb0ef41Sopenharmony_ciusing v8::Value;
8671cb0ef41Sopenharmony_ci
8681cb0ef41Sopenharmony_ciusing v8_inspector::StringBuffer;
8691cb0ef41Sopenharmony_ciusing v8_inspector::StringView;
8701cb0ef41Sopenharmony_ciusing v8_inspector::V8Inspector;
8711cb0ef41Sopenharmony_ciusing v8_inspector::V8InspectorClient;
8721cb0ef41Sopenharmony_ci
8731cb0ef41Sopenharmony_cinamespace per_process = node::per_process;
8741cb0ef41Sopenharmony_ci
8751cb0ef41Sopenharmony_cistd::unique_ptr<StringBuffer> ToProtocolString(Isolate* isolate,
8761cb0ef41Sopenharmony_ci                                               Local<Value> value) {
8771cb0ef41Sopenharmony_ci  TwoByteValue buffer(isolate, value);
8781cb0ef41Sopenharmony_ci  return StringBuffer::create(StringView(*buffer, buffer.length()));
8791cb0ef41Sopenharmony_ci}
8801cb0ef41Sopenharmony_ci
8811cb0ef41Sopenharmony_ci
8821cb0ef41Sopenharmony_ciconst int CONTEXT_GROUP_ID = 1;
8831cb0ef41Sopenharmony_ci
8841cb0ef41Sopenharmony_cistd::string GetWorkerLabel(Environment* env) {
8851cb0ef41Sopenharmony_ci  std::ostringstream result;
8861cb0ef41Sopenharmony_ci  // TODO: use thread ID as part of worker label.
8871cb0ef41Sopenharmony_ci  result << "Worker[" << "env->thread_id()" << "]";
8881cb0ef41Sopenharmony_ci  return result.str();
8891cb0ef41Sopenharmony_ci}
8901cb0ef41Sopenharmony_ci
8911cb0ef41Sopenharmony_ciclass ChannelImpl final : public v8_inspector::V8Inspector::Channel,
8921cb0ef41Sopenharmony_ci                          public protocol::FrontendChannel {
8931cb0ef41Sopenharmony_ci public:
8941cb0ef41Sopenharmony_ci  explicit ChannelImpl(const std::unique_ptr<V8Inspector>& inspector,
8951cb0ef41Sopenharmony_ci                       std::unique_ptr<InspectorSessionDelegate> delegate,
8961cb0ef41Sopenharmony_ci                       std::shared_ptr<MainThreadHandle> main_thread_,
8971cb0ef41Sopenharmony_ci                       bool prevent_shutdown)
8981cb0ef41Sopenharmony_ci      : delegate_(std::move(delegate)), prevent_shutdown_(prevent_shutdown),
8991cb0ef41Sopenharmony_ci        retaining_context_(false) {
9001cb0ef41Sopenharmony_ci    session_ = inspector->connect(CONTEXT_GROUP_ID,
9011cb0ef41Sopenharmony_ci                                  this,
9021cb0ef41Sopenharmony_ci                                  StringView(),
9031cb0ef41Sopenharmony_ci                                  V8Inspector::ClientTrustLevel::kFullyTrusted);
9041cb0ef41Sopenharmony_ci    node_dispatcher_ = std::make_unique<protocol::UberDispatcher>(this);
9051cb0ef41Sopenharmony_ci    runtime_agent_ = std::make_unique<protocol::RuntimeAgent>();
9061cb0ef41Sopenharmony_ci    runtime_agent_->Wire(node_dispatcher_.get());
9071cb0ef41Sopenharmony_ci  }
9081cb0ef41Sopenharmony_ci
9091cb0ef41Sopenharmony_ci  ~ChannelImpl() override {
9101cb0ef41Sopenharmony_ci    if (worker_agent_) {
9111cb0ef41Sopenharmony_ci      worker_agent_->disable();
9121cb0ef41Sopenharmony_ci      worker_agent_.reset();  // Dispose before the dispatchers
9131cb0ef41Sopenharmony_ci    }
9141cb0ef41Sopenharmony_ci    runtime_agent_->disable();
9151cb0ef41Sopenharmony_ci    runtime_agent_.reset();  // Dispose before the dispatchers
9161cb0ef41Sopenharmony_ci  }
9171cb0ef41Sopenharmony_ci
9181cb0ef41Sopenharmony_ci  void dispatchProtocolMessage(const StringView& message) {
9191cb0ef41Sopenharmony_ci    std::string raw_message = protocol::StringUtil::StringViewToUtf8(message);
9201cb0ef41Sopenharmony_ci    per_process::Debug(DebugCategory::INSPECTOR_SERVER,
9211cb0ef41Sopenharmony_ci                       "[inspector received] %s\n",
9221cb0ef41Sopenharmony_ci                       raw_message);
9231cb0ef41Sopenharmony_ci    std::unique_ptr<protocol::DictionaryValue> value =
9241cb0ef41Sopenharmony_ci        protocol::DictionaryValue::cast(
9251cb0ef41Sopenharmony_ci            protocol::StringUtil::parseJSON(message));
9261cb0ef41Sopenharmony_ci    int call_id;
9271cb0ef41Sopenharmony_ci    std::string method;
9281cb0ef41Sopenharmony_ci    node_dispatcher_->parseCommand(value.get(), &call_id, &method);
9291cb0ef41Sopenharmony_ci    if (v8_inspector::V8InspectorSession::canDispatchMethod(
9301cb0ef41Sopenharmony_ci            Utf8ToStringView(method)->string())) {
9311cb0ef41Sopenharmony_ci      session_->dispatchProtocolMessage(message);
9321cb0ef41Sopenharmony_ci    } else {
9331cb0ef41Sopenharmony_ci      node_dispatcher_->dispatch(call_id, method, std::move(value),
9341cb0ef41Sopenharmony_ci                                 raw_message);
9351cb0ef41Sopenharmony_ci    }
9361cb0ef41Sopenharmony_ci  }
9371cb0ef41Sopenharmony_ci
9381cb0ef41Sopenharmony_ci  void schedulePauseOnNextStatement(const std::string& reason) {
9391cb0ef41Sopenharmony_ci    std::unique_ptr<StringBuffer> buffer = Utf8ToStringView(reason);
9401cb0ef41Sopenharmony_ci    session_->schedulePauseOnNextStatement(buffer->string(), buffer->string());
9411cb0ef41Sopenharmony_ci  }
9421cb0ef41Sopenharmony_ci
9431cb0ef41Sopenharmony_ci  bool preventShutdown() {
9441cb0ef41Sopenharmony_ci    return prevent_shutdown_;
9451cb0ef41Sopenharmony_ci  }
9461cb0ef41Sopenharmony_ci
9471cb0ef41Sopenharmony_ci  bool notifyWaitingForDisconnect() {
9481cb0ef41Sopenharmony_ci    retaining_context_ = runtime_agent_->notifyWaitingForDisconnect();
9491cb0ef41Sopenharmony_ci    return retaining_context_;
9501cb0ef41Sopenharmony_ci  }
9511cb0ef41Sopenharmony_ci
9521cb0ef41Sopenharmony_ci  bool retainingContext() {
9531cb0ef41Sopenharmony_ci    return retaining_context_;
9541cb0ef41Sopenharmony_ci  }
9551cb0ef41Sopenharmony_ci
9561cb0ef41Sopenharmony_ci private:
9571cb0ef41Sopenharmony_ci  void sendResponse(
9581cb0ef41Sopenharmony_ci      int callId,
9591cb0ef41Sopenharmony_ci      std::unique_ptr<v8_inspector::StringBuffer> message) override {
9601cb0ef41Sopenharmony_ci    sendMessageToFrontend(message->string());
9611cb0ef41Sopenharmony_ci  }
9621cb0ef41Sopenharmony_ci
9631cb0ef41Sopenharmony_ci  void sendNotification(
9641cb0ef41Sopenharmony_ci      std::unique_ptr<v8_inspector::StringBuffer> message) override {
9651cb0ef41Sopenharmony_ci    sendMessageToFrontend(message->string());
9661cb0ef41Sopenharmony_ci  }
9671cb0ef41Sopenharmony_ci
9681cb0ef41Sopenharmony_ci  void flushProtocolNotifications() override { }
9691cb0ef41Sopenharmony_ci
9701cb0ef41Sopenharmony_ci  void sendMessageToFrontend(const StringView& message) {
9711cb0ef41Sopenharmony_ci    if (per_process::enabled_debug_list.enabled(
9721cb0ef41Sopenharmony_ci            DebugCategory::INSPECTOR_SERVER)) {
9731cb0ef41Sopenharmony_ci      std::string raw_message = protocol::StringUtil::StringViewToUtf8(message);
9741cb0ef41Sopenharmony_ci      per_process::Debug(DebugCategory::INSPECTOR_SERVER,
9751cb0ef41Sopenharmony_ci                         "[inspector send] %s\n",
9761cb0ef41Sopenharmony_ci                         raw_message);
9771cb0ef41Sopenharmony_ci    }
9781cb0ef41Sopenharmony_ci    delegate_->SendMessageToFrontend(message);
9791cb0ef41Sopenharmony_ci  }
9801cb0ef41Sopenharmony_ci
9811cb0ef41Sopenharmony_ci  void sendMessageToFrontend(const std::string& message) {
9821cb0ef41Sopenharmony_ci    sendMessageToFrontend(Utf8ToStringView(message)->string());
9831cb0ef41Sopenharmony_ci  }
9841cb0ef41Sopenharmony_ci
9851cb0ef41Sopenharmony_ci  using Serializable = protocol::Serializable;
9861cb0ef41Sopenharmony_ci
9871cb0ef41Sopenharmony_ci  void sendProtocolResponse(int callId,
9881cb0ef41Sopenharmony_ci                            std::unique_ptr<Serializable> message) override {
9891cb0ef41Sopenharmony_ci    sendMessageToFrontend(message->serializeToJSON());
9901cb0ef41Sopenharmony_ci  }
9911cb0ef41Sopenharmony_ci  void sendProtocolNotification(
9921cb0ef41Sopenharmony_ci      std::unique_ptr<Serializable> message) override {
9931cb0ef41Sopenharmony_ci    sendMessageToFrontend(message->serializeToJSON());
9941cb0ef41Sopenharmony_ci  }
9951cb0ef41Sopenharmony_ci
9961cb0ef41Sopenharmony_ci  void fallThrough(int callId,
9971cb0ef41Sopenharmony_ci                   const std::string& method,
9981cb0ef41Sopenharmony_ci                   const std::string& message) override {
9991cb0ef41Sopenharmony_ci    DCHECK(false);
10001cb0ef41Sopenharmony_ci  }
10011cb0ef41Sopenharmony_ci
10021cb0ef41Sopenharmony_ci  std::unique_ptr<protocol::RuntimeAgent> runtime_agent_;
10031cb0ef41Sopenharmony_ci  std::unique_ptr<protocol::WorkerAgent> worker_agent_;
10041cb0ef41Sopenharmony_ci  std::unique_ptr<InspectorSessionDelegate> delegate_;
10051cb0ef41Sopenharmony_ci  std::unique_ptr<v8_inspector::V8InspectorSession> session_;
10061cb0ef41Sopenharmony_ci  std::unique_ptr<protocol::UberDispatcher> node_dispatcher_;
10071cb0ef41Sopenharmony_ci  bool prevent_shutdown_;
10081cb0ef41Sopenharmony_ci  bool retaining_context_;
10091cb0ef41Sopenharmony_ci};
10101cb0ef41Sopenharmony_ci
10111cb0ef41Sopenharmony_ciclass SameThreadInspectorSession : public InspectorSession {
10121cb0ef41Sopenharmony_ci public:
10131cb0ef41Sopenharmony_ci  SameThreadInspectorSession(
10141cb0ef41Sopenharmony_ci      int session_id, std::shared_ptr<InspectorClient> client)
10151cb0ef41Sopenharmony_ci      : session_id_(session_id), client_(client) {}
10161cb0ef41Sopenharmony_ci  ~SameThreadInspectorSession() override;
10171cb0ef41Sopenharmony_ci  void Dispatch(const v8_inspector::StringView& message) override;
10181cb0ef41Sopenharmony_ci
10191cb0ef41Sopenharmony_ci private:
10201cb0ef41Sopenharmony_ci  int session_id_;
10211cb0ef41Sopenharmony_ci  std::weak_ptr<InspectorClient> client_;
10221cb0ef41Sopenharmony_ci};
10231cb0ef41Sopenharmony_ci
10241cb0ef41Sopenharmony_cibool IsFilePath(const std::string& path) {
10251cb0ef41Sopenharmony_ci  return !path.empty() && path[0] == '/';
10261cb0ef41Sopenharmony_ci}
10271cb0ef41Sopenharmony_ci
10281cb0ef41Sopenharmony_civoid ThrowUninitializedInspectorError(Environment* env) {
10291cb0ef41Sopenharmony_ci  HandleScope scope(env->isolate);
10301cb0ef41Sopenharmony_ci
10311cb0ef41Sopenharmony_ci  const char* msg = "This Environment was initialized without a V8::Inspector";
10321cb0ef41Sopenharmony_ci  Local<Value> exception =
10331cb0ef41Sopenharmony_ci    v8::String::NewFromUtf8(env->isolate, msg).ToLocalChecked();
10341cb0ef41Sopenharmony_ci
10351cb0ef41Sopenharmony_ci  env->isolate->ThrowException(exception);
10361cb0ef41Sopenharmony_ci}
10371cb0ef41Sopenharmony_ci
10381cb0ef41Sopenharmony_ci}  // namespace
10391cb0ef41Sopenharmony_ci
10401cb0ef41Sopenharmony_ciclass InspectorClient : public V8InspectorClient {
10411cb0ef41Sopenharmony_ci public:
10421cb0ef41Sopenharmony_ci  explicit InspectorClient(Environment* env, bool is_main)
10431cb0ef41Sopenharmony_ci      : env_(env), is_main_(is_main) {
10441cb0ef41Sopenharmony_ci    client_ = V8Inspector::create(env->isolate, this);
10451cb0ef41Sopenharmony_ci    // TODO(bnoordhuis) Make name configurable from src/node.cc.
10461cb0ef41Sopenharmony_ci    std::string name =
10471cb0ef41Sopenharmony_ci        is_main_ ? GetHumanReadableProcessName() : GetWorkerLabel(env);
10481cb0ef41Sopenharmony_ci    ContextInfo info(name);
10491cb0ef41Sopenharmony_ci    info.is_default = true;
10501cb0ef41Sopenharmony_ci    contextCreated(env->context(), info);
10511cb0ef41Sopenharmony_ci  }
10521cb0ef41Sopenharmony_ci
10531cb0ef41Sopenharmony_ci  void runMessageLoopOnPause(int context_group_id) override {
10541cb0ef41Sopenharmony_ci    waiting_for_resume_ = true;
10551cb0ef41Sopenharmony_ci    runMessageLoop();
10561cb0ef41Sopenharmony_ci  }
10571cb0ef41Sopenharmony_ci
10581cb0ef41Sopenharmony_ci  void waitForSessionsDisconnect() {
10591cb0ef41Sopenharmony_ci    waiting_for_sessions_disconnect_ = true;
10601cb0ef41Sopenharmony_ci    runMessageLoop();
10611cb0ef41Sopenharmony_ci  }
10621cb0ef41Sopenharmony_ci
10631cb0ef41Sopenharmony_ci  void waitForFrontend() {
10641cb0ef41Sopenharmony_ci    waiting_for_frontend_ = true;
10651cb0ef41Sopenharmony_ci    runMessageLoop();
10661cb0ef41Sopenharmony_ci  }
10671cb0ef41Sopenharmony_ci
10681cb0ef41Sopenharmony_ci  void maxAsyncCallStackDepthChanged(int depth) override {
10691cb0ef41Sopenharmony_ci    if (waiting_for_sessions_disconnect_) {
10701cb0ef41Sopenharmony_ci      // V8 isolate is mostly done and is only letting Inspector protocol
10711cb0ef41Sopenharmony_ci      // clients gather data.
10721cb0ef41Sopenharmony_ci      return;
10731cb0ef41Sopenharmony_ci    }
10741cb0ef41Sopenharmony_ci  }
10751cb0ef41Sopenharmony_ci
10761cb0ef41Sopenharmony_ci  void contextCreated(Local<Context> context, const ContextInfo& info) {
10771cb0ef41Sopenharmony_ci    auto name_buffer = Utf8ToStringView(info.name);
10781cb0ef41Sopenharmony_ci    auto origin_buffer = Utf8ToStringView(info.origin);
10791cb0ef41Sopenharmony_ci    std::unique_ptr<StringBuffer> aux_data_buffer;
10801cb0ef41Sopenharmony_ci
10811cb0ef41Sopenharmony_ci    v8_inspector::V8ContextInfo v8info(
10821cb0ef41Sopenharmony_ci        context, CONTEXT_GROUP_ID, name_buffer->string());
10831cb0ef41Sopenharmony_ci    v8info.origin = origin_buffer->string();
10841cb0ef41Sopenharmony_ci
10851cb0ef41Sopenharmony_ci    if (info.is_default) {
10861cb0ef41Sopenharmony_ci      aux_data_buffer = Utf8ToStringView("{\"isDefault\":true}");
10871cb0ef41Sopenharmony_ci    } else {
10881cb0ef41Sopenharmony_ci      aux_data_buffer = Utf8ToStringView("{\"isDefault\":false}");
10891cb0ef41Sopenharmony_ci    }
10901cb0ef41Sopenharmony_ci    v8info.auxData = aux_data_buffer->string();
10911cb0ef41Sopenharmony_ci
10921cb0ef41Sopenharmony_ci    client_->contextCreated(v8info);
10931cb0ef41Sopenharmony_ci  }
10941cb0ef41Sopenharmony_ci
10951cb0ef41Sopenharmony_ci  void contextDestroyed(Local<Context> context) {
10961cb0ef41Sopenharmony_ci    client_->contextDestroyed(context);
10971cb0ef41Sopenharmony_ci  }
10981cb0ef41Sopenharmony_ci
10991cb0ef41Sopenharmony_ci  void quitMessageLoopOnPause() override {
11001cb0ef41Sopenharmony_ci    waiting_for_resume_ = false;
11011cb0ef41Sopenharmony_ci  }
11021cb0ef41Sopenharmony_ci
11031cb0ef41Sopenharmony_ci  void runIfWaitingForDebugger(int context_group_id) override {
11041cb0ef41Sopenharmony_ci    waiting_for_frontend_ = false;
11051cb0ef41Sopenharmony_ci  }
11061cb0ef41Sopenharmony_ci
11071cb0ef41Sopenharmony_ci  int connectFrontend(std::unique_ptr<InspectorSessionDelegate> delegate,
11081cb0ef41Sopenharmony_ci                      bool prevent_shutdown) {
11091cb0ef41Sopenharmony_ci    int session_id = next_session_id_++;
11101cb0ef41Sopenharmony_ci    channels_[session_id] = std::make_unique<ChannelImpl>(client_,
11111cb0ef41Sopenharmony_ci                                                          std::move(delegate),
11121cb0ef41Sopenharmony_ci                                                          getThreadHandle(),
11131cb0ef41Sopenharmony_ci                                                          prevent_shutdown);
11141cb0ef41Sopenharmony_ci    return session_id;
11151cb0ef41Sopenharmony_ci  }
11161cb0ef41Sopenharmony_ci
11171cb0ef41Sopenharmony_ci  void disconnectFrontend(int session_id) {
11181cb0ef41Sopenharmony_ci    auto it = channels_.find(session_id);
11191cb0ef41Sopenharmony_ci    if (it == channels_.end())
11201cb0ef41Sopenharmony_ci      return;
11211cb0ef41Sopenharmony_ci    bool retaining_context = it->second->retainingContext();
11221cb0ef41Sopenharmony_ci    channels_.erase(it);
11231cb0ef41Sopenharmony_ci    if (retaining_context) {
11241cb0ef41Sopenharmony_ci      for (const auto& id_channel : channels_) {
11251cb0ef41Sopenharmony_ci        if (id_channel.second->retainingContext())
11261cb0ef41Sopenharmony_ci          return;
11271cb0ef41Sopenharmony_ci      }
11281cb0ef41Sopenharmony_ci      contextDestroyed(env_->context());
11291cb0ef41Sopenharmony_ci    }
11301cb0ef41Sopenharmony_ci    if (waiting_for_sessions_disconnect_ && !is_main_)
11311cb0ef41Sopenharmony_ci      waiting_for_sessions_disconnect_ = false;
11321cb0ef41Sopenharmony_ci  }
11331cb0ef41Sopenharmony_ci
11341cb0ef41Sopenharmony_ci  void dispatchMessageFromFrontend(int session_id, const StringView& message) {
11351cb0ef41Sopenharmony_ci    channels_[session_id]->dispatchProtocolMessage(message);
11361cb0ef41Sopenharmony_ci  }
11371cb0ef41Sopenharmony_ci
11381cb0ef41Sopenharmony_ci  Local<Context> ensureDefaultContextInGroup(int contextGroupId) override {
11391cb0ef41Sopenharmony_ci    return env_->context();
11401cb0ef41Sopenharmony_ci  }
11411cb0ef41Sopenharmony_ci
11421cb0ef41Sopenharmony_ci  void ReportUncaughtException(Local<Value> error, Local<Message> message) {
11431cb0ef41Sopenharmony_ci    Isolate* isolate = env_->isolate;
11441cb0ef41Sopenharmony_ci    Local<Context> context = env_->context();
11451cb0ef41Sopenharmony_ci
11461cb0ef41Sopenharmony_ci    int script_id = message->GetScriptOrigin().ScriptId();
11471cb0ef41Sopenharmony_ci
11481cb0ef41Sopenharmony_ci    Local<v8::StackTrace> stack_trace = message->GetStackTrace();
11491cb0ef41Sopenharmony_ci
11501cb0ef41Sopenharmony_ci    if (!stack_trace.IsEmpty() && stack_trace->GetFrameCount() > 0 &&
11511cb0ef41Sopenharmony_ci        script_id == stack_trace->GetFrame(isolate, 0)->GetScriptId()) {
11521cb0ef41Sopenharmony_ci      script_id = 0;
11531cb0ef41Sopenharmony_ci    }
11541cb0ef41Sopenharmony_ci
11551cb0ef41Sopenharmony_ci    const uint8_t DETAILS[] = "Uncaught";
11561cb0ef41Sopenharmony_ci
11571cb0ef41Sopenharmony_ci    client_->exceptionThrown(
11581cb0ef41Sopenharmony_ci        context,
11591cb0ef41Sopenharmony_ci        StringView(DETAILS, sizeof(DETAILS) - 1),
11601cb0ef41Sopenharmony_ci        error,
11611cb0ef41Sopenharmony_ci        ToProtocolString(isolate, message->Get())->string(),
11621cb0ef41Sopenharmony_ci        ToProtocolString(isolate, message->GetScriptResourceName())->string(),
11631cb0ef41Sopenharmony_ci        message->GetLineNumber(context).FromMaybe(0),
11641cb0ef41Sopenharmony_ci        message->GetStartColumn(context).FromMaybe(0),
11651cb0ef41Sopenharmony_ci        client_->createStackTrace(stack_trace),
11661cb0ef41Sopenharmony_ci        script_id);
11671cb0ef41Sopenharmony_ci  }
11681cb0ef41Sopenharmony_ci
11691cb0ef41Sopenharmony_ci  void startRepeatingTimer(double interval_s,
11701cb0ef41Sopenharmony_ci                           TimerCallback callback,
11711cb0ef41Sopenharmony_ci                           void* data) override {
11721cb0ef41Sopenharmony_ci    // TODO: implement this for supporting heap profiler.
11731cb0ef41Sopenharmony_ci  }
11741cb0ef41Sopenharmony_ci
11751cb0ef41Sopenharmony_ci  void cancelTimer(void* data) override {
11761cb0ef41Sopenharmony_ci    // TODO: implement this for supporting heap profiler.
11771cb0ef41Sopenharmony_ci  }
11781cb0ef41Sopenharmony_ci
11791cb0ef41Sopenharmony_ci  // Async stack traces instrumentation.
11801cb0ef41Sopenharmony_ci  void AsyncTaskScheduled(const StringView& task_name, void* task,
11811cb0ef41Sopenharmony_ci                          bool recurring) {
11821cb0ef41Sopenharmony_ci    client_->asyncTaskScheduled(task_name, task, recurring);
11831cb0ef41Sopenharmony_ci  }
11841cb0ef41Sopenharmony_ci
11851cb0ef41Sopenharmony_ci  void AsyncTaskCanceled(void* task) {
11861cb0ef41Sopenharmony_ci    client_->asyncTaskCanceled(task);
11871cb0ef41Sopenharmony_ci  }
11881cb0ef41Sopenharmony_ci
11891cb0ef41Sopenharmony_ci  void AsyncTaskStarted(void* task) {
11901cb0ef41Sopenharmony_ci    client_->asyncTaskStarted(task);
11911cb0ef41Sopenharmony_ci  }
11921cb0ef41Sopenharmony_ci
11931cb0ef41Sopenharmony_ci  void AsyncTaskFinished(void* task) {
11941cb0ef41Sopenharmony_ci    client_->asyncTaskFinished(task);
11951cb0ef41Sopenharmony_ci  }
11961cb0ef41Sopenharmony_ci
11971cb0ef41Sopenharmony_ci  void AllAsyncTasksCanceled() {
11981cb0ef41Sopenharmony_ci    client_->allAsyncTasksCanceled();
11991cb0ef41Sopenharmony_ci  }
12001cb0ef41Sopenharmony_ci
12011cb0ef41Sopenharmony_ci  void schedulePauseOnNextStatement(const std::string& reason) {
12021cb0ef41Sopenharmony_ci    for (const auto& id_channel : channels_) {
12031cb0ef41Sopenharmony_ci      id_channel.second->schedulePauseOnNextStatement(reason);
12041cb0ef41Sopenharmony_ci    }
12051cb0ef41Sopenharmony_ci  }
12061cb0ef41Sopenharmony_ci
12071cb0ef41Sopenharmony_ci  bool hasConnectedSessions() {
12081cb0ef41Sopenharmony_ci    for (const auto& id_channel : channels_) {
12091cb0ef41Sopenharmony_ci      // Other sessions are "invisible" more most purposes
12101cb0ef41Sopenharmony_ci      if (id_channel.second->preventShutdown())
12111cb0ef41Sopenharmony_ci        return true;
12121cb0ef41Sopenharmony_ci    }
12131cb0ef41Sopenharmony_ci    return false;
12141cb0ef41Sopenharmony_ci  }
12151cb0ef41Sopenharmony_ci
12161cb0ef41Sopenharmony_ci  bool notifyWaitingForDisconnect() {
12171cb0ef41Sopenharmony_ci    bool retaining_context = false;
12181cb0ef41Sopenharmony_ci    for (const auto& id_channel : channels_) {
12191cb0ef41Sopenharmony_ci      if (id_channel.second->notifyWaitingForDisconnect())
12201cb0ef41Sopenharmony_ci        retaining_context = true;
12211cb0ef41Sopenharmony_ci    }
12221cb0ef41Sopenharmony_ci    return retaining_context;
12231cb0ef41Sopenharmony_ci  }
12241cb0ef41Sopenharmony_ci
12251cb0ef41Sopenharmony_ci  std::shared_ptr<MainThreadHandle> getThreadHandle() {
12261cb0ef41Sopenharmony_ci    if (!interface_) {
12271cb0ef41Sopenharmony_ci      interface_ = std::make_shared<MainThreadInterface>(
12281cb0ef41Sopenharmony_ci          env_->inspector_agent());
12291cb0ef41Sopenharmony_ci    }
12301cb0ef41Sopenharmony_ci    return interface_->GetHandle();
12311cb0ef41Sopenharmony_ci  }
12321cb0ef41Sopenharmony_ci
12331cb0ef41Sopenharmony_ci  bool IsActive() {
12341cb0ef41Sopenharmony_ci    return !channels_.empty();
12351cb0ef41Sopenharmony_ci  }
12361cb0ef41Sopenharmony_ci
12371cb0ef41Sopenharmony_ci private:
12381cb0ef41Sopenharmony_ci  bool shouldRunMessageLoop() {
12391cb0ef41Sopenharmony_ci    if (waiting_for_frontend_)
12401cb0ef41Sopenharmony_ci      return true;
12411cb0ef41Sopenharmony_ci    if (waiting_for_sessions_disconnect_ || waiting_for_resume_) {
12421cb0ef41Sopenharmony_ci      return hasConnectedSessions();
12431cb0ef41Sopenharmony_ci    }
12441cb0ef41Sopenharmony_ci    return false;
12451cb0ef41Sopenharmony_ci  }
12461cb0ef41Sopenharmony_ci
12471cb0ef41Sopenharmony_ci  void runMessageLoop() {
12481cb0ef41Sopenharmony_ci    if (running_nested_loop_)
12491cb0ef41Sopenharmony_ci      return;
12501cb0ef41Sopenharmony_ci
12511cb0ef41Sopenharmony_ci    running_nested_loop_ = true;
12521cb0ef41Sopenharmony_ci
12531cb0ef41Sopenharmony_ci    while (shouldRunMessageLoop()) {
12541cb0ef41Sopenharmony_ci      if (interface_) interface_->WaitForFrontendEvent();
12551cb0ef41Sopenharmony_ci      env_->RunAndClearInterrupts();
12561cb0ef41Sopenharmony_ci    }
12571cb0ef41Sopenharmony_ci    running_nested_loop_ = false;
12581cb0ef41Sopenharmony_ci  }
12591cb0ef41Sopenharmony_ci
12601cb0ef41Sopenharmony_ci  double currentTimeMS() override {
12611cb0ef41Sopenharmony_ci    return env_->platform()->CurrentClockTimeMillis();
12621cb0ef41Sopenharmony_ci  }
12631cb0ef41Sopenharmony_ci
12641cb0ef41Sopenharmony_ci  std::unique_ptr<StringBuffer> resourceNameToUrl(
12651cb0ef41Sopenharmony_ci      const StringView& resource_name_view) override {
12661cb0ef41Sopenharmony_ci    std::string resource_name =
12671cb0ef41Sopenharmony_ci        protocol::StringUtil::StringViewToUtf8(resource_name_view);
12681cb0ef41Sopenharmony_ci    if (!IsFilePath(resource_name))
12691cb0ef41Sopenharmony_ci      return nullptr;
12701cb0ef41Sopenharmony_ci
12711cb0ef41Sopenharmony_ci    std::string url = node::url::FromFilePath(resource_name);
12721cb0ef41Sopenharmony_ci    return Utf8ToStringView(url);
12731cb0ef41Sopenharmony_ci  }
12741cb0ef41Sopenharmony_ci
12751cb0ef41Sopenharmony_ci  Environment* env_;
12761cb0ef41Sopenharmony_ci  bool is_main_;
12771cb0ef41Sopenharmony_ci  bool running_nested_loop_ = false;
12781cb0ef41Sopenharmony_ci  std::unique_ptr<V8Inspector> client_;
12791cb0ef41Sopenharmony_ci  std::unordered_map<int, std::unique_ptr<ChannelImpl>> channels_;
12801cb0ef41Sopenharmony_ci  int next_session_id_ = 1;
12811cb0ef41Sopenharmony_ci  bool waiting_for_resume_ = false;
12821cb0ef41Sopenharmony_ci  bool waiting_for_frontend_ = false;
12831cb0ef41Sopenharmony_ci  bool waiting_for_sessions_disconnect_ = false;
12841cb0ef41Sopenharmony_ci  // Allows accessing Inspector from non-main threads
12851cb0ef41Sopenharmony_ci  std::shared_ptr<MainThreadInterface> interface_;
12861cb0ef41Sopenharmony_ci};
12871cb0ef41Sopenharmony_ci
12881cb0ef41Sopenharmony_ciAgent::Agent(Environment* env)
12891cb0ef41Sopenharmony_ci    : parent_env_(env) {}
12901cb0ef41Sopenharmony_ci
12911cb0ef41Sopenharmony_ciAgent::~Agent() = default;
12921cb0ef41Sopenharmony_ci
12931cb0ef41Sopenharmony_cibool Agent::Start(const std::string& path,
12941cb0ef41Sopenharmony_ci                  std::shared_ptr<ExclusiveAccess<HostPort>> host_port,
12951cb0ef41Sopenharmony_ci                  bool is_main,
12961cb0ef41Sopenharmony_ci                  bool wait_for_connect) {
12971cb0ef41Sopenharmony_ci  path_ = path;
12981cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(host_port);
12991cb0ef41Sopenharmony_ci  host_port_ = host_port;
13001cb0ef41Sopenharmony_ci
13011cb0ef41Sopenharmony_ci  client_ = std::make_shared<InspectorClient>(parent_env_, is_main);
13021cb0ef41Sopenharmony_ci
13031cb0ef41Sopenharmony_ci  if (!StartIoThread()) {
13041cb0ef41Sopenharmony_ci    return false;
13051cb0ef41Sopenharmony_ci  }
13061cb0ef41Sopenharmony_ci
13071cb0ef41Sopenharmony_ci  if (wait_for_connect) {
13081cb0ef41Sopenharmony_ci    client_->waitForFrontend();
13091cb0ef41Sopenharmony_ci  }
13101cb0ef41Sopenharmony_ci  return true;
13111cb0ef41Sopenharmony_ci}
13121cb0ef41Sopenharmony_ci
13131cb0ef41Sopenharmony_cibool Agent::StartIoThread() {
13141cb0ef41Sopenharmony_ci  if (io_ != nullptr)
13151cb0ef41Sopenharmony_ci    return true;
13161cb0ef41Sopenharmony_ci
13171cb0ef41Sopenharmony_ci  if (!client_) {
13181cb0ef41Sopenharmony_ci    ThrowUninitializedInspectorError(parent_env_);
13191cb0ef41Sopenharmony_ci    return false;
13201cb0ef41Sopenharmony_ci  }
13211cb0ef41Sopenharmony_ci
13221cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(client_);
13231cb0ef41Sopenharmony_ci
13241cb0ef41Sopenharmony_ci  io_ = InspectorIo::Start(client_->getThreadHandle(),
13251cb0ef41Sopenharmony_ci                           path_,
13261cb0ef41Sopenharmony_ci                           host_port_,
13271cb0ef41Sopenharmony_ci                           { false, true });
13281cb0ef41Sopenharmony_ci  if (io_ == nullptr) {
13291cb0ef41Sopenharmony_ci    return false;
13301cb0ef41Sopenharmony_ci  }
13311cb0ef41Sopenharmony_ci  return true;
13321cb0ef41Sopenharmony_ci}
13331cb0ef41Sopenharmony_ci
13341cb0ef41Sopenharmony_civoid Agent::Stop() {
13351cb0ef41Sopenharmony_ci  io_.reset();
13361cb0ef41Sopenharmony_ci}
13371cb0ef41Sopenharmony_ci
13381cb0ef41Sopenharmony_cistd::unique_ptr<InspectorSession> Agent::Connect(
13391cb0ef41Sopenharmony_ci    std::unique_ptr<InspectorSessionDelegate> delegate,
13401cb0ef41Sopenharmony_ci    bool prevent_shutdown) {
13411cb0ef41Sopenharmony_ci  if (!client_) {
13421cb0ef41Sopenharmony_ci    ThrowUninitializedInspectorError(parent_env_);
13431cb0ef41Sopenharmony_ci    return std::unique_ptr<InspectorSession>{};
13441cb0ef41Sopenharmony_ci  }
13451cb0ef41Sopenharmony_ci
13461cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(client_);
13471cb0ef41Sopenharmony_ci
13481cb0ef41Sopenharmony_ci  int session_id = client_->connectFrontend(std::move(delegate),
13491cb0ef41Sopenharmony_ci                                            prevent_shutdown);
13501cb0ef41Sopenharmony_ci  return std::unique_ptr<InspectorSession>(
13511cb0ef41Sopenharmony_ci      new SameThreadInspectorSession(session_id, client_));
13521cb0ef41Sopenharmony_ci}
13531cb0ef41Sopenharmony_ci
13541cb0ef41Sopenharmony_civoid Agent::WaitForDisconnect() {
13551cb0ef41Sopenharmony_ci  if (!client_) {
13561cb0ef41Sopenharmony_ci    ThrowUninitializedInspectorError(parent_env_);
13571cb0ef41Sopenharmony_ci    return;
13581cb0ef41Sopenharmony_ci  }
13591cb0ef41Sopenharmony_ci
13601cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(client_);
13611cb0ef41Sopenharmony_ci  if (client_->hasConnectedSessions()) {
13621cb0ef41Sopenharmony_ci    fprintf(stderr, "Waiting for the debugger to disconnect...\n");
13631cb0ef41Sopenharmony_ci    fflush(stderr);
13641cb0ef41Sopenharmony_ci  }
13651cb0ef41Sopenharmony_ci  if (!client_->notifyWaitingForDisconnect()) {
13661cb0ef41Sopenharmony_ci    client_->contextDestroyed(parent_env_->context());
13671cb0ef41Sopenharmony_ci  }
13681cb0ef41Sopenharmony_ci  if (io_ != nullptr) {
13691cb0ef41Sopenharmony_ci    io_->StopAcceptingNewConnections();
13701cb0ef41Sopenharmony_ci    client_->waitForSessionsDisconnect();
13711cb0ef41Sopenharmony_ci  }
13721cb0ef41Sopenharmony_ci}
13731cb0ef41Sopenharmony_ci
13741cb0ef41Sopenharmony_civoid Agent::ReportUncaughtException(Local<Value> error,
13751cb0ef41Sopenharmony_ci                                    Local<Message> message) {
13761cb0ef41Sopenharmony_ci  if (!IsListening())
13771cb0ef41Sopenharmony_ci    return;
13781cb0ef41Sopenharmony_ci  client_->ReportUncaughtException(error, message);
13791cb0ef41Sopenharmony_ci  WaitForDisconnect();
13801cb0ef41Sopenharmony_ci}
13811cb0ef41Sopenharmony_ci
13821cb0ef41Sopenharmony_civoid Agent::PauseOnNextJavascriptStatement(const std::string& reason) {
13831cb0ef41Sopenharmony_ci  client_->schedulePauseOnNextStatement(reason);
13841cb0ef41Sopenharmony_ci}
13851cb0ef41Sopenharmony_ci
13861cb0ef41Sopenharmony_civoid Agent::AsyncTaskScheduled(const StringView& task_name, void* task,
13871cb0ef41Sopenharmony_ci                               bool recurring) {
13881cb0ef41Sopenharmony_ci  client_->AsyncTaskScheduled(task_name, task, recurring);
13891cb0ef41Sopenharmony_ci}
13901cb0ef41Sopenharmony_ci
13911cb0ef41Sopenharmony_civoid Agent::AsyncTaskCanceled(void* task) {
13921cb0ef41Sopenharmony_ci  client_->AsyncTaskCanceled(task);
13931cb0ef41Sopenharmony_ci}
13941cb0ef41Sopenharmony_ci
13951cb0ef41Sopenharmony_civoid Agent::AsyncTaskStarted(void* task) {
13961cb0ef41Sopenharmony_ci  client_->AsyncTaskStarted(task);
13971cb0ef41Sopenharmony_ci}
13981cb0ef41Sopenharmony_ci
13991cb0ef41Sopenharmony_civoid Agent::AsyncTaskFinished(void* task) {
14001cb0ef41Sopenharmony_ci  client_->AsyncTaskFinished(task);
14011cb0ef41Sopenharmony_ci}
14021cb0ef41Sopenharmony_ci
14031cb0ef41Sopenharmony_civoid Agent::AllAsyncTasksCanceled() {
14041cb0ef41Sopenharmony_ci  client_->AllAsyncTasksCanceled();
14051cb0ef41Sopenharmony_ci}
14061cb0ef41Sopenharmony_ci
14071cb0ef41Sopenharmony_civoid Agent::ContextCreated(Local<Context> context, const ContextInfo& info) {
14081cb0ef41Sopenharmony_ci  if (client_ == nullptr)  // This happens for a main context
14091cb0ef41Sopenharmony_ci    return;
14101cb0ef41Sopenharmony_ci  client_->contextCreated(context, info);
14111cb0ef41Sopenharmony_ci}
14121cb0ef41Sopenharmony_ci
14131cb0ef41Sopenharmony_cibool Agent::IsActive() {
14141cb0ef41Sopenharmony_ci  if (client_ == nullptr)
14151cb0ef41Sopenharmony_ci    return false;
14161cb0ef41Sopenharmony_ci  return io_ != nullptr || client_->IsActive();
14171cb0ef41Sopenharmony_ci}
14181cb0ef41Sopenharmony_ci
14191cb0ef41Sopenharmony_civoid Agent::WaitForConnect() {
14201cb0ef41Sopenharmony_ci  if (!client_) {
14211cb0ef41Sopenharmony_ci    ThrowUninitializedInspectorError(parent_env_);
14221cb0ef41Sopenharmony_ci    return;
14231cb0ef41Sopenharmony_ci  }
14241cb0ef41Sopenharmony_ci
14251cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(client_);
14261cb0ef41Sopenharmony_ci  client_->waitForFrontend();
14271cb0ef41Sopenharmony_ci}
14281cb0ef41Sopenharmony_ci
14291cb0ef41Sopenharmony_cistd::string Agent::GetWsUrl() const {
14301cb0ef41Sopenharmony_ci  if (io_ == nullptr)
14311cb0ef41Sopenharmony_ci    return "";
14321cb0ef41Sopenharmony_ci  return io_->GetWsUrl();
14331cb0ef41Sopenharmony_ci}
14341cb0ef41Sopenharmony_ci
14351cb0ef41Sopenharmony_ciSameThreadInspectorSession::~SameThreadInspectorSession() {
14361cb0ef41Sopenharmony_ci  auto client = client_.lock();
14371cb0ef41Sopenharmony_ci  if (client)
14381cb0ef41Sopenharmony_ci    client->disconnectFrontend(session_id_);
14391cb0ef41Sopenharmony_ci}
14401cb0ef41Sopenharmony_ci
14411cb0ef41Sopenharmony_civoid SameThreadInspectorSession::Dispatch(
14421cb0ef41Sopenharmony_ci    const v8_inspector::StringView& message) {
14431cb0ef41Sopenharmony_ci  auto client = client_.lock();
14441cb0ef41Sopenharmony_ci  if (client)
14451cb0ef41Sopenharmony_ci    client->dispatchMessageFromFrontend(session_id_, message);
14461cb0ef41Sopenharmony_ci}
14471cb0ef41Sopenharmony_ci
14481cb0ef41Sopenharmony_ci}  // namespace v8impl
1449