#include "base/compiler_specific.h"
#include "base/json/json_reader.h"
#include "base/lazy_instance.h"
+#include "base/memory/singleton.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "content/public/browser/devtools_external_agent_proxy_delegate.h"
#include "content/public/browser/user_metrics.h"
#include "net/base/escape.h"
+#include "net/base/net_errors.h"
using content::BrowserThread;
const int kMinVersionNewWithURL = 32;
const int kNewPageNavigateDelayMs = 500;
+} // namespace
+
// DiscoveryRequest -----------------------------------------------------
-class DiscoveryRequest : public base::RefCountedThreadSafe<
- DiscoveryRequest,
- BrowserThread::DeleteOnUIThread> {
+class DevToolsAndroidBridge::DiscoveryRequest
+ : public base::RefCountedThreadSafe<DiscoveryRequest,
+ BrowserThread::DeleteOnUIThread> {
public:
- typedef AndroidDeviceManager::Device Device;
- typedef AndroidDeviceManager::Devices Devices;
- typedef AndroidDeviceManager::DeviceInfo DeviceInfo;
- typedef DevToolsAndroidBridge::RemoteDevice RemoteDevice;
- typedef DevToolsAndroidBridge::RemoteDevices RemoteDevices;
- typedef DevToolsAndroidBridge::RemoteBrowser RemoteBrowser;
- typedef DevToolsAndroidBridge::RemoteBrowsers RemoteBrowsers;
- typedef base::Callback<void(const RemoteDevices&)> DiscoveryCallback;
-
DiscoveryRequest(AndroidDeviceManager* device_manager,
- const DiscoveryCallback& callback);
+ const DeviceListCallback& callback);
private:
friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
friend class base::DeleteHelper<DiscoveryRequest>;
virtual ~DiscoveryRequest();
- void ReceivedDevices(const Devices& devices);
- void ReceivedDeviceInfo(scoped_refptr<Device> device,
- const DeviceInfo& device_info);
+ void ReceivedDevices(const AndroidDeviceManager::Devices& devices);
+ void ReceivedDeviceInfo(scoped_refptr<AndroidDeviceManager::Device> device,
+ const AndroidDeviceManager::DeviceInfo& device_info);
void ReceivedVersion(scoped_refptr<RemoteBrowser>,
int result,
const std::string& response);
int result,
const std::string& response);
- DiscoveryCallback callback_;
- RemoteDevices remote_devices_;
+ DeviceListCallback callback_;
+ CompleteDevices complete_devices_;
};
-DiscoveryRequest::DiscoveryRequest(
+DevToolsAndroidBridge::DiscoveryRequest::DiscoveryRequest(
AndroidDeviceManager* device_manager,
- const DiscoveryCallback& callback)
+ const DeviceListCallback& callback)
: callback_(callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
device_manager->QueryDevices(
base::Bind(&DiscoveryRequest::ReceivedDevices, this));
}
-DiscoveryRequest::~DiscoveryRequest() {
+DevToolsAndroidBridge::DiscoveryRequest::~DiscoveryRequest() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- callback_.Run(remote_devices_);
+ callback_.Run(complete_devices_);
}
-void DiscoveryRequest::ReceivedDevices(const Devices& devices) {
+void DevToolsAndroidBridge::DiscoveryRequest::ReceivedDevices(
+ const AndroidDeviceManager::Devices& devices) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- for (Devices::const_iterator it = devices.begin();
- it != devices.end(); ++it) {
- (*it)->QueryDeviceInfo(
- base::Bind(&DiscoveryRequest::ReceivedDeviceInfo, this, *it));
+ for (const auto& device : devices) {
+ device->QueryDeviceInfo(
+ base::Bind(&DiscoveryRequest::ReceivedDeviceInfo, this, device));
}
}
-void DiscoveryRequest::ReceivedDeviceInfo(scoped_refptr<Device> device,
- const DeviceInfo& device_info) {
+void DevToolsAndroidBridge::DiscoveryRequest::ReceivedDeviceInfo(
+ scoped_refptr<AndroidDeviceManager::Device> device,
+ const AndroidDeviceManager::DeviceInfo& device_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
scoped_refptr<RemoteDevice> remote_device =
- new RemoteDevice(device, device_info);
- remote_devices_.push_back(remote_device);
+ new RemoteDevice(device->serial(), device_info);
+ complete_devices_.push_back(std::make_pair(device, remote_device));
for (RemoteBrowsers::iterator it = remote_device->browsers().begin();
it != remote_device->browsers().end(); ++it) {
- (*it)->SendJsonRequest(
+ device->SendJsonRequest(
+ (*it)->socket(),
kVersionRequest,
base::Bind(&DiscoveryRequest::ReceivedVersion, this, *it));
- (*it)->SendJsonRequest(
+ device->SendJsonRequest(
+ (*it)->socket(),
kPageListRequest,
base::Bind(&DiscoveryRequest::ReceivedPages, this, *it));
}
}
-void DiscoveryRequest::ReceivedVersion(scoped_refptr<RemoteBrowser> browser,
- int result,
- const std::string& response) {
+void DevToolsAndroidBridge::DiscoveryRequest::ReceivedVersion(
+ scoped_refptr<RemoteBrowser> browser,
+ int result,
+ const std::string& response) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (result < 0)
return;
std::vector<std::string> parts;
Tokenize(browser_name, "/", &parts);
if (parts.size() == 2)
- browser->set_version(parts[1]);
+ browser->version_ = parts[1];
else
- browser->set_version(browser_name);
+ browser->version_ = browser_name;
}
std::string package;
if (dict->GetString("Android-Package", &package)) {
- browser->set_display_name(
- AdbDeviceInfoQuery::GetDisplayName(browser->socket(), package));
+ browser->display_name_ =
+ AdbDeviceInfoQuery::GetDisplayName(browser->socket(), package);
}
}
}
-void DiscoveryRequest::ReceivedPages(scoped_refptr<RemoteBrowser> browser,
- int result,
- const std::string& response) {
+void DevToolsAndroidBridge::DiscoveryRequest::ReceivedPages(
+ scoped_refptr<RemoteBrowser> browser,
+ int result,
+ const std::string& response) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (result < 0)
return;
scoped_ptr<base::Value> value(base::JSONReader::Read(response));
base::ListValue* list_value;
- if (value && value->GetAsList(&list_value))
- browser->SetPageDescriptors(*list_value);
+ if (value && value->GetAsList(&list_value)) {
+ for (const auto& page_value : *list_value) {
+ base::DictionaryValue* dict;
+ if (page_value->GetAsDictionary(&dict)) {
+ browser->pages_.push_back(
+ new RemotePage(browser->browser_id_, *dict, browser->IsWebView()));
+ }
+ }
+ }
}
// ProtocolCommand ------------------------------------------------------------
+namespace {
+
class ProtocolCommand
- : public DevToolsAndroidBridge::AndroidWebSocket::Delegate {
+ : public AndroidDeviceManager::AndroidWebSocket::Delegate {
public:
ProtocolCommand(
- scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser,
+ scoped_refptr<AndroidDeviceManager::Device> device,
+ const std::string& socket,
const std::string& debug_url,
const std::string& command,
const base::Closure callback);
private:
- virtual void OnSocketOpened() OVERRIDE;
- virtual void OnFrameRead(const std::string& message) OVERRIDE;
- virtual void OnSocketClosed() OVERRIDE;
- virtual ~ProtocolCommand();
+ void OnSocketOpened() override;
+ void OnFrameRead(const std::string& message) override;
+ void OnSocketClosed() override;
+ ~ProtocolCommand() override;
const std::string command_;
const base::Closure callback_;
- scoped_ptr<DevToolsAndroidBridge::AndroidWebSocket> web_socket_;
+ scoped_ptr<AndroidDeviceManager::AndroidWebSocket> web_socket_;
DISALLOW_COPY_AND_ASSIGN(ProtocolCommand);
};
ProtocolCommand::ProtocolCommand(
- scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser,
+ scoped_refptr<AndroidDeviceManager::Device> device,
+ const std::string& socket,
const std::string& debug_url,
const std::string& command,
const base::Closure callback)
: command_(command),
callback_(callback),
- web_socket_(browser->CreateWebSocket(debug_url, this)) {
+ web_socket_(device->CreateWebSocket(socket, debug_url, this)) {
}
void ProtocolCommand::OnSocketOpened() {
} // namespace
-class AgentHostDelegate;
-
-typedef std::map<std::string, AgentHostDelegate*> AgentHostDelegates;
-
-base::LazyInstance<AgentHostDelegates>::Leaky g_host_delegates =
- LAZY_INSTANCE_INITIALIZER;
-
DevToolsAndroidBridge::Wrapper::Wrapper(content::BrowserContext* context) {
bridge_ = new DevToolsAndroidBridge(Profile::FromBrowserContext(context));
}
return new DevToolsAndroidBridge::Wrapper(context);
}
-
// AgentHostDelegate ----------------------------------------------------------
-class AgentHostDelegate
+class DevToolsAndroidBridge::AgentHostDelegate
: public content::DevToolsExternalAgentProxyDelegate,
- public DevToolsAndroidBridge::AndroidWebSocket::Delegate {
+ public AndroidDeviceManager::AndroidWebSocket::Delegate {
public:
static scoped_refptr<content::DevToolsAgentHost> GetOrCreateAgentHost(
+ scoped_refptr<DevToolsAndroidBridge> bridge,
const std::string& id,
- scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser,
- const std::string& debug_url);
+ const BrowserId& browser_id,
+ const std::string& debug_url,
+ bool is_web_view);
private:
AgentHostDelegate(
+ scoped_refptr<DevToolsAndroidBridge> bridge,
const std::string& id,
- scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser,
- const std::string& debug_url);
- virtual ~AgentHostDelegate();
- virtual void Attach(content::DevToolsExternalAgentProxy* proxy) OVERRIDE;
- virtual void Detach() OVERRIDE;
- virtual void SendMessageToBackend(
- const std::string& message) OVERRIDE;
- virtual void OnSocketOpened() OVERRIDE;
- virtual void OnFrameRead(const std::string& message) OVERRIDE;
- virtual void OnSocketClosed() OVERRIDE;
-
- const std::string id_;
- scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser_;
- const std::string debug_url_;
+ const BrowserId& browser_id,
+ const std::string& debug_url,
+ bool is_web_view);
+ ~AgentHostDelegate() override;
+ void Attach(content::DevToolsExternalAgentProxy* proxy) override;
+ void Detach() override;
+ void SendMessageToBackend(const std::string& message) override;
+ void OnSocketOpened() override;
+ void OnFrameRead(const std::string& message) override;
+ void OnSocketClosed() override;
+
+ std::string id_;
+ scoped_refptr<DevToolsAndroidBridge> bridge_;
+ BrowserId browser_id_;
+ std::string debug_url_;
bool socket_opened_;
bool is_web_view_;
std::vector<std::string> pending_messages_;
- scoped_ptr<DevToolsAndroidBridge::AndroidWebSocket> web_socket_;
+ scoped_refptr<AndroidDeviceManager::Device> device_;
+ scoped_ptr<AndroidDeviceManager::AndroidWebSocket> web_socket_;
content::DevToolsAgentHost* agent_host_;
content::DevToolsExternalAgentProxy* proxy_;
DISALLOW_COPY_AND_ASSIGN(AgentHostDelegate);
// static
scoped_refptr<content::DevToolsAgentHost>
-AgentHostDelegate::GetOrCreateAgentHost(
+DevToolsAndroidBridge::AgentHostDelegate::GetOrCreateAgentHost(
+ scoped_refptr<DevToolsAndroidBridge> bridge,
const std::string& id,
- scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser,
- const std::string& debug_url) {
+ const BrowserId& browser_id,
+ const std::string& debug_url,
+ bool is_web_view) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- AgentHostDelegates::iterator it = g_host_delegates.Get().find(id);
- if (it != g_host_delegates.Get().end())
+ AgentHostDelegates::iterator it = bridge->host_delegates_.find(id);
+ if (it != bridge->host_delegates_.end())
return it->second->agent_host_;
- AgentHostDelegate* delegate = new AgentHostDelegate(id, browser, debug_url);
+ AgentHostDelegate* delegate =
+ new AgentHostDelegate(bridge, id, browser_id, debug_url, is_web_view);
scoped_refptr<content::DevToolsAgentHost> result =
content::DevToolsAgentHost::Create(delegate);
delegate->agent_host_ = result.get();
return result;
}
-AgentHostDelegate::AgentHostDelegate(
+DevToolsAndroidBridge::AgentHostDelegate::AgentHostDelegate(
+ scoped_refptr<DevToolsAndroidBridge> bridge,
const std::string& id,
- scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser,
- const std::string& debug_url)
+ const BrowserId& browser_id,
+ const std::string& debug_url,
+ bool is_web_view)
: id_(id),
- browser_(browser),
+ bridge_(bridge),
+ browser_id_(browser_id),
debug_url_(debug_url),
socket_opened_(false),
- is_web_view_(browser->IsWebView()),
+ is_web_view_(is_web_view),
agent_host_(NULL),
proxy_(NULL) {
- g_host_delegates.Get()[id] = this;
+ bridge_->host_delegates_[id] = this;
}
-AgentHostDelegate::~AgentHostDelegate() {
- g_host_delegates.Get().erase(id_);
+DevToolsAndroidBridge::AgentHostDelegate::~AgentHostDelegate() {
+ bridge_->host_delegates_.erase(id_);
}
-void AgentHostDelegate::Attach(content::DevToolsExternalAgentProxy* proxy) {
+void DevToolsAndroidBridge::AgentHostDelegate::Attach(
+ content::DevToolsExternalAgentProxy* proxy) {
proxy_ = proxy;
content::RecordAction(base::UserMetricsAction(is_web_view_ ?
"DevTools_InspectAndroidWebView" : "DevTools_InspectAndroidPage"));
- web_socket_.reset(browser_->CreateWebSocket(debug_url_, this));
+
+ // Retain the device so it's not released until AgentHost is detached.
+ device_ = bridge_->FindDevice(browser_id_.first);
+ if (!device_.get())
+ return;
+
+ web_socket_.reset(
+ device_->CreateWebSocket(browser_id_.second, debug_url_, this));
}
-void AgentHostDelegate::Detach() {
+void DevToolsAndroidBridge::AgentHostDelegate::Detach() {
web_socket_.reset();
+ device_ = nullptr;
}
-void AgentHostDelegate::SendMessageToBackend(const std::string& message) {
+void DevToolsAndroidBridge::AgentHostDelegate::SendMessageToBackend(
+ const std::string& message) {
if (socket_opened_)
web_socket_->SendFrame(message);
else
pending_messages_.push_back(message);
}
-void AgentHostDelegate::OnSocketOpened() {
+void DevToolsAndroidBridge::AgentHostDelegate::OnSocketOpened() {
socket_opened_ = true;
for (std::vector<std::string>::iterator it = pending_messages_.begin();
it != pending_messages_.end(); ++it) {
pending_messages_.clear();
}
-void AgentHostDelegate::OnFrameRead(const std::string& message) {
+void DevToolsAndroidBridge::AgentHostDelegate::OnFrameRead(
+ const std::string& message) {
if (proxy_)
proxy_->DispatchOnClientHost(message);
}
-void AgentHostDelegate::OnSocketClosed() {
+void DevToolsAndroidBridge::AgentHostDelegate::OnSocketClosed() {
if (proxy_)
proxy_->ConnectionClosed();
}
//// RemotePageTarget ----------------------------------------------
-class RemotePageTarget : public DevToolsTargetImpl,
- public DevToolsAndroidBridge::RemotePage {
+class DevToolsAndroidBridge::RemotePageTarget : public DevToolsTargetImpl {
public:
- RemotePageTarget(scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser,
- const base::DictionaryValue& value);
- virtual ~RemotePageTarget();
-
- // DevToolsAndroidBridge::RemotePage implementation.
- virtual DevToolsTargetImpl* GetTarget() OVERRIDE;
- virtual std::string GetFrontendURL() OVERRIDE;
+ RemotePageTarget(scoped_refptr<DevToolsAndroidBridge> bridge,
+ const BrowserId& browser_id,
+ const base::DictionaryValue& value,
+ bool is_web_view_);
+ ~RemotePageTarget() override;
// DevToolsTargetImpl overrides.
- virtual std::string GetId() const OVERRIDE;
- virtual bool IsAttached() const OVERRIDE;
- virtual bool Activate() const OVERRIDE;
- virtual bool Close() const OVERRIDE;
- virtual void Inspect(Profile* profile) const OVERRIDE;
- virtual void Reload() const OVERRIDE;
+ std::string GetId() const override;
+ bool IsAttached() const override;
+ bool Activate() const override;
+ bool Close() const override;
+ void Inspect(Profile* profile) const override;
+ void Reload() const override;
void Navigate(const std::string& url, base::Closure callback) const;
private:
- scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser_;
+ scoped_refptr<DevToolsAndroidBridge> bridge_;
+ BrowserId browser_id_;
std::string debug_url_;
std::string frontend_url_;
std::string remote_id_;
}
static std::string BuildUniqueTargetId(
- DevToolsAndroidBridge::RemoteBrowser* browser,
+ const DevToolsAndroidBridge::BrowserId& browser_id,
const base::DictionaryValue& value) {
- return base::StringPrintf("%s:%s:%s", browser->serial().c_str(),
- browser->socket().c_str(), GetStringProperty(value, "id").c_str());
+ return base::StringPrintf("%s:%s:%s", browser_id.first.c_str(),
+ browser_id.second.c_str(), GetStringProperty(value, "id").c_str());
+}
+
+static std::string GetFrontendURL(const base::DictionaryValue& value) {
+ std::string frontend_url = GetStringProperty(value, "devtoolsFrontendUrl");
+ size_t ws_param = frontend_url.find("?ws");
+ if (ws_param != std::string::npos)
+ frontend_url = frontend_url.substr(0, ws_param);
+ if (frontend_url.find("http:") == 0)
+ frontend_url = "https:" + frontend_url.substr(5);
+ return frontend_url;
}
static std::string GetDebugURL(const base::DictionaryValue& value) {
if (debug_url.find("ws://") == 0)
debug_url = debug_url.substr(5);
else
- debug_url = "";
+ debug_url = std::string();
return debug_url;
}
-RemotePageTarget::RemotePageTarget(
- scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser,
- const base::DictionaryValue& value)
+DevToolsAndroidBridge::RemotePageTarget::RemotePageTarget(
+ scoped_refptr<DevToolsAndroidBridge> bridge,
+ const BrowserId& browser_id,
+ const base::DictionaryValue& value,
+ bool is_web_view)
: DevToolsTargetImpl(AgentHostDelegate::GetOrCreateAgentHost(
- BuildUniqueTargetId(browser.get(), value),
- browser, GetDebugURL(value))),
- browser_(browser),
+ bridge,
+ BuildUniqueTargetId(browser_id, value),
+ browser_id,
+ GetDebugURL(value),
+ is_web_view)),
+ bridge_(bridge),
+ browser_id_(browser_id),
debug_url_(GetDebugURL(value)),
+ frontend_url_(GetFrontendURL(value)),
remote_id_(GetStringProperty(value, "id")),
remote_type_(GetStringProperty(value, "type")),
- local_id_(BuildUniqueTargetId(browser.get(), value)) {
+ local_id_(BuildUniqueTargetId(browser_id, value)) {
set_type("adb_page");
set_url(GURL(GetStringProperty(value, "url")));
set_title(base::UTF16ToUTF8(net::UnescapeForHTML(base::UTF8ToUTF16(
set_description(GetStringProperty(value, "description"));
set_favicon_url(GURL(GetStringProperty(value, "faviconUrl")));
debug_url_ = GetDebugURL(value);
- frontend_url_ = GetStringProperty(value, "devtoolsFrontendUrl");
-
- size_t ws_param = frontend_url_.find("?ws");
- if (ws_param != std::string::npos)
- frontend_url_ = frontend_url_.substr(0, ws_param);
- if (frontend_url_.find("http:") == 0)
- frontend_url_ = "https:" + frontend_url_.substr(5);
-}
-
-RemotePageTarget::~RemotePageTarget() {
}
-DevToolsTargetImpl* RemotePageTarget::GetTarget() {
- return this;
+DevToolsAndroidBridge::RemotePageTarget::~RemotePageTarget() {
}
-std::string RemotePageTarget::GetFrontendURL() {
- return frontend_url_;
-}
-
-std::string RemotePageTarget::GetId() const {
+std::string DevToolsAndroidBridge::RemotePageTarget::GetId() const {
return local_id_;
}
-bool RemotePageTarget::IsAttached() const {
+bool DevToolsAndroidBridge::RemotePageTarget::IsAttached() const {
return debug_url_.empty();
}
static void NoOp(int, const std::string&) {}
-void RemotePageTarget::Inspect(Profile* profile) const {
+void DevToolsAndroidBridge::RemotePageTarget::Inspect(Profile* profile) const {
Activate();
bool isWorker = remote_type_ == kTargetTypeWorker ||
remote_type_ == kTargetTypeServiceWorker;
isWorker);
}
-bool RemotePageTarget::Activate() const {
+bool DevToolsAndroidBridge::RemotePageTarget::Activate() const {
std::string request = base::StringPrintf(kActivatePageRequest,
remote_id_.c_str());
- browser_->SendJsonRequest(request, base::Bind(&NoOp));
+ bridge_->SendJsonRequest(browser_id_, request, base::Bind(&NoOp));
return true;
}
-bool RemotePageTarget::Close() const {
+bool DevToolsAndroidBridge::RemotePageTarget::Close() const {
std::string request = base::StringPrintf(kClosePageRequest,
remote_id_.c_str());
- browser_->SendJsonRequest(request, base::Bind(&NoOp));
+ bridge_->SendJsonRequest(browser_id_, request, base::Bind(&NoOp));
return true;
}
-void RemotePageTarget::Reload() const {
- browser_->SendProtocolCommand(debug_url_, kPageReloadCommand, NULL,
- base::Closure());
+void DevToolsAndroidBridge::RemotePageTarget::Reload() const {
+ bridge_->SendProtocolCommand(browser_id_, debug_url_, kPageReloadCommand,
+ NULL, base::Closure());
}
-void RemotePageTarget::Navigate(const std::string& url,
- base::Closure callback) const {
+void DevToolsAndroidBridge::RemotePageTarget::Navigate(
+ const std::string& url,
+ base::Closure callback) const {
base::DictionaryValue params;
params.SetString(kUrlParam, url);
- browser_->SendProtocolCommand(debug_url_, kPageNavigateCommand, ¶ms,
- callback);
+ bridge_->SendProtocolCommand(browser_id_, debug_url_, kPageNavigateCommand,
+ ¶ms, callback);
+}
+
+// DevToolsAndroidBridge::RemotePage ------------------------------------------
+
+DevToolsAndroidBridge::RemotePage::RemotePage(
+ const BrowserId& browser_id,
+ const base::DictionaryValue& dict,
+ bool is_web_view)
+ : browser_id_(browser_id),
+ frontend_url_(GetFrontendURL(dict)),
+ is_web_view_(is_web_view),
+ dict_(dict.DeepCopy()) {
+}
+
+DevToolsAndroidBridge::RemotePage::~RemotePage() {
}
// DevToolsAndroidBridge::RemoteBrowser ---------------------------------------
DevToolsAndroidBridge::RemoteBrowser::RemoteBrowser(
- scoped_refptr<Device> device,
+ const std::string& serial,
const AndroidDeviceManager::BrowserInfo& browser_info)
- : device_(device),
- socket_(browser_info.socket_name),
+ : browser_id_(std::make_pair(serial, browser_info.socket_name)),
display_name_(browser_info.display_name),
- type_(browser_info.type),
- page_descriptors_(new base::ListValue()) {
+ type_(browser_info.type) {
}
-bool DevToolsAndroidBridge::RemoteBrowser::IsChrome() const {
+bool DevToolsAndroidBridge::RemoteBrowser::IsChrome() {
return type_ == AndroidDeviceManager::BrowserInfo::kTypeChrome;
}
-bool DevToolsAndroidBridge::RemoteBrowser::IsWebView() const {
+bool DevToolsAndroidBridge::RemoteBrowser::IsWebView() {
return type_ == AndroidDeviceManager::BrowserInfo::kTypeWebView;
}
DevToolsAndroidBridge::RemoteBrowser::ParsedVersion
-DevToolsAndroidBridge::RemoteBrowser::GetParsedVersion() const {
+DevToolsAndroidBridge::RemoteBrowser::GetParsedVersion() {
ParsedVersion result;
std::vector<std::string> parts;
Tokenize(version_, ".", &parts);
return result;
}
-std::vector<DevToolsAndroidBridge::RemotePage*>
-DevToolsAndroidBridge::RemoteBrowser::CreatePages() {
- std::vector<DevToolsAndroidBridge::RemotePage*> result;
- for (size_t i = 0; i < page_descriptors_->GetSize(); ++i) {
- base::Value* item;
- page_descriptors_->Get(i, &item);
- if (!item)
- continue;
- base::DictionaryValue* dict;
- if (!item->GetAsDictionary(&dict))
- continue;
- result.push_back(new RemotePageTarget(this, *dict));
- }
- return result;
-}
-
-void DevToolsAndroidBridge::RemoteBrowser::SetPageDescriptors(
- const base::ListValue& list) {
- page_descriptors_.reset(list.DeepCopy());
+DevToolsTargetImpl*
+DevToolsAndroidBridge::CreatePageTarget(scoped_refptr<RemotePage> page) {
+ return new RemotePageTarget(this, page->browser_id_, *page->dict_,
+ page->is_web_view_);
}
-static void RespondOnUIThread(
- const DevToolsAndroidBridge::JsonRequestCallback& callback,
- int result,
- const std::string& response) {
- if (callback.is_null())
+void DevToolsAndroidBridge::SendJsonRequest(
+ const BrowserId& browser_id,
+ const std::string& request,
+ const JsonRequestCallback& callback) {
+ scoped_refptr<AndroidDeviceManager::Device> device(
+ FindDevice(browser_id.first));
+ if (!device.get()) {
+ callback.Run(net::ERR_FAILED, std::string());
return;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::Bind(callback, result, response));
-}
-
-void DevToolsAndroidBridge::RemoteBrowser::SendJsonRequest(
- const std::string& request, const JsonRequestCallback& callback) {
- device_->SendJsonRequest(socket_, request, callback);
+ }
+ device->SendJsonRequest(browser_id.second, request, callback);
}
-void DevToolsAndroidBridge::RemoteBrowser::SendProtocolCommand(
+void DevToolsAndroidBridge::SendProtocolCommand(
+ const BrowserId& browser_id,
const std::string& debug_url,
const std::string& method,
base::DictionaryValue* params,
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (debug_url.empty())
return;
+ scoped_refptr<AndroidDeviceManager::Device> device(
+ FindDevice(browser_id.first));
+ if (!device.get()) {
+ callback.Run();
+ return;
+ }
DevToolsProtocol::Command command(1, method, params);
- new ProtocolCommand(this, debug_url, command.Serialize(), callback);
-}
-
-void DevToolsAndroidBridge::RemoteBrowser::Open(
- const std::string& url,
- const DevToolsAndroidBridge::RemotePageCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- InnerOpen(url, base::Bind(&RemoteBrowser::RespondToOpenOnUIThread,
- this, callback));
+ new ProtocolCommand(device, browser_id.second, debug_url,
+ command.Serialize(), callback);
}
scoped_refptr<content::DevToolsAgentHost>
-DevToolsAndroidBridge::RemoteBrowser::GetAgentHost() {
+DevToolsAndroidBridge::GetBrowserAgentHost(
+ scoped_refptr<RemoteBrowser> browser) {
return AgentHostDelegate::GetOrCreateAgentHost(
- "adb:" + device_->serial() + ":" + socket_, this, kBrowserTargetSocket);
+ this,
+ "adb:" + browser->serial() + ":" + browser->socket(),
+ browser->browser_id_,
+ kBrowserTargetSocket,
+ browser->IsWebView());
}
-DevToolsAndroidBridge::AndroidWebSocket*
-DevToolsAndroidBridge::RemoteBrowser::CreateWebSocket(
- const std::string& url,
- DevToolsAndroidBridge::AndroidWebSocket::Delegate* delegate) {
- return device_->CreateWebSocket(socket_, url, delegate);
+scoped_refptr<AndroidDeviceManager::Device> DevToolsAndroidBridge::FindDevice(
+ const std::string& serial) {
+ DeviceMap::iterator it = device_map_.find(serial);
+ return it == device_map_.end() ? nullptr : it->second;
}
-void DevToolsAndroidBridge::RemoteBrowser::RespondToOpenOnUIThread(
- const DevToolsAndroidBridge::RemotePageCallback& callback,
+void DevToolsAndroidBridge::RespondToOpenOnUIThread(
+ scoped_refptr<RemoteBrowser> browser,
+ const RemotePageCallback& callback,
int result,
const std::string& response) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
scoped_ptr<base::Value> value(base::JSONReader::Read(response));
base::DictionaryValue* dict;
if (value && value->GetAsDictionary(&dict)) {
- RemotePageTarget* new_page = new RemotePageTarget(this, *dict);
+ scoped_refptr<RemotePage> new_page(
+ new RemotePage(browser->browser_id_, *dict, browser->IsWebView()));
callback.Run(new_page);
}
}
-void DevToolsAndroidBridge::RemoteBrowser::InnerOpen(
+void DevToolsAndroidBridge::OpenRemotePage(
+ scoped_refptr<RemoteBrowser> browser,
const std::string& input_url,
- const JsonRequestCallback& callback) {
+ const DevToolsAndroidBridge::RemotePageCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
GURL gurl(input_url);
if (!gurl.is_valid()) {
gurl = GURL("http://" + input_url);
if (!gurl.is_valid())
- return;
+ return;
}
std::string url = gurl.spec();
+ RemoteBrowser::ParsedVersion parsed_version = browser->GetParsedVersion();
- ParsedVersion parsed_version = GetParsedVersion();
- if (IsChrome() &&
+ if (browser->IsChrome() &&
!parsed_version.empty() &&
parsed_version[0] >= kMinVersionNewWithURL) {
std::string query = net::EscapeQueryParamValue(url, false /* use_plus */);
std::string request =
base::StringPrintf(kNewPageRequestWithURL, query.c_str());
- SendJsonRequest(request, callback);
+ SendJsonRequest(browser->browser_id_, request,
+ base::Bind(&DevToolsAndroidBridge::RespondToOpenOnUIThread,
+ this, browser, callback));
} else {
- SendJsonRequest(kNewPageRequest,
- base::Bind(&RemoteBrowser::PageCreatedOnUIThread, this,
- callback, url));
+ SendJsonRequest(browser->browser_id_, kNewPageRequest,
+ base::Bind(&DevToolsAndroidBridge::PageCreatedOnUIThread,
+ this, browser, callback, url));
}
}
-void DevToolsAndroidBridge::RemoteBrowser::PageCreatedOnUIThread(
- const JsonRequestCallback& callback,
- const std::string& url, int result, const std::string& response) {
+void DevToolsAndroidBridge::PageCreatedOnUIThread(
+ scoped_refptr<RemoteBrowser> browser,
+ const RemotePageCallback& callback,
+ const std::string& url,
+ int result,
+ const std::string& response) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (result < 0)
// (crbug.com/311014). This can be avoided by adding a moderate delay.
BrowserThread::PostDelayedTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RemoteBrowser::NavigatePageOnUIThread,
- this, callback, result, response, url),
+ base::Bind(&DevToolsAndroidBridge::NavigatePageOnUIThread,
+ this, browser, callback, result, response, url),
base::TimeDelta::FromMilliseconds(kNewPageNavigateDelayMs));
}
-void DevToolsAndroidBridge::RemoteBrowser::NavigatePageOnUIThread(
- const JsonRequestCallback& callback,
- int result, const std::string& response, const std::string& url) {
+void DevToolsAndroidBridge::NavigatePageOnUIThread(
+ scoped_refptr<RemoteBrowser> browser,
+ const RemotePageCallback& callback,
+ int result,
+ const std::string& response,
+ const std::string& url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
scoped_ptr<base::Value> value(base::JSONReader::Read(response));
base::DictionaryValue* dict;
if (value && value->GetAsDictionary(&dict)) {
- RemotePageTarget new_page(this, *dict);
+ RemotePageTarget new_page(this, browser->browser_id_, *dict,
+ browser->IsWebView());
new_page.Navigate(url,
- base::Bind(&RespondOnUIThread, callback, result, response));
+ base::Bind(&DevToolsAndroidBridge::RespondToOpenOnUIThread,
+ this, browser, callback, result, response));
}
}
// DevToolsAndroidBridge::RemoteDevice ----------------------------------------
DevToolsAndroidBridge::RemoteDevice::RemoteDevice(
- scoped_refptr<AndroidDeviceManager::Device> device,
+ const std::string& serial,
const AndroidDeviceManager::DeviceInfo& device_info)
- : device_(device),
+ : serial_(serial),
model_(device_info.model),
connected_(device_info.connected),
screen_size_(device_info.screen_size) {
device_info.browser_info.begin();
it != device_info.browser_info.end();
++it) {
- browsers_.push_back(new DevToolsAndroidBridge::RemoteBrowser(device, *it));
+ browsers_.push_back(new RemoteBrowser(serial, *it));
}
}
-void DevToolsAndroidBridge::RemoteDevice::OpenSocket(
- const std::string& socket_name,
- const AndroidDeviceManager::SocketCallback& callback) {
- device_->OpenSocket(socket_name, callback);
-}
-
DevToolsAndroidBridge::RemoteDevice::~RemoteDevice() {
}
: profile_(profile),
device_manager_(AndroidDeviceManager::Create()),
task_scheduler_(base::Bind(&DevToolsAndroidBridge::ScheduleTaskDefault)),
- port_forwarding_controller_(new PortForwardingController(profile)) {
+ port_forwarding_controller_(new PortForwardingController(profile, this)) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
pref_change_registrar_.Init(profile_->GetPrefs());
pref_change_registrar_.Add(prefs::kDevToolsDiscoverUsbDevicesEnabled,
StopDeviceListPolling();
}
-// static
bool DevToolsAndroidBridge::HasDevToolsWindow(const std::string& agent_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return g_host_delegates.Get().find(agent_id) != g_host_delegates.Get().end();
+ return host_delegates_.find(agent_id) != host_delegates_.end();
}
DevToolsAndroidBridge::~DevToolsAndroidBridge() {
void DevToolsAndroidBridge::StopDeviceListPolling() {
device_list_callback_.Cancel();
- devices_.clear();
+ device_map_.clear();
}
bool DevToolsAndroidBridge::NeedsDeviceListPolling() {
}
void DevToolsAndroidBridge::RequestDeviceList(
- const base::Callback<void(const RemoteDevices&)>& callback) {
+ const DeviceListCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!NeedsDeviceListPolling() ||
new DiscoveryRequest(device_manager_.get(), callback);
}
-void DevToolsAndroidBridge::ReceivedDeviceList(const RemoteDevices& devices) {
+void DevToolsAndroidBridge::ReceivedDeviceList(
+ const CompleteDevices& complete_devices) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ device_map_.clear();
+ RemoteDevices remote_devices;
+ for (const auto& pair : complete_devices) {
+ device_map_[pair.first->serial()] = pair.first;
+ remote_devices.push_back(pair.second);
+ }
+
DeviceListListeners copy(device_list_listeners_);
for (DeviceListListeners::iterator it = copy.begin(); it != copy.end(); ++it)
- (*it)->DeviceListChanged(devices);
+ (*it)->DeviceListChanged(remote_devices);
- DevicesStatus status =
- port_forwarding_controller_->DeviceListChanged(devices);
+ ForwardingStatus status =
+ port_forwarding_controller_->DeviceListChanged(remote_devices);
PortForwardingListeners forwarding_listeners(port_forwarding_listeners_);
for (PortForwardingListeners::iterator it = forwarding_listeners.begin();
it != forwarding_listeners.end(); ++it) {
if (!NeedsDeviceListPolling())
return;
- devices_ = devices;
-
task_scheduler_.Run(
base::Bind(&DevToolsAndroidBridge::RequestDeviceList,
this, device_list_callback_.callback()));