Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(756)

Side by Side Diff: cloud_print/gcp20/prototype/printer.cc

Issue 19468002: Added confirmation for printer registration. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@new-api-availability-check
Patch Set: kbhit to _kbhit Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cloud_print/gcp20/prototype/printer.h ('k') | cloud_print/gcp20/prototype/special_io.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « cloud_print/gcp20/prototype/printer.h ('k') | cloud_print/gcp20/prototype/special_io.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698