| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/enterprise/browser/reporting/real_time_uploader.h" |
| |
| #include <queue> |
| |
| #include "base/logging.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/metrics/histogram_functions.h" |
| #include "base/task/bind_post_task.h" |
| #include "base/task/sequenced_task_runner.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "build/build_config.h" |
| #include "components/prefs/pref_service.h" |
| |
| namespace enterprise_reporting { |
| |
| // static |
| std::unique_ptr<RealTimeUploader> RealTimeUploader::Create( |
| const std::string& dm_token, |
| reporting::Destination destination, |
| reporting::Priority priority) { |
| auto uploader = base::WrapUnique(new RealTimeUploader(priority)); |
| // Create report queue outside ctor so that it can be skipped in unrelated |
| // unittests. |
| uploader->CreateReportQueue(dm_token, destination); |
| return uploader; |
| } |
| |
| RealTimeUploader::RealTimeUploader(reporting::Priority priority) |
| : report_queue_(nullptr, |
| base::OnTaskRunnerDeleter( |
| base::SequencedTaskRunner::GetCurrentDefault())), |
| report_priority_(priority) {} |
| |
| RealTimeUploader::~RealTimeUploader() = default; |
| |
| void RealTimeUploader::Upload( |
| std::unique_ptr<google::protobuf::MessageLite> report, |
| EnqueueCallback callback) { |
| DCHECK_NE(report_priority_, reporting::Priority::UNDEFINED_PRIORITY); |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| |
| if (!report_queue_) { |
| NOTREACHED(); |
| } |
| |
| report_queue_->Enqueue( |
| std::move(report), report_priority_, |
| base::BindPostTask( |
| base::SingleThreadTaskRunner::GetCurrentDefault(), |
| base::BindOnce(&RealTimeUploader::OnReportEnqueued, |
| weak_factory_.GetWeakPtr(), std::move(callback)))); |
| } |
| |
| reporting::ReportQueue* RealTimeUploader::GetReportQueue() const { |
| return report_queue_.get(); |
| } |
| |
| void RealTimeUploader::CreateReportQueue(const std::string& dm_token, |
| reporting::Destination destination) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| |
| #if !BUILDFLAG(IS_IOS) |
| // Not using ReportQueueFactory as we need to provide DM token manually. |
| auto config = reporting::ReportQueueConfiguration::Create( |
| dm_token, destination, |
| base::BindRepeating([]() { return reporting::Status::StatusOK(); })); |
| |
| if (!config.has_value()) { |
| // No special handler as we never record reporting queue config creation |
| // failure. |
| LOG(ERROR) << "Failed to create CBCM reporting queue config: " |
| << config.error(); |
| return; |
| } |
| |
| auto report_queue = reporting::ReportQueueProvider::CreateSpeculativeQueue( |
| std::move(config.value())); |
| if (!report_queue.has_value()) { |
| // No special handler as we never record reporting queue creation failure. |
| LOG(ERROR) << "Failed to create CBCM reporting queue. " |
| << report_queue.error(); |
| return; |
| } |
| report_queue_ = std::move(report_queue.value()); |
| #else |
| NOTREACHED(); |
| #endif // !BUILDFLAG(IS_IOS) |
| } |
| |
| void RealTimeUploader::OnReportEnqueued(EnqueueCallback callback, |
| reporting::Status status) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| base::UmaHistogramEnumeration("Enterprise.CBCMRealTimeReportEnqueue", |
| status.code(), |
| reporting::error::Code::MAX_VALUE); |
| LOG_IF(ERROR, !status.ok()) << "Failed to enqueue a request: " << status; |
| std::move(callback).Run(status.ok()); |
| } |
| |
| } // namespace enterprise_reporting |