OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autocomplete/keyword_provider.h" | 5 #include "chrome/browser/autocomplete/keyword_provider.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/strings/string16.h" | 10 #include "base/strings/string16.h" |
11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
13 #include "chrome/browser/autocomplete/keyword_extensions_delegate.h" | 13 #include "chrome/browser/autocomplete/keyword_extensions_delegate.h" |
14 #include "chrome/browser/chrome_notification_types.h" | |
15 #include "chrome/browser/profiles/profile.h" | |
16 #include "chrome/browser/search_engines/template_url_service_factory.h" | |
17 #include "components/metrics/proto/omnibox_input_type.pb.h" | 14 #include "components/metrics/proto/omnibox_input_type.pb.h" |
18 #include "components/omnibox/autocomplete_match.h" | 15 #include "components/omnibox/autocomplete_match.h" |
19 #include "components/omnibox/autocomplete_provider_listener.h" | 16 #include "components/omnibox/autocomplete_provider_listener.h" |
20 #include "components/search_engines/template_url.h" | 17 #include "components/search_engines/template_url.h" |
21 #include "components/search_engines/template_url_service.h" | 18 #include "components/search_engines/template_url_service.h" |
22 #include "content/public/browser/notification_details.h" | |
23 #include "content/public/browser/notification_source.h" | |
24 #include "extensions/browser/extension_system.h" | |
25 #include "grit/generated_resources.h" | 19 #include "grit/generated_resources.h" |
26 #include "net/base/escape.h" | 20 #include "net/base/escape.h" |
27 #include "net/base/net_util.h" | 21 #include "net/base/net_util.h" |
28 #include "ui/base/l10n/l10n_util.h" | 22 #include "ui/base/l10n/l10n_util.h" |
29 | 23 |
30 #if defined(ENABLE_EXTENSIONS) | |
31 #include "chrome/browser/autocomplete/keyword_extensions_delegate_impl.h" | |
32 #endif | |
33 | |
34 namespace { | 24 namespace { |
35 | 25 |
36 // Helper functor for Start(), for sorting keyword matches by quality. | 26 // Helper functor for Start(), for sorting keyword matches by quality. |
37 class CompareQuality { | 27 class CompareQuality { |
38 public: | 28 public: |
39 // A keyword is of higher quality when a greater fraction of it has been | 29 // A keyword is of higher quality when a greater fraction of it has been |
40 // typed, that is, when it is shorter. | 30 // typed, that is, when it is shorter. |
41 // | 31 // |
42 // TODO(pkasting): Most recent and most frequent keywords are probably | 32 // TODO(pkasting): Most recent and most frequent keywords are probably |
43 // better rankings than the fraction of the keyword typed. We should | 33 // better rankings than the fraction of the keyword typed. We should |
(...skipping 28 matching lines...) Expand all Loading... | |
72 if (delegate_) | 62 if (delegate_) |
73 delegate_->MaybeEndExtensionKeywordMode(); | 63 delegate_->MaybeEndExtensionKeywordMode(); |
74 } | 64 } |
75 | 65 |
76 void ScopedEndExtensionKeywordMode::StayInKeywordMode() { | 66 void ScopedEndExtensionKeywordMode::StayInKeywordMode() { |
77 delegate_ = NULL; | 67 delegate_ = NULL; |
78 } | 68 } |
79 | 69 |
80 } // namespace | 70 } // namespace |
81 | 71 |
82 KeywordProvider::KeywordProvider(AutocompleteProviderListener* listener, | 72 KeywordProvider::KeywordProvider( |
83 Profile* profile) | 73 AutocompleteProviderListener* listener, |
74 TemplateURLService* model) | |
84 : AutocompleteProvider(AutocompleteProvider::TYPE_KEYWORD), | 75 : AutocompleteProvider(AutocompleteProvider::TYPE_KEYWORD), |
85 listener_(listener), | 76 listener_(listener), |
86 profile_(profile), | |
87 model_(NULL) { | |
88 #if defined(ENABLE_EXTENSIONS) | |
89 extensions_delegate_.reset(new KeywordExtensionsDelegateImpl(this)); | |
90 #endif | |
91 } | |
92 | |
93 KeywordProvider::KeywordProvider(AutocompleteProviderListener* listener, | |
94 TemplateURLService* model) | |
95 : AutocompleteProvider(AutocompleteProvider::TYPE_KEYWORD), | |
96 listener_(listener), | |
97 profile_(NULL), | |
98 model_(model) { | 77 model_(model) { |
99 } | 78 } |
100 | 79 |
80 void KeywordProvider::SetExtensionsDelegate( | |
81 scoped_ptr<KeywordExtensionsDelegate> extensions_delegate) { | |
82 extensions_delegate_ = extensions_delegate.Pass(); | |
Peter Kasting
2014/08/12 18:24:11
Nit: This could probably be inlined into the heade
hashimoto
2014/08/13 02:22:40
Done.
| |
83 } | |
84 | |
101 // static | 85 // static |
102 base::string16 KeywordProvider::SplitKeywordFromInput( | 86 base::string16 KeywordProvider::SplitKeywordFromInput( |
103 const base::string16& input, | 87 const base::string16& input, |
104 bool trim_leading_whitespace, | 88 bool trim_leading_whitespace, |
105 base::string16* remaining_input) { | 89 base::string16* remaining_input) { |
106 // Find end of first token. The AutocompleteController has trimmed leading | 90 // Find end of first token. The AutocompleteController has trimmed leading |
107 // whitespace, so we need not skip over that. | 91 // whitespace, so we need not skip over that. |
108 const size_t first_white(input.find_first_of(base::kWhitespaceUTF16)); | 92 const size_t first_white(input.find_first_of(base::kWhitespaceUTF16)); |
109 DCHECK_NE(0U, first_white); | 93 DCHECK_NE(0U, first_white); |
110 if (first_white == base::string16::npos) | 94 if (first_white == base::string16::npos) |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
196 // Don't provide a keyword if it doesn't support replacement. | 180 // Don't provide a keyword if it doesn't support replacement. |
197 const TemplateURL* const template_url = | 181 const TemplateURL* const template_url = |
198 url_service->GetTemplateURLForKeyword(keyword); | 182 url_service->GetTemplateURLForKeyword(keyword); |
199 if (!template_url || | 183 if (!template_url || |
200 !template_url->SupportsReplacement(url_service->search_terms_data())) | 184 !template_url->SupportsReplacement(url_service->search_terms_data())) |
201 return base::string16(); | 185 return base::string16(); |
202 | 186 |
203 // Don't provide a keyword for inactive/disabled extension keywords. | 187 // Don't provide a keyword for inactive/disabled extension keywords. |
204 if ((template_url->GetType() == TemplateURL::OMNIBOX_API_EXTENSION) && | 188 if ((template_url->GetType() == TemplateURL::OMNIBOX_API_EXTENSION) && |
205 extensions_delegate_ && | 189 extensions_delegate_ && |
206 !extensions_delegate_->IsEnabledExtension( | 190 !extensions_delegate_->IsEnabledExtension(template_url->GetExtensionId())) |
207 profile_, template_url->GetExtensionId())) | |
208 return base::string16(); | 191 return base::string16(); |
209 | 192 |
210 return keyword; | 193 return keyword; |
211 } | 194 } |
212 | 195 |
213 AutocompleteMatch KeywordProvider::CreateVerbatimMatch( | 196 AutocompleteMatch KeywordProvider::CreateVerbatimMatch( |
214 const base::string16& text, | 197 const base::string16& text, |
215 const base::string16& keyword, | 198 const base::string16& keyword, |
216 const AutocompleteInput& input) { | 199 const AutocompleteInput& input) { |
217 // A verbatim match is allowed to be the default match. | 200 // A verbatim match is allowed to be the default match. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
263 TemplateURLService::TemplateURLVector matches; | 246 TemplateURLService::TemplateURLVector matches; |
264 GetTemplateURLService()->FindMatchingKeywords( | 247 GetTemplateURLService()->FindMatchingKeywords( |
265 keyword, !remaining_input.empty(), &matches); | 248 keyword, !remaining_input.empty(), &matches); |
266 | 249 |
267 for (TemplateURLService::TemplateURLVector::iterator i(matches.begin()); | 250 for (TemplateURLService::TemplateURLVector::iterator i(matches.begin()); |
268 i != matches.end(); ) { | 251 i != matches.end(); ) { |
269 const TemplateURL* template_url = *i; | 252 const TemplateURL* template_url = *i; |
270 | 253 |
271 // Prune any extension keywords that are disallowed in incognito mode (if | 254 // Prune any extension keywords that are disallowed in incognito mode (if |
272 // we're incognito), or disabled. | 255 // we're incognito), or disabled. |
273 if (profile_ && | 256 if (template_url->GetType() == TemplateURL::OMNIBOX_API_EXTENSION && |
274 (template_url->GetType() == TemplateURL::OMNIBOX_API_EXTENSION) && | |
275 extensions_delegate_ && | 257 extensions_delegate_ && |
276 !extensions_delegate_->IsEnabledExtension( | 258 !extensions_delegate_->IsEnabledExtension( |
277 profile_, template_url->GetExtensionId())) { | 259 template_url->GetExtensionId())) { |
278 i = matches.erase(i); | 260 i = matches.erase(i); |
279 continue; | 261 continue; |
280 } | 262 } |
281 | 263 |
282 // Prune any substituting keywords if there is no substitution. | 264 // Prune any substituting keywords if there is no substitution. |
283 if (template_url->SupportsReplacement( | 265 if (template_url->SupportsReplacement( |
284 GetTemplateURLService()->search_terms_data()) && | 266 GetTemplateURLService()->search_terms_data()) && |
285 remaining_input.empty() && | 267 remaining_input.empty() && |
286 !input.allow_exact_keyword_match()) { | 268 !input.allow_exact_keyword_match()) { |
287 i = matches.erase(i); | 269 i = matches.erase(i); |
(...skipping 25 matching lines...) Expand all Loading... | |
313 | 295 |
314 // TODO(pkasting): We should probably check that if the user explicitly | 296 // TODO(pkasting): We should probably check that if the user explicitly |
315 // typed a scheme, that scheme matches the one in |template_url|. | 297 // typed a scheme, that scheme matches the one in |template_url|. |
316 | 298 |
317 // When creating an exact match (either for the keyword itself, no | 299 // When creating an exact match (either for the keyword itself, no |
318 // remaining query or an extension keyword, possibly with remaining | 300 // remaining query or an extension keyword, possibly with remaining |
319 // input), allow the match to be the default match. | 301 // input), allow the match to be the default match. |
320 matches_.push_back(CreateAutocompleteMatch( | 302 matches_.push_back(CreateAutocompleteMatch( |
321 template_url, input, keyword.length(), remaining_input, true, -1)); | 303 template_url, input, keyword.length(), remaining_input, true, -1)); |
322 | 304 |
323 if (profile_ && is_extension_keyword && extensions_delegate_) { | 305 if (is_extension_keyword && extensions_delegate_) { |
324 if (extensions_delegate_->Start(input, minimal_changes, template_url, | 306 if (extensions_delegate_->Start(input, minimal_changes, template_url, |
325 remaining_input)) | 307 remaining_input)) |
326 keyword_mode_toggle.StayInKeywordMode(); | 308 keyword_mode_toggle.StayInKeywordMode(); |
327 } | 309 } |
328 } else { | 310 } else { |
329 if (matches.size() > kMaxMatches) | 311 if (matches.size() > kMaxMatches) |
330 matches.erase(matches.begin() + kMaxMatches, matches.end()); | 312 matches.erase(matches.begin() + kMaxMatches, matches.end()); |
331 for (TemplateURLService::TemplateURLVector::const_iterator i( | 313 for (TemplateURLService::TemplateURLVector::const_iterator i( |
332 matches.begin()); i != matches.end(); ++i) { | 314 matches.begin()); i != matches.end(); ++i) { |
333 matches_.push_back(CreateAutocompleteMatch( | 315 matches_.push_back(CreateAutocompleteMatch( |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
480 remaining_input, | 462 remaining_input, |
481 &content_param_offsets)); | 463 &content_param_offsets)); |
482 DCHECK_EQ(2U, content_param_offsets.size()); | 464 DCHECK_EQ(2U, content_param_offsets.size()); |
483 AutocompleteMatch::ClassifyLocationInString(content_param_offsets[1], | 465 AutocompleteMatch::ClassifyLocationInString(content_param_offsets[1], |
484 remaining_input.length(), match->contents.length(), | 466 remaining_input.length(), match->contents.length(), |
485 ACMatchClassification::NONE, &match->contents_class); | 467 ACMatchClassification::NONE, &match->contents_class); |
486 } | 468 } |
487 } | 469 } |
488 | 470 |
489 TemplateURLService* KeywordProvider::GetTemplateURLService() const { | 471 TemplateURLService* KeywordProvider::GetTemplateURLService() const { |
490 TemplateURLService* service = profile_ ? | |
491 TemplateURLServiceFactory::GetForProfile(profile_) : model_; | |
492 // Make sure the model is loaded. This is cheap and quickly bails out if | 472 // Make sure the model is loaded. This is cheap and quickly bails out if |
493 // the model is already loaded. | 473 // the model is already loaded. |
494 DCHECK(service); | 474 model_->Load(); |
495 service->Load(); | 475 return model_; |
496 return service; | |
497 } | 476 } |
OLD | NEW |