OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/devtools_bridge/client/web_client.h" | 5 #include "components/devtools_bridge/client/web_client.h" |
| 6 |
| 7 #include <map> |
| 8 |
| 9 #include "base/bind.h" |
| 10 #include "base/memory/weak_ptr.h" |
| 11 #include "base/stl_util.h" |
| 12 #include "base/values.h" |
6 #include "content/public/browser/web_contents.h" | 13 #include "content/public/browser/web_contents.h" |
7 #include "content/public/browser/web_contents_delegate.h" | 14 #include "content/public/browser/web_contents_delegate.h" |
| 15 #include "content/public/browser/web_ui_message_handler.h" |
8 | 16 |
9 namespace devtools_bridge { | 17 namespace devtools_bridge { |
10 | 18 |
11 namespace { | 19 namespace { |
12 | 20 |
13 class WebClientImpl : public WebClient, private content::WebContentsDelegate { | 21 class JSProxy : public content::WebUIMessageHandler { |
14 public: | 22 public: |
15 WebClientImpl(content::BrowserContext* context, Delegate* delegate); | 23 class Delegate { |
| 24 public: |
| 25 virtual void OnLoaded() = 0; |
| 26 virtual void SendCommand(int request_id, |
| 27 const base::DictionaryValue* command) = 0; |
| 28 }; |
| 29 |
| 30 explicit JSProxy(Delegate* delegate); |
| 31 |
| 32 void RegisterMessages() override; |
| 33 |
| 34 void StartSession(const std::string& device_id); |
| 35 void StopSession(const std::string& device_id); |
16 | 36 |
17 private: | 37 private: |
| 38 void HandleLoaded(const base::ListValue* args); |
| 39 void HandleSendCommand(const base::ListValue* args); |
| 40 |
18 Delegate* const delegate_; | 41 Delegate* const delegate_; |
| 42 }; |
| 43 |
| 44 class ClientSession { |
| 45 }; |
| 46 |
| 47 class WebClientImpl : public WebClient, |
| 48 private content::WebContentsDelegate, |
| 49 private JSProxy::Delegate, |
| 50 public base::SupportsWeakPtr<WebClientImpl> { |
| 51 public: |
| 52 WebClientImpl(content::BrowserContext* context, |
| 53 WebClient::Delegate* delegate); |
| 54 ~WebClientImpl(); |
| 55 |
| 56 // WebClient implementation. |
| 57 void Connect(const std::string& device_id) override; |
| 58 void Disconnect(const std::string& device_id) override; |
| 59 void DisconnectAll() override; |
| 60 |
| 61 private: |
| 62 typedef std::map<std::string, ClientSession*> ClientSessionMap; |
| 63 |
| 64 // JSProxy::Delegate |
| 65 void OnLoaded() override; |
| 66 void SendCommand(int request_id, |
| 67 const base::DictionaryValue* command) override; |
| 68 |
| 69 |
| 70 void OnCommandSent(int request_id, |
| 71 scoped_ptr<const base::DictionaryValue> response); |
| 72 void OnCommandFailed(int request_id); |
| 73 |
| 74 ClientSessionMap client_session_map_; |
| 75 WebClient::Delegate* const delegate_; |
| 76 JSProxy js_proxy_; |
19 const scoped_ptr<content::WebContents> web_contents_; | 77 const scoped_ptr<content::WebContents> web_contents_; |
| 78 bool is_loaded_; |
20 }; | 79 }; |
21 | 80 |
| 81 // JSProxy implementation |
| 82 |
| 83 JSProxy::JSProxy(Delegate* delegate) |
| 84 : delegate_(delegate) { |
| 85 } |
| 86 |
| 87 void JSProxy::RegisterMessages() { |
| 88 web_ui()->RegisterMessageCallback( |
| 89 "loaded", |
| 90 base::Bind(&JSProxy::HandleLoaded, base::Unretained(this))); |
| 91 web_ui()->RegisterMessageCallback( |
| 92 "sendCommand", |
| 93 base::Bind(&JSProxy::HandleSendCommand, base::Unretained(this))); |
| 94 } |
| 95 |
| 96 void JSProxy::StartSession(const std::string& device_id) { |
| 97 web_ui()->CallJavascriptFunction( |
| 98 "WebClient.instance.startSession", |
| 99 base::StringValue(device_id)); |
| 100 } |
| 101 |
| 102 void JSProxy::StopSession(const std::string& device_id) { |
| 103 web_ui()->CallJavascriptFunction( |
| 104 "WebClient.instance.stopSession", |
| 105 base::StringValue(device_id)); |
| 106 } |
| 107 |
| 108 void JSProxy::HandleLoaded(const base::ListValue* args) { |
| 109 delegate_->OnLoaded(); |
| 110 } |
| 111 |
| 112 void JSProxy::HandleSendCommand(const base::ListValue* args) { |
| 113 if (args->GetSize() != 2) { |
| 114 DLOG(ERROR) << "Wrong number of arguments"; |
| 115 return; |
| 116 } |
| 117 int request_id; |
| 118 if (!args->GetInteger(0, &request_id)) { |
| 119 DLOG(ERROR) << "No request id"; |
| 120 return; |
| 121 } |
| 122 const base::DictionaryValue* command; |
| 123 if (!args->GetDictionary(1, &command)) { |
| 124 DLOG(ERROR) << "No message"; |
| 125 return; |
| 126 } |
| 127 |
| 128 delegate_->SendCommand(request_id, command); |
| 129 } |
| 130 |
| 131 // WebClientImpl implementation. |
| 132 |
22 WebClientImpl::WebClientImpl(content::BrowserContext* context, | 133 WebClientImpl::WebClientImpl(content::BrowserContext* context, |
23 Delegate* delegate) | 134 WebClient::Delegate* delegate) |
24 : delegate_(delegate), | 135 : delegate_(delegate), |
| 136 js_proxy_(this), |
25 web_contents_(content::WebContents::Create( | 137 web_contents_(content::WebContents::Create( |
26 content::WebContents::CreateParams(context))) { | 138 content::WebContents::CreateParams(context))), |
| 139 is_loaded_(false) { |
27 web_contents_->SetDelegate(this); | 140 web_contents_->SetDelegate(this); |
| 141 GURL url("chrome-devtools://bridge/web_client.html"); |
| 142 web_contents_->GetController().LoadURL(url, |
| 143 content::Referrer(), |
| 144 ui::PAGE_TRANSITION_AUTO_TOPLEVEL, |
| 145 std::string()); |
| 146 web_contents_->GetWebUI()->AddMessageHandler(&js_proxy_); |
| 147 } |
| 148 |
| 149 WebClientImpl::~WebClientImpl() { |
| 150 STLDeleteValues(&client_session_map_); |
| 151 } |
| 152 |
| 153 void WebClientImpl::Connect(const std::string& device_id) { |
| 154 if (client_session_map_.find(device_id) != client_session_map_.end()) |
| 155 return; |
| 156 |
| 157 if (is_loaded_) |
| 158 js_proxy_.StartSession(device_id); |
| 159 |
| 160 client_session_map_.insert(std::make_pair(device_id, new ClientSession())); |
| 161 } |
| 162 |
| 163 void WebClientImpl::Disconnect(const std::string& device_id) { |
| 164 ClientSessionMap::iterator session = client_session_map_.find(device_id); |
| 165 if (session == client_session_map_.end()) |
| 166 return; |
| 167 if (is_loaded_) |
| 168 js_proxy_.StartSession(device_id); |
| 169 |
| 170 delete session->second; |
| 171 client_session_map_.erase(session); |
| 172 } |
| 173 |
| 174 void WebClientImpl::DisconnectAll() { |
| 175 if (is_loaded_) { |
| 176 for (ClientSessionMap::iterator i = client_session_map_.begin(); |
| 177 i != client_session_map_.end(); ++i) { |
| 178 js_proxy_.StopSession(i->first); |
| 179 } |
| 180 } |
| 181 STLDeleteValues(&client_session_map_); |
| 182 client_session_map_.clear(); |
| 183 } |
| 184 |
| 185 void WebClientImpl::OnLoaded() { |
| 186 DCHECK(!is_loaded_); |
| 187 for (ClientSessionMap::iterator i = client_session_map_.begin(); |
| 188 i != client_session_map_.end(); ++i) { |
| 189 js_proxy_.StartSession(i->first); |
| 190 } |
| 191 } |
| 192 |
| 193 void WebClientImpl::SendCommand(int request_id, |
| 194 const base::DictionaryValue* command) { |
| 195 delegate_->SendCommand( |
| 196 command, |
| 197 base::Bind(&WebClientImpl::OnCommandSent, AsWeakPtr(), request_id), |
| 198 base::Bind(&WebClientImpl::OnCommandFailed, AsWeakPtr(), request_id)); |
| 199 } |
| 200 |
| 201 void WebClientImpl::OnCommandSent( |
| 202 int request_id, |
| 203 scoped_ptr<const base::DictionaryValue> response) { |
| 204 // TODO(serya): implement |
| 205 } |
| 206 |
| 207 void WebClientImpl::OnCommandFailed(int request_id) { |
| 208 // TODO(serya): implement |
28 } | 209 } |
29 | 210 |
30 } // namespace | 211 } // namespace |
31 | 212 |
32 scoped_ptr<WebClient> WebClient::CreateInstance( | 213 scoped_ptr<WebClient> WebClient::CreateInstance( |
33 content::BrowserContext* context, Delegate* delegate) { | 214 content::BrowserContext* context, Delegate* delegate) { |
34 return make_scoped_ptr(new WebClientImpl(context, delegate)); | 215 return make_scoped_ptr(new WebClientImpl(context, delegate)); |
35 } | 216 } |
36 | 217 |
37 } // namespace devtools_bridge | 218 } // namespace devtools_bridge |
OLD | NEW |