blob: 282468d810aa13c72299f2cd710c043fb8233ac6 [file] [log] [blame] [edit]
// Copyright 2025 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/proxy_callback_request_adapter.h"
#include <memory>
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/functional/bind.h"
#include "base/task/single_thread_task_runner.h"
#include "base/types/expected.h"
#include "net/base/net_errors.h"
#include "net/base/proxy_delegate.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_util.h"
// Must come after all headers that specialize FromJniType() / ToJniType().
#include "components/cronet/android/cronet_jni_headers/ProxyCallbackRequestImpl_jni.h"
namespace cronet {
base::android::ScopedJavaLocalRef<jobject>
ProxyCallbackRequestAdapter::CreateProxyCallbackRequest(
net::ProxyDelegate::OnBeforeTunnelRequestCallback callback) {
JNIEnv* env = base::android::AttachCurrentThread();
return Java_ProxyCallbackRequestImpl_Constructor(
env, reinterpret_cast<long>(
new ProxyCallbackRequestAdapter(std::move(callback))));
}
ProxyCallbackRequestAdapter::ProxyCallbackRequestAdapter(
net::ProxyDelegate::OnBeforeTunnelRequestCallback callback)
: callback_(std::move(callback)),
network_task_runner_(base::SingleThreadTaskRunner::GetCurrentDefault()) {}
ProxyCallbackRequestAdapter::~ProxyCallbackRequestAdapter() = default;
bool ProxyCallbackRequestAdapter::Proceed(
JNIEnv* env,
std::vector<std::string> jextra_headers) {
net::HttpRequestHeaders extra_headers;
for (size_t i = 0; i < jextra_headers.size(); i += 2) {
auto& key = jextra_headers[i];
auto& value = jextra_headers[i + 1];
if (!net::HttpUtil::IsValidHeaderName(key) ||
!net::HttpUtil::IsValidHeaderValue(value)) {
return false;
}
extra_headers.SetHeader(key, value);
}
network_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback_), std::move(extra_headers)));
delete this;
return true;
}
void ProxyCallbackRequestAdapter::Cancel(JNIEnv* env) {
// TODO(https://crbug.com/422428959): Decide whether we want to propagate
// org.chromium.net.Proxy.Callback canceling a tunnel establishment request as
// something else (net::ERR_TUNNEL_CONNECTION_FAILED?
// net::ERR_BLOCKED_BY_CLIENT? net::ERR_PROXY_TUNNEL_REQUEST_FAILED?). This is
// currently not possible, as net::ProxyFallback::CanFalloverToNextProxy does
// not try the next proxy for a lot of these errors, unless the chain is for
// IP Protection. For the time being, we return another error for which the
// next proxy is in the list is always attempted.
network_task_runner_->PostTask(
FROM_HERE, base::BindOnce(std::move(callback_),
base::unexpected(net::ERR_CONNECTION_CLOSED)));
delete this;
}
} // namespace cronet