summaryrefslogtreecommitdiffstats
path: root/components/search
diff options
context:
space:
mode:
authorsdefresne <sdefresne@chromium.org>2015-08-03 07:18:13 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-03 14:18:41 +0000
commit51bbec7be7014d4d75d39c1a5c27b1ba9ddc3dcd (patch)
tree912625ef3699b6c080aa3cca3340966298130333 /components/search
parente52e8da071b5d27eead353a38ddbc822af9ef0fc (diff)
downloadchromium_src-51bbec7be7014d4d75d39c1a5c27b1ba9ddc3dcd.zip
chromium_src-51bbec7be7014d4d75d39c1a5c27b1ba9ddc3dcd.tar.gz
chromium_src-51bbec7be7014d4d75d39c1a5c27b1ba9ddc3dcd.tar.bz2
Partially componentize //chrome/browser/search/search.{h,cc}
Move functions from //chrome/browser/search/search.{h,cc} to the search component //components/search/search.{h,cc} so that they can be shared with iOS. Move all the code in those two files (and supporting unittests) from the "chrome" to the "search" namespace. Move unittests that do not depends on non-componentized functions into the search component. Implements GetSearchTerms() on iOS that uses a web::WebState* instead of content::WebContents and simplify the code to remove unsupported features. Directly use //components/search on iOS instead of the SearchProvider when possible. BUG=514239 TBR=sky,droger,benwells Review URL: https://codereview.chromium.org/1260033003 Cr-Commit-Position: refs/heads/master@{#341525}
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