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 EnableRequestInterception(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::EnableRequestInterception(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 devtools_url_request_interceptor->state()->StartInterceptingRequests( |
| 846 web_contents, weak_factory_.GetWeakPtr()); |
| 847 } else { |
| 848 devtools_url_request_interceptor->state()->StopInterceptingRequests( |
| 849 web_contents); |
| 850 } |
| 851 interception_enabled_ = enabled; |
| 852 return Response::OK(); |
| 853 } |
| 854 |
| 855 namespace { |
| 856 bool GetPostData(const net::URLRequest* request, std::string* post_data) { |
| 857 if (!request->has_upload()) |
| 858 return false; |
| 859 |
| 860 const net::UploadDataStream* stream = request->get_upload(); |
| 861 if (!stream->GetElementReaders()) |
| 862 return false; |
| 863 |
| 864 const auto* element_readers = stream->GetElementReaders(); |
| 865 if (element_readers->empty()) |
| 866 return false; |
| 867 |
| 868 *post_data = ""; |
| 869 for (const auto& element_reader : *element_readers) { |
| 870 const net::UploadBytesElementReader* reader = |
| 871 element_reader->AsBytesReader(); |
| 872 // TODO(alexclarke): This should really be base64 encoded. |
| 873 *post_data += std::string(reader->bytes(), reader->length()); |
| 874 } |
| 875 return true; |
| 876 } |
| 877 } // namespace |
| 878 |
| 879 // TODO(alexclarke): Support structured data as well as |base64_raw_response|. |
| 880 void NetworkHandler::ContinueInterceptedRequest( |
| 881 const std::string& interception_id, |
| 882 Maybe<std::string> error_reason, |
| 883 Maybe<std::string> base64_raw_response, |
| 884 Maybe<std::string> url, |
| 885 Maybe<std::string> method, |
| 886 Maybe<std::string> post_data, |
| 887 Maybe<protocol::Network::Headers> headers, |
| 888 std::unique_ptr<ContinueInterceptedRequestCallback> callback) { |
| 889 DevToolsURLRequestInterceptor* devtools_url_request_interceptor = |
| 890 DevToolsURLRequestInterceptor::FromBrowserContext( |
| 891 WebContents::FromRenderFrameHost(host_)->GetBrowserContext()); |
| 892 if (!devtools_url_request_interceptor) { |
| 893 callback->sendFailure(Response::InternalError()); |
| 894 return; |
| 895 } |
| 896 |
| 897 base::Optional<net::Error> error; |
| 898 if (error_reason.isJust()) |
| 899 error = NetErrorFromString(error_reason.fromJust()); |
| 900 |
| 901 base::Optional<std::string> raw_response; |
| 902 if (base64_raw_response.isJust()) { |
| 903 std::string decoded; |
| 904 if (!base::Base64Decode(base64_raw_response.fromJust(), &decoded)) { |
| 905 callback->sendFailure(Response::InvalidParams("Invalid rawResponse.")); |
| 906 return; |
| 907 } |
| 908 raw_response = decoded; |
| 909 } |
| 910 |
| 911 devtools_url_request_interceptor->state()->ContinueInterceptedRequest( |
| 912 interception_id, |
| 913 base::MakeUnique<DevToolsURLRequestInterceptor::Modifications>( |
| 914 std::move(error), std::move(raw_response), std::move(url), |
| 915 std::move(method), std::move(post_data), std::move(headers)), |
| 916 std::move(callback)); |
| 917 } |
| 918 |
| 919 // static |
| 920 std::unique_ptr<Network::Request> NetworkHandler::CreateRequestFromURLRequest( |
| 921 const net::URLRequest* request) { |
| 922 std::unique_ptr<DictionaryValue> headers_dict(DictionaryValue::create()); |
| 923 for (net::HttpRequestHeaders::Iterator it(request->extra_request_headers()); |
| 924 it.GetNext();) { |
| 925 headers_dict->setString(it.name(), it.value()); |
| 926 } |
| 927 std::unique_ptr<protocol::Network::Request> request_object = |
| 928 Network::Request::Create() |
| 929 .SetUrl(request->url().spec()) |
| 930 .SetMethod(request->method()) |
| 931 .SetHeaders(Object::fromValue(headers_dict.get(), nullptr)) |
| 932 .SetInitialPriority(resourcePriority(request->priority())) |
| 933 .SetReferrerPolicy(referrerPolicy(request->referrer_policy())) |
| 934 .Build(); |
| 935 std::string post_data; |
| 936 if (GetPostData(request, &post_data)) |
| 937 request_object->SetPostData(std::move(post_data)); |
| 938 return request_object; |
| 939 } |
| 940 |
773 } // namespace protocol | 941 } // namespace protocol |
774 } // namespace content | 942 } // namespace content |
OLD | NEW |