1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_URL_FETCHER_H_
6#define CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_URL_FETCHER_H_
7
8#include <string>
9
10#include "base/memory/ref_counted.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/time/time.h"
13#include "net/url_request/url_fetcher.h"
14#include "net/url_request/url_fetcher_delegate.h"
15
16class GURL;
17
18namespace base {
19class DictionaryValue;
20}
21
22namespace net {
23class URLRequestContextGetter;
24class URLRequestStatus;
25}  // namespace net
26
27namespace cloud_print {
28
29// Factory for creating CloudPrintURLFetchers.
30class CloudPrintURLFetcher;
31class CloudPrintURLFetcherFactory {
32 public:
33  virtual CloudPrintURLFetcher* CreateCloudPrintURLFetcher() = 0;
34  virtual ~CloudPrintURLFetcherFactory();
35};
36
37// A wrapper around URLFetcher for CloudPrint. URLFetcher applies retry logic
38// only on HTTP response codes >= 500. In the cloud print case, we want to
39// retry on all network errors. In addition, we want to treat non-JSON responses
40// (for all CloudPrint APIs that expect JSON responses) as errors and they
41// must also be retried.
42class CloudPrintURLFetcher
43    : public base::RefCountedThreadSafe<CloudPrintURLFetcher>,
44      public net::URLFetcherDelegate {
45 public:
46  enum ResponseAction {
47    CONTINUE_PROCESSING,
48    STOP_PROCESSING,
49    RETRY_REQUEST,
50  };
51
52  enum RequestType {
53    REQUEST_AUTH_CODE,
54    REQUEST_REGISTER,
55    REQUEST_UNREGISTER,
56    REQUEST_UPDATE_PRINTER,
57    REQUEST_UPDATE_JOB,
58    REQUEST_USER_MESSAGE,
59    REQUEST_TICKET,
60    REQUEST_DATA,
61    REQUEST_JOB_FETCH,
62    REQUEST_MAX,
63  };
64
65  class Delegate {
66   public:
67    // Override this to handle the raw response as it is available. No response
68    // error checking is done before this method is called. If the delegate
69    // returns CONTINUE_PROCESSING, we will then check for network
70    // errors. Most implementations will not override this.
71    virtual ResponseAction HandleRawResponse(
72        const net::URLFetcher* source,
73        const GURL& url,
74        const net::URLRequestStatus& status,
75        int response_code,
76        const net::ResponseCookies& cookies,
77        const std::string& data);
78
79    // This will be invoked only if HandleRawResponse returns
80    // CONTINUE_PROCESSING AND if there are no network errors and the HTTP
81    // response code is 200. The delegate implementation returns
82    // CONTINUE_PROCESSING if it does not want to handle the raw data itself.
83    // Handling the raw data is needed when the expected response is NOT JSON
84    // (like in the case of a print ticket response or a print job download
85    // response).
86    virtual ResponseAction HandleRawData(const net::URLFetcher* source,
87                                         const GURL& url,
88                                         const std::string& data);
89
90    // This will be invoked only if HandleRawResponse and HandleRawData return
91    // CONTINUE_PROCESSING AND if the response contains a valid JSON dictionary.
92    // |succeeded| is the value of the "success" field in the response JSON.
93    virtual ResponseAction HandleJSONData(const net::URLFetcher* source,
94                                          const GURL& url,
95                                          base::DictionaryValue* json_data,
96                                          bool succeeded);
97
98    // Invoked when the retry limit for this request has been reached (if there
99    // was a retry limit - a limit of -1 implies no limit).
100    virtual void OnRequestGiveUp() { }
101
102    // Invoked when the request returns a 403 error (applicable only when
103    // HandleRawResponse returns CONTINUE_PROCESSING).
104    // Returning RETRY_REQUEST will retry current request. (auth information
105    // may have been updated and new info is available through the
106    // Authenticator interface).
107    // Returning CONTINUE_PROCESSING will treat auth error as a network error.
108    virtual ResponseAction OnRequestAuthError() = 0;
109
110    // Authentication information may change between retries.
111    // CloudPrintURLFetcher will request auth info before sending any request.
112    virtual std::string GetAuthHeader() = 0;
113
114   protected:
115    virtual ~Delegate() {}
116  };
117
118  static CloudPrintURLFetcher* Create();
119  static void set_factory(CloudPrintURLFetcherFactory* factory);
120
121  bool IsSameRequest(const net::URLFetcher* source);
122
123  void StartGetRequest(RequestType type,
124                       const GURL& url,
125                       Delegate* delegate,
126                       int max_retries,
127                       const std::string& additional_headers);
128  void StartPostRequest(RequestType type,
129                        const GURL& url,
130                        Delegate* delegate,
131                        int max_retries,
132                        const std::string& post_data_mime_type,
133                        const std::string& post_data,
134                        const std::string& additional_headers);
135
136  // net::URLFetcherDelegate implementation.
137  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
138
139 protected:
140  CloudPrintURLFetcher();
141  friend class base::RefCountedThreadSafe<CloudPrintURLFetcher>;
142  virtual ~CloudPrintURLFetcher();
143
144  // Virtual for testing.
145  virtual net::URLRequestContextGetter* GetRequestContextGetter();
146
147 private:
148  void StartRequestHelper(RequestType type,
149                          const GURL& url,
150                          net::URLFetcher::RequestType request_type,
151                          Delegate* delegate,
152                          int max_retries,
153                          const std::string& post_data_mime_type,
154                          const std::string& post_data,
155                          const std::string& additional_headers);
156  void SetupRequestHeaders();
157  static CloudPrintURLFetcherFactory* factory();
158
159  scoped_ptr<net::URLFetcher> request_;
160  Delegate* delegate_;
161  int num_retries_;
162  net::URLFetcher::RequestType request_type_;
163  std::string additional_headers_;
164  std::string post_data_mime_type_;
165  std::string post_data_;
166
167  RequestType type_;
168  base::Time start_time_;
169};
170
171typedef CloudPrintURLFetcher::Delegate CloudPrintURLFetcherDelegate;
172
173}  // namespace cloud_print
174
175#endif  // CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_URL_FETCHER_H_
176