1// Copyright 2013 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 CLOUD_PRINT_GCP20_PROTOTYPE_PRIVET_HTTP_SERVER_H_
6#define CLOUD_PRINT_GCP20_PROTOTYPE_PRIVET_HTTP_SERVER_H_
7
8#include <string>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "base/values.h"
13#include "cloud_print/gcp20/prototype/local_print_job.h"
14#include "net/server/http_server.h"
15#include "net/server/http_server_request_info.h"
16
17class GURL;
18
19// HTTP server for receiving .
20class PrivetHttpServer: public net::HttpServer::Delegate {
21 public:
22  // TODO(maksymb): Move this enum to some namespace instead of this class.
23  enum RegistrationErrorStatus {
24    REG_ERROR_OK,
25
26    REG_ERROR_INVALID_PARAMS,
27    REG_ERROR_DEVICE_BUSY,
28    REG_ERROR_PENDING_USER_ACTION,
29    REG_ERROR_USER_CANCEL,
30    REG_ERROR_CONFIRMATION_TIMEOUT,
31    REG_ERROR_INVALID_ACTION,
32    REG_ERROR_OFFLINE,
33    REG_ERROR_SERVER_ERROR
34  };
35
36  // TODO(maksymb): Move this struct to some namespace instead of this class.
37  struct DeviceInfo {
38    DeviceInfo();
39    ~DeviceInfo();
40
41    std::string version;
42    std::string name;
43    std::string description;
44    std::string url;
45    std::string id;
46    std::string device_state;
47    std::string connection_state;
48    std::string manufacturer;
49    std::string model;
50    std::string serial_number;
51    std::string firmware;
52    int uptime;
53    std::string x_privet_token;
54
55    std::vector<std::string> api;
56    std::vector<std::string> type;
57  };
58
59  class Delegate {
60   public:
61    virtual ~Delegate() {}
62
63    // Invoked when registration is starting.
64    virtual RegistrationErrorStatus RegistrationStart(
65        const std::string& user) = 0;
66
67    // Invoked when claimtoken is needed.
68    virtual RegistrationErrorStatus RegistrationGetClaimToken(
69        const std::string& user,
70        std::string* token,
71        std::string* claim_url) = 0;
72
73    // Invoked when registration is going to be completed.
74    virtual RegistrationErrorStatus RegistrationComplete(
75        const std::string& user,
76        std::string* device_id) = 0;
77
78    // Invoked when client asked for cancelling the registration.
79    virtual RegistrationErrorStatus RegistrationCancel(
80        const std::string& user) = 0;
81
82    // Invoked for receiving server error details.
83    virtual void GetRegistrationServerError(std::string* description) = 0;
84
85    // Invoked when /privet/info is called.
86    virtual void CreateInfo(DeviceInfo* info) = 0;
87
88    // Invoked for checking wether /privet/register should be exposed.
89    virtual bool IsRegistered() const = 0;
90
91    // Invoked for checking wether /privet/printer/* should be exposed.
92    virtual bool IsLocalPrintingAllowed() const = 0;
93
94    // Invoked when XPrivetToken has to be checked.
95    virtual bool CheckXPrivetTokenHeader(const std::string& token) const = 0;
96
97    // Invoked for getting capabilities.
98    virtual const base::DictionaryValue& GetCapabilities() = 0;
99
100    // Invoked for creating a job.
101    virtual LocalPrintJob::CreateResult CreateJob(
102        const std::string& ticket,
103        std::string* job_id,
104        int* expires_in,
105        // TODO(maksymb): Use base::TimeDelta for timeouts
106        int* error_timeout,
107        std::string* error_description) = 0;
108
109    // Invoked for simple local printing.
110    virtual LocalPrintJob::SaveResult SubmitDoc(
111        const LocalPrintJob& job,
112        std::string* job_id,
113        int* expires_in,
114        std::string* error_description,
115        int* timeout) = 0;
116
117    // Invoked for advanced local printing.
118    virtual LocalPrintJob::SaveResult SubmitDocWithId(
119        const LocalPrintJob& job,
120        const std::string& job_id,
121        int* expires_in,
122        std::string* error_description,
123        int* timeout) = 0;
124
125    // Invoked for getting job status.
126    virtual bool GetJobState(const std::string& job_id,
127                             LocalPrintJob::Info* info) = 0;
128  };
129
130  // Constructor doesn't start server.
131  explicit PrivetHttpServer(Delegate* delegate);
132
133  // Destroys the object.
134  virtual ~PrivetHttpServer();
135
136  // Starts HTTP server: start listening port |port| for HTTP requests.
137  bool Start(uint16 port);
138
139  // Stops HTTP server.
140  void Shutdown();
141
142 private:
143  // net::HttpServer::Delegate methods:
144  virtual void OnConnect(int connection_id) OVERRIDE {}
145  virtual void OnHttpRequest(
146      int connection_id,
147      const net::HttpServerRequestInfo& info) OVERRIDE;
148  virtual void OnWebSocketRequest(
149      int connection_id,
150      const net::HttpServerRequestInfo& info) OVERRIDE;
151  virtual void OnWebSocketMessage(int connection_id,
152                                  const std::string& data) OVERRIDE;
153  virtual void OnClose(int connection_id) OVERRIDE;
154
155  // Sends error as response. Invoked when request method is invalid.
156  void ReportInvalidMethod(int connection_id);
157
158  // Returns |true| if |request| should be done with correct |method|.
159  // Otherwise sends |Invalid method| error.
160  // Also checks support of |request| by this server.
161  bool ValidateRequestMethod(int connection_id,
162                             const std::string& request,
163                             const std::string& method);
164
165  // Processes http request after all preparations (XPrivetHeader check,
166  // data handling etc.)
167  net::HttpStatusCode ProcessHttpRequest(
168      const GURL& url,
169      const net::HttpServerRequestInfo& info,
170      std::string* response);
171
172  // Pivet API methods. Return reference to NULL if output should be empty.
173  scoped_ptr<base::DictionaryValue> ProcessInfo(
174      net::HttpStatusCode* status_code) const;
175
176  scoped_ptr<base::DictionaryValue> ProcessCapabilities(
177      net::HttpStatusCode* status_code) const;
178
179  scoped_ptr<base::DictionaryValue> ProcessCreateJob(
180      const GURL& url,
181      const std::string& body,
182      net::HttpStatusCode* status_code) const;
183
184  scoped_ptr<base::DictionaryValue> ProcessSubmitDoc(
185      const GURL& url,
186      const net::HttpServerRequestInfo& info,
187      net::HttpStatusCode* status_code) const;
188
189  scoped_ptr<base::DictionaryValue> ProcessJobState(
190      const GURL& url,
191      net::HttpStatusCode* status_code) const;
192
193  scoped_ptr<base::DictionaryValue> ProcessRegister(
194      const GURL& url,
195      net::HttpStatusCode* status_code) const;
196
197  // Processes current status and depending on it replaces (or not)
198  // |current_response| with error or empty response.
199  void ProcessRegistrationStatus(
200      RegistrationErrorStatus status,
201      scoped_ptr<base::DictionaryValue>* current_response) const;
202
203  // Port for listening.
204
205  uint16 port_;
206
207  // Contains encapsulated object for listening for requests.
208  scoped_ptr<net::HttpServer> server_;
209
210  Delegate* delegate_;
211
212  DISALLOW_COPY_AND_ASSIGN(PrivetHttpServer);
213};
214
215#endif  // CLOUD_PRINT_GCP20_PROTOTYPE_PRIVET_HTTP_SERVER_H_
216