Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 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 | |
| 5 #include "chrome/browser/android/dev_tools_manager_delegate_android.h" | |
| 6 | |
| 7 #include "base/basictypes.h" | |
| 8 #include "base/compiler_specific.h" | |
| 9 #include "base/strings/string_number_conversions.h" | |
| 10 #include "base/strings/utf_string_conversions.h" | |
| 11 #include "chrome/browser/android/tab_android.h" | |
| 12 #include "chrome/browser/browser_process.h" | |
| 13 #include "chrome/browser/history/top_sites.h" | |
| 14 #include "chrome/browser/profiles/profile_manager.h" | |
| 15 #include "chrome/browser/ui/android/tab_model/tab_model.h" | |
| 16 #include "chrome/browser/ui/android/tab_model/tab_model_list.h" | |
| 17 #include "content/public/browser/devtools_agent_host.h" | |
| 18 #include "content/public/browser/devtools_target.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" | |
| 22 | |
| 23 using content::DevToolsAgentHost; | |
| 24 using content::WebContents; | |
| 25 | |
| 26 namespace { | |
| 27 | |
| 28 const char kTargetTypePage[] = "page"; | |
| 29 const char kTargetTypeServiceWorker[] = "service_worker"; | |
| 30 const char kTargetTypeOther[] = "other"; | |
| 31 | |
| 32 static GURL GetFaviconURLForContents(WebContents* web_contents) { | |
|
pfeldman
2014/09/18 11:45:58
No need to declare as static since in an anonymous
dgozman
2014/09/19 10:04:33
Done.
| |
| 33 content::NavigationController& controller = web_contents->GetController(); | |
| 34 content::NavigationEntry* entry = controller.GetActiveEntry(); | |
| 35 if (entry != NULL && entry->GetURL().is_valid()) | |
| 36 return entry->GetFavicon().url; | |
| 37 return GURL(); | |
| 38 } | |
| 39 | |
| 40 static GURL GetFaviconURLForAgentHost( | |
| 41 scoped_refptr<DevToolsAgentHost> agent_host) { | |
| 42 if (WebContents* web_contents = agent_host->GetWebContents()) | |
| 43 return GetFaviconURLForContents(web_contents); | |
| 44 return GURL(); | |
| 45 } | |
| 46 | |
| 47 static base::TimeTicks GetLastActiveTimeForAgentHost( | |
| 48 scoped_refptr<DevToolsAgentHost> agent_host) { | |
| 49 if (WebContents* web_contents = agent_host->GetWebContents()) | |
| 50 return web_contents->GetLastActiveTime(); | |
| 51 return base::TimeTicks(); | |
| 52 } | |
| 53 | |
| 54 class TargetBase : public content::DevToolsTarget { | |
| 55 public: | |
| 56 // content::DevToolsTarget implementation: | |
| 57 virtual std::string GetParentId() const OVERRIDE { return std::string(); } | |
| 58 | |
| 59 virtual std::string GetTitle() const OVERRIDE { return title_; } | |
| 60 | |
| 61 virtual std::string GetDescription() const OVERRIDE { return std::string(); } | |
| 62 | |
| 63 virtual GURL GetURL() const OVERRIDE { return url_; } | |
| 64 | |
| 65 virtual GURL GetFaviconURL() const OVERRIDE { return favicon_url_; } | |
| 66 | |
| 67 virtual base::TimeTicks GetLastActivityTime() const OVERRIDE { | |
| 68 return last_activity_time_; | |
| 69 } | |
| 70 | |
| 71 protected: | |
| 72 explicit TargetBase(WebContents* web_contents) | |
| 73 : title_(base::UTF16ToUTF8(web_contents->GetTitle())), | |
| 74 url_(web_contents->GetURL()), | |
| 75 favicon_url_(GetFaviconURLForContents(web_contents)), | |
| 76 last_activity_time_(web_contents->GetLastActiveTime()) { | |
| 77 } | |
| 78 | |
| 79 explicit TargetBase(scoped_refptr<DevToolsAgentHost> agent_host) | |
| 80 : title_(agent_host->GetTitle()), | |
| 81 url_(agent_host->GetURL()), | |
| 82 favicon_url_(GetFaviconURLForAgentHost(agent_host)), | |
| 83 last_activity_time_(GetLastActiveTimeForAgentHost(agent_host)) { | |
| 84 } | |
| 85 | |
| 86 TargetBase(const std::string& title, const GURL& url) | |
| 87 : title_(title), | |
| 88 url_(url) { | |
| 89 } | |
| 90 | |
| 91 private: | |
| 92 const std::string title_; | |
| 93 const GURL url_; | |
| 94 const GURL favicon_url_; | |
| 95 const base::TimeTicks last_activity_time_; | |
| 96 }; | |
| 97 | |
| 98 class TabTarget : public TargetBase { | |
| 99 public: | |
| 100 static TabTarget* CreateForWebContents(int tab_id, | |
| 101 WebContents* web_contents) { | |
| 102 return new TabTarget(tab_id, web_contents); | |
| 103 } | |
| 104 | |
| 105 static TabTarget* CreateForUnloadedTab(int tab_id, | |
| 106 const base::string16& title, | |
| 107 const GURL& url) { | |
| 108 return new TabTarget(tab_id, title, url); | |
| 109 } | |
| 110 | |
| 111 // content::DevToolsTarget implementation: | |
| 112 virtual std::string GetId() const OVERRIDE { | |
| 113 return base::IntToString(tab_id_); | |
| 114 } | |
| 115 | |
| 116 virtual std::string GetType() const OVERRIDE { | |
| 117 return kTargetTypePage; | |
| 118 } | |
| 119 | |
| 120 virtual bool IsAttached() const OVERRIDE { | |
| 121 TabModel* model; | |
| 122 int index; | |
| 123 if (!FindTab(&model, &index)) | |
| 124 return false; | |
| 125 WebContents* web_contents = model->GetWebContentsAt(index); | |
| 126 if (!web_contents) | |
| 127 return false; | |
| 128 return DevToolsAgentHost::IsDebuggerAttached(web_contents); | |
| 129 } | |
| 130 | |
| 131 virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const OVERRIDE { | |
| 132 TabModel* model; | |
| 133 int index; | |
| 134 if (!FindTab(&model, &index)) | |
| 135 return NULL; | |
| 136 WebContents* web_contents = model->GetWebContentsAt(index); | |
| 137 if (!web_contents) { | |
| 138 // The tab has been pushed out of memory, pull it back. | |
| 139 TabAndroid* tab = model->GetTabAt(index); | |
| 140 if (!tab) | |
| 141 return NULL; | |
| 142 | |
| 143 tab->LoadIfNeeded(); | |
| 144 web_contents = model->GetWebContentsAt(index); | |
| 145 if (!web_contents) | |
| 146 return NULL; | |
| 147 } | |
| 148 return DevToolsAgentHost::GetOrCreateFor(web_contents); | |
| 149 } | |
| 150 | |
| 151 virtual bool Activate() const OVERRIDE { | |
| 152 TabModel* model; | |
| 153 int index; | |
| 154 if (!FindTab(&model, &index)) | |
| 155 return false; | |
| 156 model->SetActiveIndex(index); | |
| 157 return true; | |
| 158 } | |
| 159 | |
| 160 virtual bool Close() const OVERRIDE { | |
| 161 TabModel* model; | |
| 162 int index; | |
| 163 if (!FindTab(&model, &index)) | |
| 164 return false; | |
| 165 model->CloseTabAt(index); | |
| 166 return true; | |
| 167 } | |
| 168 | |
| 169 private: | |
| 170 TabTarget(int tab_id, WebContents* web_contents) | |
| 171 : TargetBase(web_contents), | |
| 172 tab_id_(tab_id) { | |
| 173 } | |
| 174 | |
| 175 TabTarget(int tab_id, const base::string16& title, const GURL& url) | |
| 176 : TargetBase(base::UTF16ToUTF8(title), url), | |
| 177 tab_id_(tab_id) { | |
| 178 } | |
| 179 | |
| 180 bool FindTab(TabModel** model_result, int* index_result) const { | |
| 181 for (TabModelList::const_iterator iter = TabModelList::begin(); | |
| 182 iter != TabModelList::end(); ++iter) { | |
| 183 TabModel* model = *iter; | |
| 184 for (int i = 0; i < model->GetTabCount(); ++i) { | |
| 185 TabAndroid* tab = model->GetTabAt(i); | |
| 186 if (tab && tab->GetAndroidId() == tab_id_) { | |
| 187 *model_result = model; | |
| 188 *index_result = i; | |
| 189 return true; | |
| 190 } | |
| 191 } | |
| 192 } | |
| 193 return false; | |
| 194 } | |
| 195 | |
| 196 const int tab_id_; | |
| 197 }; | |
| 198 | |
| 199 class NonTabTarget : public TargetBase { | |
| 200 public: | |
| 201 explicit NonTabTarget(scoped_refptr<DevToolsAgentHost> agent_host) | |
| 202 : TargetBase(agent_host), | |
| 203 agent_host_(agent_host) { | |
| 204 } | |
| 205 | |
| 206 // content::DevToolsTarget implementation: | |
| 207 virtual std::string GetId() const OVERRIDE { | |
| 208 return agent_host_->GetId(); | |
| 209 } | |
| 210 | |
| 211 virtual std::string GetType() const OVERRIDE { | |
| 212 switch (agent_host_->GetType()) { | |
| 213 case DevToolsAgentHost::TYPE_WEB_CONTENTS: | |
| 214 if (TabModelList::begin() == TabModelList::end()) { | |
| 215 // If there are no tab models we must be running in ChromeShell. | |
| 216 // Return the 'page' target type for backwards compatibility. | |
| 217 return kTargetTypePage; | |
| 218 } | |
| 219 break; | |
| 220 case DevToolsAgentHost::TYPE_SERVICE_WORKER: | |
| 221 return kTargetTypeServiceWorker; | |
| 222 default: | |
| 223 break; | |
| 224 } | |
| 225 return kTargetTypeOther; | |
| 226 } | |
| 227 | |
| 228 virtual bool IsAttached() const OVERRIDE { | |
| 229 return agent_host_->IsAttached(); | |
| 230 } | |
| 231 | |
| 232 virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const OVERRIDE { | |
| 233 return agent_host_; | |
| 234 } | |
| 235 | |
| 236 virtual bool Activate() const OVERRIDE { | |
| 237 return agent_host_->Activate(); | |
| 238 } | |
| 239 | |
| 240 virtual bool Close() const OVERRIDE { | |
| 241 return agent_host_->Close(); | |
| 242 } | |
| 243 | |
| 244 private: | |
| 245 scoped_refptr<DevToolsAgentHost> agent_host_; | |
| 246 }; | |
| 247 | |
| 248 } // namespace | |
| 249 | |
| 250 DevToolsManagerDelegateAndroid::DevToolsManagerDelegateAndroid() | |
| 251 : network_protocol_handler_(new DevToolsNetworkProtocolHandler()) { | |
| 252 } | |
| 253 | |
| 254 DevToolsManagerDelegateAndroid::~DevToolsManagerDelegateAndroid() { | |
| 255 } | |
| 256 | |
| 257 void DevToolsManagerDelegateAndroid::Inspect( | |
| 258 content::BrowserContext* browser_context, | |
| 259 content::DevToolsAgentHost* agent_host) { | |
| 260 } | |
| 261 | |
| 262 base::DictionaryValue* DevToolsManagerDelegateAndroid::HandleCommand( | |
| 263 content::DevToolsAgentHost* agent_host, | |
| 264 base::DictionaryValue* command_dict) { | |
| 265 return network_protocol_handler_->HandleCommand(agent_host, command_dict); | |
| 266 } | |
| 267 | |
| 268 void DevToolsManagerDelegateAndroid::DevToolsAgentStateChanged( | |
| 269 content::DevToolsAgentHost* agent_host, | |
| 270 bool attached) { | |
| 271 network_protocol_handler_->DevToolsAgentStateChanged(agent_host, attached); | |
| 272 } | |
| 273 | |
| 274 scoped_ptr<content::DevToolsTarget> | |
| 275 DevToolsManagerDelegateAndroid::CreateNewTarget(const GURL& url) { | |
| 276 if (TabModelList::empty()) | |
| 277 return scoped_ptr<content::DevToolsTarget>(); | |
| 278 TabModel* tab_model = TabModelList::get(0); | |
| 279 if (!tab_model) | |
| 280 return scoped_ptr<content::DevToolsTarget>(); | |
| 281 WebContents* web_contents = tab_model->CreateNewTabForDevTools(url); | |
| 282 if (!web_contents) | |
| 283 return scoped_ptr<content::DevToolsTarget>(); | |
| 284 | |
| 285 TabAndroid* tab = TabAndroid::FromWebContents(web_contents); | |
| 286 if (!tab) | |
| 287 return scoped_ptr<content::DevToolsTarget>(); | |
| 288 | |
| 289 return scoped_ptr<content::DevToolsTarget>( | |
| 290 TabTarget::CreateForWebContents(tab->GetAndroidId(), web_contents)); | |
| 291 } | |
| 292 | |
| 293 void DevToolsManagerDelegateAndroid::EnumerateTargets(TargetCallback callback) { | |
| 294 TargetList targets; | |
| 295 | |
| 296 // Enumerate existing tabs, including the ones with no WebContents. | |
| 297 std::set<WebContents*> tab_web_contents; | |
| 298 for (TabModelList::const_iterator iter = TabModelList::begin(); | |
| 299 iter != TabModelList::end(); ++iter) { | |
| 300 TabModel* model = *iter; | |
| 301 for (int i = 0; i < model->GetTabCount(); ++i) { | |
| 302 TabAndroid* tab = model->GetTabAt(i); | |
| 303 if (!tab) | |
| 304 continue; | |
| 305 | |
| 306 WebContents* web_contents = model->GetWebContentsAt(i); | |
| 307 if (web_contents) { | |
| 308 tab_web_contents.insert(web_contents); | |
| 309 targets.push_back(TabTarget::CreateForWebContents(tab->GetAndroidId(), | |
| 310 web_contents)); | |
| 311 } else { | |
| 312 targets.push_back(TabTarget::CreateForUnloadedTab(tab->GetAndroidId(), | |
| 313 tab->GetTitle(), | |
| 314 tab->GetURL())); | |
| 315 } | |
| 316 } | |
| 317 } | |
| 318 | |
| 319 // Add targets for WebContents not associated with any tabs. | |
| 320 DevToolsAgentHost::List agents = | |
| 321 DevToolsAgentHost::GetOrCreateAll(); | |
| 322 for (DevToolsAgentHost::List::iterator it = agents.begin(); | |
| 323 it != agents.end(); ++it) { | |
| 324 if (WebContents* web_contents = (*it)->GetWebContents()) { | |
| 325 if (tab_web_contents.find(web_contents) != tab_web_contents.end()) | |
| 326 continue; | |
| 327 } | |
| 328 targets.push_back(new NonTabTarget(*it)); | |
| 329 } | |
| 330 | |
| 331 callback.Run(targets); | |
| 332 } | |
| 333 | |
| 334 std::string DevToolsManagerDelegateAndroid::GetPageThumbnailData( | |
| 335 const GURL& url) { | |
| 336 Profile* profile = | |
| 337 ProfileManager::GetLastUsedProfile()->GetOriginalProfile(); | |
| 338 history::TopSites* top_sites = profile->GetTopSites(); | |
| 339 if (top_sites) { | |
| 340 scoped_refptr<base::RefCountedMemory> data; | |
| 341 if (top_sites->GetPageThumbnail(url, false, &data)) | |
| 342 return std::string(data->front_as<char>(), data->size()); | |
| 343 } | |
| 344 return ""; | |
| 345 } | |
| OLD | NEW |