root/chrome/service/cloud_print/cloud_print_url_fetcher.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_URL_FETCHER_H_
#define CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_URL_FETCHER_H_

#include <string>

#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"

class GURL;

namespace base {
class DictionaryValue;
}

namespace net {
class URLRequestContextGetter;
class URLRequestStatus;
}  // namespace net

namespace cloud_print {

// Factory for creating CloudPrintURLFetchers.
class CloudPrintURLFetcher;
class CloudPrintURLFetcherFactory {
 public:
  virtual CloudPrintURLFetcher* CreateCloudPrintURLFetcher() = 0;
  virtual ~CloudPrintURLFetcherFactory();
};

// A wrapper around URLFetcher for CloudPrint. URLFetcher applies retry logic
// only on HTTP response codes >= 500. In the cloud print case, we want to
// retry on all network errors. In addition, we want to treat non-JSON responses
// (for all CloudPrint APIs that expect JSON responses) as errors and they
// must also be retried.
class CloudPrintURLFetcher
    : public base::RefCountedThreadSafe<CloudPrintURLFetcher>,
      public net::URLFetcherDelegate {
 public:
  enum ResponseAction {
    CONTINUE_PROCESSING,
    STOP_PROCESSING,
    RETRY_REQUEST,
  };

  enum RequestType {
    REQUEST_AUTH_CODE,
    REQUEST_REGISTER,
    REQUEST_UNREGISTER,
    REQUEST_UPDATE_PRINTER,
    REQUEST_UPDATE_JOB,
    REQUEST_USER_MESSAGE,
    REQUEST_TICKET,
    REQUEST_DATA,
    REQUEST_JOB_FETCH,
    REQUEST_MAX,
  };

  class Delegate {
   public:
    // Override this to handle the raw response as it is available. No response
    // error checking is done before this method is called. If the delegate
    // returns CONTINUE_PROCESSING, we will then check for network
    // errors. Most implementations will not override this.
    virtual ResponseAction HandleRawResponse(
        const net::URLFetcher* source,
        const GURL& url,
        const net::URLRequestStatus& status,
        int response_code,
        const net::ResponseCookies& cookies,
        const std::string& data);

    // This will be invoked only if HandleRawResponse returns
    // CONTINUE_PROCESSING AND if there are no network errors and the HTTP
    // response code is 200. The delegate implementation returns
    // CONTINUE_PROCESSING if it does not want to handle the raw data itself.
    // Handling the raw data is needed when the expected response is NOT JSON
    // (like in the case of a print ticket response or a print job download
    // response).
    virtual ResponseAction HandleRawData(const net::URLFetcher* source,
                                         const GURL& url,
                                         const std::string& data);

    // This will be invoked only if HandleRawResponse and HandleRawData return
    // CONTINUE_PROCESSING AND if the response contains a valid JSON dictionary.
    // |succeeded| is the value of the "success" field in the response JSON.
    virtual ResponseAction HandleJSONData(const net::URLFetcher* source,
                                          const GURL& url,
                                          base::DictionaryValue* json_data,
                                          bool succeeded);

    // Invoked when the retry limit for this request has been reached (if there
    // was a retry limit - a limit of -1 implies no limit).
    virtual void OnRequestGiveUp() { }

    // Invoked when the request returns a 403 error (applicable only when
    // HandleRawResponse returns CONTINUE_PROCESSING).
    // Returning RETRY_REQUEST will retry current request. (auth information
    // may have been updated and new info is available through the
    // Authenticator interface).
    // Returning CONTINUE_PROCESSING will treat auth error as a network error.
    virtual ResponseAction OnRequestAuthError() = 0;

    // Authentication information may change between retries.
    // CloudPrintURLFetcher will request auth info before sending any request.
    virtual std::string GetAuthHeader() = 0;

   protected:
    virtual ~Delegate() {}
  };

  static CloudPrintURLFetcher* Create();
  static void set_factory(CloudPrintURLFetcherFactory* factory);

  bool IsSameRequest(const net::URLFetcher* source);

  void StartGetRequest(RequestType type,
                       const GURL& url,
                       Delegate* delegate,
                       int max_retries,
                       const std::string& additional_headers);
  void StartPostRequest(RequestType type,
                        const GURL& url,
                        Delegate* delegate,
                        int max_retries,
                        const std::string& post_data_mime_type,
                        const std::string& post_data,
                        const std::string& additional_headers);

  // net::URLFetcherDelegate implementation.
  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;

 protected:
  CloudPrintURLFetcher();
  friend class base::RefCountedThreadSafe<CloudPrintURLFetcher>;
  virtual ~CloudPrintURLFetcher();

  // Virtual for testing.
  virtual net::URLRequestContextGetter* GetRequestContextGetter();

 private:
  void StartRequestHelper(RequestType type,
                          const GURL& url,
                          net::URLFetcher::RequestType request_type,
                          Delegate* delegate,
                          int max_retries,
                          const std::string& post_data_mime_type,
                          const std::string& post_data,
                          const std::string& additional_headers);
  void SetupRequestHeaders();
  static CloudPrintURLFetcherFactory* factory();

  scoped_ptr<net::URLFetcher> request_;
  Delegate* delegate_;
  int num_retries_;
  net::URLFetcher::RequestType request_type_;
  std::string additional_headers_;
  std::string post_data_mime_type_;
  std::string post_data_;

  RequestType type_;
  base::Time start_time_;
};

typedef CloudPrintURLFetcher::Delegate CloudPrintURLFetcherDelegate;

}  // namespace cloud_print

#endif  // CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_URL_FETCHER_H_

/* [<][>][^][v][top][bottom][index][help] */