diff options
Diffstat (limited to 'chromium/content/browser/devtools')
63 files changed, 1303 insertions, 573 deletions
diff --git a/chromium/content/browser/devtools/BUILD.gn b/chromium/content/browser/devtools/BUILD.gn index a39fe433f3c..a1491eb8843 100644 --- a/chromium/content/browser/devtools/BUILD.gn +++ b/chromium/content/browser/devtools/BUILD.gn @@ -6,42 +6,39 @@ import("//third_party/inspector_protocol/inspector_protocol.gni") import("//third_party/protobuf/proto_library.gni") import("//tools/grit/grit_rule.gni") -group("resources") { - if (!is_android) { - public_deps = [ ":devtools_resources" ] - } -} +# Android and Fuchsia do not support DevTools front-end. +if (!is_android && !is_fuchsia) { + grit("devtools_resources") { + source = "$root_gen_dir/devtools/devtools_resources.grd" -grit("devtools_resources") { - source = "$root_gen_dir/devtools/devtools_resources.grd" + # Required because the .grd is generated. + enable_input_discovery_for_gn_analyze = false + use_brotli = true - # Required because the .grd is generated. - enable_input_discovery_for_gn_analyze = false - use_brotli = true - - outputs = [ - "grit/devtools_resources.h", - "devtools_resources.pak", - "grit/devtools_resources_map.cc", - "grit/devtools_resources_map.h", - ] + outputs = [ + "grit/devtools_resources.h", + "devtools_resources.pak", + "grit/devtools_resources_map.cc", + "grit/devtools_resources_map.h", + ] - grit_flags = [ - "-E", - "protocol_file=" + rebase_path( - "$root_gen_dir/third_party/blink/public/devtools_protocol/protocol.json", - root_build_dir), - ] + grit_flags = [ + "-E", + "protocol_file=" + rebase_path( + "$root_gen_dir/third_party/blink/public/devtools_protocol/protocol.json", + root_build_dir), + ] - defines = - [ "SHARED_INTERMEDIATE_DIR=" + rebase_path(root_gen_dir, root_build_dir) ] + defines = [ "SHARED_INTERMEDIATE_DIR=" + + rebase_path(root_gen_dir, root_build_dir) ] - deps = [ - "//third_party/blink/public/devtools_protocol:protocol_version", + deps = [ + "//third_party/blink/public/devtools_protocol:protocol_version", - # This is the action that generates out .grd input file. - "//third_party/blink/public:blink_generate_devtools_grd", - ] + # This is the action that generates out .grd input file. + "//third_party/blink/public:blink_generate_devtools_grd", + ] + } } inspector_protocol_generate("protocol_sources") { diff --git a/chromium/content/browser/devtools/cross_thread_protocol_callback.h b/chromium/content/browser/devtools/cross_thread_protocol_callback.h index f30c73d3a7e..ab86a2ca1c4 100644 --- a/chromium/content/browser/devtools/cross_thread_protocol_callback.h +++ b/chromium/content/browser/devtools/cross_thread_protocol_callback.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/task/post_task.h" #include "content/public/browser/browser_thread.h" namespace content { @@ -26,15 +25,15 @@ class CrossThreadProtocolCallback { template <typename... Args> void sendSuccess(Args&&... args) { - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&ProtocolCallback::sendSuccess, std::move(callback_), std::forward<Args>(args)...)); } void sendFailure(protocol::DispatchResponse response) { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&ProtocolCallback::sendFailure, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&ProtocolCallback::sendFailure, std::move(callback_), std::move(response))); } @@ -55,4 +54,4 @@ CrossThreadProtocolCallback<ProtocolCallback> WrapForAnotherThread( } // namespace content -#endif // CONTENT_BROWSER_DEVTOOLS_CROSS_THREAD_PROTOCOL_CALLBACK_H_
\ No newline at end of file +#endif // CONTENT_BROWSER_DEVTOOLS_CROSS_THREAD_PROTOCOL_CALLBACK_H_ diff --git a/chromium/content/browser/devtools/devtools_background_services_context_impl.cc b/chromium/content/browser/devtools/devtools_background_services_context_impl.cc index 8d979290e13..81117f4fb96 100644 --- a/chromium/content/browser/devtools/devtools_background_services_context_impl.cc +++ b/chromium/content/browser/devtools/devtools_background_services_context_impl.cc @@ -9,7 +9,6 @@ #include "base/guid.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" -#include "base/task/post_task.h" #include "base/time/time.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" @@ -201,8 +200,8 @@ void DevToolsBackgroundServicesContextImpl::DidGetUserData( return state1.timestamp() < state2.timestamp(); }); - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(std::move(callback), std::move(events))); + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), std::move(events))); } void DevToolsBackgroundServicesContextImpl::ClearLoggedBackgroundServiceEvents( diff --git a/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc b/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc index be04f844535..e9b83139822 100644 --- a/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc +++ b/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc @@ -77,9 +77,8 @@ bool ScreenshotCategoryEnabled() { } // namespace -DevToolsFrameTraceRecorder::DevToolsFrameTraceRecorder() { } - -DevToolsFrameTraceRecorder::~DevToolsFrameTraceRecorder() { } +DevToolsFrameTraceRecorder::DevToolsFrameTraceRecorder() = default; +DevToolsFrameTraceRecorder::~DevToolsFrameTraceRecorder() = default; void DevToolsFrameTraceRecorder::OnSynchronousSwapCompositorFrame( RenderFrameHostImpl* host, diff --git a/chromium/content/browser/devtools/devtools_frontend_host_impl.cc b/chromium/content/browser/devtools/devtools_frontend_host_impl.cc index cf2e631cf39..808b77ad691 100644 --- a/chromium/content/browser/devtools/devtools_frontend_host_impl.cc +++ b/chromium/content/browser/devtools/devtools_frontend_host_impl.cc @@ -84,8 +84,7 @@ DevToolsFrontendHostImpl::DevToolsFrontendHostImpl( receiver_.BindNewEndpointAndPassRemote()); } -DevToolsFrontendHostImpl::~DevToolsFrontendHostImpl() { -} +DevToolsFrontendHostImpl::~DevToolsFrontendHostImpl() = default; void DevToolsFrontendHostImpl::BadMessageRecieved() { bad_message::ReceivedBadMessage(web_contents_->GetMainFrame()->GetProcess(), diff --git a/chromium/content/browser/devtools/devtools_http_handler.cc b/chromium/content/browser/devtools/devtools_http_handler.cc index 4956b35c127..f66e6bca5e2 100644 --- a/chromium/content/browser/devtools/devtools_http_handler.cc +++ b/chromium/content/browser/devtools/devtools_http_handler.cc @@ -22,7 +22,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" -#include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "base/threading/thread.h" #include "base/values.h" @@ -55,7 +54,7 @@ #include "base/android/build_info.h" #endif -#if !defined(OS_FUCHSIA) +#if !defined(OS_ANDROID) && !defined(OS_FUCHSIA) #include "content/browser/devtools/grit/devtools_resources.h" // nogncheck #endif @@ -299,8 +298,8 @@ void StartServerOnHandlerThread( #endif } - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&ServerStartedOnUI, std::move(handler), thread.release(), server_wrapper.release(), socket_factory.release(), std::move(ip_address))); @@ -434,16 +433,16 @@ void ServerWrapper::OnHttpRequest(int connection_id, server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools); if (base::StartsWith(info.path, "/json", base::CompareCase::SENSITIVE)) { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&DevToolsHttpHandler::OnJsonRequest, handler_, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsHttpHandler::OnJsonRequest, handler_, connection_id, info)); return; } if (info.path.empty() || info.path == "/") { // Discovery page request. - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&DevToolsHttpHandler::OnDiscoveryPageRequest, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsHttpHandler::OnDiscoveryPageRequest, handler_, connection_id)); return; } @@ -467,8 +466,8 @@ void ServerWrapper::OnHttpRequest(int connection_id, } if (bundles_resources_) { - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsHttpHandler::OnFrontendResourceRequest, handler_, connection_id, filename)); return; @@ -479,20 +478,20 @@ void ServerWrapper::OnHttpRequest(int connection_id, void ServerWrapper::OnWebSocketRequest( int connection_id, const net::HttpServerRequestInfo& request) { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&DevToolsHttpHandler::OnWebSocketRequest, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsHttpHandler::OnWebSocketRequest, handler_, connection_id, request)); } void ServerWrapper::OnWebSocketMessage(int connection_id, std::string data) { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&DevToolsHttpHandler::OnWebSocketMessage, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsHttpHandler::OnWebSocketMessage, handler_, connection_id, std::move(data))); } void ServerWrapper::OnClose(int connection_id) { - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsHttpHandler::OnClose, handler_, connection_id)); } @@ -655,7 +654,7 @@ void DevToolsHttpHandler::OnJsonRequest( } void DevToolsHttpHandler::DecompressAndSendJsonProtocol(int connection_id) { -#if defined(OS_FUCHSIA) +#if defined(OS_ANDROID) || defined(OS_FUCHSIA) NOTREACHED(); #else scoped_refptr<base::RefCountedMemory> bytes = @@ -670,7 +669,7 @@ void DevToolsHttpHandler::DecompressAndSendJsonProtocol(int connection_id) { FROM_HERE, base::BindOnce(&ServerWrapper::SendResponse, base::Unretained(server_wrapper_.get()), connection_id, response)); -#endif // defined(OS_FUCHSIA) +#endif // defined(OS_ANDROID) || defined(OS_FUCHSIA) } void DevToolsHttpHandler::RespondToJsonList( diff --git a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc index eacdf6b3fdd..5797b4f6b82 100644 --- a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc +++ b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc @@ -18,10 +18,10 @@ #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" -#include "base/task/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/devtools_manager_delegate.h" #include "content/public/browser/devtools_socket_factory.h" @@ -70,14 +70,14 @@ class DummyServerSocketFactory : public DevToolsSocketFactory { shutdown_callback_(std::move(shutdown_callback)) {} ~DummyServerSocketFactory() override { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - std::move(shutdown_callback_)); + GetUIThreadTaskRunner({})->PostTask(FROM_HERE, + std::move(shutdown_callback_)); } protected: std::unique_ptr<net::ServerSocket> CreateForHttpServer() override { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - std::move(create_socket_callback_)); + GetUIThreadTaskRunner({})->PostTask(FROM_HERE, + std::move(create_socket_callback_)); return std::make_unique<DummyServerSocket>(); } @@ -99,8 +99,8 @@ class FailingServerSocketFactory : public DummyServerSocketFactory { private: std::unique_ptr<net::ServerSocket> CreateForHttpServer() override { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - std::move(create_socket_callback_)); + GetUIThreadTaskRunner({})->PostTask(FROM_HERE, + std::move(create_socket_callback_)); return nullptr; } }; diff --git a/chromium/content/browser/devtools/devtools_instrumentation.cc b/chromium/content/browser/devtools/devtools_instrumentation.cc index 27b5e222e96..b01b639cdb7 100644 --- a/chromium/content/browser/devtools/devtools_instrumentation.cc +++ b/chromium/content/browser/devtools/devtools_instrumentation.cc @@ -7,7 +7,11 @@ #include "components/download/public/common/download_create_info.h" #include "components/download/public/common/download_item.h" #include "content/browser/devtools/browser_devtools_agent_host.h" +#include "content/browser/devtools/devtools_issue_storage.h" #include "content/browser/devtools/devtools_url_loader_interceptor.h" +#include "content/browser/devtools/protocol/audits.h" +#include "content/browser/devtools/protocol/audits_handler.h" +#include "content/browser/devtools/protocol/browser_handler.h" #include "content/browser/devtools/protocol/emulation_handler.h" #include "content/browser/devtools/protocol/fetch_handler.h" #include "content/browser/devtools/protocol/log_handler.h" @@ -22,13 +26,17 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/web_package/signed_exchange_envelope.h" #include "content/common/navigation_params.mojom.h" +#include "content/public/browser/browser_context.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "net/base/load_flags.h" #include "net/cookies/canonical_cookie.h" +#include "net/cookies/cookie_inclusion_status.h" #include "net/http/http_request_headers.h" -#include "net/quic/quic_transport_client.h" +#include "net/proxy_resolution/proxy_config.h" +#include "net/quic/quic_transport_error.h" #include "net/ssl/ssl_info.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h" @@ -86,6 +94,35 @@ FrameTreeNode* GetFtnForNetworkRequest(int process_id, int routing_id) { RenderFrameHost::GetFrameTreeNodeIdForRoutingId(process_id, routing_id)); } +std::unique_ptr<protocol::Audits::HeavyAdIssueDetails> GetHeavyAdIssueHelper( + RenderFrameHostImpl* frame, + blink::mojom::HeavyAdResolutionStatus resolution, + blink::mojom::HeavyAdReason reason) { + protocol::String status = + (resolution == blink::mojom::HeavyAdResolutionStatus::kHeavyAdBlocked) + ? protocol::Audits::HeavyAdResolutionStatusEnum::HeavyAdBlocked + : protocol::Audits::HeavyAdResolutionStatusEnum::HeavyAdWarning; + protocol::String reason_string; + switch (reason) { + case blink::mojom::HeavyAdReason::kNetworkTotalLimit: + reason_string = protocol::Audits::HeavyAdReasonEnum::NetworkTotalLimit; + break; + case blink::mojom::HeavyAdReason::kCpuTotalLimit: + reason_string = protocol::Audits::HeavyAdReasonEnum::CpuTotalLimit; + break; + case blink::mojom::HeavyAdReason::kCpuPeakLimit: + reason_string = protocol::Audits::HeavyAdReasonEnum::CpuPeakLimit; + break; + } + return protocol::Audits::HeavyAdIssueDetails::Create() + .SetReason(reason_string) + .SetResolution(status) + .SetFrame(protocol::Audits::AffectedFrame::Create() + .SetFrameId(frame->GetDevToolsFrameToken().ToString()) + .Build()) + .Build(); +} + } // namespace void OnResetNavigationRequest(NavigationRequest* navigation_request) { @@ -110,11 +147,68 @@ void OnNavigationResponseReceived( frame_id); } +namespace { +protocol::String BuildBlockedByResponseReason( + network::mojom::BlockedByResponseReason reason) { + switch (reason) { + case network::mojom::BlockedByResponseReason:: + kCoepFrameResourceNeedsCoepHeader: + return protocol::Audits::BlockedByResponseReasonEnum:: + CoepFrameResourceNeedsCoepHeader; + case network::mojom::BlockedByResponseReason:: + kCoopSandboxedIFrameCannotNavigateToCoopPage: + return protocol::Audits::BlockedByResponseReasonEnum:: + CoopSandboxedIFrameCannotNavigateToCoopPage; + case network::mojom::BlockedByResponseReason::kCorpNotSameOrigin: + return protocol::Audits::BlockedByResponseReasonEnum::CorpNotSameOrigin; + case network::mojom::BlockedByResponseReason:: + kCorpNotSameOriginAfterDefaultedToSameOriginByCoep: + return protocol::Audits::BlockedByResponseReasonEnum:: + CorpNotSameOriginAfterDefaultedToSameOriginByCoep; + case network::mojom::BlockedByResponseReason::kCorpNotSameSite: + return protocol::Audits::BlockedByResponseReasonEnum::CorpNotSameSite; + } +} +} // namespace + void OnNavigationRequestFailed( const NavigationRequest& nav_request, const network::URLLoaderCompletionStatus& status) { FrameTreeNode* ftn = nav_request.frame_tree_node(); std::string id = nav_request.devtools_navigation_token().ToString(); + + if (status.blocked_by_response_reason) { + auto issueDetails = protocol::Audits::InspectorIssueDetails::Create(); + auto request = + protocol::Audits::AffectedRequest::Create() + .SetRequestId(id) + .SetUrl(const_cast<NavigationRequest&>(nav_request).GetURL().spec()) + .Build(); + auto blockedByResponseDetails = + protocol::Audits::BlockedByResponseIssueDetails::Create() + .SetRequest(std::move(request)) + .SetReason(BuildBlockedByResponseReason( + *status.blocked_by_response_reason)) + .Build(); + + blockedByResponseDetails->SetFrame( + protocol::Audits::AffectedFrame::Create() + .SetFrameId(ftn->devtools_frame_token().ToString()) + .Build()); + issueDetails.SetBlockedByResponseIssueDetails( + std::move(blockedByResponseDetails)); + + auto inspector_issue = + protocol::Audits::InspectorIssue::Create() + .SetCode(protocol::Audits::InspectorIssueCodeEnum:: + BlockedByResponseIssue) + .SetDetails(issueDetails.Build()) + .Build(); + + DispatchToAgents(ftn, &protocol::AuditsHandler::OnIssueAdded, + inspector_issue.get()); + } + DispatchToAgents(ftn, &protocol::NetworkHandler::LoadingComplete, id, protocol::Network::ResourceTypeEnum::Document, status); } @@ -458,12 +552,23 @@ bool WillCreateURLLoaderFactory( void OnNavigationRequestWillBeSent( const NavigationRequest& navigation_request) { - auto* agent_host = static_cast<RenderFrameDevToolsAgentHost*>( - RenderFrameDevToolsAgentHost::GetFor( - navigation_request.frame_tree_node())); - if (!agent_host) - return; - agent_host->OnNavigationRequestWillBeSent(navigation_request); + // Note this intentionally deviates from the usual instrumentation signal + // logic and dispatches to all agents upwards from the frame, to make sure + // the security checks are properly applied even if no DevTools session is + // established for the navigated frame itself. This is because the page + // agent may navigate all of its subframes currently. + for (RenderFrameHostImpl* rfh = + navigation_request.frame_tree_node()->current_frame_host(); + rfh; rfh = rfh->GetParent()) { + // Only check frames that qualify as DevTools targets, i.e. (local)? roots. + if (!RenderFrameDevToolsAgentHost::ShouldCreateDevToolsForHost(rfh)) + continue; + auto* agent_host = static_cast<RenderFrameDevToolsAgentHost*>( + RenderFrameDevToolsAgentHost::GetFor(rfh)); + if (!agent_host) + continue; + agent_host->OnNavigationRequestWillBeSent(navigation_request); + } // Make sure both back-ends yield the same timestamp. auto timestamp = base::TimeTicks::Now(); @@ -535,7 +640,7 @@ void OnRequestWillBeSentExtraInfo( int process_id, int routing_id, const std::string& devtools_request_id, - const net::CookieStatusList& request_cookie_list, + const net::CookieAccessResultList& request_cookie_list, const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers) { FrameTreeNode* ftn = GetFtnForNetworkRequest(process_id, routing_id); if (ftn) { @@ -629,41 +734,47 @@ void OnCorsPreflightRequestCompleted( } namespace { -std::vector<blink::mojom::SameSiteCookieExclusionReason> BuildExclusionReasons( - net::CanonicalCookie::CookieInclusionStatus status) { - std::vector<blink::mojom::SameSiteCookieExclusionReason> exclusion_reasons; +std::unique_ptr<protocol::Array<protocol::String>> BuildExclusionReasons( + net::CookieInclusionStatus status) { + auto exclusion_reasons = + std::make_unique<protocol::Array<protocol::String>>(); if (status.HasExclusionReason( - net::CanonicalCookie::CookieInclusionStatus:: + net::CookieInclusionStatus:: EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX)) { - exclusion_reasons.push_back(blink::mojom::SameSiteCookieExclusionReason:: - ExcludeSameSiteUnspecifiedTreatedAsLax); + exclusion_reasons->push_back( + protocol::Audits::SameSiteCookieExclusionReasonEnum:: + ExcludeSameSiteUnspecifiedTreatedAsLax); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_SAMESITE_NONE_INSECURE)) { - exclusion_reasons.push_back(blink::mojom::SameSiteCookieExclusionReason:: - ExcludeSameSiteNoneInsecure); + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE)) { + exclusion_reasons->push_back( + protocol::Audits::SameSiteCookieExclusionReasonEnum:: + ExcludeSameSiteNoneInsecure); } return exclusion_reasons; } -std::vector<blink::mojom::SameSiteCookieWarningReason> BuildWarningReasons( - net::CanonicalCookie::CookieInclusionStatus status) { - std::vector<blink::mojom::SameSiteCookieWarningReason> warning_reasons; +std::unique_ptr<protocol::Array<protocol::String>> BuildWarningReasons( + net::CookieInclusionStatus status) { + auto warning_reasons = std::make_unique<protocol::Array<protocol::String>>(); if (status.HasWarningReason( - net::CanonicalCookie::CookieInclusionStatus:: + net::CookieInclusionStatus:: WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT)) { - warning_reasons.push_back(blink::mojom::SameSiteCookieWarningReason:: - WarnSameSiteUnspecifiedCrossSiteContext); + warning_reasons->push_back( + protocol::Audits::SameSiteCookieWarningReasonEnum:: + WarnSameSiteUnspecifiedCrossSiteContext); } - if (status.HasWarningReason(net::CanonicalCookie::CookieInclusionStatus:: - WARN_SAMESITE_NONE_INSECURE)) { - warning_reasons.push_back( - blink::mojom::SameSiteCookieWarningReason::WarnSameSiteNoneInsecure); + if (status.HasWarningReason( + net::CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE)) { + warning_reasons->push_back( + protocol::Audits::SameSiteCookieWarningReasonEnum:: + WarnSameSiteNoneInsecure); } - if (status.HasWarningReason(net::CanonicalCookie::CookieInclusionStatus:: + if (status.HasWarningReason(net::CookieInclusionStatus:: WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE)) { - warning_reasons.push_back(blink::mojom::SameSiteCookieWarningReason:: - WarnSameSiteUnspecifiedLaxAllowUnsafe); + warning_reasons->push_back( + protocol::Audits::SameSiteCookieWarningReasonEnum:: + WarnSameSiteUnspecifiedLaxAllowUnsafe); } // If schemeful messages are disabled, don't add a warning for them. @@ -671,34 +782,50 @@ std::vector<blink::mojom::SameSiteCookieWarningReason> BuildWarningReasons( return warning_reasons; // There can only be one of the following warnings. - if (status.HasWarningReason(net::CanonicalCookie::CookieInclusionStatus:: + if (status.HasWarningReason(net::CookieInclusionStatus:: WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE)) { - warning_reasons.push_back(blink::mojom::SameSiteCookieWarningReason:: - WarnSameSiteStrictLaxDowngradeStrict); + warning_reasons->push_back( + protocol::Audits::SameSiteCookieWarningReasonEnum:: + WarnSameSiteStrictLaxDowngradeStrict); } else if (status.HasWarningReason( - net::CanonicalCookie::CookieInclusionStatus:: + net::CookieInclusionStatus:: WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE)) { - warning_reasons.push_back(blink::mojom::SameSiteCookieWarningReason:: - WarnSameSiteStrictCrossDowngradeStrict); + warning_reasons->push_back( + protocol::Audits::SameSiteCookieWarningReasonEnum:: + WarnSameSiteStrictCrossDowngradeStrict); } else if (status.HasWarningReason( - net::CanonicalCookie::CookieInclusionStatus:: + net::CookieInclusionStatus:: WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE)) { - warning_reasons.push_back(blink::mojom::SameSiteCookieWarningReason:: - WarnSameSiteStrictCrossDowngradeLax); + warning_reasons->push_back( + protocol::Audits::SameSiteCookieWarningReasonEnum:: + WarnSameSiteStrictCrossDowngradeLax); } else if (status.HasWarningReason( - net::CanonicalCookie::CookieInclusionStatus:: + net::CookieInclusionStatus:: WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE)) { - warning_reasons.push_back(blink::mojom::SameSiteCookieWarningReason:: - WarnSameSiteLaxCrossDowngradeStrict); + warning_reasons->push_back( + protocol::Audits::SameSiteCookieWarningReasonEnum:: + WarnSameSiteLaxCrossDowngradeStrict); } else if (status.HasWarningReason( - net::CanonicalCookie::CookieInclusionStatus:: + net::CookieInclusionStatus:: WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE)) { - warning_reasons.push_back(blink::mojom::SameSiteCookieWarningReason:: - WarnSameSiteLaxCrossDowngradeLax); + warning_reasons->push_back( + protocol::Audits::SameSiteCookieWarningReasonEnum:: + WarnSameSiteLaxCrossDowngradeLax); } return warning_reasons; } + +protocol::String BuildCookieOperation( + blink::mojom::SameSiteCookieOperation operation) { + switch (operation) { + case blink::mojom::SameSiteCookieOperation::kReadCookie: + return protocol::Audits::SameSiteCookieOperationEnum::ReadCookie; + case blink::mojom::SameSiteCookieOperation::kSetCookie: + return protocol::Audits::SameSiteCookieOperationEnum::SetCookie; + } +} + } // namespace void ReportSameSiteCookieIssue( @@ -708,32 +835,89 @@ void ReportSameSiteCookieIssue( const net::SiteForCookies& site_for_cookies, blink::mojom::SameSiteCookieOperation operation, const base::Optional<std::string>& devtools_request_id) { - blink::mojom::AffectedRequestPtr affected_request; + std::unique_ptr<protocol::Audits::AffectedRequest> affected_request; if (devtools_request_id) { // We can report the url here, because if devtools_request_id is set, the // url is the url of the request. - affected_request = - blink::mojom::AffectedRequest::New(*devtools_request_id, url.spec()); - } - auto affected_cookie = blink::mojom::AffectedCookie::New( - excluded_cookie.cookie.Name(), excluded_cookie.cookie.Path(), - excluded_cookie.cookie.Domain()); - auto details = blink::mojom::InspectorIssueDetails::New(); - base::Optional<GURL> optional_site_for_cookies_url; + affected_request = protocol::Audits::AffectedRequest::Create() + .SetRequestId(*devtools_request_id) + .SetUrl(url.spec()) + .Build(); + } + + auto affected_cookie = protocol::Audits::AffectedCookie::Create() + .SetName(excluded_cookie.cookie.Name()) + .SetPath(excluded_cookie.cookie.Path()) + .SetDomain(excluded_cookie.cookie.Domain()) + .Build(); + + auto same_site_details = + protocol::Audits::SameSiteCookieIssueDetails::Create() + .SetCookie(std::move(affected_cookie)) + .SetCookieExclusionReasons( + BuildExclusionReasons(excluded_cookie.status)) + .SetCookieWarningReasons(BuildWarningReasons(excluded_cookie.status)) + .SetOperation(BuildCookieOperation(operation)) + .SetCookieUrl(url.spec()) + .SetRequest(std::move(affected_request)) + .Build(); + if (!site_for_cookies.IsNull()) { - optional_site_for_cookies_url = site_for_cookies.RepresentativeUrl(); + same_site_details->SetSiteForCookies( + site_for_cookies.RepresentativeUrl().spec()); } - details->sameSiteCookieIssueDetails = - blink::mojom::SameSiteCookieIssueDetails::New( - std::move(affected_cookie), - BuildExclusionReasons(excluded_cookie.status), - BuildWarningReasons(excluded_cookie.status), operation, - optional_site_for_cookies_url, url, std::move(affected_request)); - render_frame_host_impl->AddInspectorIssue( - blink::mojom::InspectorIssueInfo::New( - blink::mojom::InspectorIssueCode::kSameSiteCookieIssue, - std::move(details))); + auto details = + protocol::Audits::InspectorIssueDetails::Create() + .SetSameSiteCookieIssueDetails(std::move(same_site_details)) + .Build(); + + auto issue = + protocol::Audits::InspectorIssue::Create() + .SetCode( + protocol::Audits::InspectorIssueCodeEnum::SameSiteCookieIssue) + .SetDetails(std::move(details)) + .Build(); + + ReportBrowserInitiatedIssue(render_frame_host_impl, issue.get()); +} + +namespace { + +void AddIssueToIssueStorage( + RenderFrameHost* frame, + std::unique_ptr<protocol::Audits::InspectorIssue> issue) { + WebContents* web_contents = WebContents::FromRenderFrameHost(frame); + DevToolsIssueStorage* issue_storage = + DevToolsIssueStorage::GetOrCreateForWebContents(web_contents); + + issue_storage->AddInspectorIssue(frame->GetFrameTreeNodeId(), + std::move(issue)); +} + +} // namespace + +void ReportBrowserInitiatedIssue(RenderFrameHostImpl* frame, + protocol::Audits::InspectorIssue* issue) { + FrameTreeNode* ftn = frame->frame_tree_node(); + if (!ftn) + return; + + AddIssueToIssueStorage(frame, issue->clone()); + DispatchToAgents(ftn, &protocol::AuditsHandler::OnIssueAdded, issue); +} + +std::unique_ptr<protocol::Audits::InspectorIssue> GetHeavyAdIssue( + RenderFrameHostImpl* frame, + blink::mojom::HeavyAdResolutionStatus resolution, + blink::mojom::HeavyAdReason reason) { + auto issue_details = protocol::Audits::InspectorIssueDetails::Create(); + issue_details.SetHeavyAdIssueDetails( + GetHeavyAdIssueHelper(frame, resolution, reason)); + return protocol::Audits::InspectorIssue::Create() + .SetCode(protocol::Audits::InspectorIssueCodeEnum::HeavyAdIssue) + .SetDetails(issue_details.Build()) + .Build(); } void OnQuicTransportHandshakeFailed( @@ -756,7 +940,19 @@ void OnQuicTransportHandshakeFailed( .SetText(text) .SetTimestamp(base::Time::Now().ToDoubleT() * 1000.0) .Build(); - DispatchToAgents(ftn, &protocol::LogHandler::EntryAdded, std::move(entry)); + DispatchToAgents(ftn, &protocol::LogHandler::EntryAdded, entry.get()); +} + +void ApplyNetworkContextParamsOverrides( + BrowserContext* browser_context, + network::mojom::NetworkContextParams* context_params) { + for (auto* agent_host : BrowserDevToolsAgentHost::Instances()) { + for (auto* target_handler : + protocol::TargetHandler::ForAgentHost(agent_host)) { + target_handler->ApplyNetworkContextParamsOverrides(browser_context, + context_params); + } + } } } // namespace devtools_instrumentation diff --git a/chromium/content/browser/devtools/devtools_instrumentation.h b/chromium/content/browser/devtools/devtools_instrumentation.h index e15c71b22a5..3746ac12a07 100644 --- a/chromium/content/browser/devtools/devtools_instrumentation.h +++ b/chromium/content/browser/devtools/devtools_instrumentation.h @@ -43,17 +43,24 @@ class DownloadItem; } // namespace download namespace content { -class SignedExchangeEnvelope; +class BrowserContext; class FrameTreeNode; class NavigationHandle; class NavigationRequest; class NavigationThrottle; class RenderFrameHostImpl; class RenderProcessHost; +class SignedExchangeEnvelope; class WebContents; struct SignedExchangeError; +namespace protocol { +namespace Audits { +class InspectorIssue; +} // namespace Audits +} // namespace protocol + namespace devtools_instrumentation { void ApplyNetworkRequestOverrides(FrameTreeNode* frame_tree_node, @@ -129,7 +136,7 @@ void OnRequestWillBeSentExtraInfo( int process_id, int routing_id, const std::string& devtools_request_id, - const net::CookieStatusList& request_cookie_list, + const net::CookieAccessResultList& request_cookie_list, const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers); void OnResponseReceivedExtraInfo( int process_id, @@ -180,11 +187,33 @@ void ReportSameSiteCookieIssue( blink::mojom::SameSiteCookieOperation operation, const base::Optional<std::string>& devtools_request_id); +// This function works similar to RenderFrameHostImpl::AddInspectorIssue, in +// that it reports an InspectorIssue to DevTools clients. The difference is that +// |ReportBrowserInitiatedIssue| sends issues directly to clients instead of +// going through the issue storage in the renderer process. Sending issues +// directly prevents them from being (potentially) lost during navigations. +// +// DevTools must be attached, otherwise issues reported through +// |ReportBrowserInitiatedIssue| are lost. +void CONTENT_EXPORT +ReportBrowserInitiatedIssue(RenderFrameHostImpl* frame, + protocol::Audits::InspectorIssue* issue); + +// Produces a Heavy Ad Issue based on the parameters passed in. +std::unique_ptr<protocol::Audits::InspectorIssue> GetHeavyAdIssue( + RenderFrameHostImpl* frame, + blink::mojom::HeavyAdResolutionStatus resolution, + blink::mojom::HeavyAdReason reason); + void OnQuicTransportHandshakeFailed( RenderFrameHostImpl* frame_host, const GURL& url, const base::Optional<net::QuicTransportError>& error); +void ApplyNetworkContextParamsOverrides( + BrowserContext* browser_context, + network::mojom::NetworkContextParams* network_context_params); + } // namespace devtools_instrumentation } // namespace content diff --git a/chromium/content/browser/devtools/devtools_issue_storage.cc b/chromium/content/browser/devtools/devtools_issue_storage.cc new file mode 100644 index 00000000000..45ca968a3d0 --- /dev/null +++ b/chromium/content/browser/devtools/devtools_issue_storage.cc @@ -0,0 +1,75 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/devtools/devtools_issue_storage.h" + +#include "content/browser/devtools/protocol/audits.h" +#include "content/public/browser/navigation_handle.h" +#include "ui/base/page_transition_types.h" + +namespace content { + +static const unsigned kMaxIssueCount = 1000; + +WEB_CONTENTS_USER_DATA_KEY_IMPL(DevToolsIssueStorage) + +DevToolsIssueStorage::DevToolsIssueStorage(WebContents* contents) + : WebContentsObserver(contents) {} +DevToolsIssueStorage::~DevToolsIssueStorage() = default; + +void DevToolsIssueStorage::AddInspectorIssue( + int frame_tree_node_id, + std::unique_ptr<protocol::Audits::InspectorIssue> issue) { + DCHECK_LE(issues_.size(), kMaxIssueCount); + if (issues_.size() == kMaxIssueCount) { + issues_.pop_front(); + } + issues_.emplace_back(frame_tree_node_id, std::move(issue)); +} + +std::vector<const protocol::Audits::InspectorIssue*> +DevToolsIssueStorage::FilterIssuesBy( + const base::flat_set<int>& frame_tree_node_ids) const { + std::vector<const protocol::Audits::InspectorIssue*> issues; + for (const auto& entry : issues_) { + if (frame_tree_node_ids.contains(entry.first)) { + issues.push_back(entry.second.get()); + } + } + return issues; +} + +void DevToolsIssueStorage::DidFinishNavigation( + NavigationHandle* navigation_handle) { + if (!navigation_handle->IsInMainFrame()) + return; + if (!navigation_handle->HasCommitted()) + return; + + const auto transition = navigation_handle->GetPageTransition(); + if (ui::PageTransitionIsRedirect(transition)) + return; + + issues_.clear(); +} + +void DevToolsIssueStorage::FrameDeleted(RenderFrameHost* render_frame_host) { + // Deletion of the main frame causes the DevToolsIssueStorage to be cleaned + // up. Also there would no longer be a root frame we could re-parent issues + // on. + auto* const main_frame = render_frame_host->GetMainFrame(); + if (render_frame_host == main_frame) + return; + + // Reassign issues from the deleted frame to the root frame. + const int frame_id = render_frame_host->GetFrameTreeNodeId(); + const int main_frame_id = main_frame->GetFrameTreeNodeId(); + for (auto& entry : issues_) { + if (entry.first == frame_id) { + entry.first = main_frame_id; + } + } +} + +} // namespace content diff --git a/chromium/content/browser/devtools/devtools_issue_storage.h b/chromium/content/browser/devtools/devtools_issue_storage.h new file mode 100644 index 00000000000..0042dc4761b --- /dev/null +++ b/chromium/content/browser/devtools/devtools_issue_storage.h @@ -0,0 +1,57 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_ISSUE_STORAGE_H_ +#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_ISSUE_STORAGE_H_ + +#include <deque> + +#include "base/unguessable_token.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace content { + +namespace protocol { +namespace Audits { +class InspectorIssue; +} // namespace Audits +} // namespace protocol + +class DevToolsIssueStorage + : public content::WebContentsUserData<DevToolsIssueStorage>, + public WebContentsObserver { + public: + ~DevToolsIssueStorage() override; + + static DevToolsIssueStorage* GetOrCreateForWebContents( + WebContents* contents) { + content::WebContentsUserData<DevToolsIssueStorage>::CreateForWebContents( + contents); + return FromWebContents(contents); + } + + void AddInspectorIssue( + int frame_tree_node_id, + std::unique_ptr<protocol::Audits::InspectorIssue> issue); + std::vector<const protocol::Audits::InspectorIssue*> FilterIssuesBy( + const base::flat_set<int>& frame_tree_node_ids) const; + + private: + explicit DevToolsIssueStorage(content::WebContents* contents); + friend class content::WebContentsUserData<DevToolsIssueStorage>; + WEB_CONTENTS_USER_DATA_KEY_DECL(); + + // WebContentsObserver overrides. + void DidFinishNavigation(NavigationHandle* navigation_handle) override; + void FrameDeleted(RenderFrameHost* render_frame_host) override; + + using FrameAssociatedIssue = + std::pair<int, std::unique_ptr<protocol::Audits::InspectorIssue>>; + std::deque<FrameAssociatedIssue> issues_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_ISSUE_STORAGE_H_ diff --git a/chromium/content/browser/devtools/devtools_issue_storage_browsertest.cc b/chromium/content/browser/devtools/devtools_issue_storage_browsertest.cc new file mode 100644 index 00000000000..416a0ed98b5 --- /dev/null +++ b/chromium/content/browser/devtools/devtools_issue_storage_browsertest.cc @@ -0,0 +1,152 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/devtools/devtools_instrumentation.h" +#include "content/browser/devtools/protocol/audits.h" +#include "content/browser/devtools/protocol/devtools_protocol_test_support.h" +#include "content/browser/devtools/render_frame_devtools_agent_host.h" +#include "content/browser/frame_host/frame_tree_node.h" +#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/devtools_agent_host.h" +#include "content/public/browser/devtools_agent_host_client.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/url_constants.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_base.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/content_browser_test.h" +#include "content/public/test/content_browser_test_utils.h" +#include "content/shell/browser/shell.h" +#include "net/dns/mock_host_resolver.h" + +namespace content { + +class DevToolsIssueStorageBrowserTest : public DevToolsProtocolTest { + public: + void SetUpOnMainThread() override { + host_resolver()->AddRule("*", "127.0.0.1"); + SetupCrossSiteRedirector(embedded_test_server()); + } +}; + +namespace { + +void ReportDummyIssue(RenderFrameHostImpl* rfh) { + auto issueDetails = protocol::Audits::InspectorIssueDetails::Create(); + auto inspector_issue = + protocol::Audits::InspectorIssue::Create() + .SetCode( + protocol::Audits::InspectorIssueCodeEnum::SameSiteCookieIssue) + .SetDetails(issueDetails.Build()) + .Build(); + devtools_instrumentation::ReportBrowserInitiatedIssue(rfh, + inspector_issue.get()); +} + +} // namespace + +IN_PROC_BROWSER_TEST_F(DevToolsIssueStorageBrowserTest, + DevToolsReceivesBrowserIssues) { + // 1) Navigate to about:blank. + EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank"))); + + // 2) Report an empty SameSite cookie issue. + WebContentsImpl* web_contents_impl = + static_cast<WebContentsImpl*>(shell()->web_contents()); + RenderFrameHostImpl* root = web_contents_impl->GetFrameTree()->GetMainFrame(); + ReportDummyIssue(root); + + // 3) Open DevTools. + Attach(); + + // 4) Verify we haven't received any Issues yet. + ASSERT_TRUE(notifications_.empty()); + + // 5) Enable audits domain. + SendCommand("Audits.enable", std::make_unique<base::DictionaryValue>()); + + // 6) Verify we have received the SameSite issue. + WaitForNotification("Audits.issueAdded", true); +} + +IN_PROC_BROWSER_TEST_F(DevToolsIssueStorageBrowserTest, + DevToolsReceivesBrowserIssuesWhileAttached) { + // 1) Navigate to about:blank. + EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank"))); + + // 2) Open DevTools and enable Audits domain. + Attach(); + SendCommand("Audits.enable", std::make_unique<base::DictionaryValue>()); + + // 3) Verify we haven't received any Issues yet. + ASSERT_TRUE(notifications_.empty()); + + // 4) Report an empty SameSite cookie issue. + WebContentsImpl* web_contents_impl = + static_cast<WebContentsImpl*>(shell()->web_contents()); + RenderFrameHostImpl* root = web_contents_impl->GetFrameTree()->GetMainFrame(); + ReportDummyIssue(root); + + // 5) Verify we have received the SameSite issue. + WaitForNotification("Audits.issueAdded", true); +} + +IN_PROC_BROWSER_TEST_F(DevToolsIssueStorageBrowserTest, + DeleteSubframeWithIssue) { + // 1) Navigate to a page with an OOP iframe. + ASSERT_TRUE(embedded_test_server()->Start()); + GURL test_url = + embedded_test_server()->GetURL("/devtools/page-with-oopif.html"); + EXPECT_TRUE(NavigateToURL(shell(), test_url)); + + // 2) Report an empty SameSite cookie issue in the iframe. + WebContentsImpl* web_contents_impl = + static_cast<WebContentsImpl*>(shell()->web_contents()); + RenderFrameHostImpl* root = web_contents_impl->GetFrameTree()->GetMainFrame(); + EXPECT_EQ(root->child_count(), static_cast<unsigned>(1)); + RenderFrameHostImpl* iframe = root->child_at(0)->current_frame_host(); + EXPECT_FALSE(iframe->is_main_frame()); + + ReportDummyIssue(iframe); + + // 3) Delete the iframe from the page. This should cause the issue to be + // re-assigned + // to the root frame. + root->RemoveChild(iframe->frame_tree_node()); + + // 4) Open DevTools and enable Audits domain. + Attach(); + SendCommand("Audits.enable", std::make_unique<base::DictionaryValue>()); + + // 5) Verify we have received the SameSite issue on the main target. + WaitForNotification("Audits.issueAdded", true); +} + +IN_PROC_BROWSER_TEST_F(DevToolsIssueStorageBrowserTest, + MainFrameNavigationClearsIssues) { + // 1) Navigate to about:blank. + EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank"))); + + // 2) Report an empty SameSite cookie issue. + WebContentsImpl* web_contents_impl = + static_cast<WebContentsImpl*>(shell()->web_contents()); + RenderFrameHostImpl* root = web_contents_impl->GetFrameTree()->GetMainFrame(); + ReportDummyIssue(root); + + // 3) Navigate to /devtools/navigation.html + ASSERT_TRUE(embedded_test_server()->Start()); + GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html"); + EXPECT_TRUE(NavigateToURL(shell(), test_url)); + + // 4) Open DevTools and enable Audits domain. + Attach(); + SendCommand("Audits.enable", std::make_unique<base::DictionaryValue>()); + + // 5) Verify that we haven't received any notifications. + ASSERT_TRUE(notifications_.empty()); +} + +} // namespace content diff --git a/chromium/content/browser/devtools/devtools_manager.cc b/chromium/content/browser/devtools/devtools_manager.cc index 776022c5666..8fc3c21edd4 100644 --- a/chromium/content/browser/devtools/devtools_manager.cc +++ b/chromium/content/browser/devtools/devtools_manager.cc @@ -55,8 +55,7 @@ DevToolsManager::DevToolsManager() : delegate_(GetContentClient()->browser()->GetDevToolsManagerDelegate()) { } -DevToolsManager::~DevToolsManager() { -} +DevToolsManager::~DevToolsManager() = default; void DevToolsManager::SetHttpHandler( std::unique_ptr<DevToolsHttpHandler> http_handler) { diff --git a/chromium/content/browser/devtools/devtools_manager_unittest.cc b/chromium/content/browser/devtools/devtools_manager_unittest.cc index b8c3724b8b0..4f82a35c7ef 100644 --- a/chromium/content/browser/devtools/devtools_manager_unittest.cc +++ b/chromium/content/browser/devtools/devtools_manager_unittest.cc @@ -143,16 +143,16 @@ TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) { // Start a timeout. inspected_rvh->GetWidget()->StartInputEventAckTimeout(); - task_environment()->FastForwardBy( - base::TimeDelta::FromMilliseconds(kHungRendererDelayMs + 10)); + task_environment()->FastForwardBy(kHungRendererDelay + + base::TimeDelta::FromMilliseconds(10)); EXPECT_FALSE(delegate.renderer_unresponsive_received()); // Now close devtools and check that the notification is delivered. client_host.Close(); // Start a timeout. inspected_rvh->GetWidget()->StartInputEventAckTimeout(); - task_environment()->FastForwardBy( - base::TimeDelta::FromMilliseconds(kHungRendererDelayMs + 10)); + task_environment()->FastForwardBy(kHungRendererDelay + + base::TimeDelta::FromMilliseconds(10)); EXPECT_TRUE(delegate.renderer_unresponsive_received()); contents()->SetDelegate(nullptr); diff --git a/chromium/content/browser/devtools/devtools_pipe_handler.cc b/chromium/content/browser/devtools/devtools_pipe_handler.cc index adc55dd21f4..504417b6172 100644 --- a/chromium/content/browser/devtools/devtools_pipe_handler.cc +++ b/chromium/content/browser/devtools/devtools_pipe_handler.cc @@ -26,7 +26,6 @@ #include "base/single_thread_task_runner.h" #include "base/strings/string_util.h" #include "base/synchronization/atomic_flag.h" -#include "base/task/post_task.h" #include "base/threading/thread.h" #include "build/build_config.h" #include "content/public/browser/browser_task_traits.h" @@ -79,11 +78,10 @@ class PipeIOBase { pipe_io.reset(); } // Post background task that would join and destroy the thread. - base::DeleteSoon( - FROM_HERE, - {base::ThreadPool(), base::MayBlock(), base::WithBaseSyncPrimitives(), - base::TaskPriority::BEST_EFFORT}, - std::move(thread)); + base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, + base::WithBaseSyncPrimitives(), base::TaskPriority::BEST_EFFORT}) + ->DeleteSoon(FROM_HERE, std::move(thread)); } protected: @@ -156,16 +154,16 @@ class PipeReaderBase : public PipeIOBase { } void HandleMessage(std::vector<uint8_t> message) { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&DevToolsPipeHandler::HandleMessage, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsPipeHandler::HandleMessage, devtools_handler_, std::move(message))); } private: void ReadLoop() { ReadLoopInternal(); - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsPipeHandler::Shutdown, devtools_handler_)); } diff --git a/chromium/content/browser/devtools/devtools_stream_blob.cc b/chromium/content/browser/devtools/devtools_stream_blob.cc index 4812bae0335..27f0eec87ff 100644 --- a/chromium/content/browser/devtools/devtools_stream_blob.cc +++ b/chromium/content/browser/devtools/devtools_stream_blob.cc @@ -7,7 +7,6 @@ #include "base/base64.h" #include "base/bind.h" #include "base/strings/string_piece.h" -#include "base/task/post_task.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -30,8 +29,7 @@ DevToolsStreamBlob::ReadRequest::ReadRequest(off_t position, DevToolsStreamBlob::ReadRequest::~ReadRequest() = default; DevToolsStreamBlob::DevToolsStreamBlob() - : DevToolsIOContext::Stream( - base::CreateSingleThreadTaskRunner({BrowserThread::IO})), + : DevToolsIOContext::Stream(GetIOThreadTaskRunner({})), last_read_pos_(0), failed_(false), is_binary_(false) {} @@ -66,8 +64,8 @@ scoped_refptr<DevToolsIOContext::Stream> DevToolsStreamBlob::Create( } void DevToolsStreamBlob::ReadRequest::Fail() { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(std::move(callback), nullptr, false, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), nullptr, false, Stream::StatusFailure)); } @@ -75,8 +73,8 @@ void DevToolsStreamBlob::Open(scoped_refptr<ChromeBlobStorageContext> context, StoragePartition* partition, const std::string& handle, OpenCallback callback) { - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&DevToolsStreamBlob::OpenOnIO, this, context, + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsStreamBlob::OpenOnIO, this, context, handle, std::move(callback))); } @@ -85,8 +83,8 @@ void DevToolsStreamBlob::Read(off_t position, ReadCallback callback) { std::unique_ptr<ReadRequest> request( new ReadRequest(position, max_size, std::move(callback))); - base::PostTask( - FROM_HERE, {BrowserThread::IO}, + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsStreamBlob::ReadOnIO, this, std::move(request))); } @@ -117,8 +115,8 @@ void DevToolsStreamBlob::OnBlobConstructionComplete( FailOnIO(std::move(open_callback_)); return; } - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(std::move(open_callback_), true)); + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(open_callback_), true)); if (!pending_reads_.empty()) StartReadRequest(); } @@ -143,8 +141,8 @@ void DevToolsStreamBlob::FailOnIO() { } void DevToolsStreamBlob::FailOnIO(OpenCallback callback) { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(std::move(callback), false)); + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), false)); FailOnIO(); } @@ -180,8 +178,8 @@ void DevToolsStreamBlob::BeginRead() { bytes_read = blob_reader_->net_error(); DCHECK_LT(0, bytes_read); } - base::PostTask( - FROM_HERE, {BrowserThread::IO}, + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsStreamBlob::OnReadComplete, this, bytes_read)); } @@ -209,8 +207,8 @@ void DevToolsStreamBlob::OnReadComplete(int bytes_read) { *data = std::string(io_buf_->data(), bytes_read); } } - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(std::move(request->callback), std::move(data), + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(request->callback), std::move(data), base64_encoded, status)); if (!pending_reads_.empty()) StartReadRequest(); diff --git a/chromium/content/browser/devtools/devtools_stream_file.cc b/chromium/content/browser/devtools/devtools_stream_file.cc index f1bd14fb998..d7f389b075b 100644 --- a/chromium/content/browser/devtools/devtools_stream_file.cc +++ b/chromium/content/browser/devtools/devtools_stream_file.cc @@ -10,7 +10,6 @@ #include "base/sequenced_task_runner.h" #include "base/strings/string_util.h" #include "base/task/lazy_thread_pool_task_runner.h" -#include "base/task/post_task.h" #include "base/third_party/icu/icu_utf.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -121,8 +120,8 @@ void DevToolsStreamFile::ReadOnFileSequence(off_t position, base::Base64Encode(raw_data, data.get()); base64_encoded = true; } - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(std::move(callback), std::move(data), + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), std::move(data), base64_encoded, status)); } diff --git a/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc b/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc index 94c329f309b..d235f1e91c2 100644 --- a/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc +++ b/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc @@ -23,6 +23,7 @@ #include "mojo/public/cpp/system/data_pipe_drainer.h" #include "net/base/load_flags.h" #include "net/base/mime_sniffer.h" +#include "net/cookies/cookie_inclusion_status.h" #include "net/cookies/cookie_util.h" #include "net/http/http_util.h" #include "net/url_request/redirect_util.h" @@ -323,8 +324,8 @@ class InterceptionJob : public network::mojom::URLLoaderClient, network::mojom::CookieManager::GetCookieListCallback callback); void NotifyClientWithCookies( std::unique_ptr<InterceptedRequestInfo> request_info, - const net::CookieStatusList& cookie_list_with_statuses, - const net::CookieStatusList& excluded_cookies); + const net::CookieAccessResultList& cookies_with_access_result, + const net::CookieAccessResultList& excluded_cookies); void ResponseBodyComplete(); @@ -527,7 +528,7 @@ DevToolsURLLoaderFactoryProxy::DevToolsURLLoaderFactoryProxy( base::Unretained(this))); } -DevToolsURLLoaderFactoryProxy::~DevToolsURLLoaderFactoryProxy() {} +DevToolsURLLoaderFactoryProxy::~DevToolsURLLoaderFactoryProxy() = default; void DevToolsURLLoaderFactoryProxy::CreateLoaderAndStart( mojo::PendingReceiver<network::mojom::URLLoader> loader, @@ -1112,8 +1113,9 @@ void InterceptionJob::ProcessSetCookies(const net::HttpResponseHeaders& headers, // |this| might be deleted here if |cookies| is empty! auto on_cookie_set = base::BindRepeating( - [](base::RepeatingClosure closure, - net::CanonicalCookie::CookieInclusionStatus) { closure.Run(); }, + [](base::RepeatingClosure closure, net::CookieInclusionStatus) { + closure.Run(); + }, base::BarrierClosure(cookies.size(), std::move(callback))); for (auto& cookie : cookies) { cookie_manager_->SetCanonicalCookie( @@ -1269,14 +1271,14 @@ void InterceptionJob::NotifyClient( void InterceptionJob::NotifyClientWithCookies( std::unique_ptr<InterceptedRequestInfo> request_info, - const net::CookieStatusList& cookie_list_with_statuses, - const net::CookieStatusList& excluded_cookies) { + const net::CookieAccessResultList& cookies_with_access_result, + const net::CookieAccessResultList& excluded_cookies) { if (!interceptor_) return; std::string cookie_line; - if (!cookie_list_with_statuses.empty()) { + if (!cookies_with_access_result.empty()) { cookie_line = - net::CanonicalCookie::BuildCookieLine(cookie_list_with_statuses); + net::CanonicalCookie::BuildCookieLine(cookies_with_access_result); } request_info->network_request = protocol::NetworkHandler::CreateRequestFromResourceRequest( diff --git a/chromium/content/browser/devtools/devtools_video_consumer.cc b/chromium/content/browser/devtools/devtools_video_consumer.cc index 2217c3a9379..4e62096ce60 100644 --- a/chromium/content/browser/devtools/devtools_video_consumer.cc +++ b/chromium/content/browser/devtools/devtools_video_consumer.cc @@ -172,7 +172,7 @@ void DevToolsVideoConsumer::OnFrameCaptured( mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks> callbacks) {}, std::move(mapping), std::move(callbacks))); - frame->metadata()->MergeInternalValuesFrom(info->metadata); + frame->set_metadata(info->metadata); if (info->color_space.has_value()) frame->set_color_space(info->color_space.value()); diff --git a/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc b/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc index 32fbdaa3110..1613c7541aa 100644 --- a/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc +++ b/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc @@ -192,9 +192,8 @@ class DevToolsVideoConsumerTest : public testing::Test { callbacks.Bind(callbacks_remote.InitWithNewPipeAndPassReceiver()); media::mojom::VideoFrameInfoPtr info = media::mojom::VideoFrameInfo::New( - base::TimeDelta(), base::Value(base::Value::Type::DICTIONARY), kFormat, - kResolution, gfx::Rect(kResolution), gfx::ColorSpace::CreateREC709(), - nullptr); + base::TimeDelta(), media::VideoFrameMetadata(), kFormat, kResolution, + gfx::Rect(kResolution), gfx::ColorSpace::CreateREC709(), nullptr); consumer_->OnFrameCaptured(std::move(data), std::move(info), gfx::Rect(kResolution), diff --git a/chromium/content/browser/devtools/forwarding_agent_host.cc b/chromium/content/browser/devtools/forwarding_agent_host.cc index 5aa65ea8230..adb6d0cb296 100644 --- a/chromium/content/browser/devtools/forwarding_agent_host.cc +++ b/chromium/content/browser/devtools/forwarding_agent_host.cc @@ -17,8 +17,7 @@ ForwardingAgentHost::ForwardingAgentHost( NotifyCreated(); } -ForwardingAgentHost::~ForwardingAgentHost() { -} +ForwardingAgentHost::~ForwardingAgentHost() = default; bool ForwardingAgentHost::AttachSession(DevToolsSession* session) { session->TurnIntoExternalProxy(delegate_.get()); diff --git a/chromium/content/browser/devtools/protocol/audits_handler.cc b/chromium/content/browser/devtools/protocol/audits_handler.cc index 9f32e63e2f8..b6baeeac78e 100644 --- a/chromium/content/browser/devtools/protocol/audits_handler.cc +++ b/chromium/content/browser/devtools/protocol/audits_handler.cc @@ -5,6 +5,9 @@ #include "content/browser/devtools/protocol/audits_handler.h" #include "content/browser/devtools/devtools_agent_host_impl.h" +#include "content/browser/devtools/devtools_issue_storage.h" +#include "content/browser/devtools/render_frame_devtools_agent_host.h" +#include "content/browser/frame_host/frame_tree_node.h" namespace content { namespace protocol { @@ -19,6 +22,11 @@ std::vector<AuditsHandler*> AuditsHandler::ForAgentHost( return host->HandlersByName<AuditsHandler>(Audits::Metainfo::domainName); } +void AuditsHandler::SetRenderer(int process_host_id, + RenderFrameHostImpl* frame_host) { + host_ = frame_host; +} + void AuditsHandler::Wire(UberDispatcher* dispatcher) { frontend_ = std::make_unique<Audits::Frontend>(dispatcher->channel()); Audits::Dispatcher::wire(dispatcher, this); @@ -29,10 +37,57 @@ DispatchResponse AuditsHandler::Disable() { return Response::FallThrough(); } +namespace { + +void SendStoredIssuesForFrameToAgent(RenderFrameHostImpl* rfh, + protocol::AuditsHandler* handler) { + // Check the storage first. No need to do any work in case its empty. + WebContents* web_contents = WebContents::FromRenderFrameHost(rfh); + DevToolsIssueStorage* issue_storage = + DevToolsIssueStorage::FromWebContents(web_contents); + if (!issue_storage) + return; + + FrameTreeNode* local_root = rfh->frame_tree_node(); + + std::vector<int> frame_tree_node_ids; + for (FrameTreeNode* node : rfh->frame_tree()->SubtreeNodes(local_root)) { + // For each child we find the child's local root. Should the child's local + // root match |local_root|, the provided |AuditsHandler| is responsible and + // we collect the devtools_frame_token. + if (local_root == GetFrameTreeNodeAncestor(node)) { + frame_tree_node_ids.push_back(node->frame_tree_node_id()); + } + } + + base::flat_set<int> frame_ids_set(frame_tree_node_ids); + auto issues = issue_storage->FilterIssuesBy(std::move(frame_ids_set)); + for (auto* const issue : issues) { + handler->OnIssueAdded(issue); + } +} + +} // namespace + DispatchResponse AuditsHandler::Enable() { + if (enabled_) { + return Response::FallThrough(); + } + enabled_ = true; + if (host_) { + SendStoredIssuesForFrameToAgent(host_, this); + } + return Response::FallThrough(); } +void AuditsHandler::OnIssueAdded( + const protocol::Audits::InspectorIssue* issue) { + if (enabled_) { + frontend_->IssueAdded(issue->clone()); + } +} + } // namespace protocol } // namespace content diff --git a/chromium/content/browser/devtools/protocol/audits_handler.h b/chromium/content/browser/devtools/protocol/audits_handler.h index 1d00247954c..f80587abdf7 100644 --- a/chromium/content/browser/devtools/protocol/audits_handler.h +++ b/chromium/content/browser/devtools/protocol/audits_handler.h @@ -8,6 +8,7 @@ #include "base/macros.h" #include "content/browser/devtools/protocol/audits.h" #include "content/browser/devtools/protocol/devtools_domain_handler.h" +#include "content/browser/frame_host/render_frame_host_impl.h" #include "mojo/public/cpp/bindings/remote.h" namespace content { @@ -25,15 +26,20 @@ class AuditsHandler final : public DevToolsDomainHandler, static std::vector<AuditsHandler*> ForAgentHost(DevToolsAgentHostImpl* host); // DevToolsDomainHandler implementation. + void SetRenderer(int process_host_id, + RenderFrameHostImpl* frame_host) override; void Wire(UberDispatcher* dispatcher) override; // Audits::Backend implementation. DispatchResponse Disable() override; DispatchResponse Enable() override; + void OnIssueAdded(const protocol::Audits::InspectorIssue* issue); + private: std::unique_ptr<Audits::Frontend> frontend_; bool enabled_ = false; + RenderFrameHostImpl* host_; DISALLOW_COPY_AND_ASSIGN(AuditsHandler); }; diff --git a/chromium/content/browser/devtools/protocol/browser_handler.cc b/chromium/content/browser/devtools/protocol/browser_handler.cc index fd8287531b8..d446d4f44de 100644 --- a/chromium/content/browser/devtools/protocol/browser_handler.cc +++ b/chromium/content/browser/devtools/protocol/browser_handler.cc @@ -35,7 +35,7 @@ BrowserHandler::BrowserHandler(bool allow_set_download_behavior) : DevToolsDomainHandler(Browser::Metainfo::domainName), allow_set_download_behavior_(allow_set_download_behavior) {} -BrowserHandler::~BrowserHandler() {} +BrowserHandler::~BrowserHandler() = default; Response BrowserHandler::Disable() { // TODO: this leaks context ids for all contexts with overridden permissions. diff --git a/chromium/content/browser/devtools/protocol/devtools_domain_handler.cc b/chromium/content/browser/devtools/protocol/devtools_domain_handler.cc index e89a12e0aa3..802bb71f364 100644 --- a/chromium/content/browser/devtools/protocol/devtools_domain_handler.cc +++ b/chromium/content/browser/devtools/protocol/devtools_domain_handler.cc @@ -14,8 +14,7 @@ DevToolsDomainHandler::DevToolsDomainHandler(const std::string& name) : name_(name) { } -DevToolsDomainHandler::~DevToolsDomainHandler() { -} +DevToolsDomainHandler::~DevToolsDomainHandler() = default; void DevToolsDomainHandler::SetRenderer(int process_host_id, RenderFrameHostImpl* frame_host) {} diff --git a/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc b/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc index a33e174eb94..d751a29a847 100644 --- a/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc +++ b/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc @@ -6,7 +6,6 @@ #include "base/bind.h" #include "base/files/file_util.h" -#include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" @@ -81,6 +80,7 @@ bool DevToolsDownloadManagerDelegate::DetermineDownloadTarget( empty_path, download::DownloadItem::TARGET_DISPOSITION_OVERWRITE, download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, download::DownloadItem::MixedContentStatus::UNKNOWN, empty_path, + base::nullopt /*download_schedule*/, download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); return true; } @@ -147,8 +147,8 @@ void DevToolsDownloadManagerDelegate::GenerateFilename( base::CreateDirectory(suggested_directory); base::FilePath suggested_path(suggested_directory.Append(generated_name)); - base::PostTask(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(std::move(callback), suggested_path)); + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), suggested_path)); } void DevToolsDownloadManagerDelegate::OnDownloadPathGenerated( @@ -162,6 +162,7 @@ void DevToolsDownloadManagerDelegate::OnDownloadPathGenerated( download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, download::DownloadItem::MixedContentStatus::UNKNOWN, suggested_path.AddExtension(FILE_PATH_LITERAL(".crdownload")), + base::nullopt /*download_schedule*/, download::DOWNLOAD_INTERRUPT_REASON_NONE); } diff --git a/chromium/content/browser/devtools/protocol/devtools_mhtml_helper.cc b/chromium/content/browser/devtools/protocol/devtools_mhtml_helper.cc index 102d27af5a1..fb44f934f42 100644 --- a/chromium/content/browser/devtools/protocol/devtools_mhtml_helper.cc +++ b/chromium/content/browser/devtools/protocol/devtools_mhtml_helper.cc @@ -5,7 +5,6 @@ #include "content/browser/devtools/protocol/devtools_mhtml_helper.h" #include "base/bind.h" -#include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_task_traits.h" @@ -30,8 +29,8 @@ DevToolsMHTMLHelper::DevToolsMHTMLHelper( DevToolsMHTMLHelper::~DevToolsMHTMLHelper() { if (mhtml_file_.get()) { - base::PostTask( - FROM_HERE, {BrowserThread::IO}, + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&ClearFileReferenceOnIOThread, std::move(mhtml_file_))); } } @@ -58,8 +57,8 @@ void DevToolsMHTMLHelper::CreateTemporaryFile() { ReportFailure("Unable to create temporary file"); return; } - base::PostTask( - FROM_HERE, {BrowserThread::IO}, + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsMHTMLHelper::TemporaryFileCreatedOnIO, this)); } @@ -82,8 +81,8 @@ void DevToolsMHTMLHelper::TemporaryFileCreatedOnIO() { base::TaskShutdownBehavior::BLOCK_SHUTDOWN}) .get()); - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsMHTMLHelper::TemporaryFileCreatedOnUI, this)); } @@ -135,8 +134,8 @@ void DevToolsMHTMLHelper::ReadMHTML() { void DevToolsMHTMLHelper::ReportFailure(const std::string& message) { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsMHTMLHelper::ReportFailure, this, message)); return; } @@ -149,8 +148,8 @@ void DevToolsMHTMLHelper::ReportFailure(const std::string& message) { void DevToolsMHTMLHelper::ReportSuccess( std::unique_ptr<std::string> mhtml_snapshot) { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&DevToolsMHTMLHelper::ReportSuccess, this, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsMHTMLHelper::ReportSuccess, this, std::move(mhtml_snapshot))); return; } diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index c2ae1f64f0b..049c5506f75 100644 --- a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc @@ -16,6 +16,7 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" #include "base/system/sys_info.h" +#include "base/test/scoped_feature_list.h" #include "base/values.h" #include "build/build_config.h" #include "components/download/public/common/download_file_factory.h" @@ -26,6 +27,7 @@ #include "content/browser/download/download_manager_impl.h" #include "content/browser/frame_host/navigator.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" +#include "content/browser/service_worker/embedded_worker_test_helper.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_manager.h" @@ -1995,6 +1997,72 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CertificateExplanations) { explanation_cert->CalculateChainFingerprint256()); } +class DevToolsProtocolBackForwardCacheTest : public DevToolsProtocolTest { + public: + DevToolsProtocolBackForwardCacheTest() { + feature_list_.InitWithFeaturesAndParameters( + {{features::kBackForwardCache, + {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {}); + } + ~DevToolsProtocolBackForwardCacheTest() override = default; + + std::string Evaluate(std::string script, base::Location location) { + std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue()); + params->SetString("expression", script); + SendCommand("Runtime.evaluate", std::move(params), true); + base::Value* result_value; + EXPECT_TRUE(result_->Get("result.value", &result_value)); + DCHECK(result_value->is_string()) + << "Valued to evaluate " << script << " from " << location.ToString(); + return result_value->GetString(); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +// This test checks that the DevTools continue to work when the page is stored +// in and restored from back-forward cache. In particular: +// - that the session continues to be attached and the navigations are handled +// correctly. +// - when the old page is stored in the cache, the messages are still handled by +// the new page. +// - when the page is restored from the cache, it continues to handle protocol +// messages. +IN_PROC_BROWSER_TEST_F(DevToolsProtocolBackForwardCacheTest, Basic) { + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html")); + GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html")); + + // 1) Navigate to A and inject some state. + EXPECT_TRUE(NavigateToURL(shell(), url_a)); + EXPECT_TRUE(ExecJs(shell(), "var state = 'page1'")); + + // 2) Attach DevTools session. + Attach(); + + // 3) Extract the state via the DevTools protocol. + EXPECT_EQ("page1", Evaluate("state", FROM_HERE)); + + // 3) Navigate to B and inject some different state. + EXPECT_TRUE(NavigateToURL(shell(), url_b)); + EXPECT_TRUE(ExecJs(shell(), "var state = 'page2'")); + + // 4) Ensure that the DevTools protocol commands are handled by the new page + // (even though the old page is alive and is stored in the back-forward + // cache). + EXPECT_EQ("page2", Evaluate("state", FROM_HERE)); + + // 5) Go back. + shell()->web_contents()->GetController().GoBack(); + EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); + + // 6) Ensure that the page has been restored from the cache and responds to + // the DevTools commands. + EXPECT_EQ("page1", Evaluate("state", FROM_HERE)); +} + // Download tests are flaky on Android: https://crbug.com/7546 #if !defined(OS_ANDROID) namespace { diff --git a/chromium/content/browser/devtools/protocol/dom_handler.cc b/chromium/content/browser/devtools/protocol/dom_handler.cc index dba7b3a115c..ccc1376efe7 100644 --- a/chromium/content/browser/devtools/protocol/dom_handler.cc +++ b/chromium/content/browser/devtools/protocol/dom_handler.cc @@ -17,8 +17,7 @@ DOMHandler::DOMHandler(bool allow_file_access) host_(nullptr), allow_file_access_(allow_file_access) {} -DOMHandler::~DOMHandler() { -} +DOMHandler::~DOMHandler() = default; void DOMHandler::Wire(UberDispatcher* dispatcher) { DOM::Dispatcher::wire(dispatcher, this); diff --git a/chromium/content/browser/devtools/protocol/emulation_handler.cc b/chromium/content/browser/devtools/protocol/emulation_handler.cc index 470cfa7bd30..0528b6bf0e0 100644 --- a/chromium/content/browser/devtools/protocol/emulation_handler.cc +++ b/chromium/content/browser/devtools/protocol/emulation_handler.cc @@ -74,8 +74,7 @@ EmulationHandler::EmulationHandler() focus_emulation_enabled_(false), host_(nullptr) {} -EmulationHandler::~EmulationHandler() { -} +EmulationHandler::~EmulationHandler() = default; // static std::vector<EmulationHandler*> EmulationHandler::ForAgentHost( @@ -467,13 +466,25 @@ void EmulationHandler::UpdateDeviceEmulationState() { // this is tricky since we'd have to track the DevTools message id with the // WidgetMsg and acknowledgment, as well as plump the acknowledgment back to // the EmulationHandler somehow. Mojo callbacks should make this much simpler. + UpdateDeviceEmulationStateForHost(host_->GetRenderWidgetHost()); + + // Update portals inside this page. + for (auto* web_contents : GetWebContents()->GetWebContentsAndAllInner()) { + if (web_contents->IsPortal()) { + UpdateDeviceEmulationStateForHost( + web_contents->GetMainFrame()->GetRenderWidgetHost()); + } + } +} + +void EmulationHandler::UpdateDeviceEmulationStateForHost( + RenderWidgetHostImpl* render_widget_host) { if (device_emulation_enabled_) { - host_->GetRenderWidgetHost()->Send(new WidgetMsg_EnableDeviceEmulation( - host_->GetRenderWidgetHost()->GetRoutingID(), - device_emulation_params_)); + render_widget_host->Send(new WidgetMsg_EnableDeviceEmulation( + render_widget_host->GetRoutingID(), device_emulation_params_)); } else { - host_->GetRenderWidgetHost()->Send(new WidgetMsg_DisableDeviceEmulation( - host_->GetRenderWidgetHost()->GetRoutingID())); + render_widget_host->Send(new WidgetMsg_DisableDeviceEmulation( + render_widget_host->GetRoutingID())); } } diff --git a/chromium/content/browser/devtools/protocol/emulation_handler.h b/chromium/content/browser/devtools/protocol/emulation_handler.h index 0f1e96586ec..1fc66de4be3 100644 --- a/chromium/content/browser/devtools/protocol/emulation_handler.h +++ b/chromium/content/browser/devtools/protocol/emulation_handler.h @@ -19,6 +19,7 @@ namespace content { class DevToolsAgentHostImpl; class RenderFrameHostImpl; +class RenderWidgetHostImpl; class WebContentsImpl; namespace protocol { @@ -86,6 +87,8 @@ class EmulationHandler : public DevToolsDomainHandler, WebContentsImpl* GetWebContents(); void UpdateTouchEventEmulationState(); void UpdateDeviceEmulationState(); + void UpdateDeviceEmulationStateForHost( + RenderWidgetHostImpl* render_widget_host); bool touch_emulation_enabled_; std::string touch_emulation_configuration_; diff --git a/chromium/content/browser/devtools/protocol/input_handler.cc b/chromium/content/browser/devtools/protocol/input_handler.cc index 2bbaea8f2dd..53d74a4ce3c 100644 --- a/chromium/content/browser/devtools/protocol/input_handler.cc +++ b/chromium/content/browser/devtools/protocol/input_handler.cc @@ -374,6 +374,7 @@ class InputHandler::InputInjector } void InjectKeyboardEvent(const NativeWebKeyboardEvent& keyboard_event, + Maybe<Array<std::string>> commands, std::unique_ptr<DispatchKeyEventCallback> callback) { if (!widget_host_) { callback->sendFailure(Response::InternalError()); @@ -383,7 +384,15 @@ class InputHandler::InputInjector widget_host_->Focus(); input_queued_ = false; pending_key_callbacks_.push_back(std::move(callback)); - widget_host_->ForwardKeyboardEvent(keyboard_event); + ui::LatencyInfo latency; + std::vector<blink::mojom::EditCommandPtr> edit_commands; + if (commands.isJust()) { + for (const std::string& command : *commands.fromJust()) + edit_commands.push_back(blink::mojom::EditCommand::New(command, "")); + } + + widget_host_->ForwardKeyboardEventWithCommands(keyboard_event, latency, + std::move(edit_commands)); if (!input_queued_) { pending_key_callbacks_.back()->sendSuccess(); pending_key_callbacks_.pop_back(); @@ -468,8 +477,7 @@ InputHandler::InputHandler() page_scale_factor_(1.0), last_id_(0) {} -InputHandler::~InputHandler() { -} +InputHandler::~InputHandler() = default; // static std::vector<InputHandler*> InputHandler::ForAgentHost( @@ -538,6 +546,7 @@ void InputHandler::DispatchKeyEvent( Maybe<bool> is_keypad, Maybe<bool> is_system_key, Maybe<int> location, + Maybe<Array<std::string>> commands, std::unique_ptr<DispatchKeyEventCallback> callback) { blink::WebInputEvent::Type web_event_type; @@ -610,7 +619,8 @@ void InputHandler::DispatchKeyEvent( else event.skip_in_browser = true; - EnsureInjector(widget_host)->InjectKeyboardEvent(event, std::move(callback)); + EnsureInjector(widget_host) + ->InjectKeyboardEvent(event, std::move(commands), std::move(callback)); } void InputHandler::InsertText(const std::string& text, diff --git a/chromium/content/browser/devtools/protocol/input_handler.h b/chromium/content/browser/devtools/protocol/input_handler.h index 8abc50f6227..23d569995f2 100644 --- a/chromium/content/browser/devtools/protocol/input_handler.h +++ b/chromium/content/browser/devtools/protocol/input_handler.h @@ -7,8 +7,9 @@ #include <memory> #include <set> +#include <string> +#include <vector> -#include "base/containers/circular_deque.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/containers/unique_ptr_adapters.h" @@ -60,6 +61,7 @@ class InputHandler : public DevToolsDomainHandler, public Input::Backend { Maybe<bool> is_keypad, Maybe<bool> is_system_key, Maybe<int> location, + Maybe<Array<std::string>> commands, std::unique_ptr<DispatchKeyEventCallback> callback) override; void InsertText(const std::string& text, diff --git a/chromium/content/browser/devtools/protocol/inspector_handler.cc b/chromium/content/browser/devtools/protocol/inspector_handler.cc index fe3d7fa6ec5..a50014571da 100644 --- a/chromium/content/browser/devtools/protocol/inspector_handler.cc +++ b/chromium/content/browser/devtools/protocol/inspector_handler.cc @@ -11,12 +11,9 @@ namespace content { namespace protocol { InspectorHandler::InspectorHandler() - : DevToolsDomainHandler(Inspector::Metainfo::domainName), - host_(nullptr) { -} + : DevToolsDomainHandler(Inspector::Metainfo::domainName) {} -InspectorHandler::~InspectorHandler() { -} +InspectorHandler::~InspectorHandler() = default; // static std::vector<InspectorHandler*> InspectorHandler::ForAgentHost( @@ -36,10 +33,14 @@ void InspectorHandler::SetRenderer(int process_host_id, } void InspectorHandler::TargetCrashed() { + target_crashed_ = true; frontend_->TargetCrashed(); } void InspectorHandler::TargetReloadedAfterCrash() { + // Only send the event if targetCrashed was previously sent in this session. + if (!target_crashed_) + return; frontend_->TargetReloadedAfterCrash(); } @@ -49,7 +50,7 @@ void InspectorHandler::TargetDetached(const std::string& reason) { Response InspectorHandler::Enable() { if (host_ && !host_->IsRenderFrameLive()) - frontend_->TargetCrashed(); + TargetCrashed(); return Response::Success(); } diff --git a/chromium/content/browser/devtools/protocol/inspector_handler.h b/chromium/content/browser/devtools/protocol/inspector_handler.h index 19ba4e86034..13858677c06 100644 --- a/chromium/content/browser/devtools/protocol/inspector_handler.h +++ b/chromium/content/browser/devtools/protocol/inspector_handler.h @@ -38,7 +38,8 @@ class InspectorHandler : public DevToolsDomainHandler, private: std::unique_ptr<Inspector::Frontend> frontend_; - RenderFrameHostImpl* host_; + RenderFrameHostImpl* host_ = nullptr; + bool target_crashed_ = false; DISALLOW_COPY_AND_ASSIGN(InspectorHandler); }; diff --git a/chromium/content/browser/devtools/protocol/io_handler.cc b/chromium/content/browser/devtools/protocol/io_handler.cc index 8ec26b2ed7a..c49d8dad673 100644 --- a/chromium/content/browser/devtools/protocol/io_handler.cc +++ b/chromium/content/browser/devtools/protocol/io_handler.cc @@ -29,7 +29,7 @@ IOHandler::IOHandler(DevToolsIOContext* io_context) browser_context_(nullptr), storage_partition_(nullptr) {} -IOHandler::~IOHandler() {} +IOHandler::~IOHandler() = default; void IOHandler::Wire(UberDispatcher* dispatcher) { frontend_.reset(new IO::Frontend(dispatcher->channel())); diff --git a/chromium/content/browser/devtools/protocol/log_handler.cc b/chromium/content/browser/devtools/protocol/log_handler.cc index 4fca4ddf95d..67dc75c7b93 100644 --- a/chromium/content/browser/devtools/protocol/log_handler.cc +++ b/chromium/content/browser/devtools/protocol/log_handler.cc @@ -32,11 +32,11 @@ DispatchResponse LogHandler::Enable() { return Response::FallThrough(); } -void LogHandler::EntryAdded(std::unique_ptr<Log::LogEntry> entry) { +void LogHandler::EntryAdded(Log::LogEntry* entry) { if (!enabled_) { return; } - frontend_->EntryAdded(std::move(entry)); + frontend_->EntryAdded(entry->clone()); } } // namespace protocol diff --git a/chromium/content/browser/devtools/protocol/log_handler.h b/chromium/content/browser/devtools/protocol/log_handler.h index 45b54550e1b..96a1d712734 100644 --- a/chromium/content/browser/devtools/protocol/log_handler.h +++ b/chromium/content/browser/devtools/protocol/log_handler.h @@ -31,7 +31,7 @@ class LogHandler final : public DevToolsDomainHandler, public Log::Backend { DispatchResponse Disable() override; DispatchResponse Enable() override; - void EntryAdded(std::unique_ptr<Log::LogEntry> entry); + void EntryAdded(Log::LogEntry* entry); private: std::unique_ptr<Log::Frontend> frontend_; diff --git a/chromium/content/browser/devtools/protocol/memory_handler.cc b/chromium/content/browser/devtools/protocol/memory_handler.cc index bdec2689ec8..af4525c8192 100644 --- a/chromium/content/browser/devtools/protocol/memory_handler.cc +++ b/chromium/content/browser/devtools/protocol/memory_handler.cc @@ -21,7 +21,7 @@ MemoryHandler::MemoryHandler() : DevToolsDomainHandler(Memory::Metainfo::domainName), process_host_id_(ChildProcessHost::kInvalidUniqueID) {} -MemoryHandler::~MemoryHandler() {} +MemoryHandler::~MemoryHandler() = default; void MemoryHandler::Wire(UberDispatcher* dispatcher) { Memory::Dispatcher::wire(dispatcher, this); diff --git a/chromium/content/browser/devtools/protocol/network_handler.cc b/chromium/content/browser/devtools/protocol/network_handler.cc index 4b900c1f83a..a8bcb0eb483 100644 --- a/chromium/content/browser/devtools/protocol/network_handler.cc +++ b/chromium/content/browser/devtools/protocol/network_handler.cc @@ -64,6 +64,7 @@ #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" #include "net/cookies/canonical_cookie.h" +#include "net/cookies/cookie_inclusion_status.h" #include "net/cookies/cookie_util.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" @@ -181,10 +182,10 @@ class CookieRetrieverNetworkService CookieRetrieverNetworkService(std::unique_ptr<GetCookiesCallback> callback) : callback_(std::move(callback)) {} - void GotCookies(const net::CookieStatusList& cookies, - const net::CookieStatusList& excluded_cookies) { - for (const auto& cookie_with_status : cookies) { - const net::CanonicalCookie& cookie = cookie_with_status.cookie; + void GotCookies(const net::CookieAccessResultList& cookies, + const net::CookieAccessResultList& excluded_cookies) { + for (const auto& cookie_with_access_result : cookies) { + const net::CanonicalCookie& cookie = cookie_with_access_result.cookie; std::string key = base::StringPrintf( "%s::%s::%s::%d", cookie.Name().c_str(), cookie.Domain().c_str(), cookie.Path().c_str(), cookie.IsSecure()); @@ -440,6 +441,11 @@ std::unique_ptr<Network::ResourceTiming> GetTiming( load_timing.request_start)) .SetWorkerStart(-1) .SetWorkerReady(-1) + .SetWorkerFetchStart(timeDelta(load_timing.service_worker_fetch_start, + load_timing.request_start)) + .SetWorkerRespondWithSettled( + timeDelta(load_timing.service_worker_respond_with_settled, + load_timing.request_start)) .SetSendStart( timeDelta(load_timing.send_start, load_timing.request_start)) .SetSendEnd(timeDelta(load_timing.send_end, load_timing.request_start)) @@ -543,65 +549,64 @@ std::unique_ptr<Array<Network::SignedExchangeError>> BuildSignedExchangeErrors( } std::unique_ptr<Array<Network::SetCookieBlockedReason>> -GetProtocolBlockedSetCookieReason( - net::CanonicalCookie::CookieInclusionStatus status) { +GetProtocolBlockedSetCookieReason(net::CookieInclusionStatus status) { std::unique_ptr<Array<Network::SetCookieBlockedReason>> blockedReasons = std::make_unique<Array<Network::SetCookieBlockedReason>>(); if (status.HasExclusionReason( - net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY)) { + net::CookieInclusionStatus::EXCLUDE_SECURE_ONLY)) { blockedReasons->push_back(Network::SetCookieBlockedReasonEnum::SecureOnly); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_SAMESITE_STRICT)) { + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)) { blockedReasons->push_back( Network::SetCookieBlockedReasonEnum::SameSiteStrict); } if (status.HasExclusionReason( - net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)) { + net::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)) { blockedReasons->push_back(Network::SetCookieBlockedReasonEnum::SameSiteLax); } if (status.HasExclusionReason( - net::CanonicalCookie::CookieInclusionStatus:: + net::CookieInclusionStatus:: EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX)) { blockedReasons->push_back( Network::SetCookieBlockedReasonEnum::SameSiteUnspecifiedTreatedAsLax); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_SAMESITE_NONE_INSECURE)) { + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE)) { blockedReasons->push_back( Network::SetCookieBlockedReasonEnum::SameSiteNoneInsecure); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES)) { + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES)) { blockedReasons->push_back( Network::SetCookieBlockedReasonEnum::UserPreferences); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_FAILURE_TO_STORE)) { + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE)) { blockedReasons->push_back(Network::SetCookieBlockedReasonEnum::SyntaxError); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_NONCOOKIEABLE_SCHEME)) { + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME)) { blockedReasons->push_back( Network::SetCookieBlockedReasonEnum::SchemeNotSupported); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_OVERWRITE_SECURE)) { + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE)) { blockedReasons->push_back( Network::SetCookieBlockedReasonEnum::OverwriteSecure); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_INVALID_DOMAIN)) { + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN)) { blockedReasons->push_back( Network::SetCookieBlockedReasonEnum::InvalidDomain); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_INVALID_PREFIX)) { + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX)) { blockedReasons->push_back( Network::SetCookieBlockedReasonEnum::InvalidPrefix); } if (status.HasExclusionReason( - net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR)) { + net::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR)) { blockedReasons->push_back( Network::SetCookieBlockedReasonEnum::UnknownError); } @@ -610,49 +615,48 @@ GetProtocolBlockedSetCookieReason( } std::unique_ptr<Array<Network::CookieBlockedReason>> -GetProtocolBlockedCookieReason( - net::CanonicalCookie::CookieInclusionStatus status) { +GetProtocolBlockedCookieReason(net::CookieInclusionStatus status) { std::unique_ptr<Array<Network::CookieBlockedReason>> blockedReasons = std::make_unique<Array<Network::CookieBlockedReason>>(); if (status.HasExclusionReason( - net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY)) { + net::CookieInclusionStatus::EXCLUDE_SECURE_ONLY)) { blockedReasons->push_back(Network::CookieBlockedReasonEnum::SecureOnly); } if (status.HasExclusionReason( - net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH)) { + net::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH)) { blockedReasons->push_back(Network::CookieBlockedReasonEnum::NotOnPath); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_DOMAIN_MISMATCH)) { + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH)) { blockedReasons->push_back(Network::CookieBlockedReasonEnum::DomainMismatch); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_SAMESITE_STRICT)) { + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)) { blockedReasons->push_back(Network::CookieBlockedReasonEnum::SameSiteStrict); } if (status.HasExclusionReason( - net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)) { + net::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)) { blockedReasons->push_back(Network::CookieBlockedReasonEnum::SameSiteLax); } if (status.HasExclusionReason( - net::CanonicalCookie::CookieInclusionStatus:: + net::CookieInclusionStatus:: EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX)) { blockedReasons->push_back( Network::CookieBlockedReasonEnum::SameSiteUnspecifiedTreatedAsLax); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_SAMESITE_NONE_INSECURE)) { + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE)) { blockedReasons->push_back( Network::CookieBlockedReasonEnum::SameSiteNoneInsecure); } - if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus:: - EXCLUDE_USER_PREFERENCES)) { + if (status.HasExclusionReason( + net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES)) { blockedReasons->push_back( Network::CookieBlockedReasonEnum::UserPreferences); } if (status.HasExclusionReason( - net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR)) { + net::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR)) { blockedReasons->push_back(Network::CookieBlockedReasonEnum::UnknownError); } @@ -683,16 +687,16 @@ BuildProtocolBlockedSetCookies(const net::CookieAndLineStatusList& net_list) { } std::unique_ptr<Array<Network::BlockedCookieWithReason>> -BuildProtocolAssociatedCookies(const net::CookieStatusList& net_list) { +BuildProtocolAssociatedCookies(const net::CookieAccessResultList& net_list) { auto protocol_list = std::make_unique<Array<Network::BlockedCookieWithReason>>(); - for (const net::CookieWithStatus& cookie : net_list) { + for (const net::CookieWithAccessResult& cookie : net_list) { std::unique_ptr<Array<Network::CookieBlockedReason>> blocked_reasons = - GetProtocolBlockedCookieReason(cookie.status); + GetProtocolBlockedCookieReason(cookie.access_result.status); // Note that the condition below is not always true, // as there might be blocked reasons that we do not report. - if (blocked_reasons->size() || cookie.status.IsInclude()) { + if (blocked_reasons->size() || cookie.access_result.status.IsInclude()) { protocol_list->push_back( Network::BlockedCookieWithReason::Create() .SetBlockedReasons(std::move(blocked_reasons)) @@ -814,8 +818,7 @@ NetworkHandler::NetworkHandler( have_configured_service_worker_context = true; } -NetworkHandler::~NetworkHandler() { -} +NetworkHandler::~NetworkHandler() = default; // static std::unique_ptr<Array<Network::Cookie>> NetworkHandler::BuildCookieArray( @@ -1212,10 +1215,9 @@ void NetworkHandler::SetCookies( cookie_manager->SetCanonicalCookie( *cookie, net::cookie_util::SimulatedCookieSource(*cookie, "https"), options, - base::BindOnce( - [](base::RepeatingClosure callback, - net::CanonicalCookie::CookieInclusionStatus) { callback.Run(); }, - barrier_closure)); + base::BindOnce([](base::RepeatingClosure callback, + net::CookieInclusionStatus) { callback.Run(); }, + barrier_closure)); } } @@ -1433,6 +1435,20 @@ std::unique_ptr<protocol::Object> BuildResponseHeaders( return std::make_unique<protocol::Object>(std::move(headers_dict)); } +String BuildServiceWorkerResponseSource( + const network::mojom::URLResponseHead& info) { + switch (info.service_worker_response_source) { + case network::mojom::FetchResponseSource::kCacheStorage: + return protocol::Network::ServiceWorkerResponseSourceEnum::CacheStorage; + case network::mojom::FetchResponseSource::kHttpCache: + return protocol::Network::ServiceWorkerResponseSourceEnum::HttpCache; + case network::mojom::FetchResponseSource::kNetwork: + return protocol::Network::ServiceWorkerResponseSourceEnum::Network; + case network::mojom::FetchResponseSource::kUnspecified: + return protocol::Network::ServiceWorkerResponseSourceEnum::FallbackCode; + } +} + std::unique_ptr<Network::Response> BuildResponse( const GURL& url, const network::mojom::URLResponseHead& info) { @@ -1464,7 +1480,18 @@ std::unique_ptr<Network::Response> BuildResponse( info.load_timing.request_start_time) .Build(); response->SetFromServiceWorker(info.was_fetched_via_service_worker); + if (info.was_fetched_via_service_worker) { + response->SetServiceWorkerResponseSource( + BuildServiceWorkerResponseSource(info)); + } response->SetFromPrefetchCache(info.was_in_prefetch_cache); + if (!info.response_time.is_null()) { + response->SetResponseTime(info.response_time.ToJsTimeIgnoringNull()); + } + if (!info.cache_storage_cache_name.empty()) { + response->SetCacheStorageCacheName(info.cache_storage_cache_name); + } + auto* raw_info = info.raw_request_response_info.get(); if (raw_info) { if (raw_info->http_status_code) { @@ -2095,7 +2122,7 @@ void NetworkHandler::SetNetworkConditions( void NetworkHandler::OnRequestWillBeSentExtraInfo( const std::string& devtools_request_id, - const net::CookieStatusList& request_cookie_list, + const net::CookieAccessResultList& request_cookie_list, const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers) { if (!enabled_) return; diff --git a/chromium/content/browser/devtools/protocol/network_handler.h b/chromium/content/browser/devtools/protocol/network_handler.h index 52b3c3421a2..e5f15a7a7b2 100644 --- a/chromium/content/browser/devtools/protocol/network_handler.h +++ b/chromium/content/browser/devtools/protocol/network_handler.h @@ -198,7 +198,7 @@ class NetworkHandler : public DevToolsDomainHandler, void OnRequestWillBeSentExtraInfo( const std::string& devtools_request_id, - const net::CookieStatusList& request_cookie_list, + const net::CookieAccessResultList& request_cookie_list, const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers); void OnResponseReceivedExtraInfo( const std::string& devtools_request_id, diff --git a/chromium/content/browser/devtools/protocol/page_handler.cc b/chromium/content/browser/devtools/protocol/page_handler.cc index b1821434b97..630de0dd016 100644 --- a/chromium/content/browser/devtools/protocol/page_handler.cc +++ b/chromium/content/browser/devtools/protocol/page_handler.cc @@ -158,24 +158,12 @@ void GetMetadataFromFrame(const media::VideoFrame& frame, double* page_scale_factor, gfx::Vector2dF* root_scroll_offset, double* top_controls_visible_height) { - // Get metadata from |frame| and ensure that no metadata is missing. - bool success = true; - double root_scroll_offset_x, root_scroll_offset_y; - success &= frame.metadata()->GetDouble( - media::VideoFrameMetadata::DEVICE_SCALE_FACTOR, device_scale_factor); - success &= frame.metadata()->GetDouble( - media::VideoFrameMetadata::PAGE_SCALE_FACTOR, page_scale_factor); - success &= frame.metadata()->GetDouble( - media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_X, &root_scroll_offset_x); - success &= frame.metadata()->GetDouble( - media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_Y, &root_scroll_offset_y); - success &= frame.metadata()->GetDouble( - media::VideoFrameMetadata::TOP_CONTROLS_VISIBLE_HEIGHT, - top_controls_visible_height); - DCHECK(success); - - root_scroll_offset->set_x(root_scroll_offset_x); - root_scroll_offset->set_y(root_scroll_offset_y); + // Get metadata from |frame|. This will CHECK if metadata is missing. + *device_scale_factor = *frame.metadata()->device_scale_factor; + *page_scale_factor = *frame.metadata()->page_scale_factor; + root_scroll_offset->set_x(*frame.metadata()->root_scroll_offset_x); + root_scroll_offset->set_y(*frame.metadata()->root_scroll_offset_y); + *top_controls_visible_height = *frame.metadata()->top_controls_visible_height; } } // namespace @@ -338,8 +326,6 @@ void PageHandler::DidCloseJavaScriptDialog(bool success, Response PageHandler::Enable() { enabled_ = true; - if (GetWebContents() && GetWebContents()->ShowingInterstitialPage()) - frontend_->InterstitialShown(); return Response::FallThrough(); } @@ -510,7 +496,7 @@ void PageHandler::Navigate(const std::string& url, params.referrer = Referrer(GURL(referrer.fromMaybe("")), policy); params.transition_type = type; params.frame_tree_node_id = frame_tree_node->frame_tree_node_id(); - frame_tree_node->navigator()->GetController()->LoadURLWithParams(params); + frame_tree_node->navigator().GetController()->LoadURLWithParams(params); base::UnguessableToken frame_token = frame_tree_node->devtools_frame_token(); auto navigate_callback = navigate_callbacks_.find(frame_token); @@ -892,8 +878,7 @@ Response PageHandler::StartScreencast(Maybe<std::string> format, if (frame_metadata_) { InnerSwapCompositorFrame(); } else { - widget_host->Send( - new WidgetMsg_ForceRedraw(widget_host->GetRoutingID(), 0)); + widget_host->RequestForceRedraw(0); } return Response::FallThrough(); } diff --git a/chromium/content/browser/devtools/protocol/schema_handler.cc b/chromium/content/browser/devtools/protocol/schema_handler.cc index cc2210423a3..b09155489c3 100644 --- a/chromium/content/browser/devtools/protocol/schema_handler.cc +++ b/chromium/content/browser/devtools/protocol/schema_handler.cc @@ -13,8 +13,7 @@ SchemaHandler::SchemaHandler() : DevToolsDomainHandler(Schema::Metainfo::domainName) { } -SchemaHandler::~SchemaHandler() { -} +SchemaHandler::~SchemaHandler() = default; void SchemaHandler::Wire(UberDispatcher* dispatcher) { Schema::Dispatcher::wire(dispatcher, this); diff --git a/chromium/content/browser/devtools/protocol/security_handler.cc b/chromium/content/browser/devtools/protocol/security_handler.cc index 51bbd3f9e93..9504ebcb4c7 100644 --- a/chromium/content/browser/devtools/protocol/security_handler.cc +++ b/chromium/content/browser/devtools/protocol/security_handler.cc @@ -120,8 +120,7 @@ SecurityHandler::SecurityHandler() host_(nullptr) { } -SecurityHandler::~SecurityHandler() { -} +SecurityHandler::~SecurityHandler() = default; void SecurityHandler::Wire(UberDispatcher* dispatcher) { frontend_.reset(new Security::Frontend(dispatcher->channel())); diff --git a/chromium/content/browser/devtools/protocol/service_worker_handler.cc b/chromium/content/browser/devtools/protocol/service_worker_handler.cc index f370116a67b..7b3e63127d0 100644 --- a/chromium/content/browser/devtools/protocol/service_worker_handler.cc +++ b/chromium/content/browser/devtools/protocol/service_worker_handler.cc @@ -185,8 +185,7 @@ ServiceWorkerHandler::ServiceWorkerHandler(bool allow_inspect_worker) browser_context_(nullptr), storage_partition_(nullptr) {} -ServiceWorkerHandler::~ServiceWorkerHandler() { -} +ServiceWorkerHandler::~ServiceWorkerHandler() = default; void ServiceWorkerHandler::Wire(UberDispatcher* dispatcher) { frontend_.reset(new ServiceWorker::Frontend(dispatcher->channel())); @@ -438,10 +437,10 @@ void ServiceWorkerHandler::OnWorkerVersionUpdated( base::flat_set<std::string> client_set; for (const auto& client : version.clients) { - if (client.second.type == + if (client.second.type() == blink::mojom::ServiceWorkerClientType::kWindow) { - WebContents* web_contents = - WebContents::FromFrameTreeNodeId(client.second.frame_tree_node_id); + WebContents* web_contents = WebContents::FromFrameTreeNodeId( + client.second.GetFrameTreeNodeId()); // There is a possibility that the frame is already deleted // because of the thread hopping. if (!web_contents) diff --git a/chromium/content/browser/devtools/protocol/storage_handler.cc b/chromium/content/browser/devtools/protocol/storage_handler.cc index 4d888297933..09be27dbb1e 100644 --- a/chromium/content/browser/devtools/protocol/storage_handler.cc +++ b/chromium/content/browser/devtools/protocol/storage_handler.cc @@ -12,7 +12,6 @@ #include "base/bind.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" -#include "base/task/post_task.h" #include "content/browser/cache_storage/cache_storage_context_impl.h" #include "content/browser/devtools/protocol/browser_handler.h" #include "content/browser/devtools/protocol/network.h" @@ -91,8 +90,8 @@ void GotUsageAndQuotaDataCallback( int64_t quota, blink::mojom::UsageBreakdownPtr usage_breakdown) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(ReportUsageAndQuotaDataOnUIThread, std::move(callback), code, usage, quota, std::move(usage_breakdown))); } @@ -391,8 +390,8 @@ void StorageHandler::GetUsageAndQuota( } storage::QuotaManager* manager = storage_partition_->GetQuotaManager(); - base::PostTask( - FROM_HERE, {BrowserThread::IO}, + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&GetUsageAndQuotaOnIOThread, base::RetainedRef(manager), url::Origin::Create(origin_url), std::move(callback))); } diff --git a/chromium/content/browser/devtools/protocol/system_info_handler.cc b/chromium/content/browser/devtools/protocol/system_info_handler.cc index 98d0e9cf218..58256d84a27 100644 --- a/chromium/content/browser/devtools/protocol/system_info_handler.cc +++ b/chromium/content/browser/devtools/protocol/system_info_handler.cc @@ -12,7 +12,6 @@ #include "base/command_line.h" #include "base/process/process_metrics.h" #include "base/strings/utf_string_conversions.h" -#include "base/task/post_task.h" #include "build/build_config.h" #include "content/browser/gpu/compositor_util.h" #include "content/browser/gpu/gpu_data_manager_impl.h" @@ -107,10 +106,6 @@ class AuxGPUInfoEnumerator : public gpu::GPUInfo::Enumerator { void EndImageDecodeAcceleratorSupportedProfile() override {} - void BeginDx12VulkanVersionInfo() override {} - - void EndDx12VulkanVersionInfo() override {} - void BeginOverlayInfo() override {} void EndOverlayInfo() override {} @@ -291,8 +286,8 @@ class SystemInfoHandlerGpuObserver : public content::GpuDataManagerObserver { explicit SystemInfoHandlerGpuObserver( std::unique_ptr<GetInfoCallback> callback) : callback_(std::move(callback)) { - base::PostDelayedTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostDelayedTask( + FROM_HERE, base::BindOnce(&SystemInfoHandlerGpuObserver::ObserverWatchdogCallback, weak_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(kGPUInfoWatchdogTimeoutMs)); @@ -339,8 +334,7 @@ SystemInfoHandler::SystemInfoHandler() : DevToolsDomainHandler(SystemInfo::Metainfo::domainName) { } -SystemInfoHandler::~SystemInfoHandler() { -} +SystemInfoHandler::~SystemInfoHandler() = default; void SystemInfoHandler::Wire(UberDispatcher* dispatcher) { SystemInfo::Dispatcher::wire(dispatcher, this); @@ -431,9 +425,8 @@ void SystemInfoHandler::GetProcessInfo( AddRendererProcessInfo(process_info.get()); // Collect child processes info on the IO thread. - base::PostTaskAndReplyWithResult( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&AddChildProcessInfo, std::move(process_info)), + GetIOThreadTaskRunner({})->PostTaskAndReplyWithResult( + FROM_HERE, base::BindOnce(&AddChildProcessInfo, std::move(process_info)), base::BindOnce(&GetProcessInfoCallback::sendSuccess, std::move(callback))); } diff --git a/chromium/content/browser/devtools/protocol/target_auto_attacher.cc b/chromium/content/browser/devtools/protocol/target_auto_attacher.cc index 3665d4ad309..666548fd8b0 100644 --- a/chromium/content/browser/devtools/protocol/target_auto_attacher.cc +++ b/chromium/content/browser/devtools/protocol/target_auto_attacher.cc @@ -94,17 +94,17 @@ base::flat_set<GURL> GetFrameUrls(RenderFrameHostImpl* render_frame_host) { // (from WorkerCreated). See also https://crbug.com/907072 // // We are not attaching in the following case: - // 4. Frame is trying to navigate and we _should_ pick up an existing SW but we don't. - // We _could_ do this, but since we are not pausing the navigation, there - // is no principal difference between picking up SW earlier or later. + // 4. Frame is trying to navigate and we _should_ pick up an existing SW but + // we don't. We _could_ do this, but since we are not pausing the + // navigation, there is no principal difference between picking up SW + // earlier or later. // // We also try to detach from SW picked up for [3] if navigation has failed // (from DidFinishNavigation). base::flat_set<GURL> frame_urls; if (render_frame_host) { - for (FrameTreeNode* node : - render_frame_host->frame_tree_node()->frame_tree()->Nodes()) { + for (FrameTreeNode* node : render_frame_host->frame_tree()->Nodes()) { frame_urls.insert(node->current_url()); // We use both old and new frame urls to support [3], where we attach while // navigation is still ongoing. @@ -127,7 +127,7 @@ TargetAutoAttacher::TargetAutoAttacher( auto_attach_(false), wait_for_debugger_on_start_(false) {} -TargetAutoAttacher::~TargetAutoAttacher() {} +TargetAutoAttacher::~TargetAutoAttacher() = default; void TargetAutoAttacher::SetRenderFrameHost( RenderFrameHostImpl* render_frame_host) { @@ -362,16 +362,6 @@ void TargetAutoAttacher::WorkerCreated(ServiceWorkerDevToolsAgentHost* host, } } -void TargetAutoAttacher::WorkerVersionInstalled( - ServiceWorkerDevToolsAgentHost* host) { - ReattachServiceWorkers(false); -} - -void TargetAutoAttacher::WorkerVersionDoomed( - ServiceWorkerDevToolsAgentHost* host) { - ReattachServiceWorkers(false); -} - void TargetAutoAttacher::WorkerDestroyed(ServiceWorkerDevToolsAgentHost* host) { if (is_browser_mode()) { auto_attached_hosts_.erase(base::WrapRefCounted(host)); diff --git a/chromium/content/browser/devtools/protocol/target_auto_attacher.h b/chromium/content/browser/devtools/protocol/target_auto_attacher.h index 181819cf592..96e72cc13b7 100644 --- a/chromium/content/browser/devtools/protocol/target_auto_attacher.h +++ b/chromium/content/browser/devtools/protocol/target_auto_attacher.h @@ -60,8 +60,6 @@ class TargetAutoAttacher : public ServiceWorkerDevToolsManager::Observer { // ServiceWorkerDevToolsManager::Observer implementation. void WorkerCreated(ServiceWorkerDevToolsAgentHost* host, bool* should_pause_on_start) override; - void WorkerVersionInstalled(ServiceWorkerDevToolsAgentHost* host) override; - void WorkerVersionDoomed(ServiceWorkerDevToolsAgentHost* host) override; void WorkerDestroyed(ServiceWorkerDevToolsAgentHost* host) override; void UpdateFrames(); diff --git a/chromium/content/browser/devtools/protocol/target_handler.cc b/chromium/content/browser/devtools/protocol/target_handler.cc index 4614ecae211..dda5c814235 100644 --- a/chromium/content/browser/devtools/protocol/target_handler.cc +++ b/chromium/content/browser/devtools/protocol/target_handler.cc @@ -30,6 +30,35 @@ namespace protocol { namespace { +constexpr net::NetworkTrafficAnnotationTag + kSettingsProxyConfigTrafficAnnotation = + net::DefineNetworkTrafficAnnotation("devtools_proxy_config", R"( + semantics { + sender: "Proxy Configuration over Developer Tools" + description: + "Used to fetch HTTP/HTTPS/SOCKS5/PAC proxy configuration when " + "proxy is configured by DevTools. It is equivalent to the one " + "configured via the --proxy-server command line flag. " + "When proxy implies automatic configuration, it can send network " + "requests in the scope of this annotation." + trigger: + "Whenever a network request is made when the system proxy settings " + "are used, and they indicate to use a proxy server." + data: + "Proxy configuration." + destination: OTHER + destination_other: "The proxy server specified in the configuration." + } + policy { + cookies_allowed: NO + setting: + "This request cannot be disabled in settings. However it will never " + "be made if user does not run with '--remote-debugging-*' switches " + "and does not explicitly send this data over Chrome remote debugging." + policy_exception_justification: + "Not implemented, only used in DevTools and is behind a switch." + })"); + static const char kNotAllowedError[] = "Not allowed"; static const char kMethod[] = "method"; static const char kResumeMethod[] = "Runtime.runIfWaitingForDebugger"; @@ -436,7 +465,7 @@ class TargetHandler::Session : public DevToolsAgentHostClient { // was introduced. Try a DCHECK instead and possibly remove the check. if (!handler_->root_session_->HasChildSession(id_)) return; - handler_->root_session_->GetClient()->DispatchProtocolMessage( + GetRootClient()->DispatchProtocolMessage( handler_->root_session_->GetAgentHost(), message); return; } @@ -454,6 +483,26 @@ class TargetHandler::Session : public DevToolsAgentHostClient { Detach(true); } + bool MayAttachToURL(const GURL& url, bool is_webui) override { + return GetRootClient()->MayAttachToURL(url, is_webui); + } + + bool MayAttachToBrowser() override { + return GetRootClient()->MayAttachToBrowser(); + } + + bool MayReadLocalFiles() override { + return GetRootClient()->MayReadLocalFiles(); + } + + bool MayWriteLocalFiles() override { + return GetRootClient()->MayWriteLocalFiles(); + } + + content::DevToolsAgentHostClient* GetRootClient() { + return handler_->root_session_->GetClient(); + } + TargetHandler* handler_; scoped_refptr<DevToolsAgentHost> agent_host_; std::string id_; @@ -520,8 +569,7 @@ TargetHandler::TargetHandler(AccessMode access_mode, owner_target_id_(owner_target_id), root_session_(root_session) {} -TargetHandler::~TargetHandler() { -} +TargetHandler::~TargetHandler() = default; // static std::vector<TargetHandler*> TargetHandler::ForAgentHost( @@ -560,6 +608,7 @@ Response TargetHandler::Disable() { } dispose_on_detach_context_ids_.clear(); } + contexts_with_overridden_proxy_.clear(); return Response::Success(); } @@ -948,23 +997,50 @@ void TargetHandler::DevToolsAgentHostCrashed(DevToolsAgentHost* host, // ----------------- More protocol methods ------------------- -protocol::Response TargetHandler::CreateBrowserContext( - Maybe<bool> dispose_on_detach, - std::string* out_context_id) { - if (access_mode_ != AccessMode::kBrowser) - return Response::ServerError(kNotAllowedError); +void TargetHandler::CreateBrowserContext( + Maybe<bool> in_disposeOnDetach, + Maybe<String> in_proxyServer, + Maybe<String> in_proxyBypassList, + std::unique_ptr<CreateBrowserContextCallback> callback) { + if (access_mode_ != AccessMode::kBrowser) { + callback->sendFailure(Response::ServerError(kNotAllowedError)); + return; + } DevToolsManagerDelegate* delegate = DevToolsManager::GetInstance()->delegate(); - if (!delegate) - return Response::ServerError( - "Browser context management is not supported."); + if (!delegate) { + callback->sendFailure( + Response::ServerError("Browser context management is not supported.")); + return; + } + + if (in_proxyServer.isJust()) { + pending_proxy_config_ = net::ProxyConfig(); + pending_proxy_config_->proxy_rules().ParseFromString( + in_proxyServer.fromJust()); + if (in_proxyBypassList.isJust()) { + pending_proxy_config_->proxy_rules().bypass_rules.ParseFromString( + in_proxyBypassList.fromJust()); + } + } + BrowserContext* context = delegate->CreateBrowserContext(); - if (!context) - return Response::ServerError("Failed to create browser context."); - *out_context_id = context->UniqueId(); - if (dispose_on_detach.fromMaybe(false)) - dispose_on_detach_context_ids_.insert(*out_context_id); - return Response::Success(); + if (!context) { + callback->sendFailure( + Response::ServerError("Failed to create browser context.")); + pending_proxy_config_.reset(); + return; + } + + if (pending_proxy_config_) { + contexts_with_overridden_proxy_[context->UniqueId()] = + std::move(*pending_proxy_config_); + pending_proxy_config_.reset(); + } + + if (in_disposeOnDetach.fromMaybe(false)) + dispose_on_detach_context_ids_.insert(context->UniqueId()); + callback->sendSuccess(context->UniqueId()); } protocol::Response TargetHandler::GetBrowserContexts( @@ -1024,5 +1100,25 @@ void TargetHandler::DisposeBrowserContext( std::move(callback))); } +void TargetHandler::ApplyNetworkContextParamsOverrides( + BrowserContext* browser_context, + network::mojom::NetworkContextParams* context_params) { + // Under certain conditions, storage partition is created synchronously for + // the browser context. Account for this use case. + if (pending_proxy_config_) { + context_params->initial_proxy_config = + net::ProxyConfigWithAnnotation(std::move(*pending_proxy_config_), + kSettingsProxyConfigTrafficAnnotation); + pending_proxy_config_.reset(); + return; + } + auto it = contexts_with_overridden_proxy_.find(browser_context->UniqueId()); + if (it != contexts_with_overridden_proxy_.end()) { + context_params->initial_proxy_config = net::ProxyConfigWithAnnotation( + std::move(it->second), kSettingsProxyConfigTrafficAnnotation); + contexts_with_overridden_proxy_.erase(browser_context->UniqueId()); + } +} + } // namespace protocol } // namespace content diff --git a/chromium/content/browser/devtools/protocol/target_handler.h b/chromium/content/browser/devtools/protocol/target_handler.h index e410f6d96ca..83437c80f24 100644 --- a/chromium/content/browser/devtools/protocol/target_handler.h +++ b/chromium/content/browser/devtools/protocol/target_handler.h @@ -8,12 +8,15 @@ #include <map> #include <set> +#include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/memory/weak_ptr.h" #include "content/browser/devtools/protocol/devtools_domain_handler.h" #include "content/browser/devtools/protocol/target.h" #include "content/browser/devtools/protocol/target_auto_attacher.h" #include "content/public/browser/devtools_agent_host_observer.h" +#include "net/proxy_resolution/proxy_config.h" +#include "services/network/public/mojom/network_context.mojom.h" namespace content { @@ -85,8 +88,11 @@ class TargetHandler : public DevToolsDomainHandler, bool* out_success) override; Response ExposeDevToolsProtocol(const std::string& target_id, Maybe<std::string> binding_name) override; - Response CreateBrowserContext(Maybe<bool> dispose_on_detach, - std::string* out_context_id) override; + void CreateBrowserContext( + Maybe<bool> in_disposeOnDetach, + Maybe<String> in_proxyServer, + Maybe<String> in_proxyBypassList, + std::unique_ptr<CreateBrowserContextCallback> callback) override; void DisposeBrowserContext( const std::string& context_id, std::unique_ptr<DisposeBrowserContextCallback> callback) override; @@ -104,6 +110,10 @@ class TargetHandler : public DevToolsDomainHandler, std::unique_ptr<protocol::Array<Target::TargetInfo>>* target_infos) override; + void ApplyNetworkContextParamsOverrides( + BrowserContext* browser_context, + network::mojom::NetworkContextParams* network_context_params); + private: class Session; class Throttle; @@ -143,10 +153,12 @@ class TargetHandler : public DevToolsDomainHandler, std::map<DevToolsAgentHost*, Session*> auto_attached_sessions_; std::set<DevToolsAgentHost*> reported_hosts_; base::flat_set<std::string> dispose_on_detach_context_ids_; + base::flat_map<std::string, net::ProxyConfig> contexts_with_overridden_proxy_; AccessMode access_mode_; std::string owner_target_id_; DevToolsSession* root_session_; base::flat_set<Throttle*> throttles_; + base::Optional<net::ProxyConfig> pending_proxy_config_; base::WeakPtrFactory<TargetHandler> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(TargetHandler); diff --git a/chromium/content/browser/devtools/protocol/tethering_handler.cc b/chromium/content/browser/devtools/protocol/tethering_handler.cc index 84e16553bfa..315b645ab79 100644 --- a/chromium/content/browser/devtools/protocol/tethering_handler.cc +++ b/chromium/content/browser/devtools/protocol/tethering_handler.cc @@ -7,7 +7,6 @@ #include <map> #include "base/bind.h" -#include "base/task/post_task.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "net/base/io_buffer.h" @@ -288,8 +287,8 @@ TetheringHandler::TetheringImpl::~TetheringImpl() = default; void TetheringHandler::TetheringImpl::Bind( uint16_t port, std::unique_ptr<BindCallback> callback) { if (bound_sockets_.find(port) != bound_sockets_.end()) { - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&BindCallback::sendFailure, std::move(callback), Response::ServerError("Port already bound"))); return; @@ -300,16 +299,16 @@ void TetheringHandler::TetheringImpl::Bind( std::unique_ptr<BoundSocket> bound_socket = std::make_unique<BoundSocket>( std::move(accepted_callback), socket_callback_); if (!bound_socket->Listen(port)) { - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&BindCallback::sendFailure, std::move(callback), Response::ServerError("Could not bind port"))); return; } bound_sockets_[port] = std::move(bound_socket); - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&BindCallback::sendSuccess, std::move(callback))); } @@ -317,23 +316,23 @@ void TetheringHandler::TetheringImpl::Unbind( uint16_t port, std::unique_ptr<UnbindCallback> callback) { auto it = bound_sockets_.find(port); if (it == bound_sockets_.end()) { - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&UnbindCallback::sendFailure, std::move(callback), Response::InvalidParams("Port is not bound"))); return; } bound_sockets_.erase(it); - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&UnbindCallback::sendSuccess, std::move(callback))); } void TetheringHandler::TetheringImpl::Accepted(uint16_t port, const std::string& name) { - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&TetheringHandler::Accepted, handler_, port, name)); } diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.cc b/chromium/content/browser/devtools/protocol/tracing_handler.cc index 058e5b1e9ff..872b74e0ccf 100644 --- a/chromium/content/browser/devtools/protocol/tracing_handler.cc +++ b/chromium/content/browser/devtools/protocol/tracing_handler.cc @@ -18,7 +18,6 @@ #include "base/memory/ref_counted_memory.h" #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" -#include "base/task/post_task.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "base/trace_event/memory_dump_manager.h" @@ -142,8 +141,8 @@ class DevToolsStreamEndpoint : public TracingController::TraceDataEndpoint { void ReceiveTraceChunk(std::unique_ptr<std::string> chunk) override { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&DevToolsStreamEndpoint::ReceiveTraceChunk, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsStreamEndpoint::ReceiveTraceChunk, this, std::move(chunk))); return; } @@ -153,8 +152,8 @@ class DevToolsStreamEndpoint : public TracingController::TraceDataEndpoint { void ReceivedTraceFinalContents() override { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DevToolsStreamEndpoint::ReceivedTraceFinalContents, this)); return; @@ -759,8 +758,8 @@ void TracingHandler::Start(Maybe<std::string> categories, } // GPU process id can only be retrieved on IO thread. Do some thread hopping. - base::PostTaskAndReplyWithResult( - FROM_HERE, {BrowserThread::IO}, base::BindOnce([]() { + GetIOThreadTaskRunner({})->PostTaskAndReplyWithResult( + FROM_HERE, base::BindOnce([]() { GpuProcessHost* gpu_process_host = GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED, /* force_create */ false); @@ -953,10 +952,7 @@ void TracingHandler::OnFrameFromVideoConsumer( scoped_refptr<media::VideoFrame> frame) { const SkBitmap skbitmap = DevToolsVideoConsumer::GetSkBitmapFromFrame(frame); - base::TimeTicks reference_time; - const bool had_reference_time = frame->metadata()->GetTimeTicks( - media::VideoFrameMetadata::REFERENCE_TIME, &reference_time); - DCHECK(had_reference_time); + base::TimeTicks reference_time = *frame->metadata()->reference_time; TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID_AND_TIMESTAMP( TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), "Screenshot", 1, diff --git a/chromium/content/browser/devtools/protocol_config.json b/chromium/content/browser/devtools/protocol_config.json index 61abf10a52c..2f7efd98551 100644 --- a/chromium/content/browser/devtools/protocol_config.json +++ b/chromium/content/browser/devtools/protocol_config.json @@ -94,7 +94,7 @@ }, { "domain": "Target", - "async": ["disposeBrowserContext", "setAutoAttach"] + "async": ["createBrowserContext", "disposeBrowserContext", "setAutoAttach"] }, { "domain": "Tethering", diff --git a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc index 90ea37c62e7..52fdd0f1066 100644 --- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc @@ -14,7 +14,6 @@ #include "base/lazy_instance.h" #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/task/post_task.h" #include "build/build_config.h" #include "content/browser/bad_message.h" #include "content/browser/child_process_security_policy_impl.h" @@ -59,7 +58,6 @@ #include "content/public/browser/network_service_instance.h" #include "content/public/browser/render_widget_host_iterator.h" #include "content/public/browser/web_contents_delegate.h" -#include "mojo/public/cpp/bindings/associated_binding.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" @@ -88,16 +86,14 @@ RenderFrameDevToolsAgentHost* FindAgentHost(FrameTreeNode* frame_tree_node) { return it == g_agent_host_instances.Get().end() ? nullptr : it->second; } -bool ShouldCreateDevToolsForHost(RenderFrameHost* rfh) { - return rfh->IsCrossProcessSubframe() || !rfh->GetParent(); -} - bool ShouldCreateDevToolsForNode(FrameTreeNode* ftn) { return !ftn->parent() || (ftn->current_frame_host() && ftn->current_frame_host()->IsCrossProcessSubframe()); } +} // namespace + FrameTreeNode* GetFrameTreeNodeAncestor(FrameTreeNode* frame_tree_node) { while (frame_tree_node && !ShouldCreateDevToolsForNode(frame_tree_node)) frame_tree_node = FrameTreeNode::From(frame_tree_node->parent()); @@ -105,8 +101,6 @@ FrameTreeNode* GetFrameTreeNodeAncestor(FrameTreeNode* frame_tree_node) { return frame_tree_node; } -} // namespace - // static scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetOrCreateFor( WebContents* web_contents) { @@ -145,6 +139,12 @@ scoped_refptr<DevToolsAgentHost> RenderFrameDevToolsAgentHost::GetOrCreateFor( } // static +bool RenderFrameDevToolsAgentHost::ShouldCreateDevToolsForHost( + RenderFrameHost* rfh) { + return rfh->IsCrossProcessSubframe() || !rfh->GetParent(); +} + +// static scoped_refptr<DevToolsAgentHost> RenderFrameDevToolsAgentHost::CreateForCrossProcessNavigation( NavigationRequest* request) { @@ -446,13 +446,6 @@ void RenderFrameDevToolsAgentHost::DidFinishNavigation( } for (auto* target : protocol::TargetHandler::ForAgentHost(this)) target->DidFinishNavigation(); - - // RenderFrameDevToolsAgentHost is associated with frame_tree_node, while - // documents in the back-forward cache share a node, therefore we can't cache - // them. TODO(1001087): add support long-term. - content::BackForwardCache::DisableForRenderFrameHost( - navigation_handle->GetPreviousRenderFrameHostId(), - "RenderFrameDevToolsAgentHost"); } void RenderFrameDevToolsAgentHost::UpdateFrameHost( @@ -601,16 +594,6 @@ void RenderFrameDevToolsAgentHost::RenderProcessExited( } } -void RenderFrameDevToolsAgentHost::DidAttachInterstitialPage() { - for (auto* page : protocol::PageHandler::ForAgentHost(this)) - page->DidAttachInterstitialPage(); -} - -void RenderFrameDevToolsAgentHost::DidDetachInterstitialPage() { - for (auto* page : protocol::PageHandler::ForAgentHost(this)) - page->DidDetachInterstitialPage(); -} - void RenderFrameDevToolsAgentHost::OnVisibilityChanged( content::Visibility visibility) { #if defined(OS_ANDROID) @@ -633,7 +616,9 @@ void RenderFrameDevToolsAgentHost::OnPageScaleFactorChanged( void RenderFrameDevToolsAgentHost::OnNavigationRequestWillBeSent( const NavigationRequest& navigation_request) { - const auto& url = navigation_request.common_params().url; + GURL url = navigation_request.common_params().url; + if (url.SchemeIs(url::kJavaScriptScheme) && frame_host_) + url = frame_host_->GetLastCommittedURL(); std::vector<DevToolsSession*> restricted_sessions; bool is_webui = frame_host_ && frame_host_->web_ui(); for (DevToolsSession* session : sessions()) { @@ -785,8 +770,8 @@ void RenderFrameDevToolsAgentHost::SignalSynchronousSwapCompositorFrame( static_cast<RenderFrameHostImpl*>(frame_host)->frame_tree_node())); if (dtah) { // Unblock the compositor. - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce( &RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame, dtah.get(), frame_metadata)); @@ -843,9 +828,16 @@ bool RenderFrameDevToolsAgentHost::ShouldAllowSession( !manager->delegate()->AllowInspectingRenderFrameHost(frame_host_)) { return false; } - // Note this may be called before navigation is committed. - return session->GetClient()->MayAttachToURL( - frame_host_->GetSiteInstance()->GetSiteURL(), frame_host_->web_ui()); + auto* root = FrameTreeNode::From(frame_host_); + for (FrameTreeNode* node : root->frame_tree()->SubtreeNodes(root)) { + // Note this may be called before navigation is committed. + RenderFrameHostImpl* rfh = node->current_frame_host(); + const GURL& url = rfh->GetSiteInstance()->GetSiteURL(); + if (!session->GetClient()->MayAttachToURL(url, rfh->web_ui())) { + return false; + } + } + return true; } void RenderFrameDevToolsAgentHost::UpdateResourceLoaderFactories() { diff --git a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h index 69a66009454..c866dffa385 100644 --- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h +++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h @@ -61,6 +61,11 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost static scoped_refptr<DevToolsAgentHost> GetOrCreateFor( FrameTreeNode* frame_tree_node); + // Whether the RFH passed may have associated DevTools agent host + // (i.e. the specified RFH is a local root). This does not indicate + // whether DevToolsAgentHost has actually been created. + static bool ShouldCreateDevToolsForHost(RenderFrameHost* rfh); + // This method is called when new frame is created during cross process // navigation. static scoped_refptr<DevToolsAgentHost> CreateForCrossProcessNavigation( @@ -124,8 +129,6 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost RenderFrameHost* new_host) override; void FrameDeleted(RenderFrameHost* rfh) override; void RenderFrameDeleted(RenderFrameHost* rfh) override; - void DidAttachInterstitialPage() override; - void DidDetachInterstitialPage() override; void OnVisibilityChanged(content::Visibility visibility) override; void OnPageScaleFactorChanged(float page_scale_factor) override; @@ -170,6 +173,10 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost DISALLOW_COPY_AND_ASSIGN(RenderFrameDevToolsAgentHost); }; +// Returns the ancestor FrameTreeNode* for which a RenderFrameDevToolsAgentHost +// should be created (i.e. the next local root). +FrameTreeNode* GetFrameTreeNodeAncestor(FrameTreeNode* frame_tree_node); + } // namespace content #endif // CONTENT_BROWSER_DEVTOOLS_RENDER_FRAME_DEVTOOLS_AGENT_HOST_H_ diff --git a/chromium/content/browser/devtools/render_frame_devtools_agent_host_browsertest.cc b/chromium/content/browser/devtools/render_frame_devtools_agent_host_browsertest.cc index 40fc2892f7a..be8f65f513a 100644 --- a/chromium/content/browser/devtools/render_frame_devtools_agent_host_browsertest.cc +++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host_browsertest.cc @@ -10,7 +10,6 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/url_constants.h" -#include "content/public/test/back_forward_cache_util.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_base.h" #include "content/public/test/browser_test_utils.h" @@ -174,32 +173,4 @@ IN_PROC_BROWSER_TEST_F(RenderFrameDevToolsAgentHostBrowserTest, devtools_agent_host->DetachClient(&devtools_agent_host_client); } -IN_PROC_BROWSER_TEST_F(RenderFrameDevToolsAgentHostBrowserTest, - DevToolsDisableBackForwardCache) { - content::BackForwardCacheDisabledTester tester; - EXPECT_TRUE(embedded_test_server()->Start()); - - // Navigate to a page. - const GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html")); - EXPECT_TRUE(NavigateToURL(shell(), a_url)); - content::RenderFrameHost* main_frame = - shell()->web_contents()->GetMainFrame(); - int process_id = main_frame->GetProcess()->GetID(); - int frame_routing_id = main_frame->GetRoutingID(); - - // Open DevTools. - scoped_refptr<DevToolsAgentHost> devtools_agent_host = - DevToolsAgentHost::GetOrCreateFor(shell()->web_contents()); - StubDevToolsAgentHostClient devtools_agent_host_client; - devtools_agent_host->AttachClient(&devtools_agent_host_client); - - // Navigate away from the page. This should block bfcache. - const GURL b_url(embedded_test_server()->GetURL("b.com", "/title1.html")); - EXPECT_TRUE(NavigateToURL(shell(), b_url)); - EXPECT_TRUE(tester.IsDisabledForFrameWithReason( - process_id, frame_routing_id, "RenderFrameDevToolsAgentHost")); - - devtools_agent_host->DetachClient(&devtools_agent_host_client); -} - } // namespace content diff --git a/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc b/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc index bebadd2e931..1ccdae92a08 100644 --- a/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc +++ b/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc @@ -8,7 +8,6 @@ #include "base/bind_helpers.h" #include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" -#include "base/task/post_task.h" #include "content/browser/devtools/devtools_renderer_channel.h" #include "content/browser/devtools/devtools_session.h" #include "content/browser/devtools/protocol/fetch_handler.h" @@ -18,7 +17,7 @@ #include "content/browser/devtools/protocol/schema_handler.h" #include "content/browser/devtools/protocol/target_handler.h" #include "content/browser/devtools/service_worker_devtools_manager.h" -#include "content/browser/service_worker/service_worker_context_core.h" +#include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_version.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -29,31 +28,26 @@ namespace content { namespace { void TerminateServiceWorkerOnCoreThread( - base::WeakPtr<ServiceWorkerContextCore> context_weak, + scoped_refptr<ServiceWorkerContextWrapper> context, int64_t version_id) { - if (ServiceWorkerContextCore* context = context_weak.get()) { - if (ServiceWorkerVersion* version = context->GetLiveVersion(version_id)) - version->StopWorker(base::DoNothing()); - } + if (ServiceWorkerVersion* version = context->GetLiveVersion(version_id)) + version->StopWorker(base::DoNothing()); } void SetDevToolsAttachedOnCoreThread( - base::WeakPtr<ServiceWorkerContextCore> context_weak, + scoped_refptr<ServiceWorkerContextWrapper> context, int64_t version_id, bool attached) { - if (ServiceWorkerContextCore* context = context_weak.get()) { - if (ServiceWorkerVersion* version = context->GetLiveVersion(version_id)) - version->SetDevToolsAttached(attached); - } + if (ServiceWorkerVersion* version = context->GetLiveVersion(version_id)) + version->SetDevToolsAttached(attached); } void UpdateLoaderFactoriesOnCoreThread( - base::WeakPtr<ServiceWorkerContextCore> context_weak, + scoped_refptr<ServiceWorkerContextWrapper> context, int64_t version_id, std::unique_ptr<blink::PendingURLLoaderFactoryBundle> script_bundle, std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_bundle) { - auto* version = - context_weak ? context_weak->GetLiveVersion(version_id) : nullptr; + auto* version = context->GetLiveVersion(version_id); if (!version) return; version->embedded_worker()->UpdateLoaderFactories( @@ -65,8 +59,7 @@ void UpdateLoaderFactoriesOnCoreThread( ServiceWorkerDevToolsAgentHost::ServiceWorkerDevToolsAgentHost( int worker_process_id, int worker_route_id, - const ServiceWorkerContextCore* context, - base::WeakPtr<ServiceWorkerContextCore> context_weak, + scoped_refptr<ServiceWorkerContextWrapper> context_wrapper, int64_t version_id, const GURL& url, const GURL& scope, @@ -81,8 +74,7 @@ ServiceWorkerDevToolsAgentHost::ServiceWorkerDevToolsAgentHost( devtools_worker_token_(devtools_worker_token), worker_process_id_(worker_process_id), worker_route_id_(worker_route_id), - context_(context), - context_weak_(context_weak), + context_wrapper_(context_wrapper), version_id_(version_id), url_(url), scope_(scope), @@ -94,8 +86,7 @@ ServiceWorkerDevToolsAgentHost::ServiceWorkerDevToolsAgentHost( } BrowserContext* ServiceWorkerDevToolsAgentHost::GetBrowserContext() { - RenderProcessHost* rph = RenderProcessHost::FromID(worker_process_id_); - return rph ? rph->GetBrowserContext() : nullptr; + return context_wrapper_->browser_context(); } std::string ServiceWorkerDevToolsAgentHost::GetType() { @@ -120,7 +111,7 @@ void ServiceWorkerDevToolsAgentHost::Reload() { bool ServiceWorkerDevToolsAgentHost::Close() { RunOrPostTaskOnThread(FROM_HERE, ServiceWorkerContext::GetCoreThreadId(), base::BindOnce(&TerminateServiceWorkerOnCoreThread, - context_weak_, version_id_)); + context_wrapper_, version_id_)); return true; } @@ -132,12 +123,6 @@ void ServiceWorkerDevToolsAgentHost::WorkerVersionDoomed() { version_doomed_time_ = base::Time::Now(); } -bool ServiceWorkerDevToolsAgentHost::Matches( - const ServiceWorkerContextCore* context, - int64_t version_id) { - return context_ == context && version_id_ == version_id; -} - ServiceWorkerDevToolsAgentHost::~ServiceWorkerDevToolsAgentHost() { ServiceWorkerDevToolsManager::GetInstance()->AgentHostDestroyed(this); } @@ -195,7 +180,7 @@ void ServiceWorkerDevToolsAgentHost::WorkerRestarted(int worker_process_id, worker_route_id_ = worker_route_id; } -void ServiceWorkerDevToolsAgentHost::WorkerDestroyed() { +void ServiceWorkerDevToolsAgentHost::WorkerStopped() { DCHECK_NE(WORKER_TERMINATED, state_); state_ = WORKER_TERMINATED; for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this)) @@ -207,9 +192,10 @@ void ServiceWorkerDevToolsAgentHost::WorkerDestroyed() { } void ServiceWorkerDevToolsAgentHost::UpdateIsAttached(bool attached) { - RunOrPostTaskOnThread(FROM_HERE, ServiceWorkerContext::GetCoreThreadId(), - base::BindOnce(&SetDevToolsAttachedOnCoreThread, - context_weak_, version_id_, attached)); + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContext::GetCoreThreadId(), + base::BindOnce(&SetDevToolsAttachedOnCoreThread, context_wrapper_, + version_id_, attached)); } void ServiceWorkerDevToolsAgentHost::UpdateLoaderFactories( @@ -249,14 +235,14 @@ void ServiceWorkerDevToolsAgentHost::UpdateLoaderFactories( ContentBrowserClient::URLLoaderFactoryType::kServiceWorkerSubResource); if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) { - UpdateLoaderFactoriesOnCoreThread(context_weak_, version_id_, + UpdateLoaderFactoriesOnCoreThread(context_wrapper_, version_id_, std::move(script_bundle), std::move(subresource_bundle)); std::move(callback).Run(); } else { - base::PostTaskAndReply( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&UpdateLoaderFactoriesOnCoreThread, context_weak_, + GetIOThreadTaskRunner({})->PostTaskAndReply( + FROM_HERE, + base::BindOnce(&UpdateLoaderFactoriesOnCoreThread, context_wrapper_, version_id_, std::move(script_bundle), std::move(subresource_bundle)), std::move(callback)); diff --git a/chromium/content/browser/devtools/service_worker_devtools_agent_host.h b/chromium/content/browser/devtools/service_worker_devtools_agent_host.h index 08cb2e0f5b3..48a03cf0d1c 100644 --- a/chromium/content/browser/devtools/service_worker_devtools_agent_host.h +++ b/chromium/content/browser/devtools/service_worker_devtools_agent_host.h @@ -31,8 +31,7 @@ class ServiceWorkerDevToolsAgentHost : public DevToolsAgentHostImpl { ServiceWorkerDevToolsAgentHost( int worker_process_id, int worker_route_id, - const ServiceWorkerContextCore* context, - base::WeakPtr<ServiceWorkerContextCore> context_weak, + scoped_refptr<ServiceWorkerContextWrapper> context_wrapper, int64_t version_id, const GURL& url, const GURL& scope, @@ -60,7 +59,7 @@ class ServiceWorkerDevToolsAgentHost : public DevToolsAgentHostImpl { network::CrossOriginEmbedderPolicy cross_origin_embedder_policy, mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter> coep_reporter); - void WorkerDestroyed(); + void WorkerStopped(); void WorkerVersionInstalled(); void WorkerVersionDoomed(); @@ -78,8 +77,9 @@ class ServiceWorkerDevToolsAgentHost : public DevToolsAgentHostImpl { base::Time version_doomed_time() const { return version_doomed_time_; } int64_t version_id() const { return version_id_; } - - bool Matches(const ServiceWorkerContextCore* context, int64_t version_id); + const ServiceWorkerContextWrapper* context_wrapper() const { + return context_wrapper_.get(); + } private: ~ServiceWorkerDevToolsAgentHost() override; @@ -100,8 +100,7 @@ class ServiceWorkerDevToolsAgentHost : public DevToolsAgentHostImpl { base::UnguessableToken devtools_worker_token_; int worker_process_id_; int worker_route_id_; - const ServiceWorkerContextCore* context_; - base::WeakPtr<ServiceWorkerContextCore> context_weak_; + scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_; int64_t version_id_; GURL url_; GURL scope_; diff --git a/chromium/content/browser/devtools/service_worker_devtools_manager.cc b/chromium/content/browser/devtools/service_worker_devtools_manager.cc index b48794174ed..f8003e10cd7 100644 --- a/chromium/content/browser/devtools/service_worker_devtools_manager.cc +++ b/chromium/content/browser/devtools/service_worker_devtools_manager.cc @@ -7,6 +7,7 @@ #include "content/browser/devtools/protocol/network_handler.h" #include "content/browser/devtools/protocol/page_handler.h" #include "content/browser/devtools/service_worker_devtools_agent_host.h" +#include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" #include "ipc/ipc_listener.h" @@ -43,11 +44,10 @@ void ServiceWorkerDevToolsManager::AddAllAgentHostsForBrowserContext( } } -void ServiceWorkerDevToolsManager::WorkerCreated( +void ServiceWorkerDevToolsManager::WorkerStarting( int worker_process_id, int worker_route_id, - const ServiceWorkerContextCore* context, - base::WeakPtr<ServiceWorkerContextCore> context_weak, + scoped_refptr<ServiceWorkerContextWrapper> context_wrapper, int64_t version_id, const GURL& url, const GURL& scope, @@ -62,36 +62,31 @@ void ServiceWorkerDevToolsManager::WorkerCreated( const WorkerId worker_id(worker_process_id, worker_route_id); DCHECK(live_hosts_.find(worker_id) == live_hosts_.end()); - auto it = std::find_if( - terminated_hosts_.begin(), terminated_hosts_.end(), - [&context, &version_id](ServiceWorkerDevToolsAgentHost* agent_host) { - return agent_host->Matches(context, version_id); - }); - if (it == terminated_hosts_.end()) { - *devtools_worker_token = base::UnguessableToken::Create(); - scoped_refptr<ServiceWorkerDevToolsAgentHost> host = - new ServiceWorkerDevToolsAgentHost( - worker_process_id, worker_route_id, context, context_weak, - version_id, url, scope, is_installed_version, - cross_origin_embedder_policy, std::move(coep_reporter), - *devtools_worker_token); - live_hosts_[worker_id] = host; - *pause_on_start = debug_service_worker_on_start_; - for (auto& observer : observer_list_) { - bool should_pause_on_start = false; - observer.WorkerCreated(host.get(), &should_pause_on_start); - if (should_pause_on_start) - *pause_on_start = true; - } + scoped_refptr<ServiceWorkerDevToolsAgentHost> agent_host = + TakeStoppedHost(context_wrapper.get(), version_id); + if (agent_host) { + live_hosts_[worker_id] = agent_host; + agent_host->WorkerRestarted(worker_process_id, worker_route_id); + *pause_on_start = agent_host->IsAttached(); + *devtools_worker_token = agent_host->devtools_worker_token(); return; } - ServiceWorkerDevToolsAgentHost* agent_host = *it; - terminated_hosts_.erase(it); - live_hosts_[worker_id] = agent_host; - agent_host->WorkerRestarted(worker_process_id, worker_route_id); - *pause_on_start = agent_host->IsAttached(); - *devtools_worker_token = agent_host->devtools_worker_token(); + *devtools_worker_token = base::UnguessableToken::Create(); + scoped_refptr<ServiceWorkerDevToolsAgentHost> host = + new ServiceWorkerDevToolsAgentHost( + worker_process_id, worker_route_id, std::move(context_wrapper), + version_id, url, scope, is_installed_version, + cross_origin_embedder_policy, std::move(coep_reporter), + *devtools_worker_token); + live_hosts_[worker_id] = host; + *pause_on_start = debug_service_worker_on_start_; + for (auto& observer : observer_list_) { + bool should_pause_on_start = false; + observer.WorkerCreated(host.get(), &should_pause_on_start); + if (should_pause_on_start) + *pause_on_start = true; + } } void ServiceWorkerDevToolsManager::WorkerReadyForInspection( @@ -123,9 +118,8 @@ void ServiceWorkerDevToolsManager::UpdateCrossOriginEmbedderPolicy( auto it = live_hosts_.find(worker_id); if (it == live_hosts_.end()) return; - scoped_refptr<ServiceWorkerDevToolsAgentHost> host = it->second; - host->UpdateCrossOriginEmbedderPolicy(std::move(cross_origin_embedder_policy), - std::move(coep_reporter)); + it->second->UpdateCrossOriginEmbedderPolicy( + std::move(cross_origin_embedder_policy), std::move(coep_reporter)); } void ServiceWorkerDevToolsManager::WorkerVersionInstalled(int worker_process_id, @@ -135,27 +129,34 @@ void ServiceWorkerDevToolsManager::WorkerVersionInstalled(int worker_process_id, auto it = live_hosts_.find(worker_id); if (it == live_hosts_.end()) return; - scoped_refptr<ServiceWorkerDevToolsAgentHost> host = it->second; - host->WorkerVersionInstalled(); - for (auto& observer : observer_list_) - observer.WorkerVersionInstalled(host.get()); + it->second->WorkerVersionInstalled(); } -void ServiceWorkerDevToolsManager::WorkerVersionDoomed(int worker_process_id, - int worker_route_id) { +void ServiceWorkerDevToolsManager::WorkerVersionDoomed( + int worker_process_id, + int worker_route_id, + scoped_refptr<ServiceWorkerContextWrapper> context_wrapper, + int64_t version_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); const WorkerId worker_id(worker_process_id, worker_route_id); auto it = live_hosts_.find(worker_id); - if (it == live_hosts_.end()) + if (it != live_hosts_.end()) { + it->second->WorkerVersionDoomed(); + return; + } + scoped_refptr<ServiceWorkerDevToolsAgentHost> host = + TakeStoppedHost(context_wrapper.get(), version_id); + if (!host) return; - scoped_refptr<ServiceWorkerDevToolsAgentHost> host = it->second; host->WorkerVersionDoomed(); + // The worker has already been stopped and since it's doomed it will never + // restart. for (auto& observer : observer_list_) - observer.WorkerVersionDoomed(host.get()); + observer.WorkerDestroyed(host.get()); } -void ServiceWorkerDevToolsManager::WorkerDestroyed(int worker_process_id, - int worker_route_id) { +void ServiceWorkerDevToolsManager::WorkerStopped(int worker_process_id, + int worker_route_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); const WorkerId worker_id(worker_process_id, worker_route_id); auto it = live_hosts_.find(worker_id); @@ -163,21 +164,23 @@ void ServiceWorkerDevToolsManager::WorkerDestroyed(int worker_process_id, return; scoped_refptr<ServiceWorkerDevToolsAgentHost> agent_host(it->second); live_hosts_.erase(it); - terminated_hosts_.insert(agent_host.get()); - agent_host->WorkerDestroyed(); - for (auto& observer : observer_list_) - observer.WorkerDestroyed(agent_host.get()); + agent_host->WorkerStopped(); + if (agent_host->version_doomed_time().is_null()) { + stopped_hosts_.insert(agent_host.get()); + } else { + // The worker version has been doomed, it will never restart. + for (auto& observer : observer_list_) + observer.WorkerDestroyed(agent_host.get()); + } } void ServiceWorkerDevToolsManager::AgentHostDestroyed( ServiceWorkerDevToolsAgentHost* agent_host) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - auto it = terminated_hosts_.find(agent_host); // Might be missing during shutdown due to different // destruction order of this manager, service workers // and their agent hosts. - if (it != terminated_hosts_.end()) - terminated_hosts_.erase(it); + stopped_hosts_.erase(agent_host); } void ServiceWorkerDevToolsManager::AddObserver(Observer* observer) { @@ -197,8 +200,7 @@ ServiceWorkerDevToolsManager::ServiceWorkerDevToolsManager() : debug_service_worker_on_start_(false) { } -ServiceWorkerDevToolsManager::~ServiceWorkerDevToolsManager() { -} +ServiceWorkerDevToolsManager::~ServiceWorkerDevToolsManager() = default; void ServiceWorkerDevToolsManager::NavigationPreloadRequestSent( int worker_process_id, @@ -248,4 +250,22 @@ void ServiceWorkerDevToolsManager::NavigationPreloadCompleted( request_id, protocol::Network::ResourceTypeEnum::Other, status); } +scoped_refptr<ServiceWorkerDevToolsAgentHost> +ServiceWorkerDevToolsManager::TakeStoppedHost( + const ServiceWorkerContextWrapper* context_wrapper, + int64_t version_id) { + auto it = + std::find_if(stopped_hosts_.begin(), stopped_hosts_.end(), + [&context_wrapper, + &version_id](ServiceWorkerDevToolsAgentHost* agent_host) { + return agent_host->context_wrapper() == context_wrapper && + agent_host->version_id() == version_id; + }); + if (it == stopped_hosts_.end()) + return nullptr; + scoped_refptr<ServiceWorkerDevToolsAgentHost> agent_host(*it); + stopped_hosts_.erase(it); + return agent_host; +} + } // namespace content diff --git a/chromium/content/browser/devtools/service_worker_devtools_manager.h b/chromium/content/browser/devtools/service_worker_devtools_manager.h index b991e1bf55f..412fcb9774a 100644 --- a/chromium/content/browser/devtools/service_worker_devtools_manager.h +++ b/chromium/content/browser/devtools/service_worker_devtools_manager.h @@ -31,7 +31,7 @@ namespace content { class BrowserContext; class ServiceWorkerDevToolsAgentHost; -class ServiceWorkerContextCore; +class ServiceWorkerContextWrapper; // Manages ServiceWorkerDevToolsAgentHost's. This class lives on UI thread. class CONTENT_EXPORT ServiceWorkerDevToolsManager { @@ -40,8 +40,6 @@ class CONTENT_EXPORT ServiceWorkerDevToolsManager { public: virtual void WorkerCreated(ServiceWorkerDevToolsAgentHost* host, bool* should_pause_on_start) {} - virtual void WorkerVersionInstalled(ServiceWorkerDevToolsAgentHost* host) {} - virtual void WorkerVersionDoomed(ServiceWorkerDevToolsAgentHost* host) {} virtual void WorkerDestroyed(ServiceWorkerDevToolsAgentHost* host) {} protected: @@ -60,11 +58,10 @@ class CONTENT_EXPORT ServiceWorkerDevToolsManager { BrowserContext* browser_context, std::vector<scoped_refptr<ServiceWorkerDevToolsAgentHost>>* result); - void WorkerCreated( + void WorkerStarting( int worker_process_id, int worker_route_id, - const ServiceWorkerContextCore* context, - base::WeakPtr<ServiceWorkerContextCore> context_weak, + scoped_refptr<ServiceWorkerContextWrapper> context_wrapper, int64_t version_id, const GURL& url, const GURL& scope, @@ -87,8 +84,15 @@ class CONTENT_EXPORT ServiceWorkerDevToolsManager { mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter> coep_reporter); void WorkerVersionInstalled(int worker_process_id, int worker_route_id); - void WorkerVersionDoomed(int worker_process_id, int worker_route_id); - void WorkerDestroyed(int worker_process_id, int worker_route_id); + // If the worker instance is stopped its worker_process_id and + // worker_route_id will be invalid. For that case we pass context + // and version_id as well. + void WorkerVersionDoomed( + int worker_process_id, + int worker_route_id, + scoped_refptr<ServiceWorkerContextWrapper> context_wrapper, + int64_t version_id); + void WorkerStopped(int worker_process_id, int worker_route_id); void NavigationPreloadRequestSent(int worker_process_id, int worker_route_id, const std::string& request_id, @@ -123,6 +127,10 @@ class CONTENT_EXPORT ServiceWorkerDevToolsManager { ServiceWorkerDevToolsManager(); ~ServiceWorkerDevToolsManager(); + scoped_refptr<ServiceWorkerDevToolsAgentHost> TakeStoppedHost( + const ServiceWorkerContextWrapper* context_wrapper, + int64_t version_id); + base::ObserverList<Observer>::Unchecked observer_list_; bool debug_service_worker_on_start_; @@ -131,7 +139,7 @@ class CONTENT_EXPORT ServiceWorkerDevToolsManager { // Clients may retain agent host for the terminated shared worker, // and we reconnect them when shared worker is restarted. - base::flat_set<ServiceWorkerDevToolsAgentHost*> terminated_hosts_; + base::flat_set<ServiceWorkerDevToolsAgentHost*> stopped_hosts_; DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDevToolsManager); }; diff --git a/chromium/content/browser/devtools/shared_worker_devtools_manager.cc b/chromium/content/browser/devtools/shared_worker_devtools_manager.cc index 7e84c2dd3d8..9f3975d1db6 100644 --- a/chromium/content/browser/devtools/shared_worker_devtools_manager.cc +++ b/chromium/content/browser/devtools/shared_worker_devtools_manager.cc @@ -81,10 +81,7 @@ void SharedWorkerDevToolsManager::AgentHostDestroyed( terminated_hosts_.erase(it); } -SharedWorkerDevToolsManager::SharedWorkerDevToolsManager() { -} - -SharedWorkerDevToolsManager::~SharedWorkerDevToolsManager() { -} +SharedWorkerDevToolsManager::SharedWorkerDevToolsManager() = default; +SharedWorkerDevToolsManager::~SharedWorkerDevToolsManager() = default; } // namespace content diff --git a/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc b/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc index 114548c3c0d..292f5254cb3 100644 --- a/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc +++ b/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc @@ -17,6 +17,7 @@ #include "content/shell/browser/shell.h" #include "content/shell/browser/shell_download_manager_delegate.h" #include "content/test/content_browser_test_utils_internal.h" +#include "content/test/render_document_feature.h" #include "net/dns/mock_host_resolver.h" namespace content { @@ -65,7 +66,7 @@ class TestClient: public DevToolsAgentHostClient { #else #define MAYBE_CrossSiteIframeAgentHost CrossSiteIframeAgentHost #endif -IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest, +IN_PROC_BROWSER_TEST_P(SitePerProcessDevToolsBrowserTest, MAYBE_CrossSiteIframeAgentHost) { DevToolsAgentHost::List list; GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); @@ -139,7 +140,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest, parent_host = nullptr; } -IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest, AgentHostForFrames) { +IN_PROC_BROWSER_TEST_P(SitePerProcessDevToolsBrowserTest, AgentHostForFrames) { GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); EXPECT_TRUE(NavigateToURL(shell(), main_url)); @@ -177,8 +178,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest, AgentHostForFrames) { EXPECT_NE(child_frame_agent->GetId(), page_agent->GetId()); } -IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest, - AgentHostForPageEqualsOneForMainFrame) { +IN_PROC_BROWSER_TEST_P(SitePerProcessDevToolsBrowserTest, + AgentHostForPageEqualsOneForMainFrame) { GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); EXPECT_TRUE(NavigateToURL(shell(), main_url)); @@ -230,7 +231,7 @@ class SitePerProcessDownloadDevToolsBrowserTest base::ScopedTempDir downloads_directory_; }; -IN_PROC_BROWSER_TEST_F(SitePerProcessDownloadDevToolsBrowserTest, +IN_PROC_BROWSER_TEST_P(SitePerProcessDownloadDevToolsBrowserTest, NotCommittedNavigationDoesNotBlockAgent) { ASSERT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); @@ -259,4 +260,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDownloadDevToolsBrowserTest, ASSERT_TRUE(agent->DetachClient(&client)); } +INSTANTIATE_TEST_SUITE_P(All, + SitePerProcessDevToolsBrowserTest, + testing::ValuesIn(RenderDocumentFeatureLevelValues())); +INSTANTIATE_TEST_SUITE_P(All, + SitePerProcessDownloadDevToolsBrowserTest, + testing::ValuesIn(RenderDocumentFeatureLevelValues())); + } // namespace content |