1 // 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.
5 #include "chrome/browser/android/dev_tools_discovery_provider_android.h"
7 #include "base/basictypes.h"
9 #include "base/compiler_specific.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/android/tab_android.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/ui/android/tab_model/tab_model.h"
15 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
16 #include "components/devtools_discovery/basic_target_descriptor.h"
17 #include "components/devtools_discovery/devtools_discovery_manager.h"
18 #include "content/public/browser/devtools_agent_host.h"
19 #include "content/public/browser/favicon_status.h"
20 #include "content/public/browser/navigation_entry.h"
21 #include "content/public/browser/web_contents.h"
23 using content::DevToolsAgentHost
;
24 using content::WebContents
;
28 GURL
GetFaviconURLForContents(WebContents
* web_contents
) {
29 content::NavigationController
& controller
= web_contents
->GetController();
30 content::NavigationEntry
* entry
= controller
.GetActiveEntry();
31 if (entry
!= NULL
&& entry
->GetURL().is_valid())
32 return entry
->GetFavicon().url
;
36 class TabDescriptor
: public devtools_discovery::DevToolsTargetDescriptor
{
38 static TabDescriptor
* CreateForWebContents(int tab_id
,
39 WebContents
* web_contents
) {
40 return new TabDescriptor(tab_id
, web_contents
);
43 static TabDescriptor
* CreateForUnloadedTab(int tab_id
,
44 const base::string16
& title
,
46 return new TabDescriptor(tab_id
, title
, url
);
49 ~TabDescriptor() override
{
52 // devtools_discovery::DevToolsTargetDescriptor implementation.
53 std::string
GetParentId() const override
{
57 std::string
GetTitle() const override
{
61 std::string
GetDescription() const override
{
65 GURL
GetURL() const override
{
69 GURL
GetFaviconURL() const override
{
73 base::TimeTicks
GetLastActivityTime() const override
{
74 return last_activity_time_
;
77 std::string
GetId() const override
{
78 return base::IntToString(tab_id_
);
81 std::string
GetType() const override
{
82 return devtools_discovery::BasicTargetDescriptor::kTypePage
;
85 bool IsAttached() const override
{
88 if (!FindTab(&model
, &index
))
90 WebContents
* web_contents
= model
->GetWebContentsAt(index
);
93 return DevToolsAgentHost::IsDebuggerAttached(web_contents
);
96 scoped_refptr
<DevToolsAgentHost
> GetAgentHost() const override
{
99 if (!FindTab(&model
, &index
))
101 WebContents
* web_contents
= model
->GetWebContentsAt(index
);
103 // The tab has been pushed out of memory, pull it back.
104 TabAndroid
* tab
= model
->GetTabAt(index
);
108 if (!tab
->LoadIfNeeded())
111 web_contents
= model
->GetWebContentsAt(index
);
115 return DevToolsAgentHost::GetOrCreateFor(web_contents
);
118 bool Activate() const override
{
121 if (!FindTab(&model
, &index
))
123 model
->SetActiveIndex(index
);
127 bool Close() const override
{
130 if (!FindTab(&model
, &index
))
132 model
->CloseTabAt(index
);
137 TabDescriptor(int tab_id
, WebContents
* web_contents
)
139 title_(base::UTF16ToUTF8(web_contents
->GetTitle())),
140 url_(web_contents
->GetURL()),
141 favicon_url_(GetFaviconURLForContents(web_contents
)),
142 last_activity_time_(web_contents
->GetLastActiveTime()) {
145 TabDescriptor(int tab_id
, const base::string16
& title
, const GURL
& url
)
147 title_(base::UTF16ToUTF8(title
)),
151 bool FindTab(TabModel
** model_result
, int* index_result
) const {
152 for (TabModelList::const_iterator iter
= TabModelList::begin();
153 iter
!= TabModelList::end(); ++iter
) {
154 TabModel
* model
= *iter
;
155 for (int i
= 0; i
< model
->GetTabCount(); ++i
) {
156 TabAndroid
* tab
= model
->GetTabAt(i
);
157 if (tab
&& tab
->GetAndroidId() == tab_id_
) {
158 *model_result
= model
;
168 const std::string title_
;
170 const GURL favicon_url_
;
171 const base::TimeTicks last_activity_time_
;
173 DISALLOW_COPY_AND_ASSIGN(TabDescriptor
);
176 scoped_ptr
<devtools_discovery::DevToolsTargetDescriptor
>
177 CreateNewAndroidTab(const GURL
& url
) {
178 if (TabModelList::empty())
179 return scoped_ptr
<devtools_discovery::DevToolsTargetDescriptor
>();
181 TabModel
* tab_model
= TabModelList::get(0);
183 return scoped_ptr
<devtools_discovery::DevToolsTargetDescriptor
>();
185 WebContents
* web_contents
= tab_model
->CreateNewTabForDevTools(url
);
187 return scoped_ptr
<devtools_discovery::DevToolsTargetDescriptor
>();
189 TabAndroid
* tab
= TabAndroid::FromWebContents(web_contents
);
191 return scoped_ptr
<devtools_discovery::DevToolsTargetDescriptor
>();
193 return make_scoped_ptr(TabDescriptor::CreateForWebContents(
194 tab
->GetAndroidId(), web_contents
));
199 DevToolsDiscoveryProviderAndroid::DevToolsDiscoveryProviderAndroid() {
202 DevToolsDiscoveryProviderAndroid::~DevToolsDiscoveryProviderAndroid() {
205 devtools_discovery::DevToolsTargetDescriptor::List
206 DevToolsDiscoveryProviderAndroid::GetDescriptors() {
207 devtools_discovery::DevToolsTargetDescriptor::List result
;
209 // Enumerate existing tabs, including the ones with no WebContents.
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
);
219 WebContents
* web_contents
= tab
->web_contents();
221 tab_web_contents
.insert(web_contents
);
222 result
.push_back(TabDescriptor::CreateForWebContents(
223 tab
->GetAndroidId(), web_contents
));
225 result
.push_back(TabDescriptor::CreateForUnloadedTab(
226 tab
->GetAndroidId(), tab
->GetTitle(), tab
->GetURL()));
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())
239 result
.push_back(new devtools_discovery::BasicTargetDescriptor(*it
));
246 void DevToolsDiscoveryProviderAndroid::Install() {
247 devtools_discovery::DevToolsDiscoveryManager
* discovery_manager
=
248 devtools_discovery::DevToolsDiscoveryManager::GetInstance();
249 discovery_manager
->AddProvider(
250 make_scoped_ptr(new DevToolsDiscoveryProviderAndroid()));
251 discovery_manager
->SetCreateCallback(base::Bind(&CreateNewAndroidTab
));