1 // Copyright 2014 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.
5 #include "components/search/search.h"
7 #include "base/command_line.h"
8 #include "base/metrics/field_trial.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "components/search/search_switches.h"
19 // Configuration options for Embedded Search.
20 // EmbeddedSearch field trials are named in such a way that we can parse out
21 // the experiment configuration from the trial's group name in order to give
22 // us maximum flexability in running experiments.
23 // Field trial groups should be named things like "Group7 espv:2 instant:1".
24 // The first token is always GroupN for some integer N, followed by a
25 // space-delimited list of key:value pairs which correspond to these flags:
26 const char kEmbeddedPageVersionFlagName
[] = "espv";
29 const uint64 kEmbeddedPageVersionDefault
= 1;
30 #elif defined(OS_ANDROID)
31 const uint64 kEmbeddedPageVersionDefault
= 1;
32 // Use this variant to enable EmbeddedSearch SearchBox API in the results page.
33 const uint64 kEmbeddedSearchEnabledVersion
= 2;
35 const uint64 kEmbeddedPageVersionDefault
= 2;
38 const char kHideVerbatimFlagName
[] = "hide_verbatim";
40 // Constants for the field trial name and group prefix.
41 // Note in M30 and below this field trial was named "InstantExtended" and in
42 // M31 was renamed to EmbeddedSearch for clarity and cleanliness. Since we
43 // can't easilly sync up Finch configs with the pushing of this change to
44 // Dev & Canary, for now the code accepts both names.
45 // TODO(dcblack): Remove the InstantExtended name once M31 hits the Beta
47 const char kInstantExtendedFieldTrialName
[] = "InstantExtended";
48 const char kEmbeddedSearchFieldTrialName
[] = "EmbeddedSearch";
50 // If the field trial's group name ends with this string its configuration will
51 // be ignored and Instant Extended will not be enabled by default.
52 const char kDisablingSuffix
[] = "DISABLED";
56 bool IsInstantExtendedAPIEnabled() {
59 #elif defined(OS_ANDROID)
60 return EmbeddedSearchPageVersion() == kEmbeddedSearchEnabledVersion
;
63 #endif // defined(OS_IOS)
66 // Determine what embedded search page version to request from the user's
67 // default search provider. If 0, the embedded search UI should not be enabled.
68 uint64
EmbeddedSearchPageVersion() {
69 #if defined(OS_ANDROID)
70 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
71 switches::kEnableEmbeddedSearchAPI
)) {
72 return kEmbeddedSearchEnabledVersion
;
76 FieldTrialFlags flags
;
77 if (GetFieldTrialInfo(&flags
)) {
78 return GetUInt64ValueForFlagWithDefault(kEmbeddedPageVersionFlagName
,
79 kEmbeddedPageVersionDefault
,
82 return kEmbeddedPageVersionDefault
;
85 bool GetFieldTrialInfo(FieldTrialFlags
* flags
) {
86 // Get the group name. If the EmbeddedSearch trial doesn't exist, look for
87 // the older InstantExtended name.
88 std::string group_name
= base::FieldTrialList::FindFullName(
89 kEmbeddedSearchFieldTrialName
);
90 if (group_name
.empty()) {
91 group_name
= base::FieldTrialList::FindFullName(
92 kInstantExtendedFieldTrialName
);
95 if (EndsWith(group_name
, kDisablingSuffix
, true))
98 // We have a valid trial that isn't disabled. Extract the flags.
99 std::string
group_prefix(group_name
);
100 size_t first_space
= group_name
.find(" ");
101 if (first_space
!= std::string::npos
) {
102 // There is a flags section of the group name. Split that out and parse it.
103 group_prefix
= group_name
.substr(0, first_space
);
104 if (!base::SplitStringIntoKeyValuePairs(group_name
.substr(first_space
),
106 // Failed to parse the flags section. Assume the whole group name is
114 // Given a FieldTrialFlags object, returns the string value of the provided
116 std::string
GetStringValueForFlagWithDefault(const std::string
& flag
,
117 const std::string
& default_value
,
118 const FieldTrialFlags
& flags
) {
119 FieldTrialFlags::const_iterator i
;
120 for (i
= flags
.begin(); i
!= flags
.end(); i
++) {
121 if (i
->first
== flag
)
124 return default_value
;
127 // Given a FieldTrialFlags object, returns the uint64 value of the provided
129 uint64
GetUInt64ValueForFlagWithDefault(const std::string
& flag
,
130 uint64 default_value
,
131 const FieldTrialFlags
& flags
) {
133 std::string str_value
=
134 GetStringValueForFlagWithDefault(flag
, std::string(), flags
);
135 if (base::StringToUint64(str_value
, &value
))
137 return default_value
;
140 // Given a FieldTrialFlags object, returns the boolean value of the provided
142 bool GetBoolValueForFlagWithDefault(const std::string
& flag
,
144 const FieldTrialFlags
& flags
) {
145 return !!GetUInt64ValueForFlagWithDefault(flag
, default_value
? 1 : 0, flags
);
148 bool ShouldHideTopVerbatimMatch() {
149 FieldTrialFlags flags
;
150 return GetFieldTrialInfo(&flags
) && GetBoolValueForFlagWithDefault(
151 kHideVerbatimFlagName
, false, flags
);
154 } // namespace chrome