summaryrefslogtreecommitdiffstats
path: root/webkit/support/simple_resource_loader_bridge.cc
diff options
context:
space:
mode:
authorjamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-30 22:35:53 +0000
committerjamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-30 22:35:53 +0000
commit6aaecfde3c347086a6085da169d57b0303c3ccd6 (patch)
tree2ca96e9381018da170c7deb118193eda874046c3 /webkit/support/simple_resource_loader_bridge.cc
parente522cf7889669bfd5153a2d32ac47246bcee2883 (diff)
downloadchromium_src-6aaecfde3c347086a6085da169d57b0303c3ccd6.zip
chromium_src-6aaecfde3c347086a6085da169d57b0303c3ccd6.tar.gz
chromium_src-6aaecfde3c347086a6085da169d57b0303c3ccd6.tar.bz2
Revert "Move C++ code from webkit/tools/test_shell to webkit/support"
This reverts commit e522cf7889669bfd5153a2d32ac47246bcee2883. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203243 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/support/simple_resource_loader_bridge.cc')
-rw-r--r--webkit/support/simple_resource_loader_bridge.cc1168
1 files changed, 0 insertions, 1168 deletions
diff --git a/webkit/support/simple_resource_loader_bridge.cc b/webkit/support/simple_resource_loader_bridge.cc
deleted file mode 100644
index b43c094..0000000
--- a/webkit/support/simple_resource_loader_bridge.cc
+++ /dev/null
@@ -1,1168 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// This file contains an implementation of the ResourceLoaderBridge class.
-// The class is implemented using net::URLRequest, meaning it is a "simple"
-// version that directly issues requests. The more complicated one used in the
-// browser uses IPC.
-//
-// Because net::URLRequest only provides an asynchronous resource loading API,
-// this file makes use of net::URLRequest from a background IO thread. Requests
-// for cookies and synchronously loaded resources result in the main thread of
-// the application blocking until the IO thread completes the operation. (See
-// GetCookies and SyncLoad)
-//
-// Main thread IO thread
-// ----------- ---------
-// ResourceLoaderBridge <---o---------> RequestProxy (normal case)
-// \ -> net::URLRequest
-// o-------> SyncRequestProxy (synchronous case)
-// -> net::URLRequest
-// SetCookie <------------------------> CookieSetter
-// -> net_util::SetCookie
-// GetCookies <-----------------------> CookieGetter
-// -> net_util::GetCookies
-//
-// NOTE: The implementation in this file may be used to have WebKit fetch
-// resources in-process. For example, it is handy for building a single-
-// process WebKit embedding (e.g., test_shell) that can use net::URLRequest to
-// perform URL loads. See renderer/resource_dispatcher.h for details on an
-// alternate implementation that defers fetching to another process.
-
-#include "webkit/support/simple_resource_loader_bridge.h"
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop.h"
-#include "base/message_loop_proxy.h"
-#include "base/string_util.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "base/time.h"
-#include "base/timer.h"
-#include "net/base/file_stream.h"
-#include "net/base/io_buffer.h"
-#include "net/base/load_flags.h"
-#include "net/base/mime_util.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "net/base/network_delegate.h"
-#include "net/base/static_cookie_policy.h"
-#include "net/base/upload_data_stream.h"
-#include "net/cookies/cookie_store.h"
-#include "net/http/http_cache.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_response_headers.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_job.h"
-#include "webkit/appcache/appcache_interfaces.h"
-#include "webkit/browser/blob/blob_storage_controller.h"
-#include "webkit/browser/blob/blob_url_request_job.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_dir_url_request_job.h"
-#include "webkit/browser/fileapi/file_system_url_request_job.h"
-#include "webkit/common/blob/shareable_file_reference.h"
-#include "webkit/glue/resource_loader_bridge.h"
-#include "webkit/glue/resource_request_body.h"
-#include "webkit/glue/webkit_glue.h"
-#include "webkit/support/simple_appcache_system.h"
-#include "webkit/support/simple_file_system.h"
-#include "webkit/support/simple_file_writer.h"
-#include "webkit/support/simple_socket_stream_bridge.h"
-#include "webkit/support/test_shell_request_context.h"
-#include "webkit/support/test_shell_webblobregistry_impl.h"
-
-#if defined(OS_MACOSX) || defined(OS_WIN)
-#include "crypto/nss_util.h"
-#endif
-
-using webkit_glue::ResourceLoaderBridge;
-using webkit_glue::ResourceRequestBody;
-using webkit_glue::ResourceResponseInfo;
-using net::StaticCookiePolicy;
-using net::HttpResponseHeaders;
-using webkit_blob::ShareableFileReference;
-
-namespace {
-
-struct TestShellRequestContextParams {
- TestShellRequestContextParams(
- const base::FilePath& in_cache_path,
- net::HttpCache::Mode in_cache_mode,
- bool in_no_proxy)
- : cache_path(in_cache_path),
- cache_mode(in_cache_mode),
- no_proxy(in_no_proxy) {}
-
- base::FilePath cache_path;
- net::HttpCache::Mode cache_mode;
- bool no_proxy;
-};
-
-//-----------------------------------------------------------------------------
-
-bool g_accept_all_cookies = false;
-
-class TestShellNetworkDelegate : public net::NetworkDelegate {
- public:
- virtual ~TestShellNetworkDelegate() {}
-
- protected:
- // net::NetworkDelegate implementation.
- virtual int OnBeforeURLRequest(net::URLRequest* request,
- const net::CompletionCallback& callback,
- GURL* new_url) OVERRIDE {
- return net::OK;
- }
- virtual int OnBeforeSendHeaders(net::URLRequest* request,
- const net::CompletionCallback& callback,
- net::HttpRequestHeaders* headers) OVERRIDE {
- return net::OK;
- }
- virtual void OnSendHeaders(net::URLRequest* request,
- const net::HttpRequestHeaders& headers) OVERRIDE {}
- virtual int OnHeadersReceived(
- net::URLRequest* request,
- const net::CompletionCallback& callback,
- const net::HttpResponseHeaders* original_response_headers,
- scoped_refptr<net::HttpResponseHeaders>*
- override_response_headers) OVERRIDE {
- return net::OK;
- }
- virtual void OnBeforeRedirect(net::URLRequest* request,
- const GURL& new_location) OVERRIDE {}
- virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {}
- virtual void OnRawBytesRead(const net::URLRequest& request,
- int bytes_read) OVERRIDE {}
- virtual void OnCompleted(net::URLRequest* request, bool started) OVERRIDE {}
- virtual void OnURLRequestDestroyed(net::URLRequest* request) OVERRIDE {}
-
- virtual void OnPACScriptError(int line_number,
- const base::string16& error) OVERRIDE {
- }
- virtual AuthRequiredResponse OnAuthRequired(
- net::URLRequest* request,
- const net::AuthChallengeInfo& auth_info,
- const AuthCallback& callback,
- net::AuthCredentials* credentials) OVERRIDE {
- return AUTH_REQUIRED_RESPONSE_NO_ACTION;
- }
- virtual bool OnCanGetCookies(const net::URLRequest& request,
- const net::CookieList& cookie_list) OVERRIDE {
- StaticCookiePolicy::Type policy_type = g_accept_all_cookies ?
- StaticCookiePolicy::ALLOW_ALL_COOKIES :
- StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES;
-
- StaticCookiePolicy policy(policy_type);
- int rv = policy.CanGetCookies(
- request.url(), request.first_party_for_cookies());
- return rv == net::OK;
- }
- virtual bool OnCanSetCookie(const net::URLRequest& request,
- const std::string& cookie_line,
- net::CookieOptions* options) OVERRIDE {
- StaticCookiePolicy::Type policy_type = g_accept_all_cookies ?
- StaticCookiePolicy::ALLOW_ALL_COOKIES :
- StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES;
-
- StaticCookiePolicy policy(policy_type);
- int rv = policy.CanSetCookie(
- request.url(), request.first_party_for_cookies());
- return rv == net::OK;
- }
- virtual bool OnCanAccessFile(const net::URLRequest& request,
- const base::FilePath& path) const OVERRIDE {
- return true;
- }
- virtual bool OnCanThrottleRequest(
- const net::URLRequest& request) const OVERRIDE {
- return false;
- }
-
- virtual int OnBeforeSocketStreamConnect(
- net::SocketStream* stream,
- const net::CompletionCallback& callback) OVERRIDE {
- return net::OK;
- }
-
- virtual void OnRequestWaitStateChange(const net::URLRequest& request,
- RequestWaitState state) OVERRIDE {
- }
-};
-
-TestShellRequestContextParams* g_request_context_params = NULL;
-TestShellRequestContext* g_request_context = NULL;
-TestShellNetworkDelegate* g_network_delegate = NULL;
-base::Thread* g_cache_thread = NULL;
-
-//-----------------------------------------------------------------------------
-
-struct FileOverHTTPParams {
- FileOverHTTPParams(std::string in_file_path_template, GURL in_http_prefix)
- : file_path_template(in_file_path_template),
- http_prefix(in_http_prefix) {}
-
- std::string file_path_template;
- GURL http_prefix;
-};
-
-class FileOverHTTPPathMappings {
- public:
- FileOverHTTPPathMappings() : redirections_() {}
- void AddMapping(std::string file_path_template, GURL http_prefix) {
- redirections_.push_back(FileOverHTTPParams(file_path_template,
- http_prefix));
- }
-
- const FileOverHTTPParams* ParamsForRequest(std::string request,
- std::string::size_type& offset) {
- std::vector<FileOverHTTPParams>::iterator it;
- for (it = redirections_.begin(); it != redirections_.end(); ++it) {
- offset = request.find(it->file_path_template);
- if (offset != std::string::npos)
- return &*it;
- }
- return 0;
- }
-
- const FileOverHTTPParams* ParamsForResponse(std::string response_url) {
- std::vector<FileOverHTTPParams>::iterator it;
- for (it = redirections_.begin(); it != redirections_.end(); ++it) {
- if (response_url.find(it->http_prefix.spec()) == 0)
- return &*it;
- }
- return 0;
- }
-
- private:
- std::vector<FileOverHTTPParams> redirections_;
-};
-
-FileOverHTTPPathMappings* g_file_over_http_mappings = NULL;
-
-//-----------------------------------------------------------------------------
-
-class IOThread : public base::Thread {
- public:
- IOThread() : base::Thread("IOThread") {}
-
- virtual ~IOThread() {
- Stop();
- }
-
- virtual void Init() OVERRIDE {
- if (g_request_context_params) {
- g_request_context = new TestShellRequestContext(
- g_request_context_params->cache_path,
- g_request_context_params->cache_mode,
- g_request_context_params->no_proxy);
- delete g_request_context_params;
- g_request_context_params = NULL;
- } else {
- g_request_context = new TestShellRequestContext();
- }
-
- g_network_delegate = new TestShellNetworkDelegate();
- g_request_context->set_network_delegate(g_network_delegate);
-
- SimpleAppCacheSystem::InitializeOnIOThread(g_request_context);
- SimpleSocketStreamBridge::InitializeOnIOThread(g_request_context);
- SimpleFileWriter::InitializeOnIOThread(g_request_context);
- SimpleFileSystem::InitializeOnIOThread(
- g_request_context->blob_storage_controller());
- TestShellWebBlobRegistryImpl::InitializeOnIOThread(
- g_request_context->blob_storage_controller());
- }
-
- virtual void CleanUp() OVERRIDE {
- // In reverse order of initialization.
- TestShellWebBlobRegistryImpl::Cleanup();
- SimpleFileSystem::CleanupOnIOThread();
- SimpleFileWriter::CleanupOnIOThread();
- SimpleSocketStreamBridge::Cleanup();
- SimpleAppCacheSystem::CleanupOnIOThread();
-
- if (g_request_context) {
- g_request_context->set_network_delegate(NULL);
- delete g_request_context;
- g_request_context = NULL;
- }
-
- if (g_network_delegate) {
- delete g_network_delegate;
- g_network_delegate = NULL;
- }
- }
-};
-
-IOThread* g_io_thread = NULL;
-
-//-----------------------------------------------------------------------------
-
-struct RequestParams {
- std::string method;
- GURL url;
- GURL first_party_for_cookies;
- GURL referrer;
- WebKit::WebReferrerPolicy referrer_policy;
- std::string headers;
- int load_flags;
- ResourceType::Type request_type;
- int appcache_host_id;
- bool download_to_file;
- scoped_refptr<ResourceRequestBody> request_body;
-};
-
-// The interval for calls to RequestProxy::MaybeUpdateUploadProgress
-static const int kUpdateUploadProgressIntervalMsec = 100;
-
-// The RequestProxy does most of its work on the IO thread. The Start and
-// Cancel methods are proxied over to the IO thread, where an net::URLRequest
-// object is instantiated.
-struct DeleteOnIOThread; // See below.
-class RequestProxy
- : public net::URLRequest::Delegate,
- public base::RefCountedThreadSafe<RequestProxy, DeleteOnIOThread> {
- public:
- // Takes ownership of the params.
- RequestProxy()
- : download_to_file_(false),
- buf_(new net::IOBuffer(kDataSize)),
- last_upload_position_(0) {
- }
-
- void DropPeer() {
- peer_ = NULL;
- }
-
- void Start(ResourceLoaderBridge::Peer* peer, RequestParams* params) {
- peer_ = peer;
- owner_loop_ = base::MessageLoop::current();
-
- ConvertRequestParamsForFileOverHTTPIfNeeded(params);
- // proxy over to the io thread
- g_io_thread->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&RequestProxy::AsyncStart, this, params));
- }
-
- void Cancel() {
- // proxy over to the io thread
- g_io_thread->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&RequestProxy::AsyncCancel, this));
- }
-
- protected:
- friend class base::DeleteHelper<RequestProxy>;
- friend class base::RefCountedThreadSafe<RequestProxy>;
- friend struct DeleteOnIOThread;
-
- virtual ~RequestProxy() {
- // Ensure we are deleted on the IO thread because base::Timer requires that.
- // (guaranteed by the Traits class template parameter).
- DCHECK(base::MessageLoop::current() == g_io_thread->message_loop());
- }
-
- // --------------------------------------------------------------------------
- // The following methods are called on the owner's thread in response to
- // various net::URLRequest callbacks. The event hooks, defined below, trigger
- // these methods asynchronously.
-
- void NotifyReceivedRedirect(const GURL& new_url,
- const ResourceResponseInfo& info) {
- bool has_new_first_party_for_cookies = false;
- GURL new_first_party_for_cookies;
- if (peer_ && peer_->OnReceivedRedirect(new_url, info,
- &has_new_first_party_for_cookies,
- &new_first_party_for_cookies)) {
- g_io_thread->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&RequestProxy::AsyncFollowDeferredRedirect, this,
- has_new_first_party_for_cookies,
- new_first_party_for_cookies));
- } else {
- Cancel();
- }
- }
-
- void NotifyReceivedResponse(const ResourceResponseInfo& info) {
- if (peer_)
- peer_->OnReceivedResponse(info);
- }
-
- void NotifyReceivedData(int bytes_read) {
- if (!peer_)
- return;
-
- // Make a local copy of buf_, since AsyncReadData reuses it.
- scoped_ptr<char[]> buf_copy(new char[bytes_read]);
- memcpy(buf_copy.get(), buf_->data(), bytes_read);
-
- // Continue reading more data into buf_
- // Note: Doing this before notifying our peer ensures our load events get
- // dispatched in a manner consistent with DumpRenderTree (and also avoids a
- // race condition). If the order of the next 2 functions were reversed, the
- // peer could generate new requests in reponse to the received data, which
- // when run on the io thread, could race against this function in doing
- // another InvokeLater. See bug 769249.
- g_io_thread->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&RequestProxy::AsyncReadData, this));
-
- peer_->OnReceivedData(buf_copy.get(), bytes_read, -1);
- }
-
- void NotifyDownloadedData(int bytes_read) {
- if (!peer_)
- return;
-
- // Continue reading more data, see the comment in NotifyReceivedData.
- g_io_thread->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&RequestProxy::AsyncReadData, this));
-
- peer_->OnDownloadedData(bytes_read);
- }
-
- void NotifyCompletedRequest(int error_code,
- const std::string& security_info,
- const base::TimeTicks& complete_time) {
- if (peer_) {
- peer_->OnCompletedRequest(error_code, false, security_info,
- complete_time);
- DropPeer(); // ensure no further notifications
- }
- }
-
- void NotifyUploadProgress(uint64 position, uint64 size) {
- if (peer_)
- peer_->OnUploadProgress(position, size);
- }
-
- // --------------------------------------------------------------------------
- // The following methods are called on the io thread. They correspond to
- // actions performed on the owner's thread.
-
- void AsyncStart(RequestParams* params) {
- request_.reset(g_request_context->CreateRequest(params->url, this));
- request_->set_method(params->method);
- request_->set_first_party_for_cookies(params->first_party_for_cookies);
- request_->SetReferrer(params->referrer.spec());
- webkit_glue::ConfigureURLRequestForReferrerPolicy(
- request_.get(), params->referrer_policy);
- net::HttpRequestHeaders headers;
- headers.AddHeadersFromString(params->headers);
- request_->SetExtraRequestHeaders(headers);
- request_->set_load_flags(params->load_flags);
- if (params->request_body) {
- request_->set_upload(make_scoped_ptr(
- params->request_body->ResolveElementsAndCreateUploadDataStream(
- static_cast<TestShellRequestContext*>(g_request_context)->
- blob_storage_controller(),
- static_cast<TestShellRequestContext*>(g_request_context)->
- file_system_context(),
- base::MessageLoopProxy::current())));
- }
- SimpleAppCacheSystem::SetExtraRequestInfo(
- request_.get(), params->appcache_host_id, params->request_type);
-
- download_to_file_ = params->download_to_file;
- if (download_to_file_) {
- base::FilePath path;
- if (file_util::CreateTemporaryFile(&path)) {
- downloaded_file_ = ShareableFileReference::GetOrCreate(
- path, ShareableFileReference::DELETE_ON_FINAL_RELEASE,
- base::MessageLoopProxy::current());
- file_stream_.reset(new net::FileStream(NULL));
- file_stream_->OpenSync(
- path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE);
- }
- }
-
- request_->Start();
-
- if (request_->has_upload() &&
- params->load_flags & net::LOAD_ENABLE_UPLOAD_PROGRESS) {
- upload_progress_timer_.Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(kUpdateUploadProgressIntervalMsec),
- this, &RequestProxy::MaybeUpdateUploadProgress);
- }
-
- delete params;
- }
-
- void AsyncCancel() {
- // This can be null in cases where the request is already done.
- if (!request_)
- return;
-
- request_->Cancel();
- Done();
- }
-
- void AsyncFollowDeferredRedirect(bool has_new_first_party_for_cookies,
- const GURL& new_first_party_for_cookies) {
- // This can be null in cases where the request is already done.
- if (!request_)
- return;
-
- if (has_new_first_party_for_cookies)
- request_->set_first_party_for_cookies(new_first_party_for_cookies);
- request_->FollowDeferredRedirect();
- }
-
- void AsyncReadData() {
- // This can be null in cases where the request is already done.
- if (!request_)
- return;
-
- if (request_->status().is_success()) {
- int bytes_read;
- if (request_->Read(buf_, kDataSize, &bytes_read) && bytes_read) {
- OnReceivedData(bytes_read);
- } else if (!request_->status().is_io_pending()) {
- Done();
- } // else wait for OnReadCompleted
- } else {
- Done();
- }
- }
-
- // --------------------------------------------------------------------------
- // The following methods are event hooks (corresponding to net::URLRequest
- // callbacks) that run on the IO thread. They are designed to be overridden
- // by the SyncRequestProxy subclass.
-
- virtual void OnReceivedRedirect(
- const GURL& new_url,
- const ResourceResponseInfo& info,
- bool* defer_redirect) {
- *defer_redirect = true; // See AsyncFollowDeferredRedirect
- owner_loop_->PostTask(
- FROM_HERE,
- base::Bind(&RequestProxy::NotifyReceivedRedirect, this, new_url, info));
- }
-
- virtual void OnReceivedResponse(
- const ResourceResponseInfo& info) {
- owner_loop_->PostTask(
- FROM_HERE,
- base::Bind(&RequestProxy::NotifyReceivedResponse, this, info));
- }
-
- virtual void OnReceivedData(int bytes_read) {
- if (download_to_file_) {
- file_stream_->WriteSync(buf_->data(), bytes_read);
- owner_loop_->PostTask(
- FROM_HERE,
- base::Bind(&RequestProxy::NotifyDownloadedData, this, bytes_read));
- return;
- }
-
- owner_loop_->PostTask(
- FROM_HERE,
- base::Bind(&RequestProxy::NotifyReceivedData, this, bytes_read));
- }
-
- virtual void OnCompletedRequest(int error_code,
- const std::string& security_info,
- const base::TimeTicks& complete_time) {
- if (download_to_file_)
- file_stream_.reset();
- owner_loop_->PostTask(
- FROM_HERE,
- base::Bind(&RequestProxy::NotifyCompletedRequest, this, error_code,
- security_info, complete_time));
- }
-
- // --------------------------------------------------------------------------
- // net::URLRequest::Delegate implementation:
-
- virtual void OnReceivedRedirect(net::URLRequest* request,
- const GURL& new_url,
- bool* defer_redirect) OVERRIDE {
- DCHECK(request->status().is_success());
- ResourceResponseInfo info;
- PopulateResponseInfo(request, &info);
- // For file protocol, should never have the redirect situation.
- DCHECK(!ConvertResponseInfoForFileOverHTTPIfNeeded(request, &info));
- OnReceivedRedirect(new_url, info, defer_redirect);
- }
-
- virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {
- if (request->status().is_success()) {
- ResourceResponseInfo info;
- PopulateResponseInfo(request, &info);
- // If encountering error when requesting the file, cancel the request.
- if (ConvertResponseInfoForFileOverHTTPIfNeeded(request, &info) &&
- failed_file_request_status_.get()) {
- AsyncCancel();
- } else {
- OnReceivedResponse(info);
- AsyncReadData(); // start reading
- }
- } else {
- Done();
- }
- }
-
- virtual void OnSSLCertificateError(net::URLRequest* request,
- const net::SSLInfo& ssl_info,
- bool fatal) OVERRIDE {
- // Allow all certificate errors.
- request->ContinueDespiteLastError();
- }
-
- virtual void OnReadCompleted(net::URLRequest* request,
- int bytes_read) OVERRIDE {
- if (request->status().is_success() && bytes_read > 0) {
- OnReceivedData(bytes_read);
- } else {
- Done();
- }
- }
-
- // --------------------------------------------------------------------------
- // Helpers and data:
-
- void Done() {
- if (upload_progress_timer_.IsRunning()) {
- MaybeUpdateUploadProgress();
- upload_progress_timer_.Stop();
- }
- DCHECK(request_.get());
- // If |failed_file_request_status_| is not empty, which means the request
- // was a file request and encountered an error, then we need to use the
- // |failed_file_request_status_|. Otherwise use request_'s status.
- OnCompletedRequest(failed_file_request_status_.get() ?
- failed_file_request_status_->error() :
- request_->status().error(),
- std::string(), base::TimeTicks::Now());
- request_.reset(); // destroy on the io thread
- }
-
- // Called on the IO thread.
- void MaybeUpdateUploadProgress() {
- // If a redirect is received upload is cancelled in net::URLRequest, we
- // should try to stop the |upload_progress_timer_| timer and return.
- if (!request_->has_upload()) {
- if (upload_progress_timer_.IsRunning())
- upload_progress_timer_.Stop();
- return;
- }
-
- net::UploadProgress progress = request_->GetUploadProgress();
- if (progress.position() == last_upload_position_)
- return; // no progress made since last time
-
- const uint64 kHalfPercentIncrements = 200;
- const base::TimeDelta kOneSecond = base::TimeDelta::FromMilliseconds(1000);
-
- uint64 amt_since_last = progress.position() - last_upload_position_;
- base::TimeDelta time_since_last = base::TimeTicks::Now() -
- last_upload_ticks_;
-
- bool is_finished = (progress.size() == progress.position());
- bool enough_new_progress = (amt_since_last > (progress.size() /
- kHalfPercentIncrements));
- bool too_much_time_passed = time_since_last > kOneSecond;
-
- if (is_finished || enough_new_progress || too_much_time_passed) {
- owner_loop_->PostTask(
- FROM_HERE,
- base::Bind(&RequestProxy::NotifyUploadProgress, this,
- progress.position(), progress.size()));
- last_upload_ticks_ = base::TimeTicks::Now();
- last_upload_position_ = progress.position();
- }
- }
-
- void PopulateResponseInfo(net::URLRequest* request,
- ResourceResponseInfo* info) const {
- if (request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING)
- request->GetLoadTimingInfo(&info->load_timing);
- info->request_time = request->request_time();
- info->response_time = request->response_time();
- info->headers = request->response_headers();
- request->GetMimeType(&info->mime_type);
- request->GetCharset(&info->charset);
- info->content_length = request->GetExpectedContentSize();
- if (downloaded_file_)
- info->download_file_path = downloaded_file_->path();
- SimpleAppCacheSystem::GetExtraResponseInfo(
- request,
- &info->appcache_id,
- &info->appcache_manifest_url);
- }
-
- // Called on owner thread
- void ConvertRequestParamsForFileOverHTTPIfNeeded(RequestParams* params) {
- // Reset the status.
- file_url_prefix_ .clear();
- failed_file_request_status_.reset();
- // Only do this when enabling file-over-http and request is file scheme.
- if (!g_file_over_http_mappings || !params->url.SchemeIsFile())
- return;
-
- // For file protocol, method must be GET, POST or NULL.
- DCHECK(params->method == "GET" || params->method == "POST" ||
- params->method.empty());
- DCHECK(!params->download_to_file);
-
- if (params->method.empty())
- params->method = "GET";
- std::string original_request = params->url.spec();
-
- std::string::size_type offset = 0;
- const FileOverHTTPParams* redirection_params =
- g_file_over_http_mappings->ParamsForRequest(original_request, offset);
- if (!redirection_params)
- return;
-
- offset += redirection_params->file_path_template.size();
- file_url_prefix_ = original_request.substr(0, offset);
- original_request.replace(0, offset,
- redirection_params->http_prefix.spec());
- params->url = GURL(original_request);
- params->first_party_for_cookies = params->url;
- // For file protocol, nerver use cache.
- params->load_flags = net::LOAD_BYPASS_CACHE;
- }
-
- // Called on IO thread.
- bool ConvertResponseInfoForFileOverHTTPIfNeeded(net::URLRequest* request,
- ResourceResponseInfo* info) {
- // Only do this when enabling file-over-http and request url
- // matches the http prefix for file-over-http feature.
- if (!g_file_over_http_mappings || file_url_prefix_.empty())
- return false;
-
- std::string original_request = request->url().spec();
- DCHECK(!original_request.empty());
-
- const FileOverHTTPParams* redirection_params =
- g_file_over_http_mappings->ParamsForResponse(original_request);
- DCHECK(redirection_params);
-
- std::string http_prefix = redirection_params->http_prefix.spec();
- DCHECK(StartsWithASCII(original_request, http_prefix, true));
-
- // Get the File URL.
- original_request.replace(0, http_prefix.size(), file_url_prefix_);
-
- base::FilePath file_path;
- if (!net::FileURLToFilePath(GURL(original_request), &file_path)) {
- NOTREACHED();
- }
-
- info->mime_type.clear();
- DCHECK(info->headers);
- int status_code = info->headers->response_code();
- // File protocol does not support response headers.
- info->headers = NULL;
- if (200 == status_code) {
- // Don't use the MIME type from HTTP server, use net::GetMimeTypeFromFile
- // instead.
- net::GetMimeTypeFromFile(file_path, &info->mime_type);
- } else {
- // If the file does not exist, immediately call OnCompletedRequest with
- // setting URLRequestStatus to FAILED.
- DCHECK(status_code == 404 || status_code == 403);
- if (status_code == 404) {
- failed_file_request_status_.reset(
- new net::URLRequestStatus(net::URLRequestStatus::FAILED,
- net::ERR_FILE_NOT_FOUND));
- } else {
- failed_file_request_status_.reset(
- new net::URLRequestStatus(net::URLRequestStatus::FAILED,
- net::ERR_ACCESS_DENIED));
- }
- }
- return true;
- }
-
- scoped_ptr<net::URLRequest> request_;
-
- // Support for request.download_to_file behavior.
- bool download_to_file_;
- scoped_ptr<net::FileStream> file_stream_;
- scoped_refptr<ShareableFileReference> downloaded_file_;
-
- // Size of our async IO data buffers
- static const int kDataSize = 16*1024;
-
- // read buffer for async IO
- scoped_refptr<net::IOBuffer> buf_;
-
- base::MessageLoop* owner_loop_;
-
- // This is our peer in WebKit (implemented as ResourceHandleInternal). We do
- // not manage its lifetime, and we may only access it from the owner's
- // message loop (owner_loop_).
- ResourceLoaderBridge::Peer* peer_;
-
- // Timer used to pull upload progress info.
- base::RepeatingTimer<RequestProxy> upload_progress_timer_;
-
- // Info used to determine whether or not to send an upload progress update.
- uint64 last_upload_position_;
- base::TimeTicks last_upload_ticks_;
-
- // Save the real FILE URL prefix for the FILE URL which converts to HTTP URL.
- std::string file_url_prefix_;
- // Save a failed file request status to pass it to webkit.
- scoped_ptr<net::URLRequestStatus> failed_file_request_status_;
-};
-
-// Helper guaranteeing deletion on the IO thread (like
-// content::BrowserThread::DeleteOnIOThread, but without the dependency).
-struct DeleteOnIOThread {
- static void Destruct(const RequestProxy* obj) {
- if (base::MessageLoop::current() == g_io_thread->message_loop())
- delete obj;
- else
- g_io_thread->message_loop()->DeleteSoon(FROM_HERE, obj);
- }
-};
-
-//-----------------------------------------------------------------------------
-
-class SyncRequestProxy : public RequestProxy {
- public:
- explicit SyncRequestProxy(ResourceLoaderBridge::SyncLoadResponse* result)
- : result_(result), event_(true, false) {
- }
-
- void WaitForCompletion() {
- event_.Wait();
- }
-
- // --------------------------------------------------------------------------
- // RequestProxy event hooks that run on the IO thread:
-
- virtual void OnReceivedRedirect(
- const GURL& new_url,
- const ResourceResponseInfo& info,
- bool* defer_redirect) OVERRIDE {
- // TODO(darin): It would be much better if this could live in WebCore, but
- // doing so requires API changes at all levels. Similar code exists in
- // WebCore/platform/network/cf/ResourceHandleCFNet.cpp :-(
- if (new_url.GetOrigin() != result_->url.GetOrigin()) {
- DLOG(WARNING) << "Cross origin redirect denied";
- Cancel();
- return;
- }
- result_->url = new_url;
- }
-
- virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE {
- *static_cast<ResourceResponseInfo*>(result_) = info;
- }
-
- virtual void OnReceivedData(int bytes_read) OVERRIDE {
- if (download_to_file_)
- file_stream_->WriteSync(buf_->data(), bytes_read);
- else
- result_->data.append(buf_->data(), bytes_read);
- AsyncReadData(); // read more (may recurse)
- }
-
- virtual void OnCompletedRequest(
- int error_code,
- const std::string& security_info,
- const base::TimeTicks& complete_time) OVERRIDE {
- if (download_to_file_)
- file_stream_.reset();
- result_->error_code = error_code;
- event_.Signal();
- }
-
- protected:
- virtual ~SyncRequestProxy() {}
-
- private:
- ResourceLoaderBridge::SyncLoadResponse* result_;
- base::WaitableEvent event_;
-};
-
-//-----------------------------------------------------------------------------
-
-class ResourceLoaderBridgeImpl : public ResourceLoaderBridge {
- public:
- ResourceLoaderBridgeImpl(
- const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info)
- : params_(new RequestParams),
- proxy_(NULL) {
- params_->method = request_info.method;
- params_->url = request_info.url;
- params_->first_party_for_cookies = request_info.first_party_for_cookies;
- params_->referrer = request_info.referrer;
- params_->referrer_policy = request_info.referrer_policy;
- params_->headers = request_info.headers;
- params_->load_flags = request_info.load_flags;
- params_->request_type = request_info.request_type;
- params_->appcache_host_id = request_info.appcache_host_id;
- params_->download_to_file = request_info.download_to_file;
- }
-
- virtual ~ResourceLoaderBridgeImpl() {
- if (proxy_) {
- proxy_->DropPeer();
- // Let the proxy die on the IO thread
- g_io_thread->message_loop()->ReleaseSoon(FROM_HERE, proxy_);
- }
- }
-
- // --------------------------------------------------------------------------
- // ResourceLoaderBridge implementation:
-
- virtual void SetRequestBody(ResourceRequestBody* request_body) OVERRIDE {
- DCHECK(params_.get());
- DCHECK(!params_->request_body);
- params_->request_body = request_body;
- }
-
- virtual bool Start(Peer* peer) OVERRIDE {
- DCHECK(!proxy_);
-
- if (!SimpleResourceLoaderBridge::EnsureIOThread())
- return false;
-
- proxy_ = new RequestProxy();
- proxy_->AddRef();
-
- proxy_->Start(peer, params_.release());
-
- return true; // Any errors will be reported asynchronously.
- }
-
- virtual void Cancel() OVERRIDE {
- DCHECK(proxy_);
- proxy_->Cancel();
- }
-
- virtual void SetDefersLoading(bool value) OVERRIDE {
- // TODO(darin): implement me
- }
-
- virtual void SyncLoad(SyncLoadResponse* response) OVERRIDE {
- DCHECK(!proxy_);
-
- if (!SimpleResourceLoaderBridge::EnsureIOThread())
- return;
-
- // this may change as the result of a redirect
- response->url = params_->url;
-
- proxy_ = new SyncRequestProxy(response);
- proxy_->AddRef();
-
- proxy_->Start(NULL, params_.release());
-
- static_cast<SyncRequestProxy*>(proxy_)->WaitForCompletion();
- }
-
- virtual void DidChangePriority(net::RequestPriority new_priority) OVERRIDE {
- // Not really needed for DRT.
- }
-
- private:
- // Ownership of params_ is transfered to the proxy when the proxy is created.
- scoped_ptr<RequestParams> params_;
-
- // The request proxy is allocated when we start the request, and then it
- // sticks around until this ResourceLoaderBridge is destroyed.
- RequestProxy* proxy_;
-};
-
-//-----------------------------------------------------------------------------
-
-class CookieSetter : public base::RefCountedThreadSafe<CookieSetter> {
- public:
- void Set(const GURL& url, const std::string& cookie) {
- DCHECK(base::MessageLoop::current() == g_io_thread->message_loop());
- g_request_context->cookie_store()->SetCookieWithOptionsAsync(
- url, cookie, net::CookieOptions(),
- net::CookieStore::SetCookiesCallback());
- }
-
- private:
- friend class base::RefCountedThreadSafe<CookieSetter>;
- ~CookieSetter() {}
-};
-
-class CookieGetter : public base::RefCountedThreadSafe<CookieGetter> {
- public:
- CookieGetter() : event_(false, false) {
- }
-
- void Get(const GURL& url) {
- g_request_context->cookie_store()->GetCookiesWithOptionsAsync(
- url, net::CookieOptions(),
- base::Bind(&CookieGetter::OnGetCookies, this));
- }
-
- std::string GetResult() {
- event_.Wait();
- return result_;
- }
-
- private:
- friend class base::RefCountedThreadSafe<CookieGetter>;
- ~CookieGetter() {}
-
- void OnGetCookies(const std::string& cookie_line) {
- result_ = cookie_line;
- event_.Signal();
- }
-
- base::WaitableEvent event_;
- std::string result_;
-};
-
-} // anonymous namespace
-
-//-----------------------------------------------------------------------------
-
-// static
-void SimpleResourceLoaderBridge::Init(
- const base::FilePath& cache_path,
- net::HttpCache::Mode cache_mode,
- bool no_proxy) {
- // Make sure to stop any existing IO thread since it may be using the
- // current request context.
- Shutdown();
-
- DCHECK(!g_request_context_params);
- DCHECK(!g_request_context);
- DCHECK(!g_network_delegate);
- DCHECK(!g_io_thread);
-
- g_request_context_params = new TestShellRequestContextParams(
- cache_path, cache_mode, no_proxy);
-}
-
-// static
-void SimpleResourceLoaderBridge::Shutdown() {
- if (g_io_thread) {
- delete g_io_thread;
- g_io_thread = NULL;
-
- DCHECK(g_cache_thread);
- delete g_cache_thread;
- g_cache_thread = NULL;
-
- DCHECK(!g_request_context) << "should have been nulled by thread dtor";
- DCHECK(!g_network_delegate) << "should have been nulled by thread dtor";
- } else {
- delete g_request_context_params;
- g_request_context_params = NULL;
-
- delete g_file_over_http_mappings;
- g_file_over_http_mappings = NULL;
- }
-}
-
-// static
-void SimpleResourceLoaderBridge::SetCookie(const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& cookie) {
- // Proxy to IO thread to synchronize w/ network loading.
-
- if (!EnsureIOThread()) {
- NOTREACHED();
- return;
- }
-
- scoped_refptr<CookieSetter> cookie_setter(new CookieSetter());
- g_io_thread->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&CookieSetter::Set, cookie_setter.get(), url, cookie));
-}
-
-// static
-std::string SimpleResourceLoaderBridge::GetCookies(
- const GURL& url, const GURL& first_party_for_cookies) {
- // Proxy to IO thread to synchronize w/ network loading
-
- if (!EnsureIOThread()) {
- NOTREACHED();
- return std::string();
- }
-
- scoped_refptr<CookieGetter> getter(new CookieGetter());
-
- g_io_thread->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&CookieGetter::Get, getter.get(), url));
-
- return getter->GetResult();
-}
-
-// static
-bool SimpleResourceLoaderBridge::EnsureIOThread() {
- if (g_io_thread)
- return true;
-
-#if defined(OS_MACOSX) || defined(OS_WIN)
- // We want to be sure to init NSPR on the main thread.
- crypto::EnsureNSPRInit();
-#endif
-
- // Create the cache thread. We want the cache thread to outlive the IO thread,
- // so its lifetime is bonded to the IO thread lifetime.
- DCHECK(!g_cache_thread);
- g_cache_thread = new base::Thread("cache");
- CHECK(g_cache_thread->StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
-
- g_io_thread = new IOThread();
- base::Thread::Options options;
- options.message_loop_type = base::MessageLoop::TYPE_IO;
- return g_io_thread->StartWithOptions(options);
-}
-
-// static
-void SimpleResourceLoaderBridge::SetAcceptAllCookies(bool accept_all_cookies) {
- g_accept_all_cookies = accept_all_cookies;
-}
-
-// static
-scoped_refptr<base::MessageLoopProxy>
- SimpleResourceLoaderBridge::GetCacheThread() {
- return g_cache_thread->message_loop_proxy();
-}
-
-// static
-scoped_refptr<base::MessageLoopProxy>
- SimpleResourceLoaderBridge::GetIoThread() {
- if (!EnsureIOThread()) {
- LOG(DFATAL) << "Failed to create IO thread.";
- return NULL;
- }
- return g_io_thread->message_loop_proxy();
-}
-
-// static
-void SimpleResourceLoaderBridge::AllowFileOverHTTP(
- const std::string& file_path_template, const GURL& http_prefix) {
- DCHECK(!file_path_template.empty());
- DCHECK(http_prefix.is_valid() &&
- (http_prefix.SchemeIs("http") || http_prefix.SchemeIs("https")));
- if (!g_file_over_http_mappings)
- g_file_over_http_mappings = new FileOverHTTPPathMappings();
- g_file_over_http_mappings->AddMapping(file_path_template, http_prefix);
-}
-
-// static
-webkit_glue::ResourceLoaderBridge* SimpleResourceLoaderBridge::Create(
- const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info) {
- return new ResourceLoaderBridgeImpl(request_info);
-}