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 GURL GetFaviconURLForContents(WebContents* web_contents) { |
| 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 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 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 |
| 279 TabModel* tab_model = TabModelList::get(0); |
| 280 if (!tab_model) |
| 281 return scoped_ptr<content::DevToolsTarget>(); |
| 282 |
| 283 WebContents* web_contents = tab_model->CreateNewTabForDevTools(url); |
| 284 if (!web_contents) |
| 285 return scoped_ptr<content::DevToolsTarget>(); |
| 286 |
| 287 TabAndroid* tab = TabAndroid::FromWebContents(web_contents); |
| 288 if (!tab) |
| 289 return scoped_ptr<content::DevToolsTarget>(); |
| 290 |
| 291 return scoped_ptr<content::DevToolsTarget>( |
| 292 TabTarget::CreateForWebContents(tab->GetAndroidId(), web_contents)); |
| 293 } |
| 294 |
| 295 void DevToolsManagerDelegateAndroid::EnumerateTargets(TargetCallback callback) { |
| 296 TargetList targets; |
| 297 |
| 298 // Enumerate existing tabs, including the ones with no WebContents. |
| 299 std::set<WebContents*> tab_web_contents; |
| 300 for (TabModelList::const_iterator iter = TabModelList::begin(); |
| 301 iter != TabModelList::end(); ++iter) { |
| 302 TabModel* model = *iter; |
| 303 for (int i = 0; i < model->GetTabCount(); ++i) { |
| 304 TabAndroid* tab = model->GetTabAt(i); |
| 305 if (!tab) |
| 306 continue; |
| 307 |
| 308 WebContents* web_contents = model->GetWebContentsAt(i); |
| 309 if (web_contents) { |
| 310 tab_web_contents.insert(web_contents); |
| 311 targets.push_back(TabTarget::CreateForWebContents(tab->GetAndroidId(), |
| 312 web_contents)); |
| 313 } else { |
| 314 targets.push_back(TabTarget::CreateForUnloadedTab(tab->GetAndroidId(), |
| 315 tab->GetTitle(), |
| 316 tab->GetURL())); |
| 317 } |
| 318 } |
| 319 } |
| 320 |
| 321 // Add targets for WebContents not associated with any tabs. |
| 322 DevToolsAgentHost::List agents = DevToolsAgentHost::GetOrCreateAll(); |
| 323 for (DevToolsAgentHost::List::iterator it = agents.begin(); |
| 324 it != agents.end(); ++it) { |
| 325 if (WebContents* web_contents = (*it)->GetWebContents()) { |
| 326 if (tab_web_contents.find(web_contents) != tab_web_contents.end()) |
| 327 continue; |
| 328 } |
| 329 targets.push_back(new NonTabTarget(*it)); |
| 330 } |
| 331 |
| 332 callback.Run(targets); |
| 333 } |
| 334 |
| 335 std::string DevToolsManagerDelegateAndroid::GetPageThumbnailData( |
| 336 const GURL& url) { |
| 337 Profile* profile = 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 std::string(); |
| 345 } |
OLD | NEW |