[Cronet] Delay StartNetLog and StopNetLog until native request context is initialized
[chromium-blink-merge.git] / chrome / browser / local_discovery / privet_http_impl.cc
blob38d546f40ca01205c709f67356a8eb55122d60a7
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/local_discovery/privet_http_impl.h"
7 #include <algorithm>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/rand_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/local_discovery/privet_constants.h"
16 #include "net/base/url_util.h"
17 #include "url/gurl.h"
19 #if defined(ENABLE_PRINT_PREVIEW)
20 #include "chrome/browser/local_discovery/pwg_raster_converter.h"
21 #include "components/cloud_devices/common/printer_description.h"
22 #include "printing/pdf_render_settings.h"
23 #include "printing/pwg_raster_settings.h"
24 #include "ui/gfx/text_elider.h"
25 #endif // ENABLE_PRINT_PREVIEW
27 namespace cloud_print {
28 extern const char kContentTypeJSON[];
31 namespace local_discovery {
33 namespace {
34 const char kUrlPlaceHolder[] = "http://host/";
35 const char kPrivetRegisterActionArgName[] = "action";
36 const char kPrivetRegisterUserArgName[] = "user";
38 const int kPrivetCancelationTimeoutSeconds = 3;
40 #if defined(ENABLE_PRINT_PREVIEW)
41 const char kPrivetURLKeyUserName[] = "user_name";
42 const char kPrivetURLKeyClientName[] = "client_name";
43 const char kPrivetURLKeyJobname[] = "job_name";
44 const char kPrivetURLKeyOffline[] = "offline";
45 const char kPrivetURLValueOffline[] = "1";
46 const char kPrivetURLValueClientName[] = "Chrome";
48 const char kPrivetContentTypePDF[] = "application/pdf";
49 const char kPrivetContentTypePWGRaster[] = "image/pwg-raster";
50 const char kPrivetContentTypeAny[] = "*/*";
52 const char kPrivetKeyJobID[] = "job_id";
54 const int kPrivetLocalPrintMaxRetries = 2;
55 const int kPrivetLocalPrintDefaultTimeout = 5;
57 const size_t kPrivetLocalPrintMaxJobNameLength = 64;
58 #endif // ENABLE_PRINT_PREVIEW
60 GURL CreatePrivetURL(const std::string& path) {
61 GURL url(kUrlPlaceHolder);
62 GURL::Replacements replacements;
63 replacements.SetPathStr(path);
64 return url.ReplaceComponents(replacements);
67 GURL CreatePrivetRegisterURL(const std::string& action,
68 const std::string& user) {
69 GURL url = CreatePrivetURL(kPrivetRegisterPath);
70 url = net::AppendQueryParameter(url, kPrivetRegisterActionArgName, action);
71 return net::AppendQueryParameter(url, kPrivetRegisterUserArgName, user);
74 GURL CreatePrivetParamURL(const std::string& path,
75 const std::string& query_params) {
76 GURL url(kUrlPlaceHolder);
77 GURL::Replacements replacements;
78 replacements.SetPathStr(path);
79 if (!query_params.empty()) {
80 replacements.SetQueryStr(query_params);
82 return url.ReplaceComponents(replacements);
85 } // namespace
87 PrivetInfoOperationImpl::PrivetInfoOperationImpl(
88 PrivetHTTPClient* privet_client,
89 const PrivetJSONOperation::ResultCallback& callback)
90 : privet_client_(privet_client), callback_(callback) {
93 PrivetInfoOperationImpl::~PrivetInfoOperationImpl() {
96 void PrivetInfoOperationImpl::Start() {
97 url_fetcher_ = privet_client_->CreateURLFetcher(
98 CreatePrivetURL(kPrivetInfoPath), net::URLFetcher::GET, this);
100 url_fetcher_->DoNotRetryOnTransientError();
101 url_fetcher_->SendEmptyPrivetToken();
103 url_fetcher_->Start();
106 PrivetHTTPClient* PrivetInfoOperationImpl::GetHTTPClient() {
107 return privet_client_;
110 void PrivetInfoOperationImpl::OnError(PrivetURLFetcher* fetcher,
111 PrivetURLFetcher::ErrorType error) {
112 callback_.Run(NULL);
115 void PrivetInfoOperationImpl::OnParsedJson(PrivetURLFetcher* fetcher,
116 const base::DictionaryValue& value,
117 bool has_error) {
118 callback_.Run(&value);
121 PrivetRegisterOperationImpl::PrivetRegisterOperationImpl(
122 PrivetHTTPClient* privet_client,
123 const std::string& user,
124 PrivetRegisterOperation::Delegate* delegate)
125 : user_(user),
126 delegate_(delegate),
127 privet_client_(privet_client),
128 ongoing_(false) {
131 PrivetRegisterOperationImpl::~PrivetRegisterOperationImpl() {
134 void PrivetRegisterOperationImpl::Start() {
135 ongoing_ = true;
136 next_response_handler_ =
137 base::Bind(&PrivetRegisterOperationImpl::StartResponse,
138 base::Unretained(this));
139 SendRequest(kPrivetActionStart);
142 void PrivetRegisterOperationImpl::Cancel() {
143 url_fetcher_.reset();
145 if (ongoing_) {
146 // Owned by the message loop.
147 Cancelation* cancelation = new Cancelation(privet_client_, user_);
149 base::MessageLoop::current()->PostDelayedTask(
150 FROM_HERE,
151 base::Bind(&PrivetRegisterOperationImpl::Cancelation::Cleanup,
152 base::Owned(cancelation)),
153 base::TimeDelta::FromSeconds(kPrivetCancelationTimeoutSeconds));
155 ongoing_ = false;
159 void PrivetRegisterOperationImpl::CompleteRegistration() {
160 next_response_handler_ =
161 base::Bind(&PrivetRegisterOperationImpl::CompleteResponse,
162 base::Unretained(this));
163 SendRequest(kPrivetActionComplete);
166 PrivetHTTPClient* PrivetRegisterOperationImpl::GetHTTPClient() {
167 return privet_client_;
170 void PrivetRegisterOperationImpl::OnError(PrivetURLFetcher* fetcher,
171 PrivetURLFetcher::ErrorType error) {
172 ongoing_ = false;
173 int visible_http_code = -1;
174 FailureReason reason = FAILURE_NETWORK;
176 if (error == PrivetURLFetcher::RESPONSE_CODE_ERROR) {
177 visible_http_code = fetcher->response_code();
178 reason = FAILURE_HTTP_ERROR;
179 } else if (error == PrivetURLFetcher::JSON_PARSE_ERROR) {
180 reason = FAILURE_MALFORMED_RESPONSE;
181 } else if (error == PrivetURLFetcher::TOKEN_ERROR) {
182 reason = FAILURE_TOKEN;
183 } else if (error == PrivetURLFetcher::RETRY_ERROR) {
184 reason = FAILURE_RETRY;
187 delegate_->OnPrivetRegisterError(this,
188 current_action_,
189 reason,
190 visible_http_code,
191 NULL);
194 void PrivetRegisterOperationImpl::OnParsedJson(
195 PrivetURLFetcher* fetcher,
196 const base::DictionaryValue& value,
197 bool has_error) {
198 if (has_error) {
199 std::string error;
200 value.GetString(kPrivetKeyError, &error);
202 ongoing_ = false;
203 delegate_->OnPrivetRegisterError(this,
204 current_action_,
205 FAILURE_JSON_ERROR,
206 fetcher->response_code(),
207 &value);
208 return;
211 // TODO(noamsml): Match the user&action with the user&action in the object,
212 // and fail if different.
214 next_response_handler_.Run(value);
217 void PrivetRegisterOperationImpl::OnNeedPrivetToken(
218 PrivetURLFetcher* fetcher,
219 const PrivetURLFetcher::TokenCallback& callback) {
220 privet_client_->RefreshPrivetToken(callback);
223 void PrivetRegisterOperationImpl::SendRequest(const std::string& action) {
224 current_action_ = action;
225 url_fetcher_ = privet_client_->CreateURLFetcher(
226 CreatePrivetRegisterURL(action, user_), net::URLFetcher::POST, this);
227 url_fetcher_->Start();
230 void PrivetRegisterOperationImpl::StartResponse(
231 const base::DictionaryValue& value) {
232 next_response_handler_ =
233 base::Bind(&PrivetRegisterOperationImpl::GetClaimTokenResponse,
234 base::Unretained(this));
236 SendRequest(kPrivetActionGetClaimToken);
239 void PrivetRegisterOperationImpl::GetClaimTokenResponse(
240 const base::DictionaryValue& value) {
241 std::string claimUrl;
242 std::string claimToken;
243 bool got_url = value.GetString(kPrivetKeyClaimURL, &claimUrl);
244 bool got_token = value.GetString(kPrivetKeyClaimToken, &claimToken);
245 if (got_url || got_token) {
246 delegate_->OnPrivetRegisterClaimToken(this, claimToken, GURL(claimUrl));
247 } else {
248 delegate_->OnPrivetRegisterError(this,
249 current_action_,
250 FAILURE_MALFORMED_RESPONSE,
252 NULL);
256 void PrivetRegisterOperationImpl::CompleteResponse(
257 const base::DictionaryValue& value) {
258 std::string id;
259 value.GetString(kPrivetKeyDeviceID, &id);
260 ongoing_ = false;
261 expected_id_ = id;
262 StartInfoOperation();
265 void PrivetRegisterOperationImpl::OnPrivetInfoDone(
266 const base::DictionaryValue* value) {
267 // TODO(noamsml): Simplify error case and depracate HTTP error value in
268 // OnPrivetRegisterError.
269 if (!value) {
270 delegate_->OnPrivetRegisterError(this,
271 kPrivetActionNameInfo,
272 FAILURE_NETWORK,
274 NULL);
275 return;
278 if (!value->HasKey(kPrivetInfoKeyID)) {
279 if (value->HasKey(kPrivetKeyError)) {
280 delegate_->OnPrivetRegisterError(this,
281 kPrivetActionNameInfo,
282 FAILURE_JSON_ERROR,
284 value);
285 } else {
286 delegate_->OnPrivetRegisterError(this,
287 kPrivetActionNameInfo,
288 FAILURE_MALFORMED_RESPONSE,
290 NULL);
292 return;
295 std::string id;
297 if (!value->GetString(kPrivetInfoKeyID, &id) ||
298 id != expected_id_) {
299 delegate_->OnPrivetRegisterError(this,
300 kPrivetActionNameInfo,
301 FAILURE_MALFORMED_RESPONSE,
303 NULL);
304 } else {
305 delegate_->OnPrivetRegisterDone(this, id);
309 void PrivetRegisterOperationImpl::StartInfoOperation() {
310 info_operation_ = privet_client_->CreateInfoOperation(
311 base::Bind(&PrivetRegisterOperationImpl::OnPrivetInfoDone,
312 base::Unretained(this)));
313 info_operation_->Start();
316 PrivetRegisterOperationImpl::Cancelation::Cancelation(
317 PrivetHTTPClient* privet_client,
318 const std::string& user) {
319 url_fetcher_ =
320 privet_client->CreateURLFetcher(
321 CreatePrivetRegisterURL(kPrivetActionCancel, user),
322 net::URLFetcher::POST, this);
323 url_fetcher_->DoNotRetryOnTransientError();
324 url_fetcher_->Start();
327 PrivetRegisterOperationImpl::Cancelation::~Cancelation() {
330 void PrivetRegisterOperationImpl::Cancelation::OnError(
331 PrivetURLFetcher* fetcher,
332 PrivetURLFetcher::ErrorType error) {
335 void PrivetRegisterOperationImpl::Cancelation::OnParsedJson(
336 PrivetURLFetcher* fetcher,
337 const base::DictionaryValue& value,
338 bool has_error) {
341 void PrivetRegisterOperationImpl::Cancelation::Cleanup() {
342 // Nothing needs to be done, as base::Owned will delete this object,
343 // this callback is just here to pass ownership of the Cancelation to
344 // the message loop.
347 PrivetJSONOperationImpl::PrivetJSONOperationImpl(
348 PrivetHTTPClient* privet_client,
349 const std::string& path,
350 const std::string& query_params,
351 const PrivetJSONOperation::ResultCallback& callback)
352 : privet_client_(privet_client),
353 path_(path),
354 query_params_(query_params),
355 callback_(callback) {
358 PrivetJSONOperationImpl::~PrivetJSONOperationImpl() {
361 void PrivetJSONOperationImpl::Start() {
362 url_fetcher_ = privet_client_->CreateURLFetcher(
363 CreatePrivetParamURL(path_, query_params_), net::URLFetcher::GET, this);
364 url_fetcher_->DoNotRetryOnTransientError();
365 url_fetcher_->Start();
368 PrivetHTTPClient* PrivetJSONOperationImpl::GetHTTPClient() {
369 return privet_client_;
372 void PrivetJSONOperationImpl::OnError(
373 PrivetURLFetcher* fetcher,
374 PrivetURLFetcher::ErrorType error) {
375 callback_.Run(NULL);
378 void PrivetJSONOperationImpl::OnParsedJson(PrivetURLFetcher* fetcher,
379 const base::DictionaryValue& value,
380 bool has_error) {
381 callback_.Run(&value);
384 void PrivetJSONOperationImpl::OnNeedPrivetToken(
385 PrivetURLFetcher* fetcher,
386 const PrivetURLFetcher::TokenCallback& callback) {
387 privet_client_->RefreshPrivetToken(callback);
390 #if defined(ENABLE_PRINT_PREVIEW)
391 PrivetLocalPrintOperationImpl::PrivetLocalPrintOperationImpl(
392 PrivetHTTPClient* privet_client,
393 PrivetLocalPrintOperation::Delegate* delegate)
394 : privet_client_(privet_client),
395 delegate_(delegate),
396 use_pdf_(false),
397 has_extended_workflow_(false),
398 started_(false),
399 offline_(false),
400 invalid_job_retries_(0),
401 weak_factory_(this) {
404 PrivetLocalPrintOperationImpl::~PrivetLocalPrintOperationImpl() {
407 void PrivetLocalPrintOperationImpl::Start() {
408 DCHECK(!started_);
410 // We need to get the /info response so we can know which APIs are available.
411 // TODO(noamsml): Use cached info when available.
412 info_operation_ = privet_client_->CreateInfoOperation(
413 base::Bind(&PrivetLocalPrintOperationImpl::OnPrivetInfoDone,
414 base::Unretained(this)));
415 info_operation_->Start();
417 started_ = true;
420 void PrivetLocalPrintOperationImpl::OnPrivetInfoDone(
421 const base::DictionaryValue* value) {
422 if (value && !value->HasKey(kPrivetKeyError)) {
423 has_extended_workflow_ = false;
424 bool has_printing = false;
426 const base::ListValue* api_list;
427 if (value->GetList(kPrivetInfoKeyAPIList, &api_list)) {
428 for (size_t i = 0; i < api_list->GetSize(); i++) {
429 std::string api;
430 api_list->GetString(i, &api);
431 if (api == kPrivetSubmitdocPath) {
432 has_printing = true;
433 } else if (api == kPrivetCreatejobPath) {
434 has_extended_workflow_ = true;
439 if (!has_printing) {
440 delegate_->OnPrivetPrintingError(this, -1);
441 return;
444 StartInitialRequest();
445 } else {
446 delegate_->OnPrivetPrintingError(this, -1);
450 void PrivetLocalPrintOperationImpl::StartInitialRequest() {
451 use_pdf_ = false;
452 cloud_devices::printer::ContentTypesCapability content_types;
453 if (content_types.LoadFrom(capabilities_)) {
454 use_pdf_ = content_types.Contains(kPrivetContentTypePDF) ||
455 content_types.Contains(kPrivetContentTypeAny);
458 if (use_pdf_) {
459 StartPrinting();
460 } else {
461 StartConvertToPWG();
465 void PrivetLocalPrintOperationImpl::DoCreatejob() {
466 current_response_ = base::Bind(
467 &PrivetLocalPrintOperationImpl::OnCreatejobResponse,
468 base::Unretained(this));
470 url_fetcher_ = privet_client_->CreateURLFetcher(
471 CreatePrivetURL(kPrivetCreatejobPath), net::URLFetcher::POST, this);
472 url_fetcher_->SetUploadData(cloud_print::kContentTypeJSON,
473 ticket_.ToString());
475 url_fetcher_->Start();
478 void PrivetLocalPrintOperationImpl::DoSubmitdoc() {
479 current_response_ = base::Bind(
480 &PrivetLocalPrintOperationImpl::OnSubmitdocResponse,
481 base::Unretained(this));
483 GURL url = CreatePrivetURL(kPrivetSubmitdocPath);
485 url = net::AppendQueryParameter(url,
486 kPrivetURLKeyClientName,
487 kPrivetURLValueClientName);
489 if (!user_.empty()) {
490 url = net::AppendQueryParameter(url,
491 kPrivetURLKeyUserName,
492 user_);
495 base::string16 shortened_jobname;
497 gfx::ElideString(base::UTF8ToUTF16(jobname_),
498 kPrivetLocalPrintMaxJobNameLength,
499 &shortened_jobname);
501 if (!jobname_.empty()) {
502 url = net::AppendQueryParameter(
503 url, kPrivetURLKeyJobname, base::UTF16ToUTF8(shortened_jobname));
506 if (!jobid_.empty()) {
507 url = net::AppendQueryParameter(url,
508 kPrivetKeyJobID,
509 jobid_);
512 if (offline_) {
513 url = net::AppendQueryParameter(url,
514 kPrivetURLKeyOffline,
515 kPrivetURLValueOffline);
518 url_fetcher_ =
519 privet_client_->CreateURLFetcher(url, net::URLFetcher::POST, this);
521 if (!use_pdf_) {
522 url_fetcher_->SetUploadFilePath(kPrivetContentTypePWGRaster,
523 pwg_file_path_);
524 } else {
525 // TODO(noamsml): Move to file-based upload data?
526 std::string data_str((const char*)data_->front(), data_->size());
527 url_fetcher_->SetUploadData(kPrivetContentTypePDF, data_str);
530 url_fetcher_->Start();
533 void PrivetLocalPrintOperationImpl::StartPrinting() {
534 if (has_extended_workflow_ && jobid_.empty()) {
535 DoCreatejob();
536 } else {
537 DoSubmitdoc();
541 void PrivetLocalPrintOperationImpl::StartConvertToPWG() {
542 if (!pwg_raster_converter_)
543 pwg_raster_converter_ = PWGRasterConverter::CreateDefault();
545 pwg_raster_converter_->Start(
546 data_.get(),
547 PWGRasterConverter::GetConversionSettings(capabilities_, page_size_),
548 PWGRasterConverter::GetBitmapSettings(capabilities_, ticket_),
549 base::Bind(&PrivetLocalPrintOperationImpl::OnPWGRasterConverted,
550 base::Unretained(this)));
553 void PrivetLocalPrintOperationImpl::OnSubmitdocResponse(
554 bool has_error,
555 const base::DictionaryValue* value) {
556 std::string error;
557 // This error is only relevant in the case of extended workflow:
558 // If the print job ID is invalid, retry createjob and submitdoc,
559 // rather than simply retrying the current request.
560 if (has_error && value->GetString(kPrivetKeyError, &error)) {
561 if (has_extended_workflow_ &&
562 error == kPrivetErrorInvalidPrintJob &&
563 invalid_job_retries_ < kPrivetLocalPrintMaxRetries) {
564 invalid_job_retries_++;
566 int timeout = kPrivetLocalPrintDefaultTimeout;
567 value->GetInteger(kPrivetKeyTimeout, &timeout);
569 double random_scaling_factor =
570 1 + base::RandDouble() * kPrivetMaximumTimeRandomAddition;
572 timeout = static_cast<int>(timeout * random_scaling_factor);
574 timeout = std::max(timeout, kPrivetMinimumTimeout);
576 base::MessageLoop::current()->PostDelayedTask(
577 FROM_HERE, base::Bind(&PrivetLocalPrintOperationImpl::DoCreatejob,
578 weak_factory_.GetWeakPtr()),
579 base::TimeDelta::FromSeconds(timeout));
580 } else if (use_pdf_ && error == kPrivetErrorInvalidDocumentType) {
581 use_pdf_ = false;
582 StartConvertToPWG();
583 } else {
584 delegate_->OnPrivetPrintingError(this, 200);
587 return;
590 // If we've gotten this far, there are no errors, so we've effectively
591 // succeeded.
592 delegate_->OnPrivetPrintingDone(this);
595 void PrivetLocalPrintOperationImpl::OnCreatejobResponse(
596 bool has_error,
597 const base::DictionaryValue* value) {
598 if (has_error) {
599 delegate_->OnPrivetPrintingError(this, 200);
600 return;
603 // Try to get job ID from value. If not, jobid_ will be empty and we will use
604 // simple printing.
605 value->GetString(kPrivetKeyJobID, &jobid_);
607 DoSubmitdoc();
610 void PrivetLocalPrintOperationImpl::OnPWGRasterConverted(
611 bool success,
612 const base::FilePath& pwg_file_path) {
613 if (!success) {
614 delegate_->OnPrivetPrintingError(this, -1);
615 return;
618 DCHECK(!pwg_file_path.empty());
620 pwg_file_path_ = pwg_file_path;
621 StartPrinting();
624 PrivetHTTPClient* PrivetLocalPrintOperationImpl::GetHTTPClient() {
625 return privet_client_;
628 void PrivetLocalPrintOperationImpl::OnError(
629 PrivetURLFetcher* fetcher,
630 PrivetURLFetcher::ErrorType error) {
631 delegate_->OnPrivetPrintingError(this, -1);
634 void PrivetLocalPrintOperationImpl::OnParsedJson(
635 PrivetURLFetcher* fetcher,
636 const base::DictionaryValue& value,
637 bool has_error) {
638 DCHECK(!current_response_.is_null());
639 current_response_.Run(has_error, &value);
642 void PrivetLocalPrintOperationImpl::OnNeedPrivetToken(
643 PrivetURLFetcher* fetcher,
644 const PrivetURLFetcher::TokenCallback& callback) {
645 privet_client_->RefreshPrivetToken(callback);
648 void PrivetLocalPrintOperationImpl::SetData(
649 const scoped_refptr<base::RefCountedBytes>& data) {
650 DCHECK(!started_);
651 data_ = data;
654 void PrivetLocalPrintOperationImpl::SetTicket(const std::string& ticket) {
655 DCHECK(!started_);
656 ticket_.InitFromString(ticket);
659 void PrivetLocalPrintOperationImpl::SetCapabilities(
660 const std::string& capabilities) {
661 DCHECK(!started_);
662 capabilities_.InitFromString(capabilities);
665 void PrivetLocalPrintOperationImpl::SetUsername(const std::string& user) {
666 DCHECK(!started_);
667 user_ = user;
670 void PrivetLocalPrintOperationImpl::SetJobname(const std::string& jobname) {
671 DCHECK(!started_);
672 jobname_ = jobname;
675 void PrivetLocalPrintOperationImpl::SetOffline(bool offline) {
676 DCHECK(!started_);
677 offline_ = offline;
680 void PrivetLocalPrintOperationImpl::SetPageSize(const gfx::Size& page_size) {
681 DCHECK(!started_);
682 page_size_ = page_size;
685 void PrivetLocalPrintOperationImpl::SetPWGRasterConverterForTesting(
686 scoped_ptr<PWGRasterConverter> pwg_raster_converter) {
687 pwg_raster_converter_ = pwg_raster_converter.Pass();
689 #endif // ENABLE_PRINT_PREVIEW
691 PrivetHTTPClientImpl::PrivetHTTPClientImpl(
692 const std::string& name,
693 const net::HostPortPair& host_port,
694 net::URLRequestContextGetter* request_context)
695 : name_(name), request_context_(request_context), host_port_(host_port) {}
697 PrivetHTTPClientImpl::~PrivetHTTPClientImpl() {
700 const std::string& PrivetHTTPClientImpl::GetName() {
701 return name_;
704 scoped_ptr<PrivetJSONOperation> PrivetHTTPClientImpl::CreateInfoOperation(
705 const PrivetJSONOperation::ResultCallback& callback) {
706 return scoped_ptr<PrivetJSONOperation>(
707 new PrivetInfoOperationImpl(this, callback));
710 scoped_ptr<PrivetURLFetcher> PrivetHTTPClientImpl::CreateURLFetcher(
711 const GURL& url,
712 net::URLFetcher::RequestType request_type,
713 PrivetURLFetcher::Delegate* delegate) {
714 GURL::Replacements replacements;
715 replacements.SetHostStr(host_port_.host());
716 std::string port(base::IntToString(host_port_.port())); // Keep string alive.
717 replacements.SetPortStr(port);
718 return scoped_ptr<PrivetURLFetcher>(
719 new PrivetURLFetcher(url.ReplaceComponents(replacements),
720 request_type,
721 request_context_.get(),
722 delegate));
725 void PrivetHTTPClientImpl::RefreshPrivetToken(
726 const PrivetURLFetcher::TokenCallback& callback) {
727 token_callbacks_.push_back(callback);
729 if (!info_operation_) {
730 info_operation_ = CreateInfoOperation(
731 base::Bind(&PrivetHTTPClientImpl::OnPrivetInfoDone,
732 base::Unretained(this)));
733 info_operation_->Start();
737 void PrivetHTTPClientImpl::OnPrivetInfoDone(
738 const base::DictionaryValue* value) {
739 info_operation_.reset();
740 std::string token;
742 // If this does not succeed, token will be empty, and an empty string
743 // is our sentinel value, since empty X-Privet-Tokens are not allowed.
744 if (value) {
745 value->GetString(kPrivetInfoKeyToken, &token);
748 TokenCallbackVector token_callbacks;
749 token_callbacks_.swap(token_callbacks);
751 for (TokenCallbackVector::iterator i = token_callbacks.begin();
752 i != token_callbacks.end(); i++) {
753 i->Run(token);
757 PrivetV1HTTPClientImpl::PrivetV1HTTPClientImpl(
758 scoped_ptr<PrivetHTTPClient> info_client)
759 : info_client_(info_client.Pass()) {
762 PrivetV1HTTPClientImpl::~PrivetV1HTTPClientImpl() {
765 const std::string& PrivetV1HTTPClientImpl::GetName() {
766 return info_client()->GetName();
769 scoped_ptr<PrivetJSONOperation> PrivetV1HTTPClientImpl::CreateInfoOperation(
770 const PrivetJSONOperation::ResultCallback& callback) {
771 return info_client()->CreateInfoOperation(callback);
774 scoped_ptr<PrivetRegisterOperation>
775 PrivetV1HTTPClientImpl::CreateRegisterOperation(
776 const std::string& user,
777 PrivetRegisterOperation::Delegate* delegate) {
778 return scoped_ptr<PrivetRegisterOperation>(
779 new PrivetRegisterOperationImpl(info_client(), user, delegate));
782 scoped_ptr<PrivetJSONOperation>
783 PrivetV1HTTPClientImpl::CreateCapabilitiesOperation(
784 const PrivetJSONOperation::ResultCallback& callback) {
785 return scoped_ptr<PrivetJSONOperation>(new PrivetJSONOperationImpl(
786 info_client(), kPrivetCapabilitiesPath, "", callback));
789 scoped_ptr<PrivetLocalPrintOperation>
790 PrivetV1HTTPClientImpl::CreateLocalPrintOperation(
791 PrivetLocalPrintOperation::Delegate* delegate) {
792 #if defined(ENABLE_PRINT_PREVIEW)
793 return scoped_ptr<PrivetLocalPrintOperation>(
794 new PrivetLocalPrintOperationImpl(info_client(), delegate));
795 #else
796 return scoped_ptr<PrivetLocalPrintOperation>();
797 #endif // ENABLE_PRINT_PREVIEW
800 } // namespace local_discovery