omnibox_popup_model.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/omnibox/omnibox_popup_model.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/autocomplete_match.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/omnibox/omnibox_api.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url_service.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url_service_factory.h" 177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/ui/omnibox/omnibox_popup_model_observer.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/omnibox/omnibox_popup_view.h" 19ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "third_party/icu/source/common/unicode/ubidi.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/image/image.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxPopupModel 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t OmniboxPopupModel::kNoMatch = -1; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OmniboxPopupModel::OmniboxPopupModel( 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OmniboxPopupView* popup_view, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OmniboxEditModel* edit_model) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : view_(popup_view), 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) edit_model_(edit_model), 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hovered_line_(kNoMatch), 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_line_(kNoMatch), 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_line_state_(NORMAL) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) edit_model->set_popup_model(this); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OmniboxPopupModel::~OmniboxPopupModel() { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OmniboxPopupModel::IsOpen() const { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return view_->IsOpen(); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupModel::SetHoveredLine(size_t line) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool is_disabling = (line == kNoMatch); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(is_disabling || (line < result().size())); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (line == hovered_line_) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // Nothing to do 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the old hovered line is redrawn. No need to redraw the selected 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // line since selection overrides hover so the appearance won't change. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((hovered_line_ != kNoMatch) && (hovered_line_ != selected_line_)) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->InvalidateLine(hovered_line_); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Change the hover to the new line. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hovered_line_ = line; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_disabling && (hovered_line_ != selected_line_)) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->InvalidateLine(hovered_line_); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupModel::SetSelectedLine(size_t line, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool reset_to_default, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool force) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteResult& result = this->result(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result.empty()) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel the query so the matches don't change on the user. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) autocomplete_controller()->Stop(false); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line = std::min(line, result.size() - 1); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteMatch& match = result.match_at(line); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reset_to_default) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manually_selected_match_.Clear(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Track the user's selection until they cancel it. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manually_selected_match_.destination_url = match.destination_url; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manually_selected_match_.provider_affinity = match.provider; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manually_selected_match_.is_history_what_you_typed_match = 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match.is_history_what_you_typed_match; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (line == selected_line_ && !force) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // Nothing else to do. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to update |selected_line_state_| and |selected_line_| before 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // calling InvalidateLine(), since it will check them to determine how to 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // draw. We also need to update |selected_line_| before calling 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OnPopupDataChanged(), so that when the edit notifies its controller that 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // something has changed, the controller can get the correct updated data. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: We should never reach here with no selected line; the same code that 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // opened the popup and made it possible to get here should have also set a 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // selected line. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(selected_line_ != kNoMatch); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL current_destination(result.match_at(selected_line_).destination_url); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t prev_selected_line = selected_line_; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_line_state_ = NORMAL; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_line_ = line; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->InvalidateLine(prev_selected_line); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->InvalidateLine(selected_line_); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the edit with the new data for this match. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkasting): If |selected_line_| moves to the controller, this can be 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // eliminated and just become a call to the observer on the edit. 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 keyword; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_keyword_hint; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match.GetKeywordUIState(edit_model_->profile(), &keyword, &is_keyword_hint); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reset_to_default) { 114ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch edit_model_->OnPopupDataChanged(match.inline_autocompletion, NULL, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword, is_keyword_hint); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) edit_model_->OnPopupDataChanged(match.fill_into_edit, ¤t_destination, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword, is_keyword_hint); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Repaint old and new selected lines immediately, so that the edit doesn't 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appear to update [much] faster than the popup. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->PaintUpdatesNow(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupModel::ResetToDefaultMatch() { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteResult& result = this->result(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!result.empty()); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetSelectedLine(result.default_match() - result.begin(), true, false); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->OnDragCanceled(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupModel::Move(int count) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteResult& result = this->result(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result.empty()) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The user is using the keyboard to change the selection, so stop tracking 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hover. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetHoveredLine(kNoMatch); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clamp the new line to [0, result_.count() - 1]. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t new_line = selected_line_ + count; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetSelectedLine(((count < 0) && (new_line >= selected_line_)) ? 0 : new_line, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, false); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupModel::SetSelectedLineState(LineState state) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!result().empty()); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(kNoMatch, selected_line_); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteMatch& match = result().match_at(selected_line_); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(match.associated_keyword.get()); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_line_state_ = state; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->InvalidateLine(selected_line_); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupModel::TryDeletingCurrentItem() { 160b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // We could use GetInfoForCurrentText() here, but it seems better to try 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and shift-delete the actual selection, rather than any "in progress, not 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // yet visible" one. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selected_line_ == kNoMatch) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel the query so the matches don't change on the user. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) autocomplete_controller()->Stop(false); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteMatch& match = result().match_at(selected_line_); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (match.deletable) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t selected_line = selected_line_; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool was_temporary_text = !manually_selected_match_.empty(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will synchronously notify both the edit and us that the results 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have changed, causing both to revert to the default match. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) autocomplete_controller()->DeleteMatch(match); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteResult& result = this->result(); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result.empty() && 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (was_temporary_text || selected_line != selected_line_)) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move the selection to the next choice after the deleted one. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SetSelectedLine() will clamp to take care of the case where we deleted 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the last item. 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkasting): Eventually the controller should take care of this 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // before notifying us, reducing flicker. At that point the check for 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deletability can move there too. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetSelectedLine(selected_line, false, true); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Image OmniboxPopupModel::GetIconIfExtensionMatch( 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteMatch& match) const { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = edit_model_->profile(); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* template_url = match.GetTemplateURL(profile, false); 1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (template_url && 1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) (template_url->GetType() == TemplateURL::OMNIBOX_API_EXTENSION)) { 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return extensions::OmniboxAPI::Get(profile)->GetOmniboxPopupIcon( 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url->GetExtensionId()); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Image(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxPopupModel::OnResultChanged() { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteResult& result = this->result(); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_line_ = result.default_match() == result.end() ? 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kNoMatch : static_cast<size_t>(result.default_match() - result.begin()); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There had better not be a nonempty result set with no default match. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK((selected_line_ != kNoMatch) || result.empty()); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manually_selected_match_.Clear(); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_line_state_ = NORMAL; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're going to trim the window size to no longer include the hovered 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // line, turn hover off. Practically, this shouldn't happen, but it 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // doesn't hurt to be defensive. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((hovered_line_ != kNoMatch) && (result.size() <= hovered_line_)) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetHoveredLine(kNoMatch); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool popup_was_open = view_->IsOpen(); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->UpdatePopupAppearance(); 2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // If popup has just been shown or hidden, notify observers. 2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (view_->IsOpen() != popup_was_open) { 2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch FOR_EACH_OBSERVER(OmniboxPopupModelObserver, observers_, 2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch OnOmniboxPopupShownOrHidden()); 2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid OmniboxPopupModel::AddObserver(OmniboxPopupModelObserver* observer) { 2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch observers_.AddObserver(observer); 2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid OmniboxPopupModel::RemoveObserver(OmniboxPopupModelObserver* observer) { 2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch observers_.RemoveObserver(observer); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 233