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 8b94d92996fba977ad2796816704510ad95e1271..b7da5e7bd712df1ff707321216f7dc0f89fc0785 100644 |
| --- a/cloud_print/gcp20/prototype/printer.cc |
| +++ b/cloud_print/gcp20/prototype/printer.cc |
| @@ -8,12 +8,14 @@ |
| #include <string> |
| #include <vector> |
| +#include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/file_util.h" |
| #include "base/guid.h" |
| #include "base/json/json_reader.h" |
| #include "base/json/json_writer.h" |
| #include "base/strings/string_number_conversions.h" |
| +#include "base/strings/stringprintf.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" |
| @@ -22,6 +24,8 @@ |
| const char kPrinterStatePath[] = "printer_state.json"; |
| +typedef std::vector<Printjob> PrintjobList; |
| + |
| namespace { |
| const char kServiceType[] = "_privet._tcp.local"; |
| @@ -35,6 +39,9 @@ const char kUserConfirmationTitle[] = "Confirm registration: type 'y' if you " |
| "agree and any other to discard"; |
| const uint kUserConfirmationTimeout = 30; // in seconds |
| +const uint32 kReconnectTimeout = 5; // in seconds |
| +const uint32 kPrintjobsTimeout = 10; // in seconds |
| + |
| const char kCdd[] = |
| "{\n" |
| " 'version': '1.0',\n" |
| @@ -99,7 +106,7 @@ Printer::RegistrationInfo::RegistrationInfo() |
| Printer::RegistrationInfo::~RegistrationInfo() { |
| } |
| -Printer::Printer() : http_server_(this) { |
| +Printer::Printer() : http_server_(this), connection_state_(OFFLINE) { |
| } |
| Printer::~Printer() { |
| @@ -146,6 +153,11 @@ bool Printer::Start() { |
| xtoken_ = XPrivetToken(); |
| starttime_ = base::Time::Now(); |
| + printjob_handler_.reset(new PrintjobHandler); |
| + connection_state_ = CONNECTING; |
| + if (IsRegistered()) |
| + WakeUp(); |
| + |
| return true; |
| } |
| @@ -153,10 +165,20 @@ bool Printer::IsOnline() const { |
| return requester_; |
| } |
| +void Printer::WakeUp() { |
| + LOG_IF(INFO, kFunctionVebose) << "Function: " << __FUNCTION__; |
| + |
| + if (!IsRegistered()) |
| + return; |
| + |
| + FetchPrintjobs(); |
| +} |
| + |
| void Printer::Stop() { |
| dns_server_.Shutdown(); |
| http_server_.Shutdown(); |
| requester_.reset(); |
| + printjob_handler_.reset(); |
| } |
| PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationStart( |
| @@ -177,22 +199,14 @@ PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationStart( |
| base::TimeDelta::FromSeconds(kUserConfirmationTimeout); |
| base::MessageLoop::current()->PostTask( |
| FROM_HERE, |
| - base::Bind(&Printer::WaitUserConfirmation, |
| - base::Unretained(this), valid_until)); |
| + base::Bind(&Printer::WaitUserConfirmation, this->AsWeakPtr(), |
|
Vitaly Buka (NO REVIEWS)
2013/07/22 03:57:31
remote this->
maksymb
2013/07/22 22:56:53
Done.
|
| + valid_until)); |
| requester_->StartRegistration(GenerateProxyId(), kPrinterName, user, kCdd); |
| return PrivetHttpServer::REG_ERROR_OK; |
| } |
| -bool Printer::CheckXPrivetTokenHeader(const std::string& token) const { |
| - return xtoken_.CheckValidXToken(token); |
| -} |
| - |
| -bool Printer::IsRegistered() const { |
| - return reg_info_.state == RegistrationInfo::DEV_REG_REGISTERED; |
| -} |
| - |
| PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationGetClaimToken( |
| const std::string& user, |
| std::string* token, |
| @@ -275,7 +289,7 @@ void Printer::CreateInfo(PrivetHttpServer::DeviceInfo* info) { |
| info->url = kCloudPrintUrl; |
| info->id = reg_info_.device_id; |
| info->device_state = "idle"; |
| - info->connection_state = "offline"; |
| + info->connection_state = ConnectionStateToString(connection_state_); |
| info->manufacturer = "Google"; |
| info->model = "Prototype"; |
| info->serial_number = "2.3.5.7.13.17.19.31.61.89.107.127.521.607.1279.2203"; |
| @@ -290,6 +304,14 @@ void Printer::CreateInfo(PrivetHttpServer::DeviceInfo* info) { |
| info->type.push_back("printer"); |
| } |
| +bool Printer::IsRegistered() const { |
| + return reg_info_.state == RegistrationInfo::DEV_REG_REGISTERED; |
| +} |
| + |
| +bool Printer::CheckXPrivetTokenHeader(const std::string& token) const { |
| + return xtoken_.CheckValidXToken(token); |
| +} |
| + |
| void Printer::OnRegistrationStartResponseParsed( |
| const std::string& registration_token, |
| const std::string& complete_invite_url, |
| @@ -304,6 +326,7 @@ void Printer::OnGetAuthCodeResponseParsed(const std::string& refresh_token) { |
| reg_info_.state = RegistrationInfo::DEV_REG_REGISTERED; |
| reg_info_.refresh_token = refresh_token; |
| SaveToFile(kPrinterStatePath); |
| + FetchPrintjobs(); |
| } |
| void Printer::OnRegistrationError(const std::string& description) { |
| @@ -314,6 +337,53 @@ void Printer::OnRegistrationError(const std::string& description) { |
| reg_info_.error_description = description; |
| } |
| +void Printer::OnServerError(const std::string& description) { |
| + LOG_IF(INFO, kFunctionVebose) << "Function: " << __FUNCTION__; |
| + LOG(ERROR) << "Server error: " << description; |
| + |
| + PostDelayedWakeUp(base::TimeDelta::FromSeconds(kReconnectTimeout)); |
| +} |
| + |
| +void Printer::OnNetworkError() { |
| + LOG_IF(INFO, kFunctionVebose) << "Function: " << __FUNCTION__; |
| + ChangeState(OFFLINE); |
| + PostDelayedWakeUp(base::TimeDelta::FromSeconds(kReconnectTimeout)); |
| +} |
| + |
| +void Printer::OnPrintjobsAvailable(const std::vector<Printjob>& printjobs) { |
| + LOG_IF(INFO, kFunctionVebose) << "Function: " << __FUNCTION__; |
| + ChangeState(ONLINE); |
| + |
| + LOG(INFO) << "Available printjobs: " << printjobs.size(); |
| + |
| + if (printjobs.empty()) { |
| + PostDelayedWakeUp(base::TimeDelta::FromSeconds(kPrintjobsTimeout)); |
| + return; |
| + } |
| + |
| + // TODO(maksymb): After finishing XMPP add 'Printjobs available' flag. |
| + LOG(INFO) << "Downloading first printjob."; |
| + requester_->RequestPrintjob(printjobs[0]); |
| + return; |
| +} |
| + |
| +void Printer::OnPrintjobDownloaded(const Printjob& printjob) { |
| + LOG_IF(INFO, kFunctionVebose) << "Function: " << __FUNCTION__; |
| + printjob_handler_->SavePrintjob( |
| + printjob.file, |
| + printjob.ticket, |
| + base::StringPrintf("%s.%s", |
| + printjob.create_time.c_str(), printjob.jobid.c_str()), |
| + printjob.title); |
| + requester_->SendPrintjobDone(printjob.jobid); |
| +} |
| + |
| +void Printer::OnPrintjobDone() { |
| + LOG_IF(INFO, kFunctionVebose) << "Function: " << __FUNCTION__; |
| + // TODO(maksymb): Replace PostTask with with XMPP notifications. |
| + PostWakeUp(); |
| +} |
| + |
| PrivetHttpServer::RegistrationErrorStatus Printer::CheckCommonRegErrors( |
| const std::string& user) const { |
| DCHECK(!IsRegistered()); |
| @@ -350,7 +420,7 @@ void Printer::WaitUserConfirmation(base::Time valid_until) { |
| base::MessageLoop::current()->PostDelayedTask( |
| FROM_HERE, |
| - base::Bind(&Printer::WaitUserConfirmation, base::Unretained(this), |
| + base::Bind(&Printer::WaitUserConfirmation, this->AsWeakPtr(), |
| valid_until), |
| base::TimeDelta::FromMilliseconds(100)); |
| } |
| @@ -367,11 +437,24 @@ std::vector<std::string> Printer::CreateTxt() const { |
| txt.push_back("url=" + std::string(kCloudPrintUrl)); |
| txt.push_back("type=printer"); |
| txt.push_back("id=" + reg_info_.device_id); |
| - txt.push_back("cs=offline"); |
| + txt.push_back("cs=" + ConnectionStateToString(connection_state_)); |
| return txt; |
| } |
| +void Printer::FetchPrintjobs() { |
| + LOG_IF(INFO, kFunctionVebose) << "Function: " << __FUNCTION__; |
| + |
| + if (!IsRegistered()) |
| + return; |
| + |
| + if (requester_->IsBusy()) { |
| + PostDelayedWakeUp(base::TimeDelta::FromSeconds(kReconnectTimeout)); |
| + } else { |
| + requester_->FetchPrintjobs(reg_info_.refresh_token, reg_info_.device_id); |
| + } |
| +} |
| + |
| void Printer::SaveToFile(const std::string& filename) const { |
| base::DictionaryValue json; |
| // TODO(maksymb): Get rid of in-place constants. |
| @@ -453,6 +536,21 @@ bool Printer::LoadFromFile(const std::string& filename) { |
| return true; |
| } |
| +void Printer::PostWakeUp() { |
| + LOG_IF(INFO, kFunctionVebose) << "Function: " << __FUNCTION__; |
| + base::MessageLoop::current()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&Printer::WakeUp, this->AsWeakPtr())); |
| +} |
| + |
| +void Printer::PostDelayedWakeUp(const base::TimeDelta& delay) { |
| + LOG_IF(INFO, kFunctionVebose) << "Function: " << __FUNCTION__; |
| + base::MessageLoop::current()->PostDelayedTask( |
| + FROM_HERE, |
| + base::Bind(&Printer::WakeUp, this->AsWeakPtr()), |
| + delay); |
| +} |
| + |
| PrivetHttpServer::RegistrationErrorStatus |
| Printer::ConfirmationToRegistrationError( |
| RegistrationInfo::ConfirmationState state) { |
| @@ -472,3 +570,27 @@ PrivetHttpServer::RegistrationErrorStatus |
| } |
| } |
| +std::string Printer::ConnectionStateToString(ConnectionState state) const { |
| + if (state == OFFLINE) |
| + return "offline"; |
| + if (state == ONLINE) |
| + return "online"; |
| + if (state == CONNECTING) |
| + return "connecting"; |
| + if (state == NOT_CONFIGURED) |
| + return "not-configured"; |
| + |
| + NOTREACHED(); |
| + return ""; |
| +} |
| + |
| +bool Printer::ChangeState(ConnectionState new_state) { |
| + if (connection_state_ == new_state) |
| + return false; |
| + |
| + VLOG(1) << "Printer is now " << ConnectionStateToString(new_state); |
| + connection_state_ = new_state; |
| + dns_server_.UpdateMetadata(CreateTxt()); |
| + return true; |
| +} |
| + |