summaryrefslogtreecommitdiffstats
path: root/cloud_print
diff options
context:
space:
mode:
authormaksymb@chromium.org <maksymb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-24 20:10:49 +0000
committermaksymb@chromium.org <maksymb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-24 20:10:49 +0000
commit7eb6d9920f5436652fcf997a28e1c363b6aa616b (patch)
tree01342dbe2d18987309d78a30e23b96518b49f19c /cloud_print
parent468103f7fa4854a3fdcb72fd507ff54d0a42177e (diff)
downloadchromium_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.cc2
-rw-r--r--cloud_print/gcp20/prototype/cloud_print_requester.h2
-rw-r--r--cloud_print/gcp20/prototype/conio_posix.cc49
-rw-r--r--cloud_print/gcp20/prototype/conio_posix.h19
-rw-r--r--cloud_print/gcp20/prototype/dns_sd_server.cc2
-rw-r--r--cloud_print/gcp20/prototype/gcp20_device.gyp5
-rw-r--r--cloud_print/gcp20/prototype/printer.cc107
-rw-r--r--cloud_print/gcp20/prototype/printer.h37
-rw-r--r--cloud_print/gcp20/prototype/special_io.h15
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_
+