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 "content/browser/frame_host/frame_tree_node.h"
10 #include "content/browser/frame_host/render_frame_host_impl.h"
11 #include "content/public/browser/browser_context.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/content_browser_client.h"
14 #include "content/public/browser/resource_context.h"
15 #include "content/public/browser/site_instance.h"
16 #include "content/public/common/content_client.h"
17 #include "net/cookies/cookie_store.h"
18 #include "net/url_request/url_request_context.h"
19 #include "net/url_request/url_request_context_getter.h"
25 using CookieListCallback
= net::CookieStore::GetCookieListCallback
;
29 net::URLRequestContext
* GetRequestContextOnIO(
30 ResourceContext
* resource_context
,
31 net::URLRequestContextGetter
* context_getter
,
33 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
34 net::URLRequestContext
* context
=
35 GetContentClient()->browser()->OverrideRequestContextForURL(
36 url
, resource_context
);
38 context
= context_getter
->GetURLRequestContext();
42 void GotCookiesForURLOnIO(
43 const CookieListCallback
& callback
,
44 const net::CookieList
& cookie_list
) {
45 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
46 BrowserThread::PostTask(
49 base::Bind(callback
, cookie_list
));
52 void GetCookiesForURLOnIO(
53 ResourceContext
* resource_context
,
54 net::URLRequestContextGetter
* context_getter
,
56 const CookieListCallback
& callback
) {
57 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
58 net::URLRequestContext
* request_context
=
59 GetRequestContextOnIO(resource_context
, context_getter
, url
);
60 request_context
->cookie_store()->GetAllCookiesForURLAsync(
61 url
, base::Bind(&GotCookiesForURLOnIO
, callback
));
64 void GetCookiesForURLOnUI(
65 ResourceContext
* resource_context
,
66 net::URLRequestContextGetter
* context_getter
,
68 const CookieListCallback
& callback
) {
69 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
70 BrowserThread::PostTask(
73 base::Bind(&GetCookiesForURLOnIO
,
74 base::Unretained(resource_context
),
75 base::Unretained(context_getter
),
80 void DeletedCookieOnIO(const base::Closure
& callback
) {
81 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
82 BrowserThread::PostTask(
88 void DeleteCookieOnIO(
89 ResourceContext
* resource_context
,
90 net::URLRequestContextGetter
* context_getter
,
92 const std::string
& cookie_name
,
93 const base::Closure
& callback
) {
94 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
95 net::URLRequestContext
* request_context
=
96 GetRequestContextOnIO(resource_context
, context_getter
, url
);
97 request_context
->cookie_store()->DeleteCookieAsync(
98 url
, cookie_name
, base::Bind(&DeletedCookieOnIO
, callback
));
101 void DeleteCookieOnUI(
102 ResourceContext
* resource_context
,
103 net::URLRequestContextGetter
* context_getter
,
105 const std::string
& cookie_name
,
106 const base::Closure
& callback
) {
107 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
108 BrowserThread::PostTask(
111 base::Bind(&DeleteCookieOnIO
,
112 base::Unretained(resource_context
),
113 base::Unretained(context_getter
),
119 class GetCookiesCommand
{
121 explicit GetCookiesCommand(
122 RenderFrameHostImpl
* frame_host
,
123 const CookieListCallback
& callback
)
124 : callback_(callback
),
126 CookieListCallback got_cookies_callback
= base::Bind(
127 &GetCookiesCommand::GotCookiesForURL
, base::Unretained(this));
128 BrowserContext
* browser_context
=
129 frame_host
->GetSiteInstance()->GetBrowserContext();
131 std::queue
<FrameTreeNode
*> queue
;
132 queue
.push(frame_host
->frame_tree_node());
133 while (!queue
.empty()) {
134 FrameTreeNode
* node
= queue
.front();
137 // Only traverse nodes with the same local root.
138 if (node
->current_frame_host()->IsCrossProcessSubframe())
140 int process_id
= node
->current_frame_host()->GetProcess()->GetID();
142 GetCookiesForURLOnUI(
143 browser_context
->GetResourceContext(),
144 browser_context
->GetRequestContextForRenderProcess(process_id
),
146 got_cookies_callback
);
148 for (size_t i
= 0; i
< node
->child_count(); ++i
)
149 queue
.push(node
->child_at(i
));
154 void GotCookiesForURL(const net::CookieList
& cookie_list
) {
155 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
156 for (const net::CanonicalCookie
& cookie
: cookie_list
) {
157 std::string key
= base::StringPrintf(
159 cookie
.Name().c_str(),
160 cookie
.Domain().c_str(),
161 cookie
.Path().c_str(),
163 cookies_
[key
] = cookie
;
166 if (!request_count_
) {
167 net::CookieList list
;
168 list
.reserve(cookies_
.size());
169 for (const auto& pair
: cookies_
)
170 list
.push_back(pair
.second
);
176 CookieListCallback callback_
;
178 base::hash_map
<std::string
, net::CanonicalCookie
> cookies_
;
183 typedef DevToolsProtocolClient::Response Response
;
185 NetworkHandler::NetworkHandler() : host_(nullptr), weak_factory_(this) {
188 NetworkHandler::~NetworkHandler() {
191 void NetworkHandler::SetRenderFrameHost(RenderFrameHostImpl
* host
) {
195 void NetworkHandler::SetClient(scoped_ptr
<Client
> client
) {
196 client_
.swap(client
);
199 Response
NetworkHandler::ClearBrowserCache() {
201 GetContentClient()->browser()->ClearCache(host_
);
202 return Response::OK();
205 Response
NetworkHandler::ClearBrowserCookies() {
207 GetContentClient()->browser()->ClearCookies(host_
);
208 return Response::OK();
211 Response
NetworkHandler::GetCookies(DevToolsCommandId command_id
) {
213 return Response::InternalError("Could not connect to view");
214 new GetCookiesCommand(
216 base::Bind(&NetworkHandler::SendGetCookiesResponse
,
217 weak_factory_
.GetWeakPtr(),
219 return Response::OK();
222 void NetworkHandler::SendGetCookiesResponse(
223 DevToolsCommandId command_id
,
224 const net::CookieList
& cookie_list
) {
225 std::vector
<scoped_refptr
<Cookie
>> cookies
;
226 for (size_t i
= 0; i
< cookie_list
.size(); ++i
) {
227 const net::CanonicalCookie
& cookie
= cookie_list
[i
];
228 cookies
.push_back(Cookie::Create()
229 ->set_name(cookie
.Name())
230 ->set_value(cookie
.Value())
231 ->set_domain(cookie
.Domain())
232 ->set_path(cookie
.Path())
233 ->set_expires(cookie
.ExpiryDate().ToDoubleT() * 1000)
234 ->set_size(cookie
.Name().length() + cookie
.Value().length())
235 ->set_http_only(cookie
.IsHttpOnly())
236 ->set_secure(cookie
.IsSecure())
237 ->set_session(!cookie
.IsPersistent()));
239 client_
->SendGetCookiesResponse(command_id
,
240 GetCookiesResponse::Create()->set_cookies(cookies
));
243 Response
NetworkHandler::DeleteCookie(
244 DevToolsCommandId command_id
,
245 const std::string
& cookie_name
,
246 const std::string
& url
) {
248 return Response::InternalError("Could not connect to view");
249 BrowserContext
* browser_context
=
250 host_
->GetSiteInstance()->GetBrowserContext();
251 int process_id
= host_
->GetProcess()->GetID();
253 browser_context
->GetResourceContext(),
254 browser_context
->GetRequestContextForRenderProcess(process_id
),
257 base::Bind(&NetworkHandler::SendDeleteCookieResponse
,
258 weak_factory_
.GetWeakPtr(),
260 return Response::OK();
263 void NetworkHandler::SendDeleteCookieResponse(DevToolsCommandId command_id
) {
264 client_
->SendDeleteCookieResponse(command_id
,
265 DeleteCookieResponse::Create());
269 Response
NetworkHandler::CanEmulateNetworkConditions(bool* result
) {
271 return Response::OK();
274 Response
NetworkHandler::EmulateNetworkConditions(bool offline
,
276 double download_throughput
,
277 double upload_throughput
) {
278 return Response::FallThrough();
282 } // namespace devtools
283 } // namespace content