| // 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<CefRequest> request, |
| CefRefPtr<URLRequestClient> 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<CefResponse> 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<CefRequest> request_; |
| CefRefPtr<URLRequestClient> client_; |
| |
| // sync method calls |
| CriticalLock lock_; |
| CriticalWait waitCond_; |
| URLRequestMode mode_; |
| |
| // result values |
| CefRefPtr<CefURLRequest> urlRequest_; |
| CefURLRequest::Status status_; |
| CefURLRequest::ErrorCode error_; |
| CefRefPtr<CefResponse> 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<URLRequest> GetSelf(jlong self) { |
| return reinterpret_cast<URLRequest*>(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<CefRequest> request = requestObj.GetCefObject(); |
| if (!request) |
| return; |
| |
| CefRefPtr<URLRequestClient> client = |
| URLRequestClient::Create(env, jRequestClient, obj); |
| |
| CefRefPtr<URLRequest> urlRequest = new URLRequest(TID_UI, request, client); |
| if (!urlRequest->Create()) |
| return; |
| SetCefForJNIObject_sync(env, obj, urlRequest.get(), kCefClassName); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_org_cef_network_CefURLRequest_1N_N_1Dispose(JNIEnv* env, |
| jobject obj, |
| jlong self) { |
| SetCefForJNIObject_sync<URLRequest>(env, obj, nullptr, kCefClassName); |
| } |
| |
| JNIEXPORT jobject JNICALL |
| Java_org_cef_network_CefURLRequest_1N_N_1GetRequestStatus(JNIEnv* env, |
| jobject obj, |
| jlong self) { |
| CefRefPtr<URLRequest> 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> 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> urlRequest = GetSelf(self); |
| if (!urlRequest) |
| return nullptr; |
| |
| CefRefPtr<CefResponse> 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> urlRequest = GetSelf(self); |
| if (!urlRequest) |
| return; |
| urlRequest->Cancel(); |
| } |