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, ¤t_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