Chromium Code Reviews| Index: cloud_print/gcp20/prototype/printer.cc |
| diff --git a/cloud_print/gcp20/prototype/printer.cc b/cloud_print/gcp20/prototype/printer.cc |
| index 97565f551ffc7141292553cfbc5484584562fdc5..f49066419013dbd5641e3d80338b0b0c6688069e 100644 |
| --- a/cloud_print/gcp20/prototype/printer.cc |
| +++ b/cloud_print/gcp20/prototype/printer.cc |
| @@ -4,6 +4,16 @@ |
| #include "cloud_print/gcp20/prototype/printer.h" |
| +#if defined(OS_WIN) |
| +#include <conio.h> |
| +#else |
| +#include <stdio.h> |
| +#include <sys/types.h> |
| +#include <sys/time.h> |
| +#include <termios.h> |
| +#include <unistd.h> |
| +#endif // !defined(OS_WIN) |
| +#include <iostream> |
| #include <string> |
| #include <vector> |
| @@ -29,6 +39,10 @@ const char* kServiceDomainName = "my-privet-device.local"; |
| const char* kPrinterName = "Google GCP2.0 Prototype"; |
| const char* kPrinterDescription = "Printer emulator"; |
| +const char* kUserConfirmationTitle = "Confirm registration: type 'y' if you " |
| + "agree and any other for otherwise."; |
| +const uint kUserConfirmationTimeout = 10; // in seconds |
| + |
| const char* kCdd = |
| "{\n" |
| " 'version': '1.0',\n" |
| @@ -83,9 +97,56 @@ net::IPAddressNumber GetLocalIp(const std::string& interface_name, |
| return net::IPAddressNumber(); |
| } |
| +#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.
|
| + |
| +// Method for disabling buffered IO. |
| +// |true| - disable, |false| - restore previous settings. |
| +void SetTemporaryTermiosSettings(bool temporary) { |
| + static termios oldt, newt; |
| + |
| + if (temporary) { |
| + tcgetattr(STDIN_FILENO, &oldt); |
| + newt = oldt; |
| + newt.c_lflag &= ~ICANON; // Disable buffered IO. |
| + tcsetattr(STDIN_FILENO, TCSANOW, &newt); |
| + } else { |
| + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // Restore default settings. |
| + } |
| +} |
| + |
| +// Analog from conio.h |
| +int kbhit() { |
| + SetTemporaryTermiosSettings(true); |
| + |
| + timeval tv; |
| + fd_set rdfs; |
| + |
| + tv.tv_sec = 0; |
| + tv.tv_usec = 0; |
| + |
| + FD_ZERO(&rdfs); |
| + FD_SET(STDIN_FILENO, &rdfs); |
| + select(STDIN_FILENO + 1, &rdfs, NULL, NULL, &tv); |
| + SetTemporaryTermiosSettings(false); |
| + |
| + return FD_ISSET(STDIN_FILENO, &rdfs); |
| +} |
| + |
| +// Analog from conio.h |
| +int getche() { |
| + SetTemporaryTermiosSettings(true); |
| + int c = getchar(); |
| + SetTemporaryTermiosSettings(false); |
| + return c; |
| +} |
| + |
| +#endif // !defined(OS_WIN) |
| + |
| } // namespace |
| -Printer::RegistrationInfo::RegistrationInfo() : state(DEV_REG_UNREGISTERED) { |
| +Printer::RegistrationInfo::RegistrationInfo() |
| + : state(DEV_REG_UNREGISTERED), |
| + confirmation_state(CONFIRMATION_PENDING) { |
| } |
| Printer::RegistrationInfo::~RegistrationInfo() { |
| @@ -164,6 +225,14 @@ PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationStart( |
| reg_info_.user = user; |
| reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_STARTED; |
| + std::cout << kUserConfirmationTitle << std::endl; |
| + base::Time valid_until = base::Time::Now() + |
| + base::TimeDelta::FromSeconds(kUserConfirmationTimeout); |
| + base::MessageLoop::current()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&Printer::WaitUserConfirmation, |
| + base::Unretained(this), valid_until)); |
| + |
| requester_->StartRegistration(GenerateProxyId(), kPrinterName, user, kCdd); |
| return PrivetHttpServer::REG_ERROR_OK; |
| @@ -185,19 +254,20 @@ PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationGetClaimToken( |
| if (status != PrivetHttpServer::REG_ERROR_OK) |
| return status; |
| - // TODO(maksymb): Add user confirmation. |
| + if (reg_info_.state != RegistrationInfo::DEV_REG_REGISTRATION_STARTED && |
| + reg_info_.state != |
| + RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY) |
| + return PrivetHttpServer::REG_ERROR_INVALID_ACTION; |
| + |
| + if (reg_info_.confirmation_state != RegistrationInfo::CONFIRMATION_CONFIRMED) |
| + return ConfirmationToRegistrationError(reg_info_.confirmation_state); |
| if (reg_info_.state == RegistrationInfo::DEV_REG_REGISTRATION_STARTED) |
| return PrivetHttpServer::REG_ERROR_DEVICE_BUSY; |
| - if (reg_info_.state == |
| - RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY) { |
| - *token = reg_info_.registration_token; |
| - *claim_url = reg_info_.complete_invite_url; |
| - return PrivetHttpServer::REG_ERROR_OK; |
| - } |
| - |
| - return PrivetHttpServer::REG_ERROR_INVALID_ACTION; |
| + *token = reg_info_.registration_token; |
| + *claim_url = reg_info_.complete_invite_url; |
| + return PrivetHttpServer::REG_ERROR_OK; |
| } |
| PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationComplete( |
| @@ -212,9 +282,11 @@ PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationComplete( |
| return PrivetHttpServer::REG_ERROR_INVALID_ACTION; |
| } |
| + if (reg_info_.confirmation_state != RegistrationInfo::CONFIRMATION_CONFIRMED) |
| + return ConfirmationToRegistrationError(reg_info_.confirmation_state); |
| + |
| reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_COMPLETING; |
| requester_->CompleteRegistration(); |
| - |
| *device_id = reg_info_.device_id; |
| return PrivetHttpServer::REG_ERROR_OK; |
| @@ -232,6 +304,10 @@ PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationCancel( |
| return PrivetHttpServer::REG_ERROR_INVALID_ACTION; |
| reg_info_ = RegistrationInfo(); |
| + requester_.reset(new CloudPrintRequester( |
| + base::MessageLoop::current()->message_loop_proxy(), |
| + this)); // Forget all old queries. |
| + |
| return PrivetHttpServer::REG_ERROR_OK; |
| } |
| @@ -306,6 +382,32 @@ PrivetHttpServer::RegistrationErrorStatus Printer::CheckCommonRegErrors( |
| return PrivetHttpServer::REG_ERROR_OK; |
| } |
| +void Printer::WaitUserConfirmation(base::Time valid_until) { |
| + if (base::Time::Now() > valid_until) { |
| + reg_info_.confirmation_state = RegistrationInfo::CONFIRMATION_TIMEOUT; |
| + LOG(INFO) << "Confirmation timeout reached."; |
| + return; |
| + } |
| + |
| + if (kbhit()) { |
| + int c = getche(); |
| + if (c == 'y' || c == 'Y') { |
| + reg_info_.confirmation_state = RegistrationInfo::CONFIRMATION_CONFIRMED; |
| + LOG(INFO) << "Registration confirmed by user."; |
| + } else { |
| + reg_info_.confirmation_state = RegistrationInfo::CONFIRMATION_DISCARTED; |
| + LOG(INFO) << "Registration discarted by user."; |
| + } |
| + return; |
| + } |
| + |
| + base::MessageLoop::current()->PostDelayedTask( |
| + FROM_HERE, |
| + base::Bind(&Printer::WaitUserConfirmation, base::Unretained(this), |
| + valid_until), |
| + base::TimeDelta::FromMilliseconds(100)); |
| +} |
| + |
| std::string Printer::GenerateProxyId() const { |
| return "{" + base::GenerateGUID() +"}"; |
| } |
| @@ -404,3 +506,22 @@ bool Printer::LoadFromFile(const std::string& filename) { |
| return true; |
| } |
| +PrivetHttpServer::RegistrationErrorStatus |
| + Printer::ConfirmationToRegistrationError( |
| + RegistrationInfo::ConfirmationState state) { |
| + switch (state) { |
| + case RegistrationInfo::CONFIRMATION_PENDING: |
| + return PrivetHttpServer::REG_ERROR_PENDING_USER_ACTION; |
| + case RegistrationInfo::CONFIRMATION_DISCARTED: |
| + return PrivetHttpServer::REG_ERROR_USER_CANCEL; |
| + case RegistrationInfo::CONFIRMATION_CONFIRMED: |
| + NOTREACHED(); |
| + return PrivetHttpServer::REG_ERROR_OK; |
| + case RegistrationInfo::CONFIRMATION_TIMEOUT: |
| + return PrivetHttpServer::REG_ERROR_CONFIRMATION_TIMEOUT; |
| + default: |
| + NOTREACHED(); |
| + return PrivetHttpServer::REG_ERROR_OK; |
| + } |
| +} |
| + |