[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / devtools / protocol / network_handler.cc
blob27f82f45c8b171c833e778543875688727aeaba5
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"
27 namespace content {
28 namespace devtools {
29 namespace network {
31 using CookieListCallback = net::CookieStore::GetCookieListCallback;
33 namespace {
35 net::URLRequestContext* GetRequestContextOnIO(
36 ResourceContext* resource_context,
37 net::URLRequestContextGetter* context_getter,
38 const GURL& url) {
39 DCHECK_CURRENTLY_ON(BrowserThread::IO);
40 net::URLRequestContext* context =
41 GetContentClient()->browser()->OverrideRequestContextForURL(
42 url, resource_context);
43 if (!context)
44 context = context_getter->GetURLRequestContext();
45 return context;
48 void GotCookiesForURLOnIO(
49 const CookieListCallback& callback,
50 const net::CookieList& cookie_list) {
51 DCHECK_CURRENTLY_ON(BrowserThread::IO);
52 BrowserThread::PostTask(
53 BrowserThread::UI,
54 FROM_HERE,
55 base::Bind(callback, cookie_list));
58 void GetCookiesForURLOnIO(
59 ResourceContext* resource_context,
60 net::URLRequestContextGetter* context_getter,
61 const GURL& url,
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,
73 const GURL& url,
74 const CookieListCallback& callback) {
75 DCHECK_CURRENTLY_ON(BrowserThread::UI);
76 BrowserThread::PostTask(
77 BrowserThread::IO,
78 FROM_HERE,
79 base::Bind(&GetCookiesForURLOnIO,
80 base::Unretained(resource_context),
81 base::Unretained(context_getter),
82 url,
83 callback));
86 void DeletedCookieOnIO(const base::Closure& callback) {
87 DCHECK_CURRENTLY_ON(BrowserThread::IO);
88 BrowserThread::PostTask(
89 BrowserThread::UI,
90 FROM_HERE,
91 callback);
94 void DeleteCookieOnIO(
95 ResourceContext* resource_context,
96 net::URLRequestContextGetter* context_getter,
97 const GURL& url,
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,
110 const GURL& url,
111 const std::string& cookie_name,
112 const base::Closure& callback) {
113 DCHECK_CURRENTLY_ON(BrowserThread::UI);
114 BrowserThread::PostTask(
115 BrowserThread::IO,
116 FROM_HERE,
117 base::Bind(&DeleteCookieOnIO,
118 base::Unretained(resource_context),
119 base::Unretained(context_getter),
120 url,
121 cookie_name,
122 callback));
125 class GetCookiesCommand {
126 public:
127 explicit GetCookiesCommand(
128 RenderFrameHostImpl* frame_host,
129 const CookieListCallback& callback)
130 : callback_(callback),
131 request_count_(0) {
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();
141 queue.pop();
143 // Only traverse nodes with the same local root.
144 if (node->current_frame_host()->IsCrossProcessSubframe())
145 continue;
146 int process_id = node->current_frame_host()->GetProcess()->GetID();
147 ++request_count_;
148 GetCookiesForURLOnUI(
149 browser_context->GetResourceContext(),
150 browser_context->GetRequestContextForRenderProcess(process_id),
151 node->current_url(),
152 got_cookies_callback);
154 for (size_t i = 0; i < node->child_count(); ++i)
155 queue.push(node->child_at(i));
159 private:
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(
164 "%s::%s::%s::%d",
165 cookie.Name().c_str(),
166 cookie.Domain().c_str(),
167 cookie.Path().c_str(),
168 cookie.IsSecure());
169 cookies_[key] = cookie;
171 --request_count_;
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);
177 callback_.Run(list);
178 delete this;
182 CookieListCallback callback_;
183 int request_count_;
184 base::hash_map<std::string, net::CanonicalCookie> cookies_;
187 } // namespace
189 typedef DevToolsProtocolClient::Response Response;
191 NetworkHandler::NetworkHandler() : host_(nullptr), weak_factory_(this) {
194 NetworkHandler::~NetworkHandler() {
197 void NetworkHandler::SetRenderFrameHost(RenderFrameHostImpl* host) {
198 host_ = host;
201 void NetworkHandler::SetClient(scoped_ptr<Client> client) {
202 client_.swap(client);
205 Response NetworkHandler::ClearBrowserCache() {
206 if (host_)
207 GetContentClient()->browser()->ClearCache(host_);
208 return Response::OK();
211 Response NetworkHandler::ClearBrowserCookies() {
212 if (host_)
213 GetContentClient()->browser()->ClearCookies(host_);
214 return Response::OK();
217 Response NetworkHandler::GetCookies(DevToolsCommandId command_id) {
218 if (!host_)
219 return Response::InternalError("Could not connect to view");
220 new GetCookiesCommand(
221 host_,
222 base::Bind(&NetworkHandler::SendGetCookiesResponse,
223 weak_factory_.GetWeakPtr(),
224 command_id));
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) {
253 if (!host_)
254 return Response::InternalError("Could not connect to view");
255 BrowserContext* browser_context =
256 host_->GetSiteInstance()->GetBrowserContext();
257 int process_id = host_->GetProcess()->GetID();
258 DeleteCookieOnUI(
259 browser_context->GetResourceContext(),
260 browser_context->GetRequestContextForRenderProcess(process_id),
261 GURL(url),
262 cookie_name,
263 base::Bind(&NetworkHandler::SendDeleteCookieResponse,
264 weak_factory_.GetWeakPtr(),
265 command_id));
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) {
276 *result = false;
277 return Response::OK();
280 Response NetworkHandler::EmulateNetworkConditions(bool offline,
281 double latency,
282 double download_throughput,
283 double upload_throughput) {
284 return Response::FallThrough();
287 Response NetworkHandler::GetCertificateDetails(
288 int certificate_id,
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);
293 if (!cert.get())
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()
307 ->set_name(name)
308 ->set_san_dns_names(dns_names)
309 ->set_san_ip_addresses(ip_addrs))
310 ->set_issuer(issuer)
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) {
317 if (!host_)
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();
325 } // namespace dom
326 } // namespace devtools
327 } // namespace content