Index: cloud_print/gcp20/prototype/printer.cc |
diff --git a/cloud_print/gcp20/prototype/printer.cc b/cloud_print/gcp20/prototype/printer.cc |
index 04d306607457f13abc6dd053b5ef68ca475df385..0aaf65205d9c4aae717c8a1f972139a754a9bfac 100644 |
--- a/cloud_print/gcp20/prototype/printer.cc |
+++ b/cloud_print/gcp20/prototype/printer.cc |
@@ -4,6 +4,7 @@ |
#include "cloud_print/gcp20/prototype/printer.h" |
+#include <stdio.h> |
#include <string> |
#include <vector> |
@@ -15,6 +16,7 @@ |
#include "base/strings/string_number_conversions.h" |
#include "cloud_print/gcp20/prototype/command_line_reader.h" |
#include "cloud_print/gcp20/prototype/service_parameters.h" |
+#include "cloud_print/gcp20/prototype/special_io.h" |
#include "net/base/net_util.h" |
#include "net/base/url_util.h" |
@@ -23,14 +25,18 @@ const base::FilePath::CharType kPrinterStatePath[] = |
namespace { |
-const char* kServiceType = "_privet._tcp.local"; |
-const char* kServiceNamePrefix = "first_gcp20_device"; |
-const char* kServiceDomainName = "my-privet-device.local"; |
+const char kServiceType[] = "_privet._tcp.local"; |
+const char kServiceNamePrefix[] = "first_gcp20_device"; |
+const char kServiceDomainName[] = "my-privet-device.local"; |
-const char* kPrinterName = "Google GCP2.0 Prototype"; |
-const char* kPrinterDescription = "Printer emulator"; |
+const char kPrinterName[] = "Google GCP2.0 Prototype"; |
+const char kPrinterDescription[] = "Printer emulator"; |
-const char* kCdd = |
+const char kUserConfirmationTitle[] = "Confirm registration: type 'y' if you " |
+ "agree and any other to discard\n"; |
+const int64 kUserConfirmationTimeout = 30; // in seconds |
+ |
+const char kCdd[] = |
"{\n" |
" 'version': '1.0',\n" |
" 'printer': {\n" |
@@ -86,7 +92,9 @@ net::IPAddressNumber GetLocalIp(const std::string& interface_name, |
} // namespace |
-Printer::RegistrationInfo::RegistrationInfo() : state(DEV_REG_UNREGISTERED) { |
+Printer::RegistrationInfo::RegistrationInfo() |
+ : state(DEV_REG_UNREGISTERED), |
+ confirmation_state(CONFIRMATION_PENDING) { |
} |
Printer::RegistrationInfo::~RegistrationInfo() { |
@@ -165,6 +173,13 @@ PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationStart( |
reg_info_.user = user; |
reg_info_.state = RegistrationInfo::DEV_REG_REGISTRATION_STARTED; |
+ printf(kUserConfirmationTitle); |
+ base::Time valid_until = base::Time::Now() + |
+ base::TimeDelta::FromSeconds(kUserConfirmationTimeout); |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&Printer::WaitUserConfirmation, AsWeakPtr(), valid_until)); |
+ |
requester_->StartRegistration(GenerateProxyId(), kPrinterName, user, kCdd); |
return PrivetHttpServer::REG_ERROR_OK; |
@@ -186,19 +201,29 @@ PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationGetClaimToken( |
if (status != PrivetHttpServer::REG_ERROR_OK) |
return status; |
- // TODO(maksymb): Add user confirmation. |
+ // Check if |action=start| was called, but |action=complete| wasn't. |
+ 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 |action=getClaimToken| is valid in this state (was checked above) then |
+ // check confirmation status. |
+ if (reg_info_.confirmation_state != RegistrationInfo::CONFIRMATION_CONFIRMED) |
+ return ConfirmationToRegistrationError(reg_info_.confirmation_state); |
+ |
+ // If reply wasn't received yet, reply with |device_busy| error. |
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; |
- } |
+ DCHECK_EQ(reg_info_.state, |
+ RegistrationInfo::DEV_REG_REGISTRATION_CLAIM_TOKEN_READY); |
+ DCHECK_EQ(reg_info_.confirmation_state, |
+ RegistrationInfo::CONFIRMATION_CONFIRMED); |
- 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( |
@@ -213,9 +238,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; |
@@ -233,6 +260,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; |
} |
@@ -307,6 +338,31 @@ 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_DISCARDED; |
+ LOG(INFO) << "Registration discarded by user."; |
+ } |
+ return; |
+ } |
+ |
+ base::MessageLoop::current()->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&Printer::WaitUserConfirmation, AsWeakPtr(), valid_until), |
+ base::TimeDelta::FromMilliseconds(100)); |
+} |
+ |
std::string Printer::GenerateProxyId() const { |
return "{" + base::GenerateGUID() +"}"; |
} |
@@ -405,3 +461,22 @@ bool Printer::LoadFromFile(const base::FilePath& file_path) { |
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_DISCARDED: |
+ 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; |
+ } |
+} |
+ |