summaryrefslogtreecommitdiffstats
path: root/components/search
diff options
context:
space:
mode:
Diffstat (limited to 'components/search')
-rw-r--r--components/search/BUILD.gn3
-rw-r--r--components/search/DEPS2
-rw-r--r--components/search/search.cc114
-rw-r--r--components/search/search.h57
-rw-r--r--components/search/search_android_unittest.cc87
-rw-r--r--components/search/search_switches.cc11
-rw-r--r--components/search/search_switches.h5
-rw-r--r--components/search/search_unittest.cc110
8 files changed, 382 insertions, 7 deletions
diff --git a/components/search/BUILD.gn b/components/search/BUILD.gn
index a895701..21c49c4d 100644
--- a/components/search/BUILD.gn
+++ b/components/search/BUILD.gn
@@ -12,5 +12,8 @@ static_library("search") {
deps = [
"//base",
+ "//components/google/core/browser",
+ "//components/search_engines",
+ "//url",
]
}
diff --git a/components/search/DEPS b/components/search/DEPS
index 80f6f90..d9bc813 100644
--- a/components/search/DEPS
+++ b/components/search/DEPS
@@ -1,3 +1,5 @@
include_rules = [
+ "+components/google/core",
+ "+components/search_engines",
"+components/variations",
]
diff --git a/components/search/search.cc b/components/search/search.cc
index 92b8ccb..654ec55 100644
--- a/components/search/search.cc
+++ b/components/search/search.cc
@@ -10,9 +10,12 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/google/core/browser/google_util.h"
#include "components/search/search_switches.h"
+#include "components/search_engines/template_url.h"
+#include "url/gurl.h"
-namespace chrome {
+namespace search {
namespace {
@@ -49,8 +52,25 @@ const char kEmbeddedSearchFieldTrialName[] = "EmbeddedSearch";
// be ignored and Instant Extended will not be enabled by default.
const char kDisablingSuffix[] = "DISABLED";
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+const char kEnableQueryExtractionFlagName[] = "query_extraction";
+#endif
+
+const char kAllowPrefetchNonDefaultMatch[] = "allow_prefetch_non_default_match";
+
+#if defined(OS_ANDROID)
+const char kPrefetchSearchResultsFlagName[] = "prefetch_results";
+
+// Controls whether to reuse prerendered Instant Search base page to commit any
+// search query.
+const char kReuseInstantSearchBasePage[] = "reuse_instant_search_base_page";
+#endif
+
} // namespace
+// Negative start-margin values prevent the "es_sm" parameter from being used.
+const int kDisableStartMargin = -1;
+
bool IsInstantExtendedAPIEnabled() {
#if defined(OS_IOS)
return false;
@@ -144,4 +164,94 @@ bool GetBoolValueForFlagWithDefault(const std::string& flag,
return !!GetUInt64ValueForFlagWithDefault(flag, default_value ? 1 : 0, flags);
}
-} // namespace chrome
+std::string InstantExtendedEnabledParam(bool for_search) {
+ if (for_search && !IsQueryExtractionEnabled())
+ return std::string();
+ return std::string(google_util::kInstantExtendedAPIParam) + "=" +
+ base::Uint64ToString(EmbeddedSearchPageVersion()) + "&";
+}
+
+std::string ForceInstantResultsParam(bool for_prerender) {
+ return (for_prerender || !IsInstantExtendedAPIEnabled()) ? "ion=1&"
+ : std::string();
+}
+
+bool IsQueryExtractionEnabled() {
+#if defined(OS_IOS) || defined(OS_ANDROID)
+ return true;
+#else
+ if (!IsInstantExtendedAPIEnabled())
+ return false;
+
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kEnableQueryExtraction))
+ return true;
+
+ FieldTrialFlags flags;
+ return GetFieldTrialInfo(&flags) &&
+ GetBoolValueForFlagWithDefault(kEnableQueryExtractionFlagName, false,
+ flags);
+#endif // defined(OS_IOS) || defined(OS_ANDROID)
+}
+
+bool ShouldPrefetchSearchResults() {
+ if (!IsInstantExtendedAPIEnabled())
+ return false;
+
+#if defined(OS_ANDROID)
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kPrefetchSearchResults)) {
+ return true;
+ }
+
+ FieldTrialFlags flags;
+ return GetFieldTrialInfo(&flags) &&
+ GetBoolValueForFlagWithDefault(kPrefetchSearchResultsFlagName, false,
+ flags);
+#else
+ return true;
+#endif
+}
+
+bool ShouldReuseInstantSearchBasePage() {
+ if (!ShouldPrefetchSearchResults())
+ return false;
+
+#if defined(OS_ANDROID)
+ FieldTrialFlags flags;
+ return GetFieldTrialInfo(&flags) &&
+ GetBoolValueForFlagWithDefault(kReuseInstantSearchBasePage, false,
+ flags);
+#else
+ return true;
+#endif
+}
+
+bool ShouldAllowPrefetchNonDefaultMatch() {
+ if (!ShouldPrefetchSearchResults())
+ return false;
+
+ FieldTrialFlags flags;
+ return GetFieldTrialInfo(&flags) &&
+ GetBoolValueForFlagWithDefault(kAllowPrefetchNonDefaultMatch, false,
+ flags);
+}
+
+// |url| should either have a secure scheme or have a non-HTTPS base URL that
+// the user specified using --google-base-url. (This allows testers to use
+// --google-base-url to point at non-HTTPS servers, which eases testing.)
+bool IsSuitableURLForInstant(const GURL& url, const TemplateURL* template_url) {
+ return template_url->HasSearchTermsReplacementKey(url) &&
+ (url.SchemeIsCryptographic() ||
+ google_util::StartsWithCommandLineGoogleBaseURL(url));
+}
+
+void EnableQueryExtractionForTesting() {
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+ base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
+ cl->AppendSwitch(switches::kEnableQueryExtraction);
+#endif
+}
+
+} // namespace search
diff --git a/components/search/search.h b/components/search/search.h
index 0a7a55b..2ce6204 100644
--- a/components/search/search.h
+++ b/components/search/search.h
@@ -13,7 +13,14 @@
#include "base/strings/string16.h"
#include "base/strings/string_split.h"
-namespace chrome {
+class GURL;
+class TemplateURL;
+
+namespace search {
+
+// Use this value for "start margin" to prevent the "es_sm" parameter from
+// being used.
+extern const int kDisableStartMargin;
// Returns whether the Instant Extended API is enabled.
bool IsInstantExtendedAPIEnabled();
@@ -55,6 +62,52 @@ bool GetBoolValueForFlagWithDefault(const std::string& flag,
bool default_value,
const FieldTrialFlags& flags);
-} // namespace chrome
+// Returns a string indicating whether InstantExtended is enabled, suitable
+// for adding as a query string param to the homepage or search requests.
+// Returns an empty string otherwise.
+//
+// |for_search| should be set to true for search requests, in which case this
+// returns a non-empty string only if query extraction is enabled.
+std::string InstantExtendedEnabledParam(bool for_search);
+
+// Returns a string that will cause the search results page to update
+// incrementally. Currently, Instant Extended passes a different param to
+// search results pages that also has this effect, so by default this function
+// returns the empty string when Instant Extended is enabled. However, when
+// doing instant search result prerendering, we still need to pass this param,
+// as Instant Extended does not cause incremental updates by default for the
+// prerender page. Callers should set |for_prerender| in this case to force
+// the returned string to be non-empty.
+std::string ForceInstantResultsParam(bool for_prerender);
+
+// Returns whether query extraction is enabled.
+bool IsQueryExtractionEnabled();
+
+// Returns true if 'prefetch_results' flag is set to true in field trials to
+// prefetch high-confidence search suggestions.
+bool ShouldPrefetchSearchResults();
+
+// Returns true if 'reuse_instant_search_base_page' flag is set to true in field
+// trials to reuse the prerendered page to commit any search query.
+bool ShouldReuseInstantSearchBasePage();
+
+// Returns true if 'allow_prefetch_non_default_match' flag is enabled in field
+// trials to allow prefetching the suggestion marked to be prefetched by the
+// suggest server even if it is not the default match.
+bool ShouldAllowPrefetchNonDefaultMatch();
+
+// |url| should either have a secure scheme or have a non-HTTPS base URL that
+// the user specified using --google-base-url. (This allows testers to use
+// --google-base-url to point at non-HTTPS servers, which eases testing.)
+bool IsSuitableURLForInstant(const GURL& url, const TemplateURL* template_url);
+
+// -----------------------------------------------------
+// The following APIs are exposed for use in tests only.
+// -----------------------------------------------------
+
+// Forces query in the omnibox to be on for tests.
+void EnableQueryExtractionForTesting();
+
+} // namespace search
#endif // COMPONENTS_SEARCH_SEARCH_H_
diff --git a/components/search/search_android_unittest.cc b/components/search/search_android_unittest.cc
index 772daaf..f5c8320 100644
--- a/components/search/search_android_unittest.cc
+++ b/components/search/search_android_unittest.cc
@@ -8,11 +8,12 @@
#include "base/memory/scoped_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/statistics_recorder.h"
+#include "components/search/search.h"
#include "components/search/search_switches.h"
#include "components/variations/entropy_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace chrome {
+namespace search {
namespace {
@@ -25,6 +26,90 @@ TEST(SearchTest, EmbeddedSearchAPIEnabled) {
EXPECT_TRUE(IsInstantExtendedAPIEnabled());
}
+TEST(SearchTest, QueryExtractionEnabled) {
+ // Query extraction is always enabled on mobile.
+ EXPECT_TRUE(IsQueryExtractionEnabled());
+}
+
+class SearchUtilTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ field_trial_list_.reset(
+ new base::FieldTrialList(new metrics::SHA1EntropyProvider("42")));
+ base::StatisticsRecorder::Initialize();
+ }
+
+ private:
+ scoped_ptr<base::FieldTrialList> field_trial_list_;
+};
+
+TEST_F(SearchUtilTest, UseDefaultEmbeddedSearchPageVersion) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch", "Group1 espv:-1 query_extraction:1"));
+ EXPECT_TRUE(IsQueryExtractionEnabled());
+ EXPECT_EQ("espv=1&", InstantExtendedEnabledParam(true));
+ EXPECT_EQ("espv=1&", InstantExtendedEnabledParam(false));
+}
+
+TEST_F(SearchUtilTest, ShouldPrefetchSearchResults_InstantExtendedAPIEnabled) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch", "Group1 espv:2 prefetch_results:1"));
+ EXPECT_TRUE(ShouldPrefetchSearchResults());
+ EXPECT_TRUE(IsInstantExtendedAPIEnabled());
+ EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
+}
+
+TEST_F(SearchUtilTest, ShouldPrefetchSearchResults_InstantExtendedAPIDisabled) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch", "Group1 espv:1 prefetch_results:1"));
+ EXPECT_FALSE(ShouldPrefetchSearchResults());
+ EXPECT_FALSE(IsInstantExtendedAPIEnabled());
+ EXPECT_EQ(1ul, EmbeddedSearchPageVersion());
+}
+
+TEST_F(SearchUtilTest, ShouldPrefetchSearchResults_DisabledViaFieldTrials) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch", "Group1 espv:2 prefetch_results:0"));
+ EXPECT_FALSE(ShouldPrefetchSearchResults());
+ EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
+}
+
+TEST_F(SearchUtilTest, ShouldPrefetchSearchResults_EnabledViaCommandLine) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kPrefetchSearchResults);
+ // Command-line enable should override Finch.
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch", "Group1 espv:2 prefetch_results:0"));
+ EXPECT_TRUE(ShouldPrefetchSearchResults());
+ EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
+}
+
+TEST_F(SearchUtilTest,
+ ShouldReuseInstantSearchBasePage_PrefetchResultsFlagDisabled) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch",
+ "Group1 espv:2 prefetch_results:0 reuse_instant_search_base_page:1"));
+ EXPECT_FALSE(ShouldPrefetchSearchResults());
+ EXPECT_FALSE(ShouldReuseInstantSearchBasePage());
+ EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
+}
+
+TEST_F(SearchUtilTest, ShouldReuseInstantSearchBasePage_EnabledViaFieldTrial) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch",
+ "Group1 espv:2 prefetch_results:1 reuse_instant_search_base_page:1"));
+ EXPECT_TRUE(ShouldReuseInstantSearchBasePage());
+ EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
+}
+
+TEST_F(SearchUtilTest, ShouldReuseInstantSearchBasePage_DisabledViaFieldTrial) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch",
+ "Group1 espv:2 prefetch_results:1 reuse_instant_search_base_page:0"));
+ EXPECT_FALSE(ShouldReuseInstantSearchBasePage());
+ EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
+}
+
} // namespace
} // namespace chrome
diff --git a/components/search/search_switches.cc b/components/search/search_switches.cc
index 9359725..d3b80da 100644
--- a/components/search/search_switches.cc
+++ b/components/search/search_switches.cc
@@ -11,6 +11,17 @@ namespace switches {
// Enables EmbeddedSearch API in the search results page.
const char kEnableEmbeddedSearchAPI[] = "enable-embeddedsearch-api";
+// Triggers prerendering of search base page to prefetch results for the typed
+// omnibox query. Only has an effect when prerender is enabled.
+const char kPrefetchSearchResults[] = "prefetch-search-results";
+
+#endif
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+
+// Enables query in the omnibox.
+const char kEnableQueryExtraction[] = "enable-query-extraction";
+
#endif
} // namespace switches
diff --git a/components/search/search_switches.h b/components/search/search_switches.h
index 48b50c1..46208e07 100644
--- a/components/search/search_switches.h
+++ b/components/search/search_switches.h
@@ -11,6 +11,11 @@ namespace switches {
#if defined(OS_ANDROID)
extern const char kEnableEmbeddedSearchAPI[];
+extern const char kPrefetchSearchResults[];
+#endif
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+extern const char kEnableQueryExtraction[];
#endif
} // namespace switches
diff --git a/components/search/search_unittest.cc b/components/search/search_unittest.cc
index 2fd5a23..4a5db38 100644
--- a/components/search/search_unittest.cc
+++ b/components/search/search_unittest.cc
@@ -9,7 +9,7 @@
#include "components/variations/entropy_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace chrome {
+namespace search {
class EmbeddedSearchFieldTrialTest : public testing::Test {
protected:
@@ -130,4 +130,110 @@ TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoControlFlags) {
EXPECT_EQ(3ul, flags.size());
}
-} // namespace chrome
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+typedef EmbeddedSearchFieldTrialTest SearchTest;
+
+TEST_F(SearchTest, ShouldPrefetchSearchResults_InstantExtendedAPIEnabled) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch",
+ "Group1 espv:2"));
+ EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
+ EXPECT_TRUE(ShouldPrefetchSearchResults());
+}
+
+TEST_F(SearchTest, ShouldPrefetchSearchResults_Default) {
+ EXPECT_TRUE(ShouldPrefetchSearchResults());
+}
+
+TEST_F(SearchTest, ShouldReuseInstantSearchBasePage_Default) {
+ EXPECT_TRUE(ShouldReuseInstantSearchBasePage());
+}
+
+TEST_F(SearchTest, ShouldAllowPrefetchNonDefaultMatch_DisabledViaFieldTrial) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch", "Group1 espv:89 allow_prefetch_non_default_match:0"));
+ EXPECT_FALSE(ShouldAllowPrefetchNonDefaultMatch());
+ EXPECT_EQ(89ul, EmbeddedSearchPageVersion());
+}
+
+TEST_F(SearchTest, ShouldAllowPrefetchNonDefaultMatch_EnabledViaFieldTrial) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch", "Group1 espv:80 allow_prefetch_non_default_match:1"));
+ EXPECT_TRUE(ShouldAllowPrefetchNonDefaultMatch());
+ EXPECT_EQ(80ul, EmbeddedSearchPageVersion());
+}
+
+TEST_F(SearchTest, ForceInstantResultsParam) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch",
+ "Group1 espv:2"));
+ EXPECT_TRUE(IsInstantExtendedAPIEnabled());
+ EXPECT_EQ("ion=1&", ForceInstantResultsParam(true));
+ EXPECT_EQ(std::string(), ForceInstantResultsParam(false));
+}
+
+typedef EmbeddedSearchFieldTrialTest InstantExtendedEnabledParamTest;
+
+TEST_F(InstantExtendedEnabledParamTest, QueryExtractionDisabled) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch",
+ "Group1 espv:12"));
+ // Make sure InstantExtendedEnabledParam() returns an empty string for search
+ // requests.
+ EXPECT_FALSE(IsQueryExtractionEnabled());
+ EXPECT_EQ("", InstantExtendedEnabledParam(true));
+ EXPECT_EQ("espv=12&", InstantExtendedEnabledParam(false));
+}
+
+TEST_F(InstantExtendedEnabledParamTest, QueryExtractionEnabled) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch", "Group1 espv:10 query_extraction:1"));
+ EXPECT_TRUE(IsQueryExtractionEnabled());
+ // Make sure InstantExtendedEnabledParam() returns a non-empty param string
+ // for search requests.
+ EXPECT_EQ("espv=10&", InstantExtendedEnabledParam(true));
+ EXPECT_EQ("espv=10&", InstantExtendedEnabledParam(false));
+}
+
+TEST_F(InstantExtendedEnabledParamTest, UseDefaultEmbeddedSearchPageVersion) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch", "Group1 espv:-1 query_extraction:1"));
+ EXPECT_TRUE(IsQueryExtractionEnabled());
+ EXPECT_EQ("espv=2&", InstantExtendedEnabledParam(true));
+ EXPECT_EQ("espv=2&", InstantExtendedEnabledParam(false));
+}
+
+typedef EmbeddedSearchFieldTrialTest IsQueryExtractionEnabledTest;
+
+TEST_F(IsQueryExtractionEnabledTest, NotSet) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch",
+ "Group1 espv:2"));
+ EXPECT_TRUE(IsInstantExtendedAPIEnabled());
+ EXPECT_FALSE(IsQueryExtractionEnabled());
+ EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
+}
+
+TEST_F(IsQueryExtractionEnabledTest, EnabledViaFieldTrial) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch", "Group1 espv:2 query_extraction:1"));
+ EXPECT_TRUE(IsInstantExtendedAPIEnabled());
+ EXPECT_TRUE(IsQueryExtractionEnabled());
+ EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
+}
+
+TEST_F(IsQueryExtractionEnabledTest, DisabledViaFieldTrial) {
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch", "Group1 espv:2 query_extraction:0"));
+ EXPECT_TRUE(IsInstantExtendedAPIEnabled());
+ EXPECT_FALSE(IsQueryExtractionEnabled());
+ EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
+}
+
+TEST_F(IsQueryExtractionEnabledTest, EnabledViaCommandLine) {
+ EnableQueryExtractionForTesting();
+ ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
+ "EmbeddedSearch", "Group1 espv:2 query_extraction:0"));
+ EXPECT_TRUE(IsInstantExtendedAPIEnabled());
+ EXPECT_TRUE(IsQueryExtractionEnabled());
+ EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
+}
+#endif // !defined(OS_IOS) && !defined(OS_ANDROID)
+
+} // namespace search