- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / task_manager / panel_resource_provider.cc
1 // Copyright 2013 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/task_manager/panel_resource_provider.h"
6
7 #include "base/i18n/rtl.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/task_manager/renderer_resource.h"
12 #include "chrome/browser/task_manager/resource_provider.h"
13 #include "chrome/browser/task_manager/task_manager.h"
14 #include "chrome/browser/task_manager/task_manager_util.h"
15 #include "chrome/browser/ui/panels/panel.h"
16 #include "chrome/browser/ui/panels/panel_manager.h"
17 #include "chrome/common/extensions/extension.h"
18 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/render_process_host.h"
20 #include "content/public/browser/render_view_host.h"
21 #include "content/public/browser/web_contents.h"
22 #include "extensions/browser/view_type_utils.h"
23 #include "ui/base/l10n/l10n_util.h"
24
25 using content::RenderProcessHost;
26 using content::RenderViewHost;
27 using content::WebContents;
28 using extensions::Extension;
29
30 namespace task_manager {
31
32 class PanelResource : public RendererResource {
33  public:
34   explicit PanelResource(Panel* panel);
35   virtual ~PanelResource();
36
37   // Resource methods:
38   virtual Type GetType() const OVERRIDE;
39   virtual string16 GetTitle() const OVERRIDE;
40   virtual string16 GetProfileName() const OVERRIDE;
41   virtual gfx::ImageSkia GetIcon() const OVERRIDE;
42   virtual content::WebContents* GetWebContents() const OVERRIDE;
43   virtual const extensions::Extension* GetExtension() const OVERRIDE;
44
45  private:
46   Panel* panel_;
47   // Determines prefix for title reflecting whether extensions are apps
48   // or in incognito mode.
49   int message_prefix_id_;
50
51   DISALLOW_COPY_AND_ASSIGN(PanelResource);
52 };
53
54 PanelResource::PanelResource(Panel* panel)
55     : RendererResource(
56         panel->GetWebContents()->GetRenderProcessHost()->GetHandle(),
57         panel->GetWebContents()->GetRenderViewHost()),
58       panel_(panel) {
59   message_prefix_id_ = util::GetMessagePrefixID(
60       GetExtension()->is_app(),
61       true,  // is_extension
62       panel->profile()->IsOffTheRecord(),
63       false,  // is_prerender
64       false,  // is_instant_overlay
65       false);  // is_background
66 }
67
68 PanelResource::~PanelResource() {
69 }
70
71 Resource::Type PanelResource::GetType() const {
72   return EXTENSION;
73 }
74
75 string16 PanelResource::GetTitle() const {
76   string16 title = panel_->GetWindowTitle();
77   // Since the title will be concatenated with an IDS_TASK_MANAGER_* prefix
78   // we need to explicitly set the title to be LTR format if there is no
79   // strong RTL charater in it. Otherwise, if the task manager prefix is an
80   // RTL word, the concatenated result might be wrong. For example,
81   // a page whose title is "Yahoo! Mail: The best web-based Email!", without
82   // setting it explicitly as LTR format, the concatenated result will be
83   // "!Yahoo! Mail: The best web-based Email :PPA", in which the capital
84   // letters "PPA" stands for the Hebrew word for "app".
85   base::i18n::AdjustStringForLocaleDirection(&title);
86
87   return l10n_util::GetStringFUTF16(message_prefix_id_, title);
88 }
89
90 string16 PanelResource::GetProfileName() const {
91   return util::GetProfileNameFromInfoCache(panel_->profile());
92 }
93
94 gfx::ImageSkia PanelResource::GetIcon() const {
95   gfx::Image icon = panel_->GetCurrentPageIcon();
96   return icon.IsEmpty() ? gfx::ImageSkia() : *icon.ToImageSkia();
97 }
98
99 WebContents* PanelResource::GetWebContents() const {
100   return panel_->GetWebContents();
101 }
102
103 const Extension* PanelResource::GetExtension() const {
104   ExtensionService* extension_service =
105       panel_->profile()->GetExtensionService();
106   return extension_service->extensions()->GetByID(panel_->extension_id());
107 }
108
109 ////////////////////////////////////////////////////////////////////////////////
110 // PanelResourceProvider class
111 ////////////////////////////////////////////////////////////////////////////////
112
113 PanelResourceProvider::PanelResourceProvider(TaskManager* task_manager)
114     : updating_(false),
115       task_manager_(task_manager) {
116 }
117
118 PanelResourceProvider::~PanelResourceProvider() {
119 }
120
121 Resource* PanelResourceProvider::GetResource(
122     int origin_pid,
123     int render_process_host_id,
124     int routing_id) {
125   // If an origin PID was specified, the request is from a plugin, not the
126   // render view host process
127   if (origin_pid)
128     return NULL;
129
130   for (PanelResourceMap::iterator i = resources_.begin();
131        i != resources_.end(); ++i) {
132     WebContents* contents = i->first->GetWebContents();
133     if (contents &&
134         contents->GetRenderProcessHost()->GetID() == render_process_host_id &&
135         contents->GetRenderViewHost()->GetRoutingID() == routing_id) {
136       return i->second;
137     }
138   }
139
140   // Can happen if the panel went away while a network request was being
141   // performed.
142   return NULL;
143 }
144
145 void PanelResourceProvider::StartUpdating() {
146   DCHECK(!updating_);
147   updating_ = true;
148
149   // Add all the Panels.
150   std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
151   for (size_t i = 0; i < panels.size(); ++i)
152     Add(panels[i]);
153
154   // Then we register for notifications to get new and remove closed panels.
155   registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
156                  content::NotificationService::AllSources());
157   registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
158                  content::NotificationService::AllSources());
159 }
160
161 void PanelResourceProvider::StopUpdating() {
162   DCHECK(updating_);
163   updating_ = false;
164
165   // Unregister for notifications about new/removed panels.
166   registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
167                     content::NotificationService::AllSources());
168   registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
169                     content::NotificationService::AllSources());
170
171   // Delete all the resources.
172   STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end());
173   resources_.clear();
174 }
175
176 void PanelResourceProvider::Add(Panel* panel) {
177   if (!updating_)
178     return;
179
180   PanelResourceMap::const_iterator iter = resources_.find(panel);
181   if (iter != resources_.end())
182     return;
183
184   PanelResource* resource = new PanelResource(panel);
185   resources_[panel] = resource;
186   task_manager_->AddResource(resource);
187 }
188
189 void PanelResourceProvider::Remove(Panel* panel) {
190   if (!updating_)
191     return;
192
193   PanelResourceMap::iterator iter = resources_.find(panel);
194   if (iter == resources_.end())
195     return;
196
197   PanelResource* resource = iter->second;
198   task_manager_->RemoveResource(resource);
199   resources_.erase(iter);
200   delete resource;
201 }
202
203 void PanelResourceProvider::Observe(int type,
204     const content::NotificationSource& source,
205     const content::NotificationDetails& details) {
206   WebContents* web_contents = content::Source<WebContents>(source).ptr();
207   if (extensions::GetViewType(web_contents) != extensions::VIEW_TYPE_PANEL)
208     return;
209
210   switch (type) {
211     case content::NOTIFICATION_WEB_CONTENTS_CONNECTED:
212     {
213       std::vector<Panel*>panels = PanelManager::GetInstance()->panels();
214       for (size_t i = 0; i < panels.size(); ++i) {
215         if (panels[i]->GetWebContents() == web_contents) {
216           Add(panels[i]);
217           break;
218         }
219       }
220       break;
221     }
222     case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED:
223     {
224       for (PanelResourceMap::iterator iter = resources_.begin();
225            iter != resources_.end(); ++iter) {
226         Panel* panel = iter->first;
227         WebContents* panel_contents = panel->GetWebContents();
228         if (!panel_contents || panel_contents == web_contents) {
229           Remove(panel);
230           break;
231         }
232       }
233       break;
234     }
235     default:
236       NOTREACHED() << "Unexpected notificiation.";
237       break;
238   }
239 }
240
241 }  // namespace task_manager