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 <stdio.h> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 24 matching lines...) Expand all Loading... |
35 const char kServiceDomainNameDefault[] = "my-privet-device.local"; | 35 const char kServiceDomainNameDefault[] = "my-privet-device.local"; |
36 | 36 |
37 const char kPrinterName[] = "Google GCP2.0 Prototype"; | 37 const char kPrinterName[] = "Google GCP2.0 Prototype"; |
38 const char kPrinterDescription[] = "Printer emulator"; | 38 const char kPrinterDescription[] = "Printer emulator"; |
39 | 39 |
40 const char kUserConfirmationTitle[] = "Confirm registration: type 'y' if you " | 40 const char kUserConfirmationTitle[] = "Confirm registration: type 'y' if you " |
41 "agree and any other to discard\n"; | 41 "agree and any other to discard\n"; |
42 const int64 kUserConfirmationTimeout = 30; // in seconds | 42 const int64 kUserConfirmationTimeout = 30; // in seconds |
43 | 43 |
44 const uint32 kReconnectTimeout = 5; // in seconds | 44 const uint32 kReconnectTimeout = 5; // in seconds |
45 const uint32 kPrintJobsTimeout = 10; // in seconds | 45 |
| 46 const double kTimeToNextAccessTokenUpdate = 0.8; // relatively to living time. |
46 | 47 |
47 const char kCdd[] = | 48 const char kCdd[] = |
48 "{\n" | 49 "{\n" |
49 " 'version': '1.0',\n" | 50 " 'version': '1.0',\n" |
50 " 'printer': {\n" | 51 " 'printer': {\n" |
51 " 'vendor_capability': [\n" | 52 " 'vendor_capability': [\n" |
52 " {\n" | 53 " {\n" |
53 " 'id': 'psk:MediaType',\n" | 54 " 'id': 'psk:MediaType',\n" |
54 " 'display_name': 'Media Type',\n" | 55 " 'display_name': 'Media Type',\n" |
55 " 'type': 'SELECT',\n" | 56 " 'type': 'SELECT',\n" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 if (iter->address.size() == expected_address_size && | 92 if (iter->address.size() == expected_address_size && |
92 (interface_name.empty() || interface_name == iter->name)) { | 93 (interface_name.empty() || interface_name == iter->name)) { |
93 LOG(INFO) << net::IPAddressToString(iter->address); | 94 LOG(INFO) << net::IPAddressToString(iter->address); |
94 return iter->address; | 95 return iter->address; |
95 } | 96 } |
96 } | 97 } |
97 | 98 |
98 return net::IPAddressNumber(); | 99 return net::IPAddressNumber(); |
99 } | 100 } |
100 | 101 |
| 102 scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() { |
| 103 return base::MessageLoop::current()->message_loop_proxy(); |
| 104 } |
| 105 |
101 } // namespace | 106 } // namespace |
102 | 107 |
103 using cloud_print_response_parser::Job; | 108 using cloud_print_response_parser::Job; |
104 | 109 |
105 Printer::RegistrationInfo::RegistrationInfo() | 110 Printer::RegistrationInfo::RegistrationInfo() |
106 : state(DEV_REG_UNREGISTERED), | 111 : state(DEV_REG_UNREGISTERED), |
107 confirmation_state(CONFIRMATION_PENDING) { | 112 confirmation_state(CONFIRMATION_PENDING) { |
108 } | 113 } |
109 | 114 |
110 Printer::RegistrationInfo::~RegistrationInfo() { | 115 Printer::RegistrationInfo::~RegistrationInfo() { |
111 } | 116 } |
112 | 117 |
113 Printer::Printer() : http_server_(this), connection_state_(OFFLINE) { | 118 Printer::Printer() |
| 119 : http_server_(this), |
| 120 connection_state_(OFFLINE), |
| 121 on_idle_posted_(false), |
| 122 pending_local_settings_check_(false), |
| 123 pending_print_jobs_check_(false) { |
114 } | 124 } |
115 | 125 |
116 Printer::~Printer() { | 126 Printer::~Printer() { |
117 Stop(); | 127 Stop(); |
118 } | 128 } |
119 | 129 |
120 bool Printer::Start() { | 130 bool Printer::Start() { |
121 if (IsOnline()) | 131 if (IsRunning()) |
122 return true; | 132 return true; |
123 | 133 |
124 // TODO(maksymb): Add switch for command line to control interface name. | 134 // TODO(maksymb): Add switch for command line to control interface name. |
125 net::IPAddressNumber ip = GetLocalIp("", false); | 135 net::IPAddressNumber ip = GetLocalIp("", false); |
126 if (ip.empty()) { | 136 if (ip.empty()) { |
127 LOG(ERROR) << "No local IP found. Cannot start printer."; | 137 LOG(ERROR) << "No local IP found. Cannot start printer."; |
128 return false; | 138 return false; |
129 } | 139 } |
130 VLOG(1) << "Local address: " << net::IPAddressToString(ip); | 140 VLOG(1) << "Local address: " << net::IPAddressToString(ip); |
131 | 141 |
(...skipping 13 matching lines...) Expand all Loading... |
145 command_line_reader::ReadDomainName(kServiceDomainNameDefault); | 155 command_line_reader::ReadDomainName(kServiceDomainNameDefault); |
146 if (!dns_server_.Start( | 156 if (!dns_server_.Start( |
147 ServiceParameters(kServiceType, service_name_prefix, service_domain_name, | 157 ServiceParameters(kServiceType, service_name_prefix, service_domain_name, |
148 ip, port), | 158 ip, port), |
149 command_line_reader::ReadTtl(kTtlDefault), | 159 command_line_reader::ReadTtl(kTtlDefault), |
150 CreateTxt())) { | 160 CreateTxt())) { |
151 http_server_.Shutdown(); | 161 http_server_.Shutdown(); |
152 return false; | 162 return false; |
153 } | 163 } |
154 | 164 |
155 // Creating Cloud Requester. | 165 print_job_handler_.reset(new PrintJobHandler); |
156 requester_.reset( | |
157 new CloudPrintRequester( | |
158 base::MessageLoop::current()->message_loop_proxy(), | |
159 this)); | |
160 | |
161 xtoken_ = XPrivetToken(); | 166 xtoken_ = XPrivetToken(); |
162 starttime_ = base::Time::Now(); | 167 starttime_ = base::Time::Now(); |
163 | 168 |
164 print_job_handler_.reset(new PrintJobHandler); | 169 TryConnect(); |
165 connection_state_ = CONNECTING; | |
166 WakeUp(); | |
167 | |
168 return true; | 170 return true; |
169 } | 171 } |
170 | 172 |
171 bool Printer::IsOnline() const { | 173 bool Printer::IsRunning() const { |
172 return requester_; | 174 return print_job_handler_; |
173 } | |
174 | |
175 void Printer::WakeUp() { | |
176 VLOG(3) << "Function: " << __FUNCTION__; | |
177 | |
178 if (!IsRegistered()) | |
179 return; | |
180 | |
181 FetchPrintJobs(); | |
182 } | 175 } |
183 | 176 |
184 void Printer::Stop() { | 177 void Printer::Stop() { |
185 dns_server_.Shutdown(); | 178 dns_server_.Shutdown(); |
186 http_server_.Shutdown(); | 179 http_server_.Shutdown(); |
187 requester_.reset(); | 180 requester_.reset(); |
188 print_job_handler_.reset(); | 181 print_job_handler_.reset(); |
| 182 xmpp_listener_.reset(); |
| 183 } |
| 184 |
| 185 void Printer::OnAuthError() { |
| 186 access_token_update_ = base::Time::Now(); |
| 187 ChangeState(OFFLINE); |
| 188 // TODO(maksymb): Implement *instant* updating of access_token. |
| 189 } |
| 190 |
| 191 std::string Printer::GetAccessToken() { |
| 192 return access_token_; |
189 } | 193 } |
190 | 194 |
191 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationStart( | 195 PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationStart( |
192 const std::string& user) { | 196 const std::string& user) { |
193 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); | 197 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); |
194 if (status != PrivetHttpServer::REG_ERROR_OK) | 198 if (status != PrivetHttpServer::REG_ERROR_OK) |
195 return status; | 199 return status; |
196 | 200 |
197 if (reg_info_.state != RegistrationInfo::DEV_REG_UNREGISTERED) | 201 if (reg_info_.state != RegistrationInfo::DEV_REG_UNREGISTERED) |
198 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; | 202 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); | 282 PrivetHttpServer::RegistrationErrorStatus status = CheckCommonRegErrors(user); |
279 if (status != PrivetHttpServer::REG_ERROR_OK && | 283 if (status != PrivetHttpServer::REG_ERROR_OK && |
280 status != PrivetHttpServer::REG_ERROR_SERVER_ERROR) { | 284 status != PrivetHttpServer::REG_ERROR_SERVER_ERROR) { |
281 return status; | 285 return status; |
282 } | 286 } |
283 | 287 |
284 if (reg_info_.state == RegistrationInfo::DEV_REG_UNREGISTERED) | 288 if (reg_info_.state == RegistrationInfo::DEV_REG_UNREGISTERED) |
285 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; | 289 return PrivetHttpServer::REG_ERROR_INVALID_ACTION; |
286 | 290 |
287 reg_info_ = RegistrationInfo(); | 291 reg_info_ = RegistrationInfo(); |
288 requester_.reset(new CloudPrintRequester( | 292 requester_.reset(new CloudPrintRequester(GetTaskRunner(), this)); |
289 base::MessageLoop::current()->message_loop_proxy(), | |
290 this)); // Forget all old queries. | |
291 | 293 |
292 return PrivetHttpServer::REG_ERROR_OK; | 294 return PrivetHttpServer::REG_ERROR_OK; |
293 } | 295 } |
294 | 296 |
295 void Printer::GetRegistrationServerError(std::string* description) { | 297 void Printer::GetRegistrationServerError(std::string* description) { |
296 DCHECK_EQ(reg_info_.state, RegistrationInfo::DEV_REG_REGISTRATION_ERROR) << | 298 DCHECK_EQ(reg_info_.state, RegistrationInfo::DEV_REG_REGISTRATION_ERROR) << |
297 "Method shouldn't be called when not needed."; | 299 "Method shouldn't be called when not needed."; |
298 | 300 |
299 *description = reg_info_.error_description; | 301 *description = reg_info_.error_description; |
300 } | 302 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 void Printer::OnRegistrationStartResponseParsed( | 337 void Printer::OnRegistrationStartResponseParsed( |
336 const std::string& registration_token, | 338 const std::string& registration_token, |
337 const std::string& complete_invite_url, | 339 const std::string& complete_invite_url, |
338 const std::string& device_id) { | 340 const std::string& device_id) { |
339 reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY; | 341 reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY; |
340 reg_info_.device_id = device_id; | 342 reg_info_.device_id = device_id; |
341 reg_info_.registration_token = registration_token; | 343 reg_info_.registration_token = registration_token; |
342 reg_info_.complete_invite_url = complete_invite_url; | 344 reg_info_.complete_invite_url = complete_invite_url; |
343 } | 345 } |
344 | 346 |
345 void Printer::OnGetAuthCodeResponseParsed(const std::string& refresh_token) { | 347 void Printer::OnGetAuthCodeResponseParsed(const std::string& refresh_token, |
| 348 const std::string& access_token, |
| 349 int access_token_expires_in_seconds) { |
346 reg_info_.state = RegistrationInfo::DEV_REG_REGISTERED; | 350 reg_info_.state = RegistrationInfo::DEV_REG_REGISTERED; |
347 reg_info_.refresh_token = refresh_token; | 351 reg_info_.refresh_token = refresh_token; |
348 SaveToFile(base::FilePath(kPrinterStatePath)); | 352 RememberAccessToken(access_token, access_token_expires_in_seconds); |
349 FetchPrintJobs(); | 353 |
| 354 ConnectXmpp(); |
| 355 } |
| 356 |
| 357 void Printer::OnAccesstokenReceviced(const std::string& access_token, |
| 358 int expires_in_seconds) { |
| 359 VLOG(3) << "Function: " << __FUNCTION__; |
| 360 RememberAccessToken(access_token, expires_in_seconds); |
| 361 switch (connection_state_) { |
| 362 case ONLINE: |
| 363 PostOnIdle(); |
| 364 break; |
| 365 |
| 366 case CONNECTING: |
| 367 TryConnect(); |
| 368 break; |
| 369 |
| 370 default: |
| 371 NOTREACHED(); |
| 372 } |
| 373 } |
| 374 |
| 375 void Printer::OnXmppJidReceived(const std::string& xmpp_jid) { |
| 376 reg_info_.xmpp_jid = xmpp_jid; |
350 } | 377 } |
351 | 378 |
352 void Printer::OnRegistrationError(const std::string& description) { | 379 void Printer::OnRegistrationError(const std::string& description) { |
353 LOG(ERROR) << "server_error: " << description; | 380 LOG(ERROR) << "server_error: " << description; |
354 | 381 |
355 // TODO(maksymb): Implement waiting after error and timeout of registration. | 382 // TODO(maksymb): Implement waiting after error and timeout of registration. |
356 reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_ERROR; | 383 reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_ERROR; |
357 reg_info_.error_description = description; | 384 reg_info_.error_description = description; |
358 } | 385 } |
359 | 386 |
| 387 void Printer::OnNetworkError() { |
| 388 VLOG(3) << "Function: " << __FUNCTION__; |
| 389 ChangeState(OFFLINE); |
| 390 } |
| 391 |
360 void Printer::OnServerError(const std::string& description) { | 392 void Printer::OnServerError(const std::string& description) { |
361 VLOG(3) << "Function: " << __FUNCTION__; | 393 VLOG(3) << "Function: " << __FUNCTION__; |
362 LOG(ERROR) << "Server error: " << description; | 394 LOG(ERROR) << "Server error: " << description; |
363 | 395 |
364 PostDelayedWakeUp(base::TimeDelta::FromSeconds(kReconnectTimeout)); | |
365 } | |
366 | |
367 void Printer::OnNetworkError() { | |
368 VLOG(3) << "Function: " << __FUNCTION__; | |
369 ChangeState(OFFLINE); | 396 ChangeState(OFFLINE); |
370 PostDelayedWakeUp(base::TimeDelta::FromSeconds(kReconnectTimeout)); | |
371 } | 397 } |
372 | 398 |
373 void Printer::OnPrintJobsAvailable(const std::vector<Job>& jobs) { | 399 void Printer::OnPrintJobsAvailable(const std::vector<Job>& jobs) { |
374 VLOG(3) << "Function: " << __FUNCTION__; | 400 VLOG(3) << "Function: " << __FUNCTION__; |
375 ChangeState(ONLINE); | |
376 | 401 |
377 LOG(INFO) << "Available printjobs: " << jobs.size(); | 402 LOG(INFO) << "Available printjobs: " << jobs.size(); |
378 | 403 |
379 if (jobs.empty()) { | 404 if (jobs.empty()) { |
380 PostDelayedWakeUp(base::TimeDelta::FromSeconds(kPrintJobsTimeout)); | 405 pending_print_jobs_check_ = false; |
| 406 PostOnIdle(); |
381 return; | 407 return; |
382 } | 408 } |
383 | 409 |
384 // TODO(maksymb): After finishing XMPP add 'Printjobs available' flag. | 410 LOG(INFO) << "Downloading printjob."; |
385 LOG(INFO) << "Downloading first printjob."; | |
386 requester_->RequestPrintJob(jobs[0]); | 411 requester_->RequestPrintJob(jobs[0]); |
387 return; | 412 return; |
388 } | 413 } |
389 | 414 |
390 void Printer::OnPrintJobDownloaded(const Job& job) { | 415 void Printer::OnPrintJobDownloaded(const Job& job) { |
391 VLOG(3) << "Function: " << __FUNCTION__; | 416 VLOG(3) << "Function: " << __FUNCTION__; |
392 print_job_handler_->SavePrintJob( | 417 print_job_handler_->SavePrintJob( |
393 job.file, | 418 job.file, |
394 job.ticket, | 419 job.ticket, |
395 base::StringPrintf("%s.%s", job.create_time.c_str(), job.job_id.c_str()), | 420 base::StringPrintf("%s.%s", job.create_time.c_str(), job.job_id.c_str()), |
396 job.title); | 421 job.title); |
397 requester_->SendPrintJobDone(job.job_id); | 422 requester_->SendPrintJobDone(job.job_id); |
398 } | 423 } |
399 | 424 |
400 void Printer::OnPrintJobDone() { | 425 void Printer::OnPrintJobDone() { |
401 VLOG(3) << "Function: " << __FUNCTION__; | 426 VLOG(3) << "Function: " << __FUNCTION__; |
402 // TODO(maksymb): Replace PostTask with with XMPP notifications. | 427 PostOnIdle(); |
403 PostWakeUp(); | 428 } |
| 429 |
| 430 void Printer::OnXmppConnected() { |
| 431 pending_local_settings_check_ = true; |
| 432 pending_print_jobs_check_ = true; |
| 433 ChangeState(ONLINE); |
| 434 PostOnIdle(); |
| 435 } |
| 436 |
| 437 void Printer::OnXmppAuthError() { |
| 438 OnAuthError(); |
| 439 } |
| 440 |
| 441 void Printer::OnXmppNetworkError() { |
| 442 ChangeState(OFFLINE); |
| 443 } |
| 444 |
| 445 void Printer::OnXmppNewPrintJob(const std::string& device_id) { |
| 446 DCHECK_EQ(reg_info_.device_id, device_id) << "Data should contain printer_id"; |
| 447 pending_print_jobs_check_ = true; |
| 448 } |
| 449 |
| 450 void Printer::OnXmppNewLocalSettings(const std::string& device_id) { |
| 451 DCHECK_EQ(reg_info_.device_id, device_id) << "Data should contain printer_id"; |
| 452 NOTIMPLEMENTED(); |
| 453 } |
| 454 |
| 455 void Printer::OnXmppDeleteNotification(const std::string& device_id) { |
| 456 DCHECK_EQ(reg_info_.device_id, device_id) << "Data should contain printer_id"; |
| 457 NOTIMPLEMENTED(); |
| 458 } |
| 459 |
| 460 void Printer::TryConnect() { |
| 461 VLOG(3) << "Function: " << __FUNCTION__; |
| 462 |
| 463 ChangeState(CONNECTING); |
| 464 if (!requester_) |
| 465 requester_.reset(new CloudPrintRequester(GetTaskRunner(), this)); |
| 466 |
| 467 if (IsRegistered()) { |
| 468 if (access_token_update_ < base::Time::Now()) { |
| 469 requester_->UpdateAccesstoken(reg_info_.refresh_token); |
| 470 } else { |
| 471 ConnectXmpp(); |
| 472 } |
| 473 } else { |
| 474 // TODO(maksymb): Ping google.com to check connection state. |
| 475 ChangeState(ONLINE); |
| 476 } |
| 477 } |
| 478 |
| 479 void Printer::ConnectXmpp() { |
| 480 xmpp_listener_.reset( |
| 481 new CloudPrintXmppListener(reg_info_.xmpp_jid, GetTaskRunner(), this)); |
| 482 xmpp_listener_->Connect(access_token_); |
| 483 } |
| 484 |
| 485 void Printer::OnIdle() { |
| 486 DCHECK(IsRegistered()); |
| 487 DCHECK(on_idle_posted_) << "Instant call is not allowed"; |
| 488 on_idle_posted_ = false; |
| 489 |
| 490 if (connection_state_ != ONLINE) |
| 491 return; |
| 492 |
| 493 if (access_token_update_ < base::Time::Now()) { |
| 494 requester_->UpdateAccesstoken(reg_info_.refresh_token); |
| 495 return; |
| 496 } |
| 497 |
| 498 // TODO(maksymb): Check if privet-accesstoken was requested. |
| 499 |
| 500 // TODO(maksymb): Check if local-printing was requested. |
| 501 |
| 502 if (pending_local_settings_check_) { |
| 503 GetLocalSettings(); |
| 504 return; |
| 505 } |
| 506 |
| 507 if (pending_print_jobs_check_) { |
| 508 FetchPrintJobs(); |
| 509 return; |
| 510 } |
| 511 |
| 512 base::MessageLoop::current()->PostDelayedTask( |
| 513 FROM_HERE, |
| 514 base::Bind(&Printer::PostOnIdle, AsWeakPtr()), |
| 515 base::TimeDelta::FromMilliseconds(1000)); |
| 516 } |
| 517 |
| 518 void Printer::GetLocalSettings() { |
| 519 DCHECK(IsRegistered()); |
| 520 |
| 521 pending_local_settings_check_ = false; |
| 522 PostOnIdle(); |
| 523 } |
| 524 |
| 525 void Printer::FetchPrintJobs() { |
| 526 VLOG(3) << "Function: " << __FUNCTION__; |
| 527 |
| 528 DCHECK(IsRegistered()); |
| 529 requester_->FetchPrintJobs(reg_info_.device_id); |
| 530 } |
| 531 |
| 532 void Printer::RememberAccessToken(const std::string& access_token, |
| 533 int expires_in_seconds) { |
| 534 using base::Time; |
| 535 using base::TimeDelta; |
| 536 access_token_ = access_token; |
| 537 int64 time_to_update = static_cast<int64>(expires_in_seconds * |
| 538 kTimeToNextAccessTokenUpdate); |
| 539 access_token_update_ = Time::Now() + TimeDelta::FromSeconds(time_to_update); |
| 540 VLOG(1) << "Current access_token: " << access_token; |
| 541 SaveToFile(base::FilePath(kPrinterStatePath)); |
404 } | 542 } |
405 | 543 |
406 PrivetHttpServer::RegistrationErrorStatus Printer::CheckCommonRegErrors( | 544 PrivetHttpServer::RegistrationErrorStatus Printer::CheckCommonRegErrors( |
407 const std::string& user) const { | 545 const std::string& user) const { |
408 DCHECK(!IsRegistered()); | 546 DCHECK(!IsRegistered()); |
409 | 547 |
410 if (reg_info_.state != RegistrationInfo::DEV_REG_UNREGISTERED && | 548 if (reg_info_.state != RegistrationInfo::DEV_REG_UNREGISTERED && |
411 user != reg_info_.user) { | 549 user != reg_info_.user) { |
412 return PrivetHttpServer::REG_ERROR_DEVICE_BUSY; | 550 return PrivetHttpServer::REG_ERROR_DEVICE_BUSY; |
413 } | 551 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 txt.push_back("ty=" + std::string(kPrinterName)); | 591 txt.push_back("ty=" + std::string(kPrinterName)); |
454 txt.push_back("note=" + std::string(kPrinterDescription)); | 592 txt.push_back("note=" + std::string(kPrinterDescription)); |
455 txt.push_back("url=" + std::string(kCloudPrintUrl)); | 593 txt.push_back("url=" + std::string(kCloudPrintUrl)); |
456 txt.push_back("type=printer"); | 594 txt.push_back("type=printer"); |
457 txt.push_back("id=" + reg_info_.device_id); | 595 txt.push_back("id=" + reg_info_.device_id); |
458 txt.push_back("cs=" + ConnectionStateToString(connection_state_)); | 596 txt.push_back("cs=" + ConnectionStateToString(connection_state_)); |
459 | 597 |
460 return txt; | 598 return txt; |
461 } | 599 } |
462 | 600 |
463 void Printer::FetchPrintJobs() { | |
464 VLOG(3) << "Function: " << __FUNCTION__; | |
465 | |
466 if (!IsRegistered()) | |
467 return; | |
468 | |
469 if (requester_->IsBusy()) { | |
470 PostDelayedWakeUp(base::TimeDelta::FromSeconds(kReconnectTimeout)); | |
471 } else { | |
472 requester_->FetchPrintJobs(reg_info_.refresh_token, reg_info_.device_id); | |
473 } | |
474 } | |
475 | |
476 void Printer::SaveToFile(const base::FilePath& file_path) const { | 601 void Printer::SaveToFile(const base::FilePath& file_path) const { |
477 base::DictionaryValue json; | 602 base::DictionaryValue json; |
478 // TODO(maksymb): Get rid of in-place constants. | 603 // TODO(maksymb): Get rid of in-place constants. |
479 if (IsRegistered()) { | 604 if (IsRegistered()) { |
480 json.SetBoolean("registered", true); | 605 json.SetBoolean("registered", true); |
481 json.SetString("user", reg_info_.user); | 606 json.SetString("user", reg_info_.user); |
482 json.SetString("device_id", reg_info_.device_id); | 607 json.SetString("device_id", reg_info_.device_id); |
483 json.SetString("refresh_token", reg_info_.refresh_token); | 608 json.SetString("refresh_token", reg_info_.refresh_token); |
| 609 json.SetString("xmpp_jid", reg_info_.xmpp_jid); |
| 610 json.SetString("access_token", access_token_); |
| 611 json.SetInteger("access_token_update", |
| 612 static_cast<int>(access_token_update_.ToTimeT())); |
484 } else { | 613 } else { |
485 json.SetBoolean("registered", false); | 614 json.SetBoolean("registered", false); |
486 } | 615 } |
487 | 616 |
488 std::string json_str; | 617 std::string json_str; |
489 base::JSONWriter::WriteWithOptions(&json, | 618 base::JSONWriter::WriteWithOptions(&json, |
490 base::JSONWriter::OPTIONS_PRETTY_PRINT, | 619 base::JSONWriter::OPTIONS_PRETTY_PRINT, |
491 &json_str); | 620 &json_str); |
492 if (!file_util::WriteFile(file_path, json_str.data(), | 621 if (!file_util::WriteFile(file_path, json_str.data(), |
493 static_cast<int>(json_str.size()))) { | 622 static_cast<int>(json_str.size()))) { |
494 LOG(ERROR) << "Cannot write state."; | 623 LOG(ERROR) << "Cannot write state."; |
495 } | 624 } |
496 LOG(INFO) << "State written to file."; | 625 LOG(INFO) << "State written to file."; |
497 } | 626 } |
498 | 627 |
499 bool Printer::LoadFromFile(const base::FilePath& file_path) { | 628 bool Printer::LoadFromFile(const base::FilePath& file_path) { |
500 if (!base::PathExists(file_path)) { | 629 if (!base::PathExists(file_path)) |
501 LOG(INFO) << "Registration info is not found. Printer is unregistered."; | |
502 return false; | 630 return false; |
503 } | |
504 | 631 |
505 LOG(INFO) << "Loading registration info from file."; | 632 LOG(INFO) << "Loading registration info from file."; |
506 std::string json_str; | 633 std::string json_str; |
507 if (!file_util::ReadFileToString(file_path, &json_str)) { | 634 if (!file_util::ReadFileToString(file_path, &json_str)) { |
508 LOG(ERROR) << "Cannot open file."; | 635 LOG(ERROR) << "Cannot open file."; |
509 return false; | 636 return false; |
510 } | 637 } |
511 | 638 |
512 scoped_ptr<base::Value> json_val(base::JSONReader::Read(json_str)); | 639 scoped_ptr<base::Value> json_val(base::JSONReader::Read(json_str)); |
513 base::DictionaryValue* json = NULL; | 640 base::DictionaryValue* json = NULL; |
(...skipping 24 matching lines...) Expand all Loading... |
538 LOG(ERROR) << "Cannot parse |device_id|."; | 665 LOG(ERROR) << "Cannot parse |device_id|."; |
539 return false; | 666 return false; |
540 } | 667 } |
541 | 668 |
542 std::string refresh_token; | 669 std::string refresh_token; |
543 if (!json->GetString("refresh_token", &refresh_token)) { | 670 if (!json->GetString("refresh_token", &refresh_token)) { |
544 LOG(ERROR) << "Cannot parse |refresh_token|."; | 671 LOG(ERROR) << "Cannot parse |refresh_token|."; |
545 return false; | 672 return false; |
546 } | 673 } |
547 | 674 |
| 675 std::string xmpp_jid; |
| 676 if (!json->GetString("xmpp_jid", &xmpp_jid)) { |
| 677 LOG(ERROR) << "Cannot parse |xmpp_jid|."; |
| 678 return false; |
| 679 } |
| 680 |
| 681 std::string access_token; |
| 682 if (!json->GetString("access_token", &access_token)) { |
| 683 LOG(ERROR) << "Cannot parse |access_token|."; |
| 684 return false; |
| 685 } |
| 686 |
| 687 int access_token_update; |
| 688 if (!json->GetInteger("access_token_update", &access_token_update)) { |
| 689 LOG(ERROR) << "Cannot parse |access_token_update|."; |
| 690 return false; |
| 691 } |
| 692 |
548 reg_info_ = RegistrationInfo(); | 693 reg_info_ = RegistrationInfo(); |
549 reg_info_.state = RegistrationInfo::DEV_REG_REGISTERED; | 694 reg_info_.state = RegistrationInfo::DEV_REG_REGISTERED; |
550 reg_info_.user = user; | 695 reg_info_.user = user; |
551 reg_info_.device_id = device_id; | 696 reg_info_.device_id = device_id; |
552 reg_info_.refresh_token = refresh_token; | 697 reg_info_.refresh_token = refresh_token; |
| 698 reg_info_.xmpp_jid = xmpp_jid; |
| 699 using base::Time; |
| 700 access_token_ = access_token; |
| 701 access_token_update_ = Time::FromTimeT(access_token_update); |
553 | 702 |
554 return true; | 703 return true; |
555 } | 704 } |
556 | 705 |
557 void Printer::PostWakeUp() { | 706 void Printer::PostOnIdle() { |
558 VLOG(3) << "Function: " << __FUNCTION__; | 707 VLOG(3) << "Function: " << __FUNCTION__; |
| 708 DCHECK(!on_idle_posted_) << "Only one instance can be posted."; |
| 709 on_idle_posted_ = true; |
| 710 |
559 base::MessageLoop::current()->PostTask( | 711 base::MessageLoop::current()->PostTask( |
560 FROM_HERE, | 712 FROM_HERE, |
561 base::Bind(&Printer::WakeUp, AsWeakPtr())); | 713 base::Bind(&Printer::OnIdle, AsWeakPtr())); |
562 } | |
563 | |
564 void Printer::PostDelayedWakeUp(const base::TimeDelta& delay) { | |
565 VLOG(3) << "Function: " << __FUNCTION__; | |
566 base::MessageLoop::current()->PostDelayedTask( | |
567 FROM_HERE, | |
568 base::Bind(&Printer::WakeUp, AsWeakPtr()), | |
569 delay); | |
570 } | 714 } |
571 | 715 |
572 PrivetHttpServer::RegistrationErrorStatus | 716 PrivetHttpServer::RegistrationErrorStatus |
573 Printer::ConfirmationToRegistrationError( | 717 Printer::ConfirmationToRegistrationError( |
574 RegistrationInfo::ConfirmationState state) { | 718 RegistrationInfo::ConfirmationState state) { |
575 switch (state) { | 719 switch (state) { |
576 case RegistrationInfo::CONFIRMATION_PENDING: | 720 case RegistrationInfo::CONFIRMATION_PENDING: |
577 return PrivetHttpServer::REG_ERROR_PENDING_USER_ACTION; | 721 return PrivetHttpServer::REG_ERROR_PENDING_USER_ACTION; |
578 case RegistrationInfo::CONFIRMATION_DISCARDED: | 722 case RegistrationInfo::CONFIRMATION_DISCARDED: |
579 return PrivetHttpServer::REG_ERROR_USER_CANCEL; | 723 return PrivetHttpServer::REG_ERROR_USER_CANCEL; |
(...skipping 22 matching lines...) Expand all Loading... |
602 default: | 746 default: |
603 NOTREACHED(); | 747 NOTREACHED(); |
604 return ""; | 748 return ""; |
605 } | 749 } |
606 } | 750 } |
607 | 751 |
608 bool Printer::ChangeState(ConnectionState new_state) { | 752 bool Printer::ChangeState(ConnectionState new_state) { |
609 if (connection_state_ == new_state) | 753 if (connection_state_ == new_state) |
610 return false; | 754 return false; |
611 | 755 |
612 VLOG(1) << "Printer is now " << ConnectionStateToString(new_state); | |
613 connection_state_ = new_state; | 756 connection_state_ = new_state; |
| 757 LOG(INFO) << base::StringPrintf( |
| 758 "Printer is now %s (%s)", |
| 759 ConnectionStateToString(connection_state_).c_str(), |
| 760 IsRegistered() ? "registered" : "unregistered"); |
| 761 |
614 dns_server_.UpdateMetadata(CreateTxt()); | 762 dns_server_.UpdateMetadata(CreateTxt()); |
| 763 |
| 764 switch (connection_state_) { |
| 765 case CONNECTING: |
| 766 break; |
| 767 |
| 768 case ONLINE: |
| 769 break; |
| 770 |
| 771 case OFFLINE: |
| 772 requester_.reset(); |
| 773 xmpp_listener_.reset(); |
| 774 base::MessageLoop::current()->PostDelayedTask( |
| 775 FROM_HERE, |
| 776 base::Bind(&Printer::TryConnect, AsWeakPtr()), |
| 777 base::TimeDelta::FromSeconds(kReconnectTimeout)); |
| 778 |
| 779 case NOT_CONFIGURED: |
| 780 break; |
| 781 |
| 782 default: |
| 783 NOTREACHED(); |
| 784 } |
| 785 |
615 return true; | 786 return true; |
616 } | 787 } |
617 | 788 |
OLD | NEW |