mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
- Add CefURLRequest support (issue #517).
- Add CefBrowserProcessHandler interface (issue #650). - Internally re-register supported schemes with CefCookieManager after changing the storage path (issue #651). - Add CefResourceHandler callbacks for blocking cookie loading and saving (issue #652). - Allow custom scheme handlers for requests that do not originate from browser content (issue #653). - Use 'int' instead of 'RequestFlags' for CefRequest::GetFlags and SetFlags (issue #654). - Rename cef_request.h CreateObject methods to Create (issue #655). - Add #ifdef guards to cef_tuple.h to allow the use of both cef_runnable.h and base/bind.h in the same unit test source file. - Retrieve cookieable schemes as part of ClientApp::RegisterCustomSchemes and register with the global cookie manager. git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@697 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
375
libcef/renderer/render_urlrequest_impl.cc
Normal file
375
libcef/renderer/render_urlrequest_impl.cc
Normal file
@ -0,0 +1,375 @@
|
||||
// Copyright (c) 2012 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 "libcef/renderer/render_urlrequest_impl.h"
|
||||
#include "libcef/common/request_impl.h"
|
||||
#include "libcef/common/response_impl.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebKitPlatformSupport.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLError.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLLoader.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLLoaderClient.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLRequest.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLResponse.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
|
||||
|
||||
using WebKit::WebString;
|
||||
using WebKit::WebURL;
|
||||
using WebKit::WebURLError;
|
||||
using WebKit::WebURLLoader;
|
||||
using WebKit::WebURLRequest;
|
||||
using WebKit::WebURLResponse;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class CefWebURLLoaderClient : public WebKit::WebURLLoaderClient {
|
||||
public:
|
||||
CefWebURLLoaderClient(CefRenderURLRequest::Context* context,
|
||||
int request_flags);
|
||||
virtual ~CefWebURLLoaderClient();
|
||||
|
||||
// WebKit::WebURLLoaderClient methods.
|
||||
virtual void willSendRequest(
|
||||
WebURLLoader* loader,
|
||||
WebURLRequest& newRequest,
|
||||
const WebURLResponse& redirectResponse) OVERRIDE;
|
||||
virtual void didSendData(
|
||||
WebURLLoader* loader,
|
||||
unsigned long long bytesSent,
|
||||
unsigned long long totalBytesToBeSent) OVERRIDE;
|
||||
virtual void didReceiveResponse(
|
||||
WebURLLoader* loader,
|
||||
const WebURLResponse& response) OVERRIDE;
|
||||
virtual void didDownloadData(WebURLLoader* loader,
|
||||
int dataLength) OVERRIDE;
|
||||
virtual void didReceiveData(WebURLLoader* loader,
|
||||
const char* data,
|
||||
int dataLength,
|
||||
int encodedDataLength) OVERRIDE;
|
||||
virtual void didReceiveCachedMetadata(WebURLLoader* loader,
|
||||
const char* data,
|
||||
int dataLength) OVERRIDE;
|
||||
virtual void didFinishLoading(WebURLLoader* loader,
|
||||
double finishTime) OVERRIDE;
|
||||
virtual void didFail(WebURLLoader* loader,
|
||||
const WebURLError& error) OVERRIDE;
|
||||
|
||||
protected:
|
||||
// The context_ pointer will outlive this object.
|
||||
CefRenderURLRequest::Context* context_;
|
||||
int request_flags_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// CefRenderURLRequest::Context -----------------------------------------------
|
||||
|
||||
class CefRenderURLRequest::Context
|
||||
: public base::RefCountedThreadSafe<CefRenderURLRequest::Context> {
|
||||
public:
|
||||
Context(CefRefPtr<CefRenderURLRequest> url_request,
|
||||
CefRefPtr<CefRequest> request,
|
||||
CefRefPtr<CefURLRequestClient> client)
|
||||
: url_request_(url_request),
|
||||
request_(request),
|
||||
client_(client),
|
||||
message_loop_proxy_(MessageLoop::current()->message_loop_proxy()),
|
||||
status_(UR_IO_PENDING),
|
||||
error_code_(ERR_NONE),
|
||||
upload_data_size_(0),
|
||||
got_upload_progress_complete_(false),
|
||||
download_data_received_(0),
|
||||
download_data_total_(-1) {
|
||||
// Mark the request as read-only.
|
||||
static_cast<CefRequestImpl*>(request_.get())->SetReadOnly(true);
|
||||
}
|
||||
|
||||
virtual ~Context() {
|
||||
}
|
||||
|
||||
inline bool CalledOnValidThread() {
|
||||
return message_loop_proxy_->BelongsToCurrentThread();
|
||||
}
|
||||
|
||||
bool Start() {
|
||||
DCHECK(CalledOnValidThread());
|
||||
|
||||
GURL url = GURL(request_->GetURL().ToString());
|
||||
if (!url.is_valid())
|
||||
return false;
|
||||
|
||||
loader_.reset(WebKit::webKitPlatformSupport()->createURLLoader());
|
||||
url_client_.reset(new CefWebURLLoaderClient(this, request_->GetFlags()));
|
||||
|
||||
WebURLRequest urlRequest;
|
||||
static_cast<CefRequestImpl*>(request_.get())->Get(urlRequest);
|
||||
|
||||
if (urlRequest.reportUploadProgress()) {
|
||||
// Attempt to determine the upload data size.
|
||||
CefRefPtr<CefPostData> post_data = request_->GetPostData();
|
||||
if (post_data.get()) {
|
||||
CefPostData::ElementVector elements;
|
||||
post_data->GetElements(elements);
|
||||
if (elements.size() == 1 && elements[0]->GetType() == PDE_TYPE_BYTES) {
|
||||
CefPostDataElementImpl* impl =
|
||||
static_cast<CefPostDataElementImpl*>(elements[0].get());
|
||||
upload_data_size_ = impl->GetBytesCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loader_->loadAsynchronously(urlRequest, url_client_.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
void Cancel() {
|
||||
DCHECK(CalledOnValidThread());
|
||||
|
||||
// The request may already be complete.
|
||||
if (!loader_.get() || status_ != UR_IO_PENDING)
|
||||
return;
|
||||
|
||||
status_ = UR_CANCELED;
|
||||
error_code_ = ERR_ABORTED;
|
||||
|
||||
// Will result in a call to OnError().
|
||||
loader_->cancel();
|
||||
}
|
||||
|
||||
void OnResponse(const WebURLResponse& response) {
|
||||
DCHECK(CalledOnValidThread());
|
||||
|
||||
response_ = CefResponse::Create();
|
||||
CefResponseImpl* responseImpl =
|
||||
static_cast<CefResponseImpl*>(response_.get());
|
||||
responseImpl->Set(response);
|
||||
responseImpl->SetReadOnly(true);
|
||||
|
||||
download_data_total_ = response.expectedContentLength();
|
||||
}
|
||||
|
||||
void OnError(const WebURLError& error) {
|
||||
DCHECK(CalledOnValidThread());
|
||||
|
||||
if (status_ == UR_IO_PENDING) {
|
||||
status_ = UR_FAILED;
|
||||
error_code_ = static_cast<CefURLRequest::ErrorCode>(error.reason);
|
||||
}
|
||||
|
||||
OnComplete();
|
||||
}
|
||||
|
||||
void OnComplete() {
|
||||
DCHECK(CalledOnValidThread());
|
||||
|
||||
if (status_ == UR_IO_PENDING) {
|
||||
status_ = UR_SUCCESS;
|
||||
NotifyUploadProgressIfNecessary();
|
||||
}
|
||||
|
||||
if (loader_.get())
|
||||
loader_.reset(NULL);
|
||||
|
||||
DCHECK(url_request_.get());
|
||||
client_->OnRequestComplete(url_request_.get());
|
||||
|
||||
// This may result in the Context object being deleted.
|
||||
url_request_ = NULL;
|
||||
}
|
||||
|
||||
void OnDownloadProgress(int64 current) {
|
||||
DCHECK(CalledOnValidThread());
|
||||
DCHECK(url_request_.get());
|
||||
|
||||
NotifyUploadProgressIfNecessary();
|
||||
|
||||
download_data_received_ += current;
|
||||
client_->OnDownloadProgress(url_request_.get(), download_data_received_,
|
||||
download_data_total_);
|
||||
}
|
||||
|
||||
void OnDownloadData(const char* data, int dataLength) {
|
||||
DCHECK(CalledOnValidThread());
|
||||
DCHECK(url_request_.get());
|
||||
client_->OnDownloadData(url_request_.get(), data, dataLength);
|
||||
}
|
||||
|
||||
void OnUploadProgress(int64 current, int64 total) {
|
||||
DCHECK(CalledOnValidThread());
|
||||
DCHECK(url_request_.get());
|
||||
if (current == total)
|
||||
got_upload_progress_complete_ = true;
|
||||
client_->OnUploadProgress(url_request_.get(), current, total);
|
||||
}
|
||||
|
||||
CefRefPtr<CefRequest> request() { return request_; }
|
||||
CefRefPtr<CefURLRequestClient> client() { return client_; }
|
||||
CefURLRequest::Status status() { return status_; }
|
||||
CefURLRequest::ErrorCode error_code() { return error_code_; }
|
||||
CefRefPtr<CefResponse> response() { return response_; }
|
||||
|
||||
private:
|
||||
void NotifyUploadProgressIfNecessary() {
|
||||
if (!got_upload_progress_complete_ && upload_data_size_ > 0) {
|
||||
// URLFetcher sends upload notifications using a timer and will not send
|
||||
// a notification if the request completes too quickly. We therefore
|
||||
// send the notification here if necessary.
|
||||
client_->OnUploadProgress(url_request_.get(), upload_data_size_,
|
||||
upload_data_size_);
|
||||
got_upload_progress_complete_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Members only accessed on the initialization thread.
|
||||
CefRefPtr<CefRenderURLRequest> url_request_;
|
||||
CefRefPtr<CefRequest> request_;
|
||||
CefRefPtr<CefURLRequestClient> client_;
|
||||
scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
|
||||
CefURLRequest::Status status_;
|
||||
CefURLRequest::ErrorCode error_code_;
|
||||
CefRefPtr<CefResponse> response_;
|
||||
scoped_ptr<WebKit::WebURLLoader> loader_;
|
||||
scoped_ptr<CefWebURLLoaderClient> url_client_;
|
||||
int64 upload_data_size_;
|
||||
bool got_upload_progress_complete_;
|
||||
int64 download_data_received_;
|
||||
int64 download_data_total_;
|
||||
};
|
||||
|
||||
|
||||
// CefWebURLLoaderClient --------------------------------------------------
|
||||
|
||||
namespace {
|
||||
|
||||
CefWebURLLoaderClient::CefWebURLLoaderClient(
|
||||
CefRenderURLRequest::Context* context,
|
||||
int request_flags)
|
||||
: context_(context),
|
||||
request_flags_(request_flags) {
|
||||
}
|
||||
|
||||
CefWebURLLoaderClient::~CefWebURLLoaderClient() {
|
||||
}
|
||||
|
||||
void CefWebURLLoaderClient::willSendRequest(
|
||||
WebURLLoader* loader,
|
||||
WebURLRequest& newRequest,
|
||||
const WebURLResponse& redirectResponse) {
|
||||
}
|
||||
|
||||
void CefWebURLLoaderClient::didSendData(
|
||||
WebURLLoader* loader,
|
||||
unsigned long long bytesSent,
|
||||
unsigned long long totalBytesToBeSent) {
|
||||
if (request_flags_ & UR_FLAG_REPORT_UPLOAD_PROGRESS)
|
||||
context_->OnUploadProgress(bytesSent, totalBytesToBeSent);
|
||||
}
|
||||
|
||||
void CefWebURLLoaderClient::didReceiveResponse(
|
||||
WebURLLoader* loader,
|
||||
const WebURLResponse& response) {
|
||||
context_->OnResponse(response);
|
||||
}
|
||||
|
||||
void CefWebURLLoaderClient::didDownloadData(WebURLLoader* loader,
|
||||
int dataLength) {
|
||||
}
|
||||
|
||||
void CefWebURLLoaderClient::didReceiveData(WebURLLoader* loader,
|
||||
const char* data,
|
||||
int dataLength,
|
||||
int encodedDataLength) {
|
||||
context_->OnDownloadProgress(dataLength);
|
||||
|
||||
if (!(request_flags_ & UR_FLAG_NO_DOWNLOAD_DATA))
|
||||
context_->OnDownloadData(data, dataLength);
|
||||
}
|
||||
|
||||
void CefWebURLLoaderClient::didReceiveCachedMetadata(WebURLLoader* loader,
|
||||
const char* data,
|
||||
int dataLength) {
|
||||
}
|
||||
|
||||
void CefWebURLLoaderClient::didFinishLoading(WebURLLoader* loader,
|
||||
double finishTime) {
|
||||
context_->OnComplete();
|
||||
}
|
||||
|
||||
void CefWebURLLoaderClient::didFail(WebURLLoader* loader,
|
||||
const WebURLError& error) {
|
||||
context_->OnError(error);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// CefRenderURLRequest --------------------------------------------------------
|
||||
|
||||
CefRenderURLRequest::CefRenderURLRequest(
|
||||
CefRefPtr<CefRequest> request,
|
||||
CefRefPtr<CefURLRequestClient> client) {
|
||||
context_ = new Context(this, request, client);
|
||||
}
|
||||
|
||||
CefRenderURLRequest::~CefRenderURLRequest() {
|
||||
}
|
||||
|
||||
bool CefRenderURLRequest::Start() {
|
||||
if (!VerifyContext())
|
||||
return false;
|
||||
return context_->Start();
|
||||
}
|
||||
|
||||
CefRefPtr<CefRequest> CefRenderURLRequest::GetRequest() {
|
||||
if (!VerifyContext())
|
||||
return NULL;
|
||||
return context_->request();
|
||||
}
|
||||
|
||||
CefRefPtr<CefURLRequestClient> CefRenderURLRequest::GetClient() {
|
||||
if (!VerifyContext())
|
||||
return NULL;
|
||||
return context_->client();
|
||||
}
|
||||
|
||||
CefURLRequest::Status CefRenderURLRequest::GetRequestStatus() {
|
||||
if (!VerifyContext())
|
||||
return UR_UNKNOWN;
|
||||
return context_->status();
|
||||
}
|
||||
|
||||
CefURLRequest::ErrorCode CefRenderURLRequest::GetRequestError() {
|
||||
if (!VerifyContext())
|
||||
return ERR_NONE;
|
||||
return context_->error_code();
|
||||
}
|
||||
|
||||
CefRefPtr<CefResponse> CefRenderURLRequest::GetResponse() {
|
||||
if (!VerifyContext())
|
||||
return NULL;
|
||||
return context_->response();
|
||||
}
|
||||
|
||||
void CefRenderURLRequest::Cancel() {
|
||||
if (!VerifyContext())
|
||||
return;
|
||||
return context_->Cancel();
|
||||
}
|
||||
|
||||
bool CefRenderURLRequest::VerifyContext() {
|
||||
DCHECK(context_.get());
|
||||
if (!context_->CalledOnValidThread()) {
|
||||
NOTREACHED() << "called on invalid thread";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
Reference in New Issue
Block a user