1 // Copyright 2014 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 "content/browser/devtools/protocol/network_handler.h"
7 #include "base/containers/hash_tables.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/time/time.h"
10 #include "content/browser/frame_host/frame_tree_node.h"
11 #include "content/browser/frame_host/render_frame_host_impl.h"
12 #include "content/public/browser/browser_context.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/cert_store.h"
15 #include "content/public/browser/content_browser_client.h"
16 #include "content/public/browser/resource_context.h"
17 #include "content/public/browser/site_instance.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/browser/web_contents_delegate.h"
20 #include "content/public/common/content_client.h"
21 #include "net/cert/x509_cert_types.h"
22 #include "net/cert/x509_certificate.h"
23 #include "net/cookies/cookie_store.h"
24 #include "net/url_request/url_request_context.h"
25 #include "net/url_request/url_request_context_getter.h"
31 using CookieListCallback
= net::CookieStore::GetCookieListCallback
;
35 net::URLRequestContext
* GetRequestContextOnIO(
36 ResourceContext
* resource_context
,
37 net::URLRequestContextGetter
* context_getter
,
39 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
40 net::URLRequestContext
* context
=
41 GetContentClient()->browser()->OverrideRequestContextForURL(
42 url
, resource_context
);
44 context
= context_getter
->GetURLRequestContext();
48 void GotCookiesForURLOnIO(
49 const CookieListCallback
& callback
,
50 const net::CookieList
& cookie_list
) {
51 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
52 BrowserThread::PostTask(
55 base::Bind(callback
, cookie_list
));
58 void GetCookiesForURLOnIO(
59 ResourceContext
* resource_context
,
60 net::URLRequestContextGetter
* context_getter
,
62 const CookieListCallback
& callback
) {
63 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
64 net::URLRequestContext
* request_context
=
65 GetRequestContextOnIO(resource_context
, context_getter
, url
);
66 request_context
->cookie_store()->GetAllCookiesForURLAsync(
67 url
, base::Bind(&GotCookiesForURLOnIO
, callback
));
70 void GetCookiesForURLOnUI(
71 ResourceContext
* resource_context
,
72 net::URLRequestContextGetter
* context_getter
,
74 const CookieListCallback
& callback
) {
75 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
76 BrowserThread::PostTask(
79 base::Bind(&GetCookiesForURLOnIO
,
80 base::Unretained(resource_context
),
81 base::Unretained(context_getter
),
86 void DeletedCookieOnIO(const base::Closure
& callback
) {
87 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
88 BrowserThread::PostTask(
94 void DeleteCookieOnIO(
95 ResourceContext
* resource_context
,
96 net::URLRequestContextGetter
* context_getter
,
98 const std::string
& cookie_name
,
99 const base::Closure
& callback
) {
100 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
101 net::URLRequestContext
* request_context
=
102 GetRequestContextOnIO(resource_context
, context_getter
, url
);
103 request_context
->cookie_store()->DeleteCookieAsync(
104 url
, cookie_name
, base::Bind(&DeletedCookieOnIO
, callback
));
107 void DeleteCookieOnUI(
108 ResourceContext
* resource_context
,
109 net::URLRequestContextGetter
* context_getter
,
111 const std::string
& cookie_name
,
112 const base::Closure
& callback
) {
113 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
114 BrowserThread::PostTask(
117 base::Bind(&DeleteCookieOnIO
,
118 base::Unretained(resource_context
),
119 base::Unretained(context_getter
),
125 class GetCookiesCommand
{
127 explicit GetCookiesCommand(
128 RenderFrameHostImpl
* frame_host
,
129 const CookieListCallback
& callback
)
130 : callback_(callback
),
132 CookieListCallback got_cookies_callback
= base::Bind(
133 &GetCookiesCommand::GotCookiesForURL
, base::Unretained(this));
134 BrowserContext
* browser_context
=
135 frame_host
->GetSiteInstance()->GetBrowserContext();
137 std::queue
<FrameTreeNode
*> queue
;
138 queue
.push(frame_host
->frame_tree_node());
139 while (!queue
.empty()) {
140 FrameTreeNode
* node
= queue
.front();
143 // Only traverse nodes with the same local root.
144 if (node
->current_frame_host()->IsCrossProcessSubframe())
146 int process_id
= node
->current_frame_host()->GetProcess()->GetID();
148 GetCookiesForURLOnUI(
149 browser_context
->GetResourceContext(),
150 browser_context
->GetRequestContextForRenderProcess(process_id
),
152 got_cookies_callback
);
154 for (size_t i
= 0; i
< node
->child_count(); ++i
)
155 queue
.push(node
->child_at(i
));
160 void GotCookiesForURL(const net::CookieList
& cookie_list
) {
161 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
162 for (const net::CanonicalCookie
& cookie
: cookie_list
) {
163 std::string key
= base::StringPrintf(
165 cookie
.Name().c_str(),
166 cookie
.Domain().c_str(),
167 cookie
.Path().c_str(),
169 cookies_
[key
] = cookie
;
172 if (!request_count_
) {
173 net::CookieList list
;
174 list
.reserve(cookies_
.size());
175 for (const auto& pair
: cookies_
)
176 list
.push_back(pair
.second
);
182 CookieListCallback callback_
;
184 base::hash_map
<std::string
, net::CanonicalCookie
> cookies_
;
189 typedef DevToolsProtocolClient::Response Response
;
191 NetworkHandler::NetworkHandler() : host_(nullptr), weak_factory_(this) {
194 NetworkHandler::~NetworkHandler() {
197 void NetworkHandler::SetRenderFrameHost(RenderFrameHostImpl
* host
) {
201 void NetworkHandler::SetClient(scoped_ptr
<Client
> client
) {
202 client_
.swap(client
);
205 Response
NetworkHandler::ClearBrowserCache() {
207 GetContentClient()->browser()->ClearCache(host_
);
208 return Response::OK();
211 Response
NetworkHandler::ClearBrowserCookies() {
213 GetContentClient()->browser()->ClearCookies(host_
);
214 return Response::OK();
217 Response
NetworkHandler::GetCookies(DevToolsCommandId command_id
) {
219 return Response::InternalError("Could not connect to view");
220 new GetCookiesCommand(
222 base::Bind(&NetworkHandler::SendGetCookiesResponse
,
223 weak_factory_
.GetWeakPtr(),
225 return Response::OK();
228 void NetworkHandler::SendGetCookiesResponse(
229 DevToolsCommandId command_id
,
230 const net::CookieList
& cookie_list
) {
231 std::vector
<scoped_refptr
<Cookie
>> cookies
;
232 for (size_t i
= 0; i
< cookie_list
.size(); ++i
) {
233 const net::CanonicalCookie
& cookie
= cookie_list
[i
];
234 cookies
.push_back(Cookie::Create()
235 ->set_name(cookie
.Name())
236 ->set_value(cookie
.Value())
237 ->set_domain(cookie
.Domain())
238 ->set_path(cookie
.Path())
239 ->set_expires(cookie
.ExpiryDate().ToDoubleT() * 1000)
240 ->set_size(cookie
.Name().length() + cookie
.Value().length())
241 ->set_http_only(cookie
.IsHttpOnly())
242 ->set_secure(cookie
.IsSecure())
243 ->set_session(!cookie
.IsPersistent()));
245 client_
->SendGetCookiesResponse(command_id
,
246 GetCookiesResponse::Create()->set_cookies(cookies
));
249 Response
NetworkHandler::DeleteCookie(
250 DevToolsCommandId command_id
,
251 const std::string
& cookie_name
,
252 const std::string
& url
) {
254 return Response::InternalError("Could not connect to view");
255 BrowserContext
* browser_context
=
256 host_
->GetSiteInstance()->GetBrowserContext();
257 int process_id
= host_
->GetProcess()->GetID();
259 browser_context
->GetResourceContext(),
260 browser_context
->GetRequestContextForRenderProcess(process_id
),
263 base::Bind(&NetworkHandler::SendDeleteCookieResponse
,
264 weak_factory_
.GetWeakPtr(),
266 return Response::OK();
269 void NetworkHandler::SendDeleteCookieResponse(DevToolsCommandId command_id
) {
270 client_
->SendDeleteCookieResponse(command_id
,
271 DeleteCookieResponse::Create());
275 Response
NetworkHandler::CanEmulateNetworkConditions(bool* result
) {
277 return Response::OK();
280 Response
NetworkHandler::EmulateNetworkConditions(bool offline
,
282 double download_throughput
,
283 double upload_throughput
) {
284 return Response::FallThrough();
287 Response
NetworkHandler::GetCertificateDetails(
289 scoped_refptr
<CertificateDetails
>* result
) {
290 scoped_refptr
<net::X509Certificate
> cert
;
291 content::CertStore
* cert_store
= CertStore::GetInstance();
292 cert_store
->RetrieveCert(certificate_id
, &cert
);
294 return Response::InvalidParams("certificateId");
296 std::string
name(cert
->subject().GetDisplayName());
297 std::string
issuer(cert
->issuer().GetDisplayName());
298 base::Time valid_from
= cert
->valid_start();
299 base::Time valid_to
= cert
->valid_expiry();
301 std::vector
<std::string
> dns_names
;
302 std::vector
<std::string
> ip_addrs
;
303 cert
->GetSubjectAltName(&dns_names
, &ip_addrs
);
305 *result
= CertificateDetails::Create()
306 ->set_subject(CertificateSubject::Create()
308 ->set_san_dns_names(dns_names
)
309 ->set_san_ip_addresses(ip_addrs
))
311 ->set_valid_from(valid_from
.ToDoubleT())
312 ->set_valid_to(valid_to
.ToDoubleT());
313 return Response::OK();
316 Response
NetworkHandler::ShowCertificateViewer(int certificate_id
) {
318 return Response::InternalError("Could not connect to view");
319 WebContents
* web_contents
= WebContents::FromRenderFrameHost(host_
);
320 web_contents
->GetDelegate()->ShowCertificateViewerInDevTools(
321 web_contents
, certificate_id
);
322 return Response::OK();
326 } // namespace devtools
327 } // namespace content