// Copyright (c) 2014 The Chromium Embedded Framework 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 "CefURLRequest_N.h" #include "include/cef_request.h" #include "include/cef_task.h" #include "include/cef_urlrequest.h" #include "critical_wait.h" #include "jni_scoped_helpers.h" #include "jni_util.h" #include "url_request_client.h" namespace { class URLRequest : public CefTask { public: URLRequest(CefThreadId threadId, CefRefPtr request, CefRefPtr client) : threadId_(threadId), request_(request), client_(client), waitCond_(&lock_) {} bool Create() { if (!urlRequest_) Dispatch(REQ_CREATE); return (urlRequest_.get() != nullptr); } CefURLRequest::Status GetRequestStatus() { if (!urlRequest_) return UR_UNKNOWN; Dispatch(REQ_STATUS); return status_; } CefURLRequest::ErrorCode GetRequestError() { if (!urlRequest_) return ERR_FAILED; Dispatch(REQ_ERROR); return error_; } CefRefPtr GetResponse() { if (!urlRequest_) return nullptr; Dispatch(REQ_RESPONSE); return response_; } void Cancel() { if (!urlRequest_) return; Dispatch(REQ_CANCEL); } private: enum URLRequestMode { REQ_CREATE, REQ_STATUS, REQ_ERROR, REQ_RESPONSE, REQ_CANCEL, }; CefThreadId threadId_; CefRefPtr request_; CefRefPtr client_; // sync method calls CriticalLock lock_; CriticalWait waitCond_; URLRequestMode mode_; // result values CefRefPtr urlRequest_; CefURLRequest::Status status_; CefURLRequest::ErrorCode error_; CefRefPtr response_; void Dispatch(URLRequestMode mode) { mode_ = mode; if (CefCurrentlyOn(threadId_)) { Execute(); } else { lock_.Lock(); CefPostTask(threadId_, this); waitCond_.Wait(); lock_.Unlock(); } } virtual void Execute() override { lock_.Lock(); switch (mode_) { case REQ_CREATE: // TODO(JCEF): Add the ability to specify a CefRequestContext. urlRequest_ = CefURLRequest::Create(request_, client_.get(), nullptr); break; case REQ_STATUS: status_ = urlRequest_->GetRequestStatus(); break; case REQ_ERROR: error_ = urlRequest_->GetRequestError(); break; case REQ_RESPONSE: response_ = urlRequest_->GetResponse(); break; case REQ_CANCEL: urlRequest_->Cancel(); break; } waitCond_.WakeUp(); lock_.Unlock(); } IMPLEMENT_REFCOUNTING(URLRequest); }; const char kCefClassName[] = "CefURLRequest"; CefRefPtr GetSelf(jlong self) { return reinterpret_cast(self); } } // namespace JNIEXPORT void JNICALL Java_org_cef_network_CefURLRequest_1N_N_1Create(JNIEnv* env, jobject obj, jobject jrequest, jobject jRequestClient) { ScopedJNIRequest requestObj(env); requestObj.SetHandle(jrequest, false /* should_delete */); CefRefPtr request = requestObj.GetCefObject(); if (!request) return; CefRefPtr client = URLRequestClient::Create(env, jRequestClient, obj); CefRefPtr urlRequest = new URLRequest(TID_UI, request, client); if (!urlRequest->Create()) return; SetCefForJNIObject(env, obj, urlRequest.get(), kCefClassName); } JNIEXPORT void JNICALL Java_org_cef_network_CefURLRequest_1N_N_1Dispose(JNIEnv* env, jobject obj, jlong self) { SetCefForJNIObject(env, obj, nullptr, kCefClassName); } JNIEXPORT jobject JNICALL Java_org_cef_network_CefURLRequest_1N_N_1GetRequestStatus(JNIEnv* env, jobject obj, jlong self) { CefRefPtr urlRequest = GetSelf(self); if (!urlRequest) return nullptr; ScopedJNIURLRequestStatus status(env, urlRequest->GetRequestStatus()); return status.Release(); } JNIEXPORT jobject JNICALL Java_org_cef_network_CefURLRequest_1N_N_1GetRequestError(JNIEnv* env, jobject obj, jlong self) { CefRefPtr urlRequest = GetSelf(self); cef_errorcode_t err = ERR_FAILED; if (urlRequest) err = urlRequest->GetRequestError(); return NewJNIErrorCode(env, err); } JNIEXPORT jobject JNICALL Java_org_cef_network_CefURLRequest_1N_N_1GetResponse(JNIEnv* env, jobject obj, jlong self) { CefRefPtr urlRequest = GetSelf(self); if (!urlRequest) return nullptr; CefRefPtr response = urlRequest->GetResponse(); if (!response) return nullptr; ScopedJNIResponse jresponse(env, response); return jresponse.Release(); } JNIEXPORT void JNICALL Java_org_cef_network_CefURLRequest_1N_N_1Cancel(JNIEnv* env, jobject obj, jlong self) { CefRefPtr urlRequest = GetSelf(self); if (!urlRequest) return; urlRequest->Cancel(); }