359cb73128b92384ef5f90be9f943742bed889d8
[platform/framework/web/crosswalk.git] / src / chrome / browser / google / google_util.cc
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.
4
5 #include "chrome/browser/google/google_util.h"
6
7 #include <string>
8 #include <vector>
9
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/common/net/url_fixer_upper.h"
20 #include "chrome/installer/util/google_update_settings.h"
21 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
22 #include "net/base/url_util.h"
23 #include "url/gurl.h"
24
25 #if defined(OS_MACOSX)
26 #include "chrome/browser/mac/keystone_glue.h"
27 #elif defined(OS_CHROMEOS)
28 #include "chrome/browser/google/google_util_chromeos.h"
29 #endif
30
31 // Only use Link Doctor on official builds.  It uses an API key, too, but
32 // seems best to just disable it, for more responsive error pages and to reduce
33 // server load.
34 #if defined(GOOGLE_CHROME_BUILD)
35 #define LINKDOCTOR_SERVER_REQUEST_URL "https://www.googleapis.com/rpc"
36 #else
37 #define LINKDOCTOR_SERVER_REQUEST_URL ""
38 #endif
39
40
41 // Helpers --------------------------------------------------------------------
42
43 namespace {
44
45 const char* brand_for_testing = NULL;
46 bool gUseMockLinkDoctorBaseURLForTesting = false;
47
48 bool IsPathHomePageBase(const std::string& path) {
49   return (path == "/") || (path == "/webhp");
50 }
51
52 }  // namespace
53
54
55 namespace google_util {
56
57 // Global functions -----------------------------------------------------------
58
59 bool HasGoogleSearchQueryParam(const std::string& str) {
60   url_parse::Component query(0, str.length()), key, value;
61   while (url_parse::ExtractQueryKeyValue(str.c_str(), &query, &key,
62                                          &value)) {
63     if ((key.len == 1) && (str[key.begin] == 'q') && value.is_nonempty())
64       return true;
65   }
66   return false;
67 }
68
69 GURL LinkDoctorBaseURL() {
70   if (gUseMockLinkDoctorBaseURLForTesting)
71     return GURL("http://mock.linkdoctor.url/for?testing");
72   return GURL(LINKDOCTOR_SERVER_REQUEST_URL);
73 }
74
75 void SetMockLinkDoctorBaseURLForTesting() {
76   gUseMockLinkDoctorBaseURLForTesting = true;
77 }
78
79 std::string GetGoogleLocale() {
80   std::string locale = g_browser_process->GetApplicationLocale();
81   // Google does not yet recognize 'nb' for Norwegian Bokmal, but it uses
82   // 'no' for that.
83   if (locale == "nb")
84     return "no";
85   return locale;
86 }
87
88 GURL AppendGoogleLocaleParam(const GURL& url) {
89   return net::AppendQueryParameter(url, "hl", GetGoogleLocale());
90 }
91
92 std::string StringAppendGoogleLocaleParam(const std::string& url) {
93   GURL original_url(url);
94   DCHECK(original_url.is_valid());
95   GURL localized_url = AppendGoogleLocaleParam(original_url);
96   return localized_url.spec();
97 }
98
99 std::string GetGoogleCountryCode(Profile* profile) {
100   const std::string google_hostname =
101       GoogleURLTracker::GoogleURL(profile).host();
102   const size_t last_dot = google_hostname.find_last_of('.');
103   if (last_dot == std::string::npos) {
104     NOTREACHED();
105   }
106   std::string country_code = google_hostname.substr(last_dot + 1);
107   // Assume the com TLD implies the US.
108   if (country_code == "com")
109     return "us";
110   // Google uses the Unicode Common Locale Data Repository (CLDR), and the CLDR
111   // code for the UK is "gb".
112   if (country_code == "uk")
113     return "gb";
114   // Catalonia does not have a CLDR country code, since it's a region in Spain,
115   // so use Spain instead.
116   if (country_code == "cat")
117     return "es";
118   return country_code;
119 }
120
121 GURL GetGoogleSearchURL(Profile* profile) {
122   // The url returned by the tracker does not include the "/search" or the
123   // "q=" query string.
124   std::string search_path = "search";
125   std::string query_string = "q=";
126   GURL::Replacements replacements;
127   replacements.SetPathStr(search_path);
128   replacements.SetQueryStr(query_string);
129   return GoogleURLTracker::GoogleURL(profile).ReplaceComponents(replacements);
130 }
131
132 #if defined(OS_WIN)
133
134 bool GetBrand(std::string* brand) {
135   if (brand_for_testing) {
136     brand->assign(brand_for_testing);
137     return true;
138   }
139
140   base::string16 brand16;
141   bool ret = GoogleUpdateSettings::GetBrand(&brand16);
142   if (ret)
143     brand->assign(base::UTF16ToASCII(brand16));
144   return ret;
145 }
146
147 bool GetReactivationBrand(std::string* brand) {
148   base::string16 brand16;
149   bool ret = GoogleUpdateSettings::GetReactivationBrand(&brand16);
150   if (ret)
151     brand->assign(base::UTF16ToASCII(brand16));
152   return ret;
153 }
154
155 #else
156
157 bool GetBrand(std::string* brand) {
158   if (brand_for_testing) {
159     brand->assign(brand_for_testing);
160     return true;
161   }
162
163 #if defined(OS_MACOSX)
164   brand->assign(keystone_glue::BrandCode());
165 #elif defined(OS_CHROMEOS)
166   brand->assign(google_util::chromeos::GetBrand());
167 #else
168   brand->clear();
169 #endif
170   return true;
171 }
172
173 bool GetReactivationBrand(std::string* brand) {
174   brand->clear();
175   return true;
176 }
177
178 #endif
179
180 GURL CommandLineGoogleBaseURL() {
181   // Unit tests may add command-line flags after the first call to this
182   // function, so we don't simply initialize a static |base_url| directly and
183   // then unconditionally return it.
184   CR_DEFINE_STATIC_LOCAL(std::string, switch_value, ());
185   CR_DEFINE_STATIC_LOCAL(GURL, base_url, ());
186   std::string current_switch_value(
187       CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
188           switches::kGoogleBaseURL));
189   if (current_switch_value != switch_value) {
190     switch_value = current_switch_value;
191     base_url = URLFixerUpper::FixupURL(switch_value, std::string());
192     if (!base_url.is_valid() || base_url.has_query() || base_url.has_ref())
193       base_url = GURL();
194   }
195   return base_url;
196 }
197
198 bool StartsWithCommandLineGoogleBaseURL(const GURL& url) {
199   GURL base_url(CommandLineGoogleBaseURL());
200   return base_url.is_valid() &&
201       StartsWithASCII(url.possibly_invalid_spec(), base_url.spec(), true);
202 }
203
204 bool IsGoogleHostname(const std::string& host,
205                       SubdomainPermission subdomain_permission) {
206   GURL base_url(CommandLineGoogleBaseURL());
207   if (base_url.is_valid() && (host == base_url.host()))
208     return true;
209
210   size_t tld_length = net::registry_controlled_domains::GetRegistryLength(
211       host,
212       net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
213       net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
214   if ((tld_length == 0) || (tld_length == std::string::npos))
215     return false;
216   std::string host_minus_tld(host, 0, host.length() - tld_length);
217   if (LowerCaseEqualsASCII(host_minus_tld, "google."))
218     return true;
219   if (subdomain_permission == ALLOW_SUBDOMAIN)
220     return EndsWith(host_minus_tld, ".google.", false);
221   return LowerCaseEqualsASCII(host_minus_tld, "www.google.");
222 }
223
224 bool IsGoogleDomainUrl(const GURL& url,
225                        SubdomainPermission subdomain_permission,
226                        PortPermission port_permission) {
227   return url.is_valid() && url.SchemeIsHTTPOrHTTPS() &&
228       (url.port().empty() || (port_permission == ALLOW_NON_STANDARD_PORTS)) &&
229       google_util::IsGoogleHostname(url.host(), subdomain_permission);
230 }
231
232 bool IsGoogleHomePageUrl(const GURL& url) {
233   // First check to see if this has a Google domain.
234   if (!IsGoogleDomainUrl(url, DISALLOW_SUBDOMAIN, DISALLOW_NON_STANDARD_PORTS))
235     return false;
236
237   // Make sure the path is a known home page path.
238   std::string path(url.path());
239   return IsPathHomePageBase(path) || StartsWithASCII(path, "/ig", false);
240 }
241
242 bool IsGoogleSearchUrl(const GURL& url) {
243   // First check to see if this has a Google domain.
244   if (!IsGoogleDomainUrl(url, DISALLOW_SUBDOMAIN, DISALLOW_NON_STANDARD_PORTS))
245     return false;
246
247   // Make sure the path is a known search path.
248   std::string path(url.path());
249   bool is_home_page_base = IsPathHomePageBase(path);
250   if (!is_home_page_base && (path != "/search"))
251     return false;
252
253   // Check for query parameter in URL parameter and hash fragment, depending on
254   // the path type.
255   return HasGoogleSearchQueryParam(url.ref()) ||
256       (!is_home_page_base && HasGoogleSearchQueryParam(url.query()));
257 }
258
259 bool IsOrganic(const std::string& brand) {
260 #if defined(OS_MACOSX)
261   if (brand.empty()) {
262     // An empty brand string on Mac is used for channels other than stable,
263     // which are always organic.
264     return true;
265   }
266 #endif
267
268   const char* const kBrands[] = {
269       "CHCA", "CHCB", "CHCG", "CHCH", "CHCI", "CHCJ", "CHCK", "CHCL",
270       "CHFO", "CHFT", "CHHS", "CHHM", "CHMA", "CHMB", "CHME", "CHMF",
271       "CHMG", "CHMH", "CHMI", "CHMQ", "CHMV", "CHNB", "CHNC", "CHNG",
272       "CHNH", "CHNI", "CHOA", "CHOB", "CHOC", "CHON", "CHOO", "CHOP",
273       "CHOQ", "CHOR", "CHOS", "CHOT", "CHOU", "CHOX", "CHOY", "CHOZ",
274       "CHPD", "CHPE", "CHPF", "CHPG", "ECBA", "ECBB", "ECDA", "ECDB",
275       "ECSA", "ECSB", "ECVA", "ECVB", "ECWA", "ECWB", "ECWC", "ECWD",
276       "ECWE", "ECWF", "EUBB", "EUBC", "GGLA", "GGLS"
277   };
278   const char* const* end = &kBrands[arraysize(kBrands)];
279   const char* const* found = std::find(&kBrands[0], end, brand);
280   if (found != end)
281     return true;
282
283   return StartsWithASCII(brand, "EUB", true) ||
284          StartsWithASCII(brand, "EUC", true) ||
285          StartsWithASCII(brand, "GGR", true);
286 }
287
288 bool IsOrganicFirstRun(const std::string& brand) {
289 #if defined(OS_MACOSX)
290   if (brand.empty()) {
291     // An empty brand string on Mac is used for channels other than stable,
292     // which are always organic.
293     return true;
294   }
295 #endif
296
297   return StartsWithASCII(brand, "GG", true) ||
298          StartsWithASCII(brand, "EU", true);
299 }
300
301 bool IsInternetCafeBrandCode(const std::string& brand) {
302   const char* const kBrands[] = {
303     "CHIQ", "CHSG", "HLJY", "NTMO", "OOBA", "OOBB", "OOBC", "OOBD", "OOBE",
304     "OOBF", "OOBG", "OOBH", "OOBI", "OOBJ", "IDCM",
305   };
306   const char* const* end = &kBrands[arraysize(kBrands)];
307   const char* const* found = std::find(&kBrands[0], end, brand);
308   return found != end;
309 }
310
311
312 // BrandForTesting ------------------------------------------------------------
313
314 BrandForTesting::BrandForTesting(const std::string& brand) : brand_(brand) {
315   DCHECK(brand_for_testing == NULL);
316   brand_for_testing = brand_.c_str();
317 }
318
319 BrandForTesting::~BrandForTesting() {
320   brand_for_testing = NULL;
321 }
322
323
324 }  // namespace google_util