17d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch/*
27d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * Copyright 2010, The Android Open Source Project
37d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch *
47d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * Redistribution and use in source and binary forms, with or without
57d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * modification, are permitted provided that the following conditions
67d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * are met:
77d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch *  * Redistributions of source code must retain the above copyright
87d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch *    notice, this list of conditions and the following disclaimer.
97d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch *  * Redistributions in binary form must reproduce the above copyright
107d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch *    notice, this list of conditions and the following disclaimer in the
117d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch *    documentation and/or other materials provided with the distribution.
127d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch *
137d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
147d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
157d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
167d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
177d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
187d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
197d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
207d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
217d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
227d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
237d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
247d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch */
257d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch#ifndef URL_FETCHER_PROXY_H_
267d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch#define URL_FETCHER_PROXY_H_
277d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
287d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch#include "android/autofill/android_url_request_context_getter.h"
297d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch#include "android/autofill/profile_android.h"
306662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block#include "base/scoped_ptr.h"
319aa5f8b435409e063e76e6e4f12f5c4e85997e0aKristian Monsen#include "base/threading/thread.h"
327d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch#include "common/net/url_fetcher.h"
337d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch#include "net/url_request/url_request_status.h"
347d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
357d214dfa174224b459660971e5b5cce2e06be02aBen Murdochclass URLFetcherProxy;
367d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
377d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch// The URLFetcherProxy uses RunnableMethod to call functions on it in
387d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch// another thread, but (since it's trying to behave like a URLFetcher)
397d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch// isn't reference counted. This specialisation makes RunnableMethod
407d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch// work with a non-reference-counted object by not manipulating the
417d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch// reference counts.
427d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch// TODO: Investigate alternatives to using RunnableMethod that don't
437d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch// expect a ref counted object so we can remove this if possible.
447d214dfa174224b459660971e5b5cce2e06be02aBen Murdochtemplate <>
457d214dfa174224b459660971e5b5cce2e06be02aBen Murdochstruct RunnableMethodTraits<class URLFetcherProxy> {
467d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  void RetainCallee(URLFetcherProxy* obj) {
477d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  }
487d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
497d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  void ReleaseCallee(URLFetcherProxy* obj) {
507d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  }
517d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch};
527d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
537d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch// A class that implements the same API as URLFetcher but instead of
547d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch// assuming that the calling thread is a chrome thread with a message
556662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block// loop, it assumes the calling thread is WebKit's main thread.
566662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block//
576662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block// It extends URLFetcher so as to minimise the diff in other code when
586662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block// using this class in place of URLFetcher. It uses a private
596662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block// URLFetcher instance to do the network request and thus implements
60851c24f8cc7438c16c50ead815bde972a60b4a18Steve Block// URLFetcher::Delegate. We always use
61851c24f8cc7438c16c50ead815bde972a60b4a18Steve Block// ProfileImplAndroid::GetDefaultRequestContext() as the request
62851c24f8cc7438c16c50ead815bde972a60b4a18Steve Block// context.
636662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block//
646662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block// Note that we overide the minimum number of methods to allow this
656662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block// class to be used by AutoFillDownloadManager ...
666662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block// - set_upload_data()
67dbeb7bfd58939b6a020a91552afd12c32108a7c7Iain Merrick// - set_automatically_retry_on_5xx()
686662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block// - Start()
696662b631f1f14f6db83e053e0dd7887bb18adb91Steve Blockclass URLFetcherProxy : public URLFetcher, public URLFetcher::Delegate {
707d214dfa174224b459660971e5b5cce2e06be02aBen Murdochpublic:
716662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  URLFetcherProxy(const GURL& url,
726662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block                  URLFetcher::RequestType request_type,
736662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block                  URLFetcher::Delegate* d)
746662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block      : URLFetcher(url /*unused*/, URLFetcher::POST /*unused*/, d),
756662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block        request_type_(request_type),
76c5a01be107ec80b0d7062dcc836c0608dd467f17Ben Murdoch        retry_(true),
77c5a01be107ec80b0d7062dcc836c0608dd467f17Ben Murdoch        url_(url)
786662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  {
796662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  }
807d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
816662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  virtual ~URLFetcherProxy()
826662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  {
83164f7496de0fbee436b385a79ead9e3cb81a50c1Ben Murdoch      pending_callbacks_.erase(this);
846662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  }
857d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
86dbeb7bfd58939b6a020a91552afd12c32108a7c7Iain Merrick  virtual void set_automatically_retry_on_5xx(bool retry)
876662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  {
886662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block    retry_ = retry;
896662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  }
907d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
916662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  virtual void set_upload_data(const std::string& upload_content_type,
926662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block                               const std::string& upload_content)
937d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  {
946662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block    upload_content_type_ = upload_content_type;
956662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block    upload_content_ = upload_content;
967d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  }
977d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
986662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  virtual void Start()
996662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  {
1008474bd350e233cca45dcbfe5f8e4f542675c4c66Kristian Monsen    scoped_refptr<net::URLRequestContextGetter> con = request_context();
10140eae52c5e5dbf475a0cf368c9ccbb7f8a0653f4Ben Murdoch    CHECK(con.get()) << "No URLRequestContextGetter!";
1026662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block    scoped_refptr<base::MessageLoopProxy> mlp = con->GetIOMessageLoopProxy();
1036662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block    // TODO: See the template specialisation at the top of the file. Can we use
1046662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block    // an alternative to RunnableMethod that doesn't expect a ref counted object?
1056662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block    mlp->PostTask(FROM_HERE, NewRunnableMethod(this, &URLFetcherProxy::DoStart));
1066662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  };
1076662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block
1087d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  virtual void OnURLFetchComplete(const URLFetcher* source,
1097d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch                                  const GURL& url,
110532b5811cf4c192c4333b19108d6a303edb23691Kristian Monsen                                  const net::URLRequestStatus& status,
1117d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch                                  int response_code,
1127d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch                                  const ResponseCookies& cookies,
1137d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch                                  const std::string& data)
1147d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  {
1157d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch    url_ = url;
1167d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch    status_ = status;
1177d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch    response_code_ = response_code;
1187d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch    cookies_ = cookies;
1197d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch    data_ = data;
120164f7496de0fbee436b385a79ead9e3cb81a50c1Ben Murdoch    pending_callbacks_[this] = true;
121cecae02673edd6b4cee88a9b87a61055a91f70bbKristian Monsen    DoComplete(this);
1227d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  }
1237d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
1247d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  net::HttpResponseHeaders* response_headers() const {return real_fetcher_->response_headers();};
1257d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
1267d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  // Returns the back-off delay before the request will be retried,
1277d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  // when a 5xx response was received.
1287d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  base::TimeDelta backoff_delay() const { return real_fetcher_->backoff_delay();};
1297d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
1307d214dfa174224b459660971e5b5cce2e06be02aBen Murdochprivate:
1317d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  void DoStart()
1327d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  {
133c5a01be107ec80b0d7062dcc836c0608dd467f17Ben Murdoch    real_fetcher_.reset(new URLFetcher(url_, request_type_, this));
134dbeb7bfd58939b6a020a91552afd12c32108a7c7Iain Merrick    real_fetcher_->set_automatically_retry_on_5xx(retry_);
1356662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block    // We expect set_upload_data() to have been called on this object.
1366662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block    real_fetcher_->set_upload_data(upload_content_type_, upload_content_);
13740eae52c5e5dbf475a0cf368c9ccbb7f8a0653f4Ben Murdoch    real_fetcher_->set_request_context(request_context());
1387d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch    real_fetcher_->Start();
1397d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  };
1407d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
1417d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  static void DoComplete(void* context)
1427d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  {
1436662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block    URLFetcherProxy* that = static_cast<URLFetcherProxy*>(context);
144164f7496de0fbee436b385a79ead9e3cb81a50c1Ben Murdoch    if (pending_callbacks_[that]) {
145164f7496de0fbee436b385a79ead9e3cb81a50c1Ben Murdoch      that->DoCompleteImpl();
146164f7496de0fbee436b385a79ead9e3cb81a50c1Ben Murdoch    }
1477d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  }
1487d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
1496662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  void DoCompleteImpl()
1506662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  {
1516662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block    delegate()->OnURLFetchComplete(this, url_, status_, response_code_, cookies_, data_);
1526662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  }
1536662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block
1546662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  scoped_ptr<URLFetcher> real_fetcher_;
1556662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  URLFetcher::RequestType request_type_;
1566662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block
1576662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  bool retry_;
1586662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  std::string upload_content_type_;
1597d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  std::string upload_content_;
1607d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
1616662b631f1f14f6db83e053e0dd7887bb18adb91Steve Block  GURL url_;
162532b5811cf4c192c4333b19108d6a303edb23691Kristian Monsen  net::URLRequestStatus status_;
1637d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  int response_code_;
1647d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  ResponseCookies cookies_;
1657d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  std::string data_;
1667d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
167164f7496de0fbee436b385a79ead9e3cb81a50c1Ben Murdoch  static std::map<URLFetcherProxy*, bool> pending_callbacks_;
168164f7496de0fbee436b385a79ead9e3cb81a50c1Ben Murdoch
1697d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch  DISALLOW_EVIL_CONSTRUCTORS(URLFetcherProxy);
1707d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch};
1717d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch
1727d214dfa174224b459660971e5b5cce2e06be02aBen Murdoch#endif  // URL_FETCHER_PROXY_H_
173