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/extensions/api/messaging/message_property_provider.h"
7 #include "base/json/json_writer.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/strings/string_piece.h"
11 #include "base/values.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "extensions/common/api/runtime.h"
15 #include "net/base/completion_callback.h"
16 #include "net/cert/asn1_util.h"
17 #include "net/cert/jwk_serializer.h"
18 #include "net/ssl/server_bound_cert_service.h"
19 #include "net/url_request/url_request_context.h"
20 #include "net/url_request/url_request_context_getter.h"
23 namespace extensions
{
25 MessagePropertyProvider::MessagePropertyProvider() {}
27 void MessagePropertyProvider::GetDomainBoundCert(Profile
* profile
,
28 const GURL
& source_url
, const DomainBoundCertCallback
& reply
) {
29 if (!source_url
.is_valid()) {
30 // This isn't a real URL, so there's no sense in looking for a channel ID
31 // for it. Dispatch with an empty tls channel ID.
32 reply
.Run(std::string());
35 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter(
36 profile
->GetRequestContext());
37 content::BrowserThread::PostTask(content::BrowserThread::IO
, FROM_HERE
,
38 base::Bind(&MessagePropertyProvider::GetDomainBoundCertOnIOThread
,
39 base::MessageLoopProxy::current(),
40 request_context_getter
,
45 // Helper struct to bind the memory addresses that will be written to by
46 // ServerBoundCertService::GetDomainBoundCert to the callback provided to
47 // MessagePropertyProvider::GetDomainBoundCert.
48 struct MessagePropertyProvider::GetDomainBoundCertOutput
{
49 std::string domain_bound_private_key
;
50 std::string domain_bound_cert
;
51 net::ServerBoundCertService::RequestHandle request_handle
;
55 void MessagePropertyProvider::GetDomainBoundCertOnIOThread(
56 scoped_refptr
<base::TaskRunner
> original_task_runner
,
57 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter
,
58 const std::string
& host
,
59 const DomainBoundCertCallback
& reply
) {
60 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
61 net::ServerBoundCertService
* server_bound_cert_service
=
62 request_context_getter
->GetURLRequestContext()->
63 server_bound_cert_service();
64 GetDomainBoundCertOutput
* output
= new GetDomainBoundCertOutput();
65 net::CompletionCallback net_completion_callback
=
66 base::Bind(&MessagePropertyProvider::GotDomainBoundCert
,
70 int status
= server_bound_cert_service
->GetDomainBoundCert(
72 &output
->domain_bound_private_key
,
73 &output
->domain_bound_cert
,
74 net_completion_callback
,
75 &output
->request_handle
);
76 if (status
== net::ERR_IO_PENDING
)
78 GotDomainBoundCert(original_task_runner
, output
, reply
, status
);
82 void MessagePropertyProvider::GotDomainBoundCert(
83 scoped_refptr
<base::TaskRunner
> original_task_runner
,
84 struct GetDomainBoundCertOutput
* output
,
85 const DomainBoundCertCallback
& reply
,
87 base::Closure no_tls_channel_id_closure
= base::Bind(reply
, "");
88 if (status
!= net::OK
) {
89 original_task_runner
->PostTask(FROM_HERE
, no_tls_channel_id_closure
);
92 base::StringPiece spki
;
93 if (!net::asn1::ExtractSPKIFromDERCert(output
->domain_bound_cert
, &spki
)) {
94 original_task_runner
->PostTask(FROM_HERE
, no_tls_channel_id_closure
);
97 base::DictionaryValue jwk_value
;
98 if (!net::JwkSerializer::ConvertSpkiFromDerToJwk(spki
, &jwk_value
)) {
99 original_task_runner
->PostTask(FROM_HERE
, no_tls_channel_id_closure
);
103 base::JSONWriter::Write(&jwk_value
, &jwk_str
);
104 original_task_runner
->PostTask(FROM_HERE
, base::Bind(reply
, jwk_str
));
107 } // namespace extensions