diff options
author | maksymb@chromium.org <maksymb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-24 20:10:49 +0000 |
---|---|---|
committer | maksymb@chromium.org <maksymb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-24 20:10:49 +0000 |
commit | 7eb6d9920f5436652fcf997a28e1c363b6aa616b (patch) | |
tree | 01342dbe2d18987309d78a30e23b96518b49f19c /cloud_print | |
parent | 468103f7fa4854a3fdcb72fd507ff54d0a42177e (diff) | |
download | chromium_src-7eb6d9920f5436652fcf997a28e1c363b6aa616b.zip chromium_src-7eb6d9920f5436652fcf997a28e1c363b6aa616b.tar.gz chromium_src-7eb6d9920f5436652fcf997a28e1c363b6aa616b.tar.bz2 |
Added confirmation for printer registration.
BUG=
Review URL: https://chromiumcodereview.appspot.com/19468002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@213498 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cloud_print')
-rw-r--r-- | cloud_print/gcp20/prototype/cloud_print_requester.cc | 2 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/cloud_print_requester.h | 2 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/conio_posix.cc | 49 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/conio_posix.h | 19 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/dns_sd_server.cc | 2 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/gcp20_device.gyp | 5 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/printer.cc | 107 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/printer.h | 37 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/special_io.h | 15 |
9 files changed, 210 insertions, 28 deletions
diff --git a/cloud_print/gcp20/prototype/cloud_print_requester.cc b/cloud_print/gcp20/prototype/cloud_print_requester.cc index ded4b47..b0c6169 100644 --- a/cloud_print/gcp20/prototype/cloud_print_requester.cc +++ b/cloud_print/gcp20/prototype/cloud_print_requester.cc @@ -18,7 +18,7 @@ #include "net/url_request/url_request_context_builder.h" #include "url/gurl.h" -const char* kCloudPrintUrl = "https://www.google.com/cloudprint"; +const char kCloudPrintUrl[] = "https://www.google.com/cloudprint"; namespace { diff --git a/cloud_print/gcp20/prototype/cloud_print_requester.h b/cloud_print/gcp20/prototype/cloud_print_requester.h index 369cca7..663ea7b 100644 --- a/cloud_print/gcp20/prototype/cloud_print_requester.h +++ b/cloud_print/gcp20/prototype/cloud_print_requester.h @@ -21,7 +21,7 @@ typedef base::Callback<void(const std::string&)> ParserCallback; class CloudPrintURLRequestContextGetter; -extern const char* kCloudPrintUrl; +extern const char kCloudPrintUrl[]; // Class for requesting CloudPrint server and parsing responses. class CloudPrintRequester : public base::SupportsWeakPtr<CloudPrintRequester>, diff --git a/cloud_print/gcp20/prototype/conio_posix.cc b/cloud_print/gcp20/prototype/conio_posix.cc new file mode 100644 index 0000000..0a955c1 --- /dev/null +++ b/cloud_print/gcp20/prototype/conio_posix.cc @@ -0,0 +1,49 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cloud_print/gcp20/prototype/conio_posix.h" + +#include <stdio.h> +#include <sys/time.h> +#include <sys/types.h> +#include <termios.h> +#include <unistd.h> + +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. + } +} + +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); +} + +int _getche() { + SetTemporaryTermiosSettings(true); + int c = getchar(); + SetTemporaryTermiosSettings(false); + return c; +} + diff --git a/cloud_print/gcp20/prototype/conio_posix.h b/cloud_print/gcp20/prototype/conio_posix.h new file mode 100644 index 0000000..f8bebea --- /dev/null +++ b/cloud_print/gcp20/prototype/conio_posix.h @@ -0,0 +1,19 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CLOUD_PRINT_GCP20_PROTOTYPE_CONIO_POSIX_H_ +#define CLOUD_PRINT_GCP20_PROTOTYPE_CONIO_POSIX_H_ + +// Method for disabling buffered IO. +// |true| - disable, |false| - restore previous settings. +void SetTemporaryTermiosSettings(bool temporary); + +// Analog from conio.h +int _kbhit(); + +// Analog from conio.h +int _getche(); + +#endif // CLOUD_PRINT_GCP20_PROTOTYPE_CONIO_POSIX_H_ + diff --git a/cloud_print/gcp20/prototype/dns_sd_server.cc b/cloud_print/gcp20/prototype/dns_sd_server.cc index 38dfb35..8a6653f 100644 --- a/cloud_print/gcp20/prototype/dns_sd_server.cc +++ b/cloud_print/gcp20/prototype/dns_sd_server.cc @@ -21,7 +21,7 @@ namespace { -const char* kDefaultIpAddressMulticast = "224.0.0.251"; +const char kDefaultIpAddressMulticast[] = "224.0.0.251"; const uint16 kDefaultPortMulticast = 5353; const double kTimeToNextAnnouncement = 0.8; // relatively to TTL diff --git a/cloud_print/gcp20/prototype/gcp20_device.gyp b/cloud_print/gcp20/prototype/gcp20_device.gyp index 795167b..bb83e45 100644 --- a/cloud_print/gcp20/prototype/gcp20_device.gyp +++ b/cloud_print/gcp20/prototype/gcp20_device.gyp @@ -30,7 +30,9 @@ 'cloud_print_response_parser.cc', 'cloud_print_response_parser.h', 'cloud_print_requester.cc', - 'cloud_print_requester.h', + 'cloud_print_requester.h', + 'conio_posix.cc', + 'conio_posix.h', 'command_line_reader.cc', 'command_line_reader.h', 'dns_packet_parser.cc', @@ -45,6 +47,7 @@ 'privet_http_server.h', 'service_parameters.cc', 'service_parameters.h', + 'special_io.h', 'x_privet_token.cc', 'x_privet_token.h', ], diff --git a/cloud_print/gcp20/prototype/printer.cc b/cloud_print/gcp20/prototype/printer.cc index 04d3066..0aaf652 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; + } +} + diff --git a/cloud_print/gcp20/prototype/printer.h b/cloud_print/gcp20/prototype/printer.h index 246e3df..9dba787 100644 --- a/cloud_print/gcp20/prototype/printer.h +++ b/cloud_print/gcp20/prototype/printer.h @@ -8,13 +8,15 @@ #include <string> #include <vector> +#include "base/memory/weak_ptr.h" #include "cloud_print/gcp20/prototype/cloud_print_requester.h" #include "cloud_print/gcp20/prototype/dns_sd_server.h" #include "cloud_print/gcp20/prototype/privet_http_server.h" #include "cloud_print/gcp20/prototype/x_privet_token.h" // This class maintain work of DNS-SD server, HTTP server and others. -class Printer : public PrivetHttpServer::Delegate, +class Printer : public base::SupportsWeakPtr<Printer>, + public PrivetHttpServer::Delegate, public CloudPrintRequester::Delegate { public: // Constructs uninitialized object. @@ -35,14 +37,25 @@ class Printer : public PrivetHttpServer::Delegate, private: struct RegistrationInfo { enum RegistrationState { - DEV_REG_UNREGISTERED = 0, - DEV_REG_REGISTRATION_STARTED, - DEV_REG_REGISTRATION_CLAIM_TOKEN_READY, - DEV_REG_REGISTRATION_COMPLETING, - DEV_REG_REGISTRATION_ERROR, + DEV_REG_UNREGISTERED, + DEV_REG_REGISTRATION_STARTED, // |action=start| was called, + // request to CloudPrint was sent. + DEV_REG_REGISTRATION_CLAIM_TOKEN_READY, // The same as previous, + // but request reply is already + // received. + DEV_REG_REGISTRATION_COMPLETING, // |action=complete| was called, + // |complete| request was sent. + DEV_REG_REGISTRATION_ERROR, // Is set when server error was occurred. DEV_REG_REGISTERED, }; + enum ConfirmationState { + CONFIRMATION_PENDING, + CONFIRMATION_CONFIRMED, + CONFIRMATION_DISCARDED, + CONFIRMATION_TIMEOUT, + }; + RegistrationInfo(); ~RegistrationInfo(); @@ -50,6 +63,7 @@ class Printer : public PrivetHttpServer::Delegate, std::string refresh_token; std::string device_id; RegistrationState state; + ConfirmationState confirmation_state; std::string registration_token; std::string complete_invite_url; @@ -100,15 +114,22 @@ class Printer : public PrivetHttpServer::Delegate, // Generates ProxyId for this device. std::string GenerateProxyId() const; + // Checks if confirmation was received. + void WaitUserConfirmation(base::Time valid_until); + // Creates data for DNS TXT respond. std::vector<std::string> CreateTxt() const; - RegistrationInfo reg_info_; - // Saving and loading registration info from file. void SaveToFile(const base::FilePath& file_path) const; bool LoadFromFile(const base::FilePath& file_path); + // Converts errors. + PrivetHttpServer::RegistrationErrorStatus ConfirmationToRegistrationError( + RegistrationInfo::ConfirmationState state); + + RegistrationInfo reg_info_; + // Contains DNS-SD server. DnsSdServer dns_server_; diff --git a/cloud_print/gcp20/prototype/special_io.h b/cloud_print/gcp20/prototype/special_io.h new file mode 100644 index 0000000..3028fec --- /dev/null +++ b/cloud_print/gcp20/prototype/special_io.h @@ -0,0 +1,15 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CLOUD_PRINT_GCP20_PROTOTYPE_SPECIAL_H_ +#define CLOUD_PRINT_GCP20_PROTOTYPE_SPECIAL_H_ + +#if defined(OS_WIN) +#include <conio.h> +#elif defined(OS_POSIX) +#include "cloud_print/gcp20/prototype/conio_posix.h" +#endif + +#endif // CLOUD_PRINT_GCP20_PROTOTYPE_SPECIAL_H_ + |