1 #include "worker_inspector.h"
2 #include "main_thread_interface.h"
3 #include "util-inl.h"
4
5 #include <memory>
6
7 namespace node {
8 namespace inspector {
9 namespace {
10
11 class WorkerStartedRequest : public Request {
12 public:
WorkerStartedRequest(uint64_t id,const std::string & url,std::shared_ptr<node::inspector::MainThreadHandle> worker_thread,bool waiting,const std::string & name)13 WorkerStartedRequest(
14 uint64_t id,
15 const std::string& url,
16 std::shared_ptr<node::inspector::MainThreadHandle> worker_thread,
17 bool waiting,
18 const std::string& name)
19 : id_(id),
20 info_(BuildWorkerTitle(id, name), url, worker_thread),
21 waiting_(waiting) {}
Call(MainThreadInterface * thread)22 void Call(MainThreadInterface* thread) override {
23 auto manager = thread->inspector_agent()->GetWorkerManager();
24 manager->WorkerStarted(id_, info_, waiting_);
25 }
26
27 private:
BuildWorkerTitle(int id,const std::string & name)28 static std::string BuildWorkerTitle(int id, const std::string& name) {
29 return "[worker " + std::to_string(id) + "]" +
30 (name == "" ? "" : " " + name);
31 }
32
33 uint64_t id_;
34 WorkerInfo info_;
35 bool waiting_;
36 };
37
38
Report(const std::unique_ptr<WorkerDelegate> & delegate,const WorkerInfo & info,bool waiting)39 void Report(const std::unique_ptr<WorkerDelegate>& delegate,
40 const WorkerInfo& info, bool waiting) {
41 if (info.worker_thread)
42 delegate->WorkerCreated(info.title, info.url, waiting, info.worker_thread);
43 }
44
45 class WorkerFinishedRequest : public Request {
46 public:
WorkerFinishedRequest(uint64_t worker_id)47 explicit WorkerFinishedRequest(uint64_t worker_id) : worker_id_(worker_id) {}
48
Call(MainThreadInterface * thread)49 void Call(MainThreadInterface* thread) override {
50 thread->inspector_agent()->GetWorkerManager()->WorkerFinished(worker_id_);
51 }
52
53 private:
54 uint64_t worker_id_;
55 };
56 } // namespace
57
ParentInspectorHandle(uint64_t id,const std::string & url,std::shared_ptr<MainThreadHandle> parent_thread,bool wait_for_connect,const std::string & name)58 ParentInspectorHandle::ParentInspectorHandle(
59 uint64_t id,
60 const std::string& url,
61 std::shared_ptr<MainThreadHandle> parent_thread,
62 bool wait_for_connect,
63 const std::string& name)
64 : id_(id),
65 url_(url),
66 parent_thread_(parent_thread),
67 wait_(wait_for_connect),
68 name_(name) {}
69
~ParentInspectorHandle()70 ParentInspectorHandle::~ParentInspectorHandle() {
71 parent_thread_->Post(
72 std::unique_ptr<Request>(new WorkerFinishedRequest(id_)));
73 }
74
WorkerStarted(std::shared_ptr<MainThreadHandle> worker_thread,bool waiting)75 void ParentInspectorHandle::WorkerStarted(
76 std::shared_ptr<MainThreadHandle> worker_thread, bool waiting) {
77 std::unique_ptr<Request> request(
78 new WorkerStartedRequest(id_, url_, worker_thread, waiting, name_));
79 parent_thread_->Post(std::move(request));
80 }
81
Connect(std::unique_ptr<inspector::InspectorSessionDelegate> delegate,bool prevent_shutdown)82 std::unique_ptr<inspector::InspectorSession> ParentInspectorHandle::Connect(
83 std::unique_ptr<inspector::InspectorSessionDelegate> delegate,
84 bool prevent_shutdown) {
85 return parent_thread_->Connect(std::move(delegate), prevent_shutdown);
86 }
87
WorkerFinished(uint64_t session_id)88 void WorkerManager::WorkerFinished(uint64_t session_id) {
89 children_.erase(session_id);
90 }
91
WorkerStarted(uint64_t session_id,const WorkerInfo & info,bool waiting)92 void WorkerManager::WorkerStarted(uint64_t session_id,
93 const WorkerInfo& info,
94 bool waiting) {
95 if (info.worker_thread->Expired())
96 return;
97 children_.emplace(session_id, info);
98 for (const auto& delegate : delegates_) {
99 Report(delegate.second, info, waiting);
100 }
101 }
102
NewParentHandle(uint64_t thread_id,const std::string & url,const std::string & name)103 std::unique_ptr<ParentInspectorHandle> WorkerManager::NewParentHandle(
104 uint64_t thread_id, const std::string& url, const std::string& name) {
105 bool wait = !delegates_waiting_on_start_.empty();
106 return std::make_unique<ParentInspectorHandle>(
107 thread_id, url, thread_, wait, name);
108 }
109
RemoveAttachDelegate(int id)110 void WorkerManager::RemoveAttachDelegate(int id) {
111 delegates_.erase(id);
112 delegates_waiting_on_start_.erase(id);
113 }
114
SetAutoAttach(std::unique_ptr<WorkerDelegate> attach_delegate)115 std::unique_ptr<WorkerManagerEventHandle> WorkerManager::SetAutoAttach(
116 std::unique_ptr<WorkerDelegate> attach_delegate) {
117 int id = ++next_delegate_id_;
118 delegates_[id] = std::move(attach_delegate);
119 const auto& delegate = delegates_[id];
120 for (const auto& worker : children_) {
121 // Waiting is only reported when a worker is started, same as browser
122 Report(delegate, worker.second, false);
123 }
124 return std::make_unique<WorkerManagerEventHandle>(shared_from_this(), id);
125 }
126
SetWaitOnStartForDelegate(int id,bool wait)127 void WorkerManager::SetWaitOnStartForDelegate(int id, bool wait) {
128 if (wait)
129 delegates_waiting_on_start_.insert(id);
130 else
131 delegates_waiting_on_start_.erase(id);
132 }
133
SetWaitOnStart(bool wait_on_start)134 void WorkerManagerEventHandle::SetWaitOnStart(bool wait_on_start) {
135 manager_->SetWaitOnStartForDelegate(id_, wait_on_start);
136 }
137
~WorkerManagerEventHandle()138 WorkerManagerEventHandle::~WorkerManagerEventHandle() {
139 manager_->RemoveAttachDelegate(id_);
140 }
141 } // namespace inspector
142 } // namespace node
143