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"
10 #include "base/bind.h"
11 #include "base/location.h"
12 #include "base/rand_util.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "chrome/browser/local_discovery/privet_constants.h"
18 #include "net/base/url_util.h"
21 #if defined(ENABLE_PRINT_PREVIEW)
22 #include "chrome/browser/local_discovery/pwg_raster_converter.h"
23 #include "components/cloud_devices/common/printer_description.h"
24 #include "printing/pdf_render_settings.h"
25 #include "printing/pwg_raster_settings.h"
26 #include "ui/gfx/text_elider.h"
27 #endif // ENABLE_PRINT_PREVIEW
29 namespace cloud_print
{
30 extern const char kContentTypeJSON
[];
33 namespace local_discovery
{
36 const char kUrlPlaceHolder
[] = "http://host/";
37 const char kPrivetRegisterActionArgName
[] = "action";
38 const char kPrivetRegisterUserArgName
[] = "user";
40 const int kPrivetCancelationTimeoutSeconds
= 3;
42 #if defined(ENABLE_PRINT_PREVIEW)
43 const char kPrivetURLKeyUserName
[] = "user_name";
44 const char kPrivetURLKeyClientName
[] = "client_name";
45 const char kPrivetURLKeyJobname
[] = "job_name";
46 const char kPrivetURLKeyOffline
[] = "offline";
47 const char kPrivetURLValueOffline
[] = "1";
48 const char kPrivetURLValueClientName
[] = "Chrome";
50 const char kPrivetContentTypePDF
[] = "application/pdf";
51 const char kPrivetContentTypePWGRaster
[] = "image/pwg-raster";
52 const char kPrivetContentTypeAny
[] = "*/*";
54 const char kPrivetKeyJobID
[] = "job_id";
56 const int kPrivetLocalPrintMaxRetries
= 2;
57 const int kPrivetLocalPrintDefaultTimeout
= 5;
59 const size_t kPrivetLocalPrintMaxJobNameLength
= 64;
60 #endif // ENABLE_PRINT_PREVIEW
62 GURL
CreatePrivetURL(const std::string
& path
) {
63 GURL
url(kUrlPlaceHolder
);
64 GURL::Replacements replacements
;
65 replacements
.SetPathStr(path
);
66 return url
.ReplaceComponents(replacements
);
69 GURL
CreatePrivetRegisterURL(const std::string
& action
,
70 const std::string
& user
) {
71 GURL url
= CreatePrivetURL(kPrivetRegisterPath
);
72 url
= net::AppendQueryParameter(url
, kPrivetRegisterActionArgName
, action
);
73 return net::AppendQueryParameter(url
, kPrivetRegisterUserArgName
, user
);
76 GURL
CreatePrivetParamURL(const std::string
& path
,
77 const std::string
& query_params
) {
78 GURL
url(kUrlPlaceHolder
);
79 GURL::Replacements replacements
;
80 replacements
.SetPathStr(path
);
81 if (!query_params
.empty()) {
82 replacements
.SetQueryStr(query_params
);
84 return url
.ReplaceComponents(replacements
);
89 PrivetInfoOperationImpl::PrivetInfoOperationImpl(
90 PrivetHTTPClient
* privet_client
,
91 const PrivetJSONOperation::ResultCallback
& callback
)
92 : privet_client_(privet_client
), callback_(callback
) {
95 PrivetInfoOperationImpl::~PrivetInfoOperationImpl() {
98 void PrivetInfoOperationImpl::Start() {
99 url_fetcher_
= privet_client_
->CreateURLFetcher(
100 CreatePrivetURL(kPrivetInfoPath
), net::URLFetcher::GET
, this);
102 url_fetcher_
->DoNotRetryOnTransientError();
103 url_fetcher_
->SendEmptyPrivetToken();
105 url_fetcher_
->Start();
108 PrivetHTTPClient
* PrivetInfoOperationImpl::GetHTTPClient() {
109 return privet_client_
;
112 void PrivetInfoOperationImpl::OnError(PrivetURLFetcher
* fetcher
,
113 PrivetURLFetcher::ErrorType error
) {
117 void PrivetInfoOperationImpl::OnParsedJson(PrivetURLFetcher
* fetcher
,
118 const base::DictionaryValue
& value
,
120 callback_
.Run(&value
);
123 PrivetRegisterOperationImpl::PrivetRegisterOperationImpl(
124 PrivetHTTPClient
* privet_client
,
125 const std::string
& user
,
126 PrivetRegisterOperation::Delegate
* delegate
)
129 privet_client_(privet_client
),
133 PrivetRegisterOperationImpl::~PrivetRegisterOperationImpl() {
136 void PrivetRegisterOperationImpl::Start() {
138 next_response_handler_
=
139 base::Bind(&PrivetRegisterOperationImpl::StartResponse
,
140 base::Unretained(this));
141 SendRequest(kPrivetActionStart
);
144 void PrivetRegisterOperationImpl::Cancel() {
145 url_fetcher_
.reset();
148 // Owned by the message loop.
149 Cancelation
* cancelation
= new Cancelation(privet_client_
, user_
);
151 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
153 base::Bind(&PrivetRegisterOperationImpl::Cancelation::Cleanup
,
154 base::Owned(cancelation
)),
155 base::TimeDelta::FromSeconds(kPrivetCancelationTimeoutSeconds
));
161 void PrivetRegisterOperationImpl::CompleteRegistration() {
162 next_response_handler_
=
163 base::Bind(&PrivetRegisterOperationImpl::CompleteResponse
,
164 base::Unretained(this));
165 SendRequest(kPrivetActionComplete
);
168 PrivetHTTPClient
* PrivetRegisterOperationImpl::GetHTTPClient() {
169 return privet_client_
;
172 void PrivetRegisterOperationImpl::OnError(PrivetURLFetcher
* fetcher
,
173 PrivetURLFetcher::ErrorType error
) {
175 int visible_http_code
= -1;
176 FailureReason reason
= FAILURE_NETWORK
;
178 if (error
== PrivetURLFetcher::RESPONSE_CODE_ERROR
) {
179 visible_http_code
= fetcher
->response_code();
180 reason
= FAILURE_HTTP_ERROR
;
181 } else if (error
== PrivetURLFetcher::JSON_PARSE_ERROR
) {
182 reason
= FAILURE_MALFORMED_RESPONSE
;
183 } else if (error
== PrivetURLFetcher::TOKEN_ERROR
) {
184 reason
= FAILURE_TOKEN
;
185 } else if (error
== PrivetURLFetcher::RETRY_ERROR
) {
186 reason
= FAILURE_RETRY
;
189 delegate_
->OnPrivetRegisterError(this,
196 void PrivetRegisterOperationImpl::OnParsedJson(
197 PrivetURLFetcher
* fetcher
,
198 const base::DictionaryValue
& value
,
202 value
.GetString(kPrivetKeyError
, &error
);
205 delegate_
->OnPrivetRegisterError(this,
208 fetcher
->response_code(),
213 // TODO(noamsml): Match the user&action with the user&action in the object,
214 // and fail if different.
216 next_response_handler_
.Run(value
);
219 void PrivetRegisterOperationImpl::OnNeedPrivetToken(
220 PrivetURLFetcher
* fetcher
,
221 const PrivetURLFetcher::TokenCallback
& callback
) {
222 privet_client_
->RefreshPrivetToken(callback
);
225 void PrivetRegisterOperationImpl::SendRequest(const std::string
& action
) {
226 current_action_
= action
;
227 url_fetcher_
= privet_client_
->CreateURLFetcher(
228 CreatePrivetRegisterURL(action
, user_
), net::URLFetcher::POST
, this);
229 url_fetcher_
->Start();
232 void PrivetRegisterOperationImpl::StartResponse(
233 const base::DictionaryValue
& value
) {
234 next_response_handler_
=
235 base::Bind(&PrivetRegisterOperationImpl::GetClaimTokenResponse
,
236 base::Unretained(this));
238 SendRequest(kPrivetActionGetClaimToken
);
241 void PrivetRegisterOperationImpl::GetClaimTokenResponse(
242 const base::DictionaryValue
& value
) {
243 std::string claimUrl
;
244 std::string claimToken
;
245 bool got_url
= value
.GetString(kPrivetKeyClaimURL
, &claimUrl
);
246 bool got_token
= value
.GetString(kPrivetKeyClaimToken
, &claimToken
);
247 if (got_url
|| got_token
) {
248 delegate_
->OnPrivetRegisterClaimToken(this, claimToken
, GURL(claimUrl
));
250 delegate_
->OnPrivetRegisterError(this,
252 FAILURE_MALFORMED_RESPONSE
,
258 void PrivetRegisterOperationImpl::CompleteResponse(
259 const base::DictionaryValue
& value
) {
261 value
.GetString(kPrivetKeyDeviceID
, &id
);
264 StartInfoOperation();
267 void PrivetRegisterOperationImpl::OnPrivetInfoDone(
268 const base::DictionaryValue
* value
) {
269 // TODO(noamsml): Simplify error case and depracate HTTP error value in
270 // OnPrivetRegisterError.
272 delegate_
->OnPrivetRegisterError(this,
273 kPrivetActionNameInfo
,
280 if (!value
->HasKey(kPrivetInfoKeyID
)) {
281 if (value
->HasKey(kPrivetKeyError
)) {
282 delegate_
->OnPrivetRegisterError(this,
283 kPrivetActionNameInfo
,
288 delegate_
->OnPrivetRegisterError(this,
289 kPrivetActionNameInfo
,
290 FAILURE_MALFORMED_RESPONSE
,
299 if (!value
->GetString(kPrivetInfoKeyID
, &id
) ||
300 id
!= expected_id_
) {
301 delegate_
->OnPrivetRegisterError(this,
302 kPrivetActionNameInfo
,
303 FAILURE_MALFORMED_RESPONSE
,
307 delegate_
->OnPrivetRegisterDone(this, id
);
311 void PrivetRegisterOperationImpl::StartInfoOperation() {
312 info_operation_
= privet_client_
->CreateInfoOperation(
313 base::Bind(&PrivetRegisterOperationImpl::OnPrivetInfoDone
,
314 base::Unretained(this)));
315 info_operation_
->Start();
318 PrivetRegisterOperationImpl::Cancelation::Cancelation(
319 PrivetHTTPClient
* privet_client
,
320 const std::string
& user
) {
322 privet_client
->CreateURLFetcher(
323 CreatePrivetRegisterURL(kPrivetActionCancel
, user
),
324 net::URLFetcher::POST
, this);
325 url_fetcher_
->DoNotRetryOnTransientError();
326 url_fetcher_
->Start();
329 PrivetRegisterOperationImpl::Cancelation::~Cancelation() {
332 void PrivetRegisterOperationImpl::Cancelation::OnError(
333 PrivetURLFetcher
* fetcher
,
334 PrivetURLFetcher::ErrorType error
) {
337 void PrivetRegisterOperationImpl::Cancelation::OnParsedJson(
338 PrivetURLFetcher
* fetcher
,
339 const base::DictionaryValue
& value
,
343 void PrivetRegisterOperationImpl::Cancelation::Cleanup() {
344 // Nothing needs to be done, as base::Owned will delete this object,
345 // this callback is just here to pass ownership of the Cancelation to
349 PrivetJSONOperationImpl::PrivetJSONOperationImpl(
350 PrivetHTTPClient
* privet_client
,
351 const std::string
& path
,
352 const std::string
& query_params
,
353 const PrivetJSONOperation::ResultCallback
& callback
)
354 : privet_client_(privet_client
),
356 query_params_(query_params
),
357 callback_(callback
) {
360 PrivetJSONOperationImpl::~PrivetJSONOperationImpl() {
363 void PrivetJSONOperationImpl::Start() {
364 url_fetcher_
= privet_client_
->CreateURLFetcher(
365 CreatePrivetParamURL(path_
, query_params_
), net::URLFetcher::GET
, this);
366 url_fetcher_
->DoNotRetryOnTransientError();
367 url_fetcher_
->Start();
370 PrivetHTTPClient
* PrivetJSONOperationImpl::GetHTTPClient() {
371 return privet_client_
;
374 void PrivetJSONOperationImpl::OnError(
375 PrivetURLFetcher
* fetcher
,
376 PrivetURLFetcher::ErrorType error
) {
380 void PrivetJSONOperationImpl::OnParsedJson(PrivetURLFetcher
* fetcher
,
381 const base::DictionaryValue
& value
,
383 callback_
.Run(&value
);
386 void PrivetJSONOperationImpl::OnNeedPrivetToken(
387 PrivetURLFetcher
* fetcher
,
388 const PrivetURLFetcher::TokenCallback
& callback
) {
389 privet_client_
->RefreshPrivetToken(callback
);
392 #if defined(ENABLE_PRINT_PREVIEW)
393 PrivetLocalPrintOperationImpl::PrivetLocalPrintOperationImpl(
394 PrivetHTTPClient
* privet_client
,
395 PrivetLocalPrintOperation::Delegate
* delegate
)
396 : privet_client_(privet_client
),
399 has_extended_workflow_(false),
402 invalid_job_retries_(0),
403 weak_factory_(this) {
406 PrivetLocalPrintOperationImpl::~PrivetLocalPrintOperationImpl() {
409 void PrivetLocalPrintOperationImpl::Start() {
412 // We need to get the /info response so we can know which APIs are available.
413 // TODO(noamsml): Use cached info when available.
414 info_operation_
= privet_client_
->CreateInfoOperation(
415 base::Bind(&PrivetLocalPrintOperationImpl::OnPrivetInfoDone
,
416 base::Unretained(this)));
417 info_operation_
->Start();
422 void PrivetLocalPrintOperationImpl::OnPrivetInfoDone(
423 const base::DictionaryValue
* value
) {
424 if (value
&& !value
->HasKey(kPrivetKeyError
)) {
425 has_extended_workflow_
= false;
426 bool has_printing
= false;
428 const base::ListValue
* api_list
;
429 if (value
->GetList(kPrivetInfoKeyAPIList
, &api_list
)) {
430 for (size_t i
= 0; i
< api_list
->GetSize(); i
++) {
432 api_list
->GetString(i
, &api
);
433 if (api
== kPrivetSubmitdocPath
) {
435 } else if (api
== kPrivetCreatejobPath
) {
436 has_extended_workflow_
= true;
442 delegate_
->OnPrivetPrintingError(this, -1);
446 StartInitialRequest();
448 delegate_
->OnPrivetPrintingError(this, -1);
452 void PrivetLocalPrintOperationImpl::StartInitialRequest() {
454 cloud_devices::printer::ContentTypesCapability content_types
;
455 if (content_types
.LoadFrom(capabilities_
)) {
456 use_pdf_
= content_types
.Contains(kPrivetContentTypePDF
) ||
457 content_types
.Contains(kPrivetContentTypeAny
);
467 void PrivetLocalPrintOperationImpl::DoCreatejob() {
468 current_response_
= base::Bind(
469 &PrivetLocalPrintOperationImpl::OnCreatejobResponse
,
470 base::Unretained(this));
472 url_fetcher_
= privet_client_
->CreateURLFetcher(
473 CreatePrivetURL(kPrivetCreatejobPath
), net::URLFetcher::POST
, this);
474 url_fetcher_
->SetUploadData(cloud_print::kContentTypeJSON
,
477 url_fetcher_
->Start();
480 void PrivetLocalPrintOperationImpl::DoSubmitdoc() {
481 current_response_
= base::Bind(
482 &PrivetLocalPrintOperationImpl::OnSubmitdocResponse
,
483 base::Unretained(this));
485 GURL url
= CreatePrivetURL(kPrivetSubmitdocPath
);
487 url
= net::AppendQueryParameter(url
,
488 kPrivetURLKeyClientName
,
489 kPrivetURLValueClientName
);
491 if (!user_
.empty()) {
492 url
= net::AppendQueryParameter(url
,
493 kPrivetURLKeyUserName
,
497 base::string16 shortened_jobname
;
499 gfx::ElideString(base::UTF8ToUTF16(jobname_
),
500 kPrivetLocalPrintMaxJobNameLength
,
503 if (!jobname_
.empty()) {
504 url
= net::AppendQueryParameter(
505 url
, kPrivetURLKeyJobname
, base::UTF16ToUTF8(shortened_jobname
));
508 if (!jobid_
.empty()) {
509 url
= net::AppendQueryParameter(url
,
515 url
= net::AppendQueryParameter(url
,
516 kPrivetURLKeyOffline
,
517 kPrivetURLValueOffline
);
521 privet_client_
->CreateURLFetcher(url
, net::URLFetcher::POST
, this);
524 url_fetcher_
->SetUploadFilePath(kPrivetContentTypePWGRaster
,
527 // TODO(noamsml): Move to file-based upload data?
528 std::string
data_str((const char*)data_
->front(), data_
->size());
529 url_fetcher_
->SetUploadData(kPrivetContentTypePDF
, data_str
);
532 url_fetcher_
->Start();
535 void PrivetLocalPrintOperationImpl::StartPrinting() {
536 if (has_extended_workflow_
&& jobid_
.empty()) {
543 void PrivetLocalPrintOperationImpl::StartConvertToPWG() {
544 if (!pwg_raster_converter_
)
545 pwg_raster_converter_
= PWGRasterConverter::CreateDefault();
547 pwg_raster_converter_
->Start(
549 PWGRasterConverter::GetConversionSettings(capabilities_
, page_size_
),
550 PWGRasterConverter::GetBitmapSettings(capabilities_
, ticket_
),
551 base::Bind(&PrivetLocalPrintOperationImpl::OnPWGRasterConverted
,
552 base::Unretained(this)));
555 void PrivetLocalPrintOperationImpl::OnSubmitdocResponse(
557 const base::DictionaryValue
* value
) {
559 // This error is only relevant in the case of extended workflow:
560 // If the print job ID is invalid, retry createjob and submitdoc,
561 // rather than simply retrying the current request.
562 if (has_error
&& value
->GetString(kPrivetKeyError
, &error
)) {
563 if (has_extended_workflow_
&&
564 error
== kPrivetErrorInvalidPrintJob
&&
565 invalid_job_retries_
< kPrivetLocalPrintMaxRetries
) {
566 invalid_job_retries_
++;
568 int timeout
= kPrivetLocalPrintDefaultTimeout
;
569 value
->GetInteger(kPrivetKeyTimeout
, &timeout
);
571 double random_scaling_factor
=
572 1 + base::RandDouble() * kPrivetMaximumTimeRandomAddition
;
574 timeout
= static_cast<int>(timeout
* random_scaling_factor
);
576 timeout
= std::max(timeout
, kPrivetMinimumTimeout
);
578 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
579 FROM_HERE
, base::Bind(&PrivetLocalPrintOperationImpl::DoCreatejob
,
580 weak_factory_
.GetWeakPtr()),
581 base::TimeDelta::FromSeconds(timeout
));
582 } else if (use_pdf_
&& error
== kPrivetErrorInvalidDocumentType
) {
586 delegate_
->OnPrivetPrintingError(this, 200);
592 // If we've gotten this far, there are no errors, so we've effectively
594 delegate_
->OnPrivetPrintingDone(this);
597 void PrivetLocalPrintOperationImpl::OnCreatejobResponse(
599 const base::DictionaryValue
* value
) {
601 delegate_
->OnPrivetPrintingError(this, 200);
605 // Try to get job ID from value. If not, jobid_ will be empty and we will use
607 value
->GetString(kPrivetKeyJobID
, &jobid_
);
612 void PrivetLocalPrintOperationImpl::OnPWGRasterConverted(
614 const base::FilePath
& pwg_file_path
) {
616 delegate_
->OnPrivetPrintingError(this, -1);
620 DCHECK(!pwg_file_path
.empty());
622 pwg_file_path_
= pwg_file_path
;
626 PrivetHTTPClient
* PrivetLocalPrintOperationImpl::GetHTTPClient() {
627 return privet_client_
;
630 void PrivetLocalPrintOperationImpl::OnError(
631 PrivetURLFetcher
* fetcher
,
632 PrivetURLFetcher::ErrorType error
) {
633 delegate_
->OnPrivetPrintingError(this, -1);
636 void PrivetLocalPrintOperationImpl::OnParsedJson(
637 PrivetURLFetcher
* fetcher
,
638 const base::DictionaryValue
& value
,
640 DCHECK(!current_response_
.is_null());
641 current_response_
.Run(has_error
, &value
);
644 void PrivetLocalPrintOperationImpl::OnNeedPrivetToken(
645 PrivetURLFetcher
* fetcher
,
646 const PrivetURLFetcher::TokenCallback
& callback
) {
647 privet_client_
->RefreshPrivetToken(callback
);
650 void PrivetLocalPrintOperationImpl::SetData(
651 const scoped_refptr
<base::RefCountedBytes
>& data
) {
656 void PrivetLocalPrintOperationImpl::SetTicket(const std::string
& ticket
) {
658 ticket_
.InitFromString(ticket
);
661 void PrivetLocalPrintOperationImpl::SetCapabilities(
662 const std::string
& capabilities
) {
664 capabilities_
.InitFromString(capabilities
);
667 void PrivetLocalPrintOperationImpl::SetUsername(const std::string
& user
) {
672 void PrivetLocalPrintOperationImpl::SetJobname(const std::string
& jobname
) {
677 void PrivetLocalPrintOperationImpl::SetOffline(bool offline
) {
682 void PrivetLocalPrintOperationImpl::SetPageSize(const gfx::Size
& page_size
) {
684 page_size_
= page_size
;
687 void PrivetLocalPrintOperationImpl::SetPWGRasterConverterForTesting(
688 scoped_ptr
<PWGRasterConverter
> pwg_raster_converter
) {
689 pwg_raster_converter_
= pwg_raster_converter
.Pass();
691 #endif // ENABLE_PRINT_PREVIEW
693 PrivetHTTPClientImpl::PrivetHTTPClientImpl(
694 const std::string
& name
,
695 const net::HostPortPair
& host_port
,
696 net::URLRequestContextGetter
* request_context
)
697 : name_(name
), request_context_(request_context
), host_port_(host_port
) {}
699 PrivetHTTPClientImpl::~PrivetHTTPClientImpl() {
702 const std::string
& PrivetHTTPClientImpl::GetName() {
706 scoped_ptr
<PrivetJSONOperation
> PrivetHTTPClientImpl::CreateInfoOperation(
707 const PrivetJSONOperation::ResultCallback
& callback
) {
708 return scoped_ptr
<PrivetJSONOperation
>(
709 new PrivetInfoOperationImpl(this, callback
));
712 scoped_ptr
<PrivetURLFetcher
> PrivetHTTPClientImpl::CreateURLFetcher(
714 net::URLFetcher::RequestType request_type
,
715 PrivetURLFetcher::Delegate
* delegate
) {
716 GURL::Replacements replacements
;
717 replacements
.SetHostStr(host_port_
.host());
718 std::string
port(base::IntToString(host_port_
.port())); // Keep string alive.
719 replacements
.SetPortStr(port
);
720 return scoped_ptr
<PrivetURLFetcher
>(
721 new PrivetURLFetcher(url
.ReplaceComponents(replacements
),
723 request_context_
.get(),
727 void PrivetHTTPClientImpl::RefreshPrivetToken(
728 const PrivetURLFetcher::TokenCallback
& callback
) {
729 token_callbacks_
.push_back(callback
);
731 if (!info_operation_
) {
732 info_operation_
= CreateInfoOperation(
733 base::Bind(&PrivetHTTPClientImpl::OnPrivetInfoDone
,
734 base::Unretained(this)));
735 info_operation_
->Start();
739 void PrivetHTTPClientImpl::OnPrivetInfoDone(
740 const base::DictionaryValue
* value
) {
741 info_operation_
.reset();
744 // If this does not succeed, token will be empty, and an empty string
745 // is our sentinel value, since empty X-Privet-Tokens are not allowed.
747 value
->GetString(kPrivetInfoKeyToken
, &token
);
750 TokenCallbackVector token_callbacks
;
751 token_callbacks_
.swap(token_callbacks
);
753 for (TokenCallbackVector::iterator i
= token_callbacks
.begin();
754 i
!= token_callbacks
.end(); i
++) {
759 PrivetV1HTTPClientImpl::PrivetV1HTTPClientImpl(
760 scoped_ptr
<PrivetHTTPClient
> info_client
)
761 : info_client_(info_client
.Pass()) {
764 PrivetV1HTTPClientImpl::~PrivetV1HTTPClientImpl() {
767 const std::string
& PrivetV1HTTPClientImpl::GetName() {
768 return info_client()->GetName();
771 scoped_ptr
<PrivetJSONOperation
> PrivetV1HTTPClientImpl::CreateInfoOperation(
772 const PrivetJSONOperation::ResultCallback
& callback
) {
773 return info_client()->CreateInfoOperation(callback
);
776 scoped_ptr
<PrivetRegisterOperation
>
777 PrivetV1HTTPClientImpl::CreateRegisterOperation(
778 const std::string
& user
,
779 PrivetRegisterOperation::Delegate
* delegate
) {
780 return scoped_ptr
<PrivetRegisterOperation
>(
781 new PrivetRegisterOperationImpl(info_client(), user
, delegate
));
784 scoped_ptr
<PrivetJSONOperation
>
785 PrivetV1HTTPClientImpl::CreateCapabilitiesOperation(
786 const PrivetJSONOperation::ResultCallback
& callback
) {
787 return scoped_ptr
<PrivetJSONOperation
>(new PrivetJSONOperationImpl(
788 info_client(), kPrivetCapabilitiesPath
, "", callback
));
791 scoped_ptr
<PrivetLocalPrintOperation
>
792 PrivetV1HTTPClientImpl::CreateLocalPrintOperation(
793 PrivetLocalPrintOperation::Delegate
* delegate
) {
794 #if defined(ENABLE_PRINT_PREVIEW)
795 return scoped_ptr
<PrivetLocalPrintOperation
>(
796 new PrivetLocalPrintOperationImpl(info_client(), delegate
));
798 return scoped_ptr
<PrivetLocalPrintOperation
>();
799 #endif // ENABLE_PRINT_PREVIEW
802 } // namespace local_discovery