Index: components/devtools_bridge/client/web_client.cc |
diff --git a/components/devtools_bridge/client/web_client.cc b/components/devtools_bridge/client/web_client.cc |
index d323db52e332d2e24d5640ec21331847ab42b112..a744f27d8a04605f6eb3836fb101dee9ad5b6dbc 100644 |
--- a/components/devtools_bridge/client/web_client.cc |
+++ b/components/devtools_bridge/client/web_client.cc |
@@ -3,28 +3,209 @@ |
// found in the LICENSE file. |
#include "components/devtools_bridge/client/web_client.h" |
+ |
+#include <map> |
+ |
+#include "base/bind.h" |
+#include "base/memory/weak_ptr.h" |
+#include "base/stl_util.h" |
+#include "base/values.h" |
#include "content/public/browser/web_contents.h" |
#include "content/public/browser/web_contents_delegate.h" |
+#include "content/public/browser/web_ui_message_handler.h" |
namespace devtools_bridge { |
namespace { |
-class WebClientImpl : public WebClient, private content::WebContentsDelegate { |
+class JSProxy : public content::WebUIMessageHandler { |
public: |
- WebClientImpl(content::BrowserContext* context, Delegate* delegate); |
+ class Delegate { |
+ public: |
+ virtual void OnLoaded() = 0; |
+ virtual void SendCommand(int request_id, |
+ const base::DictionaryValue* command) = 0; |
+ }; |
+ |
+ explicit JSProxy(Delegate* delegate); |
+ |
+ void RegisterMessages() override; |
+ |
+ void StartSession(const std::string& device_id); |
+ void StopSession(const std::string& device_id); |
private: |
+ void HandleLoaded(const base::ListValue* args); |
+ void HandleSendCommand(const base::ListValue* args); |
+ |
Delegate* const delegate_; |
+}; |
+ |
+class ClientSession { |
+}; |
+ |
+class WebClientImpl : public WebClient, |
+ private content::WebContentsDelegate, |
+ private JSProxy::Delegate, |
+ public base::SupportsWeakPtr<WebClientImpl> { |
+ public: |
+ WebClientImpl(content::BrowserContext* context, |
+ WebClient::Delegate* delegate); |
+ ~WebClientImpl(); |
+ |
+ // WebClient implementation. |
+ void Connect(const std::string& device_id) override; |
+ void Disconnect(const std::string& device_id) override; |
+ void DisconnectAll() override; |
+ |
+ private: |
+ typedef std::map<std::string, ClientSession*> ClientSessionMap; |
+ |
+ // JSProxy::Delegate |
+ void OnLoaded() override; |
+ void SendCommand(int request_id, |
+ const base::DictionaryValue* command) override; |
+ |
+ |
+ void OnCommandSent(int request_id, |
+ scoped_ptr<const base::DictionaryValue> response); |
+ void OnCommandFailed(int request_id); |
+ |
+ ClientSessionMap client_session_map_; |
+ WebClient::Delegate* const delegate_; |
+ JSProxy js_proxy_; |
const scoped_ptr<content::WebContents> web_contents_; |
+ bool is_loaded_; |
}; |
+// JSProxy implementation |
+ |
+JSProxy::JSProxy(Delegate* delegate) |
+ : delegate_(delegate) { |
+} |
+ |
+void JSProxy::RegisterMessages() { |
+ web_ui()->RegisterMessageCallback( |
+ "loaded", |
+ base::Bind(&JSProxy::HandleLoaded, base::Unretained(this))); |
+ web_ui()->RegisterMessageCallback( |
+ "sendCommand", |
+ base::Bind(&JSProxy::HandleSendCommand, base::Unretained(this))); |
+} |
+ |
+void JSProxy::StartSession(const std::string& device_id) { |
+ web_ui()->CallJavascriptFunction( |
+ "WebClient.instance.startSession", |
+ base::StringValue(device_id)); |
+} |
+ |
+void JSProxy::StopSession(const std::string& device_id) { |
+ web_ui()->CallJavascriptFunction( |
+ "WebClient.instance.stopSession", |
+ base::StringValue(device_id)); |
+} |
+ |
+void JSProxy::HandleLoaded(const base::ListValue* args) { |
+ delegate_->OnLoaded(); |
+} |
+ |
+void JSProxy::HandleSendCommand(const base::ListValue* args) { |
+ if (args->GetSize() != 2) { |
+ DLOG(ERROR) << "Wrong number of arguments"; |
+ return; |
+ } |
+ int request_id; |
+ if (!args->GetInteger(0, &request_id)) { |
+ DLOG(ERROR) << "No request id"; |
+ return; |
+ } |
+ const base::DictionaryValue* command; |
+ if (!args->GetDictionary(1, &command)) { |
+ DLOG(ERROR) << "No message"; |
+ return; |
+ } |
+ |
+ delegate_->SendCommand(request_id, command); |
+} |
+ |
+// WebClientImpl implementation. |
+ |
WebClientImpl::WebClientImpl(content::BrowserContext* context, |
- Delegate* delegate) |
+ WebClient::Delegate* delegate) |
: delegate_(delegate), |
+ js_proxy_(this), |
web_contents_(content::WebContents::Create( |
- content::WebContents::CreateParams(context))) { |
+ content::WebContents::CreateParams(context))), |
+ is_loaded_(false) { |
web_contents_->SetDelegate(this); |
+ GURL url("chrome-devtools://bridge/web_client.html"); |
+ web_contents_->GetController().LoadURL(url, |
+ content::Referrer(), |
+ ui::PAGE_TRANSITION_AUTO_TOPLEVEL, |
+ std::string()); |
+ web_contents_->GetWebUI()->AddMessageHandler(&js_proxy_); |
+} |
+ |
+WebClientImpl::~WebClientImpl() { |
+ STLDeleteValues(&client_session_map_); |
+} |
+ |
+void WebClientImpl::Connect(const std::string& device_id) { |
+ if (client_session_map_.find(device_id) != client_session_map_.end()) |
+ return; |
+ |
+ if (is_loaded_) |
+ js_proxy_.StartSession(device_id); |
+ |
+ client_session_map_.insert(std::make_pair(device_id, new ClientSession())); |
+} |
+ |
+void WebClientImpl::Disconnect(const std::string& device_id) { |
+ ClientSessionMap::iterator session = client_session_map_.find(device_id); |
+ if (session == client_session_map_.end()) |
+ return; |
+ if (is_loaded_) |
+ js_proxy_.StartSession(device_id); |
+ |
+ delete session->second; |
+ client_session_map_.erase(session); |
+} |
+ |
+void WebClientImpl::DisconnectAll() { |
+ if (is_loaded_) { |
+ for (ClientSessionMap::iterator i = client_session_map_.begin(); |
+ i != client_session_map_.end(); ++i) { |
+ js_proxy_.StopSession(i->first); |
+ } |
+ } |
+ STLDeleteValues(&client_session_map_); |
+ client_session_map_.clear(); |
+} |
+ |
+void WebClientImpl::OnLoaded() { |
+ DCHECK(!is_loaded_); |
+ for (ClientSessionMap::iterator i = client_session_map_.begin(); |
+ i != client_session_map_.end(); ++i) { |
+ js_proxy_.StartSession(i->first); |
+ } |
+} |
+ |
+void WebClientImpl::SendCommand(int request_id, |
+ const base::DictionaryValue* command) { |
+ delegate_->SendCommand( |
+ command, |
+ base::Bind(&WebClientImpl::OnCommandSent, AsWeakPtr(), request_id), |
+ base::Bind(&WebClientImpl::OnCommandFailed, AsWeakPtr(), request_id)); |
+} |
+ |
+void WebClientImpl::OnCommandSent( |
+ int request_id, |
+ scoped_ptr<const base::DictionaryValue> response) { |
+ // TODO(serya): implement |
+} |
+ |
+void WebClientImpl::OnCommandFailed(int request_id) { |
+ // TODO(serya): implement |
} |
} // namespace |