summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/location_bar
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/views/location_bar')
-rw-r--r--chrome/browser/views/location_bar/click_handler.cc36
-rw-r--r--chrome/browser/views/location_bar/click_handler.h33
-rw-r--r--chrome/browser/views/location_bar/content_setting_image_view.cc93
-rw-r--r--chrome/browser/views/location_bar/content_setting_image_view.h59
-rw-r--r--chrome/browser/views/location_bar/ev_bubble_view.cc28
-rw-r--r--chrome/browser/views/location_bar/ev_bubble_view.h37
-rw-r--r--chrome/browser/views/location_bar/icon_label_bubble_view.cc72
-rw-r--r--chrome/browser/views/location_bar/icon_label_bubble_view.h54
-rw-r--r--chrome/browser/views/location_bar/keyword_hint_view.cc137
-rw-r--r--chrome/browser/views/location_bar/keyword_hint_view.h65
-rw-r--r--chrome/browser/views/location_bar/location_bar_view.cc942
-rw-r--r--chrome/browser/views/location_bar/location_bar_view.h338
-rw-r--r--chrome/browser/views/location_bar/location_icon_view.cc23
-rw-r--r--chrome/browser/views/location_bar/location_icon_view.h34
-rw-r--r--chrome/browser/views/location_bar/page_action_image_view.cc221
-rw-r--r--chrome/browser/views/location_bar/page_action_image_view.h109
-rw-r--r--chrome/browser/views/location_bar/page_action_with_badge_view.cc35
-rw-r--r--chrome/browser/views/location_bar/page_action_with_badge_view.h35
-rw-r--r--chrome/browser/views/location_bar/selected_keyword_view.cc84
-rw-r--r--chrome/browser/views/location_bar/selected_keyword_view.h61
-rw-r--r--chrome/browser/views/location_bar/star_view.cc58
-rw-r--r--chrome/browser/views/location_bar/star_view.h43
22 files changed, 2597 insertions, 0 deletions
diff --git a/chrome/browser/views/location_bar/click_handler.cc b/chrome/browser/views/location_bar/click_handler.cc
new file mode 100644
index 0000000..e9c414c
--- /dev/null
+++ b/chrome/browser/views/location_bar/click_handler.cc
@@ -0,0 +1,36 @@
+// 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/views/location_bar/click_handler.h"
+
+#include "chrome/browser/tab_contents/navigation_controller.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/views/location_bar/location_bar_view.h"
+#include "views/view.h"
+
+ClickHandler::ClickHandler(const views::View* owner,
+ const LocationBarView* location_bar)
+ : owner_(owner),
+ location_bar_(location_bar) {
+}
+
+void ClickHandler::OnMouseReleased(const views::MouseEvent& event,
+ bool canceled) {
+ if (canceled || !owner_->HitTest(event.location()))
+ return;
+
+ // Do not show page info if the user has been editing the location
+ // bar, or the location bar is at the NTP.
+ if (location_bar_->location_entry()->IsEditingOrEmpty())
+ return;
+
+ TabContents* tab = location_bar_->GetTabContents();
+ NavigationEntry* nav_entry = tab->controller().GetActiveEntry();
+ if (!nav_entry) {
+ NOTREACHED();
+ return;
+ }
+ tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true);
+}
+
diff --git a/chrome/browser/views/location_bar/click_handler.h b/chrome/browser/views/location_bar/click_handler.h
new file mode 100644
index 0000000..e477e94
--- /dev/null
+++ b/chrome/browser/views/location_bar/click_handler.h
@@ -0,0 +1,33 @@
+// 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_VIEWS_LOCATION_BAR_CLICK_HANDLER_H_
+#define CHROME_BROWSER_VIEWS_LOCATION_BAR_CLICK_HANDLER_H_
+
+#include "base/basictypes.h"
+
+class LocationBarView;
+
+namespace views {
+class MouseEvent;
+class View;
+}
+
+// This helper class is kept as a member by classes that need to show the Page
+// Info dialog on click, to encapsulate that logic in one place.
+class ClickHandler {
+ public:
+ ClickHandler(const views::View* owner, const LocationBarView* location_bar);
+
+ void OnMouseReleased(const views::MouseEvent& event, bool canceled);
+
+ private:
+ const views::View* owner_;
+ const LocationBarView* location_bar_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ClickHandler);
+};
+
+#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_CLICK_HANDLER_H_
+
diff --git a/chrome/browser/views/location_bar/content_setting_image_view.cc b/chrome/browser/views/location_bar/content_setting_image_view.cc
new file mode 100644
index 0000000..03b30eb
--- /dev/null
+++ b/chrome/browser/views/location_bar/content_setting_image_view.cc
@@ -0,0 +1,93 @@
+// 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/views/location_bar/content_setting_image_view.h"
+
+#include "app/resource_bundle.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/content_setting_bubble_model.h"
+#include "chrome/browser/content_setting_image_model.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/views/content_blocked_bubble_contents.h"
+#include "chrome/browser/views/location_bar/location_bar_view.h"
+
+ContentSettingImageView::ContentSettingImageView(
+ ContentSettingsType content_type,
+ const LocationBarView* parent,
+ Profile* profile)
+ : content_setting_image_model_(
+ ContentSettingImageModel::CreateContentSettingImageModel(
+ content_type)),
+ parent_(parent),
+ profile_(profile),
+ info_bubble_(NULL) {
+}
+
+ContentSettingImageView::~ContentSettingImageView() {
+ if (info_bubble_)
+ info_bubble_->Close();
+}
+
+void ContentSettingImageView::UpdateFromTabContents(
+ const TabContents* tab_contents) {
+ int old_icon = content_setting_image_model_->get_icon();
+ content_setting_image_model_->UpdateFromTabContents(tab_contents);
+ if (!content_setting_image_model_->is_visible()) {
+ SetVisible(false);
+ return;
+ }
+ if (old_icon != content_setting_image_model_->get_icon()) {
+ SetImage(ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ content_setting_image_model_->get_icon()));
+ }
+ SetTooltipText(UTF8ToWide(content_setting_image_model_->get_tooltip()));
+ SetVisible(true);
+}
+
+bool ContentSettingImageView::OnMousePressed(const views::MouseEvent& event) {
+ // We want to show the bubble on mouse release; that is the standard behavior
+ // for buttons.
+ return true;
+}
+
+void ContentSettingImageView::OnMouseReleased(const views::MouseEvent& event,
+ bool canceled) {
+ if (canceled || !HitTest(event.location()))
+ return;
+
+ TabContents* tab_contents = parent_->GetTabContents();
+ if (!tab_contents)
+ return;
+
+ gfx::Rect screen_bounds(GetImageBounds());
+ gfx::Point origin(screen_bounds.origin());
+ views::View::ConvertPointToScreen(this, &origin);
+ screen_bounds.set_origin(origin);
+ ContentSettingBubbleContents* bubble_contents =
+ new ContentSettingBubbleContents(
+ ContentSettingBubbleModel::CreateContentSettingBubbleModel(
+ tab_contents, profile_,
+ content_setting_image_model_->get_content_settings_type()),
+ profile_, tab_contents);
+ DCHECK(!info_bubble_);
+ info_bubble_ =
+ InfoBubble::Show(GetWindow(), screen_bounds, bubble_contents, this);
+ bubble_contents->set_info_bubble(info_bubble_);
+}
+
+void ContentSettingImageView::VisibilityChanged(View* starting_from,
+ bool is_visible) {
+ if (!is_visible && info_bubble_)
+ info_bubble_->Close();
+}
+
+void ContentSettingImageView::InfoBubbleClosing(InfoBubble* info_bubble,
+ bool closed_by_escape) {
+ info_bubble_ = NULL;
+}
+
+bool ContentSettingImageView::CloseOnEscape() {
+ return true;
+}
+
diff --git a/chrome/browser/views/location_bar/content_setting_image_view.h b/chrome/browser/views/location_bar/content_setting_image_view.h
new file mode 100644
index 0000000..382d8a11
--- /dev/null
+++ b/chrome/browser/views/location_bar/content_setting_image_view.h
@@ -0,0 +1,59 @@
+// 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_VIEWS_LOCATION_BAR_CONTENT_SETTING_IMAGE_VIEW_H_
+#define CHROME_BROWSER_VIEWS_LOCATION_BAR_CONTENT_SETTING_IMAGE_VIEW_H_
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/views/info_bubble.h"
+#include "chrome/common/content_settings_types.h"
+#include "views/controls/image_view.h"
+
+class ContentSettingImageModel;
+class InfoBubble;
+class LocationBarView;
+class Profile;
+class TabContents;
+
+namespace views {
+class MouseEvent;
+}
+
+class ContentSettingImageView : public views::ImageView,
+ public InfoBubbleDelegate {
+ public:
+ ContentSettingImageView(ContentSettingsType content_type,
+ const LocationBarView* parent,
+ Profile* profile);
+ virtual ~ContentSettingImageView();
+
+ void set_profile(Profile* profile) { profile_ = profile; }
+ void UpdateFromTabContents(const TabContents* tab_contents);
+
+ private:
+ // views::ImageView overrides:
+ virtual bool OnMousePressed(const views::MouseEvent& event);
+ virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
+ virtual void VisibilityChanged(View* starting_from, bool is_visible);
+
+ // InfoBubbleDelegate overrides:
+ virtual void InfoBubbleClosing(InfoBubble* info_bubble,
+ bool closed_by_escape);
+ virtual bool CloseOnEscape();
+
+ scoped_ptr<ContentSettingImageModel> content_setting_image_model_;
+
+ // The owning LocationBarView.
+ const LocationBarView* parent_;
+
+ // The currently active profile.
+ Profile* profile_;
+
+ // The currently shown info bubble if any.
+ InfoBubble* info_bubble_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ContentSettingImageView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_CONTENT_SETTING_IMAGE_VIEW_H_
diff --git a/chrome/browser/views/location_bar/ev_bubble_view.cc b/chrome/browser/views/location_bar/ev_bubble_view.cc
new file mode 100644
index 0000000..882bfd0
--- /dev/null
+++ b/chrome/browser/views/location_bar/ev_bubble_view.cc
@@ -0,0 +1,28 @@
+// 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/views/location_bar/ev_bubble_view.h"
+
+EVBubbleView::EVBubbleView(const int background_images[],
+ int contained_image,
+ const SkColor& color,
+ const LocationBarView* location_bar)
+ : IconLabelBubbleView(background_images, contained_image, color),
+ ALLOW_THIS_IN_INITIALIZER_LIST(click_handler_(this, location_bar)) {
+}
+
+EVBubbleView::~EVBubbleView() {
+}
+
+bool EVBubbleView::OnMousePressed(const views::MouseEvent& event) {
+ // We want to show the dialog on mouse release; that is the standard behavior
+ // for buttons.
+ return true;
+}
+
+void EVBubbleView::OnMouseReleased(const views::MouseEvent& event,
+ bool canceled) {
+ click_handler_.OnMouseReleased(event, canceled);
+}
+
diff --git a/chrome/browser/views/location_bar/ev_bubble_view.h b/chrome/browser/views/location_bar/ev_bubble_view.h
new file mode 100644
index 0000000..4b92944
--- /dev/null
+++ b/chrome/browser/views/location_bar/ev_bubble_view.h
@@ -0,0 +1,37 @@
+// 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_VIEWS_LOCATION_BAR_EV_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_VIEWS_LOCATION_BAR_EV_BUBBLE_VIEW_H_
+
+#include "chrome/browser/views/location_bar/click_handler.h"
+#include "chrome/browser/views/location_bar/icon_label_bubble_view.h"
+
+class LocationBarView;
+
+namespace views {
+class MouseEvent;
+}
+
+// EVBubbleView displays the EV Bubble in the LocationBarView.
+class EVBubbleView : public IconLabelBubbleView {
+ public:
+ EVBubbleView(const int background_images[],
+ int contained_image,
+ const SkColor& color,
+ const LocationBarView* location_bar);
+ virtual ~EVBubbleView();
+
+ // Overridden from view.
+ virtual bool OnMousePressed(const views::MouseEvent& event);
+ virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
+
+ private:
+ ClickHandler click_handler_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(EVBubbleView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_EV_BUBBLE_VIEW_H_
+
diff --git a/chrome/browser/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/views/location_bar/icon_label_bubble_view.cc
new file mode 100644
index 0000000..c40acff
--- /dev/null
+++ b/chrome/browser/views/location_bar/icon_label_bubble_view.cc
@@ -0,0 +1,72 @@
+// 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/views/location_bar/icon_label_bubble_view.h"
+
+#include "app/resource_bundle.h"
+#include "chrome/browser/views/location_bar/location_bar_view.h"
+#include "gfx/canvas.h"
+#include "views/controls/image_view.h"
+#include "views/controls/label.h"
+
+// Amount to offset the image.
+static const int kImageOffset = 1;
+
+// Amount to offset the label from the image.
+static const int kLabelOffset = 3;
+
+// Amount of padding after the label.
+static const int kLabelPadding = 4;
+
+IconLabelBubbleView::IconLabelBubbleView(const int background_images[],
+ int contained_image,
+ const SkColor& color)
+ : background_painter_(background_images) {
+ image_ = new views::ImageView();
+ AddChildView(image_);
+ image_->SetImage(
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(contained_image));
+ label_ = new views::Label();
+ AddChildView(label_);
+ label_->SetColor(color);
+}
+
+IconLabelBubbleView::~IconLabelBubbleView() {
+}
+
+void IconLabelBubbleView::SetFont(const gfx::Font& font) {
+ label_->SetFont(font);
+}
+
+void IconLabelBubbleView::SetLabel(const std::wstring& label) {
+ label_->SetText(label);
+}
+
+void IconLabelBubbleView::Paint(gfx::Canvas* canvas) {
+ int y_offset = (GetParent()->height() - height()) / 2;
+ canvas->TranslateInt(0, y_offset);
+ background_painter_.Paint(width(), height(), canvas);
+ canvas->TranslateInt(0, -y_offset);
+}
+
+gfx::Size IconLabelBubbleView::GetPreferredSize() {
+ gfx::Size size(GetNonLabelSize());
+ size.Enlarge(label_->GetPreferredSize().width(), 0);
+ return size;
+}
+
+void IconLabelBubbleView::Layout() {
+ image_->SetBounds(kImageOffset, 0, image_->GetPreferredSize().width(),
+ height());
+ gfx::Size label_size(label_->GetPreferredSize());
+ label_->SetBounds(image_->x() + image_->width() + kLabelOffset,
+ (height() - label_size.height()) / 2, label_size.width(),
+ label_size.height());
+}
+
+gfx::Size IconLabelBubbleView::GetNonLabelSize() {
+ return gfx::Size(kImageOffset + image_->GetPreferredSize().width() +
+ kLabelOffset + kLabelPadding, background_painter_.height());
+}
+
diff --git a/chrome/browser/views/location_bar/icon_label_bubble_view.h b/chrome/browser/views/location_bar/icon_label_bubble_view.h
new file mode 100644
index 0000000..b8b9485
--- /dev/null
+++ b/chrome/browser/views/location_bar/icon_label_bubble_view.h
@@ -0,0 +1,54 @@
+// 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_VIEWS_LOCATION_BAR_ICON_LABEL_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_VIEWS_LOCATION_BAR_ICON_LABEL_BUBBLE_VIEW_H_
+
+#include <string>
+
+#include "gfx/size.h"
+#include "views/painter.h"
+#include "views/view.h"
+
+namespace gfx {
+class Canvas;
+class Font;
+}
+namespace views {
+class ImageView;
+class Label;
+}
+
+// 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.
+class IconLabelBubbleView : public views::View {
+ public:
+ IconLabelBubbleView(const int background_images[],
+ int contained_image,
+ const SkColor& color);
+ virtual ~IconLabelBubbleView();
+
+ void SetFont(const gfx::Font& font);
+ void SetLabel(const std::wstring& label);
+
+ virtual void Paint(gfx::Canvas* canvas);
+ virtual gfx::Size GetPreferredSize();
+ virtual void Layout();
+
+ protected:
+ gfx::Size GetNonLabelSize();
+
+ private:
+ // For painting the background.
+ views::HorizontalPainter background_painter_;
+
+ // The contents of the bubble.
+ views::ImageView* image_;
+ views::Label* label_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(IconLabelBubbleView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_ICON_LABEL_BUBBLE_VIEW_H_
diff --git a/chrome/browser/views/location_bar/keyword_hint_view.cc b/chrome/browser/views/location_bar/keyword_hint_view.cc
new file mode 100644
index 0000000..9f35e3b
--- /dev/null
+++ b/chrome/browser/views/location_bar/keyword_hint_view.cc
@@ -0,0 +1,137 @@
+// 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/views/location_bar/keyword_hint_view.h"
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "base/logging.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "gfx/canvas.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "views/controls/label.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+// Amount of space to offset the tab image from the top of the view by.
+static const int kTabImageYOffset = 4;
+
+// The tab key image.
+static const SkBitmap* kTabButtonBitmap = NULL;
+
+KeywordHintView::KeywordHintView(Profile* profile) : profile_(profile) {
+ leading_label_ = new views::Label();
+ trailing_label_ = new views::Label();
+ AddChildView(leading_label_);
+ AddChildView(trailing_label_);
+
+ if (!kTabButtonBitmap) {
+ kTabButtonBitmap = ResourceBundle::GetSharedInstance().
+ GetBitmapNamed(IDR_LOCATION_BAR_KEYWORD_HINT_TAB);
+ }
+}
+
+KeywordHintView::~KeywordHintView() {
+}
+
+void KeywordHintView::SetFont(const gfx::Font& font) {
+ leading_label_->SetFont(font);
+ trailing_label_->SetFont(font);
+}
+
+void KeywordHintView::SetColor(const SkColor& color) {
+ leading_label_->SetColor(color);
+ trailing_label_->SetColor(color);
+}
+
+void KeywordHintView::SetKeyword(const std::wstring& keyword) {
+ keyword_ = keyword;
+ if (keyword_.empty())
+ return;
+ DCHECK(profile_);
+ if (!profile_->GetTemplateURLModel())
+ return;
+
+ std::vector<size_t> content_param_offsets;
+ const std::wstring keyword_hint(l10n_util::GetStringF(
+ IDS_OMNIBOX_KEYWORD_HINT, std::wstring(),
+ GetKeywordName(profile_, keyword), &content_param_offsets));
+ if (content_param_offsets.size() == 2) {
+ leading_label_->SetText(
+ keyword_hint.substr(0, content_param_offsets.front()));
+ trailing_label_->SetText(
+ keyword_hint.substr(content_param_offsets.front()));
+ } else {
+ // See comments on an identical NOTREACHED() in search_provider.cc.
+ NOTREACHED();
+ }
+}
+
+void KeywordHintView::Paint(gfx::Canvas* canvas) {
+ int image_x = leading_label_->IsVisible() ? leading_label_->width() : 0;
+
+ // Since we paint the button image directly on the canvas (instead of using a
+ // child view), we must mirror the button's position manually if the locale
+ // is right-to-left.
+ gfx::Rect tab_button_bounds(image_x,
+ kTabImageYOffset,
+ kTabButtonBitmap->width(),
+ kTabButtonBitmap->height());
+ tab_button_bounds.set_x(MirroredLeftPointForRect(tab_button_bounds));
+ canvas->DrawBitmapInt(*kTabButtonBitmap,
+ tab_button_bounds.x(),
+ tab_button_bounds.y());
+}
+
+gfx::Size KeywordHintView::GetPreferredSize() {
+ // TODO(sky): currently height doesn't matter, once baseline support is
+ // added this should check baselines.
+ gfx::Size prefsize = leading_label_->GetPreferredSize();
+ int width = prefsize.width();
+ width += kTabButtonBitmap->width();
+ prefsize = trailing_label_->GetPreferredSize();
+ width += prefsize.width();
+ return gfx::Size(width, prefsize.height());
+}
+
+gfx::Size KeywordHintView::GetMinimumSize() {
+ // TODO(sky): currently height doesn't matter, once baseline support is
+ // added this should check baselines.
+ return gfx::Size(kTabButtonBitmap->width(), 0);
+}
+
+void KeywordHintView::Layout() {
+ // TODO(sky): baseline layout.
+ bool show_labels = (width() != kTabButtonBitmap->width());
+
+ leading_label_->SetVisible(show_labels);
+ trailing_label_->SetVisible(show_labels);
+ int x = 0;
+ gfx::Size pref;
+
+ if (show_labels) {
+ pref = leading_label_->GetPreferredSize();
+ leading_label_->SetBounds(x, 0, pref.width(), height());
+
+ x += pref.width() + kTabButtonBitmap->width();
+ pref = trailing_label_->GetPreferredSize();
+ trailing_label_->SetBounds(x, 0, pref.width(), height());
+ }
+}
+
+
+// static
+std::wstring KeywordHintView::GetKeywordName(Profile* profile,
+ const std::wstring& keyword) {
+ // Make sure the TemplateURL still exists.
+ // TODO(sky): Once LocationBarView adds a listener to the TemplateURLModel
+ // to track changes to the model, this should become a DCHECK.
+ const TemplateURL* template_url =
+ profile->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword);
+ if (template_url)
+ return template_url->AdjustedShortNameForLocaleDirection();
+ return std::wstring();
+}
diff --git a/chrome/browser/views/location_bar/keyword_hint_view.h b/chrome/browser/views/location_bar/keyword_hint_view.h
new file mode 100644
index 0000000..500216c
--- /dev/null
+++ b/chrome/browser/views/location_bar/keyword_hint_view.h
@@ -0,0 +1,65 @@
+// 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_VIEWS_LOCATION_BAR_KEYWORD_HINT_VIEW_H_
+#define CHROME_BROWSER_VIEWS_LOCATION_BAR_KEYWORD_HINT_VIEW_H_
+
+#include <string>
+
+#include "gfx/size.h"
+#include "views/view.h"
+
+namespace gfx {
+class Font;
+}
+class Profile;
+namespace views {
+class Label;
+}
+
+// KeywordHintView is used by the location bar view to display a hint to the
+// user when the selected url has a corresponding keyword.
+//
+// Internally KeywordHintView uses two labels to render the text, and draws
+// the tab image itself.
+//
+// NOTE: This should really be called LocationBarKeywordHintView, but I
+// couldn't bring myself to use such a long name.
+class KeywordHintView : public views::View {
+ public:
+ explicit KeywordHintView(Profile* profile);
+ virtual ~KeywordHintView();
+
+ void SetFont(const gfx::Font& font);
+
+ void SetColor(const SkColor& color);
+
+ void SetKeyword(const std::wstring& keyword);
+ std::wstring keyword() const { return keyword_; }
+
+ virtual void Paint(gfx::Canvas* canvas);
+ virtual gfx::Size GetPreferredSize();
+ // The minimum size is just big enough to show the tab.
+ virtual gfx::Size GetMinimumSize();
+ virtual void Layout();
+
+ void set_profile(Profile* profile) { profile_ = profile; }
+
+ // Returns the short name for a keyword.
+ static std::wstring GetKeywordName(Profile* profile,
+ const std::wstring& keyword);
+
+ private:
+ views::Label* leading_label_;
+ views::Label* trailing_label_;
+
+ // The keyword.
+ std::wstring keyword_;
+
+ Profile* profile_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(KeywordHintView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_KEYWORD_HINT_VIEW_H_
diff --git a/chrome/browser/views/location_bar/location_bar_view.cc b/chrome/browser/views/location_bar/location_bar_view.cc
new file mode 100644
index 0000000..16ea52f
--- /dev/null
+++ b/chrome/browser/views/location_bar/location_bar_view.cc
@@ -0,0 +1,942 @@
+// 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/views/location_bar/location_bar_view.h"
+
+#if defined(OS_LINUX)
+#include <gtk/gtk.h>
+#endif
+
+#include "app/drag_drop_types.h"
+#include "app/resource_bundle.h"
+#include "app/theme_provider.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/alternate_nav_url_fetcher.h"
+#include "chrome/browser/extensions/extension_browser_event_router.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"
+#include "chrome/browser/views/location_bar/ev_bubble_view.h"
+#include "chrome/browser/views/location_bar/keyword_hint_view.h"
+#include "chrome/browser/views/location_bar/location_icon_view.h"
+#include "chrome/browser/views/location_bar/page_action_image_view.h"
+#include "chrome/browser/views/location_bar/page_action_with_badge_view.h"
+#include "chrome/browser/views/location_bar/selected_keyword_view.h"
+#include "chrome/browser/views/location_bar/star_view.h"
+#include "gfx/canvas.h"
+#include "gfx/color_utils.h"
+#include "grit/theme_resources.h"
+#include "views/drag_utils.h"
+
+#if defined(OS_WIN)
+#include "chrome/browser/views/first_run_bubble.h"
+#endif
+
+using views::View;
+
+// static
+const int LocationBarView::kVertMargin = 2;
+
+// Padding between items in the location bar.
+static const int kViewPadding = 3;
+
+// Padding before the start of a bubble.
+static const int kBubblePadding = kViewPadding - 1;
+
+// Padding between the location icon and the edit, if they're adjacent.
+static const int kLocationIconEditPadding = kViewPadding - 1;
+
+static const int kEVBubbleBackgroundImages[] = {
+ IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_L,
+ IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_C,
+ IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_R,
+};
+
+static const int kSelectedKeywordBackgroundImages[] = {
+ IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_L,
+ IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_C,
+ IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_R,
+};
+
+static const SkBitmap* kBackground = NULL;
+
+static const SkBitmap* kPopupBackground = NULL;
+
+// LocationBarView -----------------------------------------------------------
+
+LocationBarView::LocationBarView(Profile* profile,
+ CommandUpdater* command_updater,
+ ToolbarModel* model,
+ Delegate* delegate,
+ Mode mode)
+ : profile_(profile),
+ command_updater_(command_updater),
+ model_(model),
+ delegate_(delegate),
+ disposition_(CURRENT_TAB),
+ location_icon_view_(NULL),
+ ev_bubble_view_(NULL),
+ location_entry_view_(NULL),
+ selected_keyword_view_(NULL),
+ keyword_hint_view_(NULL),
+ star_view_(NULL),
+ mode_(mode),
+ ALLOW_THIS_IN_INITIALIZER_LIST(first_run_bubble_(this)) {
+ DCHECK(profile_);
+ SetID(VIEW_ID_LOCATION_BAR);
+ SetFocusable(true);
+
+ if (!kBackground) {
+ ResourceBundle &rb = ResourceBundle::GetSharedInstance();
+ kBackground = rb.GetBitmapNamed(IDR_LOCATIONBG);
+ kPopupBackground = rb.GetBitmapNamed(IDR_LOCATIONBG_POPUPMODE_CENTER);
+ }
+}
+
+LocationBarView::~LocationBarView() {
+}
+
+void LocationBarView::Init() {
+ if (mode_ == POPUP) {
+ font_ = ResourceBundle::GetSharedInstance().GetFont(
+ ResourceBundle::BaseFont);
+ } else {
+ // Use a larger version of the system font.
+ font_ = font_.DeriveFont(3);
+ }
+
+ location_icon_view_ = new LocationIconView(this);
+ AddChildView(location_icon_view_);
+ location_icon_view_->SetVisible(true);
+ location_icon_view_->SetDragController(this);
+
+ ev_bubble_view_ =
+ new EVBubbleView(kEVBubbleBackgroundImages, IDR_OMNIBOX_HTTPS_VALID,
+ GetColor(ToolbarModel::EV_SECURE, SECURITY_TEXT), this);
+ AddChildView(ev_bubble_view_);
+ ev_bubble_view_->SetVisible(false);
+ ev_bubble_view_->SetDragController(this);
+
+ // URL edit field.
+ // View container for URL edit field.
+#if defined(OS_WIN)
+ location_entry_.reset(new AutocompleteEditViewWin(font_, this, model_, this,
+ GetWidget()->GetNativeView(), profile_, command_updater_,
+ mode_ == POPUP, this));
+#else
+ location_entry_.reset(new AutocompleteEditViewGtk(this, model_, profile_,
+ command_updater_, mode_ == POPUP, this));
+ location_entry_->Init();
+ // Make all the children of the widget visible. NOTE: this won't display
+ // anything, it just toggles the visible flag.
+ gtk_widget_show_all(location_entry_->GetNativeView());
+ // Hide the widget. NativeViewHostGtk will make it visible again as
+ // necessary.
+ gtk_widget_hide(location_entry_->GetNativeView());
+#endif
+ location_entry_view_ = new views::NativeViewHost;
+ location_entry_view_->SetID(VIEW_ID_AUTOCOMPLETE);
+ AddChildView(location_entry_view_);
+ location_entry_view_->set_focus_view(this);
+ location_entry_view_->Attach(location_entry_->GetNativeView());
+
+ selected_keyword_view_ =
+ new SelectedKeywordView(kSelectedKeywordBackgroundImages,
+ IDR_OMNIBOX_SEARCH, SK_ColorBLACK, profile_),
+ AddChildView(selected_keyword_view_);
+ selected_keyword_view_->SetFont(font_);
+ selected_keyword_view_->SetVisible(false);
+
+ SkColor dimmed_text = GetColor(ToolbarModel::NONE, DEEMPHASIZED_TEXT);
+
+ keyword_hint_view_ = new KeywordHintView(profile_);
+ AddChildView(keyword_hint_view_);
+ keyword_hint_view_->SetVisible(false);
+ keyword_hint_view_->SetFont(font_);
+ keyword_hint_view_->SetColor(dimmed_text);
+
+ for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
+ ContentSettingImageView* content_blocked_view = new ContentSettingImageView(
+ static_cast<ContentSettingsType>(i), this, profile_);
+ content_setting_views_.push_back(content_blocked_view);
+ AddChildView(content_blocked_view);
+ content_blocked_view->SetVisible(false);
+ }
+
+ // The star is not visible in popups and in the app launcher.
+ if (mode_ == NORMAL) {
+ star_view_ = new StarView(command_updater_);
+ AddChildView(star_view_);
+ star_view_->SetVisible(true);
+ }
+
+ // Notify us when any ancestor is resized. In this case we want to tell the
+ // AutocompleteEditView to close its popup.
+ SetNotifyWhenVisibleBoundsInRootChanges(true);
+
+ // Initialize the location entry. We do this to avoid a black flash which is
+ // visible when the location entry has just been initialized.
+ Update(NULL);
+
+ OnChanged();
+}
+
+bool LocationBarView::IsInitialized() const {
+ return location_entry_view_ != NULL;
+}
+
+// static
+SkColor LocationBarView::GetColor(ToolbarModel::SecurityLevel security_level,
+ ColorKind kind) {
+ switch (kind) {
+#if defined(OS_WIN)
+ case BACKGROUND: return color_utils::GetSysSkColor(COLOR_WINDOW);
+ case TEXT: return color_utils::GetSysSkColor(COLOR_WINDOWTEXT);
+ case SELECTED_TEXT: return color_utils::GetSysSkColor(COLOR_HIGHLIGHTTEXT);
+#else
+ // TODO(beng): source from theme provider.
+ case BACKGROUND: return SK_ColorWHITE;
+ case TEXT: return SK_ColorBLACK;
+ case SELECTED_TEXT: return SK_ColorWHITE;
+#endif
+
+ case DEEMPHASIZED_TEXT:
+ return color_utils::AlphaBlend(GetColor(security_level, TEXT),
+ GetColor(security_level, BACKGROUND), 128);
+
+ case SECURITY_TEXT: {
+ SkColor color;
+ switch (security_level) {
+ case ToolbarModel::EV_SECURE:
+ case ToolbarModel::SECURE:
+ color = SkColorSetRGB(7, 149, 0);
+ break;
+
+ case ToolbarModel::SECURITY_WARNING:
+ return GetColor(security_level, DEEMPHASIZED_TEXT);
+ break;
+
+ case ToolbarModel::SECURITY_ERROR:
+ color = SkColorSetRGB(162, 0, 0);
+ break;
+
+ default:
+ NOTREACHED();
+ return GetColor(security_level, TEXT);
+ }
+ return color_utils::GetReadableColor(color, GetColor(security_level,
+ BACKGROUND));
+ }
+
+ default:
+ NOTREACHED();
+ return GetColor(security_level, TEXT);
+ }
+}
+
+void LocationBarView::Update(const TabContents* tab_for_state_restoring) {
+ RefreshContentSettingViews();
+ RefreshPageActionViews();
+ // Don't Update in app launcher mode so that the location entry does not show
+ // a URL or security background.
+ if (mode_ != APP_LAUNCHER)
+ location_entry_->Update(tab_for_state_restoring);
+ OnChanged();
+}
+
+void LocationBarView::UpdateContentSettingsIcons() {
+ RefreshContentSettingViews();
+
+ Layout();
+ SchedulePaint();
+}
+
+void LocationBarView::UpdatePageActions() {
+ size_t count_before = page_action_views_.size();
+ RefreshPageActionViews();
+ if (page_action_views_.size() != count_before) {
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_PAGE_ACTION_COUNT_CHANGED,
+ Source<LocationBar>(this),
+ NotificationService::NoDetails());
+ }
+
+ Layout();
+ SchedulePaint();
+}
+
+void LocationBarView::InvalidatePageActions() {
+ size_t count_before = page_action_views_.size();
+ DeletePageActionViews();
+ if (page_action_views_.size() != count_before) {
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_PAGE_ACTION_COUNT_CHANGED,
+ Source<LocationBar>(this),
+ NotificationService::NoDetails());
+ }
+}
+
+void LocationBarView::Focus() {
+ // Focus the location entry native view.
+ location_entry_->SetFocus();
+}
+
+void LocationBarView::SetProfile(Profile* profile) {
+ DCHECK(profile);
+ if (profile_ != profile) {
+ profile_ = profile;
+ location_entry_->model()->SetProfile(profile);
+ selected_keyword_view_->set_profile(profile);
+ keyword_hint_view_->set_profile(profile);
+ for (ContentSettingViews::const_iterator i(content_setting_views_.begin());
+ i != content_setting_views_.end(); ++i)
+ (*i)->set_profile(profile);
+ }
+}
+
+TabContents* LocationBarView::GetTabContents() const {
+ return delegate_->GetTabContents();
+}
+
+void LocationBarView::SetPreviewEnabledPageAction(ExtensionAction* page_action,
+ bool preview_enabled) {
+ if (mode_ != NORMAL)
+ return;
+
+ DCHECK(page_action);
+ TabContents* contents = delegate_->GetTabContents();
+
+ RefreshPageActionViews();
+ PageActionWithBadgeView* page_action_view =
+ static_cast<PageActionWithBadgeView*>(GetPageActionView(page_action));
+ DCHECK(page_action_view);
+ if (!page_action_view)
+ return;
+
+ page_action_view->image_view()->set_preview_enabled(preview_enabled);
+ page_action_view->UpdateVisibility(contents,
+ GURL(WideToUTF8(model_->GetText())));
+ Layout();
+ SchedulePaint();
+}
+
+views::View* LocationBarView::GetPageActionView(
+ ExtensionAction *page_action) {
+ DCHECK(page_action);
+ for (PageActionViews::const_iterator i(page_action_views_.begin());
+ i != page_action_views_.end(); ++i) {
+ if ((*i)->image_view()->page_action() == page_action)
+ return *i;
+ }
+ return NULL;
+}
+
+void LocationBarView::SetStarToggled(bool on) {
+ if (star_view_)
+ star_view_->SetToggled(on);
+}
+
+void LocationBarView::ShowStarBubble(const GURL& url, bool newly_bookmarked) {
+ gfx::Rect screen_bounds(star_view_->GetImageBounds());
+ // Compensate for some built-in padding in the Star image.
+ screen_bounds.Inset(1, 1, 1, 2);
+ gfx::Point origin(screen_bounds.origin());
+ views::View::ConvertPointToScreen(star_view_, &origin);
+ screen_bounds.set_origin(origin);
+ browser::ShowBookmarkBubbleView(GetWindow(), screen_bounds, star_view_,
+ profile_, url, newly_bookmarked);
+}
+
+gfx::Size LocationBarView::GetPreferredSize() {
+ return gfx::Size(0,
+ (mode_ == POPUP ? kPopupBackground : kBackground)->height());
+}
+
+void LocationBarView::Layout() {
+ if (!location_entry_.get())
+ return;
+
+ int entry_width = width() - kViewPadding;
+
+ // |location_icon_view_| is visible except when |ev_bubble_view_| or
+ // |selected_keyword_view_| are visible.
+ int location_icon_width = 0;
+ int ev_bubble_width = 0;
+ location_icon_view_->SetVisible(false);
+ ev_bubble_view_->SetVisible(false);
+ const std::wstring keyword(location_entry_->model()->keyword());
+ const bool is_keyword_hint(location_entry_->model()->is_keyword_hint());
+ const bool show_selected_keyword = !keyword.empty() && !is_keyword_hint;
+ if (show_selected_keyword) {
+ entry_width -= kViewPadding; // Assume the keyword might be hidden.
+ } else if (model_->GetSecurityLevel() == ToolbarModel::EV_SECURE) {
+ ev_bubble_view_->SetVisible(true);
+ ev_bubble_view_->SetLabel(model_->GetEVCertName());
+ ev_bubble_width = ev_bubble_view_->GetPreferredSize().width();
+ entry_width -= kBubblePadding + ev_bubble_width + kViewPadding;
+ } else {
+ location_icon_view_->SetVisible(true);
+ location_icon_width = location_icon_view_->GetPreferredSize().width();
+ entry_width -=
+ kViewPadding + location_icon_width + kLocationIconEditPadding;
+ }
+
+ if (star_view_)
+ entry_width -= star_view_->GetPreferredSize().width() + kViewPadding;
+ for (PageActionViews::const_iterator i(page_action_views_.begin());
+ i != page_action_views_.end(); ++i) {
+ if ((*i)->IsVisible())
+ entry_width -= (*i)->GetPreferredSize().width() + kViewPadding;
+ }
+ for (ContentSettingViews::const_iterator i(content_setting_views_.begin());
+ i != content_setting_views_.end(); ++i) {
+ if ((*i)->IsVisible())
+ entry_width -= (*i)->GetPreferredSize().width() + kViewPadding;
+ }
+
+#if defined(OS_WIN)
+ RECT formatting_rect;
+ location_entry_->GetRect(&formatting_rect);
+ RECT edit_bounds;
+ location_entry_->GetClientRect(&edit_bounds);
+ int max_edit_width = entry_width - formatting_rect.left -
+ (edit_bounds.right - formatting_rect.right);
+#else
+ int max_edit_width = entry_width;
+#endif
+
+ if (max_edit_width < 0)
+ return;
+ const int available_width = AvailableWidth(max_edit_width);
+
+ const bool show_keyword_hint = !keyword.empty() && is_keyword_hint;
+ selected_keyword_view_->SetVisible(show_selected_keyword);
+ keyword_hint_view_->SetVisible(show_keyword_hint);
+ if (show_selected_keyword) {
+ if (selected_keyword_view_->keyword() != keyword)
+ selected_keyword_view_->SetKeyword(keyword);
+ } else if (show_keyword_hint) {
+ if (keyword_hint_view_->keyword() != keyword)
+ keyword_hint_view_->SetKeyword(keyword);
+ }
+
+ // TODO(sky): baseline layout.
+ int location_y = TopMargin();
+ int location_height = std::max(height() - location_y - kVertMargin, 0);
+
+ // Lay out items to the right of the edit field.
+ int offset = width() - kViewPadding;
+ if (star_view_) {
+ int star_width = star_view_->GetPreferredSize().width();
+ offset -= star_width;
+ star_view_->SetBounds(offset, location_y, star_width, location_height);
+ offset -= kViewPadding;
+ }
+
+ for (PageActionViews::const_iterator i(page_action_views_.begin());
+ i != page_action_views_.end(); ++i) {
+ if ((*i)->IsVisible()) {
+ int page_action_width = (*i)->GetPreferredSize().width();
+ offset -= page_action_width;
+ (*i)->SetBounds(offset, location_y, page_action_width, location_height);
+ offset -= kViewPadding;
+ }
+ }
+ // We use a reverse_iterator here because we're laying out the views from
+ // right to left but in the vector they're ordered left to right.
+ for (ContentSettingViews::const_reverse_iterator
+ i(content_setting_views_.rbegin()); i != content_setting_views_.rend();
+ ++i) {
+ if ((*i)->IsVisible()) {
+ int content_blocked_width = (*i)->GetPreferredSize().width();
+ offset -= content_blocked_width;
+ (*i)->SetBounds(offset, location_y, content_blocked_width,
+ location_height);
+ offset -= kViewPadding;
+ }
+ }
+
+ // Now lay out items to the left of the edit field.
+ if (location_icon_view_->IsVisible()) {
+ location_icon_view_->SetBounds(kViewPadding, location_y,
+ location_icon_width, location_height);
+ offset = location_icon_view_->bounds().right() + kLocationIconEditPadding;
+ } else if (ev_bubble_view_->IsVisible()) {
+ ev_bubble_view_->SetBounds(kBubblePadding, location_y, ev_bubble_width,
+ location_height);
+ offset = ev_bubble_view_->bounds().right() + kViewPadding;
+ } else {
+ offset = show_selected_keyword ? kBubblePadding : kViewPadding;
+ }
+
+ // Now lay out the edit field and views that autocollapse to give it more
+ // room.
+ gfx::Rect location_bounds(offset, location_y, entry_width, location_height);
+ if (show_selected_keyword) {
+ LayoutView(true, selected_keyword_view_, available_width, &location_bounds);
+ if (!selected_keyword_view_->IsVisible()) {
+ location_bounds.set_x(
+ location_bounds.x() + kViewPadding - kBubblePadding);
+ }
+ } else if (show_keyword_hint) {
+ LayoutView(false, keyword_hint_view_, available_width, &location_bounds);
+ }
+
+ location_entry_view_->SetBounds(location_bounds);
+}
+
+void LocationBarView::Paint(gfx::Canvas* canvas) {
+ View::Paint(canvas);
+ // When used in the app launcher, don't draw a border, the LocationBarView has
+ // its own views::Border.
+ if (mode_ != APP_LAUNCHER) {
+ const SkBitmap* background =
+ mode_ == POPUP ?
+ kPopupBackground :
+ GetThemeProvider()->GetBitmapNamed(IDR_LOCATIONBG);
+
+ canvas->TileImageInt(*background, 0, 0, 0, 0, width(), height());
+ }
+ gfx::Rect bounds = GetLocalBounds(false);
+ int top_margin = TopMargin();
+ canvas->FillRectInt(GetColor(ToolbarModel::NONE, BACKGROUND), bounds.x(),
+ top_margin, bounds.width(),
+ std::max(height() - top_margin - kVertMargin, 0));
+}
+
+void LocationBarView::VisibleBoundsInRootChanged() {
+ location_entry_->ClosePopup();
+}
+
+#if defined(OS_WIN)
+bool LocationBarView::OnMousePressed(const views::MouseEvent& event) {
+ UINT msg;
+ if (event.IsLeftMouseButton()) {
+ msg = (event.GetFlags() & views::MouseEvent::EF_IS_DOUBLE_CLICK) ?
+ WM_LBUTTONDBLCLK : WM_LBUTTONDOWN;
+ } else if (event.IsMiddleMouseButton()) {
+ msg = (event.GetFlags() & views::MouseEvent::EF_IS_DOUBLE_CLICK) ?
+ WM_MBUTTONDBLCLK : WM_MBUTTONDOWN;
+ } else if (event.IsRightMouseButton()) {
+ msg = (event.GetFlags() & views::MouseEvent::EF_IS_DOUBLE_CLICK) ?
+ WM_RBUTTONDBLCLK : WM_RBUTTONDOWN;
+ } else {
+ NOTREACHED();
+ return false;
+ }
+ OnMouseEvent(event, msg);
+ return true;
+}
+
+bool LocationBarView::OnMouseDragged(const views::MouseEvent& event) {
+ OnMouseEvent(event, WM_MOUSEMOVE);
+ return true;
+}
+
+void LocationBarView::OnMouseReleased(const views::MouseEvent& event,
+ bool canceled) {
+ UINT msg;
+ if (canceled) {
+ msg = WM_CAPTURECHANGED;
+ } else if (event.IsLeftMouseButton()) {
+ msg = WM_LBUTTONUP;
+ } else if (event.IsMiddleMouseButton()) {
+ msg = WM_MBUTTONUP;
+ } else if (event.IsRightMouseButton()) {
+ msg = WM_RBUTTONUP;
+ } else {
+ NOTREACHED();
+ return;
+ }
+ OnMouseEvent(event, msg);
+}
+#endif
+
+void LocationBarView::OnAutocompleteAccept(
+ const GURL& url,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition,
+ const GURL& alternate_nav_url) {
+ if (!url.is_valid())
+ return;
+
+ location_input_ = UTF8ToWide(url.spec());
+ disposition_ = disposition;
+ transition_ = transition;
+
+ if (command_updater_) {
+ if (!alternate_nav_url.is_valid()) {
+ command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
+ return;
+ }
+
+ scoped_ptr<AlternateNavURLFetcher> fetcher(
+ new AlternateNavURLFetcher(alternate_nav_url));
+ // The AlternateNavURLFetcher will listen for the pending navigation
+ // notification that will be issued as a result of the "open URL." It
+ // will automatically install itself into that navigation controller.
+ command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);
+ if (fetcher->state() == AlternateNavURLFetcher::NOT_STARTED) {
+ // I'm not sure this should be reachable, but I'm not also sure enough
+ // that it shouldn't to stick in a NOTREACHED(). In any case, this is
+ // harmless; we can simply let the fetcher get deleted here and it will
+ // clean itself up properly.
+ } else {
+ fetcher.release(); // The navigation controller will delete the fetcher.
+ }
+ }
+}
+
+void LocationBarView::OnChanged() {
+ location_icon_view_->SetImage(
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ location_entry_->GetIcon()));
+ Layout();
+ SchedulePaint();
+}
+
+void LocationBarView::OnInputInProgress(bool in_progress) {
+ delegate_->OnInputInProgress(in_progress);
+}
+
+void LocationBarView::OnKillFocus() {
+}
+
+void LocationBarView::OnSetFocus() {
+ views::FocusManager* focus_manager = GetFocusManager();
+ if (!focus_manager) {
+ NOTREACHED();
+ return;
+ }
+ focus_manager->SetFocusedView(this);
+}
+
+SkBitmap LocationBarView::GetFavIcon() const {
+ DCHECK(delegate_);
+ DCHECK(delegate_->GetTabContents());
+ return delegate_->GetTabContents()->GetFavIcon();
+}
+
+std::wstring LocationBarView::GetTitle() const {
+ DCHECK(delegate_);
+ DCHECK(delegate_->GetTabContents());
+ return UTF16ToWideHack(delegate_->GetTabContents()->GetTitle());
+}
+
+int LocationBarView::TopMargin() const {
+ return std::min(kVertMargin, height());
+}
+
+int LocationBarView::AvailableWidth(int location_bar_width) {
+#if defined(OS_WIN)
+ // Use font_.GetStringWidth() instead of
+ // PosFromChar(location_entry_->GetTextLength()) because PosFromChar() is
+ // apparently buggy. In both LTR UI and RTL UI with left-to-right layout,
+ // PosFromChar(i) might return 0 when i is greater than 1.
+ return std::max(
+ location_bar_width - font_.GetStringWidth(location_entry_->GetText()), 0);
+#else
+ return location_bar_width - location_entry_->TextWidth();
+#endif
+}
+
+bool LocationBarView::UsePref(int pref_width, int available_width) {
+ return (pref_width + kViewPadding <= available_width);
+}
+
+void LocationBarView::LayoutView(bool leading,
+ views::View* view,
+ int available_width,
+ gfx::Rect* bounds) {
+ DCHECK(view && bounds);
+ gfx::Size view_size = view->GetPreferredSize();
+ if (!UsePref(view_size.width(), available_width))
+ view_size = view->GetMinimumSize();
+ if (view_size.width() + kViewPadding >= bounds->width()) {
+ view->SetVisible(false);
+ return;
+ }
+ if (leading) {
+ view->SetBounds(bounds->x(), bounds->y(), view_size.width(),
+ bounds->height());
+ bounds->Offset(view_size.width() + kViewPadding, 0);
+ } else {
+ view->SetBounds(bounds->right() - view_size.width(), bounds->y(),
+ view_size.width(), bounds->height());
+ }
+ bounds->set_width(bounds->width() - view_size.width() - kViewPadding);
+ view->SetVisible(true);
+}
+
+void LocationBarView::RefreshContentSettingViews() {
+ const TabContents* tab_contents = delegate_->GetTabContents();
+ for (ContentSettingViews::const_iterator i(content_setting_views_.begin());
+ i != content_setting_views_.end(); ++i) {
+ (*i)->UpdateFromTabContents(
+ model_->input_in_progress() ? NULL : tab_contents);
+ }
+}
+
+void LocationBarView::DeletePageActionViews() {
+ for (PageActionViews::const_iterator i(page_action_views_.begin());
+ i != page_action_views_.end(); ++i)
+ RemoveChildView(*i);
+ STLDeleteElements(&page_action_views_);
+}
+
+void LocationBarView::RefreshPageActionViews() {
+ if (mode_ != NORMAL)
+ return;
+
+ ExtensionsService* service = profile_->GetExtensionsService();
+ if (!service)
+ return;
+
+ std::map<ExtensionAction*, bool> old_visibility;
+ for (PageActionViews::const_iterator i(page_action_views_.begin());
+ i != page_action_views_.end(); ++i)
+ old_visibility[(*i)->image_view()->page_action()] = (*i)->IsVisible();
+
+ // Remember the previous visibility of the page actions so that we can
+ // notify when this changes.
+ std::vector<ExtensionAction*> page_actions;
+ for (size_t i = 0; i < service->extensions()->size(); ++i) {
+ if (service->extensions()->at(i)->page_action())
+ page_actions.push_back(service->extensions()->at(i)->page_action());
+ }
+
+ // On startup we sometimes haven't loaded any extensions. This makes sure
+ // we catch up when the extensions (and any page actions) load.
+ if (page_actions.size() != page_action_views_.size()) {
+ DeletePageActionViews(); // Delete the old views (if any).
+
+ page_action_views_.resize(page_actions.size());
+
+ for (size_t i = 0; i < page_actions.size(); ++i) {
+ page_action_views_[i] = new PageActionWithBadgeView(
+ new PageActionImageView(this, profile_, page_actions[i]));
+ page_action_views_[i]->SetVisible(false);
+ AddChildView(page_action_views_[i]);
+ }
+ }
+
+ TabContents* contents = delegate_->GetTabContents();
+ if (!page_action_views_.empty() && contents) {
+ GURL url = GURL(WideToUTF8(model_->GetText()));
+
+ for (PageActionViews::const_iterator i(page_action_views_.begin());
+ i != page_action_views_.end(); ++i) {
+ (*i)->UpdateVisibility(contents, url);
+
+ // Check if the visibility of the action changed and notify if it did.
+ ExtensionAction* action = (*i)->image_view()->page_action();
+ if (old_visibility.find(action) == old_visibility.end() ||
+ old_visibility[action] != (*i)->IsVisible()) {
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
+ Source<ExtensionAction>(action),
+ Details<TabContents>(contents));
+ }
+ }
+ }
+}
+
+#if defined(OS_WIN)
+void LocationBarView::OnMouseEvent(const views::MouseEvent& event, UINT msg) {
+ UINT flags = 0;
+ if (event.IsControlDown())
+ flags |= MK_CONTROL;
+ if (event.IsShiftDown())
+ flags |= MK_SHIFT;
+ if (event.IsLeftMouseButton())
+ flags |= MK_LBUTTON;
+ if (event.IsMiddleMouseButton())
+ flags |= MK_MBUTTON;
+ if (event.IsRightMouseButton())
+ flags |= MK_RBUTTON;
+
+ gfx::Point screen_point(event.location());
+ ConvertPointToScreen(this, &screen_point);
+ location_entry_->HandleExternalMsg(msg, flags, screen_point.ToPOINT());
+}
+#endif
+
+void LocationBarView::ShowFirstRunBubbleInternal(
+ FirstRun::BubbleType bubble_type) {
+#if defined(OS_WIN) // First run bubble doesn't make sense for Chrome OS.
+ // If the browser is no longer active, let's not show the info bubble, as this
+ // would make the browser the active window again.
+ if (!location_entry_view_ || !location_entry_view_->GetWidget()->IsActive())
+ return;
+
+ // Point at the start of the edit control; adjust to look as good as possible.
+ const int kXOffset = 1; // Text looks like it actually starts 1 px in.
+ const int kYOffset = -4; // Point into the omnibox, not just at its edge.
+ gfx::Point origin(location_entry_view_->bounds().x() + kXOffset,
+ y() + height() + kYOffset);
+ // If the UI layout is RTL, the coordinate system is not transformed and
+ // therefore we need to adjust the X coordinate so that bubble appears on the
+ // right hand side of the location bar.
+ if (UILayoutIsRightToLeft())
+ origin.set_x(width() - origin.x());
+ views::View::ConvertPointToScreen(this, &origin);
+ FirstRunBubble::Show(profile_, GetWindow(), gfx::Rect(origin, gfx::Size()),
+ bubble_type);
+#endif
+}
+
+bool LocationBarView::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
+ if (keyword_hint_view_->IsVisible() &&
+ views::FocusManager::IsTabTraversalKeyEvent(e)) {
+ // We want to receive tab key events when the hint is showing.
+ return true;
+ }
+
+#if defined(OS_WIN)
+ return location_entry_->SkipDefaultKeyEventProcessing(e);
+#else
+ // TODO(jcampan): We need to refactor the code of
+ // AutocompleteEditViewWin::SkipDefaultKeyEventProcessing into this class so
+ // it can be shared between Windows and Linux.
+ // For now, we just override back-space as it is the accelerator for back
+ // navigation.
+ if (e.GetKeyCode() == base::VKEY_BACK)
+ return true;
+ return false;
+#endif
+}
+
+bool LocationBarView::GetAccessibleRole(AccessibilityTypes::Role* role) {
+ DCHECK(role);
+
+ *role = AccessibilityTypes::ROLE_GROUPING;
+ return true;
+}
+
+
+void LocationBarView::WriteDragData(views::View* sender,
+ const gfx::Point& press_pt,
+ OSExchangeData* data) {
+ DCHECK(GetDragOperations(sender, press_pt) != DragDropTypes::DRAG_NONE);
+
+ TabContents* tab_contents = delegate_->GetTabContents();
+ DCHECK(tab_contents);
+ drag_utils::SetURLAndDragImage(tab_contents->GetURL(),
+ UTF16ToWideHack(tab_contents->GetTitle()),
+ tab_contents->GetFavIcon(), data);
+}
+
+int LocationBarView::GetDragOperations(views::View* sender,
+ const gfx::Point& p) {
+ DCHECK((sender == location_icon_view_) || (sender == ev_bubble_view_));
+ TabContents* tab_contents = delegate_->GetTabContents();
+ return (tab_contents && tab_contents->GetURL().is_valid() &&
+ !location_entry()->IsEditingOrEmpty()) ?
+ (DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK) :
+ DragDropTypes::DRAG_NONE;
+}
+
+bool LocationBarView::CanStartDrag(View* sender,
+ const gfx::Point& press_pt,
+ const gfx::Point& p) {
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// LocationBarView, LocationBar implementation:
+
+void LocationBarView::ShowFirstRunBubble(FirstRun::BubbleType bubble_type) {
+ // We wait 30 milliseconds to open. It allows less flicker.
+ Task* task = first_run_bubble_.NewRunnableMethod(
+ &LocationBarView::ShowFirstRunBubbleInternal, bubble_type);
+ MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 30);
+}
+
+std::wstring LocationBarView::GetInputString() const {
+ return location_input_;
+}
+
+WindowOpenDisposition LocationBarView::GetWindowOpenDisposition() const {
+ return disposition_;
+}
+
+PageTransition::Type LocationBarView::GetPageTransition() const {
+ return transition_;
+}
+
+void LocationBarView::AcceptInput() {
+ location_entry_->model()->AcceptInput(CURRENT_TAB, false);
+}
+
+void LocationBarView::AcceptInputWithDisposition(WindowOpenDisposition disp) {
+ location_entry_->model()->AcceptInput(disp, false);
+}
+
+void LocationBarView::FocusLocation(bool select_all) {
+ location_entry_->SetFocus();
+ if (select_all)
+ location_entry_->SelectAll(true);
+}
+
+void LocationBarView::FocusSearch() {
+ location_entry_->SetFocus();
+ location_entry_->SetForcedQuery();
+}
+
+void LocationBarView::SaveStateToContents(TabContents* contents) {
+ location_entry_->SaveStateToTab(contents);
+}
+
+void LocationBarView::Revert() {
+ location_entry_->RevertAll();
+}
+
+int LocationBarView::PageActionVisibleCount() {
+ int result = 0;
+ for (size_t i = 0; i < page_action_views_.size(); i++) {
+ if (page_action_views_[i]->IsVisible())
+ ++result;
+ }
+ return result;
+}
+
+ExtensionAction* LocationBarView::GetPageAction(size_t index) {
+ if (index < page_action_views_.size())
+ return page_action_views_[index]->image_view()->page_action();
+
+ NOTREACHED();
+ return NULL;
+}
+
+ExtensionAction* LocationBarView::GetVisiblePageAction(size_t index) {
+ size_t current = 0;
+ for (size_t i = 0; i < page_action_views_.size(); ++i) {
+ if (page_action_views_[i]->IsVisible()) {
+ if (current == index)
+ return page_action_views_[i]->image_view()->page_action();
+
+ ++current;
+ }
+ }
+
+ NOTREACHED();
+ return NULL;
+}
+
+void LocationBarView::TestPageActionPressed(size_t index) {
+ size_t current = 0;
+ for (size_t i = 0; i < page_action_views_.size(); ++i) {
+ if (page_action_views_[i]->IsVisible()) {
+ if (current == index) {
+ const int kLeftMouseButton = 1;
+ page_action_views_[i]->image_view()->ExecuteAction(kLeftMouseButton,
+ false); // inspect_with_devtools
+ return;
+ }
+ ++current;
+ }
+ }
+
+ NOTREACHED();
+}
diff --git a/chrome/browser/views/location_bar/location_bar_view.h b/chrome/browser/views/location_bar/location_bar_view.h
new file mode 100644
index 0000000..1f9c62b
--- /dev/null
+++ b/chrome/browser/views/location_bar/location_bar_view.h
@@ -0,0 +1,338 @@
+// 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_VIEWS_LOCATION_BAR_LOCATION_BAR_VIEW_H_
+#define CHROME_BROWSER_VIEWS_LOCATION_BAR_LOCATION_BAR_VIEW_H_
+
+#include <string>
+#include <vector>
+
+#include "base/task.h"
+#include "chrome/browser/autocomplete/autocomplete_edit.h"
+#include "chrome/browser/extensions/extension_context_menu_model.h"
+#include "chrome/browser/first_run.h"
+#include "chrome/browser/location_bar.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/toolbar_model.h"
+#include "chrome/browser/views/extensions/extension_popup.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "gfx/font.h"
+#include "gfx/rect.h"
+#include "views/controls/native/native_view_host.h"
+
+#if defined(OS_WIN)
+#include "chrome/browser/autocomplete/autocomplete_edit_view_win.h"
+#else
+#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
+#endif
+
+class Browser;
+class CommandUpdater;
+class ContentSettingImageView;
+class EVBubbleView;
+class ExtensionAction;
+class GURL;
+class KeywordHintView;
+class LocationIconView;
+class PageActionWithBadgeView;
+class Profile;
+class SelectedKeywordView;
+class StarView;
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// LocationBarView class
+//
+// The LocationBarView class is a View subclass that paints the background
+// of the URL bar strip and contains its content.
+//
+/////////////////////////////////////////////////////////////////////////////
+class LocationBarView : public LocationBar,
+ public LocationBarTesting,
+ public views::View,
+ public views::DragController,
+ public AutocompleteEditController {
+ public:
+ class Delegate {
+ public:
+ // Should return the current tab contents.
+ virtual TabContents* GetTabContents() = 0;
+
+ // Called by the location bar view when the user starts typing in the edit.
+ // This forces our security style to be UNKNOWN for the duration of the
+ // editing.
+ virtual void OnInputInProgress(bool in_progress) = 0;
+ };
+
+ enum ColorKind {
+ BACKGROUND = 0,
+ TEXT,
+ SELECTED_TEXT,
+ DEEMPHASIZED_TEXT,
+ SECURITY_TEXT,
+ };
+
+ // The modes reflect the different scenarios where a location bar can be used.
+ // The normal mode is the mode used in a regular browser window.
+ // In popup mode, the location bar view is read only and has a slightly
+ // different presentation (font size / color).
+ // In app launcher mode, the location bar is empty and no security states or
+ // page/browser actions are displayed.
+ enum Mode {
+ NORMAL = 0,
+ POPUP,
+ APP_LAUNCHER
+ };
+
+ LocationBarView(Profile* profile,
+ CommandUpdater* command_updater,
+ ToolbarModel* model,
+ Delegate* delegate,
+ Mode mode);
+ virtual ~LocationBarView();
+
+ void Init();
+
+ // Returns whether this instance has been initialized by callin Init. Init can
+ // only be called when the receiving instance is attached to a view container.
+ bool IsInitialized() const;
+
+ // Returns the appropriate color for the desired kind, based on the user's
+ // system theme.
+ static SkColor GetColor(ToolbarModel::SecurityLevel security_level,
+ ColorKind kind);
+
+ // Updates the location bar. We also reset the bar's permanent text and
+ // security style, and, if |tab_for_state_restoring| is non-NULL, also restore
+ // saved state that the tab holds.
+ void Update(const TabContents* tab_for_state_restoring);
+
+ void SetProfile(Profile* profile);
+ Profile* profile() const { return profile_; }
+
+ // Returns the current TabContents.
+ TabContents* GetTabContents() const;
+
+ // Sets |preview_enabled| for the PageAction View associated with this
+ // |page_action|. If |preview_enabled| is true, the view will display the
+ // PageActions icon even though it has not been activated by the extension.
+ // This is used by the ExtensionInstalledBubble to preview what the icon
+ // will look like for the user upon installation of the extension.
+ void SetPreviewEnabledPageAction(ExtensionAction *page_action,
+ bool preview_enabled);
+
+ // Retrieves the PageAction View which is associated with |page_action|.
+ views::View* GetPageActionView(ExtensionAction* page_action);
+
+ // Toggles the star on or off.
+ void SetStarToggled(bool on);
+
+ // Shows the bookmark bubble.
+ void ShowStarBubble(const GURL& url, bool newly_bookmarked);
+
+ // Sizing functions
+ virtual gfx::Size GetPreferredSize();
+
+ // Layout and Painting functions
+ virtual void Layout();
+ virtual void Paint(gfx::Canvas* canvas);
+
+ // No focus border for the location bar, the caret is enough.
+ virtual void PaintFocusBorder(gfx::Canvas* canvas) { }
+
+ // Called when any ancestor changes its size, asks the AutocompleteEditModel
+ // to close its popup.
+ virtual void VisibleBoundsInRootChanged();
+
+#if defined(OS_WIN)
+ // Event Handlers
+ virtual bool OnMousePressed(const views::MouseEvent& event);
+ virtual bool OnMouseDragged(const views::MouseEvent& event);
+ virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
+#endif
+
+ // AutocompleteEditController
+ virtual void OnAutocompleteAccept(const GURL& url,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition,
+ const GURL& alternate_nav_url);
+ virtual void OnChanged();
+ virtual void OnInputInProgress(bool in_progress);
+ virtual void OnKillFocus();
+ virtual void OnSetFocus();
+ virtual SkBitmap GetFavIcon() const;
+ virtual std::wstring GetTitle() const;
+
+ // Overridden from views::View:
+ virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e);
+ virtual bool GetAccessibleRole(AccessibilityTypes::Role* role);
+
+ // Overridden from views::DragController:
+ virtual void WriteDragData(View* sender,
+ const gfx::Point& press_pt,
+ OSExchangeData* data);
+ virtual int GetDragOperations(View* sender, const gfx::Point& p);
+ virtual bool CanStartDrag(View* sender,
+ const gfx::Point& press_pt,
+ const gfx::Point& p);
+
+ // Overridden from LocationBar:
+ virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type);
+ virtual std::wstring GetInputString() const;
+ virtual WindowOpenDisposition GetWindowOpenDisposition() const;
+ virtual PageTransition::Type GetPageTransition() const;
+ virtual void AcceptInput();
+ virtual void AcceptInputWithDisposition(WindowOpenDisposition);
+ virtual void FocusLocation(bool select_all);
+ virtual void FocusSearch();
+ virtual void UpdateContentSettingsIcons();
+ virtual void UpdatePageActions();
+ virtual void InvalidatePageActions();
+ virtual void SaveStateToContents(TabContents* contents);
+ virtual void Revert();
+ virtual const AutocompleteEditView* location_entry() const {
+ return location_entry_.get();
+ }
+ virtual AutocompleteEditView* location_entry() {
+ return location_entry_.get();
+ }
+ virtual LocationBarTesting* GetLocationBarForTesting() { return this; }
+
+ // Overridden from LocationBarTesting:
+ virtual int PageActionCount() { return page_action_views_.size(); }
+ virtual int PageActionVisibleCount();
+ virtual ExtensionAction* GetPageAction(size_t index);
+ virtual ExtensionAction* GetVisiblePageAction(size_t index);
+ virtual void TestPageActionPressed(size_t index);
+
+ static const int kVertMargin;
+
+ protected:
+ void Focus();
+
+ private:
+ typedef std::vector<ContentSettingImageView*> ContentSettingViews;
+
+ friend class PageActionImageView;
+ friend class PageActionWithBadgeView;
+ typedef std::vector<PageActionWithBadgeView*> PageActionViews;
+
+ // Returns the height in pixels of the margin at the top of the bar.
+ int TopMargin() const;
+
+ // Returns the amount of horizontal space (in pixels) out of
+ // |location_bar_width| that is not taken up by the actual text in
+ // location_entry_.
+ int AvailableWidth(int location_bar_width);
+
+ // Returns whether the |available_width| is large enough to contain a view
+ // with preferred width |pref_width| at its preferred size. If this returns
+ // true, the preferred size should be used. If this returns false, the
+ // minimum size of the view should be used.
+ bool UsePref(int pref_width, int available_width);
+
+ // If View fits in the specified region, it is made visible and the
+ // bounds are adjusted appropriately. If the View does not fit, it is
+ // made invisible.
+ void LayoutView(bool leading, views::View* view, int available_width,
+ gfx::Rect* bounds);
+
+ // Update the visibility state of the Content Blocked icons to reflect what is
+ // actually blocked on the current page.
+ void RefreshContentSettingViews();
+
+ // Delete all page action views that we have created.
+ void DeletePageActionViews();
+
+ // Update the views for the Page Actions, to reflect state changes for
+ // PageActions.
+ void RefreshPageActionViews();
+
+ // Sets the visibility of view to new_vis.
+ void ToggleVisibility(bool new_vis, views::View* view);
+
+#if defined(OS_WIN)
+ // Helper for the Mouse event handlers that does all the real work.
+ void OnMouseEvent(const views::MouseEvent& event, UINT msg);
+#endif
+
+ // Helper to show the first run info bubble.
+ void ShowFirstRunBubbleInternal(FirstRun::BubbleType bubble_type);
+
+ // Current browser. Not owned by us.
+ Browser* browser_;
+
+ // Current profile. Not owned by us.
+ Profile* profile_;
+
+ // The Autocomplete Edit field.
+#if defined(OS_WIN)
+ scoped_ptr<AutocompleteEditViewWin> location_entry_;
+#else
+ scoped_ptr<AutocompleteEditViewGtk> location_entry_;
+#endif
+
+ // The CommandUpdater for the Browser object that corresponds to this View.
+ CommandUpdater* command_updater_;
+
+ // The model.
+ ToolbarModel* model_;
+
+ // Our delegate.
+ Delegate* delegate_;
+
+ // This is the string of text from the autocompletion session that the user
+ // entered or selected.
+ std::wstring location_input_;
+
+ // The user's desired disposition for how their input should be opened
+ WindowOpenDisposition disposition_;
+
+ // The transition type to use for the navigation
+ PageTransition::Type transition_;
+
+ // Font used by edit and some of the hints.
+ gfx::Font font_;
+
+ // An icon to the left of the edit field.
+ LocationIconView* location_icon_view_;
+
+ // A bubble displayed for EV HTTPS sites.
+ EVBubbleView* ev_bubble_view_;
+
+ // Location_entry view wrapper
+ views::NativeViewHost* location_entry_view_;
+
+ // The following views are used to provide hints and remind the user as to
+ // what is going in the edit. They are all added a children of the
+ // LocationBarView. At most one is visible at a time. Preference is
+ // given to the keyword_view_, then hint_view_.
+ // These autocollapse when the edit needs the room.
+
+ // Shown if the user has selected a keyword.
+ SelectedKeywordView* selected_keyword_view_;
+
+ // Shown if the selected url has a corresponding keyword.
+ KeywordHintView* keyword_hint_view_;
+
+ // The content setting views.
+ ContentSettingViews content_setting_views_;
+
+ // The page action icon views.
+ PageActionViews page_action_views_;
+
+ // The star.
+ StarView* star_view_;
+
+ // The mode that dictates how the bar shows.
+ Mode mode_;
+
+ // Used schedule a task for the first run info bubble.
+ ScopedRunnableMethodFactory<LocationBarView> first_run_bubble_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(LocationBarView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_LOCATION_BAR_VIEW_H_
diff --git a/chrome/browser/views/location_bar/location_icon_view.cc b/chrome/browser/views/location_bar/location_icon_view.cc
new file mode 100644
index 0000000..b862559
--- /dev/null
+++ b/chrome/browser/views/location_bar/location_icon_view.cc
@@ -0,0 +1,23 @@
+// 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/views/location_bar/location_icon_view.h"
+
+LocationIconView::LocationIconView(const LocationBarView* location_bar)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(click_handler_(this, location_bar)) {
+}
+
+LocationIconView::~LocationIconView() {
+}
+
+bool LocationIconView::OnMousePressed(const views::MouseEvent& event) {
+ // We want to show the dialog on mouse release; that is the standard behavior
+ // for buttons.
+ return true;
+}
+
+void LocationIconView::OnMouseReleased(const views::MouseEvent& event,
+ bool canceled) {
+ click_handler_.OnMouseReleased(event, canceled);
+}
diff --git a/chrome/browser/views/location_bar/location_icon_view.h b/chrome/browser/views/location_bar/location_icon_view.h
new file mode 100644
index 0000000..dd2c3e5
--- /dev/null
+++ b/chrome/browser/views/location_bar/location_icon_view.h
@@ -0,0 +1,34 @@
+// 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_VIEWS_LOCATION_BAR_LOCATION_ICON_VIEW_H_
+#define CHROME_BROWSER_VIEWS_LOCATION_BAR_LOCATION_ICON_VIEW_H_
+
+#include "chrome/browser/views/location_bar/click_handler.h"
+#include "views/controls/image_view.h"
+
+class LocationBarView;
+namespace views {
+class MouseEvent;
+}
+
+// LocationIconView is used to display an icon to the left of the edit field.
+// This shows the user's current action while editing, the page security
+// status on https pages, or a globe for other URLs.
+class LocationIconView : public views::ImageView {
+ public:
+ explicit LocationIconView(const LocationBarView* location_bar);
+ virtual ~LocationIconView();
+
+ // Overridden from view.
+ virtual bool OnMousePressed(const views::MouseEvent& event);
+ virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
+
+ private:
+ ClickHandler click_handler_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(LocationIconView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_LOCATION_ICON_VIEW_H_
diff --git a/chrome/browser/views/location_bar/page_action_image_view.cc b/chrome/browser/views/location_bar/page_action_image_view.cc
new file mode 100644
index 0000000..6ee90a3
--- /dev/null
+++ b/chrome/browser/views/location_bar/page_action_image_view.cc
@@ -0,0 +1,221 @@
+// 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/views/location_bar/page_action_image_view.h"
+
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/extensions/extension_browser_event_router.h"
+#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/views/location_bar/location_bar_view.h"
+#include "chrome/common/platform_util.h"
+#include "views/controls/menu/menu_2.h"
+
+PageActionImageView::PageActionImageView(LocationBarView* owner,
+ Profile* profile,
+ ExtensionAction* page_action)
+ : owner_(owner),
+ profile_(profile),
+ page_action_(page_action),
+ ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)),
+ current_tab_id_(-1),
+ preview_enabled_(false),
+ popup_(NULL) {
+ Extension* extension = profile->GetExtensionsService()->GetExtensionById(
+ page_action->extension_id(), false);
+ DCHECK(extension);
+
+ // Load all the icons declared in the manifest. This is the contents of the
+ // icons array, plus the default_icon property, if any.
+ std::vector<std::string> icon_paths(*page_action->icon_paths());
+ if (!page_action_->default_icon_path().empty())
+ icon_paths.push_back(page_action_->default_icon_path());
+
+ for (std::vector<std::string>::iterator iter = icon_paths.begin();
+ iter != icon_paths.end(); ++iter) {
+ tracker_.LoadImage(extension, extension->GetResource(*iter),
+ gfx::Size(Extension::kPageActionIconMaxSize,
+ Extension::kPageActionIconMaxSize),
+ ImageLoadingTracker::DONT_CACHE);
+ }
+}
+
+PageActionImageView::~PageActionImageView() {
+ if (popup_)
+ HidePopup();
+}
+
+void PageActionImageView::ExecuteAction(int button,
+ bool inspect_with_devtools) {
+ if (current_tab_id_ < 0) {
+ NOTREACHED() << "No current tab.";
+ return;
+ }
+
+ if (page_action_->HasPopup(current_tab_id_)) {
+ // In tests, GetLastActive could return NULL, so we need to have
+ // a fallback.
+ // TODO(erikkay): Find a better way to get the Browser that this
+ // button is in.
+ Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
+ if (!browser)
+ browser = BrowserList::FindBrowserWithProfile(profile_);
+ DCHECK(browser);
+
+ bool popup_showing = popup_ != NULL;
+
+ // Always hide the current popup. Only one popup at a time.
+ HidePopup();
+
+ // If we were already showing, then treat this click as a dismiss.
+ if (popup_showing)
+ return;
+
+ gfx::Rect screen_bounds(GetImageBounds());
+ gfx::Point origin(screen_bounds.origin());
+ View::ConvertPointToScreen(this, &origin);
+ screen_bounds.set_origin(origin);
+
+ popup_ = ExtensionPopup::Show(
+ page_action_->GetPopupUrl(current_tab_id_),
+ browser,
+ browser->profile(),
+ browser->window()->GetNativeHandle(),
+ screen_bounds,
+ BubbleBorder::TOP_RIGHT,
+ true, // Activate the popup window.
+ inspect_with_devtools,
+ ExtensionPopup::BUBBLE_CHROME,
+ this); // ExtensionPopup::Observer
+ } else {
+ ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
+ profile_, page_action_->extension_id(), page_action_->id(),
+ current_tab_id_, current_url_.spec(), button);
+ }
+}
+
+bool PageActionImageView::OnMousePressed(const views::MouseEvent& event) {
+ // We want to show the bubble on mouse release; that is the standard behavior
+ // for buttons. (Also, triggering on mouse press causes bugs like
+ // http://crbug.com/33155.)
+ return true;
+}
+
+void PageActionImageView::OnMouseReleased(const views::MouseEvent& event,
+ bool canceled) {
+ if (canceled || !HitTest(event.location()))
+ return;
+
+ int button = -1;
+ if (event.IsLeftMouseButton()) {
+ button = 1;
+ } else if (event.IsMiddleMouseButton()) {
+ button = 2;
+ } else if (event.IsRightMouseButton()) {
+ // Get the top left point of this button in screen coordinates.
+ gfx::Point menu_origin;
+ ConvertPointToScreen(this, &menu_origin);
+
+ // Make the menu appear below the button.
+ menu_origin.Offset(0, height());
+
+ Extension* extension = profile_->GetExtensionsService()->GetExtensionById(
+ page_action()->extension_id(), false);
+ Browser* browser = BrowserView::GetBrowserViewForNativeWindow(
+ platform_util::GetTopLevel(GetWidget()->GetNativeView()))->browser();
+ context_menu_contents_ =
+ new ExtensionContextMenuModel(extension, browser, this);
+ context_menu_menu_.reset(new views::Menu2(context_menu_contents_.get()));
+ context_menu_menu_->RunContextMenuAt(menu_origin);
+ return;
+ }
+
+ ExecuteAction(button, false); // inspect_with_devtools
+}
+
+void PageActionImageView::OnImageLoaded(
+ SkBitmap* image, ExtensionResource resource, int index) {
+ // We loaded icons()->size() icons, plus one extra if the page action had
+ // a default icon.
+ int total_icons = static_cast<int>(page_action_->icon_paths()->size());
+ if (!page_action_->default_icon_path().empty())
+ total_icons++;
+ DCHECK(index < total_icons);
+
+ // Map the index of the loaded image back to its name. If we ever get an
+ // index greater than the number of icons, it must be the default icon.
+ if (image) {
+ if (index < static_cast<int>(page_action_->icon_paths()->size()))
+ page_action_icons_[page_action_->icon_paths()->at(index)] = *image;
+ else
+ page_action_icons_[page_action_->default_icon_path()] = *image;
+ }
+
+ owner_->UpdatePageActions();
+}
+
+void PageActionImageView::UpdateVisibility(TabContents* contents,
+ const GURL& url) {
+ // Save this off so we can pass it back to the extension when the action gets
+ // executed. See PageActionImageView::OnMousePressed.
+ current_tab_id_ = ExtensionTabUtil::GetTabId(contents);
+ current_url_ = url;
+
+ bool visible =
+ preview_enabled_ || page_action_->GetIsVisible(current_tab_id_);
+ if (visible) {
+ // Set the tooltip.
+ tooltip_ = page_action_->GetTitle(current_tab_id_);
+ SetTooltipText(UTF8ToWide(tooltip_));
+
+ // Set the image.
+ // It can come from three places. In descending order of priority:
+ // - The developer can set it dynamically by path or bitmap. It will be in
+ // page_action_->GetIcon().
+ // - The developer can set it dynamically by index. It will be in
+ // page_action_->GetIconIndex().
+ // - It can be set in the manifest by path. It will be in page_action_->
+ // default_icon_path().
+
+ // First look for a dynamically set bitmap.
+ SkBitmap icon = page_action_->GetIcon(current_tab_id_);
+ if (icon.isNull()) {
+ int icon_index = page_action_->GetIconIndex(current_tab_id_);
+ std::string icon_path;
+ if (icon_index >= 0)
+ icon_path = page_action_->icon_paths()->at(icon_index);
+ else
+ icon_path = page_action_->default_icon_path();
+
+ if (!icon_path.empty()) {
+ PageActionMap::iterator iter = page_action_icons_.find(icon_path);
+ if (iter != page_action_icons_.end())
+ icon = iter->second;
+ }
+ }
+
+ if (!icon.isNull())
+ SetImage(&icon);
+ }
+ SetVisible(visible);
+}
+
+void PageActionImageView::InspectPopup(ExtensionAction* action) {
+ ExecuteAction(1, // left-click
+ true); // inspect_with_devtools
+}
+
+void PageActionImageView::ExtensionPopupClosed(ExtensionPopup* popup) {
+ DCHECK_EQ(popup_, popup);
+ // ExtensionPopup is ref-counted, so we don't need to delete it.
+ popup_ = NULL;
+}
+
+void PageActionImageView::HidePopup() {
+ if (popup_)
+ popup_->Close();
+}
+
+
diff --git a/chrome/browser/views/location_bar/page_action_image_view.h b/chrome/browser/views/location_bar/page_action_image_view.h
new file mode 100644
index 0000000..3c107e1
--- /dev/null
+++ b/chrome/browser/views/location_bar/page_action_image_view.h
@@ -0,0 +1,109 @@
+// 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_VIEWS_LOCATION_BAR_PAGE_ACTION_IMAGE_VIEW_H_
+#define CHROME_BROWSER_VIEWS_LOCATION_BAR_PAGE_ACTION_IMAGE_VIEW_H_
+
+#include <map>
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/extensions/image_loading_tracker.h"
+#include "chrome/browser/extensions/extension_context_menu_model.h"
+#include "chrome/browser/views/extensions/extension_popup.h"
+#include "views/controls/image_view.h"
+
+class LocationBarView;
+namespace views {
+class Menu2;
+};
+
+// PageActionImageView is used by the LocationBarView to display the icon for a
+// given PageAction and notify the extension when the icon is clicked.
+class PageActionImageView : public views::ImageView,
+ public ImageLoadingTracker::Observer,
+ public ExtensionContextMenuModel::PopupDelegate,
+ public ExtensionPopup::Observer {
+ public:
+ PageActionImageView(LocationBarView* owner,
+ Profile* profile,
+ ExtensionAction* page_action);
+ virtual ~PageActionImageView();
+
+ ExtensionAction* page_action() { return page_action_; }
+
+ int current_tab_id() { return current_tab_id_; }
+
+ void set_preview_enabled(bool preview_enabled) {
+ preview_enabled_ = preview_enabled;
+ }
+
+ // Overridden from view.
+ virtual bool OnMousePressed(const views::MouseEvent& event);
+ virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
+
+ // Overridden from ImageLoadingTracker.
+ virtual void OnImageLoaded(
+ SkBitmap* image, ExtensionResource resource, int index);
+
+ // Overridden from ExtensionContextMenuModelModel::Delegate
+ virtual void InspectPopup(ExtensionAction* action);
+
+ // Overridden from ExtensionPopup::Observer
+ virtual void ExtensionPopupClosed(ExtensionPopup* popup);
+
+ // Called to notify the PageAction that it should determine whether to be
+ // visible or hidden. |contents| is the TabContents that is active, |url| is
+ // the current page URL.
+ void UpdateVisibility(TabContents* contents, const GURL& url);
+
+ // Either notify listeners or show a popup depending on the page action.
+ void ExecuteAction(int button, bool inspect_with_devtools);
+
+ private:
+ // Hides the active popup, if there is one.
+ void HidePopup();
+
+ // The location bar view that owns us.
+ LocationBarView* owner_;
+
+ // The current profile (not owned by us).
+ Profile* profile_;
+
+ // The PageAction that this view represents. The PageAction is not owned by
+ // us, it resides in the extension of this particular profile.
+ ExtensionAction* page_action_;
+
+ // A cache of bitmaps the page actions might need to show, mapped by path.
+ typedef std::map<std::string, SkBitmap> PageActionMap;
+ PageActionMap page_action_icons_;
+
+ // The context menu for this page action.
+ scoped_refptr<ExtensionContextMenuModel> context_menu_contents_;
+ scoped_ptr<views::Menu2> context_menu_menu_;
+
+ // The object that is waiting for the image loading to complete
+ // asynchronously.
+ ImageLoadingTracker tracker_;
+
+ // The tab id we are currently showing the icon for.
+ int current_tab_id_;
+
+ // The URL we are currently showing the icon for.
+ GURL current_url_;
+
+ // The string to show for a tooltip;
+ std::string tooltip_;
+
+ // This is used for post-install visual feedback. The page_action icon is
+ // briefly shown even if it hasn't been enabled by its extension.
+ bool preview_enabled_;
+
+ // The current popup and the button it came from. NULL if no popup.
+ ExtensionPopup* popup_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(PageActionImageView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_PAGE_ACTION_IMAGE_VIEW_H_
diff --git a/chrome/browser/views/location_bar/page_action_with_badge_view.cc b/chrome/browser/views/location_bar/page_action_with_badge_view.cc
new file mode 100644
index 0000000..6d890f9
--- /dev/null
+++ b/chrome/browser/views/location_bar/page_action_with_badge_view.cc
@@ -0,0 +1,35 @@
+// 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/views/location_bar/page_action_with_badge_view.h"
+
+#include "chrome/browser/views/location_bar/page_action_image_view.h"
+#include "chrome/common/extensions/extension.h"
+
+PageActionWithBadgeView::PageActionWithBadgeView(
+ PageActionImageView* image_view) {
+ image_view_ = image_view;
+ AddChildView(image_view_);
+}
+
+gfx::Size PageActionWithBadgeView::GetPreferredSize() {
+ return gfx::Size(Extension::kPageActionIconMaxSize,
+ Extension::kPageActionIconMaxSize);
+}
+
+void PageActionWithBadgeView::Layout() {
+ // We have 25 pixels of vertical space in the Omnibox to play with, so even
+ // sized icons (such as 16x16) have either a 5 or a 4 pixel whitespace
+ // (padding) above and below. It looks better to have the extra pixel above
+ // the icon than below it, so we add a pixel. http://crbug.com/25708.
+ const SkBitmap& image = image_view()->GetImage();
+ int y = (image.height() + 1) % 2; // Even numbers: 1px padding. Odd: 0px.
+ image_view_->SetBounds(0, y, width(), height());
+}
+
+void PageActionWithBadgeView::UpdateVisibility(TabContents* contents,
+ const GURL& url) {
+ image_view_->UpdateVisibility(contents, url);
+ SetVisible(image_view_->IsVisible());
+}
diff --git a/chrome/browser/views/location_bar/page_action_with_badge_view.h b/chrome/browser/views/location_bar/page_action_with_badge_view.h
new file mode 100644
index 0000000..2df76bb
--- /dev/null
+++ b/chrome/browser/views/location_bar/page_action_with_badge_view.h
@@ -0,0 +1,35 @@
+// 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_VIEWS_LOCATION_BAR_PAGE_ACTION_WITH_BADGE_VIEW_H_
+#define CHROME_BROWSER_VIEWS_LOCATION_BAR_PAGE_ACTION_WITH_BADGE_VIEW_H_
+
+#include "gfx/size.h"
+#include "views/view.h"
+
+class GURL;
+class PageActionImageView;
+class TabContents;
+
+// A container for the PageActionImageView plus its badge.
+class PageActionWithBadgeView : public views::View {
+ public:
+ explicit PageActionWithBadgeView(PageActionImageView* image_view);
+
+ PageActionImageView* image_view() { return image_view_; }
+
+ virtual gfx::Size GetPreferredSize();
+
+ void UpdateVisibility(TabContents* contents, const GURL& url);
+
+ private:
+ virtual void Layout();
+
+ // The button this view contains.
+ PageActionImageView* image_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(PageActionWithBadgeView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_PAGE_ACTION_WITH_BADGE_VIEW_H_
diff --git a/chrome/browser/views/location_bar/selected_keyword_view.cc b/chrome/browser/views/location_bar/selected_keyword_view.cc
new file mode 100644
index 0000000..47779bc
--- /dev/null
+++ b/chrome/browser/views/location_bar/selected_keyword_view.cc
@@ -0,0 +1,84 @@
+// 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/views/location_bar/selected_keyword_view.h"
+
+#include "app/l10n_util.h"
+#include "base/i18n/rtl.h"
+#include "base/logging.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/views/location_bar/keyword_hint_view.h"
+#include "grit/generated_resources.h"
+
+SelectedKeywordView::SelectedKeywordView(const int background_images[],
+ int contained_image,
+ const SkColor& color,
+ Profile* profile)
+ : IconLabelBubbleView(background_images, contained_image, color),
+ profile_(profile) {
+ full_label_.SetVisible(false);
+ partial_label_.SetVisible(false);
+}
+
+SelectedKeywordView::~SelectedKeywordView() {
+}
+
+void SelectedKeywordView::SetFont(const gfx::Font& font) {
+ IconLabelBubbleView::SetFont(font);
+ full_label_.SetFont(font);
+ partial_label_.SetFont(font);
+}
+
+gfx::Size SelectedKeywordView::GetPreferredSize() {
+ gfx::Size size(GetNonLabelSize());
+ size.Enlarge(full_label_.GetPreferredSize().width(), 0);
+ return size;
+}
+
+gfx::Size SelectedKeywordView::GetMinimumSize() {
+ gfx::Size size(GetNonLabelSize());
+ size.Enlarge(partial_label_.GetMinimumSize().width(), 0);
+ return size;
+}
+
+void SelectedKeywordView::Layout() {
+ SetLabel((width() == GetPreferredSize().width()) ?
+ full_label_.GetText() : partial_label_.GetText());
+ IconLabelBubbleView::Layout();
+}
+
+void SelectedKeywordView::SetKeyword(const std::wstring& keyword) {
+ keyword_ = keyword;
+ if (keyword.empty())
+ return;
+ DCHECK(profile_);
+ if (!profile_->GetTemplateURLModel())
+ return;
+
+ const std::wstring short_name =
+ KeywordHintView::GetKeywordName(profile_, keyword);
+ full_label_.SetText(l10n_util::GetStringF(IDS_OMNIBOX_KEYWORD_TEXT,
+ short_name));
+ const std::wstring min_string = CalculateMinString(short_name);
+ partial_label_.SetText(min_string.empty() ?
+ full_label_.GetText() :
+ l10n_util::GetStringF(IDS_OMNIBOX_KEYWORD_TEXT, min_string));
+}
+
+std::wstring SelectedKeywordView::CalculateMinString(
+ const std::wstring& description) {
+ // Chop at the first '.' or whitespace.
+ const size_t dot_index = description.find(L'.');
+ const size_t ws_index = description.find_first_of(kWhitespaceWide);
+ size_t chop_index = std::min(dot_index, ws_index);
+ std::wstring min_string;
+ if (chop_index == std::wstring::npos) {
+ // No dot or whitespace, truncate to at most 3 chars.
+ min_string = l10n_util::TruncateString(description, 3);
+ } else {
+ min_string = description.substr(0, chop_index);
+ }
+ base::i18n::AdjustStringForLocaleDirection(min_string, &min_string);
+ return min_string;
+}
diff --git a/chrome/browser/views/location_bar/selected_keyword_view.h b/chrome/browser/views/location_bar/selected_keyword_view.h
new file mode 100644
index 0000000..8a3afbf
--- /dev/null
+++ b/chrome/browser/views/location_bar/selected_keyword_view.h
@@ -0,0 +1,61 @@
+// 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_VIEWS_LOCATION_BAR_SELECTED_KEYWORD_VIEW_H_
+#define CHROME_BROWSER_VIEWS_LOCATION_BAR_SELECTED_KEYWORD_VIEW_H_
+
+#include <string>
+
+#include "chrome/browser/views/location_bar/icon_label_bubble_view.h"
+#include "views/controls/label.h"
+
+class Profile;
+namespace gfx {
+class Font;
+class Size;
+}
+
+// SelectedKeywordView displays the tab-to-search UI in the location bar view.
+class SelectedKeywordView : public IconLabelBubbleView {
+ public:
+ SelectedKeywordView(const int background_images[],
+ int contained_image,
+ const SkColor& color,
+ Profile* profile);
+ virtual ~SelectedKeywordView();
+
+ void SetFont(const gfx::Font& font);
+
+ virtual gfx::Size GetPreferredSize();
+ virtual gfx::Size GetMinimumSize();
+ virtual void Layout();
+
+ // The current keyword, or an empty string if no keyword is displayed.
+ void SetKeyword(const std::wstring& keyword);
+ std::wstring keyword() const { return keyword_; }
+
+ void set_profile(Profile* profile) { profile_ = profile; }
+
+ private:
+ // Returns the truncated version of description to use.
+ std::wstring CalculateMinString(const std::wstring& description);
+
+ // The keyword we're showing. If empty, no keyword is selected.
+ // NOTE: we don't cache the TemplateURL as it is possible for it to get
+ // deleted out from under us.
+ std::wstring keyword_;
+
+ // These labels are never visible. They are used to size the view. One
+ // label contains the complete description of the keyword, the second
+ // contains a truncated version of the description, for if there is not
+ // enough room to display the complete description.
+ views::Label full_label_;
+ views::Label partial_label_;
+
+ Profile* profile_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SelectedKeywordView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_SELECTED_KEYWORD_VIEW_H_
diff --git a/chrome/browser/views/location_bar/star_view.cc b/chrome/browser/views/location_bar/star_view.cc
new file mode 100644
index 0000000..30c7888
--- /dev/null
+++ b/chrome/browser/views/location_bar/star_view.cc
@@ -0,0 +1,58 @@
+// 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/views/location_bar/star_view.h"
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/command_updater.h"
+#include "chrome/browser/view_ids.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+
+StarView::StarView(CommandUpdater* command_updater)
+ : command_updater_(command_updater) {
+ SetID(VIEW_ID_STAR_BUTTON);
+ SetToggled(false);
+}
+
+StarView::~StarView() {
+}
+
+void StarView::SetToggled(bool on) {
+ SetTooltipText(l10n_util::GetString(
+ on ? IDS_TOOLTIP_STARRED : IDS_TOOLTIP_STAR));
+ // Since StarView is an ImageView, the SetTooltipText changes the accessible
+ // name. To keep the accessible name unchanged, we need to set the accessible
+ // name right after we modify the tooltip text for this view.
+ SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_STAR));
+ SetImage(ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ on ? IDR_OMNIBOX_STAR_LIT : IDR_OMNIBOX_STAR));
+}
+
+bool StarView::GetAccessibleRole(AccessibilityTypes::Role* role) {
+ *role = AccessibilityTypes::ROLE_PUSHBUTTON;
+ return true;
+}
+
+bool StarView::OnMousePressed(const views::MouseEvent& event) {
+ // We want to show the bubble on mouse release; that is the standard behavior
+ // for buttons.
+ return true;
+}
+
+void StarView::OnMouseReleased(const views::MouseEvent& event, bool canceled) {
+ if (!canceled && HitTest(event.location()))
+ command_updater_->ExecuteCommand(IDC_BOOKMARK_PAGE);
+}
+
+void StarView::InfoBubbleClosing(InfoBubble* info_bubble,
+ bool closed_by_escape) {
+}
+
+bool StarView::CloseOnEscape() {
+ return true;
+}
+
diff --git a/chrome/browser/views/location_bar/star_view.h b/chrome/browser/views/location_bar/star_view.h
new file mode 100644
index 0000000..f5aa62c
--- /dev/null
+++ b/chrome/browser/views/location_bar/star_view.h
@@ -0,0 +1,43 @@
+// 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_VIEWS_LOCATION_BAR_STAR_VIEW_H_
+#define CHROME_BROWSER_VIEWS_LOCATION_BAR_STAR_VIEW_H_
+
+#include "chrome/browser/views/info_bubble.h"
+#include "views/controls/image_view.h"
+
+class CommandUpdater;
+class InfoBubble;
+
+namespace views {
+class MouseEvent;
+}
+
+class StarView : public views::ImageView, public InfoBubbleDelegate {
+ public:
+ explicit StarView(CommandUpdater* command_updater);
+ virtual ~StarView();
+
+ // Toggles the star on or off.
+ void SetToggled(bool on);
+
+ private:
+ // views::ImageView overrides:
+ virtual bool GetAccessibleRole(AccessibilityTypes::Role* role);
+ virtual bool OnMousePressed(const views::MouseEvent& event);
+ virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
+
+ // InfoBubbleDelegate overrides:
+ virtual void InfoBubbleClosing(InfoBubble* info_bubble,
+ bool closed_by_escape);
+ virtual bool CloseOnEscape();
+
+ // The CommandUpdater for the Browser object that owns the location bar.
+ CommandUpdater* command_updater_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StarView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_STAR_VIEW_H_