1 // 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.
5 #include "content/browser/devtools/devtools_browser_target.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/stl_util.h"
12 #include "base/values.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "net/server/http_server.h"
18 DevToolsBrowserTarget::DevToolsBrowserTarget(
19 net::HttpServer
* http_server
,
21 : message_loop_proxy_(base::MessageLoopProxy::current()),
22 http_server_(http_server
),
23 connection_id_(connection_id
),
27 void DevToolsBrowserTarget::RegisterDomainHandler(
28 const std::string
& domain
,
29 DevToolsProtocol::Handler
* handler
,
30 bool handle_on_ui_thread
) {
31 DCHECK_EQ(message_loop_proxy_
, base::MessageLoopProxy::current());
33 DCHECK(handlers_
.find(domain
) == handlers_
.end());
34 handlers_
[domain
] = handler
;
35 if (handle_on_ui_thread
) {
36 handle_on_ui_thread_
.insert(domain
);
37 handler
->SetNotifier(base::Bind(&DevToolsBrowserTarget::RespondFromUIThread
,
38 weak_factory_
.GetWeakPtr()));
40 handler
->SetNotifier(base::Bind(&DevToolsBrowserTarget::Respond
,
41 base::Unretained(this)));
45 void DevToolsBrowserTarget::HandleMessage(const std::string
& data
) {
46 DCHECK_EQ(message_loop_proxy_
, base::MessageLoopProxy::current());
48 std::string error_response
;
49 scoped_refptr
<DevToolsProtocol::Command
> command
=
50 DevToolsProtocol::ParseCommand(data
, &error_response
);
52 Respond(error_response
);
56 DomainHandlerMap::iterator it
= handlers_
.find(command
->domain());
57 if (it
== handlers_
.end()) {
58 Respond(command
->NoSuchMethodErrorResponse()->Serialize());
62 DevToolsProtocol::Handler
* handler
= it
->second
;
63 bool handle_directly
= handle_on_ui_thread_
.find(command
->domain()) ==
64 handle_on_ui_thread_
.end();
65 if (handle_directly
) {
66 scoped_refptr
<DevToolsProtocol::Response
> response
=
67 handler
->HandleCommand(command
);
68 if (response
&& response
->is_async_promise())
71 Respond(response
->Serialize());
73 Respond(command
->NoSuchMethodErrorResponse()->Serialize());
77 BrowserThread::PostTask(
80 base::Bind(&DevToolsBrowserTarget::HandleCommandOnUIThread
,
86 void DevToolsBrowserTarget::Detach() {
87 DCHECK_EQ(message_loop_proxy_
, base::MessageLoopProxy::current());
92 std::vector
<DevToolsProtocol::Handler
*> ui_handlers
;
93 for (std::set
<std::string
>::iterator domain_it
= handle_on_ui_thread_
.begin();
94 domain_it
!= handle_on_ui_thread_
.end();
96 DomainHandlerMap::iterator handler_it
= handlers_
.find(*domain_it
);
97 CHECK(handler_it
!= handlers_
.end());
98 ui_handlers
.push_back(handler_it
->second
);
99 handlers_
.erase(handler_it
);
102 STLDeleteValues(&handlers_
);
104 BrowserThread::PostTask(
107 base::Bind(&DevToolsBrowserTarget::DeleteHandlersOnUIThread
,
112 DevToolsBrowserTarget::~DevToolsBrowserTarget() {
113 // DCHECK that Detach has been called or no handler has ever been registered.
114 DCHECK(handlers_
.empty());
117 void DevToolsBrowserTarget::HandleCommandOnUIThread(
118 DevToolsProtocol::Handler
* handler
,
119 scoped_refptr
<DevToolsProtocol::Command
> command
) {
120 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
121 scoped_refptr
<DevToolsProtocol::Response
> response
=
122 handler
->HandleCommand(command
);
123 if (response
&& response
->is_async_promise())
127 RespondFromUIThread(response
->Serialize());
129 RespondFromUIThread(command
->NoSuchMethodErrorResponse()->Serialize());
132 void DevToolsBrowserTarget::DeleteHandlersOnUIThread(
133 std::vector
<DevToolsProtocol::Handler
*> handlers
) {
134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
135 STLDeleteElements(&handlers
);
138 void DevToolsBrowserTarget::Respond(const std::string
& message
) {
139 DCHECK_EQ(message_loop_proxy_
, base::MessageLoopProxy::current());
142 http_server_
->SendOverWebSocket(connection_id_
, message
);
145 void DevToolsBrowserTarget::RespondFromUIThread(const std::string
& message
) {
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
147 message_loop_proxy_
->PostTask(
149 base::Bind(&DevToolsBrowserTarget::Respond
, this, message
));
152 } // namespace content