1 #include "worker_agent.h"
2
3 #include "main_thread_interface.h"
4 #include "worker_inspector.h"
5 #include "util-inl.h"
6
7 namespace node {
8 namespace inspector {
9 namespace protocol {
10
11 class NodeWorkers
12 : public std::enable_shared_from_this<NodeWorkers> {
13 public:
NodeWorkers(std::weak_ptr<NodeWorker::Frontend> frontend,std::shared_ptr<MainThreadHandle> thread)14 explicit NodeWorkers(std::weak_ptr<NodeWorker::Frontend> frontend,
15 std::shared_ptr<MainThreadHandle> thread)
16 : frontend_(frontend), thread_(thread) {}
17 void WorkerCreated(const std::string& title,
18 const std::string& url,
19 bool waiting,
20 std::shared_ptr<MainThreadHandle> target);
21 void Receive(const std::string& id, const std::string& message);
22 void Send(const std::string& id, const std::string& message);
23 void Detached(const std::string& id);
24
25 private:
26 std::weak_ptr<NodeWorker::Frontend> frontend_;
27 std::shared_ptr<MainThreadHandle> thread_;
28 std::unordered_map<std::string, std::unique_ptr<InspectorSession>> sessions_;
29 int next_target_id_ = 0;
30 };
31
32 namespace {
33 class AgentWorkerInspectorDelegate : public WorkerDelegate {
34 public:
AgentWorkerInspectorDelegate(std::shared_ptr<NodeWorkers> workers)35 explicit AgentWorkerInspectorDelegate(std::shared_ptr<NodeWorkers> workers)
36 : workers_(workers) {}
37
WorkerCreated(const std::string & title,const std::string & url,bool waiting,std::shared_ptr<MainThreadHandle> target)38 void WorkerCreated(const std::string& title,
39 const std::string& url,
40 bool waiting,
41 std::shared_ptr<MainThreadHandle> target) override {
42 workers_->WorkerCreated(title, url, waiting, target);
43 }
44
45 private:
46 std::shared_ptr<NodeWorkers> workers_;
47 };
48
49 class ParentInspectorSessionDelegate : public InspectorSessionDelegate {
50 public:
ParentInspectorSessionDelegate(const std::string & id,std::shared_ptr<NodeWorkers> workers)51 ParentInspectorSessionDelegate(const std::string& id,
52 std::shared_ptr<NodeWorkers> workers)
53 : id_(id), workers_(workers) {}
54
~ParentInspectorSessionDelegate()55 ~ParentInspectorSessionDelegate() override {
56 workers_->Detached(id_);
57 }
58
SendMessageToFrontend(const v8_inspector::StringView & msg)59 void SendMessageToFrontend(const v8_inspector::StringView& msg) override {
60 std::string message = protocol::StringUtil::StringViewToUtf8(msg);
61 workers_->Send(id_, message);
62 }
63
64 private:
65 std::string id_;
66 std::shared_ptr<NodeWorkers> workers_;
67 };
68
WorkerInfo(const std::string & id,const std::string & title,const std::string & url)69 std::unique_ptr<NodeWorker::WorkerInfo> WorkerInfo(const std::string& id,
70 const std::string& title,
71 const std::string& url) {
72 return NodeWorker::WorkerInfo::create()
73 .setWorkerId(id)
74 .setTitle(title)
75 .setUrl(url)
76 .setType("worker").build();
77 }
78 } // namespace
79
WorkerAgent(std::weak_ptr<WorkerManager> manager)80 WorkerAgent::WorkerAgent(std::weak_ptr<WorkerManager> manager)
81 : manager_(manager) {}
82
83
Wire(UberDispatcher * dispatcher)84 void WorkerAgent::Wire(UberDispatcher* dispatcher) {
85 frontend_.reset(new NodeWorker::Frontend(dispatcher->channel()));
86 NodeWorker::Dispatcher::wire(dispatcher, this);
87 auto manager = manager_.lock();
88 CHECK_NOT_NULL(manager);
89 workers_ =
90 std::make_shared<NodeWorkers>(frontend_, manager->MainThread());
91 }
92
sendMessageToWorker(const String & message,const String & sessionId)93 DispatchResponse WorkerAgent::sendMessageToWorker(const String& message,
94 const String& sessionId) {
95 workers_->Receive(sessionId, message);
96 return DispatchResponse::OK();
97 }
98
enable(bool waitForDebuggerOnStart)99 DispatchResponse WorkerAgent::enable(bool waitForDebuggerOnStart) {
100 auto manager = manager_.lock();
101 if (!manager) {
102 return DispatchResponse::OK();
103 }
104 if (!event_handle_) {
105 std::unique_ptr<AgentWorkerInspectorDelegate> delegate(
106 new AgentWorkerInspectorDelegate(workers_));
107 event_handle_ = manager->SetAutoAttach(std::move(delegate));
108 }
109 event_handle_->SetWaitOnStart(waitForDebuggerOnStart);
110 return DispatchResponse::OK();
111 }
112
disable()113 DispatchResponse WorkerAgent::disable() {
114 event_handle_.reset();
115 return DispatchResponse::OK();
116 }
117
detach(const String & sessionId)118 DispatchResponse WorkerAgent::detach(const String& sessionId) {
119 workers_->Detached(sessionId);
120 return DispatchResponse::OK();
121 }
122
WorkerCreated(const std::string & title,const std::string & url,bool waiting,std::shared_ptr<MainThreadHandle> target)123 void NodeWorkers::WorkerCreated(const std::string& title,
124 const std::string& url,
125 bool waiting,
126 std::shared_ptr<MainThreadHandle> target) {
127 auto frontend = frontend_.lock();
128 if (!frontend)
129 return;
130 std::string id = std::to_string(++next_target_id_);
131 auto delegate = thread_->MakeDelegateThreadSafe(
132 std::unique_ptr<InspectorSessionDelegate>(
133 new ParentInspectorSessionDelegate(id, shared_from_this())));
134 sessions_[id] = target->Connect(std::move(delegate), true);
135 frontend->attachedToWorker(id, WorkerInfo(id, title, url), waiting);
136 }
137
Send(const std::string & id,const std::string & message)138 void NodeWorkers::Send(const std::string& id, const std::string& message) {
139 auto frontend = frontend_.lock();
140 if (frontend)
141 frontend->receivedMessageFromWorker(id, message);
142 }
143
Receive(const std::string & id,const std::string & message)144 void NodeWorkers::Receive(const std::string& id, const std::string& message) {
145 auto it = sessions_.find(id);
146 if (it != sessions_.end())
147 it->second->Dispatch(Utf8ToStringView(message)->string());
148 }
149
Detached(const std::string & id)150 void NodeWorkers::Detached(const std::string& id) {
151 if (sessions_.erase(id) == 0)
152 return;
153 auto frontend = frontend_.lock();
154 if (frontend) {
155 frontend->detachedFromWorker(id);
156 }
157 }
158 } // namespace protocol
159 } // namespace inspector
160 } // namespace node
161