| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 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 "components/omnibox/browser/search_provider.h" | 5 #include "components/omnibox/browser/search_provider.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 | 9 |
| 10 #include "base/base64.h" | 10 #include "base/base64.h" |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 // |template_url_service| can be null in tests. | 130 // |template_url_service| can be null in tests. |
| 131 if (template_url_service) | 131 if (template_url_service) |
| 132 template_url_service->AddObserver(this); | 132 template_url_service->AddObserver(this); |
| 133 } | 133 } |
| 134 | 134 |
| 135 // static | 135 // static |
| 136 std::string SearchProvider::GetSuggestMetadata(const AutocompleteMatch& match) { | 136 std::string SearchProvider::GetSuggestMetadata(const AutocompleteMatch& match) { |
| 137 return match.GetAdditionalInfo(kSuggestMetadataKey); | 137 return match.GetAdditionalInfo(kSuggestMetadataKey); |
| 138 } | 138 } |
| 139 | 139 |
| 140 void SearchProvider::RegisterDisplayedAnswers( |
| 141 const AutocompleteResult& result) { |
| 142 if (result.empty()) |
| 143 return; |
| 144 |
| 145 // The answer must be in the first or second slot to be considered. It should |
| 146 // only be in the second slot if AutocompleteController ranked a local search |
| 147 // history or a verbatim item higher than the answer. |
| 148 AutocompleteResult::const_iterator match = result.begin(); |
| 149 if (match->answer_contents.empty() && result.size() > 1) |
| 150 ++match; |
| 151 if (match->answer_contents.empty() || match->answer_type.empty() || |
| 152 match->fill_into_edit.empty()) |
| 153 return; |
| 154 |
| 155 // Valid answer encountered, cache it for further queries. |
| 156 answers_cache_.UpdateRecentAnswers(match->fill_into_edit, match->answer_type); |
| 157 } |
| 158 |
| 159 // static |
| 160 int SearchProvider::CalculateRelevanceForKeywordVerbatim( |
| 161 metrics::OmniboxInputType::Type type, |
| 162 bool allow_exact_keyword_match, |
| 163 bool prefer_keyword) { |
| 164 // This function is responsible for scoring verbatim query matches |
| 165 // for non-extension substituting keywords. |
| 166 // KeywordProvider::CalculateRelevance() scores all other types of |
| 167 // keyword verbatim matches. |
| 168 if (allow_exact_keyword_match && prefer_keyword) |
| 169 return 1500; |
| 170 return (allow_exact_keyword_match && |
| 171 (type == metrics::OmniboxInputType::QUERY)) ? |
| 172 1450 : 1100; |
| 173 } |
| 174 |
| 140 void SearchProvider::ResetSession() { | 175 void SearchProvider::ResetSession() { |
| 141 set_field_trial_triggered_in_session(false); | 176 set_field_trial_triggered_in_session(false); |
| 142 } | 177 } |
| 143 | 178 |
| 144 void SearchProvider::OnTemplateURLServiceChanged() { | |
| 145 // Only update matches at this time if we haven't already claimed we're done | |
| 146 // processing the query. | |
| 147 if (done_) | |
| 148 return; | |
| 149 | |
| 150 // Check that the engines we're using weren't renamed or deleted. (In short, | |
| 151 // require that an engine still exists with the keywords in use.) For each | |
| 152 // deleted engine, cancel the in-flight request if any, drop its suggestions, | |
| 153 // and, in the case when the default provider was affected, point the cached | |
| 154 // default provider keyword name at the new name for the default provider. | |
| 155 | |
| 156 // Get...ProviderURL() looks up the provider using the cached keyword name | |
| 157 // stored in |providers_|. | |
| 158 const TemplateURL* template_url = providers_.GetDefaultProviderURL(); | |
| 159 if (!template_url) { | |
| 160 CancelFetcher(&default_fetcher_); | |
| 161 default_results_.Clear(); | |
| 162 providers_.set(client() | |
| 163 ->GetTemplateURLService() | |
| 164 ->GetDefaultSearchProvider() | |
| 165 ->keyword(), | |
| 166 providers_.keyword_provider()); | |
| 167 } | |
| 168 template_url = providers_.GetKeywordProviderURL(); | |
| 169 if (!providers_.keyword_provider().empty() && !template_url) { | |
| 170 CancelFetcher(&keyword_fetcher_); | |
| 171 keyword_results_.Clear(); | |
| 172 providers_.set(providers_.default_provider(), base::string16()); | |
| 173 } | |
| 174 // It's possible the template URL changed without changing associated keyword. | |
| 175 // Hence, it's always necessary to update matches to use the new template | |
| 176 // URL. (One could cache the template URL and only call UpdateMatches() and | |
| 177 // OnProviderUpdate() if a keyword was deleted/renamed or the template URL | |
| 178 // was changed. That would save extra calls to these functions. However, | |
| 179 // this is uncommon and not likely to be worth the extra work.) | |
| 180 UpdateMatches(); | |
| 181 listener_->OnProviderUpdate(true); // always pretend something changed | |
| 182 } | |
| 183 | |
| 184 SearchProvider::~SearchProvider() { | 179 SearchProvider::~SearchProvider() { |
| 185 TemplateURLService* template_url_service = client()->GetTemplateURLService(); | 180 TemplateURLService* template_url_service = client()->GetTemplateURLService(); |
| 186 if (template_url_service) | 181 if (template_url_service) |
| 187 template_url_service->RemoveObserver(this); | 182 template_url_service->RemoveObserver(this); |
| 188 } | 183 } |
| 189 | 184 |
| 190 // static | 185 // static |
| 191 int SearchProvider::CalculateRelevanceForKeywordVerbatim( | |
| 192 metrics::OmniboxInputType::Type type, | |
| 193 bool prefer_keyword) { | |
| 194 // This function is responsible for scoring verbatim query matches | |
| 195 // for non-extension keywords. KeywordProvider::CalculateRelevance() | |
| 196 // scores verbatim query matches for extension keywords, as well as | |
| 197 // for keyword matches (i.e., suggestions of a keyword itself, not a | |
| 198 // suggestion of a query on a keyword search engine). These two | |
| 199 // functions are currently in sync, but there's no reason we | |
| 200 // couldn't decide in the future to score verbatim matches | |
| 201 // differently for extension and non-extension keywords. If you | |
| 202 // make such a change, however, you should update this comment to | |
| 203 // describe it, so it's clear why the functions diverge. | |
| 204 if (prefer_keyword) | |
| 205 return 1500; | |
| 206 return (type == metrics::OmniboxInputType::QUERY) ? 1450 : 1100; | |
| 207 } | |
| 208 | |
| 209 // static | |
| 210 void SearchProvider::UpdateOldResults( | 186 void SearchProvider::UpdateOldResults( |
| 211 bool minimal_changes, | 187 bool minimal_changes, |
| 212 SearchSuggestionParser::Results* results) { | 188 SearchSuggestionParser::Results* results) { |
| 213 // When called without |minimal_changes|, it likely means the user has | 189 // When called without |minimal_changes|, it likely means the user has |
| 214 // pressed a key. Revise the cached results appropriately. | 190 // pressed a key. Revise the cached results appropriately. |
| 215 if (!minimal_changes) { | 191 if (!minimal_changes) { |
| 216 for (SearchSuggestionParser::SuggestResults::iterator sug_it = | 192 for (SearchSuggestionParser::SuggestResults::iterator sug_it = |
| 217 results->suggest_results.begin(); | 193 results->suggest_results.begin(); |
| 218 sug_it != results->suggest_results.end(); ) { | 194 sug_it != results->suggest_results.end(); ) { |
| 219 if (sug_it->type() == AutocompleteMatchType::CALCULATOR) { | 195 if (sug_it->type() == AutocompleteMatchType::CALCULATOR) { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 void SearchProvider::RecordDeletionResult(bool success) { | 337 void SearchProvider::RecordDeletionResult(bool success) { |
| 362 if (success) { | 338 if (success) { |
| 363 base::RecordAction( | 339 base::RecordAction( |
| 364 base::UserMetricsAction("Omnibox.ServerSuggestDelete.Success")); | 340 base::UserMetricsAction("Omnibox.ServerSuggestDelete.Success")); |
| 365 } else { | 341 } else { |
| 366 base::RecordAction( | 342 base::RecordAction( |
| 367 base::UserMetricsAction("Omnibox.ServerSuggestDelete.Failure")); | 343 base::UserMetricsAction("Omnibox.ServerSuggestDelete.Failure")); |
| 368 } | 344 } |
| 369 } | 345 } |
| 370 | 346 |
| 347 void SearchProvider::OnTemplateURLServiceChanged() { |
| 348 // Only update matches at this time if we haven't already claimed we're done |
| 349 // processing the query. |
| 350 if (done_) |
| 351 return; |
| 352 |
| 353 // Check that the engines we're using weren't renamed or deleted. (In short, |
| 354 // require that an engine still exists with the keywords in use.) For each |
| 355 // deleted engine, cancel the in-flight request if any, drop its suggestions, |
| 356 // and, in the case when the default provider was affected, point the cached |
| 357 // default provider keyword name at the new name for the default provider. |
| 358 |
| 359 // Get...ProviderURL() looks up the provider using the cached keyword name |
| 360 // stored in |providers_|. |
| 361 const TemplateURL* template_url = providers_.GetDefaultProviderURL(); |
| 362 if (!template_url) { |
| 363 CancelFetcher(&default_fetcher_); |
| 364 default_results_.Clear(); |
| 365 providers_.set(client() |
| 366 ->GetTemplateURLService() |
| 367 ->GetDefaultSearchProvider() |
| 368 ->keyword(), |
| 369 providers_.keyword_provider()); |
| 370 } |
| 371 template_url = providers_.GetKeywordProviderURL(); |
| 372 if (!providers_.keyword_provider().empty() && !template_url) { |
| 373 CancelFetcher(&keyword_fetcher_); |
| 374 keyword_results_.Clear(); |
| 375 providers_.set(providers_.default_provider(), base::string16()); |
| 376 } |
| 377 // It's possible the template URL changed without changing associated keyword. |
| 378 // Hence, it's always necessary to update matches to use the new template |
| 379 // URL. (One could cache the template URL and only call UpdateMatches() and |
| 380 // OnProviderUpdate() if a keyword was deleted/renamed or the template URL |
| 381 // was changed. That would save extra calls to these functions. However, |
| 382 // this is uncommon and not likely to be worth the extra work.) |
| 383 UpdateMatches(); |
| 384 listener_->OnProviderUpdate(true); // always pretend something changed |
| 385 } |
| 386 |
| 371 void SearchProvider::OnURLFetchComplete(const net::URLFetcher* source) { | 387 void SearchProvider::OnURLFetchComplete(const net::URLFetcher* source) { |
| 372 DCHECK(!done_); | 388 DCHECK(!done_); |
| 373 const bool is_keyword = source == keyword_fetcher_.get(); | 389 const bool is_keyword = source == keyword_fetcher_.get(); |
| 374 | 390 |
| 375 // Ensure the request succeeded and that the provider used is still available. | 391 // Ensure the request succeeded and that the provider used is still available. |
| 376 // A verbatim match cannot be generated without this provider, causing errors. | 392 // A verbatim match cannot be generated without this provider, causing errors. |
| 377 const bool request_succeeded = | 393 const bool request_succeeded = |
| 378 source->GetStatus().is_success() && (source->GetResponseCode() == 200) && | 394 source->GetStatus().is_success() && (source->GetResponseCode() == 200) && |
| 379 GetTemplateURL(is_keyword); | 395 GetTemplateURL(is_keyword); |
| 380 | 396 |
| (...skipping 936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1317 (keyword_results_.verbatim_relevance >= 0) && | 1333 (keyword_results_.verbatim_relevance >= 0) && |
| 1318 !input_.prevent_inline_autocomplete() && | 1334 !input_.prevent_inline_autocomplete() && |
| 1319 ((keyword_results_.verbatim_relevance > 0) || | 1335 ((keyword_results_.verbatim_relevance > 0) || |
| 1320 !keyword_results_.suggest_results.empty() || | 1336 !keyword_results_.suggest_results.empty() || |
| 1321 !keyword_results_.navigation_results.empty()); | 1337 !keyword_results_.navigation_results.empty()); |
| 1322 if (relevance_from_server) | 1338 if (relevance_from_server) |
| 1323 *relevance_from_server = use_server_relevance; | 1339 *relevance_from_server = use_server_relevance; |
| 1324 return use_server_relevance ? | 1340 return use_server_relevance ? |
| 1325 keyword_results_.verbatim_relevance : | 1341 keyword_results_.verbatim_relevance : |
| 1326 CalculateRelevanceForKeywordVerbatim(keyword_input_.type(), | 1342 CalculateRelevanceForKeywordVerbatim(keyword_input_.type(), |
| 1343 true, |
| 1327 keyword_input_.prefer_keyword()); | 1344 keyword_input_.prefer_keyword()); |
| 1328 } | 1345 } |
| 1329 | 1346 |
| 1330 int SearchProvider::CalculateRelevanceForHistory( | 1347 int SearchProvider::CalculateRelevanceForHistory( |
| 1331 const base::Time& time, | 1348 const base::Time& time, |
| 1332 bool is_keyword, | 1349 bool is_keyword, |
| 1333 bool use_aggressive_method, | 1350 bool use_aggressive_method, |
| 1334 bool prevent_search_history_inlining) const { | 1351 bool prevent_search_history_inlining) const { |
| 1335 // The relevance of past searches falls off over time. There are two distinct | 1352 // The relevance of past searches falls off over time. There are two distinct |
| 1336 // equations used. If the first equation is used (searches to the primary | 1353 // equations used. If the first equation is used (searches to the primary |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1465 std::replace(current_token_.begin(), current_token_.end(), '+', '-'); | 1482 std::replace(current_token_.begin(), current_token_.end(), '+', '-'); |
| 1466 std::replace(current_token_.begin(), current_token_.end(), '/', '_'); | 1483 std::replace(current_token_.begin(), current_token_.end(), '/', '_'); |
| 1467 } | 1484 } |
| 1468 | 1485 |
| 1469 // Extend expiration time another 60 seconds. | 1486 // Extend expiration time another 60 seconds. |
| 1470 token_expiration_time_ = current_time + base::TimeDelta::FromSeconds(60); | 1487 token_expiration_time_ = current_time + base::TimeDelta::FromSeconds(60); |
| 1471 | 1488 |
| 1472 return current_token_; | 1489 return current_token_; |
| 1473 } | 1490 } |
| 1474 | 1491 |
| 1475 void SearchProvider::RegisterDisplayedAnswers( | |
| 1476 const AutocompleteResult& result) { | |
| 1477 if (result.empty()) | |
| 1478 return; | |
| 1479 | |
| 1480 // The answer must be in the first or second slot to be considered. It should | |
| 1481 // only be in the second slot if AutocompleteController ranked a local search | |
| 1482 // history or a verbatim item higher than the answer. | |
| 1483 AutocompleteResult::const_iterator match = result.begin(); | |
| 1484 if (match->answer_contents.empty() && result.size() > 1) | |
| 1485 ++match; | |
| 1486 if (match->answer_contents.empty() || match->answer_type.empty() || | |
| 1487 match->fill_into_edit.empty()) | |
| 1488 return; | |
| 1489 | |
| 1490 // Valid answer encountered, cache it for further queries. | |
| 1491 answers_cache_.UpdateRecentAnswers(match->fill_into_edit, match->answer_type); | |
| 1492 } | |
| 1493 | |
| 1494 AnswersQueryData SearchProvider::FindAnswersPrefetchData() { | 1492 AnswersQueryData SearchProvider::FindAnswersPrefetchData() { |
| 1495 // Retrieve the top entry from scored history results. | 1493 // Retrieve the top entry from scored history results. |
| 1496 MatchMap map; | 1494 MatchMap map; |
| 1497 AddTransformedHistoryResultsToMap(transformed_keyword_history_results_, | 1495 AddTransformedHistoryResultsToMap(transformed_keyword_history_results_, |
| 1498 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, | 1496 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, |
| 1499 &map); | 1497 &map); |
| 1500 AddTransformedHistoryResultsToMap(transformed_default_history_results_, | 1498 AddTransformedHistoryResultsToMap(transformed_default_history_results_, |
| 1501 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, | 1499 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, |
| 1502 &map); | 1500 &map); |
| 1503 | 1501 |
| 1504 ACMatches matches; | 1502 ACMatches matches; |
| 1505 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) | 1503 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) |
| 1506 matches.push_back(i->second); | 1504 matches.push_back(i->second); |
| 1507 std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant); | 1505 std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant); |
| 1508 | 1506 |
| 1509 // If there is a top scoring entry, find the corresponding answer. | 1507 // If there is a top scoring entry, find the corresponding answer. |
| 1510 if (!matches.empty()) | 1508 if (!matches.empty()) |
| 1511 return answers_cache_.GetTopAnswerEntry(matches[0].contents); | 1509 return answers_cache_.GetTopAnswerEntry(matches[0].contents); |
| 1512 | 1510 |
| 1513 return AnswersQueryData(); | 1511 return AnswersQueryData(); |
| 1514 } | 1512 } |
| OLD | NEW |