summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--chrome/chrome_browser.gypi2
26 files changed, 370 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);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index e5438f3..ce10a59 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1216,6 +1216,8 @@
'browser/extensions/extension_host.h',
'browser/extensions/extension_host_mac.h',
'browser/extensions/extension_host_mac.mm',
+ 'browser/extensions/extension_icon_manager.cc',
+ 'browser/extensions/extension_icon_manager.h',
'browser/extensions/extension_idle_api.cc',
'browser/extensions/extension_idle_api.h',
'browser/extensions/extension_idle_api_constants.cc',