| Index: chrome/browser/android/data_usage/external_data_use_reporter.cc
|
| diff --git a/chrome/browser/android/data_usage/external_data_use_observer.cc b/chrome/browser/android/data_usage/external_data_use_reporter.cc
|
| similarity index 51%
|
| copy from chrome/browser/android/data_usage/external_data_use_observer.cc
|
| copy to chrome/browser/android/data_usage/external_data_use_reporter.cc
|
| index 36d3c860696f824c193bcb56a3c77f97804bc704..898a7cbe485388776e0531c15ae2837a965f9b03 100644
|
| --- a/chrome/browser/android/data_usage/external_data_use_observer.cc
|
| +++ b/chrome/browser/android/data_usage/external_data_use_reporter.cc
|
| @@ -1,23 +1,19 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Copyright 2016 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/android/data_usage/external_data_use_observer.h"
|
| +#include "chrome/browser/android/data_usage/external_data_use_reporter.h"
|
|
|
| #include <utility>
|
|
|
| -#include "base/containers/hash_tables.h"
|
| -#include "base/message_loop/message_loop.h"
|
| #include "base/metrics/field_trial.h"
|
| #include "base/metrics/histogram_base.h"
|
| #include "base/metrics/histogram_macros.h"
|
| -#include "base/single_thread_task_runner.h"
|
| #include "base/strings/string_number_conversions.h"
|
| -#include "base/task_runner_util.h"
|
| +#include "chrome/browser/android/data_usage/data_use_tab_model.h"
|
| #include "chrome/browser/android/data_usage/external_data_use_observer_bridge.h"
|
| #include "components/data_usage/core/data_use.h"
|
| #include "components/variations/variations_associated_data.h"
|
| -#include "content/public/browser/browser_thread.h"
|
|
|
| namespace chrome {
|
|
|
| @@ -25,33 +21,41 @@ namespace android {
|
|
|
| namespace {
|
|
|
| +// Default duration after which a pending data use report is considered timed
|
| +// out. May be overridden by the field trial.
|
| +const int kDefaultDataUseReportSubmitTimeoutMsec = 60 * 2 * 1000; // 2 minutes.
|
| +
|
| +// Default value of the minimum number of bytes that should be buffered before
|
| +// a data use report is submitted. May be overridden by the field trial.
|
| +const int64_t kDefaultDataUseReportMinBytes = 100 * 1024; // 100 KB.
|
| +
|
| // Record the result of data use report submission. |bytes| is the sum of send
|
| // and received bytes in the report.
|
| void RecordDataUsageReportSubmission(
|
| - ExternalDataUseObserver::DataUsageReportSubmissionResult result,
|
| + ExternalDataUseReporter::DataUsageReportSubmissionResult result,
|
| int64_t bytes) {
|
| DCHECK_LE(0, bytes);
|
| UMA_HISTOGRAM_ENUMERATION(
|
| "DataUsage.ReportSubmissionResult", result,
|
| - ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_MAX);
|
| + ExternalDataUseReporter::DATAUSAGE_REPORT_SUBMISSION_MAX);
|
| // Cap to the maximum sample value.
|
| const int32_t bytes_capped = bytes <= base::HistogramBase::kSampleType_MAX - 1
|
| ? bytes
|
| : base::HistogramBase::kSampleType_MAX - 1;
|
| switch (result) {
|
| - case ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL:
|
| + case ExternalDataUseReporter::DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL:
|
| UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Bytes.Successful",
|
| bytes_capped);
|
| break;
|
| - case ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_FAILED:
|
| + case ExternalDataUseReporter::DATAUSAGE_REPORT_SUBMISSION_FAILED:
|
| UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Bytes.Failed",
|
| bytes_capped);
|
| break;
|
| - case ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT:
|
| + case ExternalDataUseReporter::DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT:
|
| UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Bytes.TimedOut",
|
| bytes_capped);
|
| break;
|
| - case ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_LOST:
|
| + case ExternalDataUseReporter::DATAUSAGE_REPORT_SUBMISSION_LOST:
|
| UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Bytes.Lost",
|
| bytes_capped);
|
| break;
|
| @@ -61,40 +65,12 @@ void RecordDataUsageReportSubmission(
|
| }
|
| }
|
|
|
| -// Default duration after which matching rules are periodically fetched. May be
|
| -// overridden by the field trial.
|
| -const int kDefaultFetchMatchingRulesDurationSeconds = 60 * 15; // 15 minutes.
|
| -
|
| -// Default duration after which a pending data use report is considered timed
|
| -// out. May be overridden by the field trial.
|
| -const int kDefaultDataUseReportSubmitTimeoutMsec = 60 * 2 * 1000; // 2 minutes.
|
| -
|
| -// Default value of the minimum number of bytes that should be buffered before
|
| -// a data use report is submitted. May be overridden by the field trial.
|
| -const int64_t kDefaultDataUseReportMinBytes = 100 * 1024; // 100 KB.
|
| -
|
| -// Populates various parameters from the values specified in the field trial.
|
| -int32_t GetFetchMatchingRulesDurationSeconds() {
|
| - int32_t duration_seconds = -1;
|
| - const std::string variation_value = variations::GetVariationParamValue(
|
| - chrome::android::ExternalDataUseObserver::
|
| - kExternalDataUseObserverFieldTrial,
|
| - "fetch_matching_rules_duration_seconds");
|
| - if (!variation_value.empty() &&
|
| - base::StringToInt(variation_value, &duration_seconds)) {
|
| - DCHECK_LE(0, duration_seconds);
|
| - return duration_seconds;
|
| - }
|
| - return kDefaultFetchMatchingRulesDurationSeconds;
|
| -}
|
| -
|
| -// Populates various parameters from the values specified in the field trial.
|
| -int32_t GetDataReportSubmitTimeoutMsec() {
|
| +// Populates various parameters from the values specified in the field trial
|
| +// |field_trial|.
|
| +int32_t GetDataReportSubmitTimeoutMsec(const char* field_trial) {
|
| int32_t duration_seconds = -1;
|
| const std::string variation_value = variations::GetVariationParamValue(
|
| - chrome::android::ExternalDataUseObserver::
|
| - kExternalDataUseObserverFieldTrial,
|
| - "data_report_submit_timeout_msec");
|
| + field_trial, "data_report_submit_timeout_msec");
|
| if (!variation_value.empty() &&
|
| base::StringToInt(variation_value, &duration_seconds)) {
|
| DCHECK_LE(0, duration_seconds);
|
| @@ -103,13 +79,12 @@ int32_t GetDataReportSubmitTimeoutMsec() {
|
| return kDefaultDataUseReportSubmitTimeoutMsec;
|
| }
|
|
|
| -// Populates various parameters from the values specified in the field trial.
|
| -int64_t GetMinBytes() {
|
| +// Populates various parameters from the values specified in the field trial
|
| +// |field_trial|.
|
| +int64_t GetMinBytes(const char* field_trial) {
|
| int64_t min_bytes = -1;
|
| const std::string variation_value = variations::GetVariationParamValue(
|
| - chrome::android::ExternalDataUseObserver::
|
| - kExternalDataUseObserverFieldTrial,
|
| - "data_use_report_min_bytes");
|
| + field_trial, "data_use_report_min_bytes");
|
| if (!variation_value.empty() &&
|
| base::StringToInt64(variation_value, &min_bytes)) {
|
| DCHECK_LE(0, min_bytes);
|
| @@ -121,79 +96,58 @@ int64_t GetMinBytes() {
|
| } // namespace
|
|
|
| // static
|
| -const char ExternalDataUseObserver::kExternalDataUseObserverFieldTrial[] =
|
| - "ExternalDataUseObserver";
|
| -
|
| -// static
|
| -const size_t ExternalDataUseObserver::kMaxBufferSize = 100;
|
| -
|
| -ExternalDataUseObserver::ExternalDataUseObserver(
|
| - data_usage::DataUseAggregator* data_use_aggregator,
|
| - const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
|
| - const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
|
| - : data_use_aggregator_(data_use_aggregator),
|
| - external_data_use_observer_bridge_(new ExternalDataUseObserverBridge()),
|
| - data_use_tab_model_(new DataUseTabModel()),
|
| +const size_t ExternalDataUseReporter::kMaxBufferSize = 100;
|
| +
|
| +ExternalDataUseReporter::ExternalDataUseReporter(
|
| + const char* field_trial,
|
| + DataUseTabModel* data_use_tab_model,
|
| + ExternalDataUseObserverBridge* external_data_use_observer_bridge)
|
| + : external_data_use_observer_bridge_(external_data_use_observer_bridge),
|
| + data_use_tab_model_(data_use_tab_model),
|
| last_data_report_submitted_ticks_(base::TimeTicks()),
|
| pending_report_bytes_(0),
|
| - ui_task_runner_(ui_task_runner),
|
| previous_report_time_(base::Time::Now()),
|
| - last_matching_rules_fetch_time_(base::TimeTicks::Now()),
|
| total_bytes_buffered_(0),
|
| - fetch_matching_rules_duration_(
|
| - base::TimeDelta::FromSeconds(GetFetchMatchingRulesDurationSeconds())),
|
| - data_use_report_min_bytes_(GetMinBytes()),
|
| - data_report_submit_timeout_(
|
| - base::TimeDelta::FromMilliseconds(GetDataReportSubmitTimeoutMsec())),
|
| + data_use_report_min_bytes_(GetMinBytes(field_trial)),
|
| + data_report_submit_timeout_(base::TimeDelta::FromMilliseconds(
|
| + GetDataReportSubmitTimeoutMsec(field_trial))) {
|
| + DCHECK(last_data_report_submitted_ticks_.is_null());
|
| + // Detach from current thread since rest of ExternalDataUseReporter lives on
|
| + // the UI thread and the current thread may not be UI thread..
|
| + thread_checker_.DetachFromThread();
|
| +}
|
| +
|
| +void ExternalDataUseReporter::InitOnUIThread() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| #if defined(OS_ANDROID)
|
| - app_state_listener_(new base::android::ApplicationStatusListener(
|
| - base::Bind(&ExternalDataUseObserver::OnApplicationStateChange,
|
| - base::Unretained(this)))),
|
| + app_state_listener_.reset(new base::android::ApplicationStatusListener(
|
| + base::Bind(&ExternalDataUseReporter::OnApplicationStateChange,
|
| + base::Unretained(this))));
|
| #endif
|
| - registered_as_data_use_observer_(false),
|
| - weak_factory_(this) {
|
| - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
|
| - DCHECK(data_use_aggregator_);
|
| - DCHECK(io_task_runner);
|
| - DCHECK(ui_task_runner_);
|
| - DCHECK(last_data_report_submitted_ticks_.is_null());
|
| +}
|
|
|
| - ui_task_runner_->PostTask(FROM_HERE,
|
| - base::Bind(&DataUseTabModel::InitOnUIThread,
|
| - base::Unretained(data_use_tab_model_),
|
| - external_data_use_observer_bridge_));
|
| -
|
| - // Initialize the ExternalDataUseObserverBridge object. It is okay to use
|
| - // base::Unretained here since |external_data_use_observer_bridge_| is owned
|
| - // by |this|, and is destroyed on UI thread when |this| is destroyed.
|
| - ui_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ExternalDataUseObserverBridge::Init,
|
| - base::Unretained(external_data_use_observer_bridge_),
|
| - io_task_runner, GetWeakPtr(), data_use_tab_model_));
|
| +ExternalDataUseReporter::~ExternalDataUseReporter() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| }
|
|
|
| -ExternalDataUseObserver::~ExternalDataUseObserver() {
|
| +void ExternalDataUseReporter::OnDataUse(const data_usage::DataUse& data_use) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
|
|
| - if (registered_as_data_use_observer_)
|
| - data_use_aggregator_->RemoveObserver(this);
|
| + const base::Time now_time = base::Time::Now();
|
| + DataUseTabModel::TrackingInfo tracking_info;
|
|
|
| - // Delete |data_use_tab_model_| on the UI thread. |data_use_tab_model_| should
|
| - // be deleted before |external_data_use_observer_bridge_|.
|
| - if (!ui_task_runner_->DeleteSoon(FROM_HERE, data_use_tab_model_)) {
|
| - NOTIMPLEMENTED() << " DataUseTabModel was not deleted successfully";
|
| + if (!data_use_tab_model_->GetTrackingInfoForTabAtTime(
|
| + data_use.tab_id, data_use.request_start, &tracking_info)) {
|
| + return;
|
| }
|
|
|
| - // Delete |external_data_use_observer_bridge_| on the UI thread.
|
| - if (!ui_task_runner_->DeleteSoon(FROM_HERE,
|
| - external_data_use_observer_bridge_)) {
|
| - NOTIMPLEMENTED()
|
| - << " ExternalDataUseObserverBridge was not deleted successfully";
|
| - }
|
| + BufferDataUseReport(data_use, tracking_info.label, tracking_info.tag,
|
| + previous_report_time_, now_time);
|
| + SubmitBufferedDataUseReport(false);
|
| + previous_report_time_ = now_time;
|
| }
|
|
|
| -void ExternalDataUseObserver::OnReportDataUseDone(bool success) {
|
| +void ExternalDataUseReporter::OnReportDataUseDone(bool success) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| DCHECK(!last_data_report_submitted_ticks_.is_null());
|
|
|
| @@ -215,89 +169,20 @@ void ExternalDataUseObserver::OnReportDataUseDone(bool success) {
|
| }
|
|
|
| #if defined(OS_ANDROID)
|
| -void ExternalDataUseObserver::OnApplicationStateChange(
|
| +void ExternalDataUseReporter::OnApplicationStateChange(
|
| base::android::ApplicationState new_state) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + // TODO(rajendrant): When Chromium is backgrounded, only one data use report
|
| + // is submitted since the external API only supports one pending report
|
| + // submission. Once the external API supports submitting multiple reports
|
| + // in one call, all reports should be submitted immediately.
|
| if (new_state == base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES)
|
| SubmitBufferedDataUseReport(true);
|
| }
|
| #endif
|
|
|
| -void ExternalDataUseObserver::OnDataUse(const data_usage::DataUse& data_use) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - DCHECK(registered_as_data_use_observer_);
|
| -
|
| - const base::TimeTicks now_ticks = base::TimeTicks::Now();
|
| - const base::Time now_time = base::Time::Now();
|
| -
|
| - // If the time when the matching rules were last fetched is more than
|
| - // |fetch_matching_rules_duration_|, fetch them again.
|
| - if (now_ticks - last_matching_rules_fetch_time_ >=
|
| - fetch_matching_rules_duration_) {
|
| - FetchMatchingRules();
|
| - }
|
| -
|
| - std::unique_ptr<DataUseTabModel::TrackingInfo> tracking_info(
|
| - new DataUseTabModel::TrackingInfo());
|
| -
|
| - content::BrowserThread::PostTaskAndReplyWithResult(
|
| - content::BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&DataUseTabModel::GetTrackingInfoForTabAtTime,
|
| - base::Unretained(data_use_tab_model_), data_use.tab_id,
|
| - data_use.request_start, tracking_info.get()),
|
| - base::Bind(&ExternalDataUseObserver::DataUseTrackingInfoRetrieved,
|
| - GetWeakPtr(), data_use, previous_report_time_, now_time,
|
| - base::Owned(tracking_info.release())));
|
| -
|
| - previous_report_time_ = now_time;
|
| -}
|
| -
|
| -void ExternalDataUseObserver::ShouldRegisterAsDataUseObserver(
|
| - bool should_register) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - if (registered_as_data_use_observer_ == should_register)
|
| - return;
|
| -
|
| - if (!registered_as_data_use_observer_ && should_register)
|
| - data_use_aggregator_->AddObserver(this);
|
| -
|
| - if (registered_as_data_use_observer_ && !should_register)
|
| - data_use_aggregator_->RemoveObserver(this);
|
| -
|
| - registered_as_data_use_observer_ = should_register;
|
| -}
|
| -
|
| -void ExternalDataUseObserver::FetchMatchingRules() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - last_matching_rules_fetch_time_ = base::TimeTicks::Now();
|
| -
|
| - // It is okay to use base::Unretained here since
|
| - // |external_data_use_observer_bridge_| is owned by |this|, and is destroyed
|
| - // on UI thread when |this| is destroyed.
|
| - ui_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ExternalDataUseObserverBridge::FetchMatchingRules,
|
| - base::Unretained(external_data_use_observer_bridge_)));
|
| -}
|
| -
|
| -void ExternalDataUseObserver::DataUseTrackingInfoRetrieved(
|
| - const data_usage::DataUse& data_use,
|
| - const base::Time& start_time,
|
| - const base::Time& end_time,
|
| - const DataUseTabModel::TrackingInfo* tracking_info,
|
| - bool tracking_info_valid) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - if (!tracking_info_valid)
|
| - return;
|
| -
|
| - BufferDataUseReport(data_use, tracking_info->label, tracking_info->tag,
|
| - start_time, end_time);
|
| - SubmitBufferedDataUseReport(false);
|
| -}
|
| -
|
| -void ExternalDataUseObserver::BufferDataUseReport(
|
| +void ExternalDataUseReporter::BufferDataUseReport(
|
| const data_usage::DataUse& data_use,
|
| const std::string& label,
|
| const std::string& tag,
|
| @@ -322,7 +207,8 @@ void ExternalDataUseObserver::BufferDataUseReport(
|
| buffered_data_reports_.find(data_use_report_key);
|
| if (it == buffered_data_reports_.end()) {
|
| // Limit the buffer size.
|
| - if (buffered_data_reports_.size() == kMaxBufferSize) {
|
| + if (buffered_data_reports_.size() ==
|
| + ExternalDataUseReporter::kMaxBufferSize) {
|
| RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_LOST,
|
| data_use.rx_bytes + data_use.tx_bytes);
|
| return;
|
| @@ -342,10 +228,11 @@ void ExternalDataUseObserver::BufferDataUseReport(
|
| total_bytes_buffered_ += (data_use.rx_bytes + data_use.tx_bytes);
|
|
|
| DCHECK_LT(0U, buffered_data_reports_.size());
|
| - DCHECK_LE(buffered_data_reports_.size(), kMaxBufferSize);
|
| + DCHECK_LE(buffered_data_reports_.size(),
|
| + ExternalDataUseReporter::kMaxBufferSize);
|
| }
|
|
|
| -void ExternalDataUseObserver::SubmitBufferedDataUseReport(bool immediate) {
|
| +void ExternalDataUseReporter::SubmitBufferedDataUseReport(bool immediate) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
|
|
| const base::TimeTicks ticks_now = base::TimeTicks::Now();
|
| @@ -386,29 +273,12 @@ void ExternalDataUseObserver::SubmitBufferedDataUseReport(bool immediate) {
|
| buffered_data_reports_.erase(it);
|
| total_bytes_buffered_ -= (report.bytes_downloaded + report.bytes_uploaded);
|
|
|
| - // It is okay to use base::Unretained here since
|
| - // |external_data_use_observer_bridge_| is owned by |this|, and is destroyed
|
| - // on UI thread when |this| is destroyed.
|
| - ui_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ExternalDataUseObserverBridge::ReportDataUse,
|
| - base::Unretained(external_data_use_observer_bridge_),
|
| - key.label, key.tag, key.connection_type, key.mcc_mnc,
|
| - report.start_time, report.end_time, report.bytes_downloaded,
|
| - report.bytes_uploaded));
|
| -}
|
| -
|
| -base::WeakPtr<ExternalDataUseObserver> ExternalDataUseObserver::GetWeakPtr() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - return weak_factory_.GetWeakPtr();
|
| -}
|
| -
|
| -DataUseTabModel* ExternalDataUseObserver::GetDataUseTabModel() const {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - return data_use_tab_model_;
|
| + external_data_use_observer_bridge_->ReportDataUse(
|
| + key.label, key.tag, key.connection_type, key.mcc_mnc, report.start_time,
|
| + report.end_time, report.bytes_downloaded, report.bytes_uploaded);
|
| }
|
|
|
| -ExternalDataUseObserver::DataUseReportKey::DataUseReportKey(
|
| +ExternalDataUseReporter::DataUseReportKey::DataUseReportKey(
|
| const std::string& label,
|
| const std::string& tag,
|
| net::NetworkChangeNotifier::ConnectionType connection_type,
|
| @@ -418,17 +288,16 @@ ExternalDataUseObserver::DataUseReportKey::DataUseReportKey(
|
| connection_type(connection_type),
|
| mcc_mnc(mcc_mnc) {}
|
|
|
| -ExternalDataUseObserver::DataUseReportKey::DataUseReportKey(
|
| - const ExternalDataUseObserver::DataUseReportKey& other) =
|
| - default;
|
| +ExternalDataUseReporter::DataUseReportKey::DataUseReportKey(
|
| + const ExternalDataUseReporter::DataUseReportKey& other) = default;
|
|
|
| -bool ExternalDataUseObserver::DataUseReportKey::operator==(
|
| +bool ExternalDataUseReporter::DataUseReportKey::operator==(
|
| const DataUseReportKey& other) const {
|
| return label == other.label && tag == other.tag &&
|
| connection_type == other.connection_type && mcc_mnc == other.mcc_mnc;
|
| }
|
|
|
| -ExternalDataUseObserver::DataUseReport::DataUseReport(
|
| +ExternalDataUseReporter::DataUseReport::DataUseReport(
|
| const base::Time& start_time,
|
| const base::Time& end_time,
|
| int64_t bytes_downloaded,
|
| @@ -438,7 +307,7 @@ ExternalDataUseObserver::DataUseReport::DataUseReport(
|
| bytes_downloaded(bytes_downloaded),
|
| bytes_uploaded(bytes_uploaded) {}
|
|
|
| -size_t ExternalDataUseObserver::DataUseReportKeyHash::operator()(
|
| +size_t ExternalDataUseReporter::DataUseReportKeyHash::operator()(
|
| const DataUseReportKey& k) const {
|
| // The hash is computed by hashing individual variables and combining them
|
| // using prime numbers. Prime numbers are used for multiplication because the
|
|
|