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 #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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 | |
OLD | NEW |