chromium/components/embedder_support/android/metrics/android_metrics_log_uploader.cc

// Copyright 2020 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/embedder_support/android/metrics/android_metrics_log_uploader.h"

#include "base/android/jni_array.h"
#include "base/task/thread_pool.h"
#include "components/embedder_support/android/metrics/features.h"
#include "components/metrics/log_decoder.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "components/embedder_support/android/metrics/jni/AndroidMetricsLogUploader_jni.h"

using base::android::ScopedJavaLocalRef;
using base::android::ToJavaByteArray;

namespace metrics {

AndroidMetricsLogUploader::AndroidMetricsLogUploader(
    const MetricsLogUploader::UploadCallback& on_upload_complete)
    : on_upload_complete_(on_upload_complete) {}

AndroidMetricsLogUploader::~AndroidMetricsLogUploader() = default;

int32_t UploadLogWithUploader(const std::string& log_data,
                              const bool async_metric_logging_feature) {
  JNIEnv* env = jni_zero::AttachCurrentThread();
  ScopedJavaLocalRef<jbyteArray> java_data = ToJavaByteArray(env, log_data);

  return Java_AndroidMetricsLogUploader_uploadLog(env, java_data,
                                                  async_metric_logging_feature);
}

void AndroidMetricsLogUploader::UploadLog(
    const std::string& compressed_log_data,
    const LogMetadata& /*log_metadata*/,
    const std::string& /*log_hash*/,
    const std::string& /*log_signature*/,
    const ReportingInfo& reporting_info) {
  // This uploader uses the platform logging mechanism instead of the normal UMA
  // server. The platform mechanism does its own compression, so undo the
  // previous compression.
  std::string log_data;
  if (!DecodeLogData(compressed_log_data, &log_data)) {
    // If the log is corrupt, pretend the server rejected it (HTTP Bad Request).
    OnUploadComplete(400);
    return;
  }

  if (base::FeatureList::IsEnabled(kAndroidMetricsAsyncMetricLogging)) {
    base::ThreadPool::PostTaskAndReplyWithResult(
        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
        base::BindOnce(&UploadLogWithUploader, log_data, true),
        base::BindOnce(&AndroidMetricsLogUploader::OnUploadComplete,
                       weak_factory_.GetWeakPtr()));
  } else {
    UploadLogWithUploader(log_data, false);

    // Just pass 200 (HTTP OK) and pretend everything is peachy.
    OnUploadComplete(200);
  }
}

void AndroidMetricsLogUploader::OnUploadComplete(const int32_t status) {
  on_upload_complete_.Run(status, /*error_code=*/0, /*was_https=*/true,
                          /*force_discard=*/false, /*force_discard_reason=*/"");
}

}  // namespace metrics