1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
6
7#include "base/command_line.h"
8#include "base/logging.h"
9#include "base/metrics/field_trial.h"
10#include "base/prefs/pref_service.h"
11#include "chrome/browser/browser_process.h"
12#include "chrome/browser/google/google_brand.h"
13#include "chrome/browser/google/google_profile_helper.h"
14#include "chrome/browser/profiles/profile.h"
15#include "chrome/browser/search/instant_service.h"
16#include "chrome/browser/search/instant_service_factory.h"
17#include "chrome/browser/search/search.h"
18#include "chrome/browser/themes/theme_service.h"
19#include "chrome/browser/themes/theme_service_factory.h"
20#include "chrome/common/chrome_switches.h"
21#include "chrome/common/chrome_version_info.h"
22#include "chrome/common/pref_names.h"
23#include "components/google/core/browser/google_util.h"
24#include "components/omnibox/omnibox_field_trial.h"
25#include "components/search/search.h"
26#include "content/public/browser/browser_thread.h"
27#include "ui/base/device_form_factor.h"
28#include "url/gurl.h"
29
30#if defined(ENABLE_RLZ)
31#include "chrome/browser/rlz/rlz.h"
32#endif
33
34using content::BrowserThread;
35
36// static
37std::string* UIThreadSearchTermsData::google_base_url_ = NULL;
38
39UIThreadSearchTermsData::UIThreadSearchTermsData(Profile* profile)
40    : profile_(profile) {
41  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
42      BrowserThread::CurrentlyOn(BrowserThread::UI));
43}
44
45std::string UIThreadSearchTermsData::GoogleBaseURLValue() const {
46  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
47      BrowserThread::CurrentlyOn(BrowserThread::UI));
48  if (google_base_url_)
49    return *google_base_url_;
50  GURL base_url(google_util::CommandLineGoogleBaseURL());
51  if (base_url.is_valid())
52    return base_url.spec();
53  return profile_ ?
54      google_profile_helper::GetGoogleHomePageURL(profile_).spec() :
55      SearchTermsData::GoogleBaseURLValue();
56}
57
58std::string UIThreadSearchTermsData::GetApplicationLocale() const {
59  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
60      BrowserThread::CurrentlyOn(BrowserThread::UI));
61  return g_browser_process->GetApplicationLocale();
62}
63
64// Android implementations are in ui_thread_search_terms_data_android.cc.
65#if !defined(OS_ANDROID)
66base::string16 UIThreadSearchTermsData::GetRlzParameterValue(
67    bool from_app_list) const {
68  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
69      BrowserThread::CurrentlyOn(BrowserThread::UI));
70  base::string16 rlz_string;
71#if defined(ENABLE_RLZ)
72  // For organic brandcodes do not use rlz at all. Empty brandcode usually
73  // means a chromium install. This is ok.
74  std::string brand;
75  if (google_brand::GetBrand(&brand) && !brand.empty() &&
76      !google_brand::IsOrganic(brand)) {
77    // This call will return false the first time(s) it is called until the
78    // value has been cached. This normally would mean that at most one omnibox
79    // search might not send the RLZ data but this is not really a problem.
80    rlz_lib::AccessPoint access_point = RLZTracker::ChromeOmnibox();
81#if !defined(OS_IOS)
82    if (from_app_list)
83      access_point = RLZTracker::ChromeAppList();
84#endif
85    RLZTracker::GetAccessPointRlz(access_point, &rlz_string);
86  }
87#endif
88  return rlz_string;
89}
90
91// We can enable this on non-Android if other platforms ever want a non-empty
92// search client string.  There is already a unit test in place for Android
93// called TemplateURLTest::SearchClient.
94std::string UIThreadSearchTermsData::GetSearchClient() const {
95  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
96      BrowserThread::CurrentlyOn(BrowserThread::UI));
97  return std::string();
98}
99#endif
100
101std::string UIThreadSearchTermsData::GetSuggestClient() const {
102  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
103      BrowserThread::CurrentlyOn(BrowserThread::UI));
104#if defined(OS_ANDROID)
105  return ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_PHONE ?
106      "chrome" : "chrome-omni";
107#else
108  return chrome::IsInstantExtendedAPIEnabled() ? "chrome-omni" : "chrome";
109#endif
110}
111
112std::string UIThreadSearchTermsData::GetSuggestRequestIdentifier() const {
113  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
114      BrowserThread::CurrentlyOn(BrowserThread::UI));
115#if defined(OS_ANDROID)
116  if (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_PHONE) {
117    return OmniboxFieldTrial::EnableAnswersInSuggest() ?
118        "chrome-mobile-ext-ansg" : "chrome-mobile-ext";
119  }
120  return OmniboxFieldTrial::EnableAnswersInSuggest() ?
121      "chrome-ext-ansg" : "chrome-ext";
122#elif defined(OS_IOS)
123  return OmniboxFieldTrial::EnableAnswersInSuggest() ?
124      "chrome-ext-ansg" : "chrome-ext";
125#else
126  return "chrome-ext";
127#endif
128}
129
130bool UIThreadSearchTermsData::EnableAnswersInSuggest() const {
131  return OmniboxFieldTrial::EnableAnswersInSuggest();
132}
133
134bool UIThreadSearchTermsData::IsShowingSearchTermsOnSearchResultsPages() const {
135  return chrome::IsInstantExtendedAPIEnabled() &&
136      chrome::IsQueryExtractionEnabled();
137}
138
139std::string UIThreadSearchTermsData::InstantExtendedEnabledParam(
140    bool for_search) const {
141  return chrome::InstantExtendedEnabledParam(for_search);
142}
143
144std::string UIThreadSearchTermsData::ForceInstantResultsParam(
145    bool for_prerender) const {
146  return chrome::ForceInstantResultsParam(for_prerender);
147}
148
149int UIThreadSearchTermsData::OmniboxStartMargin() const {
150  InstantService* instant_service =
151      InstantServiceFactory::GetForProfile(profile_);
152  // Android and iOS have no InstantService.
153  return instant_service ?
154      instant_service->omnibox_start_margin() : chrome::kDisableStartMargin;
155}
156
157std::string UIThreadSearchTermsData::NTPIsThemedParam() const {
158  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
159         BrowserThread::CurrentlyOn(BrowserThread::UI));
160#if defined(ENABLE_THEMES)
161  if (!chrome::IsInstantExtendedAPIEnabled())
162    return std::string();
163
164  // TODO(dhollowa): Determine fraction of custom themes that don't affect the
165  // NTP background and/or color.
166  ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile_);
167  // NTP is considered themed if the theme is not default and not native (GTK+).
168  if (theme_service && !theme_service->UsingDefaultTheme() &&
169      !theme_service->UsingSystemTheme())
170    return "es_th=1&";
171#endif  // defined(ENABLE_THEMES)
172
173  return std::string();
174}
175
176// It's acutally OK to call this method on any thread, but it's currently placed
177// in UIThreadSearchTermsData since SearchTermsData cannot depend on
178// VersionInfo.
179std::string UIThreadSearchTermsData::GoogleImageSearchSource() const {
180  chrome::VersionInfo version_info;
181  if (version_info.is_valid()) {
182    std::string version(version_info.Name() + " " + version_info.Version());
183    if (version_info.IsOfficialBuild())
184      version += " (Official)";
185    version += " " + version_info.OSType();
186    std::string modifier(version_info.GetVersionStringModifier());
187    if (!modifier.empty())
188      version += " " + modifier;
189    return version;
190  }
191  return "unknown";
192}
193
194// static
195void UIThreadSearchTermsData::SetGoogleBaseURL(const std::string& base_url) {
196  delete google_base_url_;
197  google_base_url_ = base_url.empty() ? NULL : new std::string(base_url);
198}
199