#include "worker_agent.h" #include "main_thread_interface.h" #include "worker_inspector.h" #include "util-inl.h" namespace node { namespace inspector { namespace protocol { class NodeWorkers : public std::enable_shared_from_this { public: explicit NodeWorkers(std::weak_ptr frontend, std::shared_ptr thread) : frontend_(frontend), thread_(thread) {} void WorkerCreated(const std::string& title, const std::string& url, bool waiting, std::shared_ptr target); void Receive(const std::string& id, const std::string& message); void Send(const std::string& id, const std::string& message); void Detached(const std::string& id); private: std::weak_ptr frontend_; std::shared_ptr thread_; std::unordered_map> sessions_; int next_target_id_ = 0; }; namespace { class AgentWorkerInspectorDelegate : public WorkerDelegate { public: explicit AgentWorkerInspectorDelegate(std::shared_ptr workers) : workers_(workers) {} void WorkerCreated(const std::string& title, const std::string& url, bool waiting, std::shared_ptr target) override { workers_->WorkerCreated(title, url, waiting, target); } private: std::shared_ptr workers_; }; class ParentInspectorSessionDelegate : public InspectorSessionDelegate { public: ParentInspectorSessionDelegate(const std::string& id, std::shared_ptr workers) : id_(id), workers_(workers) {} ~ParentInspectorSessionDelegate() override { workers_->Detached(id_); } void SendMessageToFrontend(const v8_inspector::StringView& msg) override { std::string message = protocol::StringUtil::StringViewToUtf8(msg); workers_->Send(id_, message); } private: std::string id_; std::shared_ptr workers_; }; std::unique_ptr WorkerInfo(const std::string& id, const std::string& title, const std::string& url) { return NodeWorker::WorkerInfo::create() .setWorkerId(id) .setTitle(title) .setUrl(url) .setType("worker").build(); } } // namespace WorkerAgent::WorkerAgent(std::weak_ptr manager) : manager_(manager) {} void WorkerAgent::Wire(UberDispatcher* dispatcher) { frontend_.reset(new NodeWorker::Frontend(dispatcher->channel())); NodeWorker::Dispatcher::wire(dispatcher, this); auto manager = manager_.lock(); CHECK_NOT_NULL(manager); workers_ = std::make_shared(frontend_, manager->MainThread()); } DispatchResponse WorkerAgent::sendMessageToWorker(const String& message, const String& sessionId) { workers_->Receive(sessionId, message); return DispatchResponse::OK(); } DispatchResponse WorkerAgent::enable(bool waitForDebuggerOnStart) { auto manager = manager_.lock(); if (!manager) { return DispatchResponse::OK(); } if (!event_handle_) { std::unique_ptr delegate( new AgentWorkerInspectorDelegate(workers_)); event_handle_ = manager->SetAutoAttach(std::move(delegate)); } event_handle_->SetWaitOnStart(waitForDebuggerOnStart); return DispatchResponse::OK(); } DispatchResponse WorkerAgent::disable() { event_handle_.reset(); return DispatchResponse::OK(); } DispatchResponse WorkerAgent::detach(const String& sessionId) { workers_->Detached(sessionId); return DispatchResponse::OK(); } void NodeWorkers::WorkerCreated(const std::string& title, const std::string& url, bool waiting, std::shared_ptr target) { auto frontend = frontend_.lock(); if (!frontend) return; std::string id = std::to_string(++next_target_id_); auto delegate = thread_->MakeDelegateThreadSafe( std::unique_ptr( new ParentInspectorSessionDelegate(id, shared_from_this()))); sessions_[id] = target->Connect(std::move(delegate), true); frontend->attachedToWorker(id, WorkerInfo(id, title, url), waiting); } void NodeWorkers::Send(const std::string& id, const std::string& message) { auto frontend = frontend_.lock(); if (frontend) frontend->receivedMessageFromWorker(id, message); } void NodeWorkers::Receive(const std::string& id, const std::string& message) { auto it = sessions_.find(id); if (it != sessions_.end()) it->second->Dispatch(Utf8ToStringView(message)->string()); } void NodeWorkers::Detached(const std::string& id) { if (sessions_.erase(id) == 0) return; auto frontend = frontend_.lock(); if (frontend) { frontend->detachedFromWorker(id); } } } // namespace protocol } // namespace inspector } // namespace node