root/chrome/browser/extensions/api/system_indicator/system_indicator_manager.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Create
  2. OnStatusIconClicked
  3. OnIconUpdated
  4. icon_factory_
  5. status_tray_
  6. Shutdown
  7. Observe
  8. OnSystemIndicatorChanged
  9. SendClickEventToExtensionForTest
  10. CreateOrUpdateIndicator
  11. RemoveIndicator

// Copyright (c) 2012 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/extensions/api/system_indicator/system_indicator_manager.h"

#include "base/memory/linked_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/status_icons/status_icon.h"
#include "chrome/browser/status_icons/status_icon_observer.h"
#include "chrome/browser/status_icons/status_tray.h"
#include "chrome/common/extensions/api/system_indicator.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "ui/gfx/image/image.h"

namespace extensions {

namespace system_indicator = api::system_indicator;

// Observes clicks on a given status icon and forwards the event to the
// appropriate extension.  Handles icon updates, and responsible for creating
// and removing the icon from the notification area during construction and
// destruction.
class ExtensionIndicatorIcon : public StatusIconObserver,
                               public ExtensionActionIconFactory::Observer {
 public:
  static ExtensionIndicatorIcon* Create(const Extension* extension,
                                        const ExtensionAction* action,
                                        Profile* profile,
                                        StatusTray* status_tray);
  virtual ~ExtensionIndicatorIcon();

  // StatusIconObserver implementation.
  virtual void OnStatusIconClicked() OVERRIDE;

  // ExtensionActionIconFactory::Observer implementation.
  virtual void OnIconUpdated() OVERRIDE;

 private:
  ExtensionIndicatorIcon(const Extension* extension,
                         const ExtensionAction* action,
                         Profile* profile,
                         StatusTray* status_tray);

  const extensions::Extension* extension_;
  StatusTray* status_tray_;
  StatusIcon* icon_;
  Profile* profile_;
  ExtensionActionIconFactory icon_factory_;
};

ExtensionIndicatorIcon* ExtensionIndicatorIcon::Create(
    const Extension* extension,
    const ExtensionAction* action,
    Profile* profile,
    StatusTray* status_tray) {
  scoped_ptr<ExtensionIndicatorIcon> extension_icon(
      new ExtensionIndicatorIcon(extension, action, profile, status_tray));

  // Check if a status icon was successfully created.
  if (extension_icon->icon_)
    return extension_icon.release();

  // We could not create a status icon.
  return NULL;
}

ExtensionIndicatorIcon::~ExtensionIndicatorIcon() {
  if (icon_) {
    icon_->RemoveObserver(this);
    status_tray_->RemoveStatusIcon(icon_);
  }
}

void ExtensionIndicatorIcon::OnStatusIconClicked() {
  scoped_ptr<base::ListValue> params(
      api::system_indicator::OnClicked::Create());

  EventRouter* event_router =
      ExtensionSystem::Get(profile_)->event_router();
  scoped_ptr<Event> event(new Event(
      system_indicator::OnClicked::kEventName,
      params.Pass(),
      profile_));
  event_router->DispatchEventToExtension(
      extension_->id(), event.Pass());
}

void ExtensionIndicatorIcon::OnIconUpdated() {
  icon_->SetImage(
      icon_factory_.GetIcon(ExtensionAction::kDefaultTabId).AsImageSkia());
}

ExtensionIndicatorIcon::ExtensionIndicatorIcon(const Extension* extension,
                                               const ExtensionAction* action,
                                               Profile* profile,
                                               StatusTray* status_tray)
    : extension_(extension),
      status_tray_(status_tray),
      icon_(NULL),
      profile_(profile),
      icon_factory_(profile, extension, action, this) {
  // Get the icon image and tool tip for the status icon. The extension name is
  // used as the tool tip.
  gfx::ImageSkia icon_image =
      icon_factory_.GetIcon(ExtensionAction::kDefaultTabId).AsImageSkia();
  base::string16 tool_tip = base::UTF8ToUTF16(extension_->name());

  icon_ = status_tray_->CreateStatusIcon(
      StatusTray::OTHER_ICON, icon_image, tool_tip);
  if (icon_)
    icon_->AddObserver(this);
}

SystemIndicatorManager::SystemIndicatorManager(Profile* profile,
                                               StatusTray* status_tray)
    : profile_(profile), status_tray_(status_tray) {
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
                 content::Source<Profile>(profile_->GetOriginalProfile()));
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_SYSTEM_INDICATOR_UPDATED,
                 content::Source<Profile>(profile_->GetOriginalProfile()));
}

SystemIndicatorManager::~SystemIndicatorManager() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

void SystemIndicatorManager::Shutdown() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

void SystemIndicatorManager::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK(thread_checker_.CalledOnValidThread());

  switch (type) {
    case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED:
      RemoveIndicator(
          content::Details<UnloadedExtensionInfo>(details)->extension->id());
      break;
    case chrome::NOTIFICATION_EXTENSION_SYSTEM_INDICATOR_UPDATED:
      OnSystemIndicatorChanged(
          content::Details<ExtensionAction>(details).ptr());
      break;
    default:
      NOTREACHED();
      break;
  }
}

void SystemIndicatorManager::OnSystemIndicatorChanged(
    const ExtensionAction* extension_action) {
  DCHECK(thread_checker_.CalledOnValidThread());
  std::string extension_id = extension_action->extension_id();
  ExtensionService* service =
      ExtensionSystem::Get(profile_)->extension_service();

  if (extension_action->GetIsVisible(ExtensionAction::kDefaultTabId)) {
    const Extension* extension =
        service->GetExtensionById(extension_id, false);
    CreateOrUpdateIndicator(extension, extension_action);
  } else {
    RemoveIndicator(extension_id);
  }
}

bool SystemIndicatorManager::SendClickEventToExtensionForTest(
    const std::string extension_id) {

    extensions::SystemIndicatorManager::SystemIndicatorMap::iterator it =
        system_indicators_.find(extension_id);

    if (it == system_indicators_.end())
      return false;

    it->second->OnStatusIconClicked();
    return true;
}

void SystemIndicatorManager::CreateOrUpdateIndicator(
    const Extension* extension,
    const ExtensionAction* extension_action) {
  DCHECK(thread_checker_.CalledOnValidThread());
  SystemIndicatorMap::iterator it = system_indicators_.find(extension->id());
  if (it != system_indicators_.end()) {
    it->second->OnIconUpdated();
    return;
  }

  ExtensionIndicatorIcon* extension_icon = ExtensionIndicatorIcon::Create(
      extension, extension_action, profile_, status_tray_);
  if (extension_icon)
    system_indicators_[extension->id()] = make_linked_ptr(extension_icon);
}

void SystemIndicatorManager::RemoveIndicator(const std::string& extension_id) {
  DCHECK(thread_checker_.CalledOnValidThread());
  system_indicators_.erase(extension_id);
}

}  // namespace extensions

/* [<][>][^][v][top][bottom][index][help] */