15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/search/search.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/command_line.h" 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/metrics/field_trial.h" 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string_split.h" 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string_util.h" 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/search/search_switches.h" 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace chrome { 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace { 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Configuration options for Embedded Search. 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// EmbeddedSearch field trials are named in such a way that we can parse out 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the experiment configuration from the trial's group name in order to give 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// us maximum flexability in running experiments. 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Field trial groups should be named things like "Group7 espv:2 instant:1". 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// The first token is always GroupN for some integer N, followed by a 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// space-delimited list of key:value pairs which correspond to these flags: 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kEmbeddedPageVersionFlagName[] = "espv"; 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_IOS) 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const uint64 kEmbeddedPageVersionDefault = 1; 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#elif defined(OS_ANDROID) 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const uint64 kEmbeddedPageVersionDefault = 1; 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use this variant to enable EmbeddedSearch SearchBox API in the results page. 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const uint64 kEmbeddedSearchEnabledVersion = 2; 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const uint64 kEmbeddedPageVersionDefault = 2; 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const char kHideVerbatimFlagName[] = "hide_verbatim"; 396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Constants for the field trial name and group prefix. 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Note in M30 and below this field trial was named "InstantExtended" and in 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// M31 was renamed to EmbeddedSearch for clarity and cleanliness. Since we 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// can't easilly sync up Finch configs with the pushing of this change to 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Dev & Canary, for now the code accepts both names. 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// TODO(dcblack): Remove the InstantExtended name once M31 hits the Beta 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// channel. 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kInstantExtendedFieldTrialName[] = "InstantExtended"; 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kEmbeddedSearchFieldTrialName[] = "EmbeddedSearch"; 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// If the field trial's group name ends with this string its configuration will 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// be ignored and Instant Extended will not be enabled by default. 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kDisablingSuffix[] = "DISABLED"; 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool IsInstantExtendedAPIEnabled() { 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_IOS) 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#elif defined(OS_ANDROID) 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return EmbeddedSearchPageVersion() == kEmbeddedSearchEnabledVersion; 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif // defined(OS_IOS) 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Determine what embedded search page version to request from the user's 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// default search provider. If 0, the embedded search UI should not be enabled. 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)uint64 EmbeddedSearchPageVersion() { 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_ANDROID) 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (CommandLine::ForCurrentProcess()->HasSwitch( 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) switches::kEnableEmbeddedSearchAPI)) { 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return kEmbeddedSearchEnabledVersion; 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FieldTrialFlags flags; 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (GetFieldTrialInfo(&flags)) { 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return GetUInt64ValueForFlagWithDefault(kEmbeddedPageVersionFlagName, 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kEmbeddedPageVersionDefault, 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) flags); 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return kEmbeddedPageVersionDefault; 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool GetFieldTrialInfo(FieldTrialFlags* flags) { 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Get the group name. If the EmbeddedSearch trial doesn't exist, look for 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // the older InstantExtended name. 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string group_name = base::FieldTrialList::FindFullName( 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kEmbeddedSearchFieldTrialName); 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (group_name.empty()) { 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) group_name = base::FieldTrialList::FindFullName( 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kInstantExtendedFieldTrialName); 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (EndsWith(group_name, kDisablingSuffix, true)) 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We have a valid trial that isn't disabled. Extract the flags. 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string group_prefix(group_name); 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t first_space = group_name.find(" "); 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (first_space != std::string::npos) { 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // There is a flags section of the group name. Split that out and parse it. 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) group_prefix = group_name.substr(0, first_space); 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!base::SplitStringIntoKeyValuePairs(group_name.substr(first_space), 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ':', ' ', flags)) { 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Failed to parse the flags section. Assume the whole group name is 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // invalid. 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Given a FieldTrialFlags object, returns the string value of the provided 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// flag. 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)std::string GetStringValueForFlagWithDefault(const std::string& flag, 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& default_value, 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const FieldTrialFlags& flags) { 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FieldTrialFlags::const_iterator i; 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (i = flags.begin(); i != flags.end(); i++) { 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (i->first == flag) 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return i->second; 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return default_value; 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Given a FieldTrialFlags object, returns the uint64 value of the provided 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// flag. 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)uint64 GetUInt64ValueForFlagWithDefault(const std::string& flag, 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint64 default_value, 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const FieldTrialFlags& flags) { 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint64 value; 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string str_value = 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GetStringValueForFlagWithDefault(flag, std::string(), flags); 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (base::StringToUint64(str_value, &value)) 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return value; 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return default_value; 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Given a FieldTrialFlags object, returns the boolean value of the provided 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// flag. 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool GetBoolValueForFlagWithDefault(const std::string& flag, 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool default_value, 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const FieldTrialFlags& flags) { 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return !!GetUInt64ValueForFlagWithDefault(flag, default_value ? 1 : 0, flags); 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool ShouldHideTopVerbatimMatch() { 1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FieldTrialFlags flags; 1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault( 1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) kHideVerbatimFlagName, false, flags); 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace chrome 155