Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / android / dev_tools_manager_delegate_android.cc
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       if (!tab->LoadIfNeeded())
144         return NULL;
145
146       web_contents = model->GetWebContentsAt(index);
147       if (!web_contents)
148         return NULL;
149     }
150     return DevToolsAgentHost::GetOrCreateFor(web_contents);
151   }
152
153   virtual bool Activate() const OVERRIDE {
154     TabModel* model;
155     int index;
156     if (!FindTab(&model, &index))
157       return false;
158     model->SetActiveIndex(index);
159     return true;
160   }
161
162   virtual bool Close() const OVERRIDE {
163     TabModel* model;
164     int index;
165     if (!FindTab(&model, &index))
166       return false;
167     model->CloseTabAt(index);
168     return true;
169   }
170
171  private:
172   TabTarget(int tab_id, WebContents* web_contents)
173       : TargetBase(web_contents),
174         tab_id_(tab_id) {
175   }
176
177   TabTarget(int tab_id, const base::string16& title, const GURL& url)
178       : TargetBase(base::UTF16ToUTF8(title), url),
179         tab_id_(tab_id) {
180   }
181
182   bool FindTab(TabModel** model_result, int* index_result) const {
183     for (TabModelList::const_iterator iter = TabModelList::begin();
184         iter != TabModelList::end(); ++iter) {
185       TabModel* model = *iter;
186       for (int i = 0; i < model->GetTabCount(); ++i) {
187         TabAndroid* tab = model->GetTabAt(i);
188         if (tab && tab->GetAndroidId() == tab_id_) {
189           *model_result = model;
190           *index_result = i;
191           return true;
192         }
193       }
194     }
195     return false;
196   }
197
198   const int tab_id_;
199 };
200
201 class NonTabTarget : public TargetBase {
202  public:
203   explicit NonTabTarget(scoped_refptr<DevToolsAgentHost> agent_host)
204       : TargetBase(agent_host),
205         agent_host_(agent_host) {
206   }
207
208   // content::DevToolsTarget implementation:
209   virtual std::string GetId() const OVERRIDE {
210     return agent_host_->GetId();
211   }
212
213   virtual std::string GetType() const OVERRIDE {
214     switch (agent_host_->GetType()) {
215       case DevToolsAgentHost::TYPE_WEB_CONTENTS:
216         if (TabModelList::begin() == TabModelList::end()) {
217           // If there are no tab models we must be running in ChromeShell.
218           // Return the 'page' target type for backwards compatibility.
219           return kTargetTypePage;
220         }
221         break;
222       case DevToolsAgentHost::TYPE_SERVICE_WORKER:
223         return kTargetTypeServiceWorker;
224       default:
225         break;
226     }
227     return kTargetTypeOther;
228   }
229
230   virtual bool IsAttached() const OVERRIDE {
231     return agent_host_->IsAttached();
232   }
233
234   virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const OVERRIDE {
235     return agent_host_;
236   }
237
238   virtual bool Activate() const OVERRIDE {
239     return agent_host_->Activate();
240   }
241
242   virtual bool Close() const OVERRIDE {
243     return agent_host_->Close();
244   }
245
246  private:
247   scoped_refptr<DevToolsAgentHost> agent_host_;
248 };
249
250 }  // namespace
251
252 DevToolsManagerDelegateAndroid::DevToolsManagerDelegateAndroid()
253     : network_protocol_handler_(new DevToolsNetworkProtocolHandler()) {
254 }
255
256 DevToolsManagerDelegateAndroid::~DevToolsManagerDelegateAndroid() {
257 }
258
259 void DevToolsManagerDelegateAndroid::Inspect(
260     content::BrowserContext* browser_context,
261     content::DevToolsAgentHost* agent_host) {
262 }
263
264 base::DictionaryValue* DevToolsManagerDelegateAndroid::HandleCommand(
265     content::DevToolsAgentHost* agent_host,
266     base::DictionaryValue* command_dict) {
267   return network_protocol_handler_->HandleCommand(agent_host, command_dict);
268 }
269
270 void DevToolsManagerDelegateAndroid::DevToolsAgentStateChanged(
271     content::DevToolsAgentHost* agent_host,
272     bool attached) {
273   network_protocol_handler_->DevToolsAgentStateChanged(agent_host, attached);
274 }
275
276 scoped_ptr<content::DevToolsTarget>
277     DevToolsManagerDelegateAndroid::CreateNewTarget(const GURL& url) {
278   if (TabModelList::empty())
279     return scoped_ptr<content::DevToolsTarget>();
280
281   TabModel* tab_model = TabModelList::get(0);
282   if (!tab_model)
283     return scoped_ptr<content::DevToolsTarget>();
284
285   WebContents* web_contents = tab_model->CreateNewTabForDevTools(url);
286   if (!web_contents)
287     return scoped_ptr<content::DevToolsTarget>();
288
289   TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
290   if (!tab)
291     return scoped_ptr<content::DevToolsTarget>();
292
293   return scoped_ptr<content::DevToolsTarget>(
294       TabTarget::CreateForWebContents(tab->GetAndroidId(), web_contents));
295 }
296
297 void DevToolsManagerDelegateAndroid::EnumerateTargets(TargetCallback callback) {
298   TargetList targets;
299
300   // Enumerate existing tabs, including the ones with no WebContents.
301   std::set<WebContents*> tab_web_contents;
302   for (TabModelList::const_iterator iter = TabModelList::begin();
303       iter != TabModelList::end(); ++iter) {
304     TabModel* model = *iter;
305     for (int i = 0; i < model->GetTabCount(); ++i) {
306       TabAndroid* tab = model->GetTabAt(i);
307       if (!tab)
308         continue;
309
310       WebContents* web_contents = model->GetWebContentsAt(i);
311       if (web_contents) {
312         tab_web_contents.insert(web_contents);
313         targets.push_back(TabTarget::CreateForWebContents(tab->GetAndroidId(),
314                                                           web_contents));
315       } else {
316         targets.push_back(TabTarget::CreateForUnloadedTab(tab->GetAndroidId(),
317                                                           tab->GetTitle(),
318                                                           tab->GetURL()));
319       }
320     }
321   }
322
323   // Add targets for WebContents not associated with any tabs.
324   DevToolsAgentHost::List agents = DevToolsAgentHost::GetOrCreateAll();
325   for (DevToolsAgentHost::List::iterator it = agents.begin();
326        it != agents.end(); ++it) {
327     if (WebContents* web_contents = (*it)->GetWebContents()) {
328       if (tab_web_contents.find(web_contents) != tab_web_contents.end())
329         continue;
330     }
331     targets.push_back(new NonTabTarget(*it));
332   }
333
334   callback.Run(targets);
335 }
336
337 std::string DevToolsManagerDelegateAndroid::GetPageThumbnailData(
338     const GURL& url) {
339   Profile* profile = ProfileManager::GetLastUsedProfile()->GetOriginalProfile();
340   history::TopSites* top_sites = profile->GetTopSites();
341   if (top_sites) {
342     scoped_refptr<base::RefCountedMemory> data;
343     if (top_sites->GetPageThumbnail(url, false, &data))
344       return std::string(data->front_as<char>(), data->size());
345   }
346   return std::string();
347 }