/* * Copyright 2010, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef URL_FETCHER_PROXY_H_ #define URL_FETCHER_PROXY_H_ #include "android/autofill/android_url_request_context_getter.h" #include "android/autofill/profile_android.h" #include "base/scoped_ptr.h" #include "base/threading/thread.h" #include "common/net/url_fetcher.h" #include "net/url_request/url_request_status.h" class URLFetcherProxy; // The URLFetcherProxy uses RunnableMethod to call functions on it in // another thread, but (since it's trying to behave like a URLFetcher) // isn't reference counted. This specialisation makes RunnableMethod // work with a non-reference-counted object by not manipulating the // reference counts. // TODO: Investigate alternatives to using RunnableMethod that don't // expect a ref counted object so we can remove this if possible. template <> struct RunnableMethodTraits { void RetainCallee(URLFetcherProxy* obj) { } void ReleaseCallee(URLFetcherProxy* obj) { } }; // A class that implements the same API as URLFetcher but instead of // assuming that the calling thread is a chrome thread with a message // loop, it assumes the calling thread is WebKit's main thread. // // It extends URLFetcher so as to minimise the diff in other code when // using this class in place of URLFetcher. It uses a private // URLFetcher instance to do the network request and thus implements // URLFetcher::Delegate. We always use // ProfileImplAndroid::GetDefaultRequestContext() as the request // context. // // Note that we overide the minimum number of methods to allow this // class to be used by AutoFillDownloadManager ... // - set_upload_data() // - set_automatically_retry_on_5xx() // - Start() class URLFetcherProxy : public URLFetcher, public URLFetcher::Delegate { public: URLFetcherProxy(const GURL& url, URLFetcher::RequestType request_type, URLFetcher::Delegate* d) : URLFetcher(url /*unused*/, URLFetcher::POST /*unused*/, d), request_type_(request_type), retry_(true), url_(url) { } virtual ~URLFetcherProxy() { pending_callbacks_.erase(this); } virtual void set_automatically_retry_on_5xx(bool retry) { retry_ = retry; } virtual void set_upload_data(const std::string& upload_content_type, const std::string& upload_content) { upload_content_type_ = upload_content_type; upload_content_ = upload_content; } virtual void Start() { scoped_refptr con = request_context(); CHECK(con.get()) << "No URLRequestContextGetter!"; scoped_refptr mlp = con->GetIOMessageLoopProxy(); // TODO: See the template specialisation at the top of the file. Can we use // an alternative to RunnableMethod that doesn't expect a ref counted object? mlp->PostTask(FROM_HERE, NewRunnableMethod(this, &URLFetcherProxy::DoStart)); }; virtual void OnURLFetchComplete(const URLFetcher* source, const GURL& url, const net::URLRequestStatus& status, int response_code, const ResponseCookies& cookies, const std::string& data) { url_ = url; status_ = status; response_code_ = response_code; cookies_ = cookies; data_ = data; pending_callbacks_[this] = true; DoComplete(this); } net::HttpResponseHeaders* response_headers() const {return real_fetcher_->response_headers();}; // Returns the back-off delay before the request will be retried, // when a 5xx response was received. base::TimeDelta backoff_delay() const { return real_fetcher_->backoff_delay();}; private: void DoStart() { real_fetcher_.reset(new URLFetcher(url_, request_type_, this)); real_fetcher_->set_automatically_retry_on_5xx(retry_); // We expect set_upload_data() to have been called on this object. real_fetcher_->set_upload_data(upload_content_type_, upload_content_); real_fetcher_->set_request_context(request_context()); real_fetcher_->Start(); }; static void DoComplete(void* context) { URLFetcherProxy* that = static_cast(context); if (pending_callbacks_[that]) { that->DoCompleteImpl(); } } void DoCompleteImpl() { delegate()->OnURLFetchComplete(this, url_, status_, response_code_, cookies_, data_); } scoped_ptr real_fetcher_; URLFetcher::RequestType request_type_; bool retry_; std::string upload_content_type_; std::string upload_content_; GURL url_; net::URLRequestStatus status_; int response_code_; ResponseCookies cookies_; std::string data_; static std::map pending_callbacks_; DISALLOW_EVIL_CONSTRUCTORS(URLFetcherProxy); }; #endif // URL_FETCHER_PROXY_H_