1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/omnibox/browser/autocomplete_classifier.h"
6 
7 #include <utility>
8 
9 #include "base/auto_reset.h"
10 #include "base/feature_list.h"
11 #include "base/ios/ios_util.h"
12 #include "build/build_config.h"
13 #include "components/omnibox/browser/autocomplete_controller.h"
14 #include "components/omnibox/browser/autocomplete_input.h"
15 #include "components/omnibox/browser/autocomplete_match.h"
16 #include "components/omnibox/browser/autocomplete_provider.h"
17 #include "components/omnibox/browser/document_provider.h"
18 #include "components/omnibox/browser/omnibox_field_trial.h"
19 #include "components/omnibox/common/omnibox_features.h"
20 #include "components/query_tiles/switches.h"
21 #include "third_party/metrics_proto/omnibox_event.pb.h"
22 #include "url/gurl.h"
23 
AutocompleteClassifier(std::unique_ptr<AutocompleteController> controller,std::unique_ptr<AutocompleteSchemeClassifier> scheme_classifier)24 AutocompleteClassifier::AutocompleteClassifier(
25     std::unique_ptr<AutocompleteController> controller,
26     std::unique_ptr<AutocompleteSchemeClassifier> scheme_classifier)
27     : controller_(std::move(controller)),
28       scheme_classifier_(std::move(scheme_classifier)),
29       inside_classify_(false) {}
30 
~AutocompleteClassifier()31 AutocompleteClassifier::~AutocompleteClassifier() {
32   // We should only reach here after Shutdown() has been called.
33   DCHECK(!controller_);
34 }
35 
Shutdown()36 void AutocompleteClassifier::Shutdown() {
37   controller_.reset();
38 }
39 
40 // static
DefaultOmniboxProviders()41 int AutocompleteClassifier::DefaultOmniboxProviders() {
42   return
43 #if !defined(OS_ANDROID) && !defined(OS_IOS)
44       // Custom search engines cannot be used on mobile.
45       AutocompleteProvider::TYPE_KEYWORD |
46 #else
47       AutocompleteProvider::TYPE_CLIPBOARD |
48       AutocompleteProvider::TYPE_MOST_VISITED_SITES |
49       AutocompleteProvider::TYPE_VERBATIM_MATCH |
50 #endif
51       AutocompleteProvider::TYPE_ZERO_SUGGEST |
52       AutocompleteProvider::TYPE_ZERO_SUGGEST_LOCAL_HISTORY |
53       (base::FeatureList::IsEnabled(omnibox::kDocumentProvider)
54            ? AutocompleteProvider::TYPE_DOCUMENT
55            : 0) |
56       (OmniboxFieldTrial::IsOnDeviceHeadSuggestEnabledForAnyMode()
57            ? AutocompleteProvider::TYPE_ON_DEVICE_HEAD
58            : 0) |
59       AutocompleteProvider::TYPE_BOOKMARK | AutocompleteProvider::TYPE_BUILTIN |
60       AutocompleteProvider::TYPE_HISTORY_QUICK |
61       AutocompleteProvider::TYPE_HISTORY_URL |
62       AutocompleteProvider::TYPE_SEARCH | AutocompleteProvider::TYPE_SHORTCUTS |
63       (query_tiles::features::IsEnabledQueryTilesInOmnibox()
64            ? AutocompleteProvider::TYPE_QUERY_TILE
65            : 0);
66 }
67 
Classify(const base::string16 & text,bool prefer_keyword,bool allow_exact_keyword_match,metrics::OmniboxEventProto::PageClassification page_classification,AutocompleteMatch * match,GURL * alternate_nav_url)68 void AutocompleteClassifier::Classify(
69     const base::string16& text,
70     bool prefer_keyword,
71     bool allow_exact_keyword_match,
72     metrics::OmniboxEventProto::PageClassification page_classification,
73     AutocompleteMatch* match,
74     GURL* alternate_nav_url) {
75   DCHECK(!inside_classify_);
76   base::AutoReset<bool> reset(&inside_classify_, true);
77   AutocompleteInput input(text, page_classification, *scheme_classifier_);
78   input.set_prevent_inline_autocomplete(true);
79   // If the user in keyword mode (which is often the case when |prefer_keyword|
80   // is true), ideally we'd set |input|'s keyword_mode_entry_method field.
81   // However, in the context of this code, we don't know how the keyword mode
82   // was entered. Moreover, we cannot add that as a parameter to Classify()
83   // because many callers do not know how keyword mode was entered. Luckily,
84   // Classify()'s purpose is to determine the default match, and at this time
85   // |keyword_mode_entry_method| only ends up affecting the ranking of
86   // lower-down suggestions.
87   input.set_prefer_keyword(prefer_keyword);
88   input.set_allow_exact_keyword_match(allow_exact_keyword_match);
89   input.set_want_asynchronous_matches(false);
90   controller_->Start(input);
91   DCHECK(controller_->done());
92 
93   auto* default_match = controller_->result().default_match();
94   if (!default_match) {
95     if (alternate_nav_url)
96       *alternate_nav_url = GURL();
97     return;
98   }
99 
100   *match = *default_match;
101   if (alternate_nav_url) {
102     *alternate_nav_url = AutocompleteResult::ComputeAlternateNavUrl(
103         input, *match, controller_->autocomplete_provider_client());
104   }
105 }
106