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