// Copyright 2021 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 "android_webview/nonembedded/net/network_fetcher_task.h" #include #include #include #include "android_webview/nonembedded/net/network_impl.h" #include "android_webview/nonembedded/nonembedded_jni_headers/NetworkFetcherTask_jni.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/callback.h" #include "base/check.h" #include "base/files/file_path.h" #include "base/location.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/task/sequenced_task_runner.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "url/android/gurl_android.h" #include "url/gurl.h" namespace android_webview { namespace { using TaskWeakPtr = base::WeakPtr; void InvokePostRequest( TaskWeakPtr weak_ptr, scoped_refptr task_runner, const GURL& url, const std::string& post_data, const std::string& content_type, const base::flat_map& post_additional_headers) { JNIEnv* env = base::android::AttachCurrentThread(); std::vector keys, values; for (auto const& header : post_additional_headers) { keys.push_back(header.first); values.push_back(header.second); } Java_NetworkFetcherTask_postRequest( env, reinterpret_cast(&weak_ptr), reinterpret_cast(task_runner.get()), url::GURLAndroid::FromNativeGURL(env, url), base::android::ToJavaByteArray(env, post_data), base::android::ConvertUTF8ToJavaString(env, content_type), base::android::ToJavaArrayOfStrings(env, keys), base::android::ToJavaArrayOfStrings(env, values)); } void InvokeDownload(TaskWeakPtr weak_ptr, scoped_refptr task_runner, const GURL& url, const base::FilePath& file_path) { JNIEnv* env = base::android::AttachCurrentThread(); Java_NetworkFetcherTask_download( env, reinterpret_cast(&weak_ptr), reinterpret_cast(task_runner.get()), url::GURLAndroid::FromNativeGURL(env, url), base::android::ConvertUTF8ToJavaString(env, file_path.value())); } } // namespace // static void JNI_NetworkFetcherTask_CallProgressCallback(JNIEnv* env, jlong weak_ptr, jlong task_runner, jlong current) { auto* native_task_runner = reinterpret_cast(task_runner); DCHECK(native_task_runner); auto* task = reinterpret_cast(weak_ptr); native_task_runner->PostTask( FROM_HERE, base::BindOnce(&NetworkFetcherTask::InvokeProgressCallback, *task, current)); } // static void JNI_NetworkFetcherTask_CallResponseStartedCallback(JNIEnv* env, jlong weak_ptr, jlong task_runner, jint response_code, jlong content_length) { auto* native_task_runner = reinterpret_cast(task_runner); DCHECK(native_task_runner); auto* task = reinterpret_cast(weak_ptr); native_task_runner->PostTask( FROM_HERE, base::BindOnce(&NetworkFetcherTask::InvokeResponseStartedCallback, *task, response_code, content_length)); } // static void JNI_NetworkFetcherTask_CallDownloadToFileCompleteCallback( JNIEnv* env, jlong weak_ptr, jlong task_runner, jint network_error, jlong content_size) { auto* native_task_runner = reinterpret_cast(task_runner); DCHECK(native_task_runner); auto* task = reinterpret_cast(weak_ptr); native_task_runner->PostTask( FROM_HERE, base::BindOnce(&NetworkFetcherTask::InvokeDownloadToFileCompleteCallback, *task, network_error, content_size)); } // static void JNI_NetworkFetcherTask_CallPostRequestCompleteCallback( JNIEnv* env, jlong weak_ptr, jlong task_runner, const base::android::JavaParamRef& response_body, jint network_error, const base::android::JavaParamRef& header_e_tag, const base::android::JavaParamRef& header_x_cup_server_proof, jlong x_header_retry_after_sec) { auto* native_task_runner = reinterpret_cast(task_runner); DCHECK(native_task_runner); auto* task = reinterpret_cast(weak_ptr); std::string response_body_str; base::android::JavaByteArrayToString(env, response_body, &response_body_str); native_task_runner->PostTask( FROM_HERE, base::BindOnce(&NetworkFetcherTask::InvokePostRequestCompleteCallback, *task, std::make_unique(response_body_str), network_error, base::android::ConvertJavaStringToUTF8(env, header_e_tag), base::android::ConvertJavaStringToUTF8( env, header_x_cup_server_proof), x_header_retry_after_sec)); } // static std::unique_ptr NetworkFetcherTask::CreateDownloadToFileTask( const GURL& url, const base::FilePath& file_path, update_client::NetworkFetcher::ResponseStartedCallback response_started_callback, update_client::NetworkFetcher::ProgressCallback progress_callback, update_client::NetworkFetcher::DownloadToFileCompleteCallback download_to_file_complete_callback) { return std::make_unique( url, file_path, std::move(response_started_callback), progress_callback, std::move(download_to_file_complete_callback)); } // static std::unique_ptr NetworkFetcherTask::CreatePostRequestTask( const GURL& url, const std::string& post_data, const std::string& content_type, const base::flat_map& post_additional_headers, update_client::NetworkFetcher::ResponseStartedCallback response_started_callback, update_client::NetworkFetcher::ProgressCallback progress_callback, update_client::NetworkFetcher::PostRequestCompleteCallback post_request_complete_callback) { return std::make_unique( url, post_data, content_type, post_additional_headers, std::move(response_started_callback), progress_callback, std::move(post_request_complete_callback)); } NetworkFetcherTask::NetworkFetcherTask( const GURL& url, const base::FilePath& file_path, update_client::NetworkFetcher::ResponseStartedCallback response_started_callback, update_client::NetworkFetcher::ProgressCallback progress_callback, update_client::NetworkFetcher::DownloadToFileCompleteCallback download_to_file_complete_callback) : response_started_callback_(std::move(response_started_callback)), progress_callback_(std::move(progress_callback)), download_to_file_complete_callback_( std::move(download_to_file_complete_callback)) { base::ThreadPool::PostTask( FROM_HERE, {base::MayBlock()}, base::BindOnce(&InvokeDownload, weak_ptr_factory_.GetWeakPtr(), task_runner_, url, file_path)); } NetworkFetcherTask::NetworkFetcherTask( const GURL& url, const std::string& post_data, const std::string& content_type, const base::flat_map& post_additional_headers, update_client::NetworkFetcher::ResponseStartedCallback response_started_callback, update_client::NetworkFetcher::ProgressCallback progress_callback, update_client::NetworkFetcher::PostRequestCompleteCallback post_request_complete_callback) : response_started_callback_(std::move(response_started_callback)), progress_callback_(std::move(progress_callback)), post_request_complete_callback_( std::move(post_request_complete_callback)) { base::ThreadPool::PostTask( FROM_HERE, {base::MayBlock()}, base::BindOnce(&InvokePostRequest, weak_ptr_factory_.GetWeakPtr(), task_runner_, url, post_data, content_type, post_additional_headers)); } NetworkFetcherTask::~NetworkFetcherTask() = default; void NetworkFetcherTask::InvokeProgressCallback(int64_t current) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); progress_callback_.Run(current); } void NetworkFetcherTask::InvokeResponseStartedCallback(int response_code, int64_t content_length) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::move(response_started_callback_).Run(response_code, content_length); } void NetworkFetcherTask::InvokeDownloadToFileCompleteCallback( int network_error, int64_t content_size) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::move(download_to_file_complete_callback_) .Run(network_error, content_size); } void NetworkFetcherTask::InvokePostRequestCompleteCallback( std::unique_ptr response_body, int network_error, const std::string& header_etag, const std::string& header_x_cup_server_proof, int64_t x_header_retry_after_sec) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::move(post_request_complete_callback_) .Run(std::move(response_body), network_error, header_etag, header_x_cup_server_proof, x_header_retry_after_sec); } } // namespace android_webview