Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: content/browser/devtools/protocol/network_handler.cc

Issue 2739323003: DevTools protocol interception, blocking & modification of requests (Closed)
Patch Set: Add a comment Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/devtools/protocol/network_handler.h ('k') | content/browser/devtools/protocol_config.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698