File: devtools_server.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (166 lines) | stat: -rw-r--r-- 6,723 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_UI_DEVTOOLS_DEVTOOLS_SERVER_H_
#define COMPONENTS_UI_DEVTOOLS_DEVTOOLS_SERVER_H_

#include <string_view>
#include <vector>

#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "base/thread_annotations.h"
#include "components/ui_devtools/devtools_client.h"
#include "components/ui_devtools/devtools_export.h"
#include "components/ui_devtools/dom.h"
#include "components/ui_devtools/forward.h"
#include "components/ui_devtools/protocol.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/server/http_server_request_info.h"
#include "net/traffic_annotation/network_traffic_annotation.h"

namespace ui_devtools {

class TracingAgent;

class UI_DEVTOOLS_EXPORT UiDevToolsServer {
 public:
  // Network tags to be used for the UI devtools servers.
  static const net::NetworkTrafficAnnotationTag kUIDevtoolsServerTag;

  UiDevToolsServer(const UiDevToolsServer&) = delete;
  UiDevToolsServer& operator=(const UiDevToolsServer&) = delete;

  ~UiDevToolsServer();

  // Returns an empty unique_ptr if ui devtools flag isn't enabled or if a
  // server instance has already been created. All network activity is performed
  // on `io_thread_task_runner`, which must run tasks on a thread with an IO
  // message pump. All other work is done on the thread the UiDevToolsServer is
  // created on. If `port` is 0, the server will choose an available port. If
  // `port` is 0 and `active_port_output_directory` is present, the server will
  // write the chosen port to `kUIDevToolsActivePortFileName` on
  // `active_port_output_directory`.
  static std::unique_ptr<UiDevToolsServer> CreateForViews(
      scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner,
      int port,
      const base::FilePath& active_port_output_directory = base::FilePath());


  // Returns a list of attached UiDevToolsClient name + URL
  using NameUrlPair = std::pair<std::string, std::string>;
  static std::vector<NameUrlPair> GetClientNamesAndUrls();

  // Returns true if UI Devtools is enabled by the given commandline switch.
  static bool IsUiDevToolsEnabled(const char* enable_devtools_flag);

  // Returns the port number specified by a command line flag. If a number is
  // not specified as a command line argument, returns the |default_port|.
  static int GetUiDevToolsPort(const char* enable_devtools_flag,
                               int default_port);

  void AttachClient(std::unique_ptr<UiDevToolsClient> client);
  void SendOverWebSocket(int connection_id, std::string_view message);

  int port() const {
    DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_);
    return port_;
  }

  TracingAgent* tracing_agent() {
    DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_);
    return tracing_agent_;
  }

  void set_tracing_agent(TracingAgent* agent) {
    DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_);
    tracing_agent_ = agent;
  }

  // Sets the callback which will be invoked when the session is closed.
  // Marks as a const function so it can be called after the server is set up
  // and used as a constant instance.
  void SetOnSessionEnded(base::OnceClosure callback) const;
  // Sets a callback that tests can use to wait for the server to be ready to
  // accept connections.
  void SetOnSocketConnectedForTesting(base::OnceClosure on_socket_connected);
  // Allows calling OnWebSocketRequest() with unexpected connection IDs for
  // tests, bypassing the HttpServer.
  void OnWebSocketRequestForTesting(int connection_id,
                                    net::HttpServerRequestInfo info);

 private:
  // Class that owns the ServerSocket and, after creation on the main thread,
  // may only subsequently be used on the IO thread. The class is needed because
  // HttpServers must live on an IO thread. This class contains all state that's
  // read or written on the IO thread, to avoid UAF's on teardown. When the
  // UiDevToolsServer server is destroyed, a task is posted to destroy the
  // IOThreadData, but that task could still be run after the UiDevToolsServer
  // is fully torn down.
  //
  // Because of this pattern, it's always safe to post messages to the IO thread
  // to dereference the IOThreadData from the UiDevToolsServer assuming this
  // class will still be valid, but tasks it posts back to the main thread to
  // dereference the UiDevToolsServer must use weak pointers.
  class IOThreadData;

  UiDevToolsServer(
      scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner,
      int port,
      const net::NetworkTrafficAnnotationTag tag,
      const base::FilePath& active_port_output_directory);

  // Invoked on the IO thread, initializes `server_` and starts listening for
  // connections on `port`.
  void MakeServer(int port);

  // Invoked on the main thread. Called by MakeServer via a post task.
  void ServerCreated(int port);

  // These mirror the corresponding HttpServer methods.
  void OnWebSocketRequest(int connection_id, net::HttpServerRequestInfo info);
  void OnWebSocketMessage(int connection_id, std::string data);
  void OnClose(int connection_id);

  using ClientsList = std::vector<std::unique_ptr<UiDevToolsClient>>;
  using ConnectionsMap =
      std::map<uint32_t, raw_ptr<UiDevToolsClient, CtnExperimental>>;
  ClientsList clients_ GUARDED_BY_CONTEXT(main_sequence_);
  ConnectionsMap connections_ GUARDED_BY_CONTEXT(main_sequence_);

  const scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_;

  // The port the devtools server listens on.
  int port_ GUARDED_BY_CONTEXT(main_sequence_);

  raw_ptr<TracingAgent> tracing_agent_ GUARDED_BY_CONTEXT(main_sequence_) =
      nullptr;

  // Invoked when the server doesn't have any live connections.
  mutable base::OnceClosure on_session_ended_
      GUARDED_BY_CONTEXT(main_sequence_);

  // Set once the server has been started.
  bool connected_ GUARDED_BY_CONTEXT(main_sequence_) = false;

  // Invoked once the server has been started.
  base::OnceClosure on_socket_connected_ GUARDED_BY_CONTEXT(main_sequence_);

  // The server (owned by Chrome for now)
  static UiDevToolsServer* devtools_server_;

  std::unique_ptr<IOThreadData> io_thread_data_;

  SEQUENCE_CHECKER(main_sequence_);
  base::WeakPtrFactory<UiDevToolsServer> weak_ptr_factory_{this};
};

}  // namespace ui_devtools

#endif  // COMPONENTS_UI_DEVTOOLS_DEVTOOLS_SERVER_H_