blob: 6f0896a4bec26d6ec2e5fe0e81ef54390024474f [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>
Peter Boström08e7ed82021-04-19 17:49:598#include <memory>
Dmitry Gozmanf7a1c2f2017-09-12 19:37:029
dgozmanec2b982a2015-04-28 10:36:3910#include "base/bind.h"
dgozmanec2b982a2015-04-28 10:36:3911#include "base/strings/string_number_conversions.h"
12#include "base/strings/utf_string_conversions.h"
Pavel Feldman43f56b7c2016-08-30 00:04:3513#include "build/build_config.h"
dgozmanec2b982a2015-04-28 10:36:3914#include "chrome/browser/android/tab_android.h"
Richard Knoll7b9de302021-04-06 23:05:4215#include "chrome/browser/profiles/profile_manager.h"
dgozmanec2b982a2015-04-28 10:36:3916#include "chrome/browser/ui/android/tab_model/tab_model.h"
17#include "chrome/browser/ui/android/tab_model/tab_model_list.h"
pfeldman10628762016-09-08 07:59:2618#include "chrome/grit/browser_resources.h"
dgozmanec2b982a2015-04-28 10:36:3919#include "content/public/browser/devtools_agent_host.h"
pfeldmana9e7dda2016-08-26 14:35:1720#include "content/public/browser/devtools_agent_host_client.h"
21#include "content/public/browser/devtools_external_agent_proxy.h"
22#include "content/public/browser/devtools_external_agent_proxy_delegate.h"
dgozmanec2b982a2015-04-28 10:36:3923#include "content/public/browser/web_contents.h"
pfeldman10628762016-09-08 07:59:2624#include "ui/base/resource/resource_bundle.h"
dgozmanec2b982a2015-04-28 10:36:3925
26using content::DevToolsAgentHost;
27using content::WebContents;
28
29namespace {
30
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0231class ClientProxy : public content::DevToolsAgentHostClient {
dgozmanec2b982a2015-04-28 10:36:3932 public:
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0233 explicit ClientProxy(content::DevToolsExternalAgentProxy* proxy)
34 : proxy_(proxy) {}
Peter Boström53c6c5952021-09-17 09:41:2635
36 ClientProxy(const ClientProxy&) = delete;
37 ClientProxy& operator=(const ClientProxy&) = delete;
38
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0239 ~ClientProxy() override {}
dgozmanec2b982a2015-04-28 10:36:3940
pfeldmana9e7dda2016-08-26 14:35:1741 void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
Johannes Henkel21e194012019-12-20 03:23:1742 base::span<const uint8_t> message) override {
pfeldmana9e7dda2016-08-26 14:35:1743 proxy_->DispatchOnClientHost(message);
dgozmanec2b982a2015-04-28 10:36:3944 }
45
Pavel Feldmana344d932017-10-31 20:24:5246 void AgentHostClosed(DevToolsAgentHost* agent_host) override {
pfeldmana9e7dda2016-08-26 14:35:1747 proxy_->ConnectionClosed();
dgozmanec2b982a2015-04-28 10:36:3948 }
49
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0250 private:
51 content::DevToolsExternalAgentProxy* proxy_;
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0252};
53
54class TabProxyDelegate : public content::DevToolsExternalAgentProxyDelegate {
55 public:
56 explicit TabProxyDelegate(TabAndroid* tab)
57 : tab_id_(tab->GetAndroidId()),
58 title_(base::UTF16ToUTF8(tab->GetTitle())),
59 url_(tab->GetURL()),
60 agent_host_(tab->web_contents()
61 ? DevToolsAgentHost::GetOrCreateFor(tab->web_contents())
62 : nullptr) {}
63
Peter Boström53c6c5952021-09-17 09:41:2664 TabProxyDelegate(const TabProxyDelegate&) = delete;
65 TabProxyDelegate& operator=(const TabProxyDelegate&) = delete;
66
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0267 ~TabProxyDelegate() override {}
68
pfeldmana9e7dda2016-08-26 14:35:1769 void Attach(content::DevToolsExternalAgentProxy* proxy) override {
Peter Boström08e7ed82021-04-19 17:49:5970 proxies_[proxy] = std::make_unique<ClientProxy>(proxy);
pfeldmana9e7dda2016-08-26 14:35:1771 MaterializeAgentHost();
pfeldman2236ce0a2016-09-20 23:59:4672 if (agent_host_)
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0273 agent_host_->AttachClient(proxies_[proxy].get());
mohsend8fe6fb42016-08-25 01:55:1074 }
75
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0276 void Detach(content::DevToolsExternalAgentProxy* proxy) override {
77 auto it = proxies_.find(proxy);
78 if (it == proxies_.end())
79 return;
pfeldmana9e7dda2016-08-26 14:35:1780 if (agent_host_)
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0281 agent_host_->DetachClient(it->second.get());
82 proxies_.erase(it);
83 if (proxies_.empty())
84 agent_host_ = nullptr;
mohsend8fe6fb42016-08-25 01:55:1085 }
86
pfeldmana9e7dda2016-08-26 14:35:1787 std::string GetType() override {
88 return agent_host_ ? agent_host_->GetType() : DevToolsAgentHost::kTypePage;
mohsend8fe6fb42016-08-25 01:55:1089 }
90
pfeldmana9e7dda2016-08-26 14:35:1791 std::string GetTitle() override {
92 return agent_host_ ? agent_host_->GetTitle() : title_;
mohsend8fe6fb42016-08-25 01:55:1093 }
94
pfeldmana9e7dda2016-08-26 14:35:1795 std::string GetDescription() override {
96 return agent_host_ ? agent_host_->GetDescription() : "";
mohsend8fe6fb42016-08-25 01:55:1097 }
98
pfeldmana9e7dda2016-08-26 14:35:1799 GURL GetURL() override {
100 return agent_host_ ? agent_host_->GetURL() : url_;
101 }
102
103 GURL GetFaviconURL() override {
104 return agent_host_ ? agent_host_->GetFaviconURL() : GURL();
105 }
106
pfeldmane7d2e412016-09-23 16:41:51107 std::string GetFrontendURL() override {
108 return std::string();
109 }
110
pfeldmana9e7dda2016-08-26 14:35:17111 bool Activate() override {
dgozmanec2b982a2015-04-28 10:36:39112 TabModel* model;
113 int index;
114 if (!FindTab(&model, &index))
115 return false;
116 model->SetActiveIndex(index);
117 return true;
118 }
119
pfeldmana9e7dda2016-08-26 14:35:17120 void Reload() override {
121 MaterializeAgentHost();
122 if (agent_host_)
123 agent_host_->Reload();
124 }
125
126 bool Close() override {
dgozmanec2b982a2015-04-28 10:36:39127 TabModel* model;
128 int index;
129 if (!FindTab(&model, &index))
130 return false;
131 model->CloseTabAt(index);
132 return true;
133 }
134
pfeldman970883722017-02-08 06:08:53135 base::TimeTicks GetLastActivityTime() override {
136 return agent_host_ ? agent_host_->GetLastActivityTime() : base::TimeTicks();
137 }
138
Dmitry Gozmanf7a1c2f2017-09-12 19:37:02139 void SendMessageToBackend(content::DevToolsExternalAgentProxy* proxy,
Johannes Henkel21e194012019-12-20 03:23:17140 base::span<const uint8_t> message) override {
Dmitry Gozmanf7a1c2f2017-09-12 19:37:02141 auto it = proxies_.find(proxy);
142 if (it == proxies_.end())
143 return;
pfeldmana9e7dda2016-08-26 14:35:17144 if (agent_host_)
Dmitry Gozmanf7a1c2f2017-09-12 19:37:02145 agent_host_->DispatchProtocolMessage(it->second.get(), message);
gab0dccfef2015-05-20 18:43:39146 }
dgozmanec2b982a2015-04-28 10:36:39147
pfeldmana9e7dda2016-08-26 14:35:17148 private:
149 void MaterializeAgentHost() {
150 if (agent_host_)
151 return;
152 TabModel* model;
153 int index;
154 if (!FindTab(&model, &index))
155 return;
156 WebContents* web_contents = model->GetWebContentsAt(index);
157 if (!web_contents)
158 return;
159 agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents);
dgozmanec2b982a2015-04-28 10:36:39160 }
161
162 bool FindTab(TabModel** model_result, int* index_result) const {
Tomasz Wiszkowski066ab9842021-03-23 00:37:31163 for (TabModel* model : TabModelList::models()) {
dgozmanec2b982a2015-04-28 10:36:39164 for (int i = 0; i < model->GetTabCount(); ++i) {
165 TabAndroid* tab = model->GetTabAt(i);
166 if (tab && tab->GetAndroidId() == tab_id_) {
167 *model_result = model;
168 *index_result = i;
169 return true;
170 }
171 }
172 }
173 return false;
174 }
175
176 const int tab_id_;
177 const std::string title_;
178 const GURL url_;
Pavel Feldman43f56b7c2016-08-30 00:04:35179 scoped_refptr<DevToolsAgentHost> agent_host_;
Dmitry Gozmanf7a1c2f2017-09-12 19:37:02180 std::map<content::DevToolsExternalAgentProxy*, std::unique_ptr<ClientProxy>>
181 proxies_;
dgozmanec2b982a2015-04-28 10:36:39182};
183
pfeldman82f29402017-04-24 20:58:02184scoped_refptr<DevToolsAgentHost> DevToolsAgentHostForTab(TabAndroid* tab) {
185 scoped_refptr<DevToolsAgentHost> result = tab->GetDevToolsAgentHost();
186 if (result)
187 return result;
188
Raul Tambrefff51b752019-02-04 13:09:47189 result = DevToolsAgentHost::Forward(base::NumberToString(tab->GetAndroidId()),
Jinho Bang7fa90e872018-01-15 18:04:12190 std::make_unique<TabProxyDelegate>(tab));
pfeldman82f29402017-04-24 20:58:02191 tab->SetDevToolsAgentHost(result);
192 return result;
193}
194
Pavel Feldman43f56b7c2016-08-30 00:04:35195} // namespace
196
Andrey Kosyakov24f33162017-09-14 22:41:40197DevToolsManagerDelegateAndroid::DevToolsManagerDelegateAndroid() = default;
Pavel Feldman43f56b7c2016-08-30 00:04:35198
Andrey Kosyakov24f33162017-09-14 22:41:40199DevToolsManagerDelegateAndroid::~DevToolsManagerDelegateAndroid() = default;
Pavel Feldman43f56b7c2016-08-30 00:04:35200
Richard Knoll7b9de302021-04-06 23:05:42201content::BrowserContext*
202DevToolsManagerDelegateAndroid::GetDefaultBrowserContext() {
203 return ProfileManager::GetActiveUserProfile()->GetOriginalProfile();
204}
205
Pavel Feldman43f56b7c2016-08-30 00:04:35206std::string DevToolsManagerDelegateAndroid::GetTargetType(
dgozman3234f372017-06-09 03:03:55207 content::WebContents* web_contents) {
Pavel Feldman43f56b7c2016-08-30 00:04:35208 TabAndroid* tab = web_contents ? TabAndroid::FromWebContents(web_contents)
209 : nullptr;
210 return tab ? DevToolsAgentHost::kTypePage :
211 DevToolsAgentHost::kTypeOther;
212}
213
pfeldman82f29402017-04-24 20:58:02214DevToolsAgentHost::List
215DevToolsManagerDelegateAndroid::RemoteDebuggingTargets() {
pfeldmane28eab42016-09-21 23:00:53216 // Enumerate existing tabs, including the ones with no WebContents.
217 DevToolsAgentHost::List result;
218 std::set<WebContents*> tab_web_contents;
Tomasz Wiszkowski066ab9842021-03-23 00:37:31219 for (const TabModel* model : TabModelList::models()) {
pfeldmane28eab42016-09-21 23:00:53220 for (int i = 0; i < model->GetTabCount(); ++i) {
221 TabAndroid* tab = model->GetTabAt(i);
222 if (!tab)
223 continue;
224
225 if (tab->web_contents())
226 tab_web_contents.insert(tab->web_contents());
pfeldman82f29402017-04-24 20:58:02227 result.push_back(DevToolsAgentHostForTab(tab));
pfeldmane28eab42016-09-21 23:00:53228 }
229 }
230
231 // Add descriptors for targets not associated with any tabs.
232 DevToolsAgentHost::List agents = DevToolsAgentHost::GetOrCreateAll();
233 for (DevToolsAgentHost::List::iterator it = agents.begin();
234 it != agents.end(); ++it) {
235 if (WebContents* web_contents = (*it)->GetWebContents()) {
236 if (tab_web_contents.find(web_contents) != tab_web_contents.end())
237 continue;
238 }
239 result.push_back(*it);
240 }
241
pfeldman82f29402017-04-24 20:58:02242 return result;
pfeldmane28eab42016-09-21 23:00:53243}
244
Pavel Feldman43f56b7c2016-08-30 00:04:35245scoped_refptr<DevToolsAgentHost>
246DevToolsManagerDelegateAndroid::CreateNewTarget(const GURL& url) {
Tomasz Wiszkowski066ab9842021-03-23 00:37:31247 if (TabModelList::models().empty())
Pavel Feldman43f56b7c2016-08-30 00:04:35248 return nullptr;
249
Tomasz Wiszkowski066ab9842021-03-23 00:37:31250 TabModel* tab_model = TabModelList::models()[0];
Pavel Feldman43f56b7c2016-08-30 00:04:35251 if (!tab_model)
252 return nullptr;
253
254 WebContents* web_contents = tab_model->CreateNewTabForDevTools(url);
255 if (!web_contents)
256 return nullptr;
257
258 TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
pfeldman82f29402017-04-24 20:58:02259 return tab ? DevToolsAgentHostForTab(tab) : nullptr;
pfeldman10628762016-09-08 07:59:26260}
261
262std::string DevToolsManagerDelegateAndroid::GetDiscoveryPageHTML() {
Sam Maiere0f6e0472019-10-31 21:37:49263 return ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
Andrew Grieve088fef72019-10-08 15:57:33264 IDR_DEVTOOLS_DISCOVERY_PAGE_HTML);
Pavel Feldman43f56b7c2016-08-30 00:04:35265}
266
Pavel Feldman77da4d52017-08-05 11:59:24267bool DevToolsManagerDelegateAndroid::IsBrowserTargetDiscoverable() {
268 return true;
269}