blob: c4f5852aac4846478cf45c25b2966d21d3847520 [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"
pfeldman10628762016-09-08 07:59:2610#include "base/memory/ptr_util.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"
dgozmanec2b982a2015-04-28 10:36:3915#include "chrome/browser/ui/android/tab_model/tab_model.h"
16#include "chrome/browser/ui/android/tab_model/tab_model_list.h"
pfeldman10628762016-09-08 07:59:2617#include "chrome/grit/browser_resources.h"
dgozmanec2b982a2015-04-28 10:36:3918#include "content/public/browser/devtools_agent_host.h"
pfeldmana9e7dda2016-08-26 14:35:1719#include "content/public/browser/devtools_agent_host_client.h"
20#include "content/public/browser/devtools_external_agent_proxy.h"
21#include "content/public/browser/devtools_external_agent_proxy_delegate.h"
dgozmanec2b982a2015-04-28 10:36:3922#include "content/public/browser/web_contents.h"
pfeldman10628762016-09-08 07:59:2623#include "ui/base/resource/resource_bundle.h"
dgozmanec2b982a2015-04-28 10:36:3924
25using content::DevToolsAgentHost;
26using content::WebContents;
27
28namespace {
29
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0230class ClientProxy : public content::DevToolsAgentHostClient {
dgozmanec2b982a2015-04-28 10:36:3931 public:
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0232 explicit ClientProxy(content::DevToolsExternalAgentProxy* proxy)
33 : proxy_(proxy) {}
34 ~ClientProxy() override {}
dgozmanec2b982a2015-04-28 10:36:3935
pfeldmana9e7dda2016-08-26 14:35:1736 void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
37 const std::string& message) override {
38 proxy_->DispatchOnClientHost(message);
dgozmanec2b982a2015-04-28 10:36:3939 }
40
pfeldmana9e7dda2016-08-26 14:35:1741 void AgentHostClosed(DevToolsAgentHost* agent_host,
42 bool replaced_with_another_client) override {
43 proxy_->ConnectionClosed();
dgozmanec2b982a2015-04-28 10:36:3944 }
45
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0246 private:
47 content::DevToolsExternalAgentProxy* proxy_;
48 DISALLOW_COPY_AND_ASSIGN(ClientProxy);
49};
50
51class TabProxyDelegate : public content::DevToolsExternalAgentProxyDelegate {
52 public:
53 explicit TabProxyDelegate(TabAndroid* tab)
54 : tab_id_(tab->GetAndroidId()),
55 title_(base::UTF16ToUTF8(tab->GetTitle())),
56 url_(tab->GetURL()),
57 agent_host_(tab->web_contents()
58 ? DevToolsAgentHost::GetOrCreateFor(tab->web_contents())
59 : nullptr) {}
60
61 ~TabProxyDelegate() override {}
62
pfeldmana9e7dda2016-08-26 14:35:1763 void Attach(content::DevToolsExternalAgentProxy* proxy) override {
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0264 proxies_[proxy].reset(new ClientProxy(proxy));
pfeldmana9e7dda2016-08-26 14:35:1765 MaterializeAgentHost();
pfeldman2236ce0a2016-09-20 23:59:4666 if (agent_host_)
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0267 agent_host_->AttachClient(proxies_[proxy].get());
mohsend8fe6fb42016-08-25 01:55:1068 }
69
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0270 void Detach(content::DevToolsExternalAgentProxy* proxy) override {
71 auto it = proxies_.find(proxy);
72 if (it == proxies_.end())
73 return;
pfeldmana9e7dda2016-08-26 14:35:1774 if (agent_host_)
Dmitry Gozmanf7a1c2f2017-09-12 19:37:0275 agent_host_->DetachClient(it->second.get());
76 proxies_.erase(it);
77 if (proxies_.empty())
78 agent_host_ = nullptr;
mohsend8fe6fb42016-08-25 01:55:1079 }
80
pfeldmana9e7dda2016-08-26 14:35:1781 std::string GetType() override {
82 return agent_host_ ? agent_host_->GetType() : DevToolsAgentHost::kTypePage;
mohsend8fe6fb42016-08-25 01:55:1083 }
84
pfeldmana9e7dda2016-08-26 14:35:1785 std::string GetTitle() override {
86 return agent_host_ ? agent_host_->GetTitle() : title_;
mohsend8fe6fb42016-08-25 01:55:1087 }
88
pfeldmana9e7dda2016-08-26 14:35:1789 std::string GetDescription() override {
90 return agent_host_ ? agent_host_->GetDescription() : "";
mohsend8fe6fb42016-08-25 01:55:1091 }
92
pfeldmana9e7dda2016-08-26 14:35:1793 GURL GetURL() override {
94 return agent_host_ ? agent_host_->GetURL() : url_;
95 }
96
97 GURL GetFaviconURL() override {
98 return agent_host_ ? agent_host_->GetFaviconURL() : GURL();
99 }
100
pfeldmane7d2e412016-09-23 16:41:51101 std::string GetFrontendURL() override {
102 return std::string();
103 }
104
pfeldmana9e7dda2016-08-26 14:35:17105 bool Activate() override {
dgozmanec2b982a2015-04-28 10:36:39106 TabModel* model;
107 int index;
108 if (!FindTab(&model, &index))
109 return false;
110 model->SetActiveIndex(index);
111 return true;
112 }
113
pfeldmana9e7dda2016-08-26 14:35:17114 void Reload() override {
115 MaterializeAgentHost();
116 if (agent_host_)
117 agent_host_->Reload();
118 }
119
120 bool Close() override {
dgozmanec2b982a2015-04-28 10:36:39121 TabModel* model;
122 int index;
123 if (!FindTab(&model, &index))
124 return false;
125 model->CloseTabAt(index);
126 return true;
127 }
128
pfeldman970883722017-02-08 06:08:53129 base::TimeTicks GetLastActivityTime() override {
130 return agent_host_ ? agent_host_->GetLastActivityTime() : base::TimeTicks();
131 }
132
Dmitry Gozmanf7a1c2f2017-09-12 19:37:02133 void SendMessageToBackend(content::DevToolsExternalAgentProxy* proxy,
134 const std::string& message) override {
135 auto it = proxies_.find(proxy);
136 if (it == proxies_.end())
137 return;
pfeldmana9e7dda2016-08-26 14:35:17138 if (agent_host_)
Dmitry Gozmanf7a1c2f2017-09-12 19:37:02139 agent_host_->DispatchProtocolMessage(it->second.get(), message);
gab0dccfef2015-05-20 18:43:39140 }
dgozmanec2b982a2015-04-28 10:36:39141
pfeldmana9e7dda2016-08-26 14:35:17142 private:
143 void MaterializeAgentHost() {
144 if (agent_host_)
145 return;
146 TabModel* model;
147 int index;
148 if (!FindTab(&model, &index))
149 return;
150 WebContents* web_contents = model->GetWebContentsAt(index);
151 if (!web_contents)
152 return;
153 agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents);
dgozmanec2b982a2015-04-28 10:36:39154 }
155
156 bool FindTab(TabModel** model_result, int* index_result) const {
157 for (TabModelList::const_iterator iter = TabModelList::begin();
158 iter != TabModelList::end(); ++iter) {
159 TabModel* model = *iter;
160 for (int i = 0; i < model->GetTabCount(); ++i) {
161 TabAndroid* tab = model->GetTabAt(i);
162 if (tab && tab->GetAndroidId() == tab_id_) {
163 *model_result = model;
164 *index_result = i;
165 return true;
166 }
167 }
168 }
169 return false;
170 }
171
172 const int tab_id_;
173 const std::string title_;
174 const GURL url_;
Pavel Feldman43f56b7c2016-08-30 00:04:35175 scoped_refptr<DevToolsAgentHost> agent_host_;
Dmitry Gozmanf7a1c2f2017-09-12 19:37:02176 std::map<content::DevToolsExternalAgentProxy*, std::unique_ptr<ClientProxy>>
177 proxies_;
pfeldmana9e7dda2016-08-26 14:35:17178 DISALLOW_COPY_AND_ASSIGN(TabProxyDelegate);
dgozmanec2b982a2015-04-28 10:36:39179};
180
pfeldman82f29402017-04-24 20:58:02181scoped_refptr<DevToolsAgentHost> DevToolsAgentHostForTab(TabAndroid* tab) {
182 scoped_refptr<DevToolsAgentHost> result = tab->GetDevToolsAgentHost();
183 if (result)
184 return result;
185
186 result = DevToolsAgentHost::Forward(base::IntToString(tab->GetAndroidId()),
187 base::MakeUnique<TabProxyDelegate>(tab));
188 tab->SetDevToolsAgentHost(result);
189 return result;
190}
191
Pavel Feldman43f56b7c2016-08-30 00:04:35192} // namespace
193
Andrey Kosyakov24f33162017-09-14 22:41:40194DevToolsManagerDelegateAndroid::DevToolsManagerDelegateAndroid() = default;
Pavel Feldman43f56b7c2016-08-30 00:04:35195
Andrey Kosyakov24f33162017-09-14 22:41:40196DevToolsManagerDelegateAndroid::~DevToolsManagerDelegateAndroid() = default;
Pavel Feldman43f56b7c2016-08-30 00:04:35197
198std::string DevToolsManagerDelegateAndroid::GetTargetType(
dgozman3234f372017-06-09 03:03:55199 content::WebContents* web_contents) {
Pavel Feldman43f56b7c2016-08-30 00:04:35200 TabAndroid* tab = web_contents ? TabAndroid::FromWebContents(web_contents)
201 : nullptr;
202 return tab ? DevToolsAgentHost::kTypePage :
203 DevToolsAgentHost::kTypeOther;
204}
205
pfeldman82f29402017-04-24 20:58:02206DevToolsAgentHost::List
207DevToolsManagerDelegateAndroid::RemoteDebuggingTargets() {
pfeldmane28eab42016-09-21 23:00:53208 // Enumerate existing tabs, including the ones with no WebContents.
209 DevToolsAgentHost::List result;
210 std::set<WebContents*> tab_web_contents;
211 for (TabModelList::const_iterator iter = TabModelList::begin();
212 iter != TabModelList::end(); ++iter) {
213 TabModel* model = *iter;
214 for (int i = 0; i < model->GetTabCount(); ++i) {
215 TabAndroid* tab = model->GetTabAt(i);
216 if (!tab)
217 continue;
218
219 if (tab->web_contents())
220 tab_web_contents.insert(tab->web_contents());
pfeldman82f29402017-04-24 20:58:02221 result.push_back(DevToolsAgentHostForTab(tab));
pfeldmane28eab42016-09-21 23:00:53222 }
223 }
224
225 // Add descriptors for targets not associated with any tabs.
226 DevToolsAgentHost::List agents = DevToolsAgentHost::GetOrCreateAll();
227 for (DevToolsAgentHost::List::iterator it = agents.begin();
228 it != agents.end(); ++it) {
229 if (WebContents* web_contents = (*it)->GetWebContents()) {
230 if (tab_web_contents.find(web_contents) != tab_web_contents.end())
231 continue;
232 }
233 result.push_back(*it);
234 }
235
pfeldman82f29402017-04-24 20:58:02236 return result;
pfeldmane28eab42016-09-21 23:00:53237}
238
Pavel Feldman43f56b7c2016-08-30 00:04:35239scoped_refptr<DevToolsAgentHost>
240DevToolsManagerDelegateAndroid::CreateNewTarget(const GURL& url) {
241 if (TabModelList::empty())
242 return nullptr;
243
244 TabModel* tab_model = TabModelList::get(0);
245 if (!tab_model)
246 return nullptr;
247
248 WebContents* web_contents = tab_model->CreateNewTabForDevTools(url);
249 if (!web_contents)
250 return nullptr;
251
252 TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
pfeldman82f29402017-04-24 20:58:02253 return tab ? DevToolsAgentHostForTab(tab) : nullptr;
pfeldman10628762016-09-08 07:59:26254}
255
256std::string DevToolsManagerDelegateAndroid::GetDiscoveryPageHTML() {
Lei Zhang7640d542017-10-03 16:26:49257 return ui::ResourceBundle::GetSharedInstance()
258 .GetRawDataResource(IDR_DEVTOOLS_DISCOVERY_PAGE_HTML)
259 .as_string();
Pavel Feldman43f56b7c2016-08-30 00:04:35260}
261
Pavel Feldman77da4d52017-08-05 11:59:24262bool DevToolsManagerDelegateAndroid::IsBrowserTargetDiscoverable() {
263 return true;
264}