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/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/containers/hash_tables.h" | 11 #include "base/containers/hash_tables.h" |
12 #include "base/process/process_handle.h" | 12 #include "base/process/process_handle.h" |
13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
16 #include "content/browser/devtools/devtools_session.h" | 16 #include "content/browser/devtools/devtools_session.h" |
| 17 #include "content/browser/devtools/devtools_url_interceptor_request_job.h" |
17 #include "content/browser/devtools/protocol/page.h" | 18 #include "content/browser/devtools/protocol/page.h" |
18 #include "content/browser/devtools/protocol/security.h" | 19 #include "content/browser/devtools/protocol/security.h" |
19 #include "content/browser/frame_host/frame_tree_node.h" | 20 #include "content/browser/frame_host/frame_tree_node.h" |
20 #include "content/browser/frame_host/render_frame_host_impl.h" | 21 #include "content/browser/frame_host/render_frame_host_impl.h" |
21 #include "content/common/navigation_params.h" | 22 #include "content/common/navigation_params.h" |
22 #include "content/common/resource_request.h" | 23 #include "content/common/resource_request.h" |
23 #include "content/common/resource_request_completion_status.h" | 24 #include "content/common/resource_request_completion_status.h" |
24 #include "content/public/browser/browser_context.h" | 25 #include "content/public/browser/browser_context.h" |
25 #include "content/public/browser/browser_thread.h" | 26 #include "content/public/browser/browser_thread.h" |
26 #include "content/public/browser/content_browser_client.h" | 27 #include "content/public/browser/content_browser_client.h" |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 case blink::kWebReferrerPolicyOriginWhenCrossOrigin: | 330 case blink::kWebReferrerPolicyOriginWhenCrossOrigin: |
330 return Network::Request::ReferrerPolicyEnum::OriginWhenCrossOrigin; | 331 return Network::Request::ReferrerPolicyEnum::OriginWhenCrossOrigin; |
331 case blink::kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin: | 332 case blink::kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin: |
332 return Network::Request::ReferrerPolicyEnum:: | 333 return Network::Request::ReferrerPolicyEnum:: |
333 NoReferrerWhenDowngradeOriginWhenCrossOrigin; | 334 NoReferrerWhenDowngradeOriginWhenCrossOrigin; |
334 } | 335 } |
335 NOTREACHED(); | 336 NOTREACHED(); |
336 return Network::Request::ReferrerPolicyEnum::NoReferrerWhenDowngrade; | 337 return Network::Request::ReferrerPolicyEnum::NoReferrerWhenDowngrade; |
337 } | 338 } |
338 | 339 |
| 340 String referrerPolicy(net::URLRequest::ReferrerPolicy referrer_policy) { |
| 341 switch (referrer_policy) { |
| 342 case net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE: |
| 343 return Network::Request::ReferrerPolicyEnum::NoReferrerWhenDowngrade; |
| 344 case net::URLRequest:: |
| 345 REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN: |
| 346 return Network::Request::ReferrerPolicyEnum:: |
| 347 NoReferrerWhenDowngradeOriginWhenCrossOrigin; |
| 348 case net::URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN: |
| 349 return Network::Request::ReferrerPolicyEnum:: |
| 350 NoReferrerWhenDowngradeOriginWhenCrossOrigin; |
| 351 case net::URLRequest::NEVER_CLEAR_REFERRER: |
| 352 return Network::Request::ReferrerPolicyEnum::Origin; |
| 353 case net::URLRequest::ORIGIN: |
| 354 return Network::Request::ReferrerPolicyEnum::Origin; |
| 355 case net::URLRequest::NO_REFERRER: |
| 356 return Network::Request::ReferrerPolicyEnum::NoReferrer; |
| 357 default: |
| 358 break; |
| 359 } |
| 360 NOTREACHED(); |
| 361 return Network::Request::ReferrerPolicyEnum::NoReferrerWhenDowngrade; |
| 362 } |
| 363 |
339 String securityState(const GURL& url, const net::CertStatus& cert_status) { | 364 String securityState(const GURL& url, const net::CertStatus& cert_status) { |
340 if (!url.SchemeIsCryptographic()) | 365 if (!url.SchemeIsCryptographic()) |
341 return Security::SecurityStateEnum::Neutral; | 366 return Security::SecurityStateEnum::Neutral; |
342 if (net::IsCertStatusError(cert_status) && | 367 if (net::IsCertStatusError(cert_status) && |
343 !net::IsCertStatusMinorError(cert_status)) { | 368 !net::IsCertStatusMinorError(cert_status)) { |
344 return Security::SecurityStateEnum::Insecure; | 369 return Security::SecurityStateEnum::Insecure; |
345 } | 370 } |
346 return Security::SecurityStateEnum::Secure; | 371 return Security::SecurityStateEnum::Secure; |
347 } | 372 } |
348 | 373 |
| 374 net::Error NetErrorFromString(const std::string& error) { |
| 375 if (error == Network::ErrorReasonEnum::Failed) |
| 376 return net::ERR_FAILED; |
| 377 if (error == Network::ErrorReasonEnum::Aborted) |
| 378 return net::ERR_ABORTED; |
| 379 if (error == Network::ErrorReasonEnum::TimedOut) |
| 380 return net::ERR_TIMED_OUT; |
| 381 if (error == Network::ErrorReasonEnum::AccessDenied) |
| 382 return net::ERR_ACCESS_DENIED; |
| 383 if (error == Network::ErrorReasonEnum::ConnectionClosed) |
| 384 return net::ERR_CONNECTION_CLOSED; |
| 385 if (error == Network::ErrorReasonEnum::ConnectionReset) |
| 386 return net::ERR_CONNECTION_RESET; |
| 387 if (error == Network::ErrorReasonEnum::ConnectionRefused) |
| 388 return net::ERR_CONNECTION_REFUSED; |
| 389 if (error == Network::ErrorReasonEnum::ConnectionAborted) |
| 390 return net::ERR_CONNECTION_ABORTED; |
| 391 if (error == Network::ErrorReasonEnum::ConnectionFailed) |
| 392 return net::ERR_CONNECTION_FAILED; |
| 393 if (error == Network::ErrorReasonEnum::NameNotResolved) |
| 394 return net::ERR_NAME_NOT_RESOLVED; |
| 395 if (error == Network::ErrorReasonEnum::InternetDisconnected) |
| 396 return net::ERR_INTERNET_DISCONNECTED; |
| 397 if (error == Network::ErrorReasonEnum::AddressUnreachable) |
| 398 return net::ERR_ADDRESS_UNREACHABLE; |
| 399 return net::ERR_FAILED; |
| 400 } |
| 401 |
349 double timeDelta(base::TimeTicks time, | 402 double timeDelta(base::TimeTicks time, |
350 base::TimeTicks start, | 403 base::TimeTicks start, |
351 double invalid_value = -1) { | 404 double invalid_value = -1) { |
352 return time.is_null() ? invalid_value : (time - start).InMillisecondsF(); | 405 return time.is_null() ? invalid_value : (time - start).InMillisecondsF(); |
353 } | 406 } |
354 | 407 |
355 std::unique_ptr<Network::ResourceTiming> getTiming( | 408 std::unique_ptr<Network::ResourceTiming> getTiming( |
356 const net::LoadTimingInfo& load_timing) { | 409 const net::LoadTimingInfo& load_timing) { |
357 const base::TimeTicks kNullTicks; | 410 const base::TimeTicks kNullTicks; |
358 return Network::ResourceTiming::Create() | 411 return Network::ResourceTiming::Create() |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 } | 465 } |
413 } | 466 } |
414 return protocol; | 467 return protocol; |
415 } | 468 } |
416 | 469 |
417 } // namespace | 470 } // namespace |
418 | 471 |
419 NetworkHandler::NetworkHandler() | 472 NetworkHandler::NetworkHandler() |
420 : DevToolsDomainHandler(Network::Metainfo::domainName), | 473 : DevToolsDomainHandler(Network::Metainfo::domainName), |
421 host_(nullptr), | 474 host_(nullptr), |
422 enabled_(false) { | 475 enabled_(false), |
423 } | 476 interception_enabled_(false), |
| 477 weak_factory_(this) {} |
424 | 478 |
425 NetworkHandler::~NetworkHandler() { | 479 NetworkHandler::~NetworkHandler() { |
| 480 EnableFetchInterception(false); |
426 } | 481 } |
427 | 482 |
428 // static | 483 // static |
429 std::vector<NetworkHandler*> NetworkHandler::ForAgentHost( | 484 std::vector<NetworkHandler*> NetworkHandler::ForAgentHost( |
430 DevToolsAgentHostImpl* host) { | 485 DevToolsAgentHostImpl* host) { |
431 return DevToolsSession::HandlersForAgentHost<NetworkHandler>( | 486 return DevToolsSession::HandlersForAgentHost<NetworkHandler>( |
432 host, Network::Metainfo::domainName); | 487 host, Network::Metainfo::domainName); |
433 } | 488 } |
434 | 489 |
435 void NetworkHandler::Wire(UberDispatcher* dispatcher) { | 490 void NetworkHandler::Wire(UberDispatcher* dispatcher) { |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 request_id, | 810 request_id, |
756 base::TimeTicks::Now().ToInternalValue() / | 811 base::TimeTicks::Now().ToInternalValue() / |
757 static_cast<double>(base::Time::kMicrosecondsPerSecond), | 812 static_cast<double>(base::Time::kMicrosecondsPerSecond), |
758 Page::ResourceTypeEnum::Document, error_string, cancelled); | 813 Page::ResourceTypeEnum::Document, error_string, cancelled); |
759 } | 814 } |
760 | 815 |
761 std::string NetworkHandler::UserAgentOverride() const { | 816 std::string NetworkHandler::UserAgentOverride() const { |
762 return enabled_ ? user_agent_ : std::string(); | 817 return enabled_ ? user_agent_ : std::string(); |
763 } | 818 } |
764 | 819 |
| 820 DispatchResponse NetworkHandler::EnableFetchInterception(bool enabled) { |
| 821 if (interception_enabled_ == enabled) |
| 822 return Response::OK(); // Nothing to do. |
| 823 |
| 824 WebContents* web_contents = WebContents::FromRenderFrameHost(host_); |
| 825 if (!web_contents) |
| 826 return Response::OK(); |
| 827 |
| 828 DevToolsURLRequestInterceptor* devtools_url_request_interceptor = |
| 829 DevToolsURLRequestInterceptor::FromBrowserContext( |
| 830 web_contents->GetBrowserContext()); |
| 831 if (!devtools_url_request_interceptor) |
| 832 return Response::OK(); |
| 833 |
| 834 if (enabled) { |
| 835 BrowserThread::PostTask( |
| 836 BrowserThread::IO, FROM_HERE, |
| 837 base::BindOnce(&DevToolsURLRequestInterceptor::State:: |
| 838 StartInterceptingRequestsFrom, |
| 839 devtools_url_request_interceptor->state().GetWeakPtr(), |
| 840 host_->GetRoutingID(), host_->GetFrameTreeNodeId(), |
| 841 weak_factory_.GetWeakPtr())); |
| 842 |
| 843 } else { |
| 844 BrowserThread::PostTask( |
| 845 BrowserThread::IO, FROM_HERE, |
| 846 base::BindOnce( |
| 847 &DevToolsURLRequestInterceptor::State::StopInterceptingRequestsFrom, |
| 848 devtools_url_request_interceptor->state().GetWeakPtr(), |
| 849 host_->GetRoutingID(), host_->GetFrameTreeNodeId())); |
| 850 } |
| 851 interception_enabled_ = enabled; |
| 852 return Response::OK(); |
| 853 } |
| 854 |
| 855 template <typename CallbackT> |
| 856 void ProcessInterceptionCommandResultOnIoThread( |
| 857 std::unique_ptr<CallbackT> callback, |
| 858 const DevToolsURLRequestInterceptor::CommandStatus& result) { |
| 859 switch (result) { |
| 860 case DevToolsURLRequestInterceptor::CommandStatus::OK: |
| 861 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 862 base::BindOnce(&CallbackT::sendSuccess, |
| 863 base::Owned(callback.release()))); |
| 864 break; |
| 865 case DevToolsURLRequestInterceptor::CommandStatus::UnknownInterceptionId: |
| 866 BrowserThread::PostTask( |
| 867 BrowserThread::UI, FROM_HERE, |
| 868 base::BindOnce(&CallbackT::sendFailure, |
| 869 base::Owned(callback.release()), |
| 870 Response::InvalidParams("Invalid interceptId."))); |
| 871 break; |
| 872 case DevToolsURLRequestInterceptor::CommandStatus::CommandAlreadyProcessed: |
| 873 BrowserThread::PostTask( |
| 874 BrowserThread::UI, FROM_HERE, |
| 875 base::BindOnce( |
| 876 &CallbackT::sendFailure, base::Owned(callback.release()), |
| 877 Response::InvalidParams("Response already processed."))); |
| 878 break; |
| 879 } |
| 880 } |
| 881 |
| 882 void NetworkHandler::AllowRequest( |
| 883 const String& intercept_id, |
| 884 std::unique_ptr<AllowRequestCallback> callback) { |
| 885 DevToolsURLRequestInterceptor* devtools_url_request_interceptor = |
| 886 DevToolsURLRequestInterceptor::FromBrowserContext( |
| 887 WebContents::FromRenderFrameHost(host_)->GetBrowserContext()); |
| 888 if (!devtools_url_request_interceptor) { |
| 889 callback->sendFailure(Response::InternalError()); |
| 890 return; |
| 891 } |
| 892 |
| 893 BrowserThread::PostTask( |
| 894 BrowserThread::IO, FROM_HERE, |
| 895 base::BindOnce( |
| 896 &DevToolsURLRequestInterceptor::State::AllowRequest, |
| 897 devtools_url_request_interceptor->state().GetWeakPtr(), intercept_id, |
| 898 base::BindOnce( |
| 899 ProcessInterceptionCommandResultOnIoThread<AllowRequestCallback>, |
| 900 base::Passed(std::move(callback))))); |
| 901 } |
| 902 |
| 903 void NetworkHandler::BlockRequest( |
| 904 const String& intercept_id, |
| 905 const std::string& error_reason, |
| 906 std::unique_ptr<BlockRequestCallback> callback) { |
| 907 DevToolsURLRequestInterceptor* devtools_url_request_interceptor = |
| 908 DevToolsURLRequestInterceptor::FromBrowserContext( |
| 909 WebContents::FromRenderFrameHost(host_)->GetBrowserContext()); |
| 910 if (!devtools_url_request_interceptor) { |
| 911 callback->sendFailure(Response::InternalError()); |
| 912 return; |
| 913 } |
| 914 |
| 915 BrowserThread::PostTask( |
| 916 BrowserThread::IO, FROM_HERE, |
| 917 base::BindOnce( |
| 918 &DevToolsURLRequestInterceptor::State::BlockRequest, |
| 919 devtools_url_request_interceptor->state().GetWeakPtr(), intercept_id, |
| 920 NetErrorFromString(error_reason), |
| 921 base::BindOnce( |
| 922 ProcessInterceptionCommandResultOnIoThread<BlockRequestCallback>, |
| 923 base::Passed(std::move(callback))))); |
| 924 } |
| 925 |
| 926 void NetworkHandler::ModifyRequest( |
| 927 const String& intercept_id, |
| 928 Maybe<String> url, |
| 929 Maybe<String> method, |
| 930 Maybe<String> post_data, |
| 931 Maybe<protocol::Network::Headers> headers, |
| 932 std::unique_ptr<ModifyRequestCallback> callback) { |
| 933 DevToolsURLRequestInterceptor* devtools_url_request_interceptor = |
| 934 DevToolsURLRequestInterceptor::FromBrowserContext( |
| 935 WebContents::FromRenderFrameHost(host_)->GetBrowserContext()); |
| 936 if (!devtools_url_request_interceptor) { |
| 937 callback->sendFailure(Response::InternalError()); |
| 938 return; |
| 939 } |
| 940 |
| 941 BrowserThread::PostTask( |
| 942 BrowserThread::IO, FROM_HERE, |
| 943 base::BindOnce( |
| 944 &DevToolsURLRequestInterceptor::State::ModifyRequest, |
| 945 devtools_url_request_interceptor->state().GetWeakPtr(), intercept_id, |
| 946 base::MakeUnique<DevToolsURLRequestInterceptor::Modifications>( |
| 947 std::move(url), std::move(method), std::move(post_data), |
| 948 std::move(headers)), |
| 949 base::BindOnce( |
| 950 ProcessInterceptionCommandResultOnIoThread<ModifyRequestCallback>, |
| 951 base::Passed(std::move(callback))))); |
| 952 } |
| 953 |
| 954 void NetworkHandler::MockResponse( |
| 955 const String& intercept_id, |
| 956 const String& raw_response, |
| 957 std::unique_ptr<MockResponseCallback> callback) { |
| 958 DevToolsURLRequestInterceptor* devtools_url_request_interceptor = |
| 959 DevToolsURLRequestInterceptor::FromBrowserContext( |
| 960 WebContents::FromRenderFrameHost(host_)->GetBrowserContext()); |
| 961 if (!devtools_url_request_interceptor) { |
| 962 callback->sendFailure(Response::InternalError()); |
| 963 return; |
| 964 } |
| 965 |
| 966 BrowserThread::PostTask( |
| 967 BrowserThread::IO, FROM_HERE, |
| 968 base::BindOnce( |
| 969 &DevToolsURLRequestInterceptor::State::MockResponse, |
| 970 devtools_url_request_interceptor->state().GetWeakPtr(), intercept_id, |
| 971 raw_response, |
| 972 base::BindOnce( |
| 973 ProcessInterceptionCommandResultOnIoThread<MockResponseCallback>, |
| 974 base::Passed(std::move(callback))))); |
| 975 } |
| 976 |
| 977 // static |
| 978 std::unique_ptr<Network::Request> NetworkHandler::CreateRequestFromURLRequest( |
| 979 const net::URLRequest* request) { |
| 980 std::unique_ptr<DictionaryValue> headers_dict(DictionaryValue::create()); |
| 981 for (net::HttpRequestHeaders::Iterator it(request->extra_request_headers()); |
| 982 it.GetNext();) { |
| 983 headers_dict->setString(it.name(), it.value()); |
| 984 } |
| 985 // TODO(alexclarke): Support post data |
| 986 return Network::Request::Create() |
| 987 .SetUrl(request->url().spec()) |
| 988 .SetMethod(request->method()) |
| 989 .SetHeaders(Object::fromValue(headers_dict.get(), nullptr)) |
| 990 .SetInitialPriority(resourcePriority(request->priority())) |
| 991 .SetReferrerPolicy(referrerPolicy(request->referrer_policy())) |
| 992 .Build(); |
| 993 } |
| 994 |
765 } // namespace protocol | 995 } // namespace protocol |
766 } // namespace content | 996 } // namespace content |
OLD | NEW |