chromium/components/cronet/android/cronet_upload_data_stream_adapter.cc

// Copyright 2015 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/cronet/android/cronet_upload_data_stream_adapter.h"

#include <memory>
#include <string>
#include <utility>

#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/check_op.h"
#include "base/functional/bind.h"
#include "base/task/single_thread_task_runner.h"
#include "components/cronet/android/cronet_url_request_adapter.h"
#include "components/cronet/android/io_buffer_with_byte_buffer.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "components/cronet/android/cronet_jni_headers/CronetUploadDataStream_jni.h"

using base::android::JavaParamRef;

namespace cronet {

CronetUploadDataStreamAdapter::CronetUploadDataStreamAdapter(
    JNIEnv* env,
    jobject jupload_data_stream) {
  jupload_data_stream_.Reset(env, jupload_data_stream);
}

CronetUploadDataStreamAdapter::~CronetUploadDataStreamAdapter() {
}

void CronetUploadDataStreamAdapter::InitializeOnNetworkThread(
    base::WeakPtr<CronetUploadDataStream> upload_data_stream) {
  DCHECK(!upload_data_stream_);
  DCHECK(!network_task_runner_.get());

  upload_data_stream_ = upload_data_stream;
  network_task_runner_ = base::SingleThreadTaskRunner::GetCurrentDefault();
  DCHECK(network_task_runner_);
}

void CronetUploadDataStreamAdapter::Read(scoped_refptr<net::IOBuffer> buffer,
                                         int buf_len) {
  DCHECK(upload_data_stream_);
  DCHECK(network_task_runner_);
  DCHECK(network_task_runner_->BelongsToCurrentThread());
  DCHECK_GT(buf_len, 0);

  JNIEnv* env = base::android::AttachCurrentThread();
  // Allow buffer reuse if |buffer| and |buf_len| are exactly the same as the
  // ones used last time.
  if (!(buffer_ && buffer_->io_buffer()->data() == buffer->data() &&
        buffer_->io_buffer_len() == buf_len)) {
    buffer_ = std::make_unique<ByteBufferWithIOBuffer>(env, std::move(buffer),
                                                       buf_len);
  }
  Java_CronetUploadDataStream_readData(env, jupload_data_stream_,
                                       buffer_->byte_buffer());
}

void CronetUploadDataStreamAdapter::Rewind() {
  DCHECK(upload_data_stream_);
  DCHECK(network_task_runner_->BelongsToCurrentThread());

  JNIEnv* env = base::android::AttachCurrentThread();
  Java_CronetUploadDataStream_rewind(env, jupload_data_stream_);
}

void CronetUploadDataStreamAdapter::OnUploadDataStreamDestroyed() {
  // If CronetUploadDataStream::InitInternal was never called,
  // |upload_data_stream_| and |network_task_runner_| will be NULL.
  DCHECK(!network_task_runner_ ||
         network_task_runner_->BelongsToCurrentThread());

  JNIEnv* env = base::android::AttachCurrentThread();
  Java_CronetUploadDataStream_onUploadDataStreamDestroyed(env,
                                                          jupload_data_stream_);
  // |this| is invalid here since the Java call above effectively destroys it.
}

void CronetUploadDataStreamAdapter::OnReadSucceeded(
    JNIEnv* env,
    const JavaParamRef<jobject>& jcaller,
    int bytes_read,
    bool final_chunk) {
  DCHECK(bytes_read > 0 || (final_chunk && bytes_read == 0));

  network_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&CronetUploadDataStream::OnReadSuccess,
                                upload_data_stream_, bytes_read, final_chunk));
}

void CronetUploadDataStreamAdapter::OnRewindSucceeded(
    JNIEnv* env,
    const JavaParamRef<jobject>& jcaller) {
  network_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&CronetUploadDataStream::OnRewindSuccess,
                                upload_data_stream_));
}

void CronetUploadDataStreamAdapter::Destroy(JNIEnv* env) {
  delete this;
}

static jlong JNI_CronetUploadDataStream_AttachUploadDataToRequest(
    JNIEnv* env,
    const JavaParamRef<jobject>& jupload_data_stream,
    jlong jcronet_url_request_adapter,
    jlong jlength) {
  CronetURLRequestAdapter* request_adapter =
      reinterpret_cast<CronetURLRequestAdapter*>(jcronet_url_request_adapter);
  DCHECK(request_adapter != nullptr);

  CronetUploadDataStreamAdapter* adapter =
      new CronetUploadDataStreamAdapter(env, jupload_data_stream);

  std::unique_ptr<CronetUploadDataStream> upload_data_stream(
      new CronetUploadDataStream(adapter, jlength));

  request_adapter->SetUpload(std::move(upload_data_stream));

  return reinterpret_cast<jlong>(adapter);
}

static jlong JNI_CronetUploadDataStream_CreateAdapterForTesting(
    JNIEnv* env,
    const JavaParamRef<jobject>& jupload_data_stream) {
  CronetUploadDataStreamAdapter* adapter =
      new CronetUploadDataStreamAdapter(env, jupload_data_stream);
  return reinterpret_cast<jlong>(adapter);
}

static jlong JNI_CronetUploadDataStream_CreateUploadDataStreamForTesting(
    JNIEnv* env,
    const JavaParamRef<jobject>& jupload_data_stream,
    jlong jlength,
    jlong jadapter) {
  CronetUploadDataStreamAdapter* adapter =
      reinterpret_cast<CronetUploadDataStreamAdapter*>(jadapter);
  CronetUploadDataStream* upload_data_stream =
      new CronetUploadDataStream(adapter, jlength);
  return reinterpret_cast<jlong>(upload_data_stream);
}

}  // namespace cronet