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