329 lines
8.7 KiB
C++
329 lines
8.7 KiB
C++
// Copyright (c) 2011 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 "include/cef.h"
|
|
#include "web_urlrequest_impl.h"
|
|
#include "browser_webkit_init.h"
|
|
#include "cef_thread.h"
|
|
#include "request_impl.h"
|
|
#include "response_impl.h"
|
|
|
|
#include "base/logging.h"
|
|
#include "base/memory/scoped_ptr.h"
|
|
#include "googleurl/src/gurl.h"
|
|
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLError.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"
|
|
#include "webkit/glue/weburlloader_impl.h"
|
|
|
|
using WebKit::WebURLError;
|
|
using WebKit::WebURLLoader;
|
|
using WebKit::WebURLRequest;
|
|
using WebKit::WebURLResponse;
|
|
|
|
namespace {
|
|
class CefWebURLLoaderClientImpl;
|
|
};
|
|
|
|
// Manages the lifespan of WebKit objects. Methods of this class will only be
|
|
// called on the UI thread.
|
|
class CefWebURLRequestImpl::Context :
|
|
public base::RefCountedThreadSafe<CefWebURLRequestImpl::Context,
|
|
CefThread::DeleteOnUIThread>
|
|
{
|
|
public:
|
|
Context(CefRefPtr<CefWebURLRequestImpl> client)
|
|
: client_(client)
|
|
{
|
|
}
|
|
virtual ~Context()
|
|
{
|
|
}
|
|
|
|
void initialize(CefRefPtr<CefRequest> request);
|
|
void destroy();
|
|
void cancel();
|
|
|
|
CefRefPtr<CefWebURLRequestImpl> client() { return client_; }
|
|
|
|
protected:
|
|
CefRefPtr<CefWebURLRequestImpl> client_;
|
|
scoped_ptr<webkit_glue::WebURLLoaderImpl> url_loader_;
|
|
scoped_ptr<CefWebURLLoaderClientImpl> url_client_;
|
|
};
|
|
|
|
|
|
namespace {
|
|
|
|
// Implements the WebURLLoaderClient interface. Methods of this class will only
|
|
// be called on the UI thread.
|
|
class CefWebURLLoaderClientImpl : public WebKit::WebURLLoaderClient
|
|
{
|
|
public:
|
|
CefWebURLLoaderClientImpl(CefWebURLRequestImpl::Context* context)
|
|
: context_(context)
|
|
{
|
|
}
|
|
virtual ~CefWebURLLoaderClientImpl()
|
|
{
|
|
}
|
|
|
|
// =====================================================================
|
|
// WebKit::WebURLLoaderClient API
|
|
//
|
|
|
|
// Called when following a redirect. |newRequest| contains the request
|
|
// generated by the redirect. The client may modify |newRequest|.
|
|
virtual void willSendRequest(WebKit::WebURLLoader*,
|
|
WebKit::WebURLRequest& newRequest,
|
|
const WebKit::WebURLResponse& redirectResponse)
|
|
{
|
|
REQUIRE_UIT();
|
|
if(!context_)
|
|
return;
|
|
|
|
CefRefPtr<CefWebURLRequestImpl> client = context_->client();
|
|
if (client.get()) {
|
|
CefRefPtr<CefWebURLRequestClient> handler = client->GetHandler();
|
|
if (handler.get()) {
|
|
CefRefPtr<CefRequestImpl> cefRequest(new CefRequestImpl());
|
|
CefRefPtr<CefResponse> cefResponse(
|
|
new CefResponseImpl(redirectResponse));
|
|
|
|
cefRequest->Set(newRequest);
|
|
handler->OnRedirect(client.get(), cefRequest.get(), cefResponse);
|
|
cefRequest->Get(newRequest);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Called to report upload progress. The bytes reported correspond to
|
|
// the HTTP message body.
|
|
virtual void didSendData(WebKit::WebURLLoader*, unsigned long long bytesSent,
|
|
unsigned long long totalBytesToBeSent)
|
|
{
|
|
REQUIRE_UIT();
|
|
if(!context_)
|
|
return;
|
|
|
|
CefRefPtr<CefWebURLRequestImpl> client = context_->client();
|
|
if (client.get()) {
|
|
CefRefPtr<CefWebURLRequestClient> handler = client->GetHandler();
|
|
if (handler.get())
|
|
handler->OnProgress(client.get(), bytesSent, totalBytesToBeSent);
|
|
}
|
|
}
|
|
|
|
// Called when response headers are received.
|
|
virtual void didReceiveResponse(WebKit::WebURLLoader*,
|
|
const WebKit::WebURLResponse& response)
|
|
{
|
|
REQUIRE_UIT();
|
|
if(!context_)
|
|
return;
|
|
|
|
CefRefPtr<CefWebURLRequestImpl> client = context_->client();
|
|
if (client.get()) {
|
|
client->DoStateChange(WUR_STATE_HEADERS_RECEIVED);
|
|
CefRefPtr<CefWebURLRequestClient> handler = client->GetHandler();
|
|
if (handler.get()) {
|
|
CefRefPtr<CefResponse> cefResponse(new CefResponseImpl(response));
|
|
handler->OnHeadersReceived(client.get(), cefResponse);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Called when a chunk of response data is downloaded. This is only called
|
|
// if WebURLRequest's downloadToFile flag was set to true.
|
|
virtual void didDownloadData(WebKit::WebURLLoader*, int dataLength)
|
|
{
|
|
NOTREACHED();
|
|
}
|
|
|
|
// Called when a chunk of response data is received.
|
|
virtual void didReceiveData(WebURLLoader*, const char* data, int dataLength,
|
|
int lengthReceived)
|
|
{
|
|
REQUIRE_UIT();
|
|
if(!context_)
|
|
return;
|
|
|
|
CefRefPtr<CefWebURLRequestImpl> client = context_->client();
|
|
if (client.get()) {
|
|
client->DoStateChange(WUR_STATE_LOADING);
|
|
CefRefPtr<CefWebURLRequestClient> handler = client->GetHandler();
|
|
if (handler.get()) {
|
|
handler->OnData(client.get(), data, dataLength);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Called when a chunk of renderer-generated metadata is received from
|
|
// the cache.
|
|
virtual void didReceiveCachedMetadata(WebKit::WebURLLoader*, const char* data,
|
|
int dataLength)
|
|
{
|
|
NOTREACHED();
|
|
}
|
|
|
|
// Called when the load completes successfully.
|
|
virtual void didFinishLoading(WebKit::WebURLLoader*, double finishTime)
|
|
{
|
|
REQUIRE_UIT();
|
|
if(!context_)
|
|
return;
|
|
|
|
CefRefPtr<CefWebURLRequestImpl> client = context_->client();
|
|
if (client.get())
|
|
client->DoStateChange(WUR_STATE_DONE);
|
|
|
|
complete();
|
|
}
|
|
|
|
// Called when the load completes with an error.
|
|
virtual void didFail(WebKit::WebURLLoader*, const WebKit::WebURLError& error)
|
|
{
|
|
REQUIRE_UIT();
|
|
if(!context_)
|
|
return;
|
|
|
|
CefRefPtr<CefWebURLRequestImpl> client = context_->client();
|
|
if (client.get() && client->GetState() != WUR_STATE_ABORT) {
|
|
client->DoStateChange(WUR_STATE_ERROR);
|
|
CefRefPtr<CefWebURLRequestClient> handler = client->GetHandler();
|
|
if (handler.get()) {
|
|
handler->OnError(client.get(),
|
|
static_cast<CefWebURLRequestClient::ErrorCode>(error.reason));
|
|
}
|
|
}
|
|
|
|
complete();
|
|
}
|
|
|
|
void complete()
|
|
{
|
|
context_->destroy();
|
|
context_ = NULL;
|
|
}
|
|
|
|
protected:
|
|
scoped_refptr<CefWebURLRequestImpl::Context> context_;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
|
|
// CefWebURLManager
|
|
|
|
void CefWebURLRequestImpl::Context::initialize(
|
|
CefRefPtr<CefRequest> request)
|
|
{
|
|
REQUIRE_UIT();
|
|
|
|
url_loader_.reset(
|
|
new webkit_glue::WebURLLoaderImpl(reinterpret_cast<BrowserWebKitInit*>(
|
|
WebKit::webKitPlatformSupport())));
|
|
url_client_.reset(new CefWebURLLoaderClientImpl(this));
|
|
|
|
WebURLRequest urlRequest;
|
|
static_cast<CefRequestImpl*>(request.get())->Get(urlRequest);
|
|
url_loader_->loadAsynchronously(urlRequest, url_client_.get());
|
|
}
|
|
|
|
void CefWebURLRequestImpl::Context::destroy()
|
|
{
|
|
REQUIRE_UIT();
|
|
client_ = NULL;
|
|
}
|
|
|
|
void CefWebURLRequestImpl::Context::cancel()
|
|
{
|
|
REQUIRE_UIT();
|
|
url_loader_->cancel();
|
|
url_client_->complete();
|
|
}
|
|
|
|
|
|
// CefWebURLRequest
|
|
|
|
// static
|
|
CefRefPtr<CefWebURLRequest>
|
|
CefWebURLRequest::CreateWebURLRequest(
|
|
CefRefPtr<CefRequest> request, CefRefPtr<CefWebURLRequestClient> client)
|
|
{
|
|
CefRefPtr<CefWebURLRequestImpl> requester = new CefWebURLRequestImpl(client);
|
|
|
|
// Send the request from the UI thread.
|
|
CefThread::PostTask(CefThread::UI, FROM_HERE,
|
|
NewRunnableMethod(requester.get(), &CefWebURLRequestImpl::DoSend,
|
|
request));
|
|
|
|
return requester.get();
|
|
}
|
|
|
|
|
|
// CefWebURLRequestImpl
|
|
|
|
CefWebURLRequestImpl::CefWebURLRequestImpl(
|
|
CefRefPtr<CefWebURLRequestClient> handler)
|
|
: handler_(handler),
|
|
state_(WUR_STATE_UNSENT)
|
|
{
|
|
}
|
|
|
|
CefWebURLRequestImpl::~CefWebURLRequestImpl()
|
|
{
|
|
}
|
|
|
|
CefWebURLRequestImpl::RequestState CefWebURLRequestImpl::GetState()
|
|
{
|
|
AutoLock lock_scope(this);
|
|
return state_;
|
|
}
|
|
|
|
void CefWebURLRequestImpl::Cancel()
|
|
{
|
|
CefThread::PostTask(CefThread::UI, FROM_HERE,
|
|
NewRunnableMethod(this, &CefWebURLRequestImpl::DoCancel));
|
|
}
|
|
|
|
void CefWebURLRequestImpl::DoSend(CefRefPtr<CefRequest> request)
|
|
{
|
|
REQUIRE_UIT();
|
|
DCHECK(state_ == WUR_STATE_UNSENT);
|
|
|
|
context_ = new CefWebURLRequestImpl::Context(this);
|
|
context_->initialize(request);
|
|
|
|
DoStateChange(WUR_STATE_STARTED);
|
|
}
|
|
|
|
void CefWebURLRequestImpl::DoCancel()
|
|
{
|
|
REQUIRE_UIT();
|
|
|
|
if (state_ < WUR_STATE_DONE) {
|
|
DoStateChange(WUR_STATE_ABORT);
|
|
context_->cancel();
|
|
}
|
|
}
|
|
|
|
void CefWebURLRequestImpl::DoStateChange(RequestState newState)
|
|
{
|
|
REQUIRE_UIT();
|
|
|
|
if (state_ == newState)
|
|
return;
|
|
|
|
{
|
|
AutoLock lock_scope(this);
|
|
state_ = newState;
|
|
}
|
|
|
|
if (handler_.get())
|
|
handler_->OnStateChange(this, newState);
|
|
}
|