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 "chrome/browser/autocomplete/search_provider.h" | 5 #include "chrome/browser/autocomplete/search_provider.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1201 std::string(), | 1201 std::string(), |
1202 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, | 1202 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, |
1203 false, | 1203 false, |
1204 input_.text(), | 1204 input_.text(), |
1205 string16(), | 1205 string16(), |
1206 input_.text(), | 1206 input_.text(), |
1207 did_not_accept_default_suggestion, | 1207 did_not_accept_default_suggestion, |
1208 std::string(), | 1208 std::string(), |
1209 &map); | 1209 &map); |
1210 } | 1210 } |
1211 const TemplateURL* keyword_url = NULL; | |
1211 if (!keyword_input_.text().empty()) { | 1212 if (!keyword_input_.text().empty()) { |
1212 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); | 1213 keyword_url = providers_.GetKeywordProviderURL(); |
1213 // We only create the verbatim search query match for a keyword | 1214 // We only create the verbatim search query match for a keyword |
1214 // if it's not an extension keyword. Extension keywords are handled | 1215 // if it's not an extension keyword. Extension keywords are handled |
1215 // in KeywordProvider::Start(). (Extensions are complicated...) | 1216 // in KeywordProvider::Start(). (Extensions are complicated...) |
1216 // Note: in this provider, SEARCH_OTHER_ENGINE must correspond | 1217 // Note: in this provider, SEARCH_OTHER_ENGINE must correspond |
1217 // to the keyword verbatim search query. Do not create other matches | 1218 // to the keyword verbatim search query. Do not create other matches |
1218 // of type SEARCH_OTHER_ENGINE. | 1219 // of type SEARCH_OTHER_ENGINE. |
1219 if (keyword_url && | 1220 if (keyword_url && |
1220 (keyword_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION)) { | 1221 (keyword_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION)) { |
1221 bool keyword_relevance_from_server; | 1222 bool keyword_relevance_from_server; |
1222 const int keyword_verbatim_relevance = | 1223 const int keyword_verbatim_relevance = |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1300 ACMatches::const_iterator SearchProvider::FindTopMatch( | 1301 ACMatches::const_iterator SearchProvider::FindTopMatch( |
1301 bool autocomplete_result_will_reorder_for_default_match) const { | 1302 bool autocomplete_result_will_reorder_for_default_match) const { |
1302 if (!autocomplete_result_will_reorder_for_default_match) | 1303 if (!autocomplete_result_will_reorder_for_default_match) |
1303 return matches_.begin(); | 1304 return matches_.begin(); |
1304 ACMatches::const_iterator it = matches_.begin(); | 1305 ACMatches::const_iterator it = matches_.begin(); |
1305 while ((it != matches_.end()) && !it->allowed_to_be_default_match) | 1306 while ((it != matches_.end()) && !it->allowed_to_be_default_match) |
1306 ++it; | 1307 ++it; |
1307 return it; | 1308 return it; |
1308 } | 1309 } |
1309 | 1310 |
1310 bool SearchProvider::IsTopMatchNavigationInKeywordMode( | 1311 bool SearchProvider::IsTopMatchNavigation( |
1311 bool autocomplete_result_will_reorder_for_default_match) const { | 1312 bool autocomplete_result_will_reorder_for_default_match) const { |
1312 ACMatches::const_iterator first_match = | 1313 ACMatches::const_iterator first_match = |
1313 FindTopMatch(autocomplete_result_will_reorder_for_default_match); | 1314 FindTopMatch(autocomplete_result_will_reorder_for_default_match); |
1314 return !providers_.keyword_provider().empty() && | 1315 return (first_match != matches_.end()) && |
1315 (first_match != matches_.end()) && | |
1316 (first_match->type == AutocompleteMatchType::NAVSUGGEST); | 1316 (first_match->type == AutocompleteMatchType::NAVSUGGEST); |
1317 } | 1317 } |
1318 | 1318 |
1319 bool SearchProvider::HasKeywordMatchThatCanBeDefault( | |
1320 bool autocomplete_result_will_reorder_for_default_match) const { | |
1321 // In regular (non-reorder) mode we don't care about the | |
1322 // |allowed_to_be_default_match| state, so return true saying | |
1323 // everything is fine. | |
1324 if (!autocomplete_result_will_reorder_for_default_match) | |
1325 return true; | |
1326 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); | |
1327 if (keyword_url == NULL) // not in keyword mode -> say everything's okay | |
1328 return true; | |
1329 for (ACMatches::const_iterator it = matches_.begin(); it != matches_.end(); | |
1330 ++it) { | |
1331 if ((it->keyword == keyword_url->keyword()) && | |
1332 it->allowed_to_be_default_match) | |
1333 return true; | |
1334 } | |
1335 return false; | |
1336 } | |
1337 | |
1319 bool SearchProvider::IsTopMatchScoreTooLow( | 1338 bool SearchProvider::IsTopMatchScoreTooLow( |
1320 bool autocomplete_result_will_reorder_for_default_match) const { | 1339 bool autocomplete_result_will_reorder_for_default_match) const { |
1321 // In reorder mode, there's no such thing as a score that's too low. | 1340 // In reorder mode, there's no such thing as a score that's too low. |
1322 if (autocomplete_result_will_reorder_for_default_match) | 1341 if (autocomplete_result_will_reorder_for_default_match) |
1323 return false; | 1342 return false; |
1324 | 1343 |
1325 // Here we use CalculateRelevanceForVerbatimIgnoringKeywordModeState() | 1344 // Here we use CalculateRelevanceForVerbatimIgnoringKeywordModeState() |
1326 // rather than CalculateRelevanceForVerbatim() because the latter returns | 1345 // rather than CalculateRelevanceForVerbatim() because the latter returns |
1327 // a very low score (250) if keyword mode is active. This is because | 1346 // a very low score (250) if keyword mode is active. This is because |
1328 // when keyword mode is active the user probably wants the keyword matches, | 1347 // when keyword mode is active the user probably wants the keyword matches, |
(...skipping 28 matching lines...) Expand all Loading... | |
1357 if (it->allowed_to_be_default_match) | 1376 if (it->allowed_to_be_default_match) |
1358 return true; | 1377 return true; |
1359 if (!autocomplete_result_will_reorder_for_default_match) | 1378 if (!autocomplete_result_will_reorder_for_default_match) |
1360 return false; | 1379 return false; |
1361 } | 1380 } |
1362 return false; | 1381 return false; |
1363 } | 1382 } |
1364 | 1383 |
1365 void SearchProvider::UpdateMatches() { | 1384 void SearchProvider::UpdateMatches() { |
1366 base::TimeTicks update_matches_start_time(base::TimeTicks::Now()); | 1385 base::TimeTicks update_matches_start_time(base::TimeTicks::Now()); |
1386 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); | |
1367 ConvertResultsToAutocompleteMatches(); | 1387 ConvertResultsToAutocompleteMatches(); |
1368 | 1388 |
1389 // True if the omnibox will reorder matches as necessary to make the first | |
1390 // one something that is allowed to be the default match. | |
1391 const bool omnibox_will_reorder_for_legal_default_match = | |
1392 OmniboxFieldTrial::ReorderForLegalDefaultMatch( | |
1393 input_.current_page_classification()); | |
1394 | |
1369 // Check constraints that may be violated by suggested relevances. | 1395 // Check constraints that may be violated by suggested relevances. |
1370 if (!matches_.empty() && | 1396 if (!matches_.empty() && |
1371 (default_results_.HasServerProvidedScores() || | 1397 (default_results_.HasServerProvidedScores() || |
1372 keyword_results_.HasServerProvidedScores())) { | 1398 keyword_results_.HasServerProvidedScores())) { |
1373 // These blocks attempt to repair undesirable behavior by suggested | 1399 // These blocks attempt to repair undesirable behavior by suggested |
1374 // relevances with minimal impact, preserving other suggested relevances. | 1400 // relevances with minimal impact, preserving other suggested relevances. |
1375 | 1401 |
1376 // True if the omnibox will reorder matches as necessary to make the first | 1402 if ((keyword_url != NULL) && |
1377 // one something that is allowed to be the default match. | 1403 IsTopMatchNavigation(omnibox_will_reorder_for_legal_default_match)) { |
1378 const bool omnibox_will_reorder_for_legal_default_match = | |
1379 OmniboxFieldTrial::ReorderForLegalDefaultMatch( | |
1380 input_.current_page_classification()); | |
1381 if (IsTopMatchNavigationInKeywordMode( | |
1382 omnibox_will_reorder_for_legal_default_match)) { | |
1383 // Correct the suggested relevance scores if the top match is a | 1404 // Correct the suggested relevance scores if the top match is a |
1384 // navigation in keyword mode, since inlining a navigation match | 1405 // navigation in keyword mode, since inlining a navigation match |
1385 // would break the user out of keyword mode. By the way, if the top | 1406 // would break the user out of keyword mode. We only need to do this |
1386 // match is a non-keyword match (query or navsuggestion) in keyword | 1407 // correction in regular (non-reorder) mode; in reorder mode, we rely |
1387 // mode, the user would also break out of keyword mode. However, | 1408 // on the fact that navigation matches are marked as not allowed to be |
1388 // that situation is impossible given the current scoring paradigm | 1409 // the default match. |
1389 // and the fact that only one search engine (Google) provides suggested | |
1390 // relevance scores at this time. | |
1391 DemoteKeywordNavigationMatchesPastTopQuery(); | 1410 DemoteKeywordNavigationMatchesPastTopQuery(); |
1392 ConvertResultsToAutocompleteMatches(); | 1411 ConvertResultsToAutocompleteMatches(); |
1393 DCHECK(!IsTopMatchNavigationInKeywordMode( | 1412 DCHECK(!IsTopMatchNavigation( |
1394 omnibox_will_reorder_for_legal_default_match)); | 1413 omnibox_will_reorder_for_legal_default_match)); |
1395 } | 1414 } |
1415 if ((keyword_url != NULL) && !HasKeywordMatchThatCanBeDefault( | |
1416 omnibox_will_reorder_for_legal_default_match)) { | |
1417 // In keyword mode, disregard the keyword verbatim suggested relevance | |
1418 // if necessary so there at least one keyword match that's allowed to | |
1419 // be the default match. | |
1420 keyword_results_.verbatim_relevance = -1; | |
1421 ConvertResultsToAutocompleteMatches(); | |
1422 } | |
1396 if (IsTopMatchScoreTooLow(omnibox_will_reorder_for_legal_default_match)) { | 1423 if (IsTopMatchScoreTooLow(omnibox_will_reorder_for_legal_default_match)) { |
1397 // Disregard the suggested verbatim relevance if the top score is below | 1424 // Disregard the suggested verbatim relevance if the top score is below |
1398 // the usual verbatim value. For example, a BarProvider may rely on | 1425 // the usual verbatim value. For example, a BarProvider may rely on |
1399 // SearchProvider's verbatim or inlineable matches for input "foo" (all | 1426 // SearchProvider's verbatim or inlineable matches for input "foo" (all |
1400 // allowed to be default match) to always outrank its own lowly-ranked | 1427 // allowed to be default match) to always outrank its own lowly-ranked |
1401 // "bar" matches that shouldn't be the default match. | 1428 // "bar" matches that shouldn't be the default match. |
1402 default_results_.verbatim_relevance = -1; | 1429 default_results_.verbatim_relevance = -1; |
1403 keyword_results_.verbatim_relevance = -1; | 1430 keyword_results_.verbatim_relevance = -1; |
1404 ConvertResultsToAutocompleteMatches(); | 1431 ConvertResultsToAutocompleteMatches(); |
1405 } | 1432 } |
(...skipping 16 matching lines...) Expand all Loading... | |
1422 // match or inlinable). For example, input "foo" should not invoke a | 1449 // match or inlinable). For example, input "foo" should not invoke a |
1423 // search for "bar", which would happen if the "bar" search match | 1450 // search for "bar", which would happen if the "bar" search match |
1424 // outranked all other matches. On the other hand, if the omnibox will | 1451 // outranked all other matches. On the other hand, if the omnibox will |
1425 // reorder matches as necessary to put a legal default match at the top, | 1452 // reorder matches as necessary to put a legal default match at the top, |
1426 // all we need to guarantee is that SearchProvider returns a legal | 1453 // all we need to guarantee is that SearchProvider returns a legal |
1427 // default match. (The omnibox always needs at least one legal default | 1454 // default match. (The omnibox always needs at least one legal default |
1428 // match, and it relies on SearchProvider to always return one.) | 1455 // match, and it relies on SearchProvider to always return one.) |
1429 ApplyCalculatedRelevance(); | 1456 ApplyCalculatedRelevance(); |
1430 ConvertResultsToAutocompleteMatches(); | 1457 ConvertResultsToAutocompleteMatches(); |
1431 } | 1458 } |
1432 DCHECK(!IsTopMatchNavigationInKeywordMode( | 1459 DCHECK((keyword_url == NULL) || |
1460 !IsTopMatchNavigation(omnibox_will_reorder_for_legal_default_match)); | |
1461 DCHECK((keyword_url == NULL) || HasKeywordMatchThatCanBeDefault( | |
1433 omnibox_will_reorder_for_legal_default_match)); | 1462 omnibox_will_reorder_for_legal_default_match)); |
1434 DCHECK(!IsTopMatchScoreTooLow( | 1463 DCHECK(!IsTopMatchScoreTooLow( |
1435 omnibox_will_reorder_for_legal_default_match)); | 1464 omnibox_will_reorder_for_legal_default_match)); |
1436 DCHECK(!IsTopMatchSearchWithURLInput( | 1465 DCHECK(!IsTopMatchSearchWithURLInput( |
1437 omnibox_will_reorder_for_legal_default_match)); | 1466 omnibox_will_reorder_for_legal_default_match)); |
1438 DCHECK(HasValidDefaultMatch(omnibox_will_reorder_for_legal_default_match)); | 1467 DCHECK(HasValidDefaultMatch(omnibox_will_reorder_for_legal_default_match)); |
1439 } | 1468 } |
1440 | 1469 |
1470 if ((keyword_url != NULL) && HasKeywordMatchThatCanBeDefault( | |
1471 omnibox_will_reorder_for_legal_default_match)) { | |
1472 // If there is a keyword match that is allowed to be the default match, | |
Mark P
2013/11/17 02:18:34
I can move this block into a subroutine if you app
| |
1473 // then prohibit default provider matches from being the defaul match lest | |
1474 // such matches cause the user to break out of keyword mode. | |
1475 for (ACMatches::const_iterator keyword_match_it = matches_.begin(); | |
1476 keyword_match_it != matches_.end(); ++keyword_match_it) { | |
1477 if (keyword_match_it->allowed_to_be_default_match && | |
1478 (keyword_match_it->keyword == keyword_url->keyword())) { | |
1479 // Found one such match. | |
1480 for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); | |
1481 ++it) { | |
1482 if (it->keyword != keyword_url->keyword()) | |
1483 it->allowed_to_be_default_match = false; | |
1484 } | |
1485 break; | |
1486 } | |
1487 } | |
1488 } | |
1489 | |
1441 base::TimeTicks update_starred_start_time(base::TimeTicks::Now()); | 1490 base::TimeTicks update_starred_start_time(base::TimeTicks::Now()); |
1442 UpdateStarredStateOfMatches(); | 1491 UpdateStarredStateOfMatches(); |
1443 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.UpdateStarredTime", | 1492 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.UpdateStarredTime", |
1444 base::TimeTicks::Now() - update_starred_start_time); | 1493 base::TimeTicks::Now() - update_starred_start_time); |
1445 UpdateDone(); | 1494 UpdateDone(); |
1446 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.UpdateMatchesTime", | 1495 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.UpdateMatchesTime", |
1447 base::TimeTicks::Now() - update_matches_start_time); | 1496 base::TimeTicks::Now() - update_matches_start_time); |
1448 } | 1497 } |
1449 | 1498 |
1450 void SearchProvider::AddNavigationResultsToMatches( | 1499 void SearchProvider::AddNavigationResultsToMatches( |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1832 // Preserve the forced query '?' prefix in |match.fill_into_edit|. | 1881 // Preserve the forced query '?' prefix in |match.fill_into_edit|. |
1833 // Otherwise, user edits to a suggestion would show non-Search results. | 1882 // Otherwise, user edits to a suggestion would show non-Search results. |
1834 if (input_.type() == AutocompleteInput::FORCED_QUERY) { | 1883 if (input_.type() == AutocompleteInput::FORCED_QUERY) { |
1835 match.fill_into_edit.insert(0, ASCIIToUTF16("?")); | 1884 match.fill_into_edit.insert(0, ASCIIToUTF16("?")); |
1836 if (inline_autocomplete_offset != string16::npos) | 1885 if (inline_autocomplete_offset != string16::npos) |
1837 ++inline_autocomplete_offset; | 1886 ++inline_autocomplete_offset; |
1838 } | 1887 } |
1839 if (!input_.prevent_inline_autocomplete() && | 1888 if (!input_.prevent_inline_autocomplete() && |
1840 (inline_autocomplete_offset != string16::npos)) { | 1889 (inline_autocomplete_offset != string16::npos)) { |
1841 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); | 1890 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); |
1842 match.allowed_to_be_default_match = true; | 1891 // Navsuggestions can only be the default match when there is no |
1892 // keyword provider active lest it appears first and breaks the user | |
1893 // out of keyword mode. | |
1894 match.allowed_to_be_default_match = | |
1895 (providers_.GetKeywordProviderURL() == NULL); | |
1843 match.inline_autocompletion = | 1896 match.inline_autocompletion = |
1844 match.fill_into_edit.substr(inline_autocomplete_offset); | 1897 match.fill_into_edit.substr(inline_autocomplete_offset); |
1845 } | 1898 } |
1846 | 1899 |
1847 match.contents = net::FormatUrl(navigation.url(), languages, | 1900 match.contents = net::FormatUrl(navigation.url(), languages, |
1848 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start); | 1901 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start); |
1849 // If the first match in the untrimmed string was inside a scheme that we | 1902 // If the first match in the untrimmed string was inside a scheme that we |
1850 // trimmed, look for a subsequent match. | 1903 // trimmed, look for a subsequent match. |
1851 if (match_start == string16::npos) | 1904 if (match_start == string16::npos) |
1852 match_start = match.contents.find(input); | 1905 match_start = match.contents.find(input); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1907 it->set_relevance(max_query_relevance); | 1960 it->set_relevance(max_query_relevance); |
1908 it->set_relevance_from_server(relevance_from_server); | 1961 it->set_relevance_from_server(relevance_from_server); |
1909 } | 1962 } |
1910 } | 1963 } |
1911 | 1964 |
1912 void SearchProvider::UpdateDone() { | 1965 void SearchProvider::UpdateDone() { |
1913 // We're done when the timer isn't running, there are no suggest queries | 1966 // We're done when the timer isn't running, there are no suggest queries |
1914 // pending, and we're not waiting on Instant. | 1967 // pending, and we're not waiting on Instant. |
1915 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); | 1968 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); |
1916 } | 1969 } |
OLD | NEW |