summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-15 21:13:47 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-15 21:13:47 +0000
commitb671760bb1967f74d584c7790af86a5aee6fd43c (patch)
tree293ed23ee335c9300dbf72b679cbaf083b41bb4f /chrome/browser
parentf9a2b2fe071c001a6864e527fd7035489a985243 (diff)
downloadchromium_src-b671760bb1967f74d584c7790af86a5aee6fd43c.zip
chromium_src-b671760bb1967f74d584c7790af86a5aee6fd43c.tar.gz
chromium_src-b671760bb1967f74d584c7790af86a5aee6fd43c.tar.bz2
Use the extension icon for extension omnibox results instead of the generic
search icon. I refactored the extension menu manager to separate the icon-specific bits. BUG=46479 TEST=load the chrome search extension at src/chrome/common/extensions/docs/examples/extensions/chrome_search/ and type "src foo" into the omnibox. You should see the extension icon instead of the magnifying glass. Switch back and forth between the "src" keyword result, other results, and other keywords and the icons should update properly. Review URL: http://codereview.chromium.org/2973006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52535 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_model.cc10
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_model.h5
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc52
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_gtk.h9
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_mac.h6
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_mac.mm17
-rw-r--r--chrome/browser/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm4
-rw-r--r--chrome/browser/cocoa/location_bar/autocomplete_text_field_unittest.mm3
-rw-r--r--chrome/browser/cocoa/location_bar/location_bar_view_mac.h2
-rw-r--r--chrome/browser/cocoa/location_bar/location_bar_view_mac.mm14
-rw-r--r--chrome/browser/cocoa/location_bar/selected_keyword_decoration.h2
-rw-r--r--chrome/browser/cocoa/location_bar/selected_keyword_decoration.mm10
-rwxr-xr-xchrome/browser/extensions/extension_icon_manager.cc96
-rwxr-xr-xchrome/browser/extensions/extension_icon_manager.h66
-rw-r--r--chrome/browser/extensions/extension_menu_manager.cc84
-rw-r--r--chrome/browser/extensions/extension_menu_manager.h34
-rw-r--r--chrome/browser/extensions/extensions_service.cc13
-rw-r--r--chrome/browser/extensions/extensions_service.h8
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.cc22
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.h4
-rw-r--r--chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc15
-rw-r--r--chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h5
-rw-r--r--chrome/browser/views/location_bar/icon_label_bubble_view.cc4
-rw-r--r--chrome/browser/views/location_bar/icon_label_bubble_view.h3
-rw-r--r--chrome/browser/views/location_bar/location_bar_view.cc15
25 files changed, 368 insertions, 135 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_popup_model.cc b/chrome/browser/autocomplete/autocomplete_popup_model.cc
index 009cc0b..f4f7a82 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_model.cc
+++ b/chrome/browser/autocomplete/autocomplete_popup_model.cc
@@ -8,6 +8,7 @@
#include "chrome/browser/autocomplete/autocomplete_edit.h"
#include "chrome/browser/autocomplete/autocomplete_popup_view.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/common/notification_service.h"
@@ -279,3 +280,12 @@ void AutocompletePopupModel::Observe(NotificationType type,
view_->UpdatePopupAppearance();
}
+
+const SkBitmap* AutocompletePopupModel::GetSpecialIconForMatch(
+ const AutocompleteMatch& match) const {
+ if (!match.template_url || !match.template_url->IsExtensionKeyword())
+ return NULL;
+
+ return &profile_->GetExtensionsService()->GetOmniboxIcon(
+ match.template_url->GetExtensionId());
+}
diff --git a/chrome/browser/autocomplete/autocomplete_popup_model.h b/chrome/browser/autocomplete/autocomplete_popup_model.h
index a986419..8686bde 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_model.h
+++ b/chrome/browser/autocomplete/autocomplete_popup_model.h
@@ -12,6 +12,7 @@
class AutocompleteEditModel;
class AutocompleteEditView;
class Profile;
+class SkBitmap;
class AutocompletePopupView;
@@ -110,6 +111,10 @@ class AutocompletePopupModel : public NotificationObserver {
// can be removed from history, and if so, remove it and update the popup.
void TryDeletingCurrentItem();
+ // Returns the special icon to use for a given match, or NULL if we should
+ // use a standard style icon.
+ const SkBitmap* GetSpecialIconForMatch(const AutocompleteMatch& match) const;
+
// The token value for selected_line_, hover_line_ and functions dealing with
// a "line number" that indicates "no line".
static const size_t kNoMatch = -1;
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc
index a6605ba..8a6c24b 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc
@@ -13,6 +13,7 @@
#include "base/basictypes.h"
#include "base/i18n/rtl.h"
#include "base/logging.h"
+#include "base/stl_util-inl.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/autocomplete/autocomplete.h"
#include "chrome/browser/autocomplete/autocomplete_edit.h"
@@ -196,26 +197,6 @@ void SetupLayoutForMatch(PangoLayout* layout,
pango_attr_list_unref(attrs);
}
-GdkPixbuf* IconForMatch(BrowserThemeProvider* theme,
- const AutocompleteMatch& match,
- bool selected) {
- int icon = match.starred ?
- IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match.type);
- if (selected) {
- switch (icon) {
- case IDR_OMNIBOX_HTTP: icon = IDR_OMNIBOX_HTTP_DARK; break;
- case IDR_OMNIBOX_HISTORY: icon = IDR_OMNIBOX_HISTORY_DARK; break;
- case IDR_OMNIBOX_SEARCH: icon = IDR_OMNIBOX_SEARCH_DARK; break;
- case IDR_OMNIBOX_MORE: icon = IDR_OMNIBOX_MORE_DARK; break;
- case IDR_OMNIBOX_STAR: icon = IDR_OMNIBOX_STAR_DARK; break;
- default: NOTREACHED(); break;
- }
- }
-
- // TODO(estade): Do we want to flip these for RTL? (Windows doesn't).
- return theme->GetPixbufNamed(icon);
-}
-
// Generates the normal URL color, a green color used in unhighlighted URL
// text. It is a mix of |kURLTextColor| and the current text color. Unlike the
// selected text color, It is more important to match the qualities of the
@@ -352,6 +333,9 @@ AutocompletePopupViewGtk::~AutocompletePopupViewGtk() {
model_.reset();
g_object_unref(layout_);
gtk_widget_destroy(window_);
+
+ for (PixbufMap::iterator it = pixbufs_.begin(); it != pixbufs_.end(); ++it)
+ g_object_unref(it->second);
}
void AutocompletePopupViewGtk::InvalidateLine(size_t line) {
@@ -498,6 +482,32 @@ void AutocompletePopupViewGtk::AcceptLine(size_t line,
is_keyword_hint ? std::wstring() : keyword);
}
+GdkPixbuf* AutocompletePopupViewGtk::IconForMatch(
+ const AutocompleteMatch& match, bool selected) {
+ const SkBitmap* bitmap = model_->GetSpecialIconForMatch(match);
+ if (bitmap) {
+ if (!ContainsKey(pixbufs_, bitmap))
+ pixbufs_[bitmap] = gfx::GdkPixbufFromSkBitmap(bitmap);
+ return pixbufs_[bitmap];
+ }
+
+ int icon = match.starred ?
+ IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match.type);
+ if (selected) {
+ switch (icon) {
+ case IDR_OMNIBOX_HTTP: icon = IDR_OMNIBOX_HTTP_DARK; break;
+ case IDR_OMNIBOX_HISTORY: icon = IDR_OMNIBOX_HISTORY_DARK; break;
+ case IDR_OMNIBOX_SEARCH: icon = IDR_OMNIBOX_SEARCH_DARK; break;
+ case IDR_OMNIBOX_MORE: icon = IDR_OMNIBOX_MORE_DARK; break;
+ case IDR_OMNIBOX_STAR: icon = IDR_OMNIBOX_STAR_DARK; break;
+ default: NOTREACHED(); break;
+ }
+ }
+
+ // TODO(estade): Do we want to flip these for RTL? (Windows doesn't).
+ return theme_provider_->GetPixbufNamed(icon);
+}
+
gboolean AutocompletePopupViewGtk::HandleMotion(GtkWidget* widget,
GdkEventMotion* event) {
// TODO(deanm): Windows has a bunch of complicated logic here.
@@ -610,7 +620,7 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget,
(line_rect.width() - kIconLeftPadding - kIconWidth + gtk_offset);
// Draw the icon for this result.
DrawFullPixbuf(drawable, gc,
- IconForMatch(theme_provider_, match, is_selected),
+ IconForMatch(match, is_selected),
icon_start_x, line_rect.y() + kIconTopPadding);
// Draw the results text vertically centered in the results space.
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h
index 4759417..2942489 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_GTK_H_
#include <gtk/gtk.h>
+#include <map>
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
@@ -16,6 +17,7 @@
class AutocompleteEditModel;
class AutocompleteEditView;
+class AutocompleteMatch;
class AutocompletePopupModel;
class GtkThemeProvider;
class Profile;
@@ -56,6 +58,8 @@ class AutocompletePopupViewGtk : public AutocompletePopupView,
// Accept a line of the results, for example, when the user clicks a line.
void AcceptLine(size_t line, WindowOpenDisposition disposition);
+ GdkPixbuf* IconForMatch(const AutocompleteMatch& match, bool selected);
+
static gboolean HandleExposeThunk(GtkWidget* widget, GdkEventExpose* event,
gpointer userdata) {
return reinterpret_cast<AutocompletePopupViewGtk*>(userdata)->
@@ -99,6 +103,11 @@ class AutocompletePopupViewGtk : public AutocompletePopupView,
GtkThemeProvider* theme_provider_;
NotificationRegistrar registrar_;
+ // Used to cache GdkPixbufs and map them from the SkBitmaps they were created
+ // from.
+ typedef std::map<const SkBitmap*, GdkPixbuf*> PixbufMap;
+ PixbufMap pixbufs_;
+
// A list of colors which we should use for drawing the popup. These change
// between gtk and normal mode.
GdkColor border_color_;
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.h b/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
index d19576f..7d1ec26 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
@@ -8,6 +8,7 @@
#import <Cocoa/Cocoa.h>
#include <string>
+#include <map>
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
@@ -20,7 +21,9 @@
class AutocompletePopupModel;
class AutocompleteEditModel;
class AutocompleteEditViewMac;
+@class NSImage;
class Profile;
+class SkBitmap;
// Implements AutocompletePopupView using a raw NSWindow containing an
// NSTableView.
@@ -114,6 +117,9 @@ class AutocompletePopupViewMac : public AutocompletePopupView {
// change.
void PositionPopup(const CGFloat matrixHeight);
+ // Returns the NSImage that should be used as an icon for the given match.
+ NSImage* ImageForMatch(const AutocompleteMatch& match);
+
scoped_ptr<AutocompletePopupModel> model_;
AutocompleteEditViewMac* edit_view_;
NSTextField* field_; // owned by tab controller
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
index 8319f00..16105ad 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
@@ -6,6 +6,7 @@
#include "app/resource_bundle.h"
#include "app/text_elider.h"
+#include "base/stl_util-inl.h"
#include "base/sys_string_conversions.h"
#include "chrome/browser/autocomplete/autocomplete_edit.h"
#include "chrome/browser/autocomplete/autocomplete_edit_view_mac.h"
@@ -14,6 +15,7 @@
#include "chrome/browser/cocoa/image_utils.h"
#include "gfx/rect.h"
#include "grit/theme_resources.h"
+#include "skia/ext/skia_utils_mac.h"
#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
namespace {
@@ -356,6 +358,17 @@ void AutocompletePopupViewMac::PositionPopup(const CGFloat matrixHeight) {
[[field_ window] addChildWindow:popup_ ordered:NSWindowAbove];
}
+NSImage* AutocompletePopupViewMac::ImageForMatch(
+ const AutocompleteMatch& match) {
+ const SkBitmap* bitmap = model_->GetSpecialIconForMatch(match);
+ if (bitmap)
+ return gfx::SkBitmapToNSImage(*bitmap);
+
+ const int resource_id = match.starred ?
+ IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match.type);
+ return AutocompleteEditViewMac::ImageForResource(resource_id);
+}
+
void AutocompletePopupViewMac::UpdatePopupAppearance() {
DCHECK([NSThread isMainThread]);
const AutocompleteResult& result = model_->result();
@@ -400,9 +413,7 @@ void AutocompletePopupViewMac::UpdatePopupAppearance() {
for (size_t ii = 0; ii < rows; ++ii) {
AutocompleteButtonCell* cell = [matrix cellAtRow:ii column:0];
const AutocompleteMatch& match = model_->result().match_at(ii);
- const int resource_id = match.starred ? IDR_OMNIBOX_STAR
- : AutocompleteMatch::TypeToIcon(match.type);
- [cell setImage:AutocompleteEditViewMac::ImageForResource(resource_id)];
+ [cell setImage:ImageForMatch(match)];
[cell setAttributedTitle:MatchText(match, resultFont, matrixWidth)];
}
diff --git a/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm b/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm
index f22de95..69c3f47 100644
--- a/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm
+++ b/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm
@@ -230,6 +230,7 @@ TEST_F(AutocompleteTextFieldCellTest, TextFrame) {
EXPECT_LT(NSMaxX(textFrame), searchHintMaxX);
EXPECT_TRUE(NSContainsRect(cursorFrame, textFrame));
+
// Text frame should take everything over again on reset.
[cell clearHint];
textFrame = [cell textFrameForFrame:bounds];
@@ -288,6 +289,7 @@ TEST_F(AutocompleteTextFieldCellTest, DrawingRectForBounds) {
EXPECT_TRUE(NSContainsRect(NSInsetRect(textFrame, 1, 1), drawingRect));
[cell clearHint];
+
textFrame = [cell textFrameForFrame:bounds];
drawingRect = [cell drawingRectForBounds:bounds];
EXPECT_FALSE(NSIsEmptyRect(drawingRect));
@@ -414,6 +416,8 @@ TEST_F(AutocompleteTextFieldCellTest, PageActionImageFrame) {
EXPECT_LE(NSMaxX(labelRect), NSMinX(iconRect0));
}
+ NSImage* image = [NSImage imageNamed:@"NSApplicationIcon"];
+
// Test that the cell drops the search hint if there is no room for
// it.
TEST_F(AutocompleteTextFieldCellTest, OmitsSearchHintIfNarrow) {
diff --git a/chrome/browser/cocoa/location_bar/autocomplete_text_field_unittest.mm b/chrome/browser/cocoa/location_bar/autocomplete_text_field_unittest.mm
index 44e223b..162ccf9 100644
--- a/chrome/browser/cocoa/location_bar/autocomplete_text_field_unittest.mm
+++ b/chrome/browser/cocoa/location_bar/autocomplete_text_field_unittest.mm
@@ -266,6 +266,7 @@ TEST_F(AutocompleteTextFieldTest, Display) {
[field_ display];
[cell clearHint];
+
[field_ display];
}
@@ -382,6 +383,7 @@ TEST_F(AutocompleteTextFieldTest, ResetFieldEditorKeywordHint) {
// Capture the editor frame resulting from the standard focus
// machinery.
+
[test_window() makePretendKeyWindowAndSetFirstResponder:field_];
const NSRect baseEditorFrame(EditorFrame());
@@ -398,6 +400,7 @@ TEST_F(AutocompleteTextFieldTest, ResetFieldEditorKeywordHint) {
mock_left_decoration_.SetVisible(true);
EXPECT_FALSE(NSIsEmptyRect([cell frameForDecoration:&mock_left_decoration_
inFrame:[field_ bounds]]));
+
[field_ resetFieldEditorFrameIfNeeded];
EXPECT_TRUE(NSEqualRects(baseEditorFrame, EditorFrame()));
}
diff --git a/chrome/browser/cocoa/location_bar/location_bar_view_mac.h b/chrome/browser/cocoa/location_bar/location_bar_view_mac.h
index 8dd1a2e..24e7344 100644
--- a/chrome/browser/cocoa/location_bar/location_bar_view_mac.h
+++ b/chrome/browser/cocoa/location_bar/location_bar_view_mac.h
@@ -130,8 +130,10 @@ class LocationBarViewMac : public AutocompleteEditController,
virtual std::wstring GetTitle() const;
NSImage* GetTabButtonImage();
+ NSImage* GetKeywordImage(const std::wstring& keyword);
AutocompleteTextField* GetAutocompleteTextField() { return field_; }
+
// Overridden from NotificationObserver.
virtual void Observe(NotificationType type,
const NotificationSource& source,
diff --git a/chrome/browser/cocoa/location_bar/location_bar_view_mac.mm b/chrome/browser/cocoa/location_bar/location_bar_view_mac.mm
index ebd1e60..4fb40d6 100644
--- a/chrome/browser/cocoa/location_bar/location_bar_view_mac.mm
+++ b/chrome/browser/cocoa/location_bar/location_bar_view_mac.mm
@@ -391,6 +391,18 @@ NSImage* LocationBarViewMac::GetTabButtonImage() {
return tab_button_image_;
}
+NSImage* LocationBarViewMac::GetKeywordImage(const std::wstring& keyword) {
+ const TemplateURL* template_url =
+ profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword);
+ if (template_url && template_url->IsExtensionKeyword()) {
+ const SkBitmap& bitmap = profile_->GetExtensionsService()->
+ GetOmniboxIcon(template_url->GetExtensionId());
+ return gfx::SkBitmapToNSImage(bitmap);
+ }
+
+ return AutocompleteEditViewMac::ImageForResource(IDR_OMNIBOX_SEARCH);
+}
+
void LocationBarViewMac::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
@@ -851,8 +863,8 @@ void LocationBarViewMac::Layout() {
// Switch from location icon to keyword mode.
location_icon_decoration_->SetVisible(false);
selected_keyword_decoration_->SetVisible(true);
-
selected_keyword_decoration_->SetKeyword(short_name, is_extension_keyword);
+ selected_keyword_decoration_->SetImage(GetKeywordImage(keyword));
// TODO(shess): This goes away once the hints are decorations.
[cell clearHint];
diff --git a/chrome/browser/cocoa/location_bar/selected_keyword_decoration.h b/chrome/browser/cocoa/location_bar/selected_keyword_decoration.h
index 8df3ed7..683a8ed 100644
--- a/chrome/browser/cocoa/location_bar/selected_keyword_decoration.h
+++ b/chrome/browser/cocoa/location_bar/selected_keyword_decoration.h
@@ -24,6 +24,8 @@ class SelectedKeywordDecoration : public BubbleDecoration {
// return the resulting width.
virtual CGFloat GetWidthForSpace(CGFloat width);
+ void SetImage(NSImage* image);
+
private:
friend class SelectedKeywordDecorationTest;
FRIEND_TEST_ALL_PREFIXES(SelectedKeywordDecorationTest,
diff --git a/chrome/browser/cocoa/location_bar/selected_keyword_decoration.mm b/chrome/browser/cocoa/location_bar/selected_keyword_decoration.mm
index ebb62bf..3c593ac 100644
--- a/chrome/browser/cocoa/location_bar/selected_keyword_decoration.mm
+++ b/chrome/browser/cocoa/location_bar/selected_keyword_decoration.mm
@@ -30,12 +30,12 @@ CGFloat SelectedKeywordDecoration::GetWidthForSpace(CGFloat width) {
const CGFloat full_width =
GetWidthForImageAndLabel(search_image_, full_string_);
if (full_width <= width) {
- SetImage(search_image_);
+ BubbleDecoration::SetImage(search_image_);
SetLabel(full_string_);
return full_width;
}
- SetImage(nil);
+ BubbleDecoration::SetImage(nil);
const CGFloat no_image_width = GetWidthForImageAndLabel(nil, full_string_);
if (no_image_width <= width || !partial_string_) {
SetLabel(full_string_);
@@ -65,3 +65,9 @@ void SelectedKeywordDecoration::SetKeyword(const std::wstring& short_name,
[l10n_util::GetNSStringF(message_id, WideToUTF16(min_name)) copy]);
}
}
+
+void SelectedKeywordDecoration::SetImage(NSImage* image) {
+ if (image != search_image_)
+ search_image_.reset([image retain]);
+ BubbleDecoration::SetImage(image);
+}
diff --git a/chrome/browser/extensions/extension_icon_manager.cc b/chrome/browser/extensions/extension_icon_manager.cc
new file mode 100755
index 0000000..1e3befc
--- /dev/null
+++ b/chrome/browser/extensions/extension_icon_manager.cc
@@ -0,0 +1,96 @@
+// Copyright (c) 2010 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/extension_icon_manager.h"
+
+#include "app/resource_bundle.h"
+#include "base/logging.h"
+#include "base/stl_util-inl.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_resource.h"
+#include "gfx/color_utils.h"
+#include "gfx/favicon_size.h"
+#include "gfx/skbitmap_operations.h"
+#include "gfx/size.h"
+#include "grit/theme_resources.h"
+#include "skia/ext/image_operations.h"
+
+ExtensionIconManager::ExtensionIconManager()
+ : ALLOW_THIS_IN_INITIALIZER_LIST(image_tracker_(this)),
+ monochrome_(false) {
+}
+
+void ExtensionIconManager::LoadIcon(Extension* extension) {
+ ExtensionResource icon_resource;
+ extension->GetIconPathAllowLargerSize(&icon_resource,
+ Extension::EXTENSION_ICON_BITTY);
+ if (!icon_resource.extension_root().empty()) {
+ image_tracker_.LoadImage(extension,
+ icon_resource,
+ gfx::Size(kFavIconSize, kFavIconSize),
+ ImageLoadingTracker::CACHE);
+ pending_icons_.insert(extension->id());
+ }
+}
+
+const SkBitmap& ExtensionIconManager::GetIcon(const std::string& extension_id) {
+ const SkBitmap* result = NULL;
+ if (ContainsKey(icons_, extension_id)) {
+ result = &icons_[extension_id];
+ } else {
+ EnsureDefaultIcon();
+ result = &default_icon_;
+ }
+ DCHECK(result);
+ DCHECK(result->width() == kFavIconSize);
+ DCHECK(result->height() == kFavIconSize);
+ return *result;
+}
+
+void ExtensionIconManager::RemoveIcon(const std::string& extension_id) {
+ icons_.erase(extension_id);
+ pending_icons_.erase(extension_id);
+}
+
+void ExtensionIconManager::OnImageLoaded(SkBitmap* image,
+ ExtensionResource resource,
+ int index) {
+ if (!image)
+ return;
+
+ const std::string extension_id = resource.extension_id();
+
+ // We may have removed the icon while waiting for it to load. In that case,
+ // do nothing.
+ if (!ContainsKey(pending_icons_, extension_id))
+ return;
+
+ pending_icons_.erase(extension_id);
+ icons_[extension_id] = ApplyTransforms(*image);
+}
+
+void ExtensionIconManager::EnsureDefaultIcon() {
+ if (default_icon_.empty()) {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ SkBitmap* src = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION);
+ default_icon_ = ApplyTransforms(*src);
+ }
+}
+
+SkBitmap ExtensionIconManager::ApplyTransforms(const SkBitmap& source) {
+ SkBitmap result = source;
+
+ if (result.width() != kFavIconSize || result.height() != kFavIconSize) {
+ result = skia::ImageOperations::Resize(
+ result, skia::ImageOperations::RESIZE_LANCZOS3,
+ kFavIconSize, kFavIconSize);
+ }
+
+ if (monochrome_) {
+ color_utils::HSL shift = {-1, 0, 0.6};
+ result = SkBitmapOperations::CreateHSLShiftedBitmap(result, shift);
+ }
+
+ return result;
+}
diff --git a/chrome/browser/extensions/extension_icon_manager.h b/chrome/browser/extensions/extension_icon_manager.h
new file mode 100755
index 0000000..abf7192
--- /dev/null
+++ b/chrome/browser/extensions/extension_icon_manager.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_ICON_MANAGER_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_ICON_MANAGER_H_
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "base/basictypes.h"
+#include "chrome/browser/extensions/image_loading_tracker.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+class Extension;
+
+class ExtensionIconManager : public ImageLoadingTracker::Observer {
+ public:
+ ExtensionIconManager();
+
+ // Start loading the icon for the given extension.
+ void LoadIcon(Extension* extension);
+
+ // This returns a bitmap of width/height kFavIconSize, loaded either from an
+ // entry specified in the extension's 'icon' section of the manifest, or a
+ // default extension icon.
+ const SkBitmap& GetIcon(const std::string& extension_id);
+
+ // Removes the extension's icon from memory.
+ void RemoveIcon(const std::string& extension_id);
+
+ // Implements the ImageLoadingTracker::Observer interface.
+ virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource,
+ int index);
+
+ void set_monochrome(bool value) { monochrome_ = value; }
+
+ private:
+ // Makes sure we've done one-time initialization of the default extension icon
+ // default_icon_.
+ void EnsureDefaultIcon();
+
+ // Helper function to return a copy of |src| with the proper scaling and
+ // coloring.
+ SkBitmap ApplyTransforms(const SkBitmap& src);
+
+ // Used for loading extension icons.
+ ImageLoadingTracker image_tracker_;
+
+ // Maps extension id to an SkBitmap with the icon for that extension.
+ std::map<std::string, SkBitmap> icons_;
+
+ // Set of extension IDs waiting for icons to load.
+ std::set<std::string> pending_icons_;
+
+ // The default icon we'll use if an extension doesn't have one.
+ SkBitmap default_icon_;
+
+ // If true, we will desaturate the icons to make them monochromatic.
+ bool monochrome_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionIconManager);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_ICON_MANAGER_H_
diff --git a/chrome/browser/extensions/extension_menu_manager.cc b/chrome/browser/extensions/extension_menu_manager.cc
index 1bc55c7..8cce43c 100644
--- a/chrome/browser/extensions/extension_menu_manager.cc
+++ b/chrome/browser/extensions/extension_menu_manager.cc
@@ -6,23 +6,17 @@
#include <algorithm>
-#include "app/resource_bundle.h"
#include "base/logging.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/json/json_writer.h"
-#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/extensions/extension_message_service.h"
#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/browser/profile.h"
#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_resource.h"
#include "gfx/favicon_size.h"
-#include "gfx/size.h"
-#include "grit/theme_resources.h"
-#include "skia/ext/image_operations.h"
#include "webkit/glue/context_menu.h"
ExtensionMenuItem::ExtensionMenuItem(const Id& id,
@@ -35,7 +29,8 @@ ExtensionMenuItem::ExtensionMenuItem(const Id& id,
type_(type),
checked_(checked),
contexts_(contexts),
- parent_id_(0) {}
+ parent_id_(0) {
+}
ExtensionMenuItem::~ExtensionMenuItem() {
STLDeleteElements(&children_);
@@ -101,8 +96,7 @@ void ExtensionMenuItem::AddChild(ExtensionMenuItem* item) {
children_.push_back(item);
}
-ExtensionMenuManager::ExtensionMenuManager()
- : ALLOW_THIS_IN_INITIALIZER_LIST(image_tracker_(this)) {
+ExtensionMenuManager::ExtensionMenuManager() {
registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
NotificationService::AllSources());
}
@@ -150,17 +144,8 @@ bool ExtensionMenuManager::AddContextItem(Extension* extension,
RadioItemSelected(item);
// If this is the first item for this extension, start loading its icon.
- if (first_item) {
- ExtensionResource icon_resource;
- extension->GetIconPathAllowLargerSize(&icon_resource,
- Extension::EXTENSION_ICON_BITTY);
- if (!icon_resource.extension_root().empty()) {
- image_tracker_.LoadImage(extension,
- icon_resource,
- gfx::Size(kFavIconSize, kFavIconSize),
- ImageLoadingTracker::CACHE);
- }
- }
+ if (first_item)
+ icon_manager_.LoadIcon(extension);
return true;
}
@@ -275,8 +260,8 @@ bool ExtensionMenuManager::RemoveContextMenuItem(
}
DCHECK(result); // The check at the very top should have prevented this.
- if (list.empty() && ContainsKey(extension_icons_, extension_id))
- extension_icons_.erase(extension_id);
+ if (list.empty())
+ icon_manager_.RemoveIcon(extension_id);
return result;
}
@@ -297,9 +282,7 @@ void ExtensionMenuManager::RemoveAllContextItems(std::string extension_id) {
}
STLDeleteElements(&context_items_[extension_id]);
context_items_.erase(extension_id);
-
- if (ContainsKey(extension_icons_, extension_id))
- extension_icons_.erase(extension_id);
+ icon_manager_.RemoveIcon(extension_id);
}
ExtensionMenuItem* ExtensionMenuManager::GetItemById(
@@ -461,54 +444,5 @@ void ExtensionMenuManager::Observe(NotificationType type,
const SkBitmap& ExtensionMenuManager::GetIconForExtension(
const std::string& extension_id) {
- const SkBitmap* result = NULL;
- if (ContainsKey(extension_icons_, extension_id)) {
- result = &(extension_icons_[extension_id]);
- } else {
- EnsureDefaultIcon();
- result = &default_icon_;
- }
- DCHECK(result);
- DCHECK(result->width() == kFavIconSize);
- DCHECK(result->height() == kFavIconSize);
- return *result;
-}
-
-void ExtensionMenuManager::OnImageLoaded(SkBitmap* image,
- ExtensionResource resource,
- int index) {
- if (!image)
- return;
-
- const std::string extension_id = resource.extension_id();
-
- // Make sure we still have menu items for this extension (since image loading
- // is asynchronous, there's a slight chance they may have all been removed
- // while the icon was loading).
- if (!ContainsKey(context_items_, extension_id))
- return;
-
- if (image->width() == kFavIconSize && image->height() == kFavIconSize)
- extension_icons_[extension_id] = *image;
- else
- extension_icons_[extension_id] = ScaleToFavIconSize(*image);
-}
-
-void ExtensionMenuManager::EnsureDefaultIcon() {
- if (default_icon_.empty()) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- SkBitmap* src = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION);
- if (src->width() == kFavIconSize && src->height() == kFavIconSize) {
- default_icon_ = *src;
- } else {
- default_icon_ = SkBitmap(ScaleToFavIconSize(*src));
- }
- }
-}
-
-SkBitmap ExtensionMenuManager::ScaleToFavIconSize(const SkBitmap& source) {
- return skia::ImageOperations::Resize(source,
- skia::ImageOperations::RESIZE_LANCZOS3,
- kFavIconSize,
- kFavIconSize);
+ return icon_manager_.GetIcon(extension_id);
}
diff --git a/chrome/browser/extensions/extension_menu_manager.h b/chrome/browser/extensions/extension_menu_manager.h
index 9e407d0..882c972 100644
--- a/chrome/browser/extensions/extension_menu_manager.h
+++ b/chrome/browser/extensions/extension_menu_manager.h
@@ -13,16 +13,16 @@
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "base/string16.h"
-#include "chrome/browser/extensions/image_loading_tracker.h"
+#include "chrome/browser/extensions/extension_icon_manager.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
-#include "third_party/skia/include/core/SkBitmap.h"
struct ContextMenuParams;
class Extension;
class ExtensionMessageService;
class Profile;
+class SkBitmap;
class TabContents;
// Represents a menu item added by an extension.
@@ -156,9 +156,7 @@ class ExtensionMenuItem {
};
// This class keeps track of menu items added by extensions.
-class ExtensionMenuManager
- : public ImageLoadingTracker::Observer,
- public NotificationObserver {
+class ExtensionMenuManager : public NotificationObserver {
public:
ExtensionMenuManager();
virtual ~ExtensionMenuManager();
@@ -207,18 +205,14 @@ class ExtensionMenuManager
const ContextMenuParams& params,
const ExtensionMenuItem::Id& menuItemId);
- // Implements the NotificationObserver interface.
- virtual void Observe(NotificationType type, const NotificationSource& source,
- const NotificationDetails& details);
-
// This returns a bitmap of width/height kFavIconSize, loaded either from an
// entry specified in the extension's 'icon' section of the manifest, or a
// default extension icon.
const SkBitmap& GetIconForExtension(const std::string& extension_id);
- // Implements the ImageLoadingTracker::Observer interface.
- virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource,
- int index);
+ // Implements the NotificationObserver interface.
+ virtual void Observe(NotificationType type, const NotificationSource& source,
+ const NotificationDetails& details);
private:
// This is a helper function which takes care of de-selecting any other radio
@@ -229,13 +223,6 @@ class ExtensionMenuManager
bool DescendantOf(ExtensionMenuItem* item,
const ExtensionMenuItem::Id& ancestor_id);
- // Makes sure we've done one-time initialization of the default extension icon
- // default_icon_.
- void EnsureDefaultIcon();
-
- // Helper function to return a copy of |src| scaled to kFavIconSize.
- SkBitmap ScaleToFavIconSize(const SkBitmap& src);
-
// We keep items organized by mapping an extension id to a list of items.
typedef std::map<std::string, ExtensionMenuItem::List> MenuItemMap;
MenuItemMap context_items_;
@@ -247,14 +234,7 @@ class ExtensionMenuManager
NotificationRegistrar registrar_;
- // Used for loading extension icons.
- ImageLoadingTracker image_tracker_;
-
- // Maps extension id to an SkBitmap with the icon for that extension.
- std::map<std::string, SkBitmap> extension_icons_;
-
- // The default icon we'll use if an extension doesn't have one.
- SkBitmap default_icon_;
+ ExtensionIconManager icon_manager_;
DISALLOW_COPY_AND_ASSIGN(ExtensionMenuManager);
};
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 9a91533..3259c11 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -186,6 +186,9 @@ ExtensionsService::ExtensionsService(Profile* profile,
}
backend_ = new ExtensionsServiceBackend(install_directory_);
+
+ // Use monochrome icons for omnibox icons.
+ omnibox_icon_manager_.set_monochrome(true);
}
ExtensionsService::~ExtensionsService() {
@@ -906,6 +909,11 @@ void ExtensionsService::OnExtensionLoaded(Extension* extension,
if (profile_->GetTemplateURLModel())
profile_->GetTemplateURLModel()->RegisterExtensionKeyword(extension);
+
+ // Load the icon for omnibox-enabled extensions so it will be ready to display
+ // in the URL bar.
+ if (!extension->omnibox_keyword().empty())
+ omnibox_icon_manager_.LoadIcon(extension);
}
void ExtensionsService::UpdateActiveExtensionsInCrashReporter() {
@@ -1029,6 +1037,11 @@ Extension* ExtensionsService::GetExtensionByOverlappingWebExtent(
return NULL;
}
+const SkBitmap& ExtensionsService::GetOmniboxIcon(
+ const std::string& extension_id) {
+ return omnibox_icon_manager_.GetIcon(extension_id);
+}
+
void ExtensionsService::ClearProvidersForTesting() {
ChromeThread::PostTask(
ChromeThread::FILE, FROM_HERE,
diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h
index 5385da5..fa4e260 100644
--- a/chrome/browser/extensions/extensions_service.h
+++ b/chrome/browser/extensions/extensions_service.h
@@ -20,6 +20,7 @@
#include "base/tuple.h"
#include "base/values.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/extensions/extension_icon_manager.h"
#include "chrome/browser/extensions/extension_menu_manager.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_process_manager.h"
@@ -275,6 +276,9 @@ class ExtensionsService
// extent, if one exists.
Extension* GetExtensionByOverlappingWebExtent(const ExtensionExtent& extent);
+ // Returns the icon to display in the omnibox for the given extension.
+ const SkBitmap& GetOmniboxIcon(const std::string& extension_id);
+
// Clear all ExternalExtensionProviders.
void ClearProvidersForTesting();
@@ -333,7 +337,6 @@ class ExtensionsService
ExtensionsQuotaService* quota_service() { return &quota_service_; }
- // Access to menu items added by extensions.
ExtensionMenuManager* menu_manager() { return &menu_manager_; }
// Notify the frontend that there was an error loading an extension.
@@ -436,6 +439,9 @@ class ExtensionsService
// Keeps track of menu items added by extensions.
ExtensionMenuManager menu_manager_;
+ // Keeps track of favicon-sized omnibox icons for extensions.
+ ExtensionIconManager omnibox_icon_manager_;
+
// List of registered component extensions (see Extension::Location).
typedef std::vector<ComponentExtensionInfo> RegisteredComponentExtensions;
RegisteredComponentExtensions component_extension_manifests_;
diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc
index 601586b..24c7151 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.cc
+++ b/chrome/browser/gtk/location_bar_view_gtk.cc
@@ -208,9 +208,9 @@ void LocationBarViewGtk::Init(bool popup_window_mode) {
tab_to_search_partial_label_, FALSE, FALSE, 0);
GtkWidget* tab_to_search_hbox = gtk_hbox_new(FALSE, 0);
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- GtkWidget* tab_to_search_lens = gtk_image_new_from_pixbuf(
+ tab_to_search_magnifier_ = gtk_image_new_from_pixbuf(
rb.GetPixbufNamed(IDR_OMNIBOX_SEARCH));
- gtk_box_pack_start(GTK_BOX(tab_to_search_hbox), tab_to_search_lens,
+ gtk_box_pack_start(GTK_BOX(tab_to_search_hbox), tab_to_search_magnifier_,
FALSE, FALSE, 0);
gtk_util::CenterWidgetInHBox(tab_to_search_hbox, tab_to_search_label_hbox,
false, 0);
@@ -875,6 +875,24 @@ void LocationBarViewGtk::SetKeywordLabel(const std::wstring& keyword) {
WideToUTF8(full_name).c_str());
gtk_label_set_text(GTK_LABEL(tab_to_search_partial_label_),
WideToUTF8(partial_name).c_str());
+
+ if (last_keyword_ != keyword) {
+ last_keyword_ = keyword;
+
+ if (is_extension_keyword) {
+ const TemplateURL* template_url =
+ profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword);
+ const SkBitmap& bitmap = profile_->GetExtensionsService()->
+ GetOmniboxIcon(template_url->GetExtensionId());
+ GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
+ gtk_image_set_from_pixbuf(GTK_IMAGE(tab_to_search_magnifier_), pixbuf);
+ g_object_unref(pixbuf);
+ } else {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ gtk_image_set_from_pixbuf(GTK_IMAGE(tab_to_search_magnifier_),
+ rb.GetPixbufNamed(IDR_OMNIBOX_SEARCH));
+ }
+ }
}
void LocationBarViewGtk::SetKeywordHintLabel(const std::wstring& keyword) {
diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h
index da87cdc..870e415 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.h
+++ b/chrome/browser/gtk/location_bar_view_gtk.h
@@ -362,6 +362,7 @@ class LocationBarViewGtk : public AutocompleteEditController,
// Area on the left shown when in tab to search mode.
GtkWidget* tab_to_search_box_;
+ GtkWidget* tab_to_search_magnifier_;
GtkWidget* tab_to_search_full_label_;
GtkWidget* tab_to_search_partial_label_;
@@ -417,6 +418,9 @@ class LocationBarViewGtk : public AutocompleteEditController,
// Indicate if |tab_to_search_hint_| should be shown.
bool show_keyword_hint_;
+ // The last search keyword that was shown via the |tab_to_search_box_|.
+ std::wstring last_keyword_;
+
DISALLOW_COPY_AND_ASSIGN(LocationBarViewGtk);
};
diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc
index 17d243c..45a10bf 100644
--- a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc
+++ b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc
@@ -153,7 +153,7 @@ class AutocompleteResultView : public views::View {
ResultViewState GetState() const;
- SkBitmap* GetIcon() const;
+ const SkBitmap* GetIcon() const;
// Draws the specified |text| into the canvas, using highlighting provided by
// |classifications|. If |force_dim| is true, ACMatchClassification::DIM is
@@ -339,7 +339,11 @@ ResultViewState AutocompleteResultView::GetState() const {
return model_->IsHoveredIndex(model_index_) ? HOVERED : NORMAL;
}
-SkBitmap* AutocompleteResultView::GetIcon() const {
+const SkBitmap* AutocompleteResultView::GetIcon() const {
+ const SkBitmap* bitmap = model_->GetSpecialIcon(model_index_);
+ if (bitmap)
+ return bitmap;
+
int icon = match_.starred ?
IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match_.type);
if (model_->IsSelectedIndex(model_index_)) {
@@ -740,6 +744,13 @@ bool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const {
return HasMatchAt(index) ? index == model_->hovered_line() : false;
}
+const SkBitmap* AutocompletePopupContentsView::GetSpecialIcon(
+ size_t index) const {
+ if (!HasMatchAt(index))
+ return NULL;
+ return model_->GetSpecialIconForMatch(GetMatchAtIndex(index));
+}
+
////////////////////////////////////////////////////////////////////////////////
// AutocompletePopupContentsView, AnimationDelegate implementation:
diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h
index d814206..80704cd 100644
--- a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h
+++ b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h
@@ -33,6 +33,10 @@ class AutocompleteResultViewModel {
// Returns true if the index is hovered.
virtual bool IsHoveredIndex(size_t index) const = 0;
+
+ // Returns the special-case icon we should use for the given index, or NULL
+ // if we should use the default icon.
+ virtual const SkBitmap* GetSpecialIcon(size_t index) const = 0;
};
// A view representing the contents of the autocomplete popup.
@@ -63,6 +67,7 @@ class AutocompletePopupContentsView : public views::View,
// Overridden from AutocompleteResultViewModel:
virtual bool IsSelectedIndex(size_t index) const;
virtual bool IsHoveredIndex(size_t index) const;
+ virtual const SkBitmap* GetSpecialIcon(size_t index) const;
// Overridden from AnimationDelegate:
virtual void AnimationProgressed(const Animation* animation);
diff --git a/chrome/browser/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/views/location_bar/icon_label_bubble_view.cc
index 729c9a1..4e92ac0 100644
--- a/chrome/browser/views/location_bar/icon_label_bubble_view.cc
+++ b/chrome/browser/views/location_bar/icon_label_bubble_view.cc
@@ -43,6 +43,10 @@ void IconLabelBubbleView::SetLabel(const std::wstring& label) {
label_->SetText(label);
}
+void IconLabelBubbleView::SetImage(const SkBitmap& bitmap) {
+ image_->SetImage(bitmap);
+}
+
void IconLabelBubbleView::Paint(gfx::Canvas* canvas) {
int y_offset = (GetParent()->height() - height()) / 2;
canvas->TranslateInt(0, y_offset);
diff --git a/chrome/browser/views/location_bar/icon_label_bubble_view.h b/chrome/browser/views/location_bar/icon_label_bubble_view.h
index 53b0b33..dd5b196 100644
--- a/chrome/browser/views/location_bar/icon_label_bubble_view.h
+++ b/chrome/browser/views/location_bar/icon_label_bubble_view.h
@@ -20,6 +20,8 @@ class ImageView;
class Label;
}
+class SkBitmap;
+
// View used to draw a bubble to the left of the address, containing an icon and
// a label. We use this as a base for the classes that handle the EV bubble and
// tab-to-search UI.
@@ -32,6 +34,7 @@ class IconLabelBubbleView : public views::View {
void SetFont(const gfx::Font& font);
void SetLabel(const std::wstring& label);
+ void SetImage(const SkBitmap& bitmap);
virtual void Paint(gfx::Canvas* canvas);
virtual gfx::Size GetPreferredSize();
diff --git a/chrome/browser/views/location_bar/location_bar_view.cc b/chrome/browser/views/location_bar/location_bar_view.cc
index 8ed874d..4dffa4e 100644
--- a/chrome/browser/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/views/location_bar/location_bar_view.cc
@@ -17,6 +17,7 @@
#include "chrome/browser/extensions/extension_browser_event_router.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/view_ids.h"
#include "chrome/browser/views/browser_dialogs.h"
#include "chrome/browser/views/location_bar/content_setting_image_view.h"
@@ -457,8 +458,20 @@ void LocationBarView::Layout() {
selected_keyword_view_->SetVisible(show_selected_keyword);
keyword_hint_view_->SetVisible(show_keyword_hint);
if (show_selected_keyword) {
- if (selected_keyword_view_->keyword() != keyword)
+ if (selected_keyword_view_->keyword() != keyword) {
selected_keyword_view_->SetKeyword(keyword);
+
+ const TemplateURL* template_url =
+ profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword);
+ if (template_url && template_url->IsExtensionKeyword()) {
+ const SkBitmap& bitmap = profile_->GetExtensionsService()->
+ GetOmniboxIcon(template_url->GetExtensionId());
+ selected_keyword_view_->SetImage(bitmap);
+ } else {
+ selected_keyword_view_->SetImage(*ResourceBundle::GetSharedInstance().
+ GetBitmapNamed(IDR_OMNIBOX_SEARCH));
+ }
+ }
} else if (show_keyword_hint) {
if (keyword_hint_view_->keyword() != keyword)
keyword_hint_view_->SetKeyword(keyword);