Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Unified Diff: chrome/browser/views/browser_actions_container.cc

Issue 243001: Implement Browser Actions extensions.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/views/browser_actions_container.cc
===================================================================
--- chrome/browser/views/browser_actions_container.cc (revision 0)
+++ chrome/browser/views/browser_actions_container.cc (revision 0)
@@ -0,0 +1,207 @@
+// Copyright (c) 2006-2009 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/views/browser_actions_container.h"
+
+#include "base/stl_util-inl.h"
+#include "chrome/browser/extensions/extension_browser_event_router.h"
+#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/extensions/extension_tabs_module.h"
+#include "chrome/browser/image_loading_tracker.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/views/toolbar_view.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/page_action.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "views/controls/button/image_button.h"
+
+// The size of the icon for page actions.
+static const int kIconSize = 16;
+
+// The padding between icons (pixels between each icon).
+static const int kIconHorizontalPadding = 10;
+
+////////////////////////////////////////////////////////////////////////////////
+// BrowserActionImageView
+
+// The BrowserActionImageView is a specialization of the ImageButton class.
+// It acts on a ContextualAction, in this case a BrowserAction and handles
+// loading the image for the button asynchronously on the file thread to
+class BrowserActionImageView : public views::ImageButton,
+ public views::ButtonListener,
+ public ImageLoadingTracker::Observer {
+ public:
+ BrowserActionImageView(ContextualAction* browser_action,
+ Extension* extension,
+ BrowserActionsContainer* panel);
+ ~BrowserActionImageView();
+
+ // Overridden from views::ButtonListener:
+ virtual void ButtonPressed(views::Button* sender, const views::Event& event);
+
+ // Overridden from ImageLoadingTracker.
+ virtual void OnImageLoaded(SkBitmap* image, size_t index);
+
+ private:
+ // The browser action this view represents. The ContextualAction is not owned
+ // by this class.
+ ContextualAction* browser_action_;
+
+ // The icons representing different states for the browser action.
+ std::vector<SkBitmap> browser_action_icons_;
+
+ // The object that is waiting for the image loading to complete
+ // asynchronously. This object can potentially outlive the BrowserActionView,
+ // and takes care of deleting itself.
+ ImageLoadingTracker* tracker_;
+
+ // The browser action shelf.
+ BrowserActionsContainer* panel_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserActionImageView);
+};
+
+BrowserActionImageView::BrowserActionImageView(
+ ContextualAction* browser_action, Extension* extension,
+ BrowserActionsContainer* panel)
+ : ImageButton(this),
+ browser_action_(browser_action),
+ tracker_(NULL),
+ panel_(panel) {
+ // Load the images this view needs asynchronously on the file thread. We'll
+ // get a call back into OnImageLoaded if the image loads successfully. If not,
+ // the ImageView will have no image and will not appear in the browser chrome.
+ DCHECK(!browser_action->icon_paths().empty());
+ const std::vector<std::string>& icon_paths = browser_action->icon_paths();
+ browser_action_icons_.resize(icon_paths.size());
+ tracker_ = new ImageLoadingTracker(this, icon_paths.size());
+ for (std::vector<std::string>::const_iterator iter = icon_paths.begin();
+ iter != icon_paths.end(); ++iter) {
+ FilePath path = extension->GetResourcePath(*iter);
+ tracker_->PostLoadImageTask(path);
+ }
+}
+
+BrowserActionImageView::~BrowserActionImageView() {
+ if (tracker_) {
+ tracker_->StopTrackingImageLoad();
+ tracker_ = NULL; // The tracker object will be deleted when we return.
+ }
+}
+
+void BrowserActionImageView::ButtonPressed(
+ views::Button* sender, const views::Event& event) {
+ panel_->OnBrowserActionExecuted(*browser_action_);
+}
+
+void BrowserActionImageView::OnImageLoaded(SkBitmap* image, size_t index) {
+ DCHECK(index < browser_action_icons_.size());
+ browser_action_icons_[index] = *image;
+ if (index == 0) {
+ SetImage(views::CustomButton::BS_NORMAL, image);
+ SetImage(views::CustomButton::BS_HOT, image);
+ SetImage(views::CustomButton::BS_PUSHED, image);
+ SetTooltipText(ASCIIToWide(browser_action_->name()));
+ panel_->OnBrowserActionVisibilityChanged();
+ }
+
+ if (index == browser_action_icons_.size() - 1)
+ tracker_ = NULL; // The tracker object will delete itself when we return.
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// BrowserActionsContainer
+
+BrowserActionsContainer::BrowserActionsContainer(
+ Profile* profile, ToolbarView* toolbar)
+ : profile_(profile), toolbar_(toolbar) {
+ ExtensionsService* extension_service = profile->GetExtensionsService();
+ registrar_.Add(this, NotificationType::EXTENSION_LOADED,
+ Source<ExtensionsService>(extension_service));
+ registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
+ Source<ExtensionsService>(extension_service));
+ registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED,
+ Source<ExtensionsService>(extension_service));
+
+ RefreshBrowserActionViews();
+}
+
+BrowserActionsContainer::~BrowserActionsContainer() {
+ DeleteBrowserActionViews();
+}
+
+void BrowserActionsContainer::RefreshBrowserActionViews() {
+ ExtensionsService* extension_service = profile_->GetExtensionsService();
+ if (!extension_service) // The |extension_service| can be NULL in Incognito.
+ return;
+
+ std::vector<ContextualAction*> browser_actions;
+ browser_actions = extension_service->GetBrowserActions();
+
+ if (browser_action_views_.size() != browser_actions.size()) {
+ DeleteBrowserActionViews();
+
+ for (size_t i = 0; i < browser_actions.size(); ++i) {
+ Extension* extension = extension_service->GetExtensionById(
+ browser_actions[i]->extension_id());
+ DCHECK(extension);
+
+ BrowserActionImageView* view =
+ new BrowserActionImageView(browser_actions[i], extension, this);
+ browser_action_views_.push_back(view);
+ AddChildView(view);
+ }
+ }
+}
+
+void BrowserActionsContainer::DeleteBrowserActionViews() {
+ if (!browser_action_views_.empty()) {
+ for (size_t i = 0; i < browser_action_views_.size(); ++i)
+ RemoveChildView(browser_action_views_[i]);
+ STLDeleteContainerPointers(browser_action_views_.begin(),
+ browser_action_views_.end());
+ browser_action_views_.clear();
+ }
+}
+
+void BrowserActionsContainer::OnBrowserActionVisibilityChanged() {
+ toolbar_->Layout();
+}
+
+void BrowserActionsContainer::OnBrowserActionExecuted(
+ const ContextualAction& browser_action) {
+ int window_id = ExtensionTabUtil::GetWindowId(toolbar_->browser());
+ ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
+ profile_, browser_action.extension_id(), window_id);
+}
+
+gfx::Size BrowserActionsContainer::GetPreferredSize() {
+ if (browser_action_views_.empty())
+ return gfx::Size(0, 0);
+ int width = kIconHorizontalPadding + browser_action_views_.size() *
+ (kIconSize + kIconHorizontalPadding);
+ return gfx::Size(width, kIconSize);
+}
+
+void BrowserActionsContainer::Layout() {
+ for (size_t i = 0; i < browser_action_views_.size(); ++i) {
+ views::ImageButton* view = browser_action_views_[i];
+ gfx::Size sz = view->GetPreferredSize();
+ int x = kIconHorizontalPadding + i * (kIconSize + kIconHorizontalPadding);
+ view->SetBounds(x, (height() - sz.height()) / 2, sz.width(), sz.height());
+ }
+}
+
+void BrowserActionsContainer::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type == NotificationType::EXTENSION_LOADED ||
+ type == NotificationType::EXTENSION_UNLOADED ||
+ type == NotificationType::EXTENSION_UNLOADED_DISABLED) {
+ RefreshBrowserActionViews();
+ } else {
+ NOTREACHED() << L"Received unexpected notification";
+ }
+}
Property changes on: chrome\browser\views\browser_actions_container.cc
___________________________________________________________________
Added: svn:eol-style
+ LF

Powered by Google App Engine
This is Rietveld 408576698