OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/devtools/protocol/network_handler.h" | 5 #include "content/browser/devtools/protocol/network_handler.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/barrier_closure.h" | 9 #include "base/barrier_closure.h" |
10 #include "base/base64.h" | |
10 #include "base/command_line.h" | 11 #include "base/command_line.h" |
11 #include "base/containers/hash_tables.h" | 12 #include "base/containers/hash_tables.h" |
12 #include "base/process/process_handle.h" | 13 #include "base/process/process_handle.h" |
13 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
14 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
15 #include "base/time/time.h" | 16 #include "base/time/time.h" |
16 #include "content/browser/devtools/devtools_session.h" | 17 #include "content/browser/devtools/devtools_session.h" |
18 #include "content/browser/devtools/devtools_url_interceptor_request_job.h" | |
17 #include "content/browser/devtools/protocol/page.h" | 19 #include "content/browser/devtools/protocol/page.h" |
18 #include "content/browser/devtools/protocol/security.h" | 20 #include "content/browser/devtools/protocol/security.h" |
19 #include "content/browser/frame_host/frame_tree_node.h" | 21 #include "content/browser/frame_host/frame_tree_node.h" |
20 #include "content/browser/frame_host/render_frame_host_impl.h" | 22 #include "content/browser/frame_host/render_frame_host_impl.h" |
21 #include "content/common/navigation_params.h" | 23 #include "content/common/navigation_params.h" |
22 #include "content/common/resource_request.h" | 24 #include "content/common/resource_request.h" |
23 #include "content/common/resource_request_completion_status.h" | 25 #include "content/common/resource_request_completion_status.h" |
24 #include "content/public/browser/browser_context.h" | 26 #include "content/public/browser/browser_context.h" |
25 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
26 #include "content/public/browser/browsing_data_remover.h" | 28 #include "content/public/browser/browsing_data_remover.h" |
27 #include "content/public/browser/content_browser_client.h" | 29 #include "content/public/browser/content_browser_client.h" |
28 #include "content/public/browser/render_process_host.h" | 30 #include "content/public/browser/render_process_host.h" |
29 #include "content/public/browser/resource_context.h" | 31 #include "content/public/browser/resource_context.h" |
30 #include "content/public/browser/site_instance.h" | 32 #include "content/public/browser/site_instance.h" |
31 #include "content/public/browser/storage_partition.h" | 33 #include "content/public/browser/storage_partition.h" |
32 #include "content/public/browser/web_contents.h" | 34 #include "content/public/browser/web_contents.h" |
33 #include "content/public/common/content_client.h" | 35 #include "content/public/common/content_client.h" |
34 #include "content/public/common/content_switches.h" | 36 #include "content/public/common/content_switches.h" |
35 #include "content/public/common/resource_devtools_info.h" | 37 #include "content/public/common/resource_devtools_info.h" |
36 #include "content/public/common/resource_response.h" | 38 #include "content/public/common/resource_response.h" |
37 #include "net/base/net_errors.h" | 39 #include "net/base/net_errors.h" |
40 #include "net/base/upload_bytes_element_reader.h" | |
38 #include "net/cookies/cookie_store.h" | 41 #include "net/cookies/cookie_store.h" |
39 #include "net/http/http_response_headers.h" | 42 #include "net/http/http_response_headers.h" |
40 #include "net/url_request/url_request_context.h" | 43 #include "net/url_request/url_request_context.h" |
41 #include "net/url_request/url_request_context_getter.h" | 44 #include "net/url_request/url_request_context_getter.h" |
42 | 45 |
43 namespace content { | 46 namespace content { |
44 namespace protocol { | 47 namespace protocol { |
45 namespace { | 48 namespace { |
46 | 49 |
47 using ProtocolCookieArray = Array<Network::Cookie>; | 50 using ProtocolCookieArray = Array<Network::Cookie>; |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
330 case blink::kWebReferrerPolicyOriginWhenCrossOrigin: | 333 case blink::kWebReferrerPolicyOriginWhenCrossOrigin: |
331 return Network::Request::ReferrerPolicyEnum::OriginWhenCrossOrigin; | 334 return Network::Request::ReferrerPolicyEnum::OriginWhenCrossOrigin; |
332 case blink::kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin: | 335 case blink::kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin: |
333 return Network::Request::ReferrerPolicyEnum:: | 336 return Network::Request::ReferrerPolicyEnum:: |
334 NoReferrerWhenDowngradeOriginWhenCrossOrigin; | 337 NoReferrerWhenDowngradeOriginWhenCrossOrigin; |
335 } | 338 } |
336 NOTREACHED(); | 339 NOTREACHED(); |
337 return Network::Request::ReferrerPolicyEnum::NoReferrerWhenDowngrade; | 340 return Network::Request::ReferrerPolicyEnum::NoReferrerWhenDowngrade; |
338 } | 341 } |
339 | 342 |
343 String referrerPolicy(net::URLRequest::ReferrerPolicy referrer_policy) { | |
344 switch (referrer_policy) { | |
345 case net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE: | |
346 return Network::Request::ReferrerPolicyEnum::NoReferrerWhenDowngrade; | |
347 case net::URLRequest:: | |
348 REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN: | |
349 return Network::Request::ReferrerPolicyEnum:: | |
350 NoReferrerWhenDowngradeOriginWhenCrossOrigin; | |
351 case net::URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN: | |
352 return Network::Request::ReferrerPolicyEnum:: | |
353 NoReferrerWhenDowngradeOriginWhenCrossOrigin; | |
354 case net::URLRequest::NEVER_CLEAR_REFERRER: | |
355 return Network::Request::ReferrerPolicyEnum::Origin; | |
356 case net::URLRequest::ORIGIN: | |
357 return Network::Request::ReferrerPolicyEnum::Origin; | |
358 case net::URLRequest::NO_REFERRER: | |
359 return Network::Request::ReferrerPolicyEnum::NoReferrer; | |
360 default: | |
361 break; | |
362 } | |
363 NOTREACHED(); | |
364 return Network::Request::ReferrerPolicyEnum::NoReferrerWhenDowngrade; | |
365 } | |
366 | |
340 String securityState(const GURL& url, const net::CertStatus& cert_status) { | 367 String securityState(const GURL& url, const net::CertStatus& cert_status) { |
341 if (!url.SchemeIsCryptographic()) | 368 if (!url.SchemeIsCryptographic()) |
342 return Security::SecurityStateEnum::Neutral; | 369 return Security::SecurityStateEnum::Neutral; |
343 if (net::IsCertStatusError(cert_status) && | 370 if (net::IsCertStatusError(cert_status) && |
344 !net::IsCertStatusMinorError(cert_status)) { | 371 !net::IsCertStatusMinorError(cert_status)) { |
345 return Security::SecurityStateEnum::Insecure; | 372 return Security::SecurityStateEnum::Insecure; |
346 } | 373 } |
347 return Security::SecurityStateEnum::Secure; | 374 return Security::SecurityStateEnum::Secure; |
348 } | 375 } |
349 | 376 |
377 net::Error NetErrorFromString(const std::string& error) { | |
378 if (error == Network::ErrorReasonEnum::Failed) | |
379 return net::ERR_FAILED; | |
380 if (error == Network::ErrorReasonEnum::Aborted) | |
381 return net::ERR_ABORTED; | |
382 if (error == Network::ErrorReasonEnum::TimedOut) | |
383 return net::ERR_TIMED_OUT; | |
384 if (error == Network::ErrorReasonEnum::AccessDenied) | |
385 return net::ERR_ACCESS_DENIED; | |
386 if (error == Network::ErrorReasonEnum::ConnectionClosed) | |
387 return net::ERR_CONNECTION_CLOSED; | |
388 if (error == Network::ErrorReasonEnum::ConnectionReset) | |
389 return net::ERR_CONNECTION_RESET; | |
390 if (error == Network::ErrorReasonEnum::ConnectionRefused) | |
391 return net::ERR_CONNECTION_REFUSED; | |
392 if (error == Network::ErrorReasonEnum::ConnectionAborted) | |
393 return net::ERR_CONNECTION_ABORTED; | |
394 if (error == Network::ErrorReasonEnum::ConnectionFailed) | |
395 return net::ERR_CONNECTION_FAILED; | |
396 if (error == Network::ErrorReasonEnum::NameNotResolved) | |
397 return net::ERR_NAME_NOT_RESOLVED; | |
398 if (error == Network::ErrorReasonEnum::InternetDisconnected) | |
399 return net::ERR_INTERNET_DISCONNECTED; | |
400 if (error == Network::ErrorReasonEnum::AddressUnreachable) | |
401 return net::ERR_ADDRESS_UNREACHABLE; | |
402 return net::ERR_FAILED; | |
403 } | |
404 | |
350 double timeDelta(base::TimeTicks time, | 405 double timeDelta(base::TimeTicks time, |
351 base::TimeTicks start, | 406 base::TimeTicks start, |
352 double invalid_value = -1) { | 407 double invalid_value = -1) { |
353 return time.is_null() ? invalid_value : (time - start).InMillisecondsF(); | 408 return time.is_null() ? invalid_value : (time - start).InMillisecondsF(); |
354 } | 409 } |
355 | 410 |
356 std::unique_ptr<Network::ResourceTiming> getTiming( | 411 std::unique_ptr<Network::ResourceTiming> getTiming( |
357 const net::LoadTimingInfo& load_timing) { | 412 const net::LoadTimingInfo& load_timing) { |
358 const base::TimeTicks kNullTicks; | 413 const base::TimeTicks kNullTicks; |
359 return Network::ResourceTiming::Create() | 414 return Network::ResourceTiming::Create() |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
413 } | 468 } |
414 } | 469 } |
415 return protocol; | 470 return protocol; |
416 } | 471 } |
417 | 472 |
418 } // namespace | 473 } // namespace |
419 | 474 |
420 NetworkHandler::NetworkHandler() | 475 NetworkHandler::NetworkHandler() |
421 : DevToolsDomainHandler(Network::Metainfo::domainName), | 476 : DevToolsDomainHandler(Network::Metainfo::domainName), |
422 host_(nullptr), | 477 host_(nullptr), |
423 enabled_(false) { | 478 enabled_(false), |
424 } | 479 interception_enabled_(false), |
480 weak_factory_(this) {} | |
425 | 481 |
426 NetworkHandler::~NetworkHandler() { | 482 NetworkHandler::~NetworkHandler() { |
427 } | 483 } |
428 | 484 |
429 // static | 485 // static |
430 std::vector<NetworkHandler*> NetworkHandler::ForAgentHost( | 486 std::vector<NetworkHandler*> NetworkHandler::ForAgentHost( |
431 DevToolsAgentHostImpl* host) { | 487 DevToolsAgentHostImpl* host) { |
432 return DevToolsSession::HandlersForAgentHost<NetworkHandler>( | 488 return DevToolsSession::HandlersForAgentHost<NetworkHandler>( |
433 host, Network::Metainfo::domainName); | 489 host, Network::Metainfo::domainName); |
434 } | 490 } |
435 | 491 |
436 void NetworkHandler::Wire(UberDispatcher* dispatcher) { | 492 void NetworkHandler::Wire(UberDispatcher* dispatcher) { |
437 frontend_.reset(new Network::Frontend(dispatcher->channel())); | 493 frontend_.reset(new Network::Frontend(dispatcher->channel())); |
438 Network::Dispatcher::wire(dispatcher, this); | 494 Network::Dispatcher::wire(dispatcher, this); |
439 } | 495 } |
440 | 496 |
441 void NetworkHandler::SetRenderFrameHost(RenderFrameHostImpl* host) { | 497 void NetworkHandler::SetRenderFrameHost(RenderFrameHostImpl* host) { |
442 host_ = host; | 498 host_ = host; |
443 } | 499 } |
444 | 500 |
445 Response NetworkHandler::Enable(Maybe<int> max_total_size, | 501 Response NetworkHandler::Enable(Maybe<int> max_total_size, |
446 Maybe<int> max_resource_size) { | 502 Maybe<int> max_resource_size) { |
447 enabled_ = true; | 503 enabled_ = true; |
448 return Response::FallThrough(); | 504 return Response::FallThrough(); |
449 } | 505 } |
450 | 506 |
451 Response NetworkHandler::Disable() { | 507 Response NetworkHandler::Disable() { |
452 enabled_ = false; | 508 enabled_ = false; |
453 user_agent_ = std::string(); | 509 user_agent_ = std::string(); |
510 EnableFetchInterception(false); | |
454 return Response::FallThrough(); | 511 return Response::FallThrough(); |
455 } | 512 } |
456 | 513 |
457 Response NetworkHandler::ClearBrowserCache() { | 514 Response NetworkHandler::ClearBrowserCache() { |
458 if (host_) { | 515 if (host_) { |
459 content::BrowsingDataRemover* remover = | 516 content::BrowsingDataRemover* remover = |
460 content::BrowserContext::GetBrowsingDataRemover( | 517 content::BrowserContext::GetBrowsingDataRemover( |
461 host_->GetSiteInstance()->GetProcess()->GetBrowserContext()); | 518 host_->GetSiteInstance()->GetProcess()->GetBrowserContext()); |
462 remover->Remove(base::Time(), base::Time::Max(), | 519 remover->Remove(base::Time(), base::Time::Max(), |
463 content::BrowsingDataRemover::DATA_TYPE_CACHE, | 520 content::BrowsingDataRemover::DATA_TYPE_CACHE, |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
763 request_id, | 820 request_id, |
764 base::TimeTicks::Now().ToInternalValue() / | 821 base::TimeTicks::Now().ToInternalValue() / |
765 static_cast<double>(base::Time::kMicrosecondsPerSecond), | 822 static_cast<double>(base::Time::kMicrosecondsPerSecond), |
766 Page::ResourceTypeEnum::Document, error_string, cancelled); | 823 Page::ResourceTypeEnum::Document, error_string, cancelled); |
767 } | 824 } |
768 | 825 |
769 std::string NetworkHandler::UserAgentOverride() const { | 826 std::string NetworkHandler::UserAgentOverride() const { |
770 return enabled_ ? user_agent_ : std::string(); | 827 return enabled_ ? user_agent_ : std::string(); |
771 } | 828 } |
772 | 829 |
830 DispatchResponse NetworkHandler::EnableFetchInterception(bool enabled) { | |
831 if (interception_enabled_ == enabled) | |
832 return Response::OK(); // Nothing to do. | |
833 | |
834 WebContents* web_contents = WebContents::FromRenderFrameHost(host_); | |
835 if (!web_contents) | |
836 return Response::OK(); | |
837 | |
838 DevToolsURLRequestInterceptor* devtools_url_request_interceptor = | |
839 DevToolsURLRequestInterceptor::FromBrowserContext( | |
840 web_contents->GetBrowserContext()); | |
841 if (!devtools_url_request_interceptor) | |
842 return Response::OK(); | |
843 | |
844 if (enabled) { | |
845 BrowserThread::PostTask( | |
846 BrowserThread::IO, FROM_HERE, | |
847 base::BindOnce( | |
848 &DevToolsURLRequestInterceptor::State::StartInterceptingRequests, | |
849 devtools_url_request_interceptor->state().GetWeakPtr(), | |
dgozman
2017/05/25 21:29:36
It's prohibited to dereference weak pointer on the
alex clarke (OOO till 29th)
2017/05/26 19:37:03
An alternative is we can make the state ref counte
| |
850 web_contents, weak_factory_.GetWeakPtr())); | |
851 } else { | |
852 BrowserThread::PostTask( | |
853 BrowserThread::IO, FROM_HERE, | |
854 base::BindOnce( | |
855 &DevToolsURLRequestInterceptor::State::StopInterceptingRequests, | |
856 devtools_url_request_interceptor->state().GetWeakPtr(), | |
857 web_contents)); | |
858 } | |
859 interception_enabled_ = enabled; | |
860 return Response::OK(); | |
861 } | |
862 | |
863 namespace { | |
864 void ProcessContinueRequestResultOnIoThread( | |
865 std::unique_ptr<NetworkHandler::ContinueRequestCallback> callback, | |
866 const DevToolsURLRequestInterceptor::CommandStatus& result) { | |
867 switch (result) { | |
868 case DevToolsURLRequestInterceptor::CommandStatus::OK: | |
869 BrowserThread::PostTask( | |
870 BrowserThread::UI, FROM_HERE, | |
871 base::BindOnce(&NetworkHandler::ContinueRequestCallback::sendSuccess, | |
872 base::Owned(callback.release()))); | |
873 break; | |
874 case DevToolsURLRequestInterceptor::CommandStatus::UnknownInterceptionId: | |
875 BrowserThread::PostTask( | |
876 BrowserThread::UI, FROM_HERE, | |
877 base::BindOnce(&NetworkHandler::ContinueRequestCallback::sendFailure, | |
878 base::Owned(callback.release()), | |
879 Response::InvalidParams("Invalid InterceptionId."))); | |
880 break; | |
881 case DevToolsURLRequestInterceptor::CommandStatus::CommandAlreadyProcessed: | |
882 BrowserThread::PostTask( | |
883 BrowserThread::UI, FROM_HERE, | |
884 base::BindOnce( | |
885 &NetworkHandler::ContinueRequestCallback::sendFailure, | |
886 base::Owned(callback.release()), | |
887 Response::InvalidParams("Response already processed."))); | |
888 break; | |
889 } | |
890 } | |
891 | |
892 bool GetPostData(const net::URLRequest* request, std::string* post_data) { | |
893 if (!request->has_upload()) | |
894 return false; | |
895 | |
896 const net::UploadDataStream* stream = request->get_upload(); | |
897 if (!stream->GetElementReaders()) | |
898 return false; | |
899 | |
900 if (stream->GetElementReaders()->size() == 0) | |
901 return false; | |
902 | |
903 DCHECK_EQ(1u, stream->GetElementReaders()->size()); | |
dgozman
2017/05/25 21:29:36
Is this guaranteed by net?
alex clarke (OOO till 29th)
2017/05/26 19:37:03
Looks like no although this is the common case. I
dgozman
2017/05/30 21:44:27
IIUC, std::string += operator is smart since it us
alex clarke (OOO till 29th)
2017/05/31 15:52:02
Mmm OK that should help. I'm just worried about p
| |
904 const net::UploadBytesElementReader* reader = | |
905 (*stream->GetElementReaders())[0]->AsBytesReader(); | |
906 if (!reader) | |
907 return false; | |
908 *post_data = std::string(reader->bytes(), reader->length()); | |
dgozman
2017/05/25 21:29:36
I think we'll need to base64-encode this? Let's ha
alex clarke (OOO till 29th)
2017/05/26 19:37:03
For reference it's simple to base 64 encode that h
| |
909 return true; | |
910 } | |
911 } // namespace | |
912 | |
913 void NetworkHandler::ContinueRequest( | |
914 const std::string& interception_id, | |
915 Maybe<std::string> error_reason, | |
916 Maybe<std::string> base64_raw_response, | |
917 Maybe<std::string> url, | |
918 Maybe<std::string> method, | |
919 Maybe<std::string> post_data, | |
920 Maybe<protocol::Network::Headers> headers, | |
921 std::unique_ptr<ContinueRequestCallback> callback) { | |
922 DevToolsURLRequestInterceptor* devtools_url_request_interceptor = | |
923 DevToolsURLRequestInterceptor::FromBrowserContext( | |
924 WebContents::FromRenderFrameHost(host_)->GetBrowserContext()); | |
925 if (!devtools_url_request_interceptor) { | |
926 callback->sendFailure(Response::InternalError()); | |
927 return; | |
928 } | |
929 | |
930 base::Optional<net::Error> error; | |
931 if (error_reason.isJust()) | |
932 error = NetErrorFromString(error_reason.fromJust()); | |
933 | |
934 base::Optional<std::string> raw_response; | |
935 if (base64_raw_response.isJust()) { | |
936 std::string decoded; | |
937 if (!base::Base64Decode(base64_raw_response.fromJust(), &decoded)) { | |
938 callback->sendFailure(Response::InvalidParams("Invalid rawResponse.")); | |
939 return; | |
940 } | |
941 raw_response = decoded; | |
942 } | |
943 | |
944 BrowserThread::PostTask( | |
945 BrowserThread::IO, FROM_HERE, | |
946 base::BindOnce( | |
947 &DevToolsURLRequestInterceptor::State::ContinueRequest, | |
948 devtools_url_request_interceptor->state().GetWeakPtr(), | |
dgozman
2017/05/25 21:29:36
Similar thing here.
alex clarke (OOO till 29th)
2017/05/26 19:37:03
Done.
| |
949 interception_id, | |
950 base::MakeUnique<DevToolsURLRequestInterceptor::Modifications>( | |
951 std::move(error), std::move(raw_response), std::move(url), | |
952 std::move(method), std::move(post_data), std::move(headers)), | |
953 base::BindOnce(ProcessContinueRequestResultOnIoThread, | |
954 base::Passed(std::move(callback))))); | |
955 } | |
956 | |
957 // static | |
958 std::unique_ptr<Network::Request> NetworkHandler::CreateRequestFromURLRequest( | |
959 const net::URLRequest* request) { | |
960 std::unique_ptr<DictionaryValue> headers_dict(DictionaryValue::create()); | |
961 for (net::HttpRequestHeaders::Iterator it(request->extra_request_headers()); | |
962 it.GetNext();) { | |
963 headers_dict->setString(it.name(), it.value()); | |
964 } | |
965 std::unique_ptr<protocol::Network::Request> request_object = | |
966 Network::Request::Create() | |
967 .SetUrl(request->url().spec()) | |
968 .SetMethod(request->method()) | |
969 .SetHeaders(Object::fromValue(headers_dict.get(), nullptr)) | |
970 .SetInitialPriority(resourcePriority(request->priority())) | |
971 .SetReferrerPolicy(referrerPolicy(request->referrer_policy())) | |
972 .Build(); | |
973 std::string post_data; | |
974 if (GetPostData(request, &post_data)) | |
975 request_object->SetPostData(std::move(post_data)); | |
976 return request_object; | |
977 } | |
978 | |
773 } // namespace protocol | 979 } // namespace protocol |
774 } // namespace content | 980 } // namespace content |
OLD | NEW |