• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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