blob: 6fe04d8500f811a319bdd55e672f82129bb8f075 [file] [log] [blame]
dgozmanec2b982a2015-04-28 10:36:391// Copyright 2015 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
Pavel Feldman43f56b7c2016-08-30 00:04:355#include "chrome/browser/android/devtools_manager_delegate_android.h"
dgozmanec2b982a2015-04-28 10:36:396
Dmitry Gozmanf7a1c2f2017-09-12 19:37:027#include <map>
8
dgozmanec2b982a2015-04-28 10:36:399#include "base/bind.h"
dgozmanec2b982a2015-04-28 10:36:3910#include "base/strings/string_number_conversions.h"
11#include "base/strings/utf_string_conversions.h"
Pavel Feldman43f56b7c2016-08-30 00:04:3512#include "build/build_config.h"
dgozmanec2b982a2015-04-28 10:36:3913#include "chrome/browser/android/tab_android.h"
dgozmanec2b982a2015-04-28 10:36:3914#include "chrome/browser/ui/android/tab_model/tab_model.h"
15#include "chrome/browser/ui/android/tab_model/tab_model_list.h"
pfeldman10628762016-09-08 07:59:2616#include "chrome/grit/browser_resources.h"
dgozmanec2b982a2015-04-28 10:36:3917#include "content/public/browser/devtools_agent_host.h"
pfeldmana9e7dda2016-08-26 14:35:1718#include "content/public/browser/devtools_agent_host_client.h"
19#include "content/public/browser/devtools_external_agent_proxy.h"
20#include "content/public/browser/devtools_external_agent_proxy_delegate.h"
dgozmanec2b982a2015-04-28 10:36:3921#include "content/public/browser/web_contents.h"
pfeldman10628762016-09-08 07:59:2622#include "ui/base/resource/resource_bundle.h"
dgozmanec2b982a2015-04-28 10:36:3923
24using content::DevToolsAgentHost;
25using content::WebContents;
26
27namespace {
28
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0229class ClientProxy : public content::DevToolsAgentHostClient {
dgozmanec2b982a2015-04-28 10:36:3930 public:
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0231 explicit ClientProxy(content::DevToolsExternalAgentProxy* proxy)
32 : proxy_(proxy) {}
33 ~ClientProxy() override {}
dgozmanec2b982a2015-04-28 10:36:3934
pfeldmana9e7dda2016-08-26 14:35:1735 void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
36 const std::string& message) override {
37 proxy_->DispatchOnClientHost(message);
dgozmanec2b982a2015-04-28 10:36:3938 }
39
Pavel Feldmana344d932017-10-31 20:24:5240 void AgentHostClosed(DevToolsAgentHost* agent_host) override {
pfeldmana9e7dda2016-08-26 14:35:1741 proxy_->ConnectionClosed();
dgozmanec2b982a2015-04-28 10:36:3942 }
43
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0244 private:
45 content::DevToolsExternalAgentProxy* proxy_;
46 DISALLOW_COPY_AND_ASSIGN(ClientProxy);
47};
48
49class TabProxyDelegate : public content::DevToolsExternalAgentProxyDelegate {
50 public:
51 explicit TabProxyDelegate(TabAndroid* tab)
52 : tab_id_(tab->GetAndroidId()),
53 title_(base::UTF16ToUTF8(tab->GetTitle())),
54 url_(tab->GetURL()),
55 agent_host_(tab->web_contents()
56 ? DevToolsAgentHost::GetOrCreateFor(tab->web_contents())
57 : nullptr) {}
58
59 ~TabProxyDelegate() override {}
60
pfeldmana9e7dda2016-08-26 14:35:1761 void Attach(content::DevToolsExternalAgentProxy* proxy) override {
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0262 proxies_[proxy].reset(new ClientProxy(proxy));
pfeldmana9e7dda2016-08-26 14:35:1763 MaterializeAgentHost();
pfeldman2236ce0a2016-09-20 23:59:4664 if (agent_host_)
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0265 agent_host_->AttachClient(proxies_[proxy].get());
mohsend8fe6fb42016-08-25 01:55:1066 }
67
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0268 void Detach(content::DevToolsExternalAgentProxy* proxy) override {
69 auto it = proxies_.find(proxy);
70 if (it == proxies_.end())
71 return;
pfeldmana9e7dda2016-08-26 14:35:1772 if (agent_host_)
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0273 agent_host_->DetachClient(it->second.get());
74 proxies_.erase(it);
75 if (proxies_.empty())
76 agent_host_ = nullptr;
mohsend8fe6fb42016-08-25 01:55:1077 }
78
pfeldmana9e7dda2016-08-26 14:35:1779 std::string GetType() override {
80 return agent_host_ ? agent_host_->GetType() : DevToolsAgentHost::kTypePage;
mohsend8fe6fb42016-08-25 01:55:1081 }
82
pfeldmana9e7dda2016-08-26 14:35:1783 std::string GetTitle() override {
84 return agent_host_ ? agent_host_->GetTitle() : title_;
mohsend8fe6fb42016-08-25 01:55:1085 }
86
pfeldmana9e7dda2016-08-26 14:35:1787 std::string GetDescription() override {
88 return agent_host_ ? agent_host_->GetDescription() : "";
mohsend8fe6fb42016-08-25 01:55:1089 }
90
pfeldmana9e7dda2016-08-26 14:35:1791 GURL GetURL() override {
92 return agent_host_ ? agent_host_->GetURL() : url_;
93 }
94
95 GURL GetFaviconURL() override {
96 return agent_host_ ? agent_host_->GetFaviconURL() : GURL();
97 }
98
pfeldmane7d2e412016-09-23 16:41:5199 std::string GetFrontendURL() override {
100 return std::string();
101 }
102
pfeldmana9e7dda2016-08-26 14:35:17103 bool Activate() override {
dgozmanec2b982a2015-04-28 10:36:39104 TabModel* model;
105 int index;
106 if (!FindTab(&model, &index))
107 return false;
108 model->SetActiveIndex(index);
109 return true;
110 }
111
pfeldmana9e7dda2016-08-26 14:35:17112 void Reload() override {
113 MaterializeAgentHost();
114 if (agent_host_)
115 agent_host_->Reload();
116 }
117
118 bool Close() override {
dgozmanec2b982a2015-04-28 10:36:39119 TabModel* model;
120 int index;
121 if (!FindTab(&model, &index))
122 return false;
123 model->CloseTabAt(index);
124 return true;
125 }
126
pfeldman970883722017-02-08 06:08:53127 base::TimeTicks GetLastActivityTime() override {
128 return agent_host_ ? agent_host_->GetLastActivityTime() : base::TimeTicks();
129 }
130
Dmitry Gozmanf7a1c2f2017-09-12 19:37:02131 void SendMessageToBackend(content::DevToolsExternalAgentProxy* proxy,
132 const std::string& message) override {
133 auto it = proxies_.find(proxy);
134 if (it == proxies_.end())
135 return;
pfeldmana9e7dda2016-08-26 14:35:17136 if (agent_host_)
Dmitry Gozmanf7a1c2f2017-09-12 19:37:02137 agent_host_->DispatchProtocolMessage(it->second.get(), message);
gab0dccfef2015-05-20 18:43:39138 }
dgozmanec2b982a2015-04-28 10:36:39139
pfeldmana9e7dda2016-08-26 14:35:17140 private:
141 void MaterializeAgentHost() {
142 if (agent_host_)
143 return;
144 TabModel* model;
145 int index;
146 if (!FindTab(&model, &index))
147 return;
148 WebContents* web_contents = model->GetWebContentsAt(index);
149 if (!web_contents)
150 return;
151 agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents);
dgozmanec2b982a2015-04-28 10:36:39152 }
153
154 bool FindTab(TabModel** model_result, int* index_result) const {
155 for (TabModelList::const_iterator iter = TabModelList::begin();
156 iter != TabModelList::end(); ++iter) {
157 TabModel* model = *iter;
158 for (int i = 0; i < model->GetTabCount(); ++i) {
159 TabAndroid* tab = model->GetTabAt(i);
160 if (tab && tab->GetAndroidId() == tab_id_) {
161 *model_result = model;
162 *index_result = i;
163 return true;
164 }
165 }
166 }
167 return false;
168 }
169
170 const int tab_id_;
171 const std::string title_;
172 const GURL url_;
Pavel Feldman43f56b7c2016-08-30 00:04:35173 scoped_refptr<DevToolsAgentHost> agent_host_;
Dmitry Gozmanf7a1c2f2017-09-12 19:37:02174 std::map<content::DevToolsExternalAgentProxy*, std::unique_ptr<ClientProxy>>
175 proxies_;
pfeldmana9e7dda2016-08-26 14:35:17176 DISALLOW_COPY_AND_ASSIGN(TabProxyDelegate);
dgozmanec2b982a2015-04-28 10:36:39177};
178
pfeldman82f29402017-04-24 20:58:02179scoped_refptr<DevToolsAgentHost> DevToolsAgentHostForTab(TabAndroid* tab) {
180 scoped_refptr<DevToolsAgentHost> result = tab->GetDevToolsAgentHost();
181 if (result)
182 return result;
183
184 result = DevToolsAgentHost::Forward(base::IntToString(tab->GetAndroidId()),
Jinho Bang7fa90e872018-01-15 18:04:12185 std::make_unique<TabProxyDelegate>(tab));
pfeldman82f29402017-04-24 20:58:02186 tab->SetDevToolsAgentHost(result);
187 return result;
188}
189
Pavel Feldman43f56b7c2016-08-30 00:04:35190} // namespace
191
Andrey Kosyakov24f33162017-09-14 22:41:40192DevToolsManagerDelegateAndroid::DevToolsManagerDelegateAndroid() = default;
Pavel Feldman43f56b7c2016-08-30 00:04:35193
Andrey Kosyakov24f33162017-09-14 22:41:40194DevToolsManagerDelegateAndroid::~DevToolsManagerDelegateAndroid() = default;
Pavel Feldman43f56b7c2016-08-30 00:04:35195
196std::string DevToolsManagerDelegateAndroid::GetTargetType(
dgozman3234f372017-06-09 03:03:55197 content::WebContents* web_contents) {
Pavel Feldman43f56b7c2016-08-30 00:04:35198 TabAndroid* tab = web_contents ? TabAndroid::FromWebContents(web_contents)
199 : nullptr;
200 return tab ? DevToolsAgentHost::kTypePage :
201 DevToolsAgentHost::kTypeOther;
202}
203
pfeldman82f29402017-04-24 20:58:02204DevToolsAgentHost::List
205DevToolsManagerDelegateAndroid::RemoteDebuggingTargets() {
pfeldmane28eab42016-09-21 23:00:53206 // Enumerate existing tabs, including the ones with no WebContents.
207 DevToolsAgentHost::List result;
208 std::set<WebContents*> tab_web_contents;
209 for (TabModelList::const_iterator iter = TabModelList::begin();
210 iter != TabModelList::end(); ++iter) {
211 TabModel* model = *iter;
212 for (int i = 0; i < model->GetTabCount(); ++i) {
213 TabAndroid* tab = model->GetTabAt(i);
214 if (!tab)
215 continue;
216
217 if (tab->web_contents())
218 tab_web_contents.insert(tab->web_contents());
pfeldman82f29402017-04-24 20:58:02219 result.push_back(DevToolsAgentHostForTab(tab));
pfeldmane28eab42016-09-21 23:00:53220 }
221 }
222
223 // Add descriptors for targets not associated with any tabs.
224 DevToolsAgentHost::List agents = DevToolsAgentHost::GetOrCreateAll();
225 for (DevToolsAgentHost::List::iterator it = agents.begin();
226 it != agents.end(); ++it) {
227 if (WebContents* web_contents = (*it)->GetWebContents()) {
228 if (tab_web_contents.find(web_contents) != tab_web_contents.end())
229 continue;
230 }
231 result.push_back(*it);
232 }
233
pfeldman82f29402017-04-24 20:58:02234 return result;
pfeldmane28eab42016-09-21 23:00:53235}
236
Pavel Feldman43f56b7c2016-08-30 00:04:35237scoped_refptr<DevToolsAgentHost>
238DevToolsManagerDelegateAndroid::CreateNewTarget(const GURL& url) {
239 if (TabModelList::empty())
240 return nullptr;
241
242 TabModel* tab_model = TabModelList::get(0);
243 if (!tab_model)
244 return nullptr;
245
246 WebContents* web_contents = tab_model->CreateNewTabForDevTools(url);
247 if (!web_contents)
248 return nullptr;
249
250 TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
pfeldman82f29402017-04-24 20:58:02251 return tab ? DevToolsAgentHostForTab(tab) : nullptr;
pfeldman10628762016-09-08 07:59:26252}
253
254std::string DevToolsManagerDelegateAndroid::GetDiscoveryPageHTML() {
Lei Zhang7640d542017-10-03 16:26:49255 return ui::ResourceBundle::GetSharedInstance()
256 .GetRawDataResource(IDR_DEVTOOLS_DISCOVERY_PAGE_HTML)
257 .as_string();
Pavel Feldman43f56b7c2016-08-30 00:04:35258}
259
Pavel Feldman77da4d52017-08-05 11:59:24260bool DevToolsManagerDelegateAndroid::IsBrowserTargetDiscoverable() {
261 return true;
262}