1 // Copyright (c) 2012 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.
5 #include "chrome/browser/google/google_util.h"
10 #include "base/command_line.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/google/google_url_tracker.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/installer/util/google_update_settings.h"
20 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
21 #include "net/base/url_util.h"
24 #if defined(OS_MACOSX)
25 #include "chrome/browser/mac/keystone_glue.h"
26 #elif defined(OS_CHROMEOS)
27 #include "chrome/browser/google/google_util_chromeos.h"
30 #if defined(GOOGLE_CHROME_BUILD)
31 #include "chrome/browser/google/linkdoctor_internal/linkdoctor_internal.h"
34 #ifndef LINKDOCTOR_SERVER_REQUEST_URL
35 #define LINKDOCTOR_SERVER_REQUEST_URL std::string()
39 // Helpers --------------------------------------------------------------------
43 const char* brand_for_testing
= NULL
;
44 bool gUseMockLinkDoctorBaseURLForTesting
= false;
46 bool IsPathHomePageBase(const std::string
& path
) {
47 return (path
== "/") || (path
== "/webhp");
53 namespace google_util
{
55 // Global functions -----------------------------------------------------------
57 bool HasGoogleSearchQueryParam(const std::string
& str
) {
58 url_parse::Component
query(0, str
.length()), key
, value
;
59 while (url_parse::ExtractQueryKeyValue(str
.c_str(), &query
, &key
,
61 if ((key
.len
== 1) && (str
[key
.begin
] == 'q') && value
.is_nonempty())
67 GURL
LinkDoctorBaseURL() {
68 if (gUseMockLinkDoctorBaseURLForTesting
)
69 return GURL("http://mock.linkdoctor.url/for?testing");
70 return GURL(LINKDOCTOR_SERVER_REQUEST_URL
);
73 void SetMockLinkDoctorBaseURLForTesting() {
74 gUseMockLinkDoctorBaseURLForTesting
= true;
77 GURL
AppendGoogleLocaleParam(const GURL
& url
) {
78 // Google does not yet recognize 'nb' for Norwegian Bokmal, but it uses
80 std::string locale
= g_browser_process
->GetApplicationLocale();
83 return net::AppendQueryParameter(url
, "hl", locale
);
86 std::string
StringAppendGoogleLocaleParam(const std::string
& url
) {
87 GURL
original_url(url
);
88 DCHECK(original_url
.is_valid());
89 GURL localized_url
= AppendGoogleLocaleParam(original_url
);
90 return localized_url
.spec();
93 GURL
AppendGoogleTLDParam(Profile
* profile
, const GURL
& url
) {
94 const std::string
google_domain(
95 net::registry_controlled_domains::GetDomainAndRegistry(
96 GoogleURLTracker::GoogleURL(profile
),
97 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES
));
98 const size_t first_dot
= google_domain
.find('.');
99 if (first_dot
== std::string::npos
) {
103 return net::AppendQueryParameter(url
, "sd",
104 google_domain
.substr(first_dot
+ 1));
109 bool GetBrand(std::string
* brand
) {
110 if (brand_for_testing
) {
111 brand
->assign(brand_for_testing
);
115 base::string16 brand16
;
116 bool ret
= GoogleUpdateSettings::GetBrand(&brand16
);
118 brand
->assign(WideToASCII(brand16
));
122 bool GetReactivationBrand(std::string
* brand
) {
123 base::string16 brand16
;
124 bool ret
= GoogleUpdateSettings::GetReactivationBrand(&brand16
);
126 brand
->assign(WideToASCII(brand16
));
132 bool GetBrand(std::string
* brand
) {
133 if (brand_for_testing
) {
134 brand
->assign(brand_for_testing
);
138 #if defined(OS_MACOSX)
139 brand
->assign(keystone_glue::BrandCode());
140 #elif defined(OS_CHROMEOS)
141 brand
->assign(google_util::chromeos::GetBrand());
148 bool GetReactivationBrand(std::string
* brand
) {
155 bool StartsWithCommandLineGoogleBaseURL(const GURL
& url
) {
156 const std::string
base_url(CommandLine::ForCurrentProcess()->
157 GetSwitchValueASCII(switches::kGoogleBaseURL
));
158 return !base_url
.empty() &&
159 StartsWithASCII(url
.possibly_invalid_spec(), base_url
, true);
162 bool IsGoogleHostname(const std::string
& host
,
163 SubdomainPermission subdomain_permission
) {
164 const std::string
base_url(CommandLine::ForCurrentProcess()->
165 GetSwitchValueASCII(switches::kGoogleBaseURL
));
166 if (!base_url
.empty()) {
167 GURL
base_gurl(base_url
);
168 if (base_gurl
.is_valid() && (host
== base_gurl
.host()))
172 size_t tld_length
= net::registry_controlled_domains::GetRegistryLength(
174 net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES
,
175 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES
);
176 if ((tld_length
== 0) || (tld_length
== std::string::npos
))
178 std::string
host_minus_tld(host
, 0, host
.length() - tld_length
);
179 if (LowerCaseEqualsASCII(host_minus_tld
, "google."))
181 if (subdomain_permission
== ALLOW_SUBDOMAIN
)
182 return EndsWith(host_minus_tld
, ".google.", false);
183 return LowerCaseEqualsASCII(host_minus_tld
, "www.google.");
186 bool IsGoogleDomainUrl(const GURL
& url
,
187 SubdomainPermission subdomain_permission
,
188 PortPermission port_permission
) {
189 return url
.is_valid() && url
.SchemeIsHTTPOrHTTPS() &&
190 (url
.port().empty() || (port_permission
== ALLOW_NON_STANDARD_PORTS
)) &&
191 google_util::IsGoogleHostname(url
.host(), subdomain_permission
);
194 bool IsGoogleHomePageUrl(const GURL
& url
) {
195 // First check to see if this has a Google domain.
196 if (!IsGoogleDomainUrl(url
, DISALLOW_SUBDOMAIN
, DISALLOW_NON_STANDARD_PORTS
))
199 // Make sure the path is a known home page path.
200 std::string
path(url
.path());
201 return IsPathHomePageBase(path
) || StartsWithASCII(path
, "/ig", false);
204 bool IsGoogleSearchUrl(const GURL
& url
) {
205 // First check to see if this has a Google domain.
206 if (!IsGoogleDomainUrl(url
, DISALLOW_SUBDOMAIN
, DISALLOW_NON_STANDARD_PORTS
))
209 // Make sure the path is a known search path.
210 std::string
path(url
.path());
211 bool is_home_page_base
= IsPathHomePageBase(path
);
212 if (!is_home_page_base
&& (path
!= "/search"))
215 // Check for query parameter in URL parameter and hash fragment, depending on
217 return HasGoogleSearchQueryParam(url
.ref()) ||
218 (!is_home_page_base
&& HasGoogleSearchQueryParam(url
.query()));
221 bool IsOrganic(const std::string
& brand
) {
222 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
223 if (command_line
.HasSwitch(switches::kOrganicInstall
))
226 #if defined(OS_MACOSX)
228 // An empty brand string on Mac is used for channels other than stable,
229 // which are always organic.
234 const char* const kBrands
[] = {
235 "CHCA", "CHCB", "CHCG", "CHCH", "CHCI", "CHCJ", "CHCK", "CHCL",
236 "CHFO", "CHFT", "CHHS", "CHHM", "CHMA", "CHMB", "CHME", "CHMF",
237 "CHMG", "CHMH", "CHMI", "CHMQ", "CHMV", "CHNB", "CHNC", "CHNG",
238 "CHNH", "CHNI", "CHOA", "CHOB", "CHOC", "CHON", "CHOO", "CHOP",
239 "CHOQ", "CHOR", "CHOS", "CHOT", "CHOU", "CHOX", "CHOY", "CHOZ",
240 "CHPD", "CHPE", "CHPF", "CHPG", "ECBA", "ECBB", "ECDA", "ECDB",
241 "ECSA", "ECSB", "ECVA", "ECVB", "ECWA", "ECWB", "ECWC", "ECWD",
242 "ECWE", "ECWF", "EUBB", "EUBC", "GGLA", "GGLS"
244 const char* const* end
= &kBrands
[arraysize(kBrands
)];
245 const char* const* found
= std::find(&kBrands
[0], end
, brand
);
249 return StartsWithASCII(brand
, "EUB", true) ||
250 StartsWithASCII(brand
, "EUC", true) ||
251 StartsWithASCII(brand
, "GGR", true);
254 bool IsOrganicFirstRun(const std::string
& brand
) {
255 // Used for testing, to force search engine selector to appear.
256 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
257 if (command_line
.HasSwitch(switches::kOrganicInstall
))
260 #if defined(OS_MACOSX)
262 // An empty brand string on Mac is used for channels other than stable,
263 // which are always organic.
268 return StartsWithASCII(brand
, "GG", true) ||
269 StartsWithASCII(brand
, "EU", true);
272 bool IsInternetCafeBrandCode(const std::string
& brand
) {
273 const char* const kBrands
[] = {
274 "CHIQ", "CHSG", "HLJY", "NTMO", "OOBA", "OOBB", "OOBC", "OOBD", "OOBE",
275 "OOBF", "OOBG", "OOBH", "OOBI", "OOBJ", "IDCM",
277 const char* const* end
= &kBrands
[arraysize(kBrands
)];
278 const char* const* found
= std::find(&kBrands
[0], end
, brand
);
283 // BrandForTesting ------------------------------------------------------------
285 BrandForTesting::BrandForTesting(const std::string
& brand
) : brand_(brand
) {
286 DCHECK(brand_for_testing
== NULL
);
287 brand_for_testing
= brand_
.c_str();
290 BrandForTesting::~BrandForTesting() {
291 brand_for_testing
= NULL
;
295 } // namespace google_util