• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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