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