blob: c078ba30c92dc0db4bf961270140bc98fe27904d [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/task_manager/panel_resource_provider.h"
#include "base/i18n/rtl.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/task_manager/renderer_resource.h"
#include "chrome/browser/task_manager/resource_provider.h"
#include "chrome/browser/task_manager/task_manager.h"
#include "chrome/browser/task_manager/task_manager_util.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_manager.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/view_type_utils.h"
#include "ui/base/l10n/l10n_util.h"
using content::RenderProcessHost;
using content::RenderViewHost;
using content::WebContents;
using extensions::Extension;
namespace task_manager {
class PanelResource : public RendererResource {
public:
explicit PanelResource(Panel* panel);
virtual ~PanelResource();
// Resource methods:
virtual Type GetType() const OVERRIDE;
virtual string16 GetTitle() const OVERRIDE;
virtual string16 GetProfileName() const OVERRIDE;
virtual gfx::ImageSkia GetIcon() const OVERRIDE;
virtual content::WebContents* GetWebContents() const OVERRIDE;
virtual const extensions::Extension* GetExtension() const OVERRIDE;
private:
Panel* panel_;
// Determines prefix for title reflecting whether extensions are apps
// or in incognito mode.
int message_prefix_id_;
DISALLOW_COPY_AND_ASSIGN(PanelResource);
};
PanelResource::PanelResource(Panel* panel)
: RendererResource(
panel->GetWebContents()->GetRenderProcessHost()->GetHandle(),
panel->GetWebContents()->GetRenderViewHost()),
panel_(panel) {
message_prefix_id_ = util::GetMessagePrefixID(
GetExtension()->is_app(),
true, // is_extension
panel->profile()->IsOffTheRecord(),
false, // is_prerender
false, // is_instant_overlay
false); // is_background
}
PanelResource::~PanelResource() {
}
Resource::Type PanelResource::GetType() const {
return EXTENSION;
}
string16 PanelResource::GetTitle() const {
string16 title = panel_->GetWindowTitle();
// Since the title will be concatenated with an IDS_TASK_MANAGER_* prefix
// we need to explicitly set the title to be LTR format if there is no
// strong RTL charater in it. Otherwise, if the task manager prefix is an
// RTL word, the concatenated result might be wrong. For example,
// a page whose title is "Yahoo! Mail: The best web-based Email!", without
// setting it explicitly as LTR format, the concatenated result will be
// "!Yahoo! Mail: The best web-based Email :PPA", in which the capital
// letters "PPA" stands for the Hebrew word for "app".
base::i18n::AdjustStringForLocaleDirection(&title);
return l10n_util::GetStringFUTF16(message_prefix_id_, title);
}
string16 PanelResource::GetProfileName() const {
return util::GetProfileNameFromInfoCache(panel_->profile());
}
gfx::ImageSkia PanelResource::GetIcon() const {
gfx::Image icon = panel_->GetCurrentPageIcon();
return icon.IsEmpty() ? gfx::ImageSkia() : *icon.ToImageSkia();
}
WebContents* PanelResource::GetWebContents() const {
return panel_->GetWebContents();
}
const Extension* PanelResource::GetExtension() const {
ExtensionService* extension_service =
panel_->profile()->GetExtensionService();
return extension_service->extensions()->GetByID(panel_->extension_id());
}
////////////////////////////////////////////////////////////////////////////////
// PanelResourceProvider class
////////////////////////////////////////////////////////////////////////////////
PanelResourceProvider::PanelResourceProvider(TaskManager* task_manager)
: updating_(false),
task_manager_(task_manager) {
}
PanelResourceProvider::~PanelResourceProvider() {
}
Resource* PanelResourceProvider::GetResource(
int origin_pid,
int render_process_host_id,
int routing_id) {
// If an origin PID was specified, the request is from a plugin, not the
// render view host process
if (origin_pid)
return NULL;
for (PanelResourceMap::iterator i = resources_.begin();
i != resources_.end(); ++i) {
WebContents* contents = i->first->GetWebContents();
if (contents &&
contents->GetRenderProcessHost()->GetID() == render_process_host_id &&
contents->GetRenderViewHost()->GetRoutingID() == routing_id) {
return i->second;
}
}
// Can happen if the panel went away while a network request was being
// performed.
return NULL;
}
void PanelResourceProvider::StartUpdating() {
DCHECK(!updating_);
updating_ = true;
// Add all the Panels.
std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
for (size_t i = 0; i < panels.size(); ++i)
Add(panels[i]);
// Then we register for notifications to get new and remove closed panels.
registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
content::NotificationService::AllSources());
registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
content::NotificationService::AllSources());
}
void PanelResourceProvider::StopUpdating() {
DCHECK(updating_);
updating_ = false;
// Unregister for notifications about new/removed panels.
registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
content::NotificationService::AllSources());
registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
content::NotificationService::AllSources());
// Delete all the resources.
STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end());
resources_.clear();
}
void PanelResourceProvider::Add(Panel* panel) {
if (!updating_)
return;
PanelResourceMap::const_iterator iter = resources_.find(panel);
if (iter != resources_.end())
return;
PanelResource* resource = new PanelResource(panel);
resources_[panel] = resource;
task_manager_->AddResource(resource);
}
void PanelResourceProvider::Remove(Panel* panel) {
if (!updating_)
return;
PanelResourceMap::iterator iter = resources_.find(panel);
if (iter == resources_.end())
return;
PanelResource* resource = iter->second;
task_manager_->RemoveResource(resource);
resources_.erase(iter);
delete resource;
}
void PanelResourceProvider::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
WebContents* web_contents = content::Source<WebContents>(source).ptr();
if (extensions::GetViewType(web_contents) != extensions::VIEW_TYPE_PANEL)
return;
switch (type) {
case content::NOTIFICATION_WEB_CONTENTS_CONNECTED:
{
std::vector<Panel*>panels = PanelManager::GetInstance()->panels();
for (size_t i = 0; i < panels.size(); ++i) {
if (panels[i]->GetWebContents() == web_contents) {
Add(panels[i]);
break;
}
}
break;
}
case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED:
{
for (PanelResourceMap::iterator iter = resources_.begin();
iter != resources_.end(); ++iter) {
Panel* panel = iter->first;
WebContents* panel_contents = panel->GetWebContents();
if (!panel_contents || panel_contents == web_contents) {
Remove(panel);
break;
}
}
break;
}
default:
NOTREACHED() << "Unexpected notificiation.";
break;
}
}
} // namespace task_manager