• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/extensions/api/messaging/message_property_provider.h"
6 
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/channel_id_service.h"
19 #include "net/url_request/url_request_context.h"
20 #include "net/url_request/url_request_context_getter.h"
21 #include "url/gurl.h"
22 
23 namespace extensions {
24 
MessagePropertyProvider()25 MessagePropertyProvider::MessagePropertyProvider() {}
26 
GetChannelID(Profile * profile,const GURL & source_url,const ChannelIDCallback & reply)27 void MessagePropertyProvider::GetChannelID(Profile* profile,
28     const GURL& source_url, const ChannelIDCallback& 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());
33     return;
34   }
35   scoped_refptr<net::URLRequestContextGetter> request_context_getter(
36       profile->GetRequestContext());
37   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
38       base::Bind(&MessagePropertyProvider::GetChannelIDOnIOThread,
39                  base::MessageLoopProxy::current(),
40                  request_context_getter,
41                  source_url.host(),
42                  reply));
43 }
44 
45 // Helper struct to bind the memory addresses that will be written to by
46 // ChannelIDService::GetChannelID to the callback provided to
47 // MessagePropertyProvider::GetChannelID.
48 struct MessagePropertyProvider::GetChannelIDOutput {
49   std::string domain_bound_private_key;
50   std::string domain_bound_cert;
51   net::ChannelIDService::RequestHandle request_handle;
52 };
53 
54 // static
GetChannelIDOnIOThread(scoped_refptr<base::TaskRunner> original_task_runner,scoped_refptr<net::URLRequestContextGetter> request_context_getter,const std::string & host,const ChannelIDCallback & reply)55 void MessagePropertyProvider::GetChannelIDOnIOThread(
56     scoped_refptr<base::TaskRunner> original_task_runner,
57     scoped_refptr<net::URLRequestContextGetter> request_context_getter,
58     const std::string& host,
59     const ChannelIDCallback& reply) {
60   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
61   net::ChannelIDService* channel_id_service =
62       request_context_getter->GetURLRequestContext()->
63           channel_id_service();
64   GetChannelIDOutput* output = new GetChannelIDOutput();
65   net::CompletionCallback net_completion_callback =
66       base::Bind(&MessagePropertyProvider::GotChannelID,
67                  original_task_runner,
68                  base::Owned(output),
69                  reply);
70   int status = channel_id_service->GetChannelID(
71       host,
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)
77     return;
78   GotChannelID(original_task_runner, output, reply, status);
79 }
80 
81 // static
GotChannelID(scoped_refptr<base::TaskRunner> original_task_runner,struct GetChannelIDOutput * output,const ChannelIDCallback & reply,int status)82 void MessagePropertyProvider::GotChannelID(
83     scoped_refptr<base::TaskRunner> original_task_runner,
84     struct GetChannelIDOutput* output,
85     const ChannelIDCallback& reply,
86     int status) {
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);
90     return;
91   }
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);
95     return;
96   }
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);
100     return;
101   }
102   std::string jwk_str;
103   base::JSONWriter::Write(&jwk_value, &jwk_str);
104   original_task_runner->PostTask(FROM_HERE, base::Bind(reply, jwk_str));
105 }
106 
107 }  // namespace extensions
108