diff options
Diffstat (limited to 'components/search')
-rw-r--r-- | components/search/BUILD.gn | 3 | ||||
-rw-r--r-- | components/search/DEPS | 2 | ||||
-rw-r--r-- | components/search/search.cc | 114 | ||||
-rw-r--r-- | components/search/search.h | 57 | ||||
-rw-r--r-- | components/search/search_android_unittest.cc | 87 | ||||
-rw-r--r-- | components/search/search_switches.cc | 11 | ||||
-rw-r--r-- | components/search/search_switches.h | 5 | ||||
-rw-r--r-- | components/search/search_unittest.cc | 110 |
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 |