OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cloud_print/gcp20/prototype/printer.h" | 5 #include "cloud_print/gcp20/prototype/printer.h" |
6 | 6 |
| 7 #include <stdio.h> |
7 #include <string> | 8 #include <string> |
8 #include <vector> | 9 #include <vector> |
9 | 10 |
10 #include "base/command_line.h" | 11 #include "base/command_line.h" |
11 #include "base/file_util.h" | 12 #include "base/file_util.h" |
12 #include "base/guid.h" | 13 #include "base/guid.h" |
13 #include "base/json/json_reader.h" | 14 #include "base/json/json_reader.h" |
14 #include "base/json/json_writer.h" | 15 #include "base/json/json_writer.h" |
15 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
16 #include "cloud_print/gcp20/prototype/command_line_reader.h" | 17 #include "cloud_print/gcp20/prototype/command_line_reader.h" |
17 #include "cloud_print/gcp20/prototype/service_parameters.h" | 18 #include "cloud_print/gcp20/prototype/service_parameters.h" |
| 19 #include "cloud_print/gcp20/prototype/special_io.h" |
18 #include "net/base/net_util.h" | 20 #include "net/base/net_util.h" |
19 #include "net/base/url_util.h" | 21 #include "net/base/url_util.h" |
20 | 22 |
21 const base::FilePath::CharType kPrinterStatePath[] = | 23 const base::FilePath::CharType kPrinterStatePath[] = |
22 FILE_PATH_LITERAL("printer_state.json"); | 24 FILE_PATH_LITERAL("printer_state.json"); |
23 | 25 |
24 namespace { | 26 namespace { |
25 | 27 |
26 const char* kServiceType = "_privet._tcp.local"; | 28 const char kServiceType[] = "_privet._tcp.local"; |
27 const char* kServiceNamePrefix = "first_gcp20_device"; | 29 const char kServiceNamePrefix[] = "first_gcp20_device"; |
28 const char* kServiceDomainName = "my-privet-device.local"; | 30 const char kServiceDomainName[] = "my-privet-device.local"; |
29 | 31 |
30 const char* kPrinterName = "Google GCP2.0 Prototype"; | 32 const char kPrinterName[] = "Google GCP2.0 Prototype"; |
31 const char* kPrinterDescription = "Printer emulator"; | 33 const char kPrinterDescription[] = "Printer emulator"; |
32 | 34 |
33 const char* kCdd = | 35 const char kUserConfirmationTitle[] = "Confirm registration: type 'y' if you " |
| 36 "agree and any other to discard\n"; |
| 37 const int64 kUserConfirmationTimeout = 30; // in seconds |
| 38 |
| 39 const char kCdd[] = |
34 "{\n" | 40 "{\n" |
35 " 'version': '1.0',\n" | 41 " 'version': '1.0',\n" |
36 " 'printer': {\n" | 42 " 'printer': {\n" |
37 " 'vendor_capability': [\n" | 43 " 'vendor_capability': [\n" |
38 " {\n" | 44 " {\n" |
39 " 'id': 'psk:MediaType',\n" | 45 " 'id': 'psk:MediaType',\n" |
40 " 'display_name': 'Media Type',\n" | 46 " 'display_name': 'Media Type',\n" |
41 " 'type': 'SELECT',\n" | 47 " 'type': 'SELECT',\n" |
42 " 'select_cap': {\n" | 48 " 'select_cap': {\n" |
43 " 'option': [\n" | 49 " 'option': [\n" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 LOG(INFO) << net::IPAddressToString(iter->address); | 85 LOG(INFO) << net::IPAddressToString(iter->address); |
80 return iter->address; | 86 return iter->address; |
81 } | 87 } |
82 } | 88 } |
83 | 89 |
84 return net::IPAddressNumber(); | 90 return net::IPAddressNumber(); |
85 } | 91 } |
86 | 92 |
87 } // namespace | 93 } // namespace |
88 | 94 |
89 Printer::RegistrationInfo::RegistrationInfo() : state(DEV_REG_UNREGISTERED) { | 95 Printer::RegistrationInfo::RegistrationInfo() |
| 96 : state(DEV_REG_UNREGISTERED), |
| 97 confirmation_state(CONFIRMATION_PENDING) { |
90 } | 98 } |
91 | 99 |
92 Printer::RegistrationInfo::~RegistrationInfo() { | 100 Printer::RegistrationInfo::~RegistrationInfo() { |
93 } | 101 } |
94 | 102 |
95 Printer::Printer() : http_server_(this) { | 103 Printer::Printer() : http_server_(this) { |
96 } | 104 } |
97 | 105 |
98 Printer::~Printer() { | 106 Printer::~Printer() { |
99 Stop(); | 107 Stop(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 if (status != PrivetHttpServer::REG_ERROR_OK) | 166 if (status != PrivetHttpServer::REG_ERROR_OK) |
159 return status; | 167 return status; |
160 | 168 |
161 if (reg_info_.state != RegistrationInfo::DEV_REG_UNREGISTERED) | 169 if (reg_info_.state != RegistrationInfo::DEV_REG_UNREGISTERED) |
162 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; | 170 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; |
163 | 171 |
164 reg_info_ = RegistrationInfo(); | 172 reg_info_ = RegistrationInfo(); |
165 reg_info_.user = user; | 173 reg_info_.user = user; |
166 reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_STARTED; | 174 reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_STARTED; |
167 | 175 |
| 176 printf(kUserConfirmationTitle); |
| 177 base::Time valid_until = base::Time::Now() + |
| 178 base::TimeDelta::FromSeconds(kUserConfirmationTimeout); |
| 179 base::MessageLoop::current()->PostTask( |
| 180 FROM_HERE, |
| 181 base::Bind(&Printer::WaitUserConfirmation, AsWeakPtr(), valid_until)); |
| 182 |
168 requester_->StartRegistration(GenerateProxyId(), kPrinterName, user, kCdd); | 183 requester_->StartRegistration(GenerateProxyId(), kPrinterName, user, kCdd); |
169 | 184 |
170 return PrivetHttpServer::REG_ERROR_OK; | 185 return PrivetHttpServer::REG_ERROR_OK; |
171 } | 186 } |
172 | 187 |
173 bool Printer::CheckXPrivetTokenHeader(const std::string& token) const { | 188 bool Printer::CheckXPrivetTokenHeader(const std::string& token) const { |
174 return xtoken_.CheckValidXToken(token); | 189 return xtoken_.CheckValidXToken(token); |
175 } | 190 } |
176 | 191 |
177 bool Printer::IsRegistered() const { | 192 bool Printer::IsRegistered() const { |
178 return reg_info_.state == RegistrationInfo::DEV_REG_REGISTERED; | 193 return reg_info_.state == RegistrationInfo::DEV_REG_REGISTERED; |
179 } | 194 } |
180 | 195 |
181 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationGetClaimToken( | 196 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationGetClaimToken( |
182 const std::string& user, | 197 const std::string& user, |
183 std::string* token, | 198 std::string* token, |
184 std::string* claim_url) { | 199 std::string* claim_url) { |
185 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); | 200 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); |
186 if (status != PrivetHttpServer::REG_ERROR_OK) | 201 if (status != PrivetHttpServer::REG_ERROR_OK) |
187 return status; | 202 return status; |
188 | 203 |
189 // TODO(maksymb): Add user confirmation. | 204 // Check if |action=start| was called, but |action=complete| wasn't. |
| 205 if (reg_info_.state != RegistrationInfo::DEV_REG_REGISTRATION_STARTED && |
| 206 reg_info_.state != |
| 207 RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY) |
| 208 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; |
190 | 209 |
| 210 // If |action=getClaimToken| is valid in this state (was checked above) then |
| 211 // check confirmation status. |
| 212 if (reg_info_.confirmation_state != RegistrationInfo::CONFIRMATION_CONFIRMED) |
| 213 return ConfirmationToRegistrationError(reg_info_.confirmation_state); |
| 214 |
| 215 // If reply wasn't received yet, reply with |device_busy| error. |
191 if (reg_info_.state == RegistrationInfo::DEV_REG_REGISTRATION_STARTED) | 216 if (reg_info_.state == RegistrationInfo::DEV_REG_REGISTRATION_STARTED) |
192 return PrivetHttpServer::REG_ERROR_DEVICE_BUSY; | 217 return PrivetHttpServer::REG_ERROR_DEVICE_BUSY; |
193 | 218 |
194 if (reg_info_.state == | 219 DCHECK_EQ(reg_info_.state, |
195 RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY) { | 220 RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY); |
196 *token = reg_info_.registration_token; | 221 DCHECK_EQ(reg_info_.confirmation_state, |
197 *claim_url = reg_info_.complete_invite_url; | 222 RegistrationInfo::CONFIRMATION_CONFIRMED); |
198 return PrivetHttpServer::REG_ERROR_OK; | |
199 } | |
200 | 223 |
201 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; | 224 *token = reg_info_.registration_token; |
| 225 *claim_url = reg_info_.complete_invite_url; |
| 226 return PrivetHttpServer::REG_ERROR_OK; |
202 } | 227 } |
203 | 228 |
204 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationComplete( | 229 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationComplete( |
205 const std::string& user, | 230 const std::string& user, |
206 std::string* device_id) { | 231 std::string* device_id) { |
207 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); | 232 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); |
208 if (status != PrivetHttpServer::REG_ERROR_OK) | 233 if (status != PrivetHttpServer::REG_ERROR_OK) |
209 return status; | 234 return status; |
210 | 235 |
211 if (reg_info_.state != | 236 if (reg_info_.state != |
212 RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY) { | 237 RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY) { |
213 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; | 238 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; |
214 } | 239 } |
215 | 240 |
| 241 if (reg_info_.confirmation_state != RegistrationInfo::CONFIRMATION_CONFIRMED) |
| 242 return ConfirmationToRegistrationError(reg_info_.confirmation_state); |
| 243 |
216 reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_COMPLETING; | 244 reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_COMPLETING; |
217 requester_->CompleteRegistration(); | 245 requester_->CompleteRegistration(); |
218 | |
219 *device_id = reg_info_.device_id; | 246 *device_id = reg_info_.device_id; |
220 | 247 |
221 return PrivetHttpServer::REG_ERROR_OK; | 248 return PrivetHttpServer::REG_ERROR_OK; |
222 } | 249 } |
223 | 250 |
224 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationCancel( | 251 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationCancel( |
225 const std::string& user) { | 252 const std::string& user) { |
226 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); | 253 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); |
227 if (status != PrivetHttpServer::REG_ERROR_OK && | 254 if (status != PrivetHttpServer::REG_ERROR_OK && |
228 status != PrivetHttpServer::REG_ERROR_SERVER_ERROR) { | 255 status != PrivetHttpServer::REG_ERROR_SERVER_ERROR) { |
229 return status; | 256 return status; |
230 } | 257 } |
231 | 258 |
232 if (reg_info_.state == RegistrationInfo::DEV_REG_UNREGISTERED) | 259 if (reg_info_.state == RegistrationInfo::DEV_REG_UNREGISTERED) |
233 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; | 260 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; |
234 | 261 |
235 reg_info_ = RegistrationInfo(); | 262 reg_info_ = RegistrationInfo(); |
| 263 requester_.reset(new CloudPrintRequester( |
| 264 base::MessageLoop::current()->message_loop_proxy(), |
| 265 this)); // Forget all old queries. |
| 266 |
236 return PrivetHttpServer::REG_ERROR_OK; | 267 return PrivetHttpServer::REG_ERROR_OK; |
237 } | 268 } |
238 | 269 |
239 void Printer::GetRegistrationServerError(std::string* description) { | 270 void Printer::GetRegistrationServerError(std::string* description) { |
240 DCHECK_EQ(reg_info_.state, RegistrationInfo::DEV_REG_REGISTRATION_ERROR) << | 271 DCHECK_EQ(reg_info_.state, RegistrationInfo::DEV_REG_REGISTRATION_ERROR) << |
241 "Method shouldn't be called when not needed."; | 272 "Method shouldn't be called when not needed."; |
242 | 273 |
243 *description = reg_info_.error_description; | 274 *description = reg_info_.error_description; |
244 } | 275 } |
245 | 276 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 user != reg_info_.user) { | 331 user != reg_info_.user) { |
301 return PrivetHttpServer::REG_ERROR_DEVICE_BUSY; | 332 return PrivetHttpServer::REG_ERROR_DEVICE_BUSY; |
302 } | 333 } |
303 | 334 |
304 if (reg_info_.state == RegistrationInfo::DEV_REG_REGISTRATION_ERROR) | 335 if (reg_info_.state == RegistrationInfo::DEV_REG_REGISTRATION_ERROR) |
305 return PrivetHttpServer::REG_ERROR_SERVER_ERROR; | 336 return PrivetHttpServer::REG_ERROR_SERVER_ERROR; |
306 | 337 |
307 return PrivetHttpServer::REG_ERROR_OK; | 338 return PrivetHttpServer::REG_ERROR_OK; |
308 } | 339 } |
309 | 340 |
| 341 void Printer::WaitUserConfirmation(base::Time valid_until) { |
| 342 if (base::Time::Now() > valid_until) { |
| 343 reg_info_.confirmation_state = RegistrationInfo::CONFIRMATION_TIMEOUT; |
| 344 LOG(INFO) << "Confirmation timeout reached."; |
| 345 return; |
| 346 } |
| 347 |
| 348 if (_kbhit()) { |
| 349 int c = _getche(); |
| 350 if (c == 'y' || c == 'Y') { |
| 351 reg_info_.confirmation_state = RegistrationInfo::CONFIRMATION_CONFIRMED; |
| 352 LOG(INFO) << "Registration confirmed by user."; |
| 353 } else { |
| 354 reg_info_.confirmation_state = RegistrationInfo::CONFIRMATION_DISCARDED; |
| 355 LOG(INFO) << "Registration discarded by user."; |
| 356 } |
| 357 return; |
| 358 } |
| 359 |
| 360 base::MessageLoop::current()->PostDelayedTask( |
| 361 FROM_HERE, |
| 362 base::Bind(&Printer::WaitUserConfirmation, AsWeakPtr(), valid_until), |
| 363 base::TimeDelta::FromMilliseconds(100)); |
| 364 } |
| 365 |
310 std::string Printer::GenerateProxyId() const { | 366 std::string Printer::GenerateProxyId() const { |
311 return "{" + base::GenerateGUID() +"}"; | 367 return "{" + base::GenerateGUID() +"}"; |
312 } | 368 } |
313 | 369 |
314 std::vector<std::string> Printer::CreateTxt() const { | 370 std::vector<std::string> Printer::CreateTxt() const { |
315 std::vector<std::string> txt; | 371 std::vector<std::string> txt; |
316 txt.push_back("txtvers=1"); | 372 txt.push_back("txtvers=1"); |
317 txt.push_back("ty=" + std::string(kPrinterName)); | 373 txt.push_back("ty=" + std::string(kPrinterName)); |
318 txt.push_back("note=" + std::string(kPrinterDescription)); | 374 txt.push_back("note=" + std::string(kPrinterDescription)); |
319 txt.push_back("url=" + std::string(kCloudPrintUrl)); | 375 txt.push_back("url=" + std::string(kCloudPrintUrl)); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 | 454 |
399 reg_info_ = RegistrationInfo(); | 455 reg_info_ = RegistrationInfo(); |
400 reg_info_.state = RegistrationInfo::DEV_REG_REGISTERED; | 456 reg_info_.state = RegistrationInfo::DEV_REG_REGISTERED; |
401 reg_info_.user = user; | 457 reg_info_.user = user; |
402 reg_info_.device_id = device_id; | 458 reg_info_.device_id = device_id; |
403 reg_info_.refresh_token = refresh_token; | 459 reg_info_.refresh_token = refresh_token; |
404 | 460 |
405 return true; | 461 return true; |
406 } | 462 } |
407 | 463 |
| 464 PrivetHttpServer::RegistrationErrorStatus |
| 465 Printer::ConfirmationToRegistrationError( |
| 466 RegistrationInfo::ConfirmationState state) { |
| 467 switch (state) { |
| 468 case RegistrationInfo::CONFIRMATION_PENDING: |
| 469 return PrivetHttpServer::REG_ERROR_PENDING_USER_ACTION; |
| 470 case RegistrationInfo::CONFIRMATION_DISCARDED: |
| 471 return PrivetHttpServer::REG_ERROR_USER_CANCEL; |
| 472 case RegistrationInfo::CONFIRMATION_CONFIRMED: |
| 473 NOTREACHED(); |
| 474 return PrivetHttpServer::REG_ERROR_OK; |
| 475 case RegistrationInfo::CONFIRMATION_TIMEOUT: |
| 476 return PrivetHttpServer::REG_ERROR_CONFIRMATION_TIMEOUT; |
| 477 default: |
| 478 NOTREACHED(); |
| 479 return PrivetHttpServer::REG_ERROR_OK; |
| 480 } |
| 481 } |
| 482 |
OLD | NEW |