| Index: cloud_print/gcp20/prototype/cloud_print_requester.cc
|
| diff --git a/cloud_print/gcp20/prototype/cloud_print_requester.cc b/cloud_print/gcp20/prototype/cloud_print_requester.cc
|
| index b0c61695019f0a55d1b13afeb919465c3b8641a2..f0d192618c00243b9ca6a803fe751d536e0b13b8 100644
|
| --- a/cloud_print/gcp20/prototype/cloud_print_requester.cc
|
| +++ b/cloud_print/gcp20/prototype/cloud_print_requester.cc
|
| @@ -4,18 +4,18 @@
|
|
|
| #include "cloud_print/gcp20/prototype/cloud_print_requester.h"
|
|
|
| +#include "base/bind.h"
|
| #include "base/md5.h"
|
| #include "base/message_loop/message_loop.h"
|
| #include "base/rand_util.h"
|
| #include "base/strings/stringprintf.h"
|
| -#include "cloud_print/gcp20/prototype/cloud_print_response_parser.h"
|
| #include "google_apis/google_api_keys.h"
|
| -#include "net/base/load_flags.h"
|
| #include "net/base/mime_util.h"
|
| #include "net/base/url_util.h"
|
| #include "net/proxy/proxy_config_service_fixed.h"
|
| #include "net/url_request/url_request_context.h"
|
| #include "net/url_request/url_request_context_builder.h"
|
| +#include "net/url_request/url_request_context_getter.h"
|
| #include "url/gurl.h"
|
|
|
| const char kCloudPrintUrl[] = "https://www.google.com/cloudprint";
|
| @@ -34,8 +34,23 @@ GURL CreateRegisterUrl() {
|
| return GURL(std::string(kCloudPrintUrl) + "/register");
|
| }
|
|
|
| +GURL CreateFetchUrl(const std::string& device_id) {
|
| + GURL url(std::string(kCloudPrintUrl) + "/fetch");
|
| + url = net::AppendQueryParameter(url, "printerid", device_id);
|
| + return url;
|
| +}
|
| +
|
| +GURL CreateControlUrl(const std::string& job_id, const std::string& status) {
|
| + GURL url(std::string(kCloudPrintUrl) + "/control");
|
| + url = net::AppendQueryParameter(url, "jobid", job_id);
|
| + url = net::AppendQueryParameter(url, "status", status);
|
| + return url;
|
| +}
|
| +
|
| } // namespace
|
|
|
| +using cloud_print_response_parser::Job;
|
| +
|
| // Used to return a dummy context, which lives on the message loop
|
| // given in the constructor.
|
| class CloudPrintURLRequestContextGetter : public net::URLRequestContextGetter {
|
| @@ -89,7 +104,11 @@ CloudPrintRequester::CloudPrintRequester(
|
| CloudPrintRequester::~CloudPrintRequester() {
|
| }
|
|
|
| -bool CloudPrintRequester::StartRegistration(const std::string& proxy_id,
|
| +bool CloudPrintRequester::IsBusy() const {
|
| + return request_ || gaia_;
|
| +}
|
| +
|
| +void CloudPrintRequester::StartRegistration(const std::string& proxy_id,
|
| const std::string& device_name,
|
| const std::string& user,
|
| const std::string& cdd) {
|
| @@ -100,65 +119,114 @@ bool CloudPrintRequester::StartRegistration(const std::string& proxy_id,
|
| "---------------------------%08X%08X", r1, r2);
|
|
|
| std::string data;
|
| - net::AddMultipartValueForUpload(kProxyIdValue, proxy_id,
|
| - mime_boundary, std::string(), &data);
|
| - net::AddMultipartValueForUpload(kPrinterNameValue, device_name,
|
| - mime_boundary, std::string(), &data);
|
| - net::AddMultipartValueForUpload("use_cdd", "true",
|
| - mime_boundary, std::string(), &data);
|
| - net::AddMultipartValueForUpload(kPrinterNameValue, device_name,
|
| - mime_boundary, std::string(), &data);
|
| - net::AddMultipartValueForUpload(kPrinterCapsValue, cdd,
|
| - mime_boundary, "application/json", &data);
|
| + std::string data_mimetype;
|
| + data_mimetype = "multipart/form-data; boundary=" + mime_boundary;
|
| +
|
| + net::AddMultipartValueForUpload(kProxyIdValue, proxy_id, mime_boundary,
|
| + std::string(), &data);
|
| + net::AddMultipartValueForUpload(kPrinterNameValue, device_name, mime_boundary,
|
| + std::string(), &data);
|
| + net::AddMultipartValueForUpload("use_cdd", "true", mime_boundary,
|
| + std::string(), &data);
|
| + net::AddMultipartValueForUpload(kPrinterNameValue, device_name, mime_boundary,
|
| + std::string(), &data);
|
| + net::AddMultipartValueForUpload(kPrinterCapsValue, cdd, mime_boundary,
|
| + "application/json", &data);
|
| net::AddMultipartValueForUpload(kPrinterCapsHashValue, base::MD5String(cdd),
|
| mime_boundary, std::string(), &data);
|
| net::AddMultipartValueForUpload(kPrinterUserValue, user,
|
| mime_boundary, std::string(), &data);
|
| net::AddMultipartFinalDelimiterForUpload(mime_boundary, &data);
|
|
|
| - std::string mime_type("multipart/form-data; boundary=" + mime_boundary);
|
| + request_ = CreatePost(
|
| + CreateRegisterUrl(),
|
| + data,
|
| + data_mimetype,
|
| + base::Bind(&CloudPrintRequester::ParseRegisterStart, AsWeakPtr()));
|
| + request_->Run(access_token_, context_getter_);
|
| +}
|
| +
|
| +void CloudPrintRequester::CompleteRegistration() {
|
| + request_ = CreateGet(
|
| + GURL(polling_url_ + oauth_client_info_.client_id),
|
| + base::Bind(&CloudPrintRequester::ParseRegisterComplete, AsWeakPtr()));
|
| + request_->Run(access_token_, context_getter_);
|
| +}
|
| +
|
| +void CloudPrintRequester::FetchPrintJobs(const std::string& refresh_token,
|
| + const std::string& device_id) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + if (IsBusy())
|
| + return;
|
|
|
| - if (!CreateRequest(
|
| - CreateRegisterUrl(), net::URLFetcher::POST,
|
| - base::Bind(&CloudPrintRequester::ParseRegisterStartResponse,
|
| - AsWeakPtr()))) {
|
| - return false;
|
| + if (access_token_.empty()) {
|
| + UpdateAccesstoken(refresh_token);
|
| + return;
|
| }
|
| - fetcher_->SetUploadData(mime_type, data);
|
| - fetcher_->Start();
|
|
|
| - return true;
|
| + VLOG(3) << "Function: " << __FUNCTION__ <<
|
| + ": request created";
|
| + request_ = CreateGet(
|
| + CreateFetchUrl(device_id),
|
| + base::Bind(&CloudPrintRequester::ParseFetch, AsWeakPtr()));
|
| + request_->Run(access_token_, context_getter_);
|
| }
|
|
|
| -bool CloudPrintRequester::CompleteRegistration() {
|
| - if (!CreateRequest(
|
| - GURL(polling_url_ + oauth_client_info_.client_id),
|
| - net::URLFetcher::GET,
|
| - base::Bind(&CloudPrintRequester::ParseRegisterCompleteResponse,
|
| - AsWeakPtr()))) {
|
| - return false;
|
| - }
|
| - fetcher_->Start();
|
| +void CloudPrintRequester::UpdateAccesstoken(const std::string& refresh_token) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + DCHECK(!IsBusy());
|
| + gaia_.reset(new gaia::GaiaOAuthClient(context_getter_.get()));
|
| + gaia_->RefreshToken(oauth_client_info_, refresh_token,
|
| + std::vector<std::string>(), kGaiaMaxRetries, this);
|
| + delegate_->OnServerError("Access token requested.");
|
| +}
|
|
|
| - return true;
|
| +void CloudPrintRequester::RequestPrintJob(const Job& job) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + current_print_job_.reset(new Job(job));
|
| + request_ = CreateGet(
|
| + CreateControlUrl(current_print_job_->job_id, "IN_PROGRESS"),
|
| + base::Bind(&CloudPrintRequester::ParsePrintJobInProgress, AsWeakPtr()));
|
| + request_->Run(access_token_, context_getter_);
|
| }
|
|
|
| -void CloudPrintRequester::OnURLFetchComplete(const net::URLFetcher* source) {
|
| - std::string response;
|
| - source->GetResponseAsString(&response);
|
| - fetcher_.reset();
|
| - VLOG(1) << response;
|
| +void CloudPrintRequester::SendPrintJobDone(const std::string& job_id) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + request_ = CreateGet(
|
| + CreateControlUrl(job_id, "DONE"),
|
| + base::Bind(&CloudPrintRequester::ParsePrintJobDone, AsWeakPtr()));
|
| + request_->Run(access_token_, context_getter_);
|
| +}
|
|
|
| - // TODO(maksymb): Add |server_http_code| and |server_api| info for errors.
|
| - if (!parse_response_callback_.is_null()) {
|
| - parse_response_callback_.Run(response);
|
| - parse_response_callback_.Reset();
|
| - }
|
| +void CloudPrintRequester::OnFetchComplete(const std::string& response) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + ParserCallback callback = parser_callback_;
|
| + EraseRequest();
|
| + callback.Run(response);
|
| +}
|
| +
|
| +void CloudPrintRequester::OnFetchError(const std::string& server_api,
|
| + int server_code,
|
| + int server_http_code) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + EraseRequest();
|
| + current_print_job_.reset();
|
| + delegate_->OnServerError("Fetch error");
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +void CloudPrintRequester::OnFetchTimeoutReached() {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + EraseRequest();
|
| + current_print_job_.reset();
|
| + delegate_->OnNetworkError();
|
| }
|
|
|
| void CloudPrintRequester::OnGetTokensResponse(const std::string& refresh_token,
|
| const std::string& access_token,
|
| int expires_in_seconds) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + gaia_.reset();
|
| access_token_ = access_token;
|
| delegate_->OnGetAuthCodeResponseParsed(refresh_token);
|
| }
|
| @@ -166,42 +234,53 @@ void CloudPrintRequester::OnGetTokensResponse(const std::string& refresh_token,
|
| void CloudPrintRequester::OnRefreshTokenResponse(
|
| const std::string& access_token,
|
| int expires_in_seconds) {
|
| - NOTIMPLEMENTED();
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + gaia_.reset();
|
| + access_token_ = access_token;
|
| + LOG(INFO) << "New accesstoken: " << access_token;
|
| }
|
|
|
| void CloudPrintRequester::OnOAuthError() {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + gaia_.reset();
|
| NOTIMPLEMENTED();
|
| }
|
|
|
| void CloudPrintRequester::OnNetworkError(int response_code) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + gaia_.reset();
|
| NOTIMPLEMENTED();
|
| }
|
|
|
| -bool CloudPrintRequester::CreateRequest(const GURL& url,
|
| - net::URLFetcher::RequestType method,
|
| - const ParserCallback& callback) {
|
| - if (fetcher_)
|
| - return false; // Only one query is supported.
|
| -
|
| - fetcher_.reset(net::URLFetcher::Create(url, method, this));
|
| - fetcher_->SetRequestContext(context_getter_);
|
| -
|
| - int load_flags = fetcher_->GetLoadFlags();
|
| - load_flags |= net::LOAD_DO_NOT_SEND_COOKIES;
|
| - load_flags |= net::LOAD_DO_NOT_SAVE_COOKIES;
|
| - fetcher_->SetLoadFlags(load_flags);
|
| -
|
| - fetcher_->AddExtraRequestHeader("X-CloudPrint-Proxy: \"\"");
|
| - if (!access_token_.empty())
|
| - fetcher_->AddExtraRequestHeader("Authorization: Bearer " + access_token_);
|
| +scoped_ptr<CloudPrintRequest> CloudPrintRequester::CreateGet(
|
| + const GURL& url,
|
| + const ParserCallback& parser_callback) {
|
| + DCHECK(!IsBusy());
|
| + DCHECK(parser_callback_.is_null());
|
| + parser_callback_ = parser_callback;
|
| + return CloudPrintRequest::CreateGet(url, this);
|
| +}
|
|
|
| - parse_response_callback_ = callback;
|
| +scoped_ptr<CloudPrintRequest> CloudPrintRequester::CreatePost(
|
| + const GURL& url,
|
| + const std::string& content,
|
| + const std::string& mimetype,
|
| + const ParserCallback& parser_callback) {
|
| + DCHECK(!IsBusy());
|
| + DCHECK(parser_callback_.is_null());
|
| + parser_callback_ = parser_callback;
|
| + return CloudPrintRequest::CreatePost(url, content, mimetype, this);
|
| +}
|
|
|
| - return true;
|
| +void CloudPrintRequester::EraseRequest() {
|
| + DCHECK(request_);
|
| + DCHECK(!parser_callback_.is_null());
|
| + request_.reset();
|
| + parser_callback_.Reset();
|
| }
|
|
|
| -void CloudPrintRequester::ParseRegisterStartResponse(
|
| - const std::string& response) {
|
| +void CloudPrintRequester::ParseRegisterStart(const std::string& response) {
|
| + std::string error_description;
|
| std::string polling_url;
|
| std::string registration_token;
|
| std::string complete_invite_url;
|
| @@ -209,36 +288,88 @@ void CloudPrintRequester::ParseRegisterStartResponse(
|
|
|
| bool success = cloud_print_response_parser::ParseRegisterStartResponse(
|
| response,
|
| - base::Bind(&CloudPrintRequester::Delegate::OnRegistrationError,
|
| - base::Unretained(delegate_)),
|
| + &error_description,
|
| &polling_url,
|
| ®istration_token,
|
| &complete_invite_url,
|
| &device_id);
|
|
|
| - if (!success)
|
| - return;
|
| -
|
| - polling_url_ = polling_url;
|
| - delegate_->OnRegistrationStartResponseParsed(registration_token,
|
| - complete_invite_url, device_id);
|
| + if (success) {
|
| + polling_url_ = polling_url;
|
| + delegate_->OnRegistrationStartResponseParsed(registration_token,
|
| + complete_invite_url,
|
| + device_id);
|
| + } else {
|
| + delegate_->OnRegistrationError(error_description);
|
| + }
|
| }
|
|
|
| -void CloudPrintRequester::ParseRegisterCompleteResponse(
|
| - const std::string& response) {
|
| +void CloudPrintRequester::ParseRegisterComplete(const std::string& response) {
|
| + std::string error_description;
|
| std::string authorization_code;
|
|
|
| bool success = cloud_print_response_parser::ParseRegisterCompleteResponse(
|
| response,
|
| - base::Bind(&CloudPrintRequester::Delegate::OnRegistrationError,
|
| - base::Unretained(delegate_)),
|
| + &error_description,
|
| &authorization_code);
|
|
|
| - if (!success)
|
| - return;
|
| + if (success) {
|
| + gaia_.reset(new gaia::GaiaOAuthClient(context_getter_.get()));
|
| + gaia_->GetTokensFromAuthCode(oauth_client_info_, authorization_code,
|
| + kGaiaMaxRetries, this);
|
| + } else {
|
| + delegate_->OnRegistrationError(error_description);
|
| + }
|
| +}
|
|
|
| - gaia_.reset(new gaia::GaiaOAuthClient(context_getter_.get()));
|
| - gaia_->GetTokensFromAuthCode(oauth_client_info_, authorization_code,
|
| - kGaiaMaxRetries, this);
|
| +void CloudPrintRequester::ParseFetch(const std::string& response) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| +
|
| + std::string error_description;
|
| + std::vector<Job> list;
|
| + bool success = cloud_print_response_parser::ParseFetchResponse(
|
| + response,
|
| + &error_description,
|
| + &list);
|
| +
|
| + if (success) {
|
| + delegate_->OnPrintJobsAvailable(list);
|
| + } else {
|
| + delegate_->OnServerError(error_description);
|
| + }
|
| +}
|
| +
|
| +void CloudPrintRequester::ParseGetPrintJobTicket(const std::string& response) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + current_print_job_->ticket = response;
|
| +
|
| + DCHECK(current_print_job_);
|
| + request_ = CreateGet(
|
| + GURL(current_print_job_->file_url),
|
| + base::Bind(&CloudPrintRequester::ParseGetPrintJobData, AsWeakPtr()));
|
| + request_->AddHeader("Accept: \"application/pdf\"");
|
| + request_->Run(access_token_, context_getter_);
|
| +}
|
| +
|
| +void CloudPrintRequester::ParseGetPrintJobData(const std::string& response) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + current_print_job_->file = response;
|
| + DCHECK(current_print_job_);
|
| + delegate_->OnPrintJobDownloaded(*current_print_job_);
|
| +}
|
| +
|
| +void CloudPrintRequester::ParsePrintJobDone(const std::string& response) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + current_print_job_.reset();
|
| + delegate_->OnPrintJobDone();
|
| +}
|
| +
|
| +void CloudPrintRequester::ParsePrintJobInProgress(const std::string& response) {
|
| + VLOG(3) << "Function: " << __FUNCTION__;
|
| + DCHECK(current_print_job_);
|
| + request_ = CreateGet(
|
| + GURL(current_print_job_->ticket_url),
|
| + base::Bind(&CloudPrintRequester::ParseGetPrintJobTicket, AsWeakPtr()));
|
| + request_->Run(access_token_, context_getter_);
|
| }
|
|
|
|
|