chromium/services/accessibility/features/devtools/os_devtools_agent.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/accessibility/features/devtools/os_devtools_agent.h"

#include <memory>

#include "services/accessibility/features/devtools/debug_command_queue.h"
#include "services/accessibility/features/devtools/os_devtools_session.h"
#include "services/accessibility/features/v8_manager.h"
namespace ax {

OSDevToolsAgent::OSDevToolsAgent(
    V8Environment& v8_env,
    scoped_refptr<base::SequencedTaskRunner> io_session_receiver_sequence)
    : v8_env_(v8_env),
      debug_command_queue_(base::MakeRefCounted<DebugCommandQueue>()),
      io_session_task_runner_(std::move(io_session_receiver_sequence)),
      v8_inspector_(
          v8_inspector::V8Inspector::create(v8_env.GetIsolate(), this)) {
  v8::Isolate::Scope isolate_scope(v8_env.GetIsolate());
  v8::HandleScope handle_scope(v8_env.GetIsolate());
  v8_inspector::V8ContextInfo info(v8_env.GetContext(),
                                   V8Environment::kDefaultContextId,
                                   v8_inspector::StringView());

  // Also notify that the context was created. The context already exists,
  // but the inspector was just created and also needs to be informed.
  v8_inspector_->contextCreated(info);
}

OSDevToolsAgent::~OSDevToolsAgent() {
  v8::Isolate::Scope isolate_scope(v8_env_->GetIsolate());
  v8::HandleScope handle_scope(v8_env_->GetIsolate());
  auto ctx = v8_env_->GetContext();
  v8_inspector_->contextDestroyed(ctx);
}

void OSDevToolsAgent::Connect(
    mojo::PendingAssociatedReceiver<blink::mojom::DevToolsAgent> agent) {
  receiver_.Bind(std::move(agent));
}

std::unique_ptr<v8_inspector::V8InspectorSession>
OSDevToolsAgent::ConnectSession(OSDevToolsSession* session,
                                bool session_waits_for_debugger) {
  return v8_inspector_->connect(
      V8Environment::kDefaultContextId, session, v8_inspector::StringView(),
      v8_inspector::V8Inspector::kFullyTrusted,
      session_waits_for_debugger
          ? v8_inspector::V8Inspector::kWaitingForDebugger
          : v8_inspector::V8Inspector::kNotWaitingForDebugger);
}

void OSDevToolsAgent::MaybeTriggerInstrumentationBreakpoint(
    const std::string& name) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(v8_sequence_checker_);
  for (OSDevToolsSession* session : sessions_) {
    session->MaybeTriggerInstrumentationBreakpoint(name);
  }
}

void OSDevToolsAgent::AttachDevToolsSession(
    mojo::PendingAssociatedRemote<blink::mojom::DevToolsSessionHost> host,
    mojo::PendingAssociatedReceiver<blink::mojom::DevToolsSession>
        session_receiver,
    mojo::PendingReceiver<blink::mojom::DevToolsSession> io_session_receiver,
    blink::mojom::DevToolsSessionStatePtr reattach_session_state,
    bool client_expects_binary_responses,
    bool client_is_trusted,
    const std::string& session_id,
    bool session_waits_for_debugger) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(v8_sequence_checker_);

  auto session_destroyed_callback = base::BindOnce(
      &OSDevToolsAgent::SessionDestroyed, weak_ptr_factory_.GetWeakPtr());

  auto session = std::make_unique<OSDevToolsSession>(
      v8_env_.get(), *this, debug_command_queue_, session_id,
      client_expects_binary_responses, session_waits_for_debugger,
      std::move(host), io_session_task_runner_, std::move(io_session_receiver),
      std::move(session_destroyed_callback));

  sessions_.insert(session.get());
  // Adding here binds the session_reciever to the session.
  mojom_sessions_.Add(std::move(session), std::move(session_receiver));
}

void OSDevToolsAgent::InspectElement(const ::gfx::Point& point) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(v8_sequence_checker_);
  NOTIMPLEMENTED();  // Should not be used with this.
}

void OSDevToolsAgent::ReportChildTargets(bool report,
                                         bool wait_for_debugger,
                                         ReportChildTargetsCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(v8_sequence_checker_);
  NOTIMPLEMENTED();  // Should not be used with this.
}

void OSDevToolsAgent::runMessageLoopOnPause(int context_group_id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(v8_sequence_checker_);
  // NO-OP --- TODO(b/290815208).
}

void OSDevToolsAgent::quitMessageLoopOnPause() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(v8_sequence_checker_);
  debug_command_queue_->QuitPauseForDebugger();
}
void OSDevToolsAgent::runIfWaitingForDebugger(int context_group_id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(v8_sequence_checker_);
  // NO-OP --- TODO(b/290815208).
}

void OSDevToolsAgent::SessionDestroyed(OSDevToolsSession* session) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(v8_sequence_checker_);
  // Pointer cleanup.
  sessions_.erase(session);
}

}  // namespace ax