1 /* 2 * Copyright 2010, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 #ifndef URL_FETCHER_PROXY_H_ 26 #define URL_FETCHER_PROXY_H_ 27 28 #include "android/autofill/android_url_request_context_getter.h" 29 #include "android/autofill/profile_android.h" 30 #include "base/scoped_ptr.h" 31 #include "base/threading/thread.h" 32 #include "common/net/url_fetcher.h" 33 #include "net/url_request/url_request_status.h" 34 35 class URLFetcherProxy; 36 37 // The URLFetcherProxy uses RunnableMethod to call functions on it in 38 // another thread, but (since it's trying to behave like a URLFetcher) 39 // isn't reference counted. This specialisation makes RunnableMethod 40 // work with a non-reference-counted object by not manipulating the 41 // reference counts. 42 // TODO: Investigate alternatives to using RunnableMethod that don't 43 // expect a ref counted object so we can remove this if possible. 44 template <> 45 struct RunnableMethodTraits<class URLFetcherProxy> { 46 void RetainCallee(URLFetcherProxy* obj) { 47 } 48 49 void ReleaseCallee(URLFetcherProxy* obj) { 50 } 51 }; 52 53 // A class that implements the same API as URLFetcher but instead of 54 // assuming that the calling thread is a chrome thread with a message 55 // loop, it assumes the calling thread is WebKit's main thread. 56 // 57 // It extends URLFetcher so as to minimise the diff in other code when 58 // using this class in place of URLFetcher. It uses a private 59 // URLFetcher instance to do the network request and thus implements 60 // URLFetcher::Delegate. We always use 61 // ProfileImplAndroid::GetDefaultRequestContext() as the request 62 // context. 63 // 64 // Note that we overide the minimum number of methods to allow this 65 // class to be used by AutoFillDownloadManager ... 66 // - set_upload_data() 67 // - set_automatically_retry_on_5xx() 68 // - Start() 69 class URLFetcherProxy : public URLFetcher, public URLFetcher::Delegate { 70 public: 71 URLFetcherProxy(const GURL& url, 72 URLFetcher::RequestType request_type, 73 URLFetcher::Delegate* d) 74 : URLFetcher(url /*unused*/, URLFetcher::POST /*unused*/, d), 75 request_type_(request_type), 76 retry_(true), 77 url_(url) 78 { 79 } 80 81 virtual ~URLFetcherProxy() 82 { 83 pending_callbacks_.erase(this); 84 } 85 86 virtual void set_automatically_retry_on_5xx(bool retry) 87 { 88 retry_ = retry; 89 } 90 91 virtual void set_upload_data(const std::string& upload_content_type, 92 const std::string& upload_content) 93 { 94 upload_content_type_ = upload_content_type; 95 upload_content_ = upload_content; 96 } 97 98 virtual void Start() 99 { 100 scoped_refptr<net::URLRequestContextGetter> con = request_context(); 101 CHECK(con.get()) << "No URLRequestContextGetter!"; 102 scoped_refptr<base::MessageLoopProxy> mlp = con->GetIOMessageLoopProxy(); 103 // TODO: See the template specialisation at the top of the file. Can we use 104 // an alternative to RunnableMethod that doesn't expect a ref counted object? 105 mlp->PostTask(FROM_HERE, NewRunnableMethod(this, &URLFetcherProxy::DoStart)); 106 }; 107 108 virtual void OnURLFetchComplete(const URLFetcher* source, 109 const GURL& url, 110 const net::URLRequestStatus& status, 111 int response_code, 112 const ResponseCookies& cookies, 113 const std::string& data) 114 { 115 url_ = url; 116 status_ = status; 117 response_code_ = response_code; 118 cookies_ = cookies; 119 data_ = data; 120 pending_callbacks_[this] = true; 121 DoComplete(this); 122 } 123 124 net::HttpResponseHeaders* response_headers() const {return real_fetcher_->response_headers();}; 125 126 // Returns the back-off delay before the request will be retried, 127 // when a 5xx response was received. 128 base::TimeDelta backoff_delay() const { return real_fetcher_->backoff_delay();}; 129 130 private: 131 void DoStart() 132 { 133 real_fetcher_.reset(new URLFetcher(url_, request_type_, this)); 134 real_fetcher_->set_automatically_retry_on_5xx(retry_); 135 // We expect set_upload_data() to have been called on this object. 136 real_fetcher_->set_upload_data(upload_content_type_, upload_content_); 137 real_fetcher_->set_request_context(request_context()); 138 real_fetcher_->Start(); 139 }; 140 141 static void DoComplete(void* context) 142 { 143 URLFetcherProxy* that = static_cast<URLFetcherProxy*>(context); 144 if (pending_callbacks_[that]) { 145 that->DoCompleteImpl(); 146 } 147 } 148 149 void DoCompleteImpl() 150 { 151 delegate()->OnURLFetchComplete(this, url_, status_, response_code_, cookies_, data_); 152 } 153 154 scoped_ptr<URLFetcher> real_fetcher_; 155 URLFetcher::RequestType request_type_; 156 157 bool retry_; 158 std::string upload_content_type_; 159 std::string upload_content_; 160 161 GURL url_; 162 net::URLRequestStatus status_; 163 int response_code_; 164 ResponseCookies cookies_; 165 std::string data_; 166 167 static std::map<URLFetcherProxy*, bool> pending_callbacks_; 168 169 DISALLOW_EVIL_CONSTRUCTORS(URLFetcherProxy); 170 }; 171 172 #endif // URL_FETCHER_PROXY_H_ 173