blob: a782462ba4c585efbc846a984d7d4a609771265e [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/devtools/devtools_browser_target.h"
6
7#include "base/bind.h"
8#include "base/location.h"
9#include "base/logging.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010#include "base/message_loop/message_loop_proxy.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000011#include "base/values.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010012#include "content/public/browser/browser_thread.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000013#include "net/server/http_server.h"
14
15namespace content {
16
17DevToolsBrowserTarget::DevToolsBrowserTarget(
18 base::MessageLoopProxy* message_loop_proxy,
19 net::HttpServer* http_server,
20 int connection_id)
21 : message_loop_proxy_(message_loop_proxy),
22 http_server_(http_server),
23 connection_id_(connection_id),
24 handlers_deleter_(&handlers_),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010025 weak_factory_(this) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000026}
27
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000028void DevToolsBrowserTarget::RegisterDomainHandler(
29 const std::string& domain,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010030 DevToolsProtocol::Handler* handler,
31 bool handle_on_ui_thread) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000032 DCHECK(handlers_.find(domain) == handlers_.end());
33 handlers_[domain] = handler;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010034 if (handle_on_ui_thread) {
35 handle_on_ui_thread_.insert(domain);
36 handler->SetNotifier(base::Bind(&DevToolsBrowserTarget::RespondFromUIThread,
37 weak_factory_.GetWeakPtr()));
38 } else {
39 handler->SetNotifier(base::Bind(&DevToolsBrowserTarget::Respond,
40 base::Unretained(this)));
41 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000042}
43
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010044void DevToolsBrowserTarget::HandleMessage(const std::string& data) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000045 std::string error_response;
Ben Murdochbb1529c2013-08-08 10:24:53 +010046 scoped_refptr<DevToolsProtocol::Command> command =
47 DevToolsProtocol::ParseCommand(data, &error_response);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010048 if (!command) {
49 Respond(error_response);
50 return;
51 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000052
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010053 DomainHandlerMap::iterator it = handlers_.find(command->domain());
54 if (it == handlers_.end()) {
55 Respond(command->NoSuchMethodErrorResponse()->Serialize());
56 return;
57 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000058
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010059 DevToolsProtocol::Handler* handler = it->second;
60 bool handle_directly = handle_on_ui_thread_.find(command->domain()) ==
61 handle_on_ui_thread_.end();
62 if (handle_directly) {
Ben Murdochbb1529c2013-08-08 10:24:53 +010063 scoped_refptr<DevToolsProtocol::Response> response =
64 handler->HandleCommand(command);
65 if (response && response->is_async_promise())
66 return;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010067 if (response)
68 Respond(response->Serialize());
69 else
70 Respond(command->NoSuchMethodErrorResponse()->Serialize());
71 return;
72 }
73
Ben Murdoch32409262013-08-07 11:04:47 +010074 BrowserThread::PostTask(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010075 BrowserThread::UI,
76 FROM_HERE,
77 base::Bind(&DevToolsBrowserTarget::HandleCommandOnUIThread,
78 this,
79 handler,
Ben Murdochbb1529c2013-08-08 10:24:53 +010080 command));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000081}
82
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010083void DevToolsBrowserTarget::Detach() {
84 message_loop_proxy_ = NULL;
85 http_server_ = NULL;
86
87 std::vector<DevToolsProtocol::Handler*> ui_handlers;
88 for (std::set<std::string>::iterator domain_it = handle_on_ui_thread_.begin();
89 domain_it != handle_on_ui_thread_.end();
90 ++domain_it) {
91 DomainHandlerMap::iterator handler_it = handlers_.find(*domain_it);
92 CHECK(handler_it != handlers_.end());
93 ui_handlers.push_back(handler_it->second);
94 handlers_.erase(handler_it);
95 }
96
Ben Murdoch32409262013-08-07 11:04:47 +010097 BrowserThread::PostTask(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010098 BrowserThread::UI,
99 FROM_HERE,
100 base::Bind(&DevToolsBrowserTarget::DeleteHandlersOnUIThread,
101 this,
Ben Murdoch32409262013-08-07 11:04:47 +0100102 ui_handlers));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100103}
104
105DevToolsBrowserTarget::~DevToolsBrowserTarget() {
106}
107
108void DevToolsBrowserTarget::HandleCommandOnUIThread(
109 DevToolsProtocol::Handler* handler,
Ben Murdochbb1529c2013-08-08 10:24:53 +0100110 scoped_refptr<DevToolsProtocol::Command> command) {
111 scoped_refptr<DevToolsProtocol::Response> response =
112 handler->HandleCommand(command);
113 if (response && response->is_async_promise())
114 return;
115
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100116 if (response)
117 RespondFromUIThread(response->Serialize());
118 else
119 RespondFromUIThread(command->NoSuchMethodErrorResponse()->Serialize());
120}
121
122void DevToolsBrowserTarget::DeleteHandlersOnUIThread(
123 std::vector<DevToolsProtocol::Handler*> handlers) {
124 STLDeleteElements(&handlers);
125}
126
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100127void DevToolsBrowserTarget::Respond(const std::string& message) {
128 if (!http_server_)
129 return;
130 http_server_->SendOverWebSocket(connection_id_, message);
131}
132
133void DevToolsBrowserTarget::RespondFromUIThread(const std::string& message) {
134 if (!message_loop_proxy_)
135 return;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000136 message_loop_proxy_->PostTask(
137 FROM_HERE,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100138 base::Bind(&DevToolsBrowserTarget::Respond, this, message));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000139}
140
141} // namespace content