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 "chrome/common/cloud_print/cloud_print_constants.h"
19 #include "net/base/url_util.h"
22 #if defined(ENABLE_PRINT_PREVIEW)
23 #include "chrome/browser/local_discovery/pwg_raster_converter.h"
24 #include "components/cloud_devices/common/printer_description.h"
25 #include "printing/pdf_render_settings.h"
26 #include "printing/pwg_raster_settings.h"
27 #include "ui/gfx/text_elider.h"
28 #endif // ENABLE_PRINT_PREVIEW
30 namespace local_discovery
{
33 const char kUrlPlaceHolder
[] = "http://host/";
34 const char kPrivetRegisterActionArgName
[] = "action";
35 const char kPrivetRegisterUserArgName
[] = "user";
37 const int kPrivetCancelationTimeoutSeconds
= 3;
39 #if defined(ENABLE_PRINT_PREVIEW)
40 const char kPrivetURLKeyUserName
[] = "user_name";
41 const char kPrivetURLKeyClientName
[] = "client_name";
42 const char kPrivetURLKeyJobname
[] = "job_name";
43 const char kPrivetURLKeyOffline
[] = "offline";
44 const char kPrivetURLValueOffline
[] = "1";
45 const char kPrivetURLValueClientName
[] = "Chrome";
47 const char kPrivetContentTypePDF
[] = "application/pdf";
48 const char kPrivetContentTypePWGRaster
[] = "image/pwg-raster";
49 const char kPrivetContentTypeAny
[] = "*/*";
51 const char kPrivetKeyJobID
[] = "job_id";
53 const int kPrivetLocalPrintMaxRetries
= 2;
54 const int kPrivetLocalPrintDefaultTimeout
= 5;
56 const size_t kPrivetLocalPrintMaxJobNameLength
= 64;
57 #endif // ENABLE_PRINT_PREVIEW
59 GURL
CreatePrivetURL(const std::string
& path
) {
60 GURL
url(kUrlPlaceHolder
);
61 GURL::Replacements replacements
;
62 replacements
.SetPathStr(path
);
63 return url
.ReplaceComponents(replacements
);
66 GURL
CreatePrivetRegisterURL(const std::string
& action
,
67 const std::string
& user
) {
68 GURL url
= CreatePrivetURL(kPrivetRegisterPath
);
69 url
= net::AppendQueryParameter(url
, kPrivetRegisterActionArgName
, action
);
70 return net::AppendQueryParameter(url
, kPrivetRegisterUserArgName
, user
);
73 GURL
CreatePrivetParamURL(const std::string
& path
,
74 const std::string
& query_params
) {
75 GURL
url(kUrlPlaceHolder
);
76 GURL::Replacements replacements
;
77 replacements
.SetPathStr(path
);
78 if (!query_params
.empty()) {
79 replacements
.SetQueryStr(query_params
);
81 return url
.ReplaceComponents(replacements
);
86 PrivetInfoOperationImpl::PrivetInfoOperationImpl(
87 PrivetHTTPClient
* privet_client
,
88 const PrivetJSONOperation::ResultCallback
& callback
)
89 : privet_client_(privet_client
), callback_(callback
) {
92 PrivetInfoOperationImpl::~PrivetInfoOperationImpl() {
95 void PrivetInfoOperationImpl::Start() {
96 url_fetcher_
= privet_client_
->CreateURLFetcher(
97 CreatePrivetURL(kPrivetInfoPath
), net::URLFetcher::GET
, this);
99 url_fetcher_
->DoNotRetryOnTransientError();
100 url_fetcher_
->SendEmptyPrivetToken();
102 url_fetcher_
->Start();
105 PrivetHTTPClient
* PrivetInfoOperationImpl::GetHTTPClient() {
106 return privet_client_
;
109 void PrivetInfoOperationImpl::OnError(PrivetURLFetcher
* fetcher
,
110 PrivetURLFetcher::ErrorType error
) {
114 void PrivetInfoOperationImpl::OnParsedJson(PrivetURLFetcher
* fetcher
,
115 const base::DictionaryValue
& value
,
117 callback_
.Run(&value
);
120 PrivetRegisterOperationImpl::PrivetRegisterOperationImpl(
121 PrivetHTTPClient
* privet_client
,
122 const std::string
& user
,
123 PrivetRegisterOperation::Delegate
* delegate
)
126 privet_client_(privet_client
),
130 PrivetRegisterOperationImpl::~PrivetRegisterOperationImpl() {
133 void PrivetRegisterOperationImpl::Start() {
135 next_response_handler_
=
136 base::Bind(&PrivetRegisterOperationImpl::StartResponse
,
137 base::Unretained(this));
138 SendRequest(kPrivetActionStart
);
141 void PrivetRegisterOperationImpl::Cancel() {
142 url_fetcher_
.reset();
145 // Owned by the message loop.
146 Cancelation
* cancelation
= new Cancelation(privet_client_
, user_
);
148 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
150 base::Bind(&PrivetRegisterOperationImpl::Cancelation::Cleanup
,
151 base::Owned(cancelation
)),
152 base::TimeDelta::FromSeconds(kPrivetCancelationTimeoutSeconds
));
158 void PrivetRegisterOperationImpl::CompleteRegistration() {
159 next_response_handler_
=
160 base::Bind(&PrivetRegisterOperationImpl::CompleteResponse
,
161 base::Unretained(this));
162 SendRequest(kPrivetActionComplete
);
165 PrivetHTTPClient
* PrivetRegisterOperationImpl::GetHTTPClient() {
166 return privet_client_
;
169 void PrivetRegisterOperationImpl::OnError(PrivetURLFetcher
* fetcher
,
170 PrivetURLFetcher::ErrorType error
) {
172 int visible_http_code
= -1;
173 FailureReason reason
= FAILURE_NETWORK
;
175 if (error
== PrivetURLFetcher::RESPONSE_CODE_ERROR
) {
176 visible_http_code
= fetcher
->response_code();
177 reason
= FAILURE_HTTP_ERROR
;
178 } else if (error
== PrivetURLFetcher::JSON_PARSE_ERROR
) {
179 reason
= FAILURE_MALFORMED_RESPONSE
;
180 } else if (error
== PrivetURLFetcher::TOKEN_ERROR
) {
181 reason
= FAILURE_TOKEN
;
182 } else if (error
== PrivetURLFetcher::RETRY_ERROR
) {
183 reason
= FAILURE_RETRY
;
186 delegate_
->OnPrivetRegisterError(this,
193 void PrivetRegisterOperationImpl::OnParsedJson(
194 PrivetURLFetcher
* fetcher
,
195 const base::DictionaryValue
& value
,
199 value
.GetString(kPrivetKeyError
, &error
);
202 delegate_
->OnPrivetRegisterError(this,
205 fetcher
->response_code(),
210 // TODO(noamsml): Match the user&action with the user&action in the object,
211 // and fail if different.
213 next_response_handler_
.Run(value
);
216 void PrivetRegisterOperationImpl::OnNeedPrivetToken(
217 PrivetURLFetcher
* fetcher
,
218 const PrivetURLFetcher::TokenCallback
& callback
) {
219 privet_client_
->RefreshPrivetToken(callback
);
222 void PrivetRegisterOperationImpl::SendRequest(const std::string
& action
) {
223 current_action_
= action
;
224 url_fetcher_
= privet_client_
->CreateURLFetcher(
225 CreatePrivetRegisterURL(action
, user_
), net::URLFetcher::POST
, this);
226 url_fetcher_
->Start();
229 void PrivetRegisterOperationImpl::StartResponse(
230 const base::DictionaryValue
& value
) {
231 next_response_handler_
=
232 base::Bind(&PrivetRegisterOperationImpl::GetClaimTokenResponse
,
233 base::Unretained(this));
235 SendRequest(kPrivetActionGetClaimToken
);
238 void PrivetRegisterOperationImpl::GetClaimTokenResponse(
239 const base::DictionaryValue
& value
) {
240 std::string claimUrl
;
241 std::string claimToken
;
242 bool got_url
= value
.GetString(kPrivetKeyClaimURL
, &claimUrl
);
243 bool got_token
= value
.GetString(kPrivetKeyClaimToken
, &claimToken
);
244 if (got_url
|| got_token
) {
245 delegate_
->OnPrivetRegisterClaimToken(this, claimToken
, GURL(claimUrl
));
247 delegate_
->OnPrivetRegisterError(this,
249 FAILURE_MALFORMED_RESPONSE
,
255 void PrivetRegisterOperationImpl::CompleteResponse(
256 const base::DictionaryValue
& value
) {
258 value
.GetString(kPrivetKeyDeviceID
, &id
);
261 StartInfoOperation();
264 void PrivetRegisterOperationImpl::OnPrivetInfoDone(
265 const base::DictionaryValue
* value
) {
266 // TODO(noamsml): Simplify error case and depracate HTTP error value in
267 // OnPrivetRegisterError.
269 delegate_
->OnPrivetRegisterError(this,
270 kPrivetActionNameInfo
,
277 if (!value
->HasKey(kPrivetInfoKeyID
)) {
278 if (value
->HasKey(kPrivetKeyError
)) {
279 delegate_
->OnPrivetRegisterError(this,
280 kPrivetActionNameInfo
,
285 delegate_
->OnPrivetRegisterError(this,
286 kPrivetActionNameInfo
,
287 FAILURE_MALFORMED_RESPONSE
,
296 if (!value
->GetString(kPrivetInfoKeyID
, &id
) ||
297 id
!= expected_id_
) {
298 delegate_
->OnPrivetRegisterError(this,
299 kPrivetActionNameInfo
,
300 FAILURE_MALFORMED_RESPONSE
,
304 delegate_
->OnPrivetRegisterDone(this, id
);
308 void PrivetRegisterOperationImpl::StartInfoOperation() {
309 info_operation_
= privet_client_
->CreateInfoOperation(
310 base::Bind(&PrivetRegisterOperationImpl::OnPrivetInfoDone
,
311 base::Unretained(this)));
312 info_operation_
->Start();
315 PrivetRegisterOperationImpl::Cancelation::Cancelation(
316 PrivetHTTPClient
* privet_client
,
317 const std::string
& user
) {
319 privet_client
->CreateURLFetcher(
320 CreatePrivetRegisterURL(kPrivetActionCancel
, user
),
321 net::URLFetcher::POST
, this);
322 url_fetcher_
->DoNotRetryOnTransientError();
323 url_fetcher_
->Start();
326 PrivetRegisterOperationImpl::Cancelation::~Cancelation() {
329 void PrivetRegisterOperationImpl::Cancelation::OnError(
330 PrivetURLFetcher
* fetcher
,
331 PrivetURLFetcher::ErrorType error
) {
334 void PrivetRegisterOperationImpl::Cancelation::OnParsedJson(
335 PrivetURLFetcher
* fetcher
,
336 const base::DictionaryValue
& value
,
340 void PrivetRegisterOperationImpl::Cancelation::Cleanup() {
341 // Nothing needs to be done, as base::Owned will delete this object,
342 // this callback is just here to pass ownership of the Cancelation to
346 PrivetJSONOperationImpl::PrivetJSONOperationImpl(
347 PrivetHTTPClient
* privet_client
,
348 const std::string
& path
,
349 const std::string
& query_params
,
350 const PrivetJSONOperation::ResultCallback
& callback
)
351 : privet_client_(privet_client
),
353 query_params_(query_params
),
354 callback_(callback
) {
357 PrivetJSONOperationImpl::~PrivetJSONOperationImpl() {
360 void PrivetJSONOperationImpl::Start() {
361 url_fetcher_
= privet_client_
->CreateURLFetcher(
362 CreatePrivetParamURL(path_
, query_params_
), net::URLFetcher::GET
, this);
363 url_fetcher_
->DoNotRetryOnTransientError();
364 url_fetcher_
->Start();
367 PrivetHTTPClient
* PrivetJSONOperationImpl::GetHTTPClient() {
368 return privet_client_
;
371 void PrivetJSONOperationImpl::OnError(
372 PrivetURLFetcher
* fetcher
,
373 PrivetURLFetcher::ErrorType error
) {
377 void PrivetJSONOperationImpl::OnParsedJson(PrivetURLFetcher
* fetcher
,
378 const base::DictionaryValue
& value
,
380 callback_
.Run(&value
);
383 void PrivetJSONOperationImpl::OnNeedPrivetToken(
384 PrivetURLFetcher
* fetcher
,
385 const PrivetURLFetcher::TokenCallback
& callback
) {
386 privet_client_
->RefreshPrivetToken(callback
);
389 #if defined(ENABLE_PRINT_PREVIEW)
390 PrivetLocalPrintOperationImpl::PrivetLocalPrintOperationImpl(
391 PrivetHTTPClient
* privet_client
,
392 PrivetLocalPrintOperation::Delegate
* delegate
)
393 : privet_client_(privet_client
),
396 has_extended_workflow_(false),
399 invalid_job_retries_(0),
400 weak_factory_(this) {
403 PrivetLocalPrintOperationImpl::~PrivetLocalPrintOperationImpl() {
406 void PrivetLocalPrintOperationImpl::Start() {
409 // We need to get the /info response so we can know which APIs are available.
410 // TODO(noamsml): Use cached info when available.
411 info_operation_
= privet_client_
->CreateInfoOperation(
412 base::Bind(&PrivetLocalPrintOperationImpl::OnPrivetInfoDone
,
413 base::Unretained(this)));
414 info_operation_
->Start();
419 void PrivetLocalPrintOperationImpl::OnPrivetInfoDone(
420 const base::DictionaryValue
* value
) {
421 if (value
&& !value
->HasKey(kPrivetKeyError
)) {
422 has_extended_workflow_
= false;
423 bool has_printing
= false;
425 const base::ListValue
* api_list
;
426 if (value
->GetList(kPrivetInfoKeyAPIList
, &api_list
)) {
427 for (size_t i
= 0; i
< api_list
->GetSize(); i
++) {
429 api_list
->GetString(i
, &api
);
430 if (api
== kPrivetSubmitdocPath
) {
432 } else if (api
== kPrivetCreatejobPath
) {
433 has_extended_workflow_
= true;
439 delegate_
->OnPrivetPrintingError(this, -1);
443 StartInitialRequest();
445 delegate_
->OnPrivetPrintingError(this, -1);
449 void PrivetLocalPrintOperationImpl::StartInitialRequest() {
451 cloud_devices::printer::ContentTypesCapability content_types
;
452 if (content_types
.LoadFrom(capabilities_
)) {
453 use_pdf_
= content_types
.Contains(kPrivetContentTypePDF
) ||
454 content_types
.Contains(kPrivetContentTypeAny
);
464 void PrivetLocalPrintOperationImpl::DoCreatejob() {
465 current_response_
= base::Bind(
466 &PrivetLocalPrintOperationImpl::OnCreatejobResponse
,
467 base::Unretained(this));
469 url_fetcher_
= privet_client_
->CreateURLFetcher(
470 CreatePrivetURL(kPrivetCreatejobPath
), net::URLFetcher::POST
, this);
471 url_fetcher_
->SetUploadData(cloud_print::kContentTypeJSON
,
474 url_fetcher_
->Start();
477 void PrivetLocalPrintOperationImpl::DoSubmitdoc() {
478 current_response_
= base::Bind(
479 &PrivetLocalPrintOperationImpl::OnSubmitdocResponse
,
480 base::Unretained(this));
482 GURL url
= CreatePrivetURL(kPrivetSubmitdocPath
);
484 url
= net::AppendQueryParameter(url
,
485 kPrivetURLKeyClientName
,
486 kPrivetURLValueClientName
);
488 if (!user_
.empty()) {
489 url
= net::AppendQueryParameter(url
,
490 kPrivetURLKeyUserName
,
494 base::string16 shortened_jobname
;
496 gfx::ElideString(base::UTF8ToUTF16(jobname_
),
497 kPrivetLocalPrintMaxJobNameLength
,
500 if (!jobname_
.empty()) {
501 url
= net::AppendQueryParameter(
502 url
, kPrivetURLKeyJobname
, base::UTF16ToUTF8(shortened_jobname
));
505 if (!jobid_
.empty()) {
506 url
= net::AppendQueryParameter(url
,
512 url
= net::AppendQueryParameter(url
,
513 kPrivetURLKeyOffline
,
514 kPrivetURLValueOffline
);
518 privet_client_
->CreateURLFetcher(url
, net::URLFetcher::POST
, this);
521 url_fetcher_
->SetUploadFilePath(kPrivetContentTypePWGRaster
,
524 // TODO(noamsml): Move to file-based upload data?
525 std::string
data_str((const char*)data_
->front(), data_
->size());
526 url_fetcher_
->SetUploadData(kPrivetContentTypePDF
, data_str
);
529 url_fetcher_
->Start();
532 void PrivetLocalPrintOperationImpl::StartPrinting() {
533 if (has_extended_workflow_
&& jobid_
.empty()) {
540 void PrivetLocalPrintOperationImpl::StartConvertToPWG() {
541 if (!pwg_raster_converter_
)
542 pwg_raster_converter_
= PWGRasterConverter::CreateDefault();
544 pwg_raster_converter_
->Start(
546 PWGRasterConverter::GetConversionSettings(capabilities_
, page_size_
),
547 PWGRasterConverter::GetBitmapSettings(capabilities_
, ticket_
),
548 base::Bind(&PrivetLocalPrintOperationImpl::OnPWGRasterConverted
,
549 base::Unretained(this)));
552 void PrivetLocalPrintOperationImpl::OnSubmitdocResponse(
554 const base::DictionaryValue
* value
) {
556 // This error is only relevant in the case of extended workflow:
557 // If the print job ID is invalid, retry createjob and submitdoc,
558 // rather than simply retrying the current request.
559 if (has_error
&& value
->GetString(kPrivetKeyError
, &error
)) {
560 if (has_extended_workflow_
&&
561 error
== kPrivetErrorInvalidPrintJob
&&
562 invalid_job_retries_
< kPrivetLocalPrintMaxRetries
) {
563 invalid_job_retries_
++;
565 int timeout
= kPrivetLocalPrintDefaultTimeout
;
566 value
->GetInteger(kPrivetKeyTimeout
, &timeout
);
568 double random_scaling_factor
=
569 1 + base::RandDouble() * kPrivetMaximumTimeRandomAddition
;
571 timeout
= static_cast<int>(timeout
* random_scaling_factor
);
573 timeout
= std::max(timeout
, kPrivetMinimumTimeout
);
575 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
576 FROM_HERE
, base::Bind(&PrivetLocalPrintOperationImpl::DoCreatejob
,
577 weak_factory_
.GetWeakPtr()),
578 base::TimeDelta::FromSeconds(timeout
));
579 } else if (use_pdf_
&& error
== kPrivetErrorInvalidDocumentType
) {
583 delegate_
->OnPrivetPrintingError(this, 200);
589 // If we've gotten this far, there are no errors, so we've effectively
591 delegate_
->OnPrivetPrintingDone(this);
594 void PrivetLocalPrintOperationImpl::OnCreatejobResponse(
596 const base::DictionaryValue
* value
) {
598 delegate_
->OnPrivetPrintingError(this, 200);
602 // Try to get job ID from value. If not, jobid_ will be empty and we will use
604 value
->GetString(kPrivetKeyJobID
, &jobid_
);
609 void PrivetLocalPrintOperationImpl::OnPWGRasterConverted(
611 const base::FilePath
& pwg_file_path
) {
613 delegate_
->OnPrivetPrintingError(this, -1);
617 DCHECK(!pwg_file_path
.empty());
619 pwg_file_path_
= pwg_file_path
;
623 PrivetHTTPClient
* PrivetLocalPrintOperationImpl::GetHTTPClient() {
624 return privet_client_
;
627 void PrivetLocalPrintOperationImpl::OnError(
628 PrivetURLFetcher
* fetcher
,
629 PrivetURLFetcher::ErrorType error
) {
630 delegate_
->OnPrivetPrintingError(this, -1);
633 void PrivetLocalPrintOperationImpl::OnParsedJson(
634 PrivetURLFetcher
* fetcher
,
635 const base::DictionaryValue
& value
,
637 DCHECK(!current_response_
.is_null());
638 current_response_
.Run(has_error
, &value
);
641 void PrivetLocalPrintOperationImpl::OnNeedPrivetToken(
642 PrivetURLFetcher
* fetcher
,
643 const PrivetURLFetcher::TokenCallback
& callback
) {
644 privet_client_
->RefreshPrivetToken(callback
);
647 void PrivetLocalPrintOperationImpl::SetData(
648 const scoped_refptr
<base::RefCountedBytes
>& data
) {
653 void PrivetLocalPrintOperationImpl::SetTicket(const std::string
& ticket
) {
655 ticket_
.InitFromString(ticket
);
658 void PrivetLocalPrintOperationImpl::SetCapabilities(
659 const std::string
& capabilities
) {
661 capabilities_
.InitFromString(capabilities
);
664 void PrivetLocalPrintOperationImpl::SetUsername(const std::string
& user
) {
669 void PrivetLocalPrintOperationImpl::SetJobname(const std::string
& jobname
) {
674 void PrivetLocalPrintOperationImpl::SetOffline(bool offline
) {
679 void PrivetLocalPrintOperationImpl::SetPageSize(const gfx::Size
& page_size
) {
681 page_size_
= page_size
;
684 void PrivetLocalPrintOperationImpl::SetPWGRasterConverterForTesting(
685 scoped_ptr
<PWGRasterConverter
> pwg_raster_converter
) {
686 pwg_raster_converter_
= pwg_raster_converter
.Pass();
688 #endif // ENABLE_PRINT_PREVIEW
690 PrivetHTTPClientImpl::PrivetHTTPClientImpl(
691 const std::string
& name
,
692 const net::HostPortPair
& host_port
,
693 net::URLRequestContextGetter
* request_context
)
694 : name_(name
), request_context_(request_context
), host_port_(host_port
) {}
696 PrivetHTTPClientImpl::~PrivetHTTPClientImpl() {
699 const std::string
& PrivetHTTPClientImpl::GetName() {
703 scoped_ptr
<PrivetJSONOperation
> PrivetHTTPClientImpl::CreateInfoOperation(
704 const PrivetJSONOperation::ResultCallback
& callback
) {
705 return scoped_ptr
<PrivetJSONOperation
>(
706 new PrivetInfoOperationImpl(this, callback
));
709 scoped_ptr
<PrivetURLFetcher
> PrivetHTTPClientImpl::CreateURLFetcher(
711 net::URLFetcher::RequestType request_type
,
712 PrivetURLFetcher::Delegate
* delegate
) {
713 GURL::Replacements replacements
;
714 replacements
.SetHostStr(host_port_
.host());
715 std::string
port(base::IntToString(host_port_
.port())); // Keep string alive.
716 replacements
.SetPortStr(port
);
717 return scoped_ptr
<PrivetURLFetcher
>(
718 new PrivetURLFetcher(url
.ReplaceComponents(replacements
),
720 request_context_
.get(),
724 void PrivetHTTPClientImpl::RefreshPrivetToken(
725 const PrivetURLFetcher::TokenCallback
& callback
) {
726 token_callbacks_
.push_back(callback
);
728 if (!info_operation_
) {
729 info_operation_
= CreateInfoOperation(
730 base::Bind(&PrivetHTTPClientImpl::OnPrivetInfoDone
,
731 base::Unretained(this)));
732 info_operation_
->Start();
736 void PrivetHTTPClientImpl::OnPrivetInfoDone(
737 const base::DictionaryValue
* value
) {
738 info_operation_
.reset();
741 // If this does not succeed, token will be empty, and an empty string
742 // is our sentinel value, since empty X-Privet-Tokens are not allowed.
744 value
->GetString(kPrivetInfoKeyToken
, &token
);
747 TokenCallbackVector token_callbacks
;
748 token_callbacks_
.swap(token_callbacks
);
750 for (TokenCallbackVector::iterator i
= token_callbacks
.begin();
751 i
!= token_callbacks
.end(); i
++) {
756 PrivetV1HTTPClientImpl::PrivetV1HTTPClientImpl(
757 scoped_ptr
<PrivetHTTPClient
> info_client
)
758 : info_client_(info_client
.Pass()) {
761 PrivetV1HTTPClientImpl::~PrivetV1HTTPClientImpl() {
764 const std::string
& PrivetV1HTTPClientImpl::GetName() {
765 return info_client()->GetName();
768 scoped_ptr
<PrivetJSONOperation
> PrivetV1HTTPClientImpl::CreateInfoOperation(
769 const PrivetJSONOperation::ResultCallback
& callback
) {
770 return info_client()->CreateInfoOperation(callback
);
773 scoped_ptr
<PrivetRegisterOperation
>
774 PrivetV1HTTPClientImpl::CreateRegisterOperation(
775 const std::string
& user
,
776 PrivetRegisterOperation::Delegate
* delegate
) {
777 return scoped_ptr
<PrivetRegisterOperation
>(
778 new PrivetRegisterOperationImpl(info_client(), user
, delegate
));
781 scoped_ptr
<PrivetJSONOperation
>
782 PrivetV1HTTPClientImpl::CreateCapabilitiesOperation(
783 const PrivetJSONOperation::ResultCallback
& callback
) {
784 return scoped_ptr
<PrivetJSONOperation
>(new PrivetJSONOperationImpl(
785 info_client(), kPrivetCapabilitiesPath
, "", callback
));
788 scoped_ptr
<PrivetLocalPrintOperation
>
789 PrivetV1HTTPClientImpl::CreateLocalPrintOperation(
790 PrivetLocalPrintOperation::Delegate
* delegate
) {
791 #if defined(ENABLE_PRINT_PREVIEW)
792 return scoped_ptr
<PrivetLocalPrintOperation
>(
793 new PrivetLocalPrintOperationImpl(info_client(), delegate
));
795 return scoped_ptr
<PrivetLocalPrintOperation
>();
796 #endif // ENABLE_PRINT_PREVIEW
799 } // namespace local_discovery