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; |
+ } |
+} |
+ |