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/omnibox/omnibox_field_trial.h" | 5 #include "chrome/browser/omnibox/omnibox_field_trial.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/metrics/field_trial.h" | 10 #include "base/metrics/field_trial.h" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "base/strings/string_split.h" | 12 #include "base/strings/string_split.h" |
13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
16 #include "chrome/browser/autocomplete/autocomplete_input.h" | |
17 #include "chrome/browser/search/search.h" | 16 #include "chrome/browser/search/search.h" |
18 #include "chrome/common/variations/variation_ids.h" | 17 #include "chrome/common/variations/variation_ids.h" |
| 18 #include "components/metrics/proto/omnibox_event.pb.h" |
19 #include "components/variations/active_field_trials.h" | 19 #include "components/variations/active_field_trials.h" |
20 #include "components/variations/metrics_util.h" | 20 #include "components/variations/metrics_util.h" |
21 #include "components/variations/variations_associated_data.h" | 21 #include "components/variations/variations_associated_data.h" |
22 | 22 |
| 23 using metrics::OmniboxEventProto; |
| 24 |
23 namespace { | 25 namespace { |
24 | 26 |
25 typedef std::map<std::string, std::string> VariationParams; | 27 typedef std::map<std::string, std::string> VariationParams; |
26 typedef HUPScoringParams::ScoreBuckets ScoreBuckets; | 28 typedef HUPScoringParams::ScoreBuckets ScoreBuckets; |
27 | 29 |
28 // Field trial names. | 30 // Field trial names. |
29 const char kHUPCullRedirectsFieldTrialName[] = "OmniboxHUPCullRedirects"; | 31 const char kHUPCullRedirectsFieldTrialName[] = "OmniboxHUPCullRedirects"; |
30 const char kHUPCreateShorterMatchFieldTrialName[] = | 32 const char kHUPCreateShorterMatchFieldTrialName[] = |
31 "OmniboxHUPCreateShorterMatch"; | 33 "OmniboxHUPCreateShorterMatch"; |
32 const char kStopTimerFieldTrialName[] = "OmniboxStopTimer"; | 34 const char kStopTimerFieldTrialName[] = "OmniboxStopTimer"; |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 | 301 |
300 bool OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() { | 302 bool OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() { |
301 return HasDynamicFieldTrialGroupPrefix( | 303 return HasDynamicFieldTrialGroupPrefix( |
302 kEnableZeroSuggestPersonalizedGroupPrefix) || | 304 kEnableZeroSuggestPersonalizedGroupPrefix) || |
303 chrome_variations::GetVariationParamValue( | 305 chrome_variations::GetVariationParamValue( |
304 kBundledExperimentFieldTrialName, | 306 kBundledExperimentFieldTrialName, |
305 kZeroSuggestVariantRule) == "Personalized"; | 307 kZeroSuggestVariantRule) == "Personalized"; |
306 } | 308 } |
307 | 309 |
308 bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance( | 310 bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance( |
309 AutocompleteInput::PageClassification current_page_classification, | 311 OmniboxEventProto::PageClassification current_page_classification, |
310 int* max_relevance) { | 312 int* max_relevance) { |
311 // The value of the rule is a string that encodes an integer containing | 313 // The value of the rule is a string that encodes an integer containing |
312 // the max relevance. | 314 // the max relevance. |
313 const std::string& max_relevance_str = | 315 const std::string& max_relevance_str = |
314 OmniboxFieldTrial::GetValueForRuleInContext( | 316 OmniboxFieldTrial::GetValueForRuleInContext( |
315 kShortcutsScoringMaxRelevanceRule, current_page_classification); | 317 kShortcutsScoringMaxRelevanceRule, current_page_classification); |
316 if (max_relevance_str.empty()) | 318 if (max_relevance_str.empty()) |
317 return false; | 319 return false; |
318 if (!base::StringToInt(max_relevance_str, max_relevance)) | 320 if (!base::StringToInt(max_relevance_str, max_relevance)) |
319 return false; | 321 return false; |
320 return true; | 322 return true; |
321 } | 323 } |
322 | 324 |
323 bool OmniboxFieldTrial::SearchHistoryPreventInlining( | 325 bool OmniboxFieldTrial::SearchHistoryPreventInlining( |
324 AutocompleteInput::PageClassification current_page_classification) { | 326 OmniboxEventProto::PageClassification current_page_classification) { |
325 return OmniboxFieldTrial::GetValueForRuleInContext( | 327 return OmniboxFieldTrial::GetValueForRuleInContext( |
326 kSearchHistoryRule, current_page_classification) == "PreventInlining"; | 328 kSearchHistoryRule, current_page_classification) == "PreventInlining"; |
327 } | 329 } |
328 | 330 |
329 bool OmniboxFieldTrial::SearchHistoryDisable( | 331 bool OmniboxFieldTrial::SearchHistoryDisable( |
330 AutocompleteInput::PageClassification current_page_classification) { | 332 OmniboxEventProto::PageClassification current_page_classification) { |
331 return OmniboxFieldTrial::GetValueForRuleInContext( | 333 return OmniboxFieldTrial::GetValueForRuleInContext( |
332 kSearchHistoryRule, current_page_classification) == "Disable"; | 334 kSearchHistoryRule, current_page_classification) == "Disable"; |
333 } | 335 } |
334 | 336 |
335 void OmniboxFieldTrial::GetDemotionsByType( | 337 void OmniboxFieldTrial::GetDemotionsByType( |
336 AutocompleteInput::PageClassification current_page_classification, | 338 OmniboxEventProto::PageClassification current_page_classification, |
337 DemotionMultipliers* demotions_by_type) { | 339 DemotionMultipliers* demotions_by_type) { |
338 demotions_by_type->clear(); | 340 demotions_by_type->clear(); |
339 std::string demotion_rule = OmniboxFieldTrial::GetValueForRuleInContext( | 341 std::string demotion_rule = OmniboxFieldTrial::GetValueForRuleInContext( |
340 kDemoteByTypeRule, current_page_classification); | 342 kDemoteByTypeRule, current_page_classification); |
341 // If there is no demotion rule for this context, then use the default | 343 // If there is no demotion rule for this context, then use the default |
342 // value for that context. At the moment the default value is non-empty | 344 // value for that context. At the moment the default value is non-empty |
343 // only for the fakebox-focus context. | 345 // only for the fakebox-focus context. |
344 if (demotion_rule.empty() && | 346 if (demotion_rule.empty() && |
345 (current_page_classification == | 347 (current_page_classification == |
346 AutocompleteInput::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS)) | 348 OmniboxEventProto::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS)) |
347 demotion_rule = "1:61,2:61,3:61,4:61,12:61"; | 349 demotion_rule = "1:61,2:61,3:61,4:61,12:61"; |
348 | 350 |
349 // The value of the DemoteByType rule is a comma-separated list of | 351 // The value of the DemoteByType rule is a comma-separated list of |
350 // {ResultType + ":" + Number} where ResultType is an AutocompleteMatchType:: | 352 // {ResultType + ":" + Number} where ResultType is an AutocompleteMatchType:: |
351 // Type enum represented as an integer and Number is an integer number | 353 // Type enum represented as an integer and Number is an integer number |
352 // between 0 and 100 inclusive. Relevance scores of matches of that result | 354 // between 0 and 100 inclusive. Relevance scores of matches of that result |
353 // type are multiplied by Number / 100. 100 means no change. | 355 // type are multiplied by Number / 100. 100 means no change. |
354 base::StringPairs kv_pairs; | 356 base::StringPairs kv_pairs; |
355 if (base::SplitStringIntoKeyValuePairs(demotion_rule, ':', ',', &kv_pairs)) { | 357 if (base::SplitStringIntoKeyValuePairs(demotion_rule, ':', ',', &kv_pairs)) { |
356 for (base::StringPairs::const_iterator it = kv_pairs.begin(); | 358 for (base::StringPairs::const_iterator it = kv_pairs.begin(); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 const char OmniboxFieldTrial::kHUPNewScoringVisitedCountScoreBucketsParam[] = | 464 const char OmniboxFieldTrial::kHUPNewScoringVisitedCountScoreBucketsParam[] = |
463 "VisitedCountScoreBuckets"; | 465 "VisitedCountScoreBuckets"; |
464 | 466 |
465 // Background and implementation details: | 467 // Background and implementation details: |
466 // | 468 // |
467 // Each experiment group in any field trial can come with an optional set of | 469 // Each experiment group in any field trial can come with an optional set of |
468 // parameters (key-value pairs). In the bundled omnibox experiment | 470 // parameters (key-value pairs). In the bundled omnibox experiment |
469 // (kBundledExperimentFieldTrialName), each experiment group comes with a | 471 // (kBundledExperimentFieldTrialName), each experiment group comes with a |
470 // list of parameters in the form: | 472 // list of parameters in the form: |
471 // key=<Rule>: | 473 // key=<Rule>: |
472 // <AutocompleteInput::PageClassification (as an int)>: | 474 // <OmniboxEventProto::PageClassification (as an int)>: |
473 // <whether Instant Extended is enabled (as a 1 or 0)> | 475 // <whether Instant Extended is enabled (as a 1 or 0)> |
474 // (note that there are no linebreaks in keys; this format is for | 476 // (note that there are no linebreaks in keys; this format is for |
475 // presentation only> | 477 // presentation only> |
476 // value=<arbitrary string> | 478 // value=<arbitrary string> |
477 // Both the AutocompleteInput::PageClassification and the Instant Extended | 479 // Both the OmniboxEventProto::PageClassification and the Instant Extended |
478 // entries can be "*", which means this rule applies for all values of the | 480 // entries can be "*", which means this rule applies for all values of the |
479 // matching portion of the context. | 481 // matching portion of the context. |
480 // One example parameter is | 482 // One example parameter is |
481 // key=SearchHistory:6:1 | 483 // key=SearchHistory:6:1 |
482 // value=PreventInlining | 484 // value=PreventInlining |
483 // This means in page classification context 6 (a search result page doing | 485 // This means in page classification context 6 (a search result page doing |
484 // search term replacement) with Instant Extended enabled, the SearchHistory | 486 // search term replacement) with Instant Extended enabled, the SearchHistory |
485 // experiment should PreventInlining. | 487 // experiment should PreventInlining. |
486 // | 488 // |
487 // When an exact match to the rule in the current context is missing, we | 489 // When an exact match to the rule in the current context is missing, we |
488 // give preference to a wildcard rule that matches the instant extended | 490 // give preference to a wildcard rule that matches the instant extended |
489 // context over a wildcard rule that matches the page classification | 491 // context over a wildcard rule that matches the page classification |
490 // context. Hopefully, though, users will write their field trial configs | 492 // context. Hopefully, though, users will write their field trial configs |
491 // so as not to rely on this fall back order. | 493 // so as not to rely on this fall back order. |
492 // | 494 // |
493 // In short, this function tries to find the value associated with key | 495 // In short, this function tries to find the value associated with key |
494 // |rule|:|page_classification|:|instant_extended|, failing that it looks up | 496 // |rule|:|page_classification|:|instant_extended|, failing that it looks up |
495 // |rule|:*:|instant_extended|, failing that it looks up | 497 // |rule|:*:|instant_extended|, failing that it looks up |
496 // |rule|:|page_classification|:*, failing that it looks up |rule|:*:*, | 498 // |rule|:|page_classification|:*, failing that it looks up |rule|:*:*, |
497 // and failing that it returns the empty string. | 499 // and failing that it returns the empty string. |
498 std::string OmniboxFieldTrial::GetValueForRuleInContext( | 500 std::string OmniboxFieldTrial::GetValueForRuleInContext( |
499 const std::string& rule, | 501 const std::string& rule, |
500 AutocompleteInput::PageClassification page_classification) { | 502 OmniboxEventProto::PageClassification page_classification) { |
501 VariationParams params; | 503 VariationParams params; |
502 if (!chrome_variations::GetVariationParams(kBundledExperimentFieldTrialName, | 504 if (!chrome_variations::GetVariationParams(kBundledExperimentFieldTrialName, |
503 ¶ms)) { | 505 ¶ms)) { |
504 return std::string(); | 506 return std::string(); |
505 } | 507 } |
506 const std::string page_classification_str = | 508 const std::string page_classification_str = |
507 base::IntToString(static_cast<int>(page_classification)); | 509 base::IntToString(static_cast<int>(page_classification)); |
508 const std::string instant_extended = | 510 const std::string instant_extended = |
509 chrome::IsInstantExtendedAPIEnabled() ? "1" : "0"; | 511 chrome::IsInstantExtendedAPIEnabled() ? "1" : "0"; |
510 // Look up rule in this exact context. | 512 // Look up rule in this exact context. |
511 VariationParams::const_iterator it = params.find( | 513 VariationParams::const_iterator it = params.find( |
512 rule + ":" + page_classification_str + ":" + instant_extended); | 514 rule + ":" + page_classification_str + ":" + instant_extended); |
513 if (it != params.end()) | 515 if (it != params.end()) |
514 return it->second; | 516 return it->second; |
515 // Fall back to the global page classification context. | 517 // Fall back to the global page classification context. |
516 it = params.find(rule + ":*:" + instant_extended); | 518 it = params.find(rule + ":*:" + instant_extended); |
517 if (it != params.end()) | 519 if (it != params.end()) |
518 return it->second; | 520 return it->second; |
519 // Fall back to the global instant extended context. | 521 // Fall back to the global instant extended context. |
520 it = params.find(rule + ":" + page_classification_str + ":*"); | 522 it = params.find(rule + ":" + page_classification_str + ":*"); |
521 if (it != params.end()) | 523 if (it != params.end()) |
522 return it->second; | 524 return it->second; |
523 // Look up rule in the global context. | 525 // Look up rule in the global context. |
524 it = params.find(rule + ":*:*"); | 526 it = params.find(rule + ":*:*"); |
525 return (it != params.end()) ? it->second : std::string(); | 527 return (it != params.end()) ? it->second : std::string(); |
526 } | 528 } |
OLD | NEW |