Home | History | Annotate | Download | only in google
      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/installer/util/google_update_settings.h"
     20 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
     21 #include "net/base/url_util.h"
     22 #include "url/gurl.h"
     23 
     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"
     28 #endif
     29 
     30 #if defined(GOOGLE_CHROME_BUILD)
     31 #include "chrome/browser/google/linkdoctor_internal/linkdoctor_internal.h"
     32 #endif
     33 
     34 #ifndef LINKDOCTOR_SERVER_REQUEST_URL
     35 #define LINKDOCTOR_SERVER_REQUEST_URL std::string()
     36 #endif
     37 
     38 
     39 // Helpers --------------------------------------------------------------------
     40 
     41 namespace {
     42 
     43 const char* brand_for_testing = NULL;
     44 bool gUseMockLinkDoctorBaseURLForTesting = false;
     45 
     46 bool IsPathHomePageBase(const std::string& path) {
     47   return (path == "/") || (path == "/webhp");
     48 }
     49 
     50 }  // namespace
     51 
     52 
     53 namespace google_util {
     54 
     55 // Global functions -----------------------------------------------------------
     56 
     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,
     60                                          &value)) {
     61     if ((key.len == 1) && (str[key.begin] == 'q') && value.is_nonempty())
     62       return true;
     63   }
     64   return false;
     65 }
     66 
     67 GURL LinkDoctorBaseURL() {
     68   if (gUseMockLinkDoctorBaseURLForTesting)
     69     return GURL("http://mock.linkdoctor.url/for?testing");
     70   return GURL(LINKDOCTOR_SERVER_REQUEST_URL);
     71 }
     72 
     73 void SetMockLinkDoctorBaseURLForTesting() {
     74   gUseMockLinkDoctorBaseURLForTesting = true;
     75 }
     76 
     77 GURL AppendGoogleLocaleParam(const GURL& url) {
     78   // Google does not yet recognize 'nb' for Norwegian Bokmal, but it uses
     79   // 'no' for that.
     80   std::string locale = g_browser_process->GetApplicationLocale();
     81   if (locale == "nb")
     82     locale = "no";
     83   return net::AppendQueryParameter(url, "hl", locale);
     84 }
     85 
     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();
     91 }
     92 
     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) {
    100     NOTREACHED();
    101     return url;
    102   }
    103   return net::AppendQueryParameter(url, "sd",
    104                                    google_domain.substr(first_dot + 1));
    105 }
    106 
    107 #if defined(OS_WIN)
    108 
    109 bool GetBrand(std::string* brand) {
    110   if (brand_for_testing) {
    111     brand->assign(brand_for_testing);
    112     return true;
    113   }
    114 
    115   string16 brand16;
    116   bool ret = GoogleUpdateSettings::GetBrand(&brand16);
    117   if (ret)
    118     brand->assign(WideToASCII(brand16));
    119   return ret;
    120 }
    121 
    122 bool GetReactivationBrand(std::string* brand) {
    123   string16 brand16;
    124   bool ret = GoogleUpdateSettings::GetReactivationBrand(&brand16);
    125   if (ret)
    126     brand->assign(WideToASCII(brand16));
    127   return ret;
    128 }
    129 
    130 #else
    131 
    132 bool GetBrand(std::string* brand) {
    133   if (brand_for_testing) {
    134     brand->assign(brand_for_testing);
    135     return true;
    136   }
    137 
    138 #if defined(OS_MACOSX)
    139   brand->assign(keystone_glue::BrandCode());
    140 #elif defined(OS_CHROMEOS)
    141   brand->assign(google_util::chromeos::GetBrand());
    142 #else
    143   brand->clear();
    144 #endif
    145   return true;
    146 }
    147 
    148 bool GetReactivationBrand(std::string* brand) {
    149   brand->clear();
    150   return true;
    151 }
    152 
    153 #endif
    154 
    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);
    160 }
    161 
    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()))
    169       return true;
    170   }
    171 
    172   size_t tld_length = net::registry_controlled_domains::GetRegistryLength(
    173       host,
    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))
    177     return false;
    178   std::string host_minus_tld(host, 0, host.length() - tld_length);
    179   if (LowerCaseEqualsASCII(host_minus_tld, "google."))
    180     return true;
    181   if (subdomain_permission == ALLOW_SUBDOMAIN)
    182     return EndsWith(host_minus_tld, ".google.", false);
    183   return LowerCaseEqualsASCII(host_minus_tld, "www.google.");
    184 }
    185 
    186 bool IsGoogleDomainUrl(const GURL& url,
    187                        SubdomainPermission subdomain_permission,
    188                        PortPermission port_permission) {
    189   return url.is_valid() && (url.SchemeIs("http") || url.SchemeIs("https")) &&
    190       (url.port().empty() || (port_permission == ALLOW_NON_STANDARD_PORTS)) &&
    191       google_util::IsGoogleHostname(url.host(), subdomain_permission);
    192 }
    193 
    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))
    197     return false;
    198 
    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);
    202 }
    203 
    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))
    207     return false;
    208 
    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"))
    213     return false;
    214 
    215   // Check for query parameter in URL parameter and hash fragment, depending on
    216   // the path type.
    217   return HasGoogleSearchQueryParam(url.ref()) ||
    218       (!is_home_page_base && HasGoogleSearchQueryParam(url.query()));
    219 }
    220 
    221 bool IsOrganic(const std::string& brand) {
    222   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    223   if (command_line.HasSwitch(switches::kOrganicInstall))
    224     return true;
    225 
    226 #if defined(OS_MACOSX)
    227   if (brand.empty()) {
    228     // An empty brand string on Mac is used for channels other than stable,
    229     // which are always organic.
    230     return true;
    231   }
    232 #endif
    233 
    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"
    243   };
    244   const char* const* end = &kBrands[arraysize(kBrands)];
    245   const char* const* found = std::find(&kBrands[0], end, brand);
    246   if (found != end)
    247     return true;
    248 
    249   return StartsWithASCII(brand, "EUB", true) ||
    250          StartsWithASCII(brand, "EUC", true) ||
    251          StartsWithASCII(brand, "GGR", true);
    252 }
    253 
    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))
    258     return true;
    259 
    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   return StartsWithASCII(brand, "GG", true) ||
    269          StartsWithASCII(brand, "EU", true);
    270 }
    271 
    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",
    276   };
    277   const char* const* end = &kBrands[arraysize(kBrands)];
    278   const char* const* found = std::find(&kBrands[0], end, brand);
    279   return found != end;
    280 }
    281 
    282 
    283 // BrandForTesting ------------------------------------------------------------
    284 
    285 BrandForTesting::BrandForTesting(const std::string& brand) : brand_(brand) {
    286   DCHECK(brand_for_testing == NULL);
    287   brand_for_testing = brand_.c_str();
    288 }
    289 
    290 BrandForTesting::~BrandForTesting() {
    291   brand_for_testing = NULL;
    292 }
    293 
    294 
    295 }  // namespace google_util
    296