summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorstevet@chromium.org <stevet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-02 14:05:44 +0000
committerstevet@chromium.org <stevet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-02 14:05:44 +0000
commit274647e044b45a0eb150a9dca590157344d7fab3 (patch)
tree08a3b328ddc6f079090909fa96272cd06ebdb5f7
parentf4b40c369913c720c7752669c3fc2f3f98a6106b (diff)
downloadchromium_src-274647e044b45a0eb150a9dca590157344d7fab3.zip
chromium_src-274647e044b45a0eb150a9dca590157344d7fab3.tar.gz
chromium_src-274647e044b45a0eb150a9dca590157344d7fab3.tar.bz2
Transmit a X-Chrome-UMA-Enabled bit to Google domains from clients that have UMA enabled.
This requires a change to the ChromeResourceDispatcherHostDelegate and profiles where we feed the incognito and metrics-enabled states into the object at creation time, so we can check that field when doing our header setting. This was originally committed as r134625, but reverted due to CrOS failures, which are now fixed in this patch (see delta from patch sets 1 to 2). 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". Ensure that disabling UMA also disables the transmission of this header entirely. Also, ensure that unit_tests GoogleUtilTests all pass. TBR=pkasting,ivankr Review URL: http://codereview.chromium.org/10273028 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134902 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/google/google_util.cc28
-rw-r--r--chrome/browser/google/google_util.h17
-rw-r--r--chrome/browser/google/google_util_unittest.cc49
-rw-r--r--chrome/browser/profiles/profile_impl_io_data.cc2
-rw-r--r--chrome/browser/profiles/profile_io_data.cc46
-rw-r--r--chrome/browser/profiles/profile_io_data.h25
-rw-r--r--chrome/browser/protector/protector_service.cc7
-rw-r--r--chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc25
-rw-r--r--chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h8
-rw-r--r--chrome/browser/search_engines/template_url_prepopulate_data.cc3
10 files changed, 185 insertions, 25 deletions
diff --git a/chrome/browser/google/google_util.cc b/chrome/browser/google/google_util.cc
index d95b116..22b17fc 100644
--- a/chrome/browser/google/google_util.cc
+++ b/chrome/browser/google/google_util.cc
@@ -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.
diff --git a/chrome/browser/google/google_util.h b/chrome/browser/google/google_util.h
index 95ae4b9..670591a 100644
--- a/chrome/browser/google/google_util.h
+++ b/chrome/browser/google/google_util.h
@@ -46,8 +46,21 @@ 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 |permission| is ALLOW_SUBDOMAIN, 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
+// |permission| is ALLOW_SUBDOMAIN, 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.
diff --git a/chrome/browser/google/google_util_unittest.cc b/chrome/browser/google/google_util_unittest.cc
index f51460c..5c0bfbb 100644
--- a/chrome/browser/google/google_util_unittest.cc
+++ b/chrome/browser/google/google_util_unittest.cc
@@ -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,51 @@ 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));
+
+ // Port and scheme checks.
+ EXPECT_TRUE(IsGoogleDomainUrl("http://www.google.com:80",
+ google_util::DISALLOW_SUBDOMAIN));
+ EXPECT_FALSE(IsGoogleDomainUrl("http://www.google.com:123",
+ google_util::DISALLOW_SUBDOMAIN));
+ EXPECT_TRUE(IsGoogleDomainUrl("https://www.google.com:443",
+ google_util::DISALLOW_SUBDOMAIN));
+ EXPECT_FALSE(IsGoogleDomainUrl("https://www.google.com:123",
+ google_util::DISALLOW_SUBDOMAIN));
+ EXPECT_FALSE(IsGoogleDomainUrl("file://www.google.com",
+ google_util::DISALLOW_SUBDOMAIN));
+ EXPECT_FALSE(IsGoogleDomainUrl("doesnotexist://www.google.com",
+ google_util::DISALLOW_SUBDOMAIN));
+}
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc
index 3345c85..9d8334a 100644
--- a/chrome/browser/profiles/profile_impl_io_data.cc
+++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -113,6 +113,8 @@ void ProfileImplIOData::Handle::Init(
local_state,
io_thread,
main_request_context_getter_);
+
+ io_data_->InitializeMetricsEnabledStateOnUIThread();
}
base::Callback<ChromeURLDataManagerBackend*(void)>
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 5fa6fbc..1d17668 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -56,6 +56,8 @@
#include "net/url_request/url_request.h"
#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/cros_settings.h"
+#include "chrome/browser/chromeos/cros_settings_names.h"
#include "chrome/browser/chromeos/gview_request_interceptor.h"
#include "chrome/browser/chromeos/proxy_config_service_impl.h"
#endif // defined(OS_CHROMEOS)
@@ -160,7 +162,6 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) {
scoped_ptr<ProfileParams> params(new ProfileParams);
params->path = profile->GetPath();
- params->is_incognito = profile->IsOffTheRecord();
params->clear_local_state_on_exit =
pref_service->GetBoolean(prefs::kClearSiteDataOnExit);
@@ -247,8 +248,7 @@ void ProfileIOData::AppRequestContext::SetHttpTransactionFactory(
ProfileIOData::AppRequestContext::~AppRequestContext() {}
ProfileIOData::ProfileParams::ProfileParams()
- : is_incognito(false),
- clear_local_state_on_exit(false),
+ : clear_local_state_on_exit(false),
io_thread(NULL),
#if defined(ENABLE_NOTIFICATIONS)
notification_service(NULL),
@@ -262,7 +262,8 @@ ProfileIOData::ProfileIOData(bool is_incognito)
: initialized_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(
resource_context_(new ResourceContext(this))),
- initialized_on_UI_thread_(false) {
+ initialized_on_UI_thread_(false),
+ is_incognito_(is_incognito) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
@@ -376,6 +377,34 @@ DesktopNotificationService* ProfileIOData::GetNotificationService() const {
}
#endif
+void ProfileIOData::InitializeMetricsEnabledStateOnUIThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+#if defined(OS_CHROMEOS)
+ // Just fetch the value from ChromeOS' settings while we're on the UI thread.
+ // TODO(stevet): For now, this value is only set on profile initialization.
+ // We will want to do something similar to the PrefMember method below in the
+ // future to more accurately capture this state.
+ chromeos::CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref,
+ &enable_metrics_);
+#else
+ // Prep the PrefMember and send it to the IO thread, since this value will be
+ // read from there.
+ enable_metrics_.Init(prefs::kMetricsReportingEnabled,
+ g_browser_process->local_state(),
+ NULL);
+ enable_metrics_.MoveToThread(BrowserThread::IO);
+#endif // defined(OS_CHROMEOS)
+}
+
+bool ProfileIOData::GetMetricsEnabledStateOnIOThread() const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+#if defined(OS_CHROMEOS)
+ return enable_metrics_;
+#else
+ return enable_metrics_.GetValue();
+#endif // defined(OS_CHROMEOS)
+}
+
chrome_browser_net::HttpServerPropertiesManager*
ProfileIOData::http_server_properties_manager() const {
return http_server_properties_manager_.get();
@@ -464,7 +493,7 @@ void ProfileIOData::LazyInitialize() const {
transport_security_persister_.reset(
new TransportSecurityPersister(transport_security_state_.get(),
profile_params_->path,
- profile_params_->is_incognito));
+ is_incognito()));
const std::string& serialized =
command_line.GetSwitchValueASCII(switches::kHstsHosts);
transport_security_persister_.get()->DeserializeFromCommandLine(serialized);
@@ -479,7 +508,7 @@ void ProfileIOData::LazyInitialize() const {
}
bool set_protocol = job_factory_->SetProtocolHandler(
chrome::kExtensionScheme,
- CreateExtensionProtocolHandler(profile_params_->is_incognito,
+ CreateExtensionProtocolHandler(is_incognito(),
profile_params_->extension_info_map));
DCHECK(set_protocol);
set_protocol = job_factory_->SetProtocolHandler(
@@ -517,7 +546,7 @@ void ProfileIOData::LazyInitialize() const {
void ProfileIOData::ApplyProfileParamsToContext(
ChromeURLRequestContext* context) const {
- context->set_is_incognito(profile_params_->is_incognito);
+ context->set_is_incognito(is_incognito());
context->set_accept_language(profile_params_->accept_language);
context->set_accept_charset(profile_params_->accept_charset);
context->set_referrer_charset(profile_params_->referrer_charset);
@@ -527,6 +556,9 @@ void ProfileIOData::ApplyProfileParamsToContext(
void ProfileIOData::ShutdownOnUIThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
enable_referrers_.Destroy();
+#if !defined(OS_CHROMEOS)
+ enable_metrics_.Destroy();
+#endif
clear_local_state_on_exit_.Destroy();
safe_browsing_enabled_.Destroy();
session_startup_pref_.Destroy();
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h
index 2f892ed..bc10f01 100644
--- a/chrome/browser/profiles/profile_io_data.h
+++ b/chrome/browser/profiles/profile_io_data.h
@@ -114,6 +114,19 @@ class ProfileIOData {
chrome_browser_net::HttpServerPropertiesManager*
http_server_properties_manager() const;
+ bool is_incognito() const {
+ return is_incognito_;
+ }
+
+ // Initialize the member needed to track the metrics enabled state. This is
+ // only to be called on the UI thread.
+ void InitializeMetricsEnabledStateOnUIThread();
+
+ // Returns whether or not metrics reporting is enabled in the browser instance
+ // on which this profile resides. This is safe for use from the IO thread, and
+ // should only be called from there.
+ bool GetMetricsEnabledStateOnIOThread() const;
+
protected:
class AppRequestContext : public ChromeURLRequestContext {
public:
@@ -136,7 +149,6 @@ class ProfileIOData {
~ProfileParams();
FilePath path;
- bool is_incognito;
bool clear_local_state_on_exit;
std::string accept_language;
std::string accept_charset;
@@ -295,6 +307,15 @@ class ProfileIOData {
// TODO(marja): Remove session_startup_pref_ if no longer needed.
mutable IntegerPrefMember session_startup_pref_;
+ // The state of metrics reporting in the browser that this profile runs on.
+ // Unfortunately, since ChromeOS has a separate representation of this state,
+ // we need to make one available based on the platform.
+#if defined(OS_CHROMEOS)
+ bool enable_metrics_;
+#else
+ BooleanPrefMember enable_metrics_;
+#endif
+
// Pointed to by NetworkDelegate.
mutable scoped_ptr<policy::URLBlacklistManager> url_blacklist_manager_;
@@ -333,6 +354,8 @@ class ProfileIOData {
// TODO(jhawkins): Remove once crbug.com/102004 is fixed.
bool initialized_on_UI_thread_;
+ bool is_incognito_;
+
DISALLOW_COPY_AND_ASSIGN(ProfileIOData);
};
diff --git a/chrome/browser/protector/protector_service.cc b/chrome/browser/protector/protector_service.cc
index a70ec37..3dc2a29 100644
--- a/chrome/browser/protector/protector_service.cc
+++ b/chrome/browser/protector/protector_service.cc
@@ -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);
}
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
index 9f01973..a209b33 100644
--- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
+++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/download/download_util.h"
#include "chrome/browser/extensions/user_script_listener.h"
#include "chrome/browser/external_protocol/external_protocol_handler.h"
+#include "chrome/browser/google/google_util.h"
#include "chrome/browser/instant/instant_loader.h"
#include "chrome/browser/net/load_timing_observer.h"
#include "chrome/browser/prerender/prerender_manager.h"
@@ -165,6 +166,8 @@ void ChromeResourceDispatcherHostDelegate::RequestBeginning(
#endif
}
+ AppendChromeMetricsHeaders(request, resource_context, resource_type);
+
AppendStandardResourceThrottles(request,
resource_context,
child_id,
@@ -295,6 +298,28 @@ void ChromeResourceDispatcherHostDelegate::AppendStandardResourceThrottles(
throttles->push_back(throttle);
}
+void ChromeResourceDispatcherHostDelegate::AppendChromeMetricsHeaders(
+ net::URLRequest* request,
+ content::ResourceContext* resource_context,
+ ResourceType::Type resource_type) {
+ // 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 only transmit for non-Incognito profiles.
+ // 3. For the X-Chrome-UMA-Enabled bit, we only set it if UMA is in fact
+ // enabled for this install of Chrome.
+ ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
+ if (google_util::IsGoogleDomainUrl(request->url().spec(),
+ google_util::ALLOW_SUBDOMAIN) &&
+ !io_data->is_incognito() && io_data->GetMetricsEnabledStateOnIOThread()) {
+ request->SetExtraRequestHeaderByName("X-Chrome-UMA-Enabled",
+ "1",
+ false);
+ }
+}
+
bool ChromeResourceDispatcherHostDelegate::ShouldForceDownloadResource(
const GURL& url, const std::string& mime_type) {
// Special-case user scripts to get downloaded instead of viewed.
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h
index 34ffb27..4a4d002 100644
--- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h
+++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h
@@ -87,6 +87,14 @@ class ChromeResourceDispatcherHostDelegate
ResourceType::Type resource_type,
ScopedVector<content::ResourceThrottle>* throttles);
+ // Adds Chrome experiment and metrics state as custom headers to |request|.
+ // This is a best-effort attempt, and does not interrupt the request if the
+ // headers can not be appended.
+ void AppendChromeMetricsHeaders(
+ net::URLRequest* request,
+ content::ResourceContext* resource_context,
+ ResourceType::Type resource_type);
+
scoped_refptr<DownloadRequestLimiter> download_request_limiter_;
scoped_refptr<SafeBrowsingService> safe_browsing_;
scoped_refptr<UserScriptListener> user_script_listener_;
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.cc b/chrome/browser/search_engines/template_url_prepopulate_data.cc
index 7cd25c3..64101db 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data.cc
@@ -3284,7 +3284,8 @@ 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.