Home | History | Annotate | Download | only in autofill
      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