autocomplete_controller.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/autocomplete/autocomplete_controller.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/autocomplete_controller_delegate.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/bookmark_provider.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/builtin_provider.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/extension_app_provider.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/history_contents_provider.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/history_quick_provider.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/history_url_provider.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/keyword_provider.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/search_provider.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/shortcuts_provider.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/zero_suggest_provider.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/omnibox/omnibox_field_trial.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/contact_provider_chromeos.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/contacts/contact_manager.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts the given type to an integer based on the AQS specification. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For more details, See http://goto.google.com/binary-clients-logging . 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int AutocompleteMatchToAssistedQueryType(const AutocompleteMatch::Type& type) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case AutocompleteMatch::SEARCH_SUGGEST: return 0; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case AutocompleteMatch::NAVSUGGEST: return 5; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED: return 57; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case AutocompleteMatch::URL_WHAT_YOU_TYPED: return 58; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case AutocompleteMatch::SEARCH_HISTORY: return 59; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case AutocompleteMatch::HISTORY_URL: return 60; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case AutocompleteMatch::HISTORY_TITLE: return 61; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case AutocompleteMatch::HISTORY_BODY: return 62; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case AutocompleteMatch::HISTORY_KEYWORD: return 63; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case AutocompleteMatch::BOOKMARK_TITLE: return 65; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: Default must remain 64 for server-side compatability. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: return 64; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Appends available autocompletion of the given type and number to the existing 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// available autocompletions string, encoding according to the spec. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppendAvailableAutocompletion(int type, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* autocompletions) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!autocompletions->empty()) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) autocompletions->append("j"); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringAppendF(autocompletions, "%d", type); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count > 1) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringAppendF(autocompletions, "l%d", count); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Amount of time (in ms) between when the user stops typing and when we remove 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// any copied entries. We do this from the time the user stopped typing as some 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// providers (such as SearchProvider) wait for the user to stop typing before 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// they initiate a query. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kExpireTimeMS = 500; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int AutocompleteController::kNoItemSelected = -1; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutocompleteController::AutocompleteController( 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteControllerDelegate* delegate, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int provider_types) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : delegate_(delegate), 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_provider_(NULL), 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_provider_(NULL), 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zero_suggest_provider_(NULL), 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_(true), 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_start_(false), 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_zero_suggest_(false), 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_(profile) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // AND with the disabled providers, if any. 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) provider_types &= ~OmniboxFieldTrial::GetDisabledProviderTypes(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool use_hqp = !!(provider_types & AutocompleteProvider::TYPE_HISTORY_QUICK); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mrossetti): Permanently modify the HistoryURLProvider to not search 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // titles once HQP is turned on permanently. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // History quick provider can be used on all platforms other than Android. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jcivelli): Enable the History Quick Provider and figure out why it 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reports the wrong results for some pages. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_hqp = false; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider_types & AutocompleteProvider::TYPE_BUILTIN) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.push_back(new BuiltinProvider(this, profile)); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider_types & AutocompleteProvider::TYPE_CONTACT) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.push_back(new ContactProvider(this, profile, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contacts::ContactManager::GetInstance()->GetWeakPtr())); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider_types & AutocompleteProvider::TYPE_EXTENSION_APP) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.push_back(new ExtensionAppProvider(this, profile)); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider_types & AutocompleteProvider::TYPE_HISTORY_CONTENTS) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.push_back(new HistoryContentsProvider(this, profile, use_hqp)); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_hqp) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.push_back(new HistoryQuickProvider(this, profile)); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider_types & AutocompleteProvider::TYPE_HISTORY_URL) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.push_back(new HistoryURLProvider(this, profile)); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Search provider/"tab to search" can be used on all platforms other than 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Android. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider_types & AutocompleteProvider::TYPE_KEYWORD) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_provider_ = new KeywordProvider(this, profile); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.push_back(keyword_provider_); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider_types & AutocompleteProvider::TYPE_SEARCH) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_provider_ = new SearchProvider(this, profile); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.push_back(search_provider_); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider_types & AutocompleteProvider::TYPE_SHORTCUTS) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.push_back(new ShortcutsProvider(this, profile)); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create ZeroSuggest if it is enabled. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider_types & AutocompleteProvider::TYPE_ZERO_SUGGEST) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zero_suggest_provider_ = ZeroSuggestProvider::Create(this, profile); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (zero_suggest_provider_) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.push_back(zero_suggest_provider_); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((provider_types & AutocompleteProvider::TYPE_BOOKMARK) && 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !CommandLine::ForCurrentProcess()->HasSwitch( 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches::kDisableBookmarkAutocompleteProvider)) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.push_back(new BookmarkProvider(this, profile)); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->AddRef(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutocompleteController::~AutocompleteController() { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The providers may have tasks outstanding that hold refs to them. We need 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to ensure they won't call us back if they outlive us. (Practically, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // calling Stop() should also cancel those tasks and make it so that we hold 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the only refs.) We also don't want to bother notifying anyone of our 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // result changes here, because the notification observer is in the midst of 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shutdown too, so we don't ask Stop() to clear |result_| (and notify). 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.Reset(); // Not really necessary. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(false); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->Release(); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.clear(); // Not really necessary. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutocompleteController::Start(const AutocompleteInput& input) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16 old_input_text(input_.text()); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteInput::MatchesRequested old_matches_requested = 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_.matches_requested(); 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_ = input; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if we can avoid rerunning autocomplete when the query hasn't changed 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // much. When the user presses or releases the ctrl key, the desired_tld 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // changes, and when the user finishes an IME composition, inline autocomplete 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may no longer be prevented. In both these cases the text itself hasn't 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // changed since the last query, and some providers can do much less work (and 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // get matches back more quickly). Taking advantage of this reduces flicker. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: This comes after constructing |input_| above since that construction 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can change the text string (e.g. by stripping off a leading '?'). 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool minimal_changes = (input_.text() == old_input_text) && 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (input_.matches_requested() == old_matches_requested); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expire_timer_.Stop(); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start the new query. 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_zero_suggest_ = false; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_start_ = true; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks start_time = base::TimeTicks::Now(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->Start(input_, minimal_changes); 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (input.matches_requested() != AutocompleteInput::ALL_MATCHES) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK((*i)->done()); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (input.matches_requested() == AutocompleteInput::ALL_MATCHES && 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (input.text().length() < 6)) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks end_time = base::TimeTicks::Now(); 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string name = "Omnibox.QueryTime." + base::IntToString( 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input.text().length()); 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::HistogramBase* counter = base::Histogram::FactoryGet( 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name, 1, 1000, 50, base::Histogram::kUmaTargetedHistogramFlag); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) counter->Add(static_cast<int>((end_time - start_time).InMilliseconds())); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_start_ = false; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfDone(); 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The second true forces saying the default match has changed. 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This triggers the edit model to update things such as the inline 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // autocomplete state. In particular, if the user has typed a key 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // since the last notification, and we're now re-running 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // autocomplete, then we need to update the inline autocompletion 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // even if the current match is for the same URL as the last run's 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // default match. Likewise, the controller doesn't know what's 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // happened in the edit since the last time it ran autocomplete. 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The user might have selected all the text and hit delete, then 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // typed a new character. The selection and delete won't send any 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // signals to the controller so it doesn't realize that anything was 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // cleared or changed. Even if the default match hasn't changed, we 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // need the edit model to update the display. 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateResult(false, true); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!done_) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartExpireTimer(); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::Stop(bool clear_result) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->Stop(clear_result); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expire_timer_.Stop(); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_ = true; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (clear_result && !result_.empty()) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.Reset(); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: We pass in false since we're trying to only clear the popup, not 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // touch the edit... this is all a mess and should be cleaned up :( 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyChanged(false); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::StartZeroSuggest( 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& user_text) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (zero_suggest_provider_ != NULL) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!in_start_); // We should not be already running a query. 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_zero_suggest_ = true; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zero_suggest_provider_->StartZeroSuggest(url, user_text); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::StopZeroSuggest() { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (zero_suggest_provider_ != NULL) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!in_start_); // We should not be already running a query. 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zero_suggest_provider_->Stop(false); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::DeleteMatch(const AutocompleteMatch& match) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(match.deletable); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match.provider->DeleteMatch(match); // This may synchronously call back to 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OnProviderUpdate(). 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If DeleteMatch resulted in a callback to OnProviderUpdate and we're 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not done, we might attempt to redisplay the deleted match. Make sure 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we aren't displaying it by removing any old entries. 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpireCopiedEntries(); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::ExpireCopiedEntries() { 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The first true makes UpdateResult() clear out the results and 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // regenerate them, thus ensuring that no results from the previous 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // result set remain. 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateResult(true, false); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::OnProviderUpdate(bool updated_matches) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (in_zero_suggest_) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We got ZeroSuggest results before Start(). Show only those results, 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because results from other providers are stale. 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.Reset(); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.AppendMatches(zero_suggest_provider_->matches()); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.SortAndCull(input_, profile_); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyChanged(true); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfDone(); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Multiple providers may provide synchronous results, so we only update the 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // results if we're not in Start(). 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!in_start_ && (updated_matches || done_)) 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateResult(false, false); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::AddProvidersInfo( 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProvidersInfo* provider_info) const { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider_info->clear(); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add per-provider info, if any. 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->AddProviderInfo(provider_info); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is also a good place to put code to add info that you want to 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // add for every provider. 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutocompleteController::ResetSession() { 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++i) 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*i)->ResetSession(); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutocompleteController::UpdateResult( 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool regenerate_result, 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool force_notify_default_match_changed) { 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool last_default_was_valid = result_.default_match() != result_.end(); 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The following two variables are only set and used if 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |last_default_was_valid|. 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string16 last_default_fill_into_edit, last_default_associated_keyword; 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (last_default_was_valid) { 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_default_fill_into_edit = result_.default_match()->fill_into_edit; 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (result_.default_match()->associated_keyword != NULL) 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_default_associated_keyword = 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result_.default_match()->associated_keyword->keyword; 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (regenerate_result) 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result_.Reset(); 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteResult last_result; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_result.Swap(&result_); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.AppendMatches((*i)->matches()); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sort the matches and trim to a small number of "best" matches. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.SortAndCull(input_, profile_); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to validate before invoking CopyOldMatches as the old matches are not 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // valid against the current input. 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.Validate(); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!done_) { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This conditional needs to match the conditional in Start that invokes 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // StartExpireTimer. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_.CopyOldMatches(input_, last_result, profile_); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateKeywordDescriptions(&result_); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateAssociatedKeywords(&result_); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateAssistedQueryStats(&result_); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool default_is_valid = result_.default_match() != result_.end(); 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string16 default_associated_keyword; 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (default_is_valid && 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (result_.default_match()->associated_keyword != NULL)) { 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default_associated_keyword = 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result_.default_match()->associated_keyword->keyword; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We've gotten async results. Send notification that the default match 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // updated if fill_into_edit differs or associated_keyword differ. (The 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // latter can change if we've just started Chrome and the keyword database 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // finishes loading while processing this request.) We don't check the URL 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // as that may change for the default match even though the fill into edit 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // hasn't changed (see SearchProvider for one case of this). 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool notify_default_match = 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (last_default_was_valid != default_is_valid) || 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (last_default_was_valid && 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ((result_.default_match()->fill_into_edit != 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_default_fill_into_edit) || 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (default_associated_keyword != last_default_associated_keyword))); 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (notify_default_match) 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_time_default_match_changed_ = base::TimeTicks::Now(); 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NotifyChanged(force_notify_default_match_changed || notify_default_match); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::UpdateAssociatedKeywords( 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteResult* result) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!keyword_provider_) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<string16> keywords; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ACMatches::iterator match(result->begin()); match != result->end(); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++match) { 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 keyword(match->GetSubstitutingExplicitlyInvokedKeyword(profile_)); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!keyword.empty()) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keywords.insert(keyword); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 keyword = match->associated_keyword.get() ? 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match->associated_keyword->keyword : 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_provider_->GetKeywordForText(match->fill_into_edit); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only add the keyword if the match does not have a duplicate keyword 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with a more relevant match. 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!keyword.empty() && !keywords.count(keyword)) { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keywords.insert(keyword); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!match->associated_keyword.get()) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match->associated_keyword.reset(new AutocompleteMatch( 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_provider_->CreateAutocompleteMatch(match->fill_into_edit, 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword, input_))); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match->associated_keyword.reset(); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::UpdateAssistedQueryStats( 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteResult* result) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result->empty()) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build the impressions string (the AQS part after "."). 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string autocompletions; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int last_type = -1; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ACMatches::iterator match(result->begin()); match != result->end(); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++match) { 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type = AutocompleteMatchToAssistedQueryType(match->type); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (last_type != -1 && type != last_type) { 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppendAvailableAutocompletion(last_type, count, &autocompletions); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count = 1; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count++; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_type = type; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppendAvailableAutocompletion(last_type, count, &autocompletions); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Go over all matches and set AQS if the match supports it. 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t index = 0; index < result->size(); ++index) { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteMatch* match = result->match_at(index); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* template_url = match->GetTemplateURL(profile_, false); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!template_url || !match->search_terms_args.get()) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match->search_terms_args->assisted_query_stats = 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPrintf("chrome.%" PRIuS ".%s", 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index, 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) autocompletions.c_str()); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match->destination_url = GURL(template_url->url_ref().ReplaceSearchTerms( 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *match->search_terms_args)); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GURL AutocompleteController::GetDestinationURL( 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const AutocompleteMatch& match, 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta query_formulation_time) const { 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL destination_url(match.destination_url); 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TemplateURL* template_url = match.GetTemplateURL(profile_, false); 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Append the query formulation time (time from when the user first typed a 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // character into the omnibox to when the user selected a query) and whether 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a field trial has triggered to the AQS parameter, if other AQS parameters 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // were already populated. 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (template_url && match.search_terms_args.get() && 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !match.search_terms_args->assisted_query_stats.empty()) { 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TemplateURLRef::SearchTermsArgs search_terms_args(*match.search_terms_args); 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) search_terms_args.assisted_query_stats += base::StringPrintf( 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ".%" PRId64 "j%d", 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) query_formulation_time.InMilliseconds(), 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) search_provider_ && 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) search_provider_->field_trial_triggered_in_session()); 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) destination_url = GURL(template_url->url_ref(). 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ReplaceSearchTerms(search_terms_args)); 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return destination_url; 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::UpdateKeywordDescriptions( 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteResult* result) { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 last_keyword; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (AutocompleteResult::iterator i(result->begin()); i != result->end(); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((i->provider->type() == AutocompleteProvider::TYPE_KEYWORD && 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !i->keyword.empty()) || 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (i->provider->type() == AutocompleteProvider::TYPE_SEARCH && 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteMatch::IsSearchType(i->type))) { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->description.clear(); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->description_class.clear(); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!i->keyword.empty()); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->keyword != last_keyword) { 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* template_url = i->GetTemplateURL(profile_, false); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (template_url) { 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->description = l10n_util::GetStringFUTF16( 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_AUTOCOMPLETE_SEARCH_DESCRIPTION, 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url->AdjustedShortNameForLocaleDirection()); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->description_class.push_back( 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACMatchClassification(0, ACMatchClassification::DIM)); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_keyword = i->keyword; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_keyword.clear(); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::NotifyChanged(bool notify_default_match) { 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delegate_) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnResultChanged(notify_default_match); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (done_) { 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::current()->Notify( 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY, 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<AutocompleteController>(this), 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::NoDetails()); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::CheckIfDone() { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(*i)->done()) { 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_ = false; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_ = true; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteController::StartExpireTimer() { 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result_.HasCopiedMatches()) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expire_timer_.Start(FROM_HERE, 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kExpireTimeMS), 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, &AutocompleteController::ExpireCopiedEntries); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 536