OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/android/dev_tools_discovery_provider_android.h" | 5 #include "chrome/browser/android/dev_tools_discovery_provider_android.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
13 #include "chrome/browser/android/tab_android.h" | 13 #include "chrome/browser/android/tab_android.h" |
14 #include "chrome/browser/browser_process.h" | 14 #include "chrome/browser/browser_process.h" |
15 #include "chrome/browser/ui/android/tab_model/tab_model.h" | 15 #include "chrome/browser/ui/android/tab_model/tab_model.h" |
16 #include "chrome/browser/ui/android/tab_model/tab_model_list.h" | 16 #include "chrome/browser/ui/android/tab_model/tab_model_list.h" |
17 #include "components/devtools_discovery/basic_target_descriptor.h" | 17 #include "components/devtools_discovery/basic_target_descriptor.h" |
18 #include "components/devtools_discovery/devtools_discovery_manager.h" | 18 #include "components/devtools_discovery/devtools_discovery_manager.h" |
19 #include "content/public/browser/devtools_agent_host.h" | 19 #include "content/public/browser/devtools_agent_host.h" |
20 #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" | |
23 #include "content/public/browser/favicon_status.h" | 20 #include "content/public/browser/favicon_status.h" |
24 #include "content/public/browser/navigation_entry.h" | 21 #include "content/public/browser/navigation_entry.h" |
25 #include "content/public/browser/web_contents.h" | 22 #include "content/public/browser/web_contents.h" |
26 | 23 |
27 using content::DevToolsAgentHost; | 24 using content::DevToolsAgentHost; |
28 using content::WebContents; | 25 using content::WebContents; |
29 using devtools_discovery::DevToolsTargetDescriptor; | |
30 | 26 |
31 namespace { | 27 namespace { |
32 | 28 |
33 class TabProxyDelegate : public content::DevToolsExternalAgentProxyDelegate, | 29 GURL GetFaviconURLForContents(WebContents* web_contents) { |
34 public content::DevToolsAgentHostClient { | 30 content::NavigationController& controller = web_contents->GetController(); |
| 31 content::NavigationEntry* entry = controller.GetActiveEntry(); |
| 32 if (entry != NULL && entry->GetURL().is_valid()) |
| 33 return entry->GetFavicon().url; |
| 34 return GURL(); |
| 35 } |
| 36 |
| 37 class TabDescriptor : public devtools_discovery::DevToolsTargetDescriptor { |
35 public: | 38 public: |
36 explicit TabProxyDelegate(TabAndroid* tab) | 39 static TabDescriptor* CreateForWebContents(int tab_id, |
37 : tab_id_(tab->GetAndroidId()), | 40 WebContents* web_contents) { |
38 title_(base::UTF16ToUTF8(tab->GetTitle())), | 41 return new TabDescriptor(tab_id, web_contents); |
39 url_(tab->GetURL()), | |
40 agent_host_(tab->web_contents() ? | |
41 DevToolsAgentHost::GetOrCreateFor(tab->web_contents()) : nullptr) { | |
42 } | 42 } |
43 | 43 |
44 ~TabProxyDelegate() override { | 44 static TabDescriptor* CreateForUnloadedTab(int tab_id, |
| 45 const base::string16& title, |
| 46 const GURL& url) { |
| 47 return new TabDescriptor(tab_id, title, url); |
45 } | 48 } |
46 | 49 |
47 void DispatchProtocolMessage(DevToolsAgentHost* agent_host, | 50 ~TabDescriptor() override { |
48 const std::string& message) override { | |
49 proxy_->DispatchOnClientHost(message); | |
50 } | 51 } |
51 | 52 |
52 void AgentHostClosed(DevToolsAgentHost* agent_host, | 53 // devtools_discovery::DevToolsTargetDescriptor implementation. |
53 bool replaced_with_another_client) override { | 54 std::string GetParentId() const override { |
54 proxy_->ConnectionClosed(); | 55 return std::string(); |
55 } | 56 } |
56 | 57 |
57 void Attach(content::DevToolsExternalAgentProxy* proxy) override { | 58 std::string GetTitle() const override { |
58 proxy_ = proxy; | 59 return title_; |
59 MaterializeAgentHost(); | |
60 } | 60 } |
61 | 61 |
62 void Detach() override { | 62 std::string GetDescription() const override { |
63 if (agent_host_) | 63 return std::string(); |
64 agent_host_->DetachClient(this); | |
65 agent_host_ = nullptr; | |
66 proxy_ = nullptr; | |
67 } | 64 } |
68 | 65 |
69 std::string GetId() override { | 66 GURL GetURL() const override { |
| 67 return url_; |
| 68 } |
| 69 |
| 70 GURL GetFaviconURL() const override { |
| 71 return favicon_url_; |
| 72 } |
| 73 |
| 74 base::TimeTicks GetLastActivityTime() const override { |
| 75 return last_activity_time_; |
| 76 } |
| 77 |
| 78 std::string GetId() const override { |
70 return base::IntToString(tab_id_); | 79 return base::IntToString(tab_id_); |
71 } | 80 } |
72 | 81 |
73 std::string GetType() override { | 82 std::string GetType() const override { |
74 return agent_host_ ? agent_host_->GetType() : DevToolsAgentHost::kTypePage; | 83 return devtools_discovery::BasicTargetDescriptor::kTypePage; |
75 } | 84 } |
76 | 85 |
77 std::string GetTitle() override { | 86 bool IsAttached() const override { |
78 return agent_host_ ? agent_host_->GetTitle() : title_; | |
79 } | |
80 | |
81 std::string GetDescription() override { | |
82 return agent_host_ ? agent_host_->GetDescription() : ""; | |
83 } | |
84 | |
85 GURL GetURL() override { | |
86 return agent_host_ ? agent_host_->GetURL() : url_; | |
87 } | |
88 | |
89 GURL GetFaviconURL() override { | |
90 return agent_host_ ? agent_host_->GetFaviconURL() : GURL(); | |
91 } | |
92 | |
93 bool Activate() override { | |
94 TabModel* model; | 87 TabModel* model; |
95 int index; | 88 int index; |
96 if (!FindTab(&model, &index)) | 89 if (!FindTab(&model, &index)) |
| 90 return false; |
| 91 WebContents* web_contents = model->GetWebContentsAt(index); |
| 92 if (!web_contents) |
| 93 return false; |
| 94 return DevToolsAgentHost::IsDebuggerAttached(web_contents); |
| 95 } |
| 96 |
| 97 scoped_refptr<DevToolsAgentHost> GetAgentHost() const override { |
| 98 TabModel* model; |
| 99 int index; |
| 100 if (!FindTab(&model, &index)) |
| 101 return NULL; |
| 102 WebContents* web_contents = model->GetWebContentsAt(index); |
| 103 if (!web_contents) { |
| 104 // The tab has been pushed out of memory, pull it back. |
| 105 TabAndroid* tab = model->GetTabAt(index); |
| 106 if (!tab) |
| 107 return NULL; |
| 108 |
| 109 if (!tab->LoadIfNeeded()) |
| 110 return NULL; |
| 111 |
| 112 web_contents = model->GetWebContentsAt(index); |
| 113 if (!web_contents) |
| 114 return NULL; |
| 115 } |
| 116 return DevToolsAgentHost::GetOrCreateFor(web_contents); |
| 117 } |
| 118 |
| 119 bool Activate() const override { |
| 120 TabModel* model; |
| 121 int index; |
| 122 if (!FindTab(&model, &index)) |
97 return false; | 123 return false; |
98 model->SetActiveIndex(index); | 124 model->SetActiveIndex(index); |
99 return true; | 125 return true; |
100 } | 126 } |
101 | 127 |
102 bool Inspect() override { | 128 bool Close() const override { |
103 MaterializeAgentHost(); | |
104 if (agent_host_) | |
105 return agent_host_->Inspect(); | |
106 return false; | |
107 } | |
108 | |
109 void Reload() override { | |
110 MaterializeAgentHost(); | |
111 if (agent_host_) | |
112 agent_host_->Reload(); | |
113 } | |
114 | |
115 bool Close() override { | |
116 TabModel* model; | 129 TabModel* model; |
117 int index; | 130 int index; |
118 if (!FindTab(&model, &index)) | 131 if (!FindTab(&model, &index)) |
119 return false; | 132 return false; |
120 model->CloseTabAt(index); | 133 model->CloseTabAt(index); |
121 return true; | 134 return true; |
122 } | 135 } |
123 | 136 |
124 void SendMessageToBackend(const std::string& message) override { | 137 private: |
125 if (agent_host_) | 138 TabDescriptor(int tab_id, WebContents* web_contents) |
126 agent_host_->DispatchProtocolMessage(this, message); | 139 : tab_id_(tab_id), |
| 140 title_(base::UTF16ToUTF8(web_contents->GetTitle())), |
| 141 url_(web_contents->GetURL()), |
| 142 favicon_url_(GetFaviconURLForContents(web_contents)), |
| 143 last_activity_time_(web_contents->GetLastActiveTime()) { |
127 } | 144 } |
128 | 145 |
129 private: | 146 TabDescriptor(int tab_id, const base::string16& title, const GURL& url) |
130 void MaterializeAgentHost() { | 147 : tab_id_(tab_id), |
131 if (agent_host_) | 148 title_(base::UTF16ToUTF8(title)), |
132 return; | 149 url_(url) { |
133 TabModel* model; | |
134 int index; | |
135 if (!FindTab(&model, &index)) | |
136 return; | |
137 WebContents* web_contents = model->GetWebContentsAt(index); | |
138 if (!web_contents) | |
139 return; | |
140 agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents); | |
141 } | 150 } |
142 | 151 |
143 bool FindTab(TabModel** model_result, int* index_result) const { | 152 bool FindTab(TabModel** model_result, int* index_result) const { |
144 for (TabModelList::const_iterator iter = TabModelList::begin(); | 153 for (TabModelList::const_iterator iter = TabModelList::begin(); |
145 iter != TabModelList::end(); ++iter) { | 154 iter != TabModelList::end(); ++iter) { |
146 TabModel* model = *iter; | 155 TabModel* model = *iter; |
147 for (int i = 0; i < model->GetTabCount(); ++i) { | 156 for (int i = 0; i < model->GetTabCount(); ++i) { |
148 TabAndroid* tab = model->GetTabAt(i); | 157 TabAndroid* tab = model->GetTabAt(i); |
149 if (tab && tab->GetAndroidId() == tab_id_) { | 158 if (tab && tab->GetAndroidId() == tab_id_) { |
150 *model_result = model; | 159 *model_result = model; |
151 *index_result = i; | 160 *index_result = i; |
152 return true; | 161 return true; |
153 } | 162 } |
154 } | 163 } |
155 } | 164 } |
156 return false; | 165 return false; |
157 } | 166 } |
158 | 167 |
159 const int tab_id_; | 168 const int tab_id_; |
160 const std::string title_; | 169 const std::string title_; |
161 const GURL url_; | 170 const GURL url_; |
162 scoped_refptr<content::DevToolsAgentHost> agent_host_; | 171 const GURL favicon_url_; |
163 content::DevToolsExternalAgentProxy* proxy_; | 172 const base::TimeTicks last_activity_time_; |
164 DISALLOW_COPY_AND_ASSIGN(TabProxyDelegate); | 173 |
| 174 DISALLOW_COPY_AND_ASSIGN(TabDescriptor); |
165 }; | 175 }; |
166 | 176 |
167 std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor> | 177 std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor> |
168 CreateNewAndroidTab(const GURL& url) { | 178 CreateNewAndroidTab(const GURL& url) { |
169 if (TabModelList::empty()) | 179 if (TabModelList::empty()) |
170 return std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor>(); | 180 return std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor>(); |
171 | 181 |
172 TabModel* tab_model = TabModelList::get(0); | 182 TabModel* tab_model = TabModelList::get(0); |
173 if (!tab_model) | 183 if (!tab_model) |
174 return std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor>(); | 184 return std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor>(); |
175 | 185 |
176 WebContents* web_contents = tab_model->CreateNewTabForDevTools(url); | 186 WebContents* web_contents = tab_model->CreateNewTabForDevTools(url); |
177 if (!web_contents) | 187 if (!web_contents) |
178 return std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor>(); | 188 return std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor>(); |
179 | 189 |
180 TabAndroid* tab = TabAndroid::FromWebContents(web_contents); | 190 TabAndroid* tab = TabAndroid::FromWebContents(web_contents); |
181 if (!tab) | 191 if (!tab) |
182 return std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor>(); | 192 return std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor>(); |
183 | 193 |
184 scoped_refptr<content::DevToolsAgentHost> host = | 194 return base::WrapUnique( |
185 DevToolsAgentHost::Create(new TabProxyDelegate(tab)); | 195 TabDescriptor::CreateForWebContents(tab->GetAndroidId(), web_contents)); |
186 return base::WrapUnique(new devtools_discovery::BasicTargetDescriptor(host)); | |
187 } | 196 } |
188 | 197 |
189 } // namespace | 198 } // namespace |
190 | 199 |
191 DevToolsDiscoveryProviderAndroid::DevToolsDiscoveryProviderAndroid() { | 200 DevToolsDiscoveryProviderAndroid::DevToolsDiscoveryProviderAndroid() { |
192 } | 201 } |
193 | 202 |
194 DevToolsDiscoveryProviderAndroid::~DevToolsDiscoveryProviderAndroid() { | 203 DevToolsDiscoveryProviderAndroid::~DevToolsDiscoveryProviderAndroid() { |
195 } | 204 } |
196 | 205 |
197 devtools_discovery::DevToolsTargetDescriptor::List | 206 devtools_discovery::DevToolsTargetDescriptor::List |
198 DevToolsDiscoveryProviderAndroid::GetDescriptors() { | 207 DevToolsDiscoveryProviderAndroid::GetDescriptors() { |
199 devtools_discovery::DevToolsTargetDescriptor::List result; | 208 devtools_discovery::DevToolsTargetDescriptor::List result; |
200 | 209 |
201 // Enumerate existing tabs, including the ones with no WebContents. | 210 // Enumerate existing tabs, including the ones with no WebContents. |
202 std::set<WebContents*> tab_web_contents; | 211 std::set<WebContents*> tab_web_contents; |
203 for (TabModelList::const_iterator iter = TabModelList::begin(); | 212 for (TabModelList::const_iterator iter = TabModelList::begin(); |
204 iter != TabModelList::end(); ++iter) { | 213 iter != TabModelList::end(); ++iter) { |
205 TabModel* model = *iter; | 214 TabModel* model = *iter; |
206 for (int i = 0; i < model->GetTabCount(); ++i) { | 215 for (int i = 0; i < model->GetTabCount(); ++i) { |
207 TabAndroid* tab = model->GetTabAt(i); | 216 TabAndroid* tab = model->GetTabAt(i); |
208 if (!tab) | 217 if (!tab) |
209 continue; | 218 continue; |
210 | 219 |
211 scoped_refptr<content::DevToolsAgentHost> host = | 220 WebContents* web_contents = tab->web_contents(); |
212 DevToolsAgentHost::Create(new TabProxyDelegate(tab)); | 221 if (web_contents) { |
| 222 tab_web_contents.insert(web_contents); |
| 223 result.push_back(TabDescriptor::CreateForWebContents( |
| 224 tab->GetAndroidId(), web_contents)); |
| 225 } else { |
| 226 result.push_back(TabDescriptor::CreateForUnloadedTab( |
| 227 tab->GetAndroidId(), tab->GetTitle(), tab->GetURL())); |
| 228 } |
213 } | 229 } |
214 } | 230 } |
215 | 231 |
216 // Add descriptors for targets not associated with any tabs. | 232 // Add descriptors for targets not associated with any tabs. |
217 DevToolsAgentHost::List agents = DevToolsAgentHost::GetOrCreateAll(); | 233 DevToolsAgentHost::List agents = DevToolsAgentHost::GetOrCreateAll(); |
218 for (DevToolsAgentHost::List::iterator it = agents.begin(); | 234 for (DevToolsAgentHost::List::iterator it = agents.begin(); |
219 it != agents.end(); ++it) { | 235 it != agents.end(); ++it) { |
220 if (WebContents* web_contents = (*it)->GetWebContents()) { | 236 if (WebContents* web_contents = (*it)->GetWebContents()) { |
221 if (tab_web_contents.find(web_contents) != tab_web_contents.end()) | 237 if (tab_web_contents.find(web_contents) != tab_web_contents.end()) |
222 continue; | 238 continue; |
223 } | 239 } |
224 result.push_back(new devtools_discovery::BasicTargetDescriptor(*it)); | 240 result.push_back(new devtools_discovery::BasicTargetDescriptor(*it)); |
225 } | 241 } |
226 | 242 |
227 return result; | 243 return result; |
228 } | 244 } |
229 | 245 |
230 // static | 246 // static |
231 void DevToolsDiscoveryProviderAndroid::Install() { | 247 void DevToolsDiscoveryProviderAndroid::Install() { |
232 devtools_discovery::DevToolsDiscoveryManager* discovery_manager = | 248 devtools_discovery::DevToolsDiscoveryManager* discovery_manager = |
233 devtools_discovery::DevToolsDiscoveryManager::GetInstance(); | 249 devtools_discovery::DevToolsDiscoveryManager::GetInstance(); |
234 discovery_manager->AddProvider( | 250 discovery_manager->AddProvider( |
235 base::WrapUnique(new DevToolsDiscoveryProviderAndroid())); | 251 base::WrapUnique(new DevToolsDiscoveryProviderAndroid())); |
236 discovery_manager->SetCreateCallback(base::Bind(&CreateNewAndroidTab)); | 252 discovery_manager->SetCreateCallback(base::Bind(&CreateNewAndroidTab)); |
237 } | 253 } |
OLD | NEW |