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
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <algorithm>
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "unicode/ubidi.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/utf_string_conversions.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/autocomplete_edit.h"
14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/autocomplete/autocomplete_match.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/autocomplete_popup_view.h"
1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h"
1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/search_engines/template_url.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/search_engines/template_url_model.h"
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/rect.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AutocompletePopupModel
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAutocompletePopupModel::AutocompletePopupModel(
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AutocompletePopupView* popup_view,
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AutocompleteEditModel* edit_model,
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile)
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : view_(popup_view),
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      edit_model_(edit_model),
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      profile_(profile),
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      hovered_line_(kNoMatch),
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      selected_line_(kNoMatch) {
34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  edit_model->set_popup_model(this);
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAutocompletePopupModel::~AutocompletePopupModel() {
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompletePopupModel::IsOpen() const {
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return view_->IsOpen();
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupModel::SetHoveredLine(size_t line) {
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const bool is_disabling = (line == kNoMatch);
46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(is_disabling || (line < result().size()));
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (line == hovered_line_)
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;  // Nothing to do
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make sure the old hovered line is redrawn.  No need to redraw the selected
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // line since selection overrides hover so the appearance won't change.
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if ((hovered_line_ != kNoMatch) && (hovered_line_ != selected_line_))
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    view_->InvalidateLine(hovered_line_);
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Change the hover to the new line.
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hovered_line_ = line;
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!is_disabling && (hovered_line_ != selected_line_))
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    view_->InvalidateLine(hovered_line_);
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupModel::SetSelectedLine(size_t line,
6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                             bool reset_to_default,
6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                             bool force) {
65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const AutocompleteResult& result = this->result();
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result.empty())
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Cancel the query so the matches don't change on the user.
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  autocomplete_controller()->Stop(false);
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  line = std::min(line, result.size() - 1);
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const AutocompleteMatch& match = result.match_at(line);
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (reset_to_default) {
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    manually_selected_match_.Clear();
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Track the user's selection until they cancel it.
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    manually_selected_match_.destination_url = match.destination_url;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    manually_selected_match_.provider_affinity = match.provider;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    manually_selected_match_.is_history_what_you_typed_match =
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        match.is_history_what_you_typed_match;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (line == selected_line_ && !force)
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;  // Nothing else to do.
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We need to update |selected_line_| before calling OnPopupDataChanged(), so
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // that when the edit notifies its controller that something has changed, the
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // controller can get the correct updated data.
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // NOTE: We should never reach here with no selected line; the same code that
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // opened the popup and made it possible to get here should have also set a
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // selected line.
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CHECK(selected_line_ != kNoMatch);
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL current_destination(result.match_at(selected_line_).destination_url);
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  view_->InvalidateLine(selected_line_);
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  selected_line_ = line;
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  view_->InvalidateLine(selected_line_);
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Update the edit with the new data for this match.
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(pkasting): If |selected_line_| moves to the controller, this can be
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // eliminated and just become a call to the observer on the edit.
10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  string16 keyword;
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const bool is_keyword_hint = GetKeywordForMatch(match, &keyword);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (reset_to_default) {
10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    string16 inline_autocomplete_text;
10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if ((match.inline_autocomplete_offset != string16::npos) &&
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        (match.inline_autocomplete_offset < match.fill_into_edit.length())) {
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      inline_autocomplete_text =
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          match.fill_into_edit.substr(match.inline_autocomplete_offset);
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    edit_model_->OnPopupDataChanged(inline_autocomplete_text, NULL,
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    keyword, is_keyword_hint);
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    edit_model_->OnPopupDataChanged(match.fill_into_edit, &current_destination,
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    keyword, is_keyword_hint);
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Repaint old and new selected lines immediately, so that the edit doesn't
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // appear to update [much] faster than the popup.
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  view_->PaintUpdatesNow();
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupModel::ResetToDefaultMatch() {
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const AutocompleteResult& result = this->result();
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CHECK(!result.empty());
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  SetSelectedLine(result.default_match() - result.begin(), true, false);
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  view_->OnDragCanceled();
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AutocompletePopupModel::GetKeywordForMatch(const AutocompleteMatch& match,
13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                string16* keyword) const {
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the current match is a keyword, return that as the selected keyword.
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (TemplateURL::SupportsReplacement(match.template_url)) {
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    keyword->assign(match.template_url->keyword());
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // See if the current match's fill_into_edit corresponds to a keyword.
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return GetKeywordForText(match.fill_into_edit, keyword);
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool AutocompletePopupModel::GetKeywordForText(const string16& text,
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                               string16* keyword) const {
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Creates keyword_hint first in case |keyword| is a pointer to |text|.
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const string16 keyword_hint(TemplateURLModel::CleanUserInputKeyword(text));
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Assume we have no keyword until we find otherwise.
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  keyword->clear();
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (keyword_hint.empty())
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!profile_->GetTemplateURLModel())
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  profile_->GetTemplateURLModel()->Load();
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Don't provide a hint if this keyword doesn't support replacement.
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const TemplateURL* const template_url =
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword_hint);
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!TemplateURL::SupportsReplacement(template_url))
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
163201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Don't provide a hint for inactive/disabled extension keywords.
164201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (template_url->IsExtensionKeyword()) {
16521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const Extension* extension = profile_->GetExtensionService()->
166513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        GetExtensionById(template_url->GetExtensionId(), false);
167201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (!extension ||
168201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        (profile_->IsOffTheRecord() &&
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         !profile_->GetExtensionService()->
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen             IsIncognitoEnabled(extension->id())))
171513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return false;
172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  keyword->assign(keyword_hint);
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupModel::Move(int count) {
179dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const AutocompleteResult& result = this->result();
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result.empty())
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The user is using the keyboard to change the selection, so stop tracking
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // hover.
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetHoveredLine(kNoMatch);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Clamp the new line to [0, result_.count() - 1].
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const size_t new_line = selected_line_ + count;
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SetSelectedLine(((count < 0) && (new_line >= selected_line_)) ? 0 : new_line,
19072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                  false, false);
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AutocompletePopupModel::TryDeletingCurrentItem() {
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We could use InfoForCurrentSelection() here, but it seems better to try
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // and shift-delete the actual selection, rather than any "in progress, not
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // yet visible" one.
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (selected_line_ == kNoMatch)
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Cancel the query so the matches don't change on the user.
201dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  autocomplete_controller()->Stop(false);
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const AutocompleteMatch& match = result().match_at(selected_line_);
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (match.deletable) {
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const size_t selected_line = selected_line_;
20672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const bool was_temporary_text = !manually_selected_match_.empty();
20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
20872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // This will synchronously notify both the edit and us that the results
20972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // have changed, causing both to revert to the default match.
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    autocomplete_controller()->DeleteMatch(match);
211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const AutocompleteResult& result = this->result();
21272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!result.empty() &&
21372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        (was_temporary_text || selected_line != selected_line_)) {
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Move the selection to the next choice after the deleted one.
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // SetSelectedLine() will clamp to take care of the case where we deleted
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // the last item.
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // TODO(pkasting): Eventually the controller should take care of this
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // before notifying us, reducing flicker.  At that point the check for
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // deletability can move there too.
22072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      SetSelectedLine(selected_line, false, true);
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst SkBitmap* AutocompletePopupModel::GetIconIfExtensionMatch(
22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const AutocompleteMatch& match) const {
22772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!match.template_url || !match.template_url->IsExtensionKeyword())
22872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return NULL;
22972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
23072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return &profile_->GetExtensionService()->GetOmniboxPopupIcon(
23172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      match.template_url->GetExtensionId());
23272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid AutocompletePopupModel::OnResultChanged() {
235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const AutocompleteResult& result = this->result();
23672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  selected_line_ = result.default_match() == result.end() ?
23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      kNoMatch : static_cast<size_t>(result.default_match() - result.begin());
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // There had better not be a nonempty result set with no default match.
23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CHECK((selected_line_ != kNoMatch) || result.empty());
24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  manually_selected_match_.Clear();
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If we're going to trim the window size to no longer include the hovered
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // line, turn hover off.  Practically, this shouldn't happen, but it
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // doesn't hurt to be defensive.
24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if ((hovered_line_ != kNoMatch) && (result.size() <= hovered_line_))
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SetHoveredLine(kNoMatch);
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  view_->UpdatePopupAppearance();
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
249