| // 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 <string> |
| #include <utility> |
| #include <vector> |
| |
| #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/sequenced_task_runner.h" |
| #include "base/task/post_task.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<NetworkFetcherTask>; |
| |
| void InvokePostRequest( |
| TaskWeakPtr weak_ptr, |
| scoped_refptr<base::SequencedTaskRunner> task_runner, |
| const GURL& url, |
| const std::string& post_data, |
| const std::string& content_type, |
| const base::flat_map<std::string, std::string>& post_additional_headers) { |
| JNIEnv* env = base::android::AttachCurrentThread(); |
| |
| std::vector<std::string> 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<intptr_t>(&weak_ptr), |
| reinterpret_cast<intptr_t>(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<base::SequencedTaskRunner> task_runner, |
| const GURL& url, |
| const base::FilePath& file_path) { |
| JNIEnv* env = base::android::AttachCurrentThread(); |
| Java_NetworkFetcherTask_download( |
| env, reinterpret_cast<intptr_t>(&weak_ptr), |
| reinterpret_cast<intptr_t>(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<base::SequencedTaskRunner*>(task_runner); |
| DCHECK(native_task_runner); |
| |
| auto* task = reinterpret_cast<TaskWeakPtr*>(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<base::SequencedTaskRunner*>(task_runner); |
| DCHECK(native_task_runner); |
| |
| auto* task = reinterpret_cast<TaskWeakPtr*>(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<base::SequencedTaskRunner*>(task_runner); |
| DCHECK(native_task_runner); |
| |
| auto* task = reinterpret_cast<TaskWeakPtr*>(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<jbyteArray>& response_body, |
| jint network_error, |
| const base::android::JavaParamRef<jstring>& header_e_tag, |
| const base::android::JavaParamRef<jstring>& header_x_cup_server_proof, |
| jlong x_header_retry_after_sec) { |
| auto* native_task_runner = |
| reinterpret_cast<base::SequencedTaskRunner*>(task_runner); |
| DCHECK(native_task_runner); |
| |
| auto* task = reinterpret_cast<TaskWeakPtr*>(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<std::string>(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> |
| 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<NetworkFetcherTask>( |
| url, file_path, std::move(response_started_callback), progress_callback, |
| std::move(download_to_file_complete_callback)); |
| } |
| |
| // static |
| std::unique_ptr<NetworkFetcherTask> NetworkFetcherTask::CreatePostRequestTask( |
| const GURL& url, |
| const std::string& post_data, |
| const std::string& content_type, |
| const base::flat_map<std::string, std::string>& 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<NetworkFetcherTask>( |
| 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<std::string, std::string>& 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<std::string> 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 |