Commit 58423331 authored by stevet@chromium.org's avatar stevet@chromium.org

Transmit a X-Chrome-UMA-Enabled bit to Google domains from clients that have UMA enabled.

BUG=123609
TEST=With UMA enabled (not Chromium), visit www.google.com and ensure that the request header includes X-Chrome-UMA-Enabled with value "1". Also, ensure that unit_tests GoogleUtilTests all pass.

Review URL: http://codereview.chromium.org/10054029

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132479 0039d316-1c4b-4281-b951-d872f2087c98
parent 4e5540ac
......@@ -44,13 +44,6 @@ bool HasQueryParameter(const std::string& str) {
return false;
}
// True if |url| is an HTTP[S] request with host "[www.]google.<TLD>" and no
// explicit port.
bool IsGoogleDomainUrl(const GURL& url) {
return url.is_valid() && (url.SchemeIs("http") || url.SchemeIs("https")) &&
url.port().empty() && google_util::IsGoogleHostname(url.host());
}
} // anonymous namespace
namespace google_util {
......@@ -142,21 +135,32 @@ bool GetReactivationBrand(std::string* brand) {
#endif
bool IsGoogleHostname(const std::string& host) {
bool IsGoogleDomainUrl(const std::string& url, SubdomainPermission permission) {
GURL original_url(url);
return original_url.is_valid() && original_url.port().empty() &&
(original_url.SchemeIs("http") || original_url.SchemeIs("https")) &&
google_util::IsGoogleHostname(original_url.host(), permission);
}
bool IsGoogleHostname(const std::string& host,
SubdomainPermission permission) {
size_t tld_length =
net::RegistryControlledDomainService::GetRegistryLength(host, false);
if ((tld_length == 0) || (tld_length == std::string::npos))
return false;
std::string host_minus_tld(host, 0, host.length() - tld_length);
return LowerCaseEqualsASCII(host_minus_tld, "www.google.") ||
LowerCaseEqualsASCII(host_minus_tld, "google.");
if (LowerCaseEqualsASCII(host_minus_tld, "google."))
return true;
if (permission == ALLOW_SUBDOMAIN)
return EndsWith(host_minus_tld, ".google.", false);
return LowerCaseEqualsASCII(host_minus_tld, "www.google.");
}
bool IsGoogleHomePageUrl(const std::string& url) {
GURL original_url(url);
// First check to see if this has a Google domain.
if (!IsGoogleDomainUrl(original_url))
if (!IsGoogleDomainUrl(url, DISALLOW_SUBDOMAIN))
return false;
// Make sure the path is a known home page path.
......@@ -173,7 +177,7 @@ bool IsGoogleSearchUrl(const std::string& url) {
GURL original_url(url);
// First check to see if this has a Google domain.
if (!IsGoogleDomainUrl(original_url))
if (!IsGoogleDomainUrl(url, DISALLOW_SUBDOMAIN))
return false;
// Make sure the path is a known search path.
......
......@@ -46,8 +46,20 @@ bool GetReactivationBrand(std::string* brand);
// need to restrict some behavior to only happen on Google's officially-owned
// domains, use TransportSecurityState::IsGooglePinnedProperty() instead.
// True if |host| is "[www.]google.<TLD>" with a valid TLD.
bool IsGoogleHostname(const std::string& host);
// Designate whether or not a URL checking function also checks for specific
// subdomains, or only "www" and empty subdomains.
enum SubdomainPermission {
ALLOW_SUBDOMAIN,
DISALLOW_SUBDOMAIN,
};
// True if |url| is an HTTP[S] request with host "[www.]google.<TLD>" and no
// explicit port. If |allow_subdomain| is true, we check against host
// "*.google.<TLD>" instead.
bool IsGoogleDomainUrl(const std::string& url, SubdomainPermission permission);
// True if |host| is "[www.]google.<TLD>" with a valid TLD. If
// |allow_subdomain| is true, we check against host "*.google.<TLD>" instead.
bool IsGoogleHostname(const std::string& host, SubdomainPermission permission);
// True if |url| represents a valid Google home page URL.
bool IsGoogleHomePageUrl(const std::string& url);
// True if |url| represents a valid Google search URL.
......
......@@ -6,6 +6,7 @@
#include "chrome/browser/google/google_util.h"
#include "testing/gtest/include/gtest/gtest.h"
using google_util::IsGoogleDomainUrl;
using google_util::IsGoogleHomePageUrl;
using google_util::IsGoogleSearchUrl;
......@@ -241,3 +242,37 @@ TEST(GoogleUtilTest, BadSearches) {
EXPECT_FALSE(IsGoogleSearchUrl(
"http://www.google.com/WEBHP#q=something"));
}
TEST(GoogleUtilTest, GoogleDomains) {
// Test some good Google domains (valid TLDs).
EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com",
google_util::ALLOW_SUBDOMAIN));
EXPECT_TRUE(IsGoogleDomainUrl("http://google.com",
google_util::ALLOW_SUBDOMAIN));
EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.ca",
google_util::ALLOW_SUBDOMAIN));
EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.biz.tj",
google_util::ALLOW_SUBDOMAIN));
EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com/search?q=something",
google_util::ALLOW_SUBDOMAIN));
EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com/webhp",
google_util::ALLOW_SUBDOMAIN));
// Test some bad Google domains (invalid TLDs).
EXPECT_FALSE(IsGoogleDomainUrl("http://www.google.notrealtld",
google_util::ALLOW_SUBDOMAIN));
EXPECT_FALSE(IsGoogleDomainUrl("http://www.google.faketld/search?q=something",
google_util::ALLOW_SUBDOMAIN));
EXPECT_FALSE(IsGoogleDomainUrl("http://www.yahoo.com",
google_util::ALLOW_SUBDOMAIN));
// Test subdomain checks.
EXPECT_TRUE(IsGoogleDomainUrl("http://images.google.com",
google_util::ALLOW_SUBDOMAIN));
EXPECT_FALSE(IsGoogleDomainUrl("http://images.google.com",
google_util::DISALLOW_SUBDOMAIN));
EXPECT_TRUE(IsGoogleDomainUrl("http://google.com",
google_util::DISALLOW_SUBDOMAIN));
EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com",
google_util::DISALLOW_SUBDOMAIN));
}
......@@ -32,6 +32,7 @@
class BookmarkModel;
class BookmarkNode;
class ChromeNetworkDelegate;
class MetricsReportingScheduler;
class PrefService;
class Profile;
......@@ -437,6 +438,7 @@ class MetricsServiceHelper {
friend class InstantFieldTrial;
friend bool prerender::IsOmniboxEnabled(Profile* profile);
friend class extensions::ExtensionDownloader;
friend class ChromeNetworkDelegate;
// Returns true if prefs::kMetricsReportingEnabled is set.
static bool IsMetricsReportingEnabled();
......
......@@ -14,6 +14,8 @@
#include "chrome/browser/extensions/extension_event_router_forwarder.h"
#include "chrome/browser/extensions/extension_info_map.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/prefs/pref_member.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/task_manager/task_manager.h"
......@@ -165,6 +167,10 @@ int ChromeNetworkDelegate::OnBeforeSendHeaders(
net::URLRequest* request,
const net::CompletionCallback& callback,
net::HttpRequestHeaders* headers) {
// Attach any applicable Chrome metrics headers. This is a best-effort attempt
// where failure will not cause OnBeforeSendHeaders to back out.
AddChromeMetricsStateHeader(request, headers);
return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeSendHeaders(
profile_, extension_info_map_.get(), request, callback, headers);
}
......@@ -304,3 +310,23 @@ bool ChromeNetworkDelegate::CanSetCookie(
return allow;
}
void ChromeNetworkDelegate::AddChromeMetricsStateHeader(
net::URLRequest* request,
net::HttpRequestHeaders* headers) {
// Note our criteria for attaching Chrome experiment headers:
// 1. We only transmit to *.google.<TLD> domains. NOTE that this use of
// google_util helpers to check this does not guarantee that the URL is
// Google-owned, only that it is of the form *.google.<TLD>. In the future
// we may choose to reinforce this check.
// 2. We must verify that the transmitting profile is not off the record.
// 3. For the X-Chrome-UMA-Enabled bit, we only set it if UMA is in fact
// enabled for this install of Chrome.
Profile* profile_instance = reinterpret_cast<Profile*>(profile_);
if (google_util::IsGoogleDomainUrl(request->url().spec(),
google_util::ALLOW_SUBDOMAIN) &&
profile_instance && !profile_instance->IsOffTheRecord() &&
MetricsServiceHelper::IsMetricsReportingEnabled()) {
headers->SetHeader("X-Chrome-UMA-Enabled", "1");
}
}
......@@ -83,6 +83,11 @@ class ChromeNetworkDelegate : public net::NetworkDelegate {
const std::string& cookie_line,
net::CookieOptions* options) OVERRIDE;
// Adds Chrome experiment and metrics state as custom headers to |headers|
// based on local state and |request|.
void AddChromeMetricsStateHeader(net::URLRequest* request,
net::HttpRequestHeaders* headers);
scoped_refptr<ExtensionEventRouterForwarder> event_router_;
void* profile_;
scoped_refptr<CookieSettings> cookie_settings_;
......
......@@ -26,8 +26,11 @@ namespace {
bool CanMerge(const GURL& url1, const GURL& url2) {
VLOG(1) << "Checking if can merge " << url1.spec() << " with " << url2.spec();
// All Google URLs are considered the same one.
if (google_util::IsGoogleHostname(url1.host()))
return google_util::IsGoogleHostname(url2.host());
if (google_util::IsGoogleHostname(url1.host(),
google_util::DISALLOW_SUBDOMAIN)) {
return google_util::IsGoogleHostname(url2.host(),
google_util::DISALLOW_SUBDOMAIN);
}
// Otherwise URLs must have the same domain.
return net::RegistryControlledDomainService::SameDomainOrHost(url1, url2);
}
......
......@@ -3281,8 +3281,10 @@ static const PrepopulatedEngine* GetEngineForURL(const std::string& url) {
// First special-case Google, because the prepopulate URL for it will not
// convert to a GURL and thus won't have an origin. Instead see if the
// incoming URL's host is "[*.]google.<TLD>".
if (google_util::IsGoogleHostname(as_gurl.host()))
if (google_util::IsGoogleHostname(as_gurl.host(),
google_util::DISALLOW_SUBDOMAIN)) {
return &google;
}
// Now check the rest of the prepopulate data.
GURL origin(as_gurl.GetOrigin());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment