summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/metrics/chrome_metrics_service_client.cc36
-rw-r--r--chrome/browser/metrics/chrome_metrics_service_client.h4
-rw-r--r--chrome/browser/metrics/compression_utils.h17
-rw-r--r--chrome/browser/metrics/metrics_service.cc105
-rw-r--r--chrome/browser/metrics/metrics_service.h26
-rw-r--r--chrome/chrome_browser.gypi3
-rw-r--r--chrome/chrome_tests_unit.gypi1
-rw-r--r--components/components_tests.gyp5
-rw-r--r--components/metrics.gypi20
-rw-r--r--components/metrics/metrics_log_uploader.cc21
-rw-r--r--components/metrics/metrics_log_uploader.h44
-rw-r--r--components/metrics/metrics_service_client.h10
-rw-r--r--components/metrics/net/DEPS4
-rw-r--r--components/metrics/net/compression_utils.cc (renamed from chrome/browser/metrics/compression_utils.cc)22
-rw-r--r--components/metrics/net/compression_utils.h17
-rw-r--r--components/metrics/net/compression_utils_unittest.cc (renamed from chrome/browser/metrics/compression_utils_unittest.cc)14
-rw-r--r--components/metrics/net/net_metrics_log_uploader.cc74
-rw-r--r--components/metrics/net/net_metrics_log_uploader.h54
-rw-r--r--components/metrics/test_metrics_service_client.cc8
-rw-r--r--components/metrics/test_metrics_service_client.h4
20 files changed, 353 insertions, 136 deletions
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index 1998bab..763d43a 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -4,6 +4,8 @@
#include "chrome/browser/metrics/chrome_metrics_service_client.h"
+#include <vector>
+
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
@@ -26,6 +28,7 @@
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/crash_keys.h"
#include "chrome/common/render_messages.h"
+#include "components/metrics/net/net_metrics_log_uploader.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/histogram_fetcher.h"
#include "content/public/browser/notification_service.h"
@@ -182,6 +185,17 @@ void ChromeMetricsServiceClient::OnLogUploadComplete() {
network_stats_uploader_.CollectAndReportNetworkStats();
}
+void ChromeMetricsServiceClient::StartGatheringMetrics(
+ const base::Closure& done_callback) {
+// TODO(blundell): Move all metrics gathering tasks from MetricsService to
+// here.
+#if defined(OS_CHROMEOS)
+ chromeos_metrics_provider_->InitTaskGetHardwareClass(done_callback);
+#else
+ done_callback.Run();
+#endif
+}
+
void ChromeMetricsServiceClient::CollectFinalMetrics(
const base::Closure& done_callback) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -212,6 +226,17 @@ void ChromeMetricsServiceClient::CollectFinalMetrics(
}
}
+scoped_ptr<metrics::MetricsLogUploader>
+ChromeMetricsServiceClient::CreateUploader(
+ const std::string& server_url,
+ const std::string& mime_type,
+ const base::Callback<void(int)>& on_upload_complete) {
+ return scoped_ptr<metrics::MetricsLogUploader>(
+ new metrics::NetMetricsLogUploader(
+ g_browser_process->system_request_context(), server_url, mime_type,
+ on_upload_complete));
+}
+
void ChromeMetricsServiceClient::OnMemoryDetailCollectionDone() {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -335,17 +360,6 @@ void ChromeMetricsServiceClient::Observe(
}
}
-void ChromeMetricsServiceClient::StartGatheringMetrics(
- const base::Closure& done_callback) {
-// TODO(blundell): Move all metrics gathering tasks from MetricsService to
-// here.
-#if defined(OS_CHROMEOS)
- chromeos_metrics_provider_->InitTaskGetHardwareClass(done_callback);
-#else
- done_callback.Run();
-#endif
-}
-
#if defined(OS_WIN)
void ChromeMetricsServiceClient::CountBrowserCrashDumpAttempts() {
// Open the registry key for iteration.
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.h b/chrome/browser/metrics/chrome_metrics_service_client.h
index aef2120..aba5945 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.h
+++ b/chrome/browser/metrics/chrome_metrics_service_client.h
@@ -48,6 +48,10 @@ class ChromeMetricsServiceClient : public metrics::MetricsServiceClient,
const base::Closure& done_callback) OVERRIDE;
virtual void CollectFinalMetrics(const base::Closure& done_callback)
OVERRIDE;
+ virtual scoped_ptr<metrics::MetricsLogUploader> CreateUploader(
+ const std::string& server_url,
+ const std::string& mime_type,
+ const base::Callback<void(int)>& on_upload_complete) OVERRIDE;
MetricsService* metrics_service() { return metrics_service_.get(); }
diff --git a/chrome/browser/metrics/compression_utils.h b/chrome/browser/metrics/compression_utils.h
deleted file mode 100644
index ec208ec..0000000
--- a/chrome/browser/metrics/compression_utils.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_METRICS_COMPRESSION_UTILS_H_
-#define CHROME_BROWSER_METRICS_COMPRESSION_UTILS_H_
-
-#include <string>
-
-namespace chrome {
-
-// Compresses the text in |input| using gzip storing the result in |output|.
-bool GzipCompress(const std::string& input, std::string* output);
-
-} // namespace chrome
-
-#endif // CHROME_BROWSER_METRICS_COMPRESSION_UTILS_H_
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc
index b12aae4..c616651 100644
--- a/chrome/browser/metrics/metrics_service.cc
+++ b/chrome/browser/metrics/metrics_service.cc
@@ -185,7 +185,6 @@
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/metrics/chrome_stability_metrics_provider.h"
-#include "chrome/browser/metrics/compression_utils.h"
#include "chrome/browser/metrics/gpu_metrics_provider.h"
#include "chrome/browser/metrics/metrics_log.h"
#include "chrome/browser/metrics/metrics_state_manager.h"
@@ -196,12 +195,11 @@
#include "chrome/common/variations/variations_util.h"
#include "components/metrics/metrics_log_base.h"
#include "components/metrics/metrics_log_manager.h"
+#include "components/metrics/metrics_log_uploader.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/metrics_reporting_scheduler.h"
#include "components/metrics/metrics_service_client.h"
#include "components/variations/entropy_provider.h"
-#include "net/base/load_flags.h"
-#include "net/url_request/url_fetcher.h"
#if defined(ENABLE_PLUGINS)
// TODO(asvitkine): Move this out of MetricsService.
@@ -270,12 +268,12 @@ enum ResponseStatus {
ResponseStatus ResponseCodeToStatus(int response_code) {
switch (response_code) {
+ case -1:
+ return NO_RESPONSE;
case 200:
return SUCCESS;
case 400:
return BAD_REQUEST;
- case net::URLFetcher::RESPONSE_CODE_INVALID:
- return NO_RESPONSE;
default:
return UNKNOWN_FAILURE;
}
@@ -371,11 +369,11 @@ MetricsService::MetricsService(metrics::MetricsStateManager* state_manager,
test_mode_active_(false),
state_(INITIALIZED),
has_initial_stability_log_(false),
+ log_upload_in_progress_(false),
idle_since_last_transmission_(false),
session_id_(-1),
self_ptr_factory_(this),
- state_saver_factory_(this),
- waiting_for_asynchronous_reporting_step_(false) {
+ state_saver_factory_(this) {
DCHECK(IsSingleThreaded());
DCHECK(state_manager_);
DCHECK(client_);
@@ -885,7 +883,7 @@ void MetricsService::PushPendingLogsToPersistentStorage() {
if (log_manager_.has_staged_log()) {
// We may race here, and send second copy of the log later.
metrics::PersistedLogs::StoreType store_type;
- if (current_fetch_.get())
+ if (log_upload_in_progress_)
store_type = metrics::PersistedLogs::PROVISIONAL_STORE;
else
store_type = metrics::PersistedLogs::NORMAL_STORE;
@@ -960,11 +958,11 @@ void MetricsService::StartScheduledUpload() {
}
void MetricsService::OnFinalLogInfoCollectionDone() {
- // If somehow there is a fetch in progress, we return and hope things work
- // out. The scheduler isn't informed since if this happens, the scheduler
+ // If somehow there is a log upload in progress, we return and hope things
+ // work out. The scheduler isn't informed since if this happens, the scheduler
// will get a response from the upload.
- DCHECK(!current_fetch_.get());
- if (current_fetch_.get())
+ DCHECK(!log_upload_in_progress_);
+ if (log_upload_in_progress_)
return;
// Abort if metrics were turned off during the final info gathering.
@@ -1111,78 +1109,39 @@ void MetricsService::PrepareInitialMetricsLog() {
void MetricsService::SendStagedLog() {
DCHECK(log_manager_.has_staged_log());
+ if (!log_manager_.has_staged_log())
+ return;
- PrepareFetchWithStagedLog();
+ DCHECK(!log_upload_in_progress_);
+ log_upload_in_progress_ = true;
- bool upload_created = (current_fetch_.get() != NULL);
- UMA_HISTOGRAM_BOOLEAN("UMA.UploadCreation", upload_created);
- if (!upload_created) {
- // Compression failed, and log discarded :-/.
+ if (!log_uploader_) {
+ log_uploader_ = client_->CreateUploader(
+ kServerUrl, kMimeType,
+ base::Bind(&MetricsService::OnLogUploadComplete,
+ self_ptr_factory_.GetWeakPtr()));
+ }
+
+ const std::string hash =
+ base::HexEncode(log_manager_.staged_log_hash().data(),
+ log_manager_.staged_log_hash().size());
+ bool success = log_uploader_->UploadLog(log_manager_.staged_log(), hash);
+ UMA_HISTOGRAM_BOOLEAN("UMA.UploadCreation", success);
+ if (!success) {
// Skip this upload and hope things work out next time.
log_manager_.DiscardStagedLog();
scheduler_->UploadCancelled();
+ log_upload_in_progress_ = false;
return;
}
- DCHECK(!waiting_for_asynchronous_reporting_step_);
- waiting_for_asynchronous_reporting_step_ = true;
-
- current_fetch_->Start();
-
HandleIdleSinceLastTransmission(true);
}
-void MetricsService::PrepareFetchWithStagedLog() {
- DCHECK(log_manager_.has_staged_log());
-
- // Prepare the protobuf version.
- DCHECK(!current_fetch_.get());
- if (log_manager_.has_staged_log()) {
- current_fetch_.reset(net::URLFetcher::Create(
- GURL(kServerUrl), net::URLFetcher::POST, this));
- current_fetch_->SetRequestContext(
- g_browser_process->system_request_context());
-
- std::string log_text = log_manager_.staged_log();
- std::string compressed_log_text;
- bool compression_successful = chrome::GzipCompress(log_text,
- &compressed_log_text);
- DCHECK(compression_successful);
- if (compression_successful) {
- current_fetch_->SetUploadData(kMimeType, compressed_log_text);
- // Tell the server that we're uploading gzipped protobufs.
- current_fetch_->SetExtraRequestHeaders("content-encoding: gzip");
- const std::string hash =
- base::HexEncode(log_manager_.staged_log_hash().data(),
- log_manager_.staged_log_hash().size());
- DCHECK(!hash.empty());
- current_fetch_->AddExtraRequestHeader("X-Chrome-UMA-Log-SHA1: " + hash);
- UMA_HISTOGRAM_PERCENTAGE(
- "UMA.ProtoCompressionRatio",
- 100 * compressed_log_text.size() / log_text.size());
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "UMA.ProtoGzippedKBSaved",
- (log_text.size() - compressed_log_text.size()) / 1024,
- 1, 2000, 50);
- }
-
- // We already drop cookies server-side, but we might as well strip them out
- // client-side as well.
- current_fetch_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES);
- }
-}
-
-void MetricsService::OnURLFetchComplete(const net::URLFetcher* source) {
- DCHECK(waiting_for_asynchronous_reporting_step_);
- // We're not allowed to re-use the existing |URLFetcher|s, so free them here.
- // Note however that |source| is aliased to the fetcher, so we should be
- // careful not to delete it too early.
- DCHECK_EQ(current_fetch_.get(), source);
- scoped_ptr<net::URLFetcher> s(current_fetch_.Pass());
-
- int response_code = source->GetResponseCode();
+void MetricsService::OnLogUploadComplete(int response_code) {
+ DCHECK(log_upload_in_progress_);
+ log_upload_in_progress_ = false;
// Log a histogram to track response success vs. failure rates.
UMA_HISTOGRAM_ENUMERATION("UMA.UploadResponseStatus.Protobuf",
@@ -1210,8 +1169,6 @@ void MetricsService::OnURLFetchComplete(const net::URLFetcher* source) {
if (upload_succeeded || discard_log)
log_manager_.DiscardStagedLog();
- waiting_for_asynchronous_reporting_step_ = false;
-
if (!log_manager_.has_staged_log()) {
switch (state_) {
case SENDING_INITIAL_STABILITY_LOG:
diff --git a/chrome/browser/metrics/metrics_service.h b/chrome/browser/metrics/metrics_service.h
index 705392f..116fadf 100644
--- a/chrome/browser/metrics/metrics_service.h
+++ b/chrome/browser/metrics/metrics_service.h
@@ -32,7 +32,6 @@
#include "components/metrics/metrics_provider.h"
#include "components/metrics/metrics_service_observer.h"
#include "components/variations/active_field_trials.h"
-#include "net/url_request/url_fetcher_delegate.h"
class GoogleUpdateMetricsProviderWin;
class MetricsReportingScheduler;
@@ -55,6 +54,7 @@ namespace content {
}
namespace metrics {
+class MetricsLogUploader;
class MetricsServiceClient;
class MetricsStateManager;
}
@@ -89,8 +89,7 @@ struct SyntheticTrialGroup {
class MetricsService
: public base::HistogramFlattener,
- public chrome_browser_metrics::TrackingSynchronizerObserver,
- public net::URLFetcherDelegate {
+ public chrome_browser_metrics::TrackingSynchronizerObserver {
public:
// The execution phase of the browser.
enum ExecutionPhase {
@@ -357,14 +356,8 @@ class MetricsService
// Uploads the currently staged log (which must be non-null).
void SendStagedLog();
- // Prepared the staged log to be passed to the server. Upon return,
- // current_fetch_ should be reset with its upload data set to a compressed
- // copy of the staged log.
- void PrepareFetchWithStagedLog();
-
- // Implementation of net::URLFetcherDelegate. Called after transmission
- // completes (either successfully or with failure).
- virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
+ // Called after transmission completes (either successfully or with failure).
+ void OnLogUploadComplete(int response_code);
// Reads, increments and then sets the specified integer preference.
void IncrementPrefValue(const char* path);
@@ -453,8 +446,11 @@ class MetricsService
// initial stability log may be sent before this.
scoped_ptr<MetricsLog> initial_metrics_log_;
- // The outstanding transmission appears as a URL Fetch operation.
- scoped_ptr<net::URLFetcher> current_fetch_;
+ // Instance of the helper class for uploading logs.
+ scoped_ptr<metrics::MetricsLogUploader> log_uploader_;
+
+ // Whether there is a current log upload in progress.
+ bool log_upload_in_progress_;
// Whether the MetricsService object has received any notifications since
// the last time a transmission was sent.
@@ -474,10 +470,6 @@ class MetricsService
// The scheduler for determining when uploads should happen.
scoped_ptr<MetricsReportingScheduler> scheduler_;
- // Indicates that an asynchronous reporting step is running.
- // This is used only for debugging.
- bool waiting_for_asynchronous_reporting_step_;
-
// Stores the time of the first call to |GetUptimes()|.
base::TimeTicks first_updated_time_;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index b7288d58..bc33485 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -43,6 +43,7 @@
'../components/components.gyp:infobars_core',
'../components/components.gyp:invalidation',
'../components/components.gyp:metrics',
+ '../components/components.gyp:metrics_net',
'../components/components.gyp:navigation_metrics',
'../components/components.gyp:os_crypt',
'../components/components.gyp:password_manager_core_browser',
@@ -1210,8 +1211,6 @@
'browser/metrics/chrome_metrics_service_client.h',
'browser/metrics/chrome_stability_metrics_provider.cc',
'browser/metrics/chrome_stability_metrics_provider.h',
- 'browser/metrics/compression_utils.cc',
- 'browser/metrics/compression_utils.h',
'browser/metrics/extensions_metrics_provider.cc',
'browser/metrics/extensions_metrics_provider.h',
'browser/metrics/field_trial_synchronizer.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index f30f6f8..5894c64 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -1091,7 +1091,6 @@
'browser/media_galleries/win/mtp_device_object_enumerator_unittest.cc',
'browser/metrics/chrome_metrics_service_accessor_unittest.cc',
'browser/metrics/cloned_install_detector_unittest.cc',
- 'browser/metrics/compression_utils_unittest.cc',
'browser/metrics/extensions_metrics_provider_unittest.cc',
'browser/metrics/gpu_metrics_provider_unittest.cc',
'browser/metrics/metrics_log_unittest.cc',
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 0674d26..56dd758 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -111,6 +111,7 @@
'metrics/metrics_log_base_unittest.cc',
'metrics/metrics_log_manager_unittest.cc',
'metrics/metrics_reporting_scheduler_unittest.cc',
+ 'metrics/net/compression_utils_unittest.cc',
'metrics/persisted_logs_unittest.cc',
'navigation_interception/intercept_navigation_resource_throttle_unittest.cc',
'os_crypt/ie7_password_win_unittest.cc',
@@ -263,6 +264,10 @@
# Dependencies of language_usage_metrics
'components.gyp:language_usage_metrics',
+ # Dependencies of metrics
+ 'components.gyp:metrics',
+ 'components.gyp:metrics_net',
+
# Dependencies of os_crypt
'components.gyp:os_crypt',
diff --git a/components/metrics.gypi b/components/metrics.gypi
index fd79d50..f9896fb 100644
--- a/components/metrics.gypi
+++ b/components/metrics.gypi
@@ -25,6 +25,8 @@
'metrics/metrics_hashes.h',
'metrics/metrics_log_base.cc',
'metrics/metrics_log_base.h',
+ 'metrics/metrics_log_uploader.cc',
+ 'metrics/metrics_log_uploader.h',
'metrics/metrics_log_manager.cc',
'metrics/metrics_log_manager.h',
'metrics/metrics_pref_names.cc',
@@ -51,6 +53,24 @@
],
},
{
+ 'target_name': 'metrics_net',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
+ ],
+ 'dependencies': [
+ '../net/net.gyp:net',
+ '../third_party/zlib/zlib.gyp:zlib',
+ 'metrics',
+ ],
+ 'sources': [
+ 'metrics/net/compression_utils.cc',
+ 'metrics/net/compression_utils.h',
+ 'metrics/net/net_metrics_log_uploader.cc',
+ 'metrics/net/net_metrics_log_uploader.h',
+ ],
+ },
+ {
# Protobuf compiler / generator for UMA (User Metrics Analysis).
'target_name': 'component_metrics_proto',
'type': 'static_library',
diff --git a/components/metrics/metrics_log_uploader.cc b/components/metrics/metrics_log_uploader.cc
new file mode 100644
index 0000000..41b83ed
--- /dev/null
+++ b/components/metrics/metrics_log_uploader.cc
@@ -0,0 +1,21 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/metrics/metrics_log_uploader.h"
+
+namespace metrics {
+
+MetricsLogUploader::MetricsLogUploader(
+ const std::string& server_url,
+ const std::string& mime_type,
+ const base::Callback<void(int)>& on_upload_complete)
+ : server_url_(server_url),
+ mime_type_(mime_type),
+ on_upload_complete_(on_upload_complete) {
+}
+
+MetricsLogUploader::~MetricsLogUploader() {
+}
+
+} // namespace metrics
diff --git a/components/metrics/metrics_log_uploader.h b/components/metrics/metrics_log_uploader.h
new file mode 100644
index 0000000..0deecc8
--- /dev/null
+++ b/components/metrics/metrics_log_uploader.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_METRICS_METRICS_LOG_UPLOADER_H_
+#define COMPONENTS_METRICS_METRICS_LOG_UPLOADER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/macros.h"
+
+namespace metrics {
+
+// MetricsLogUploader is an abstract base class for uploading UMA logs on behalf
+// of MetricsService.
+class MetricsLogUploader {
+ public:
+ // Constructs the uploader that will upload logs to the specified |server_url|
+ // with the given |mime_type|. The |on_upload_complete| callback will be
+ // called with the HTTP response code of the upload or with -1 on an error.
+ MetricsLogUploader(const std::string& server_url,
+ const std::string& mime_type,
+ const base::Callback<void(int)>& on_upload_complete);
+ virtual ~MetricsLogUploader();
+
+ // Uploads a log with the specified |log_data| and |log_hash|. |log_hash| is
+ // expected to be the hex-encoded SHA1 hash of |log_data|.
+ virtual bool UploadLog(const std::string& log_data,
+ const std::string& log_hash) = 0;
+
+ protected:
+ const std::string server_url_;
+ const std::string mime_type_;
+ const base::Callback<void(int)> on_upload_complete_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MetricsLogUploader);
+};
+
+} // namespace metrics
+
+#endif // COMPONENTS_METRICS_METRICS_LOG_UPLOADER_H_
diff --git a/components/metrics/metrics_service_client.h b/components/metrics/metrics_service_client.h
index dbad4a3..1fcfb6e 100644
--- a/components/metrics/metrics_service_client.h
+++ b/components/metrics/metrics_service_client.h
@@ -9,10 +9,13 @@
#include "base/basictypes.h"
#include "base/callback_forward.h"
+#include "base/memory/scoped_ptr.h"
#include "components/metrics/proto/system_profile.pb.h"
namespace metrics {
+class MetricsLogUploader;
+
// An abstraction of operations that depend on the embedder's (e.g. Chrome)
// environment.
class MetricsServiceClient {
@@ -50,6 +53,13 @@ class MetricsServiceClient {
// extra histograms that will go in that log. Asynchronous API - the client
// implementation should call |done_callback| when complete.
virtual void CollectFinalMetrics(const base::Closure& done_callback) = 0;
+
+ // Creates a MetricsLogUploader with the specified parameters (see comments on
+ // MetricsLogUploader for details).
+ virtual scoped_ptr<MetricsLogUploader> CreateUploader(
+ const std::string& server_url,
+ const std::string& mime_type,
+ const base::Callback<void(int)>& on_upload_complete) = 0;
};
} // namespace metrics
diff --git a/components/metrics/net/DEPS b/components/metrics/net/DEPS
new file mode 100644
index 0000000..71ea427
--- /dev/null
+++ b/components/metrics/net/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+net",
+ "+third_party/zlib",
+]
diff --git a/chrome/browser/metrics/compression_utils.cc b/components/metrics/net/compression_utils.cc
index 71f68ab..e8efe18 100644
--- a/chrome/browser/metrics/compression_utils.cc
+++ b/components/metrics/net/compression_utils.cc
@@ -1,8 +1,8 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/metrics/compression_utils.h"
+#include "components/metrics/net/compression_utils.h"
#include <vector>
@@ -62,31 +62,35 @@ int GzipCompressHelper(Bytef* dest,
err = deflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
- deflateEnd(&stream);
- return err == Z_OK ? Z_BUF_ERROR : err;
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
}
*dest_length = stream.total_out;
err = deflateEnd(&stream);
return err;
}
+
} // namespace
-namespace chrome {
+namespace metrics {
bool GzipCompress(const std::string& input, std::string* output) {
+ const uLongf input_size = static_cast<uLongf>(input.size());
std::vector<Bytef> compressed_data(kGzipZlibHeaderDifferenceBytes +
- compressBound(input.size()));
+ compressBound(input_size));
- uLongf compressed_size = compressed_data.size();
+ uLongf compressed_size = static_cast<uLongf>(compressed_data.size());
if (GzipCompressHelper(&compressed_data.front(),
&compressed_size,
bit_cast<const Bytef*>(input.data()),
- input.size()) != Z_OK)
+ input_size) != Z_OK) {
return false;
+ }
compressed_data.resize(compressed_size);
output->assign(compressed_data.begin(), compressed_data.end());
return true;
}
-} // namespace chrome
+
+} // namespace metrics
diff --git a/components/metrics/net/compression_utils.h b/components/metrics/net/compression_utils.h
new file mode 100644
index 0000000..ee875dd
--- /dev/null
+++ b/components/metrics/net/compression_utils.h
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_METRICS_NET_COMPRESSION_UTILS_H_
+#define COMPONENTS_METRICS_NET_COMPRESSION_UTILS_H_
+
+#include <string>
+
+namespace metrics {
+
+// Compresses the text in |input| using gzip, storing the result in |output|.
+bool GzipCompress(const std::string& input, std::string* output);
+
+} // namespace metrics
+
+#endif // COMPONENTS_METRICS_NET_COMPRESSION_UTILS_H_
diff --git a/chrome/browser/metrics/compression_utils_unittest.cc b/components/metrics/net/compression_utils_unittest.cc
index ad05eef..05305d4 100644
--- a/chrome/browser/metrics/compression_utils_unittest.cc
+++ b/components/metrics/net/compression_utils_unittest.cc
@@ -1,17 +1,19 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "components/metrics/net/compression_utils.h"
+
#include <string>
#include "base/base_paths.h"
#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/path_service.h"
-#include "chrome/browser/metrics/compression_utils.h"
-#include "chrome/common/chrome_paths.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace metrics {
+
namespace {
// The data to be compressed by gzip. This is the hex representation of "hello
@@ -35,14 +37,16 @@ const uint8 kCompressedData[] =
#pragma warning( default: 4309 )
#endif
+} // namespace
+
TEST(CompressionUtilsTest, GzipCompression) {
std::string data(reinterpret_cast<const char*>(kData), arraysize(kData));
std::string compressed_data;
- EXPECT_TRUE(chrome::GzipCompress(data, &compressed_data));
+ EXPECT_TRUE(GzipCompress(data, &compressed_data));
std::string golden_compressed_data(
reinterpret_cast<const char*>(kCompressedData),
arraysize(kCompressedData));
EXPECT_EQ(golden_compressed_data, compressed_data);
}
-} // namespace
+} // namespace metrics
diff --git a/components/metrics/net/net_metrics_log_uploader.cc b/components/metrics/net/net_metrics_log_uploader.cc
new file mode 100644
index 0000000..09042bd
--- /dev/null
+++ b/components/metrics/net/net_metrics_log_uploader.cc
@@ -0,0 +1,74 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/metrics/net/net_metrics_log_uploader.h"
+
+#include "base/metrics/histogram.h"
+#include "components/metrics/net/compression_utils.h"
+#include "net/base/load_flags.h"
+#include "net/url_request/url_fetcher.h"
+#include "url/gurl.h"
+
+namespace metrics {
+
+NetMetricsLogUploader::NetMetricsLogUploader(
+ net::URLRequestContextGetter* request_context_getter,
+ const std::string& server_url,
+ const std::string& mime_type,
+ const base::Callback<void(int)>& on_upload_complete)
+ : MetricsLogUploader(server_url, mime_type, on_upload_complete),
+ request_context_getter_(request_context_getter) {
+}
+
+NetMetricsLogUploader::~NetMetricsLogUploader() {
+}
+
+bool NetMetricsLogUploader::UploadLog(const std::string& log_data,
+ const std::string& log_hash) {
+ std::string compressed_log_data;
+ if (!GzipCompress(log_data, &compressed_log_data)) {
+ NOTREACHED();
+ return false;
+ }
+
+ UMA_HISTOGRAM_PERCENTAGE(
+ "UMA.ProtoCompressionRatio",
+ static_cast<int>(100 * compressed_log_data.size() / log_data.size()));
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "UMA.ProtoGzippedKBSaved",
+ static_cast<int>((log_data.size() - compressed_log_data.size()) / 1024),
+ 1, 2000, 50);
+
+ current_fetch_.reset(
+ net::URLFetcher::Create(GURL(server_url_), net::URLFetcher::POST, this));
+ current_fetch_->SetRequestContext(request_context_getter_);
+ current_fetch_->SetUploadData(mime_type_, compressed_log_data);
+
+ // Tell the server that we're uploading gzipped protobufs.
+ current_fetch_->SetExtraRequestHeaders("content-encoding: gzip");
+
+ DCHECK(!log_hash.empty());
+ current_fetch_->AddExtraRequestHeader("X-Chrome-UMA-Log-SHA1: " + log_hash);
+
+ // We already drop cookies server-side, but we might as well strip them out
+ // client-side as well.
+ current_fetch_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
+ net::LOAD_DO_NOT_SEND_COOKIES);
+ return true;
+}
+
+void NetMetricsLogUploader::OnURLFetchComplete(const net::URLFetcher* source) {
+ // We're not allowed to re-use the existing |URLFetcher|s, so free them here.
+ // Note however that |source| is aliased to the fetcher, so we should be
+ // careful not to delete it too early.
+ DCHECK_EQ(current_fetch_.get(), source);
+
+ int response_code = source->GetResponseCode();
+ if (response_code == net::URLFetcher::RESPONSE_CODE_INVALID)
+ response_code = -1;
+ on_upload_complete_.Run(response_code);
+ current_fetch_.reset();
+}
+
+} // namespace metrics
diff --git a/components/metrics/net/net_metrics_log_uploader.h b/components/metrics/net/net_metrics_log_uploader.h
new file mode 100644
index 0000000..4753fd7
--- /dev/null
+++ b/components/metrics/net/net_metrics_log_uploader.h
@@ -0,0 +1,54 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_METRICS_NET_NET_METRICS_LOG_UPLOADER_H_
+#define COMPONENTS_METRICS_NET_NET_METRICS_LOG_UPLOADER_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "components/metrics/metrics_log_uploader.h"
+#include "net/url_request/url_fetcher_delegate.h"
+
+namespace net {
+class URLFetcher;
+class URLRequestContextGetter;
+}
+
+namespace metrics {
+
+// Implementation of MetricsLogUploader using the Chrome network stack.
+class NetMetricsLogUploader : public MetricsLogUploader,
+ public net::URLFetcherDelegate {
+ public:
+ // Constructs a NetMetricsLogUploader with the specified request context and
+ // other params (see comments on MetricsLogUploader for details). The caller
+ // must ensure that |request_context_getter| remains valid for the lifetime
+ // of this class.
+ NetMetricsLogUploader(net::URLRequestContextGetter* request_context_getter,
+ const std::string& server_url,
+ const std::string& mime_type,
+ const base::Callback<void(int)>& on_upload_complete);
+ virtual ~NetMetricsLogUploader();
+
+ // MetricsLogUploader:
+ virtual bool UploadLog(const std::string& log_data,
+ const std::string& log_hash) OVERRIDE;
+
+ private:
+ // net::URLFetcherDelegate:
+ virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
+
+ // The request context for fetches done using the network stack.
+ net::URLRequestContextGetter* const request_context_getter_;
+
+ // The outstanding transmission appears as a URL Fetch operation.
+ scoped_ptr<net::URLFetcher> current_fetch_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetMetricsLogUploader);
+};
+
+} // namespace metrics
+
+#endif // COMPONENTS_METRICS_NET_NET_METRICS_LOG_UPLOADER_H_
diff --git a/components/metrics/test_metrics_service_client.cc b/components/metrics/test_metrics_service_client.cc
index 891b90f..8d1b337 100644
--- a/components/metrics/test_metrics_service_client.cc
+++ b/components/metrics/test_metrics_service_client.cc
@@ -5,6 +5,7 @@
#include "components/metrics/test_metrics_service_client.h"
#include "base/callback.h"
+#include "components/metrics/metrics_log_uploader.h"
namespace metrics {
@@ -55,4 +56,11 @@ void TestMetricsServiceClient::CollectFinalMetrics(
done_callback.Run();
}
+scoped_ptr<MetricsLogUploader> TestMetricsServiceClient::CreateUploader(
+ const std::string& server_url,
+ const std::string& mime_type,
+ const base::Callback<void(int)>& on_upload_complete) {
+ return scoped_ptr<MetricsLogUploader>();
+}
+
} // namespace metrics
diff --git a/components/metrics/test_metrics_service_client.h b/components/metrics/test_metrics_service_client.h
index b5b7ba9..407109d 100644
--- a/components/metrics/test_metrics_service_client.h
+++ b/components/metrics/test_metrics_service_client.h
@@ -32,6 +32,10 @@ class TestMetricsServiceClient : public MetricsServiceClient {
const base::Closure& done_callback) OVERRIDE;
virtual void CollectFinalMetrics(const base::Closure& done_callback)
OVERRIDE;
+ virtual scoped_ptr<MetricsLogUploader> CreateUploader(
+ const std::string& server_url,
+ const std::string& mime_type,
+ const base::Callback<void(int)>& on_upload_complete) OVERRIDE;
const std::string& get_client_id() const { return client_id_; }