172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/compiler_specific.h"
8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/utf_string_conversions.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/instant/instant_confirm_dialog.h"
124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/instant/promo_counter.h"
1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/views/autocomplete/autocomplete_result_view.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/bubble/bubble_border.h"
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "grit/chromium_strings.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkShader.h"
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/theme_provider.h"
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas_skia.h"
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/insets.h"
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/path.h"
27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "unicode/ubidi.h"
28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "views/controls/button/text_button.h"
29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "views/controls/label.h"
3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "views/layout/grid_layout.h"
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "views/layout/layout_constants.h"
32731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "views/painter.h"
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget.h"
34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "views/window/window.h"
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <commctrl.h>
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <dwmapi.h>
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <objidl.h>
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/win/scoped_gdi_object.h"
4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "views/widget/widget_win.h"
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_LINUX)
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/skia_utils_gtk.h"
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst SkAlpha kGlassPopupAlpha = 240;
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst SkAlpha kOpaquePopupAlpha = 255;
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The size delta between the font used for the edit and the result rows. Passed
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to gfx::Font::DeriveFont.
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_CHROMEOS)
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Don't adjust the size on Chrome OS (http://crbug.com/61433).
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kEditFontAdjust = 0;
58201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#else
59201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst int kEditFontAdjust = -1;
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Horizontal padding between the buttons on the opt in promo.
63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickconst int kOptInButtonPadding = 2;
64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
65731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Padding around the opt in view.
66731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickconst int kOptInLeftPadding = 12;
674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst int kOptInRightPadding = 10;
68731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickconst int kOptInTopPadding = 6;
694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst int kOptInBottomPadding = 5;
70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Horizontal/Vertical inset of the promo background.
724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst int kOptInBackgroundHInset = 6;
734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst int kOptInBackgroundVInset = 2;
74731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Border for instant opt-in buttons. Consists of two 9 patch painters: one for
76731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// the normal state, the other for the pressed state.
77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickclass OptInButtonBorder : public views::Border {
78731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick public:
79731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  OptInButtonBorder() {
80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    border_painter_.reset(CreatePainter(IDR_OPT_IN_BUTTON));
81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    border_pushed_painter_.reset(CreatePainter(IDR_OPT_IN_BUTTON_P));
82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
83731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  virtual void Paint(const views::View& view, gfx::Canvas* canvas) const {
85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    views::Painter* painter;
86731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (static_cast<const views::CustomButton&>(view).state() ==
87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        views::CustomButton::BS_PUSHED) {
88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      painter = border_pushed_painter_.get();
89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    } else {
90731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      painter = border_painter_.get();
91731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    painter->Paint(view.width(), view.height(), canvas);
93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  virtual void GetInsets(gfx::Insets* insets) const {
96731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    insets->Set(3, 8, 3, 8);
97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick private:
100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Creates 9 patch painter from the image with the id |image_id|.
101731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  views::Painter* CreatePainter(int image_id) {
102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    SkBitmap* image =
103731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        ResourceBundle::GetSharedInstance().GetBitmapNamed(image_id);
104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    int w = image->width() / 2;
105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (image->width() % 2 == 0)
106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      w--;
107731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    int h = image->height() / 2;
108731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (image->height() % 2 == 0)
109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      h--;
110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    gfx::Insets insets(h, w, h, w);
111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return views::Painter::CreateImagePainter(*image, insets, true);
112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
114731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_ptr<views::Painter> border_painter_;
115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_ptr<views::Painter> border_pushed_painter_;
116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DISALLOW_COPY_AND_ASSIGN(OptInButtonBorder);
118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick};
119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}  // namespace
121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
122731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickclass AutocompletePopupContentsView::InstantOptInView
123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    : public views::View,
124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      public views::ButtonListener {
125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick public:
126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  InstantOptInView(AutocompletePopupContentsView* contents_view,
127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                   const gfx::Font& label_font,
128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                   const gfx::Font& button_font)
1294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      : contents_view_(contents_view),
1304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        bg_painter_(views::Painter::CreateVerticalGradient(
1314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                        SkColorSetRGB(255, 242, 183),
1324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                        SkColorSetRGB(250, 230, 145))) {
1333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    views::Label* label = new views::Label(
1343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        UTF16ToWide(l10n_util::GetStringUTF16(IDS_INSTANT_OPT_IN_LABEL)));
135731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    label->SetFont(label_font);
136731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
137731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    views::GridLayout* layout = new views::GridLayout(this);
138731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    layout->SetInsets(kOptInTopPadding, kOptInLeftPadding,
139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                      kOptInBottomPadding, kOptInRightPadding);
140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    SetLayoutManager(layout);
141731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
142731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const int first_column_set = 1;
143731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    views::GridLayout::Alignment v_align = views::GridLayout::CENTER;
144731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    views::ColumnSet* column_set = layout->AddColumnSet(first_column_set);
145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    column_set->AddColumn(views::GridLayout::TRAILING, v_align, 1,
146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          views::GridLayout::USE_PREF, 0, 0);
14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    column_set->AddColumn(views::GridLayout::CENTER, v_align, 0,
149731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          views::GridLayout::USE_PREF, 0, 0);
150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    column_set->AddPaddingColumn(0, kOptInButtonPadding);
151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    column_set->AddColumn(views::GridLayout::CENTER, v_align, 0,
152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          views::GridLayout::USE_PREF, 0, 0);
153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    column_set->LinkColumnSizes(2, 4, -1);
154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    layout->StartRow(0, first_column_set);
155731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    layout->AddView(label);
156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    layout->AddView(CreateButton(IDS_INSTANT_OPT_IN_ENABLE, button_font));
157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    layout->AddView(CreateButton(IDS_INSTANT_OPT_IN_NO_THANKS, button_font));
158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  virtual void ButtonPressed(views::Button* sender, const views::Event& event) {
161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    contents_view_->UserPressedOptIn(
162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        sender->tag() == IDS_INSTANT_OPT_IN_ENABLE);
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // WARNING: we've been deleted.
164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual void OnPaint(gfx::Canvas* canvas) {
1674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    canvas->Save();
1684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    canvas->TranslateInt(kOptInBackgroundHInset, kOptInBackgroundVInset);
1694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    bg_painter_->Paint(width() - kOptInBackgroundHInset * 2,
1704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                       height() - kOptInBackgroundVInset * 2, canvas);
1714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    canvas->DrawRectInt(ResourceBundle::toolbar_separator_color, 0, 0,
1724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                        width() - kOptInBackgroundHInset * 2,
1734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                        height() - kOptInBackgroundVInset * 2);
1744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    canvas->Restore();
175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick private:
178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Creates and returns a button configured for the opt-in promo.
179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  views::View* CreateButton(int id, const gfx::Font& font) {
180731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // NOTE: we can't use NativeButton as the popup is a layered window and
181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // native buttons don't draw  in layered windows.
182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // TODO: these buttons look crap. Figure out the right border/background to
183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // use.
184731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    views::TextButton* button =
1853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        new views::TextButton(this, UTF16ToWide(l10n_util::GetStringUTF16(id)));
186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    button->set_border(new OptInButtonBorder());
187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    button->SetNormalHasBorder(true);
188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    button->set_tag(id);
189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    button->SetFont(font);
190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    button->set_animate_on_state_change(false);
191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return button;
192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  AutocompletePopupContentsView* contents_view_;
1954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  scoped_ptr<views::Painter> bg_painter_;
196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DISALLOW_COPY_AND_ASSIGN(InstantOptInView);
198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick};
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AutocompletePopupContentsView, public:
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAutocompletePopupContentsView::AutocompletePopupContentsView(
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gfx::Font& font,
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AutocompleteEditView* edit_view,
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AutocompleteEditModel* edit_model,
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile,
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const views::View* location_bar)
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : model_(new AutocompletePopupModel(this, edit_model, profile)),
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      opt_in_view_(NULL),
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      edit_view_(edit_view),
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      location_bar_(location_bar),
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      result_font_(font.DeriveFont(kEditFontAdjust)),
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      result_bold_font_(result_font_.DeriveFont(0, gfx::Font::BOLD)),
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ignore_mouse_drag_(false),
216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) {
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The following little dance is required because set_border() requires a
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // pointer to a non-const object.
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BubbleBorder* bubble_border = new BubbleBorder(BubbleBorder::NONE);
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bubble_border_ = bubble_border;
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  set_border(bubble_border);
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // The contents is owned by the LocationBarView.
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  set_parent_owned(false);
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAutocompletePopupContentsView::~AutocompletePopupContentsView() {
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't need to do anything with |popup_| here.  The OS either has already
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // closed the window, in which case it's been deleted, or it will soon, in
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // which case there's nothing we need to do.
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AutocompletePopupContentsView::GetPopupBounds() const {
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!size_animation_.is_animating())
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return target_bounds_;
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect current_frame_bounds = start_bounds_;
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int total_height_delta = target_bounds_.height() - start_bounds_.height();
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Round |current_height_delta| instead of truncating so we won't leave single
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // white pixels at the bottom of the popup as long when animating very small
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // height differences.
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int current_height_delta = static_cast<int>(
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      size_animation_.GetCurrentValue() * total_height_delta - 0.5);
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  current_frame_bounds.set_height(
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      current_frame_bounds.height() + current_height_delta);
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return current_frame_bounds;
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutocompletePopupContentsView::LayoutChildren() {
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  gfx::Rect contents_rect = GetContentsBounds();
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int top = contents_rect.y();
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (int i = 0; i < child_count(); ++i) {
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    View* v = GetChildViewAt(i);
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (v->IsVisible()) {
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      v->SetBounds(contents_rect.x(), top, contents_rect.width(),
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                   v->GetPreferredSize().height());
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      top = v->bounds().bottom();
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AutocompletePopupContentsView, AutocompletePopupView overrides:
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompletePopupContentsView::IsOpen() const {
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (popup_ != NULL);
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupContentsView::InvalidateLine(size_t line) {
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GetChildViewAt(static_cast<int>(line))->SchedulePaint();
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupContentsView::UpdatePopupAppearance() {
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (model_->result().empty()) {
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // No matches, close any existing popup.
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (popup_ != NULL) {
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      size_animation_.Stop();
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // triggered by the popup receiving a message (e.g. LBUTTONUP), and
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // destroying the popup would cause us to read garbage when we unwind back
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // to that level.
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      popup_->Close();  // This will eventually delete the popup.
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      popup_.reset();
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Update the match cached by each row, in the process of doing so make sure
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // we have enough row views.
28972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  size_t child_rv_count = child_count();
290731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (opt_in_view_) {
291731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DCHECK(child_rv_count > 0);
292731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    child_rv_count--;
293731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < model_->result().size(); ++i) {
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AutocompleteResultView* result_view;
296731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (i >= child_rv_count) {
2973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      result_view =
298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          CreateResultView(this, i, result_font_, result_bold_font_);
29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      AddChildViewAt(result_view, static_cast<int>(i));
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      result_view = static_cast<AutocompleteResultView*>(GetChildViewAt(i));
302731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      result_view->SetVisible(true);
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result_view->SetMatch(GetMatchAtIndex(i));
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
306731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (size_t i = model_->result().size(); i < child_rv_count; ++i)
307731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    GetChildViewAt(i)->SetVisible(false);
308731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
3094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  PromoCounter* counter = model_->profile()->GetInstantPromoCounter();
3104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!opt_in_view_ && counter && counter->ShouldShow(base::Time::Now())) {
311731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    opt_in_view_ = new InstantOptInView(this, result_bold_font_, result_font_);
312731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    AddChildView(opt_in_view_);
3134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  } else if (opt_in_view_ && (!counter ||
3144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                              !counter->ShouldShow(base::Time::Now()))) {
3154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    delete opt_in_view_;
3164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    opt_in_view_ = NULL;
317731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
318731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  gfx::Rect new_target_bounds = CalculateTargetBounds(CalculatePopupHeight());
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If we're animating and our target height changes, reset the animation.
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // NOTE: If we just reset blindly on _every_ update, then when the user types
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // rapidly we could get "stuck" trying repeatedly to animate shrinking by the
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // last few pixels to get to one visible result.
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (new_target_bounds.height() != target_bounds_.height())
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_animation_.Reset();
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  target_bounds_ = new_target_bounds;
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (popup_ == NULL) {
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If the popup is currently closed, we need to create it.
331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    popup_ = (new AutocompletePopupClass)->AsWeakPtr();
332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    views::Widget::CreateParams params(views::Widget::CreateParams::TYPE_POPUP);
333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    params.can_activate = false;
334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    params.transparent = true;
335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    popup_->SetCreateParams(params);
336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    popup_->Init(location_bar_->GetWidget()->GetNativeView(), GetPopupBounds());
337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    popup_->SetContentsView(this);
338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    popup_->MoveAbove(popup_->GetRelativeWindowForPopup(
339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        edit_view_->GetNativeView()));
340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    popup_->Show();
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Animate the popup shrinking, but don't animate growing larger since that
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // would make the popup feel less responsive.
344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    start_bounds_ = GetWidget()->GetWindowScreenBounds();
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (target_bounds_.height() < start_bounds_.height())
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      size_animation_.Show();
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    else
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      start_bounds_ = target_bounds_;
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    popup_->SetBounds(GetPopupBounds());
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SchedulePaint();
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickgfx::Rect AutocompletePopupContentsView::GetTargetBounds() {
3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return target_bounds_;
3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupContentsView::PaintUpdatesNow() {
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(beng): remove this from the interface.
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupContentsView::OnDragCanceled() {
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ignore_mouse_drag_ = true;
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AutocompletePopupContentsView, AutocompleteResultViewModel implementation:
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompletePopupContentsView::IsSelectedIndex(size_t index) const {
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return HasMatchAt(index) ? index == model_->selected_line() : false;
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const {
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return HasMatchAt(index) ? index == model_->hovered_line() : false;
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst SkBitmap* AutocompletePopupContentsView::GetIconIfExtensionMatch(
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t index) const {
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!HasMatchAt(index))
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return model_->GetIconIfExtensionMatch(GetMatchAtIndex(index));
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AutocompletePopupContentsView, AnimationDelegate implementation:
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupContentsView::AnimationProgressed(
3893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const ui::Animation* animation) {
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We should only be running the animation when the popup is already visible.
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(popup_ != NULL);
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  popup_->SetBounds(GetPopupBounds());
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AutocompletePopupContentsView, views::View overrides:
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupContentsView::Layout() {
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateBlurRegion();
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Size our children to the available content area.
402dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  LayoutChildren();
403dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
404dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We need to manually schedule a paint here since we are a layered window and
405dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // won't implicitly require painting until we ask for one.
406dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SchedulePaint();
407dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
408dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenviews::View* AutocompletePopupContentsView::GetEventHandlerForPoint(
410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const gfx::Point& point) {
411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If there is no opt in view, then we want all mouse events. Otherwise let
412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // any descendants of the opt-in view get mouse events.
413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!opt_in_view_)
414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return this;
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  views::View* child = views::View::GetEventHandlerForPoint(point);
417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  views::View* ancestor = child;
418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  while (ancestor && ancestor != opt_in_view_)
419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ancestor = ancestor->parent();
420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return ancestor ? child : this;
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompletePopupContentsView::OnMousePressed(
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const views::MouseEvent& event) {
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ignore_mouse_drag_ = false;  // See comment on |ignore_mouse_drag_| in header.
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) {
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t index = GetIndexForPoint(event.location());
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model_->SetHoveredLine(index);
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (HasMatchAt(index) && event.IsLeftMouseButton())
43072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      model_->SetSelectedLine(index, false, false);
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool AutocompletePopupContentsView::OnMouseDragged(
436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const views::MouseEvent& event) {
437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) {
438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    size_t index = GetIndexForPoint(event.location());
439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    model_->SetHoveredLine(index);
440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!ignore_mouse_drag_ && HasMatchAt(index) && event.IsLeftMouseButton())
441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      model_->SetSelectedLine(index, false, false);
442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
443ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
444ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupContentsView::OnMouseReleased(
447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const views::MouseEvent& event) {
448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (ignore_mouse_drag_) {
449ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    OnMouseCaptureLost();
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t index = GetIndexForPoint(event.location());
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (event.IsOnlyMiddleMouseButton())
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OpenIndex(index, NEW_BACKGROUND_TAB);
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else if (event.IsOnlyLeftMouseButton())
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OpenIndex(index, CURRENT_TAB);
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutocompletePopupContentsView::OnMouseCaptureLost() {
461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ignore_mouse_drag_ = false;
462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutocompletePopupContentsView::OnMouseMoved(
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const views::MouseEvent& event) {
466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  model_->SetHoveredLine(GetIndexForPoint(event.location()));
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutocompletePopupContentsView::OnMouseEntered(
470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const views::MouseEvent& event) {
471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  model_->SetHoveredLine(GetIndexForPoint(event.location()));
472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
473731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutocompletePopupContentsView::OnMouseExited(
475ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const views::MouseEvent& event) {
476ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  model_->SetHoveredLine(AutocompletePopupModel::kNoMatch);
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
479dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen////////////////////////////////////////////////////////////////////////////////
480dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// AutocompletePopupContentsView, protected:
481dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
482dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutocompletePopupContentsView::PaintResultViews(gfx::CanvasSkia* canvas) {
483dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  canvas->drawColor(AutocompleteResultView::GetColor(
484dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      AutocompleteResultView::NORMAL, AutocompleteResultView::BACKGROUND));
485dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  View::PaintChildren(canvas);
486dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
487dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
488dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint AutocompletePopupContentsView::CalculatePopupHeight() {
489dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_GE(static_cast<size_t>(child_count()), model_->result().size());
490dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int popup_height = 0;
491dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (size_t i = 0; i < model_->result().size(); ++i)
492dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    popup_height += GetChildViewAt(i)->GetPreferredSize().height();
493dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return popup_height +
494dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      (opt_in_view_ ? opt_in_view_->GetPreferredSize().height() : 0);
495dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
496dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
497dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenAutocompleteResultView* AutocompletePopupContentsView::CreateResultView(
498dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    AutocompleteResultViewModel* model,
499dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int model_index,
500dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const gfx::Font& font,
501dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const gfx::Font& bold_font) {
502dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return new AutocompleteResultView(model, model_index, font, bold_font);
503dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// AutocompletePopupContentsView, views::View overrides, protected:
507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutocompletePopupContentsView::OnPaint(gfx::Canvas* canvas) {
509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // We paint our children in an unconventional way.
510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //
511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Because the border of this view creates an anti-aliased round-rect region
512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // for the contents, we need to render our rectangular result child views into
513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // this round rect region. We can't use a simple clip because clipping is
514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // 1-bit and we get nasty jagged edges.
515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //
516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Instead, we paint all our children into a second canvas and use that as a
517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // shader to fill a path representing the round-rect clipping region. This
518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // yields a nice anti-aliased edge.
519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  gfx::CanvasSkia contents_canvas(width(), height(), true);
520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  PaintResultViews(&contents_canvas);
521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // We want the contents background to be slightly transparent so we can see
523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // the blurry glass effect on DWM systems behind. We do this _after_ we paint
524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // the children since they paint text, and GDI will reset this alpha data if
525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // we paint text after this call.
526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MakeCanvasTransparent(&contents_canvas);
527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Now paint the contents of the contents canvas into the actual canvas.
529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SkPaint paint;
530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  paint.setAntiAlias(true);
531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SkShader* shader = SkShader::CreateBitmapShader(
533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      contents_canvas.getDevice()->accessBitmap(false),
534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SkShader::kClamp_TileMode,
535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SkShader::kClamp_TileMode);
536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  paint.setShader(shader);
537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  shader->unref();
538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  gfx::Path path;
540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MakeContentsPath(&path, GetContentsBounds());
541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  canvas->AsCanvasSkia()->drawPath(path, paint);
542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Now we paint the border, so it will be alpha-blended atop the contents.
544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // This looks slightly better in the corners than drawing the contents atop
545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // the border.
546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  OnPaintBorder(canvas);
547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AutocompletePopupContentsView::PaintChildren(gfx::Canvas* canvas) {
550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // We paint our children inside OnPaint().
551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen////////////////////////////////////////////////////////////////////////////////
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AutocompletePopupContentsView, private:
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompletePopupContentsView::HasMatchAt(size_t index) const {
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return index < model_->result().size();
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst AutocompleteMatch& AutocompletePopupContentsView::GetMatchAtIndex(
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t index) const {
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return model_->result().match_at(index);
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupContentsView::MakeContentsPath(
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::Path* path,
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gfx::Rect& bounding_rect) {
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkRect rect;
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rect.set(SkIntToScalar(bounding_rect.x()),
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           SkIntToScalar(bounding_rect.y()),
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           SkIntToScalar(bounding_rect.right()),
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           SkIntToScalar(bounding_rect.bottom()));
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius());
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  path->addRoundRect(rect, radius, radius);
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupContentsView::UpdateBlurRegion() {
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We only support background blurring on Vista with Aero-Glass enabled.
58172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!views::WidgetWin::IsAeroGlassEnabled() || !GetWidget())
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Provide a blurred background effect within the contents region of the
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // popup.
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DWM_BLURBEHIND bb = {0};
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bb.fEnable = true;
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Translate the contents rect into widget coordinates, since that's what
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // DwmEnableBlurBehindWindow expects a region in.
59272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Rect contents_rect = GetContentsBounds();
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point origin(contents_rect.origin());
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  views::View::ConvertPointToWidget(this, &origin);
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  contents_rect.set_origin(origin);
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Path contents_path;
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MakeContentsPath(&contents_path, contents_rect);
59921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  base::win::ScopedGDIObject<HRGN> popup_region;
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  popup_region.Set(contents_path.CreateNativeRegion());
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bb.hRgnBlur = popup_region.Get();
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DwmEnableBlurBehindWindow(GetWidget()->GetNativeView(), &bb);
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupContentsView::MakeCanvasTransparent(
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::Canvas* canvas) {
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Allow the window blur effect to show through the popup background.
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkAlpha alpha = GetThemeProvider()->ShouldUseNativeFrame() ?
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kGlassPopupAlpha : kOpaquePopupAlpha;
611dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  canvas->AsCanvasSkia()->drawColor(SkColorSetA(
612dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      AutocompleteResultView::GetColor(AutocompleteResultView::NORMAL,
613dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      AutocompleteResultView::BACKGROUND), alpha), SkXfermode::kDstIn_Mode);
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupContentsView::OpenIndex(
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t index,
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WindowOpenDisposition disposition) {
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!HasMatchAt(index))
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const AutocompleteMatch& match = model_->result().match_at(index);
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // OpenURL() may close the popup, which will clear the result set and, by
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // extension, |match| and its contents.  So copy the relevant strings out to
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // make sure they stay alive until the call completes.
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const GURL url(match.destination_url);
62772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  string16 keyword;
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const bool is_keyword_hint = model_->GetKeywordForMatch(match, &keyword);
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  edit_view_->OpenURL(url, disposition, match.transition, GURL(), index,
63072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                      is_keyword_hint ? string16() : keyword);
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsize_t AutocompletePopupContentsView::GetIndexForPoint(
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gfx::Point& point) {
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!HitTest(point))
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return AutocompletePopupModel::kNoMatch;
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int nb_match = model_->result().size();
63972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(nb_match <= child_count());
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < nb_match; ++i) {
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    views::View* child = GetChildViewAt(i);
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::Point point_in_child_coords(point);
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    View::ConvertPointToView(this, child, &point_in_child_coords);
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (child->HitTest(point_in_child_coords))
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return i;
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return AutocompletePopupModel::kNoMatch;
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
6493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickgfx::Rect AutocompletePopupContentsView::CalculateTargetBounds(int h) {
65172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Rect location_bar_bounds(location_bar_->GetContentsBounds());
6523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const views::Border* border = location_bar_->border();
6533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (border) {
6543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Adjust for the border so that the bubble and location bar borders are
6553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // aligned.
6563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    gfx::Insets insets;
6573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    border->GetInsets(&insets);
6583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    location_bar_bounds.Inset(insets.left(), 0, insets.right(), 0);
6593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else {
6603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // The normal location bar is drawn using a background graphic that includes
6613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // the border, so we inset by enough to make the edges line up, and the
6623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // bubble appear at the same height as the Star bubble.
6633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    location_bar_bounds.Inset(LocationBarView::kNormalHorizontalEdgeThickness,
6643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              0);
6653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
6663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gfx::Point location_bar_origin(location_bar_bounds.origin());
6673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  views::View::ConvertPointToScreen(location_bar_, &location_bar_origin);
6683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  location_bar_bounds.set_origin(location_bar_origin);
6693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return bubble_border_->GetBounds(
6703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      location_bar_bounds, gfx::Size(location_bar_bounds.width(), h));
6713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
672731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
673731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid AutocompletePopupContentsView::UserPressedOptIn(bool opt_in) {
674731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  delete opt_in_view_;
675731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  opt_in_view_ = NULL;
6764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  PromoCounter* counter = model_->profile()->GetInstantPromoCounter();
6774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DCHECK(counter);
6784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  counter->Hide();
6794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (opt_in) {
6804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    browser::ShowInstantConfirmDialogIfNecessary(
6814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        location_bar_->GetWindow()->GetNativeWindow(), model_->profile());
6824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
683731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  UpdatePopupAppearance();
684731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
685