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 "content/public/browser/notification_service.h" 18 #include "content/public/browser/render_process_host.h" 19 #include "content/public/browser/render_view_host.h" 20 #include "content/public/browser/web_contents.h" 21 #include "extensions/browser/view_type_utils.h" 22 #include "extensions/common/extension.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 base::string16 GetTitle() const OVERRIDE; 40 virtual base::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 base::string16 PanelResource::GetTitle() const { 76 base::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 base::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 242