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

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: 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') | no next file » | 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 #if defined(OS_WIN)
8 #include <conio.h>
9 #else
10 #include <stdio.h>
11 #include <sys/types.h>
12 #include <sys/time.h>
13 #include <termios.h>
14 #include <unistd.h>
15 #endif // !defined(OS_WIN)
16 #include <iostream>
7 #include <string> 17 #include <string>
8 #include <vector> 18 #include <vector>
9 19
10 #include "base/command_line.h" 20 #include "base/command_line.h"
11 #include "base/file_util.h" 21 #include "base/file_util.h"
12 #include "base/guid.h" 22 #include "base/guid.h"
13 #include "base/json/json_reader.h" 23 #include "base/json/json_reader.h"
14 #include "base/json/json_writer.h" 24 #include "base/json/json_writer.h"
15 #include "base/strings/string_number_conversions.h" 25 #include "base/strings/string_number_conversions.h"
16 #include "cloud_print/gcp20/prototype/command_line_reader.h" 26 #include "cloud_print/gcp20/prototype/command_line_reader.h"
17 #include "cloud_print/gcp20/prototype/service_parameters.h" 27 #include "cloud_print/gcp20/prototype/service_parameters.h"
18 #include "net/base/net_util.h" 28 #include "net/base/net_util.h"
19 #include "net/base/url_util.h" 29 #include "net/base/url_util.h"
20 30
21 const char* kPrinterStatePath = "printer_state.json"; 31 const char* kPrinterStatePath = "printer_state.json";
22 32
23 namespace { 33 namespace {
24 34
25 const char* kServiceType = "_privet._tcp.local"; 35 const char* kServiceType = "_privet._tcp.local";
26 const char* kServiceNamePrefix = "first_gcp20_device"; 36 const char* kServiceNamePrefix = "first_gcp20_device";
Vitaly Buka (NO REVIEWS) 2013/07/17 06:59:00 Just noticed, please replace all such consts with
maksymb 2013/07/17 18:24:50 Done.
27 const char* kServiceDomainName = "my-privet-device.local"; 37 const char* kServiceDomainName = "my-privet-device.local";
28 38
29 const char* kPrinterName = "Google GCP2.0 Prototype"; 39 const char* kPrinterName = "Google GCP2.0 Prototype";
30 const char* kPrinterDescription = "Printer emulator"; 40 const char* kPrinterDescription = "Printer emulator";
31 41
42 const char* kUserConfirmationTitle = "Confirm registration: type 'y' if you "
43 "agree and any other for otherwise.";
44 const uint kUserConfirmationTimeout = 10; // in seconds
45
32 const char* kCdd = 46 const char* kCdd =
33 "{\n" 47 "{\n"
34 " 'version': '1.0',\n" 48 " 'version': '1.0',\n"
35 " 'printer': {\n" 49 " 'printer': {\n"
36 " 'vendor_capability': [\n" 50 " 'vendor_capability': [\n"
37 " {\n" 51 " {\n"
38 " 'id': 'psk:MediaType',\n" 52 " 'id': 'psk:MediaType',\n"
39 " 'display_name': 'Media Type',\n" 53 " 'display_name': 'Media Type',\n"
40 " 'type': 'SELECT',\n" 54 " 'type': 'SELECT',\n"
41 " 'select_cap': {\n" 55 " 'select_cap': {\n"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 if (iter->address.size() == expected_address_size && 90 if (iter->address.size() == expected_address_size &&
77 (interface_name.empty() || interface_name == iter->name)) { 91 (interface_name.empty() || interface_name == iter->name)) {
78 LOG(INFO) << net::IPAddressToString(iter->address); 92 LOG(INFO) << net::IPAddressToString(iter->address);
79 return iter->address; 93 return iter->address;
80 } 94 }
81 } 95 }
82 96
83 return net::IPAddressNumber(); 97 return net::IPAddressNumber();
84 } 98 }
85 99
100 #if !defined(OS_WIN)
maksymb 2013/07/17 01:28:20 I don't like to see all this stuff here, in this f
Vitaly Buka (NO REVIEWS) 2013/07/17 06:59:00 sure, you can put this in some file with _posix.cc
maksymb 2013/07/17 18:24:50 Done.
101
102 // Method for disabling buffered IO.
103 // |true| - disable, |false| - restore previous settings.
104 void SetTemporaryTermiosSettings(bool temporary) {
105 static termios oldt, newt;
106
107 if (temporary) {
108 tcgetattr(STDIN_FILENO, &oldt);
109 newt = oldt;
110 newt.c_lflag &= ~ICANON; // Disable buffered IO.
111 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
112 } else {
113 tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // Restore default settings.
114 }
115 }
116
117 // Analog from conio.h
118 int kbhit() {
119 SetTemporaryTermiosSettings(true);
120
121 timeval tv;
122 fd_set rdfs;
123
124 tv.tv_sec = 0;
125 tv.tv_usec = 0;
126
127 FD_ZERO(&rdfs);
128 FD_SET(STDIN_FILENO, &rdfs);
129 select(STDIN_FILENO + 1, &rdfs, NULL, NULL, &tv);
130 SetTemporaryTermiosSettings(false);
131
132 return FD_ISSET(STDIN_FILENO, &rdfs);
133 }
134
135 // Analog from conio.h
136 int getche() {
137 SetTemporaryTermiosSettings(true);
138 int c = getchar();
139 SetTemporaryTermiosSettings(false);
140 return c;
141 }
142
143 #endif // !defined(OS_WIN)
144
86 } // namespace 145 } // namespace
87 146
88 Printer::RegistrationInfo::RegistrationInfo() : state(DEV_REG_UNREGISTERED) { 147 Printer::RegistrationInfo::RegistrationInfo()
148 : state(DEV_REG_UNREGISTERED),
149 confirmation_state(CONFIRMATION_PENDING) {
89 } 150 }
90 151
91 Printer::RegistrationInfo::~RegistrationInfo() { 152 Printer::RegistrationInfo::~RegistrationInfo() {
92 } 153 }
93 154
94 Printer::Printer() : http_server_(this) { 155 Printer::Printer() : http_server_(this) {
95 } 156 }
96 157
97 Printer::~Printer() { 158 Printer::~Printer() {
98 Stop(); 159 Stop();
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 if (status != PrivetHttpServer::REG_ERROR_OK) 218 if (status != PrivetHttpServer::REG_ERROR_OK)
158 return status; 219 return status;
159 220
160 if (reg_info_.state != RegistrationInfo::DEV_REG_UNREGISTERED) 221 if (reg_info_.state != RegistrationInfo::DEV_REG_UNREGISTERED)
161 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; 222 return PrivetHttpServer::REG_ERROR_INVALID_ACTION;
162 223
163 reg_info_ = RegistrationInfo(); 224 reg_info_ = RegistrationInfo();
164 reg_info_.user = user; 225 reg_info_.user = user;
165 reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_STARTED; 226 reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_STARTED;
166 227
228 std::cout << kUserConfirmationTitle << std::endl;
229 base::Time valid_until = base::Time::Now() +
230 base::TimeDelta::FromSeconds(kUserConfirmationTimeout);
231 base::MessageLoop::current()->PostTask(
232 FROM_HERE,
233 base::Bind(&Printer::WaitUserConfirmation,
234 base::Unretained(this), valid_until));
235
167 requester_->StartRegistration(GenerateProxyId(), kPrinterName, user, kCdd); 236 requester_->StartRegistration(GenerateProxyId(), kPrinterName, user, kCdd);
168 237
169 return PrivetHttpServer::REG_ERROR_OK; 238 return PrivetHttpServer::REG_ERROR_OK;
170 } 239 }
171 240
172 bool Printer::CheckXPrivetTokenHeader(const std::string& token) const { 241 bool Printer::CheckXPrivetTokenHeader(const std::string& token) const {
173 return xtoken_.CheckValidXToken(token); 242 return xtoken_.CheckValidXToken(token);
174 } 243 }
175 244
176 bool Printer::IsRegistered() const { 245 bool Printer::IsRegistered() const {
177 return reg_info_.state == RegistrationInfo::DEV_REG_REGISTERED; 246 return reg_info_.state == RegistrationInfo::DEV_REG_REGISTERED;
178 } 247 }
179 248
180 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationGetClaimToken( 249 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationGetClaimToken(
181 const std::string& user, 250 const std::string& user,
182 std::string* token, 251 std::string* token,
183 std::string* claim_url) { 252 std::string* claim_url) {
184 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); 253 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user);
185 if (status != PrivetHttpServer::REG_ERROR_OK) 254 if (status != PrivetHttpServer::REG_ERROR_OK)
186 return status; 255 return status;
187 256
188 // TODO(maksymb): Add user confirmation. 257 if (reg_info_.state != RegistrationInfo::DEV_REG_REGISTRATION_STARTED &&
258 reg_info_.state !=
259 RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY)
260 return PrivetHttpServer::REG_ERROR_INVALID_ACTION;
261
262 if (reg_info_.confirmation_state != RegistrationInfo::CONFIRMATION_CONFIRMED)
263 return ConfirmationToRegistrationError(reg_info_.confirmation_state);
189 264
190 if (reg_info_.state == RegistrationInfo::DEV_REG_REGISTRATION_STARTED) 265 if (reg_info_.state == RegistrationInfo::DEV_REG_REGISTRATION_STARTED)
191 return PrivetHttpServer::REG_ERROR_DEVICE_BUSY; 266 return PrivetHttpServer::REG_ERROR_DEVICE_BUSY;
192 267
193 if (reg_info_.state == 268 *token = reg_info_.registration_token;
194 RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY) { 269 *claim_url = reg_info_.complete_invite_url;
195 *token = reg_info_.registration_token; 270 return PrivetHttpServer::REG_ERROR_OK;
196 *claim_url = reg_info_.complete_invite_url;
197 return PrivetHttpServer::REG_ERROR_OK;
198 }
199
200 return PrivetHttpServer::REG_ERROR_INVALID_ACTION;
201 } 271 }
202 272
203 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationComplete( 273 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationComplete(
204 const std::string& user, 274 const std::string& user,
205 std::string* device_id) { 275 std::string* device_id) {
206 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); 276 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user);
207 if (status != PrivetHttpServer::REG_ERROR_OK) 277 if (status != PrivetHttpServer::REG_ERROR_OK)
208 return status; 278 return status;
209 279
210 if (reg_info_.state != 280 if (reg_info_.state !=
211 RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY) { 281 RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY) {
212 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; 282 return PrivetHttpServer::REG_ERROR_INVALID_ACTION;
213 } 283 }
214 284
285 if (reg_info_.confirmation_state != RegistrationInfo::CONFIRMATION_CONFIRMED)
286 return ConfirmationToRegistrationError(reg_info_.confirmation_state);
287
215 reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_COMPLETING; 288 reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_COMPLETING;
216 requester_->CompleteRegistration(); 289 requester_->CompleteRegistration();
217
218 *device_id = reg_info_.device_id; 290 *device_id = reg_info_.device_id;
219 291
220 return PrivetHttpServer::REG_ERROR_OK; 292 return PrivetHttpServer::REG_ERROR_OK;
221 } 293 }
222 294
223 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationCancel( 295 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationCancel(
224 const std::string& user) { 296 const std::string& user) {
225 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); 297 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user);
226 if (status != PrivetHttpServer::REG_ERROR_OK && 298 if (status != PrivetHttpServer::REG_ERROR_OK &&
227 status != PrivetHttpServer::REG_ERROR_SERVER_ERROR) { 299 status != PrivetHttpServer::REG_ERROR_SERVER_ERROR) {
228 return status; 300 return status;
229 } 301 }
230 302
231 if (reg_info_.state == RegistrationInfo::DEV_REG_UNREGISTERED) 303 if (reg_info_.state == RegistrationInfo::DEV_REG_UNREGISTERED)
232 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; 304 return PrivetHttpServer::REG_ERROR_INVALID_ACTION;
233 305
234 reg_info_ = RegistrationInfo(); 306 reg_info_ = RegistrationInfo();
307 requester_.reset(new CloudPrintRequester(
308 base::MessageLoop::current()->message_loop_proxy(),
309 this)); // Forget all old queries.
310
235 return PrivetHttpServer::REG_ERROR_OK; 311 return PrivetHttpServer::REG_ERROR_OK;
236 } 312 }
237 313
238 void Printer::GetRegistrationServerError(std::string* description) { 314 void Printer::GetRegistrationServerError(std::string* description) {
239 DCHECK_EQ(reg_info_.state, RegistrationInfo::DEV_REG_REGISTRATION_ERROR) << 315 DCHECK_EQ(reg_info_.state, RegistrationInfo::DEV_REG_REGISTRATION_ERROR) <<
240 "Method shouldn't be called when not needed."; 316 "Method shouldn't be called when not needed.";
241 317
242 *description = reg_info_.error_description; 318 *description = reg_info_.error_description;
243 } 319 }
244 320
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 user != reg_info_.user) { 375 user != reg_info_.user) {
300 return PrivetHttpServer::REG_ERROR_DEVICE_BUSY; 376 return PrivetHttpServer::REG_ERROR_DEVICE_BUSY;
301 } 377 }
302 378
303 if (reg_info_.state == RegistrationInfo::DEV_REG_REGISTRATION_ERROR) 379 if (reg_info_.state == RegistrationInfo::DEV_REG_REGISTRATION_ERROR)
304 return PrivetHttpServer::REG_ERROR_SERVER_ERROR; 380 return PrivetHttpServer::REG_ERROR_SERVER_ERROR;
305 381
306 return PrivetHttpServer::REG_ERROR_OK; 382 return PrivetHttpServer::REG_ERROR_OK;
307 } 383 }
308 384
385 void Printer::WaitUserConfirmation(base::Time valid_until) {
386 if (base::Time::Now() > valid_until) {
387 reg_info_.confirmation_state = RegistrationInfo::CONFIRMATION_TIMEOUT;
388 LOG(INFO) << "Confirmation timeout reached.";
389 return;
390 }
391
392 if (kbhit()) {
393 int c = getche();
394 if (c == 'y' || c == 'Y') {
395 reg_info_.confirmation_state = RegistrationInfo::CONFIRMATION_CONFIRMED;
396 LOG(INFO) << "Registration confirmed by user.";
397 } else {
398 reg_info_.confirmation_state = RegistrationInfo::CONFIRMATION_DISCARTED;
399 LOG(INFO) << "Registration discarted by user.";
400 }
401 return;
402 }
403
404 base::MessageLoop::current()->PostDelayedTask(
405 FROM_HERE,
406 base::Bind(&Printer::WaitUserConfirmation, base::Unretained(this),
407 valid_until),
408 base::TimeDelta::FromMilliseconds(100));
409 }
410
309 std::string Printer::GenerateProxyId() const { 411 std::string Printer::GenerateProxyId() const {
310 return "{" + base::GenerateGUID() +"}"; 412 return "{" + base::GenerateGUID() +"}";
311 } 413 }
312 414
313 std::vector<std::string> Printer::CreateTxt() const { 415 std::vector<std::string> Printer::CreateTxt() const {
314 std::vector<std::string> txt; 416 std::vector<std::string> txt;
315 txt.push_back("txtvers=1"); 417 txt.push_back("txtvers=1");
316 txt.push_back("ty=" + std::string(kPrinterName)); 418 txt.push_back("ty=" + std::string(kPrinterName));
317 txt.push_back("note=" + std::string(kPrinterDescription)); 419 txt.push_back("note=" + std::string(kPrinterDescription));
318 txt.push_back("url=" + std::string(kCloudPrintUrl)); 420 txt.push_back("url=" + std::string(kCloudPrintUrl));
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 499
398 reg_info_ = RegistrationInfo(); 500 reg_info_ = RegistrationInfo();
399 reg_info_.state = RegistrationInfo::DEV_REG_REGISTERED; 501 reg_info_.state = RegistrationInfo::DEV_REG_REGISTERED;
400 reg_info_.user = user; 502 reg_info_.user = user;
401 reg_info_.device_id = device_id; 503 reg_info_.device_id = device_id;
402 reg_info_.refresh_token = refresh_token; 504 reg_info_.refresh_token = refresh_token;
403 505
404 return true; 506 return true;
405 } 507 }
406 508
509 PrivetHttpServer::RegistrationErrorStatus
510 Printer::ConfirmationToRegistrationError(
511 RegistrationInfo::ConfirmationState state) {
512 switch (state) {
513 case RegistrationInfo::CONFIRMATION_PENDING:
514 return PrivetHttpServer::REG_ERROR_PENDING_USER_ACTION;
515 case RegistrationInfo::CONFIRMATION_DISCARTED:
516 return PrivetHttpServer::REG_ERROR_USER_CANCEL;
517 case RegistrationInfo::CONFIRMATION_CONFIRMED:
518 NOTREACHED();
519 return PrivetHttpServer::REG_ERROR_OK;
520 case RegistrationInfo::CONFIRMATION_TIMEOUT:
521 return PrivetHttpServer::REG_ERROR_CONFIRMATION_TIMEOUT;
522 default:
523 NOTREACHED();
524 return PrivetHttpServer::REG_ERROR_OK;
525 }
526 }
527
OLDNEW
« no previous file with comments | « cloud_print/gcp20/prototype/printer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698