summaryrefslogtreecommitdiff
path: root/src/inspector/worker_inspector.cc
blob: deeddcc0836dd1f6fee527c4b8b3a02467ed3022 (plain)
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
#include "worker_inspector.h"
#include "main_thread_interface.h"
#include "util-inl.h"

#include <memory>

namespace node {
namespace inspector {
namespace {

class WorkerStartedRequest : public Request {
 public:
  WorkerStartedRequest(
      int id,
      const std::string& url,
      std::shared_ptr<node::inspector::MainThreadHandle> worker_thread,
      bool waiting)
      : id_(id),
        info_(BuildWorkerTitle(id), url, worker_thread),
        waiting_(waiting) {}
  void Call(MainThreadInterface* thread) override {
    auto manager = thread->inspector_agent()->GetWorkerManager();
    manager->WorkerStarted(id_, info_, waiting_);
  }

 private:
  static std::string BuildWorkerTitle(int id) {
    return "Worker " + std::to_string(id);
  }

  int id_;
  WorkerInfo info_;
  bool waiting_;
};


void Report(const std::unique_ptr<WorkerDelegate>& delegate,
            const WorkerInfo& info, bool waiting) {
  if (info.worker_thread)
    delegate->WorkerCreated(info.title, info.url, waiting, info.worker_thread);
}

class WorkerFinishedRequest : public Request {
 public:
  explicit WorkerFinishedRequest(int worker_id) : worker_id_(worker_id) {}

  void Call(MainThreadInterface* thread) override {
    thread->inspector_agent()->GetWorkerManager()->WorkerFinished(worker_id_);
  }

 private:
  int worker_id_;
};
}  // namespace


ParentInspectorHandle::ParentInspectorHandle(
    int id, const std::string& url,
    std::shared_ptr<MainThreadHandle> parent_thread, bool wait_for_connect)
    : id_(id), url_(url), parent_thread_(parent_thread),
      wait_(wait_for_connect) {}

ParentInspectorHandle::~ParentInspectorHandle() {
  parent_thread_->Post(
      std::unique_ptr<Request>(new WorkerFinishedRequest(id_)));
}

void ParentInspectorHandle::WorkerStarted(
    std::shared_ptr<MainThreadHandle> worker_thread, bool waiting) {
  std::unique_ptr<Request> request(
      new WorkerStartedRequest(id_, url_, worker_thread, waiting));
  parent_thread_->Post(std::move(request));
}

std::unique_ptr<inspector::InspectorSession> ParentInspectorHandle::Connect(
    std::unique_ptr<inspector::InspectorSessionDelegate> delegate,
    bool prevent_shutdown) {
  return parent_thread_->Connect(std::move(delegate), prevent_shutdown);
}

void WorkerManager::WorkerFinished(int session_id) {
  children_.erase(session_id);
}

void WorkerManager::WorkerStarted(int session_id,
                                  const WorkerInfo& info,
                                  bool waiting) {
  if (info.worker_thread->Expired())
    return;
  children_.emplace(session_id, info);
  for (const auto& delegate : delegates_) {
    Report(delegate.second, info, waiting);
  }
}

std::unique_ptr<ParentInspectorHandle>
WorkerManager::NewParentHandle(int thread_id, const std::string& url) {
  bool wait = !delegates_waiting_on_start_.empty();
  return std::make_unique<ParentInspectorHandle>(thread_id, url, thread_, wait);
}

void WorkerManager::RemoveAttachDelegate(int id) {
  delegates_.erase(id);
  delegates_waiting_on_start_.erase(id);
}

std::unique_ptr<WorkerManagerEventHandle> WorkerManager::SetAutoAttach(
    std::unique_ptr<WorkerDelegate> attach_delegate) {
  int id = ++next_delegate_id_;
  delegates_[id] = std::move(attach_delegate);
  const auto& delegate = delegates_[id];
  for (const auto& worker : children_) {
    // Waiting is only reported when a worker is started, same as browser
    Report(delegate, worker.second, false);
  }
  return std::make_unique<WorkerManagerEventHandle>(shared_from_this(), id);
}

void WorkerManager::SetWaitOnStartForDelegate(int id, bool wait) {
  if (wait)
    delegates_waiting_on_start_.insert(id);
  else
    delegates_waiting_on_start_.erase(id);
}

void WorkerManagerEventHandle::SetWaitOnStart(bool wait_on_start) {
    manager_->SetWaitOnStartForDelegate(id_, wait_on_start);
}

WorkerManagerEventHandle::~WorkerManagerEventHandle() {
  manager_->RemoveAttachDelegate(id_);
}
}  // namespace inspector
}  // namespace node