From b1e7ed4ddcfc453c1c006d3adf9fece2df12cc10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=96=87=E9=9B=AA?= Date: Thu, 26 Dec 2024 09:29:35 +0000 Subject: [PATCH 1/2] preload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 杨文雪 --- .../renderer_host/navigation_request.cc | 83 +- .../renderer_host/navigation_request.h | 11 + content/browser/renderer_host/navigator.cc | 54 +- .../renderer_host/render_frame_host_impl.cc | 27 +- .../renderer_host/render_frame_host_impl.h | 8 +- .../url_loader_factory_params_helper.cc | 29 +- .../url_loader_factory_params_helper.h | 13 +- ...ohos_media_decoder_bridge_impl_unittest.cc | 1 + net/BUILD.gn | 14 +- net/base/page_res_request_info.cc | 87 ++ net/base/page_res_request_info.h | 267 ++++ net/features.gni | 3 + net/http/http_cache_transaction.cc | 35 +- net/http/http_cache_transaction.h | 20 +- net/http/http_request_info.h | 5 +- net/http/http_transaction.h | 20 + .../include/page_res_parallel_preload_mgr.h | 34 - .../include/page_res_request_info.h | 77 -- net/prp_preload/src/res_preload_scheduler.cc | 108 -- .../src/res_request_info_updater.cc | 52 - net/url_request/url_request.h | 30 +- net/url_request/url_request_context.cc | 14 + net/url_request/url_request_context.h | 11 + net/url_request/url_request_http_job.cc | 15 +- services/network/BUILD.gn | 10 + services/network/cors/cors_url_loader.cc | 4 + .../network/cors/cors_url_loader_factory.cc | 4 + services/network/cors/preflight_controller.cc | 6 + services/network/network_context.cc | 44 +- services/network/network_context.h | 10 +- .../network}/prp_preload/BUILD.gn | 18 +- .../include/page_res_parallel_preload_mgr.h | 78 ++ .../preload_runner/prpp_request_loader.h | 85 ++ .../prpp_request_loader_factory.h | 61 + .../src/disk_cache_backend_factory.cc | 9 +- .../src/disk_cache_backend_factory.h | 12 +- .../prp_preload/src/disk_cache_file.cc | 19 +- .../prp_preload/src/disk_cache_file.h | 10 +- .../prp_preload/src/disk_cache_info_parser.cc | 1131 +++++++++++++++++ .../prp_preload/src/disk_cache_info_parser.h | 303 +++++ .../src/page_res_parallel_preload_mgr_impl.cc | 340 +++++ .../src/page_res_parallel_preload_mgr_impl.h | 50 +- .../src/preload_runner}/preconnect_runner.cc | 17 +- .../src/preload_runner}/preconnect_runner.h | 10 +- .../prpp_request_loader_factory_impl.cc | 289 +++++ .../prpp_request_loader_factory_impl.h | 71 ++ .../prpp_request_loader_impl.cc | 646 ++++++++++ .../preload_runner/prpp_request_loader_impl.h | 125 ++ .../src/res_parallel_preload_ctrler.cc | 115 +- .../src/res_parallel_preload_ctrler.h | 40 +- .../prp_preload/src/res_preload_scheduler.cc | 219 ++++ .../prp_preload/src/res_preload_scheduler.h | 55 +- .../src/res_request_info_cache_mgr.cc | 214 ++++ .../src/res_request_info_cache_mgr.h | 25 +- .../src/res_request_info_updater.cc | 189 +++ .../src/res_request_info_updater.h | 35 +- .../network/public/cpp/resource_request.h | 8 +- .../public/cpp/url_request_mojom_traits.cc | 13 +- .../public/cpp/url_request_mojom_traits.h | 15 +- services/network/public/mojom/BUILD.gn | 8 + .../public/mojom/network_context.mojom | 18 +- .../network/public/mojom/url_request.mojom | 9 +- services/network/test/test_network_context.h | 8 +- services/network/url_loader.cc | 438 ++++++- services/network/url_loader.h | 43 +- services/network/url_loader_factory.cc | 35 +- services/network/url_loader_factory.h | 9 + ui/events/blink/fling_booster_unittest.cc | 1 + 68 files changed, 5311 insertions(+), 556 deletions(-) create mode 100644 net/base/page_res_request_info.cc create mode 100644 net/base/page_res_request_info.h delete mode 100644 net/prp_preload/include/page_res_parallel_preload_mgr.h delete mode 100644 net/prp_preload/include/page_res_request_info.h delete mode 100644 net/prp_preload/src/res_preload_scheduler.cc delete mode 100644 net/prp_preload/src/res_request_info_updater.cc rename {net => services/network}/prp_preload/BUILD.gn (59%) create mode 100644 services/network/prp_preload/include/page_res_parallel_preload_mgr.h create mode 100644 services/network/prp_preload/include/preload_runner/prpp_request_loader.h create mode 100644 services/network/prp_preload/include/preload_runner/prpp_request_loader_factory.h rename {net => services/network}/prp_preload/src/disk_cache_backend_factory.cc (85%) rename {net => services/network}/prp_preload/src/disk_cache_backend_factory.h (75%) rename {net => services/network}/prp_preload/src/disk_cache_file.cc (92%) rename {net => services/network}/prp_preload/src/disk_cache_file.h (92%) create mode 100644 services/network/prp_preload/src/disk_cache_info_parser.cc create mode 100644 services/network/prp_preload/src/disk_cache_info_parser.h create mode 100644 services/network/prp_preload/src/page_res_parallel_preload_mgr_impl.cc rename {net => services/network}/prp_preload/src/page_res_parallel_preload_mgr_impl.h (42%) rename {net/prp_preload/src => services/network/prp_preload/src/preload_runner}/preconnect_runner.cc (81%) rename {net/prp_preload/src => services/network/prp_preload/src/preload_runner}/preconnect_runner.h (67%) create mode 100644 services/network/prp_preload/src/preload_runner/prpp_request_loader_factory_impl.cc create mode 100644 services/network/prp_preload/src/preload_runner/prpp_request_loader_factory_impl.h create mode 100644 services/network/prp_preload/src/preload_runner/prpp_request_loader_impl.cc create mode 100644 services/network/prp_preload/src/preload_runner/prpp_request_loader_impl.h rename {net => services/network}/prp_preload/src/res_parallel_preload_ctrler.cc (37%) rename {net => services/network}/prp_preload/src/res_parallel_preload_ctrler.h (42%) create mode 100644 services/network/prp_preload/src/res_preload_scheduler.cc rename {net => services/network}/prp_preload/src/res_preload_scheduler.h (31%) create mode 100644 services/network/prp_preload/src/res_request_info_cache_mgr.cc rename {net => services/network}/prp_preload/src/res_request_info_cache_mgr.h (66%) create mode 100644 services/network/prp_preload/src/res_request_info_updater.cc rename {net => services/network}/prp_preload/src/res_request_info_updater.h (44%) diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index f327256bd9..7f851d897f 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc @@ -198,6 +198,9 @@ #if defined(OHOS_RENDERER_ANR_DUMP) #include "content/public/browser/web_contents_delegate.h" #endif +#if BUILDFLAG(IS_OHOS_PRPP) +#include "mojo/public/cpp/bindings/callback_helpers.h" +#endif namespace content { @@ -217,6 +220,10 @@ base::TimeDelta g_commit_timeout = kDefaultCommitTimeout; constexpr base::TimeDelta kCompositorLockTimeout = base::Milliseconds(150); #endif +#if BUILDFLAG(IS_OHOS_PRPP) +const std::string ORIGIN = "origin.DEFAULT"; +#endif + // crbug.com/954271: This feature is a part of an ablation study which makes // history navigations slower. // TODO(altimin): Clean this up after the study finishes. @@ -5847,7 +5854,12 @@ void NavigationRequest::CommitNavigation() { std::move(url_loader_client_endpoints_), std::move(subresource_loader_params_), std::move(subresource_overrides_), std::move(service_worker_container_info), document_token_, - devtools_navigation_token_); + devtools_navigation_token_ +#if BUILDFLAG(IS_OHOS_PRPP) + , + addr_web_handle_ +#endif + ); UpdateNavigationHandleTimingsOnCommitSent(); // Give SpareRenderProcessHostManager a heads-up about the most recently used @@ -9536,4 +9548,73 @@ void NavigationRequest::CreateWebUIIfNeeded(RenderFrameHostImpl* frame_host) { web_ui_->SetController(std::move(controller)); } +#if BUILDFLAG(IS_OHOS_PRPP) +network::mojom::NetworkContext* NavigationRequest::GetNetworkContext() const +{ + if (!common_params_) { + LOG(DEBUG) << "PRPPreload.NavigationRequest::GetNetworkContext, no common_params"; + return nullptr; + } + if (common_params_->url.spec() == "about:blank") { + LOG(DEBUG) << "PRPPreload.NavigationRequest::GetNetworkContext, blank page not need"; + return nullptr; + } + if (!frame_tree_node_) { + LOG(DEBUG) << "PRPPreload.NavigationRequest::GetNetworkContext, no frame_tree_node"; + return nullptr; + } + if (!frame_tree_node_->IsMainFrame()) { + LOG(DEBUG) << "PRPPreload.NavigationRequest::GetNetworkContext, not main frame"; + return nullptr; + } + if (!frame_tree_node_->current_frame_host()) { + LOG(DEBUG) << "PRPPreload.NavigationRequest::GetNetworkContext, no current_frame_host"; + return nullptr; + } + if (!frame_tree_node_->current_frame_host()->GetStoragePartition()) { + LOG(DEBUG) << "PRPPreload.NavigationRequest::GetNetworkContext, no storage_partition"; + return nullptr; + } + + return frame_tree_node_->current_frame_host()->GetStoragePartition()->GetNetworkContext(); +} + +using StartPageCallback__ = base::OnceCallback; +void NavigationRequest::StartPage(uint64_t addr_web_handle) +{ + network::mojom::NetworkContext* network_context = GetNetworkContext(); + if (!network_context) { + return; + } + + addr_web_handle_ = addr_web_handle; + network_context->StartPage(common_params_->url.spec(), addr_web_handle_, + mojo::WrapCallbackWithDefaultInvokeIfNotRun(base::BindOnce(&NavigationRequest::OnGetIsolation, + weak_factory_.GetWeakPtr()), ORIGIN)); +} + +void NavigationRequest::OnGetIsolation(const std::string& origin) +{ + if (origin.starts_with(ORIGIN)) { + LOG(DEBUG) << "PRPPreload.NavigationRequest::OnGetIsolation, canceled"; + return; + } + + network::mojom::NetworkContext* network_context = GetNetworkContext(); + if (!network_context) { + return; + } + + url::Origin url_origin = url::Origin::Create(GURL(origin)); + net::IsolationInfo prp_isolation = + frame_tree_node_->current_frame_host()->ComputeIsolationInfoForSubresourcesForPendingCommit( + url_origin, is_credentialless(), ComputeFencedFrameNonce()); + network::mojom::URLLoaderFactoryParamsPtr params = network::mojom::URLLoaderFactoryParams::New(); + if (params) { + params->isolation_info = prp_isolation; + params->main_url = common_params_->url.spec(); + network_context->SetParam(std::move(params)); + } +} +#endif } // namespace content diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h index 722cb755bd..4b896eef29 100644 --- a/content/browser/renderer_host/navigation_request.h +++ b/content/browser/renderer_host/navigation_request.h @@ -1214,6 +1214,13 @@ class CONTENT_EXPORT NavigationRequest // navigation. ErrorPageProcess ComputeErrorPageProcess(); +#if BUILDFLAG(IS_OHOS_PRPP) + uint64_t GetAddrWebHandle() { return addr_web_handle_; } + network::mojom::NetworkContext* GetNetworkContext() const; + void StartPage(uint64_t addr_web_handle); + void OnGetIsolation(const std::string& origin); +#endif + private: friend class NavigationRequestTest; @@ -2576,6 +2583,10 @@ class CONTENT_EXPORT NavigationRequest // by the RenderFrameHost. std::unique_ptr web_ui_; +#if BUILDFLAG(IS_OHOS_PRPP) + uint64_t addr_web_handle_; +#endif + base::WeakPtrFactory weak_factory_{this}; }; diff --git a/content/browser/renderer_host/navigator.cc b/content/browser/renderer_host/navigator.cc index c8e192d221..462415e319 100644 --- a/content/browser/renderer_host/navigator.cc +++ b/content/browser/renderer_host/navigator.cc @@ -58,10 +58,6 @@ #include "url/gurl.h" #include "url/url_util.h" -#if BUILDFLAG(IS_OHOS) -#include "services/network/public/mojom/network_context.mojom.h" -#endif - namespace content { namespace { @@ -340,11 +336,14 @@ Navigator::Navigator( delegate_(delegate) {} Navigator::~Navigator() { -#if BUILDFLAG(IS_OHOS) - network::mojom::NetworkContext* network_context = controller_.GetBrowserContext() - ->GetDefaultStoragePartition()->GetNetworkContext(); - if (network_context != nullptr) { - network_context->StopMainPage(reinterpret_cast(this)); +#if BUILDFLAG(IS_OHOS_PRPP) + content::StoragePartition* storage_partition = + controller_.GetBrowserContext()->GetDefaultStoragePartition(); + if (storage_partition) { + network::mojom::NetworkContext* network_context = storage_partition->GetNetworkContext(); + if (network_context != nullptr) { + network_context->StopPage(reinterpret_cast(this)); + } } #endif } @@ -474,14 +473,9 @@ void Navigator::DidNavigate( bool was_within_same_document) { DCHECK(navigation_request); FrameTreeNode* frame_tree_node = render_frame_host->frame_tree_node(); -#if BUILDFLAG(IS_OHOS) - network::mojom::NetworkContext* network_context = frame_tree_node->current_frame_host() - ->GetStoragePartition()->GetNetworkContext(); - if (network_context != nullptr) { - const net::NetworkAnonymizationKey networkAnonymizationKey = - GetNetworkAnonymizationKey(frame_tree_node, navigation_request.get()); - network_context->StartMainPage(params.url.possibly_invalid_spec(), networkAnonymizationKey, - reinterpret_cast(this)); +#if BUILDFLAG(IS_OHOS_PRPP) + if (navigation_request) { + navigation_request->StartPage(reinterpret_cast(this)); } #endif FrameTree& frame_tree = frame_tree_node->frame_tree(); @@ -740,15 +734,8 @@ void Navigator::Navigate(std::unique_ptr request, FrameTreeNode* frame_tree_node = request->frame_tree_node(); DCHECK_EQ(&(frame_tree_node->frame_tree()), &controller_.frame_tree()); -#if BUILDFLAG(IS_OHOS) - network::mojom::NetworkContext* network_context = frame_tree_node->current_frame_host() - ->GetStoragePartition()->GetNetworkContext(); - if (network_context != nullptr) { - const net::NetworkAnonymizationKey networkAnonymizationKey = - GetNetworkAnonymizationKey(frame_tree_node, request.get()); - network_context->StartMainPage(request->common_params().url.spec(), networkAnonymizationKey, - reinterpret_cast(this)); - } +#if BUILDFLAG(IS_OHOS_PRPP) + request->StartPage(reinterpret_cast(this)); #endif metrics_data_ = std::make_unique( @@ -1092,6 +1079,10 @@ void Navigator::OnBeginNavigation( frame_tree_node->current_frame_host()->GetPageUkmSourceId(), false /* is_browser_initiated_before_unload */); +#if BUILDFLAG(IS_OHOS_PRPP) + navigation_request->StartPage(reinterpret_cast(this)); +#endif + LogRendererInitiatedBeforeUnloadTime( navigation_request->begin_params().before_unload_start, navigation_request->begin_params().before_unload_end); @@ -1122,17 +1113,6 @@ void Navigator::OnBeginNavigation( navigation_request->common_params().navigation_start); } -#if BUILDFLAG(IS_OHOS) - network::mojom::NetworkContext* network_context = frame_tree_node->current_frame_host() - ->GetStoragePartition()->GetNetworkContext(); - if (network_context != nullptr) { - const net::NetworkAnonymizationKey networkAnonymizationKey = - GetNetworkAnonymizationKey(frame_tree_node, navigation_request); - network_context->StartMainPage(navigation_request->common_params().url.spec(), networkAnonymizationKey, - reinterpret_cast(this)); - } -#endif - // For main frames, NavigationHandle will be created after the call to // |DidStartMainFrameNavigation|, so it receives the most up to date pending // entry from the NavigationController. diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index dd02f42eb8..5ff741165f 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc @@ -1196,6 +1196,10 @@ class RenderFrameHostImpl::SubresourceLoaderFactoriesConfig { static SubresourceLoaderFactoriesConfig ForPendingNavigation( NavigationRequest& navigation_request) { SubresourceLoaderFactoriesConfig result; +#if BUILDFLAG(IS_OHOS_PRPP) + result.main_url_ = navigation_request.common_params().url; + result.addr_web_handle_ = navigation_request.GetAddrWebHandle(); +#endif result.origin_ = navigation_request.GetOriginToCommit().value(); result.client_security_state_ = navigation_request.BuildClientSecurityState(); @@ -1285,6 +1289,10 @@ class RenderFrameHostImpl::SubresourceLoaderFactoriesConfig { const SubresourceLoaderFactoriesConfig&) = delete; const url::Origin& origin() const { return origin_; } +#if BUILDFLAG(IS_OHOS_PRPP) + const GURL& main_url() const { return main_url_; } + uint64_t addr_web_handle() const { return addr_web_handle_; } +#endif const net::IsolationInfo& isolation_info() const { return isolation_info_; } network::mojom::ClientSecurityStatePtr GetClientSecurityState() const { @@ -1320,6 +1328,10 @@ class RenderFrameHostImpl::SubresourceLoaderFactoriesConfig { // Private constructor - please go through the static For... methods. SubresourceLoaderFactoriesConfig() = default; +#if BUILDFLAG(IS_OHOS_PRPP) + GURL main_url_; + uint64_t addr_web_handle_; +#endif url::Origin origin_; net::IsolationInfo isolation_info_; network::mojom::ClientSecurityStatePtr client_security_state_; @@ -9735,7 +9747,12 @@ void RenderFrameHostImpl::CommitNavigation( subresource_overrides, blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info, const absl::optional& document_token, - const base::UnguessableToken& devtools_navigation_token) { + const base::UnguessableToken& devtools_navigation_token +#if BUILDFLAG(IS_OHOS_PRPP) + , + uint64_t addr_web_handle +#endif + ) { TRACE_EVENT2("navigation", "RenderFrameHostImpl::CommitNavigation", "navigation_request", navigation_request, "url", common_params->url); @@ -10955,7 +10972,13 @@ RenderFrameHostImpl::CreateURLLoaderFactoryParamsForMainWorld( config.GetClientSecurityState(), config.GetCoepReporter(), GetProcess(), config.trust_token_issuance_policy(), config.trust_token_redemption_policy(), config.cookie_setting_overrides(), - debug_tag); + debug_tag +#if BUILDFLAG(IS_OHOS_PRPP) + , + config.main_url(), + config.addr_web_handle() +#endif + ); } bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve( diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index 42dd13c4dc..325ba17bc8 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h @@ -100,6 +100,7 @@ #include "mojo/public/cpp/system/data_pipe.h" #include "net/base/isolation_info.h" #include "net/base/network_isolation_key.h" +#include "net/base/prp_preload_buildflags.h" #include "net/cookies/cookie_setting_override.h" #include "net/net_buildflags.h" #include "ppapi/buildflags/buildflags.h" @@ -1465,7 +1466,12 @@ class CONTENT_EXPORT RenderFrameHostImpl subresource_overrides, blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info, const absl::optional& document_token, - const base::UnguessableToken& devtools_navigation_token); + const base::UnguessableToken& devtools_navigation_token +#if BUILDFLAG(IS_OHOS_PRPP) + , + uint64_t addr_web_handle +#endif + ); // Indicates that a navigation failed and that this RenderFrame should display // an error page. diff --git a/content/browser/url_loader_factory_params_helper.cc b/content/browser/url_loader_factory_params_helper.cc index fa34def671..dc451e50d3 100644 --- a/content/browser/url_loader_factory_params_helper.cc +++ b/content/browser/url_loader_factory_params_helper.cc @@ -64,7 +64,13 @@ network::mojom::URLLoaderFactoryParamsPtr CreateParams( network::mojom::TrustTokenOperationPolicyVerdict trust_token_redemption_policy, net::CookieSettingOverrides cookie_setting_overrides, - base::StringPiece debug_tag) { + base::StringPiece debug_tag +#if BUILDFLAG(IS_OHOS_PRPP) + , + const GURL& main_url = GURL(), + uint64_t addr_web_handle = 0 +#endif + ) { DCHECK(process); network::mojom::URLLoaderFactoryParamsPtr params = @@ -119,6 +125,11 @@ network::mojom::URLLoaderFactoryParamsPtr CreateParams( params->debug_tag = std::string(debug_tag); +#if BUILDFLAG(IS_OHOS_PRPP) + params->main_url = main_url.spec(); + params->addr_web_handle = addr_web_handle; +#endif + return params; } @@ -139,7 +150,13 @@ URLLoaderFactoryParamsHelper::CreateForFrame( network::mojom::TrustTokenOperationPolicyVerdict trust_token_redemption_policy, net::CookieSettingOverrides cookie_setting_overrides, - base::StringPiece debug_tag) { + base::StringPiece debug_tag +#if BUILDFLAG(IS_OHOS_PRPP) + , + const GURL& main_url, + uint64_t addr_web_handle +#endif + ) { return CreateParams( process, frame_origin, // origin @@ -154,7 +171,13 @@ URLLoaderFactoryParamsHelper::CreateForFrame( frame->CreateURLLoaderNetworkObserver(), NetworkServiceDevToolsObserver::MakeSelfOwned(frame->frame_tree_node()), trust_token_issuance_policy, trust_token_redemption_policy, - cookie_setting_overrides, debug_tag); + cookie_setting_overrides, debug_tag +#if BUILDFLAG(IS_OHOS_PRPP) + , + main_url, + addr_web_handle +#endif + ); } // static diff --git a/content/browser/url_loader_factory_params_helper.h b/content/browser/url_loader_factory_params_helper.h index 3012a6596a..272936c46e 100644 --- a/content/browser/url_loader_factory_params_helper.h +++ b/content/browser/url_loader_factory_params_helper.h @@ -8,12 +8,17 @@ #include "base/strings/string_piece.h" #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/pending_remote.h" +#include "net/base/prp_preload_buildflags.h" #include "services/network/public/mojom/cross_origin_embedder_policy.mojom-forward.h" #include "services/network/public/mojom/early_hints.mojom-forward.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/url_loader.mojom-shared.h" #include "url/origin.h" +#if BUILDFLAG(IS_OHOS_PRPP) +#include "url/gurl.h" +#endif + namespace net { class IsolationInfo; } // namespace net @@ -59,7 +64,13 @@ class URLLoaderFactoryParamsHelper { network::mojom::TrustTokenOperationPolicyVerdict trust_token_redemption_policy, net::CookieSettingOverrides cookie_setting_overrides, - base::StringPiece debug_tag); + base::StringPiece debug_tag +#if BUILDFLAG(IS_OHOS_PRPP) + , + const GURL& main_url = GURL(), + uint64_t addr_web_handle = 0 +#endif + ); // Creates URLLoaderFactoryParams to be used by |isolated_world_origin| hosted // within the |frame|. diff --git a/media/base/ohos/ohos_media_decoder_bridge_impl_unittest.cc b/media/base/ohos/ohos_media_decoder_bridge_impl_unittest.cc index 8c80446537..68ac96b43a 100755 --- a/media/base/ohos/ohos_media_decoder_bridge_impl_unittest.cc +++ b/media/base/ohos/ohos_media_decoder_bridge_impl_unittest.cc @@ -98,6 +98,7 @@ public: MOCK_METHOD(std::string, GetUserAgentBaseOSName, (), (override)); MOCK_METHOD(std::string, GetUserAgentOSVersion, (), (override)); MOCK_METHOD(std::string, GetCompatibleDeviceType, (), (override)); + MOCK_METHOD(std::string, GetPRPPreloadMode, (), (override)); }; class MockWindowAdapter : public WindowAdapter { diff --git a/net/BUILD.gn b/net/BUILD.gn index 00c731028f..64bf80467d 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn @@ -122,6 +122,12 @@ buildflag_header("cronet_buildflags") { flags = [ "CRONET_BUILD=$is_cronet_build" ] } +buildflag_header("prp_preload_buildflags") { + header = "prp_preload_buildflags.h" + header_dir = "net/base" + flags = [ "IS_OHOS_PRPP=$enable_prp_preload" ] +} + component("net") { sources = [ "base/address_family.cc", @@ -1080,6 +1086,7 @@ component("net") { deps = [ ":cronet_buildflags", ":net_deps", + ":prp_preload_buildflags", "//build:chromeos_buildflags", "//net/data/ssl/chrome_root_store:gen_root_store_inc", "//net/http:transport_security_state_generated_files", @@ -1187,7 +1194,12 @@ component("net") { "proxy_resolution/proxy_config_service_ohos.h", ] - deps += [ "//net/prp_preload:prp_preload" ] + if (enable_prp_preload) { + sources += [ + "base/page_res_request_info.cc", + "base/page_res_request_info.h", + ] + } } if (is_chromeos && use_nss_certs) { diff --git a/net/base/page_res_request_info.cc b/net/base/page_res_request_info.cc new file mode 100644 index 0000000000..d089a77296 --- /dev/null +++ b/net/base/page_res_request_info.cc @@ -0,0 +1,87 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/page_res_request_info.h" + +#include "net/url_request/url_request.h" + +namespace ohos_prp_preload { +void PRRequestInfo::InitInfoFromUrlRequest(const net::URLRequest& request) +{ + std::lock_guard cache_info_guard(cache_info_mutex_); + url_ = request.url(); + allow_credentials_ = request.allow_credentials(); + is_for_websockets_ = request.is_for_websockets(); + initiator_ = request.initiator(); + referrer_ = request.referrer(); + method_ = request.method(); + has_storage_access_ = request.has_storage_access(); + extra_request_headers_ = request.extra_request_headers(); + load_flags_ = request.load_flags(); + secure_dns_policy_ = request.secure_dns_policy(); + accepted_stream_types_ = request.accepted_stream_types(); + upgrade_if_insecure_ = request.upgrade_if_insecure(); + send_client_certs_ = request.send_client_certs(); + idempotency_ = request.GetIdempotency(); + force_ignore_site_for_cookies_ = request.force_ignore_site_for_cookies(); + force_main_frame_for_same_site_cookies_ = request.force_main_frame_for_same_site_cookies(); + cookie_setting_overrides_ = request.cookie_setting_overrides(); + referrer_policy_ = request.referrer_policy(); + first_party_url_policy_ = request.first_party_url_policy(); + net_log_ = request.net_log(); + force_ignore_top_frame_party_for_cookies_ = request.force_ignore_top_frame_party_for_cookies(); +} + +// for multi-thread read/write scenarios +CacheInfo PRRequestInfo::cache_info() { + std::lock_guard cache_info_guard(cache_info_mutex_); + return CacheInfo {cache_type_, freshness_life_times_, e_tag_, last_modified_}; +} + +void PRRequestInfo::set_cache_info(PRRequestCacheType cache_type, + int64_t freshness_life_times, + const std::string& e_tag, + const std::string& last_modified) { + std::lock_guard cache_info_guard(cache_info_mutex_); + cache_type_ = cache_type; + freshness_life_times_ = freshness_life_times; + e_tag_ = e_tag; + last_modified_ = last_modified; +} + +void PRRequestInfo::set_request_end_time(int64_t time) +{ + std::lock_guard cache_info_guard(cache_info_mutex_); + req_end_time_ = time; +} + +int64_t PRRequestInfo::request_end_time() const +{ + int64_t req_end_time = 0; + { + std::lock_guard cache_info_guard(cache_info_mutex_); + req_end_time = req_end_time_; + } + return req_end_time > req_start_time_ ? req_end_time : 0; +} + +void PRRequestInfo::set_preload_flag(PRRequestFlags flags) +{ + std::lock_guard cache_info_guard(cache_info_mutex_); + preload_flags_ = flags; +} + +void PRRequestInfo::or_preload_flag(PRRequestFlags flags) +{ + std::lock_guard cache_info_guard(cache_info_mutex_); + preload_flags_ = (PRRequestFlags)(preload_flags_ | flags); +} + +PRRequestFlags PRRequestInfo::preload_flag() const +{ + std::lock_guard cache_info_guard(cache_info_mutex_); + return preload_flags_; +} + +} // namespace ohos_prp_preload \ No newline at end of file diff --git a/net/base/page_res_request_info.h b/net/base/page_res_request_info.h new file mode 100644 index 0000000000..eb37b7e250 --- /dev/null +++ b/net/base/page_res_request_info.h @@ -0,0 +1,267 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_PAGR_RES_REQUEST_INFO_H +#define NET_BASE_PAGR_RES_REQUEST_INFO_H + +#include +#include +#include "net/base/idempotency.h" +#include "net/base/load_flags.h" +#include "net/base/network_anonymization_key.h" +#include "net/cookies/cookie_setting_override.h" +#include "net/dns/public/secure_dns_policy.h" +#include "net/http/http_request_headers.h" +#include "net/log/net_log_with_source.h" +#include "net/url_request/redirect_info.h" + +namespace net { +class URLRequest; +} + +namespace ohos_prp_preload { +#define PRPP_PREFLIGHT_PREFIX "preflight://" + +// Marker if need to establish connection +enum class PRRequestCacheType { + NEGOTIATION_CACHE, // need to establish connection + FORCE_CACHE, // only if cache expires, need to establish connection + DISABLE_CACHE, // need to establish connection +}; + +struct CacheInfo { + PRRequestCacheType cache_type_ { PRRequestCacheType::DISABLE_CACHE }; + int64_t freshness_life_times_ { 0 }; + std::string e_tag_; + std::string last_modified_; +}; + +struct LoaderInfo { + bool corb_detachable_; + int resource_type_; + bool keepalive_; + bool do_not_prompt_for_login_; + int request_mode_; + int request_credentials_mode_; + int request_destination_; +}; + +// Marker for request info type +enum class PRRequestInfoType { + TYPE_DEFAULT, // default request + TYPE_PAGE_ORIGIN, // record page origin + TYPE_PAGE_PREFLIGHT, // preflight request +}; + +// Mark if preload request need to be send +enum PRRequestFlags : uint32_t { + PRPP_FLAGS_NONE, // not visible, do not send preload request + PRPP_FLAGS_HDR_NOT_MATCH = 1 << 0, // header param is unstable, do not send preload request + PRPP_FLAGS_VISIBLE = 1 << 1, // visible, precondition for preload + PRPP_FLAGS_HDR_DYNAMIC = 1 << 2, // header can be predicted, send preload request + PRPP_FLAGS_URL_DYNAMIC = 1 << 3, // URL is dynamic, do not send preload request +}; + +class PRRequestInfo { + public: + PRRequestInfo() = default; + PRRequestInfo(const GURL& url, bool allow_credentials) : + url_(url), allow_credentials_(allow_credentials) {} + void InitInfoFromUrlRequest(const net::URLRequest& request); + ~PRRequestInfo() = default; + + const GURL& url() const { return url_; } + void set_url(const GURL& url) { url_ = url; } + bool allow_credentials() const { return allow_credentials_; } + void set_allow_credentials(bool allow_credentials) { + allow_credentials_ = allow_credentials; + } + PRRequestCacheType cache_type() const { return cache_type_; } + void set_cache_type(PRRequestCacheType cache_type) { cache_type_ = cache_type; } + int64_t freshness_life_times() const { return freshness_life_times_; } + void set_freshness_life_times(int64_t freshness_life_times) { + freshness_life_times_ = freshness_life_times; + } + const std::string& e_tag() const { return e_tag_; } + void set_e_tag(const std::string& e_tag) { e_tag_ = e_tag; } + const std::string& last_modified() const { return last_modified_; } + void set_last_modified(const std::string& last_modified) { + last_modified_ = last_modified; + } + + bool is_for_websockets() const { return is_for_websockets_; } + void set_is_for_websockets(bool is_for_websockets) { is_for_websockets_ = is_for_websockets; } + absl::optional initiator() const { return initiator_; } + void set_initiator(absl::optional initiator) { initiator_ = initiator; } + const std::string& referrer() const { return referrer_; } + void set_referrer(const std::string& referrer) { referrer_ = referrer; } + const std::string& method() const { return method_; } + void set_method(const std::string& method) { method_ = method; } + bool has_storage_access() const { return has_storage_access_; } + void set_has_storage_access(bool has_storage_access) { has_storage_access_ = has_storage_access; } + net::HttpRequestHeaders& extra_request_headers() { return extra_request_headers_; } + void set_extra_request_headers(const net::HttpRequestHeaders& extra_request_headers) { + extra_request_headers_ = extra_request_headers; + } + int load_flags() const { return load_flags_; } + void set_load_flags(int load_flags) { load_flags_ = load_flags; } + net::SecureDnsPolicy secure_dns_policy() const { return secure_dns_policy_; } + void set_secure_dns_policy(net::SecureDnsPolicy secure_dns_policy) { secure_dns_policy_ = secure_dns_policy; } + absl::optional> accepted_stream_types() const { + return accepted_stream_types_; + } + void set_accepted_stream_types(absl::optional> accepted_stream_types) { + accepted_stream_types_ = accepted_stream_types; + } + bool upgrade_if_insecure() const { return upgrade_if_insecure_; } + void set_upgrade_if_insecure(bool upgrade_if_insecure) { upgrade_if_insecure_ = upgrade_if_insecure; } + bool send_client_certs() const { return send_client_certs_; } + void set_send_client_certs(bool send_client_certs) { send_client_certs_ = send_client_certs; } + net::Idempotency idempotency() const { return idempotency_; } + void set_idempotency(net::Idempotency idempotency) { idempotency_ = idempotency; } + bool force_ignore_site_for_cookies() const { return force_ignore_site_for_cookies_; } + void set_force_ignore_site_for_cookies(bool force_ignore_site_for_cookies) { + force_ignore_site_for_cookies_ = force_ignore_site_for_cookies; + } + bool force_main_frame_for_same_site_cookies() const { return force_main_frame_for_same_site_cookies_; } + void set_force_main_frame_for_same_site_cookies(bool force_main_frame_for_same_site_cookies) { + force_main_frame_for_same_site_cookies_ = force_main_frame_for_same_site_cookies; + } + net::CookieSettingOverrides cookie_setting_overrides() const { return cookie_setting_overrides_; } + void set_cookie_setting_overrides(net::CookieSettingOverrides cookie_setting_overrides) { + cookie_setting_overrides_ = cookie_setting_overrides; + } + net::ReferrerPolicy referrer_policy() const { return referrer_policy_; } + void set_referrer_policy(net::ReferrerPolicy referrer_policy) { referrer_policy_ = referrer_policy; } + net::RedirectInfo::FirstPartyURLPolicy first_party_url_policy() const { return first_party_url_policy_; } + void set_first_party_url_policy(net::RedirectInfo::FirstPartyURLPolicy first_party_url_policy) { + first_party_url_policy_ = first_party_url_policy; + } + net::NetLogWithSource net_log() const { return net_log_; } + void set_net_log(net::NetLogWithSource net_log) { net_log_ = net_log; } + bool force_ignore_top_frame_party_for_cookies() const { return force_ignore_top_frame_party_for_cookies_; } + void set_force_ignore_top_frame_party_for_cookies(bool force_ignore_top_frame_party_for_cookies) { + force_ignore_top_frame_party_for_cookies_ = force_ignore_top_frame_party_for_cookies; + } + void set_loader_info(const LoaderInfo& loader_info) { + corb_detachable_ = loader_info.corb_detachable_; + resource_type_ = loader_info.resource_type_; + keepalive_ = loader_info.keepalive_; + do_not_prompt_for_login_ = loader_info.do_not_prompt_for_login_; + request_mode_ = loader_info.request_mode_; + request_credentials_mode_ = loader_info.request_credentials_mode_; + request_destination_ = loader_info.request_destination_; + } + bool corb_detachable() const { return corb_detachable_; } + void set_corb_detachable(bool corb_detachable) { corb_detachable_ = corb_detachable; } + int resource_type() const { return resource_type_; } + void set_resource_type(int resource_type) { resource_type_ = resource_type; } + bool keepalive() const { return keepalive_; } + void set_keepalive(bool keepalive) { keepalive_ = keepalive; } + bool do_not_prompt_for_login() const { return do_not_prompt_for_login_; } + void set_do_not_prompt_for_login(bool do_not_prompt_for_login) { do_not_prompt_for_login_ = do_not_prompt_for_login; } + int request_mode() const { return request_mode_; } + void set_request_mode(int request_mode) { request_mode_ = request_mode; } + int request_credentials_mode() const { return request_credentials_mode_; } + void set_request_credentials_mode(int request_credentials_mode) { + request_credentials_mode_ = request_credentials_mode; + } + int request_destination() const { return request_destination_; } + void set_request_destination(int request_destination) { request_destination_ = request_destination; } + + // for multi-thread read/write scenarios + CacheInfo cache_info(); + void set_cache_info(PRRequestCacheType cache_type, + int64_t freshness_life_times, + const std::string& e_tag, + const std::string& last_modified); + + const PRRequestInfoType& type() const { return type_; } + void set_type(PRRequestInfoType type) { type_ = type; } + const std::string& page_origin() const { return page_origin_; } + void set_page_origin(const std::string& page_origin) { page_origin_ = page_origin; } + bool only_send_reuse_request() const { return only_send_reuse_request_; } + void set_only_send_reuse_request(bool only_send_reuse_request) { only_send_reuse_request_ = only_send_reuse_request; } + const std::set& dynamic_header_keys() { return dynamic_header_keys_; } + void set_dynamic_header_keys(const std::set& dynamic_header_keys) { + dynamic_header_keys_ = dynamic_header_keys; + } + const GURL& parent_for_dynamic_header() { return parent_for_dynamic_header_; } + void set_parent_for_dynamic_header(const GURL& parent_for_dynamic_header) { + parent_for_dynamic_header_ = parent_for_dynamic_header; + } + void set_request_start_time(int64_t time) { req_start_time_ = time; } + int64_t request_start_time() const { return req_start_time_; } + + // for multi-thread read/write scenarios + void set_request_end_time(int64_t time); + int64_t request_end_time() const; + void set_preload_flag(PRRequestFlags flags); + void or_preload_flag(PRRequestFlags flags); + PRRequestFlags preload_flag() const; + private: + mutable std::mutex cache_info_mutex_; // lock for update request info after request start + GURL url_; + bool allow_credentials_ { false }; + PRRequestCacheType cache_type_ { PRRequestCacheType::DISABLE_CACHE }; // updated by network thread, need to lock + int64_t freshness_life_times_ { 0 }; // updated by network thread, need to lock + std::string e_tag_; // updated by network thread, need to lock + std::string last_modified_; // updated by network thread, need to lock + + bool is_for_websockets_ { false }; + absl::optional initiator_; + std::string referrer_; + std::string method_; + bool has_storage_access_ { false }; + net::HttpRequestHeaders extra_request_headers_; + int load_flags_ { net::LOAD_NORMAL }; + net::SecureDnsPolicy secure_dns_policy_ { net::SecureDnsPolicy::kAllow }; + absl::optional> + accepted_stream_types_; + bool upgrade_if_insecure_ { false }; + bool send_client_certs_ { true }; + net::Idempotency idempotency_ { net::DEFAULT_IDEMPOTENCY }; + bool force_ignore_site_for_cookies_ { false }; + bool force_main_frame_for_same_site_cookies_ { false }; + net::CookieSettingOverrides cookie_setting_overrides_; + net::ReferrerPolicy referrer_policy_ { net::ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE }; + net::RedirectInfo::FirstPartyURLPolicy first_party_url_policy_ + { net::RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL }; + bool corb_detachable_ { false }; + int resource_type_ { 0 }; + bool keepalive_ { false }; + bool do_not_prompt_for_login_ { false }; + int request_mode_ { 0 }; + int request_credentials_mode_ { 0 }; + int request_destination_ { 0 }; + net::NetLogWithSource net_log_; + bool force_ignore_top_frame_party_for_cookies_ { false }; + std::string page_origin_; + PRRequestInfoType type_ { PRRequestInfoType::TYPE_DEFAULT }; + bool only_send_reuse_request_ { false }; + int64_t req_start_time_ { 0 }; + int64_t req_end_time_ { 0 }; // updated by network thread, need to lock + PRRequestFlags preload_flags_ { PRRequestFlags::PRPP_FLAGS_NONE }; // updated by network thread, need to lock + GURL parent_for_dynamic_header_; + std::set dynamic_header_keys_; +}; + +struct PRPPPreconnectInfo { + GURL origin_url_; + bool allow_credential_ { false }; + net::NetworkAnonymizationKey net_anonymization_key_; +}; + +using PRPPPreconnectInfoList = std::list; + +struct PRPPReqInfoTreeNode { + PRPPReqInfoTreeNode* parent_ { nullptr }; + std::list> children_; + std::shared_ptr req_info_ { nullptr }; + bool already_preloading_ { false }; +}; + +} // namespace ohos_prp_preload + +#endif // NET_BASE_PAGR_RES_REQUEST_INFO_H \ No newline at end of file diff --git a/net/features.gni b/net/features.gni index 10bc8d313b..7c0e16f58c 100644 --- a/net/features.gni +++ b/net/features.gni @@ -53,6 +53,9 @@ declare_args() { # Platforms for which certificate verification can only be performed using # the builtin cert verifier with the Chrome Root Store. chrome_root_store_only = is_win || is_mac + + # Only support ohos + enable_prp_preload = is_ohos } assert(!chrome_root_store_optional || !chrome_root_store_only, diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc index e681517d40..ce5ca68394 100644 --- a/net/http/http_cache_transaction.cc +++ b/net/http/http_cache_transaction.cc @@ -266,16 +266,9 @@ int HttpCache::Transaction::Start(const HttpRequestInfo* request, // We have to wait until the backend is initialized so we start the SM. next_state_ = STATE_GET_BACKEND; -#if BUILDFLAG(IS_OHOS) - if (ohos_prp_preload::PRParallelPreloadMgr::GetInstance().PRParallelPreloadEnabled()) { - if (request_->allow_preload_record) { - preload_info_ = std::make_shared(request_->url, - request_->privacy_mode == PRIVACY_MODE_DISABLED); - ohos_prp_preload::PRParallelPreloadMgr::GetInstance().UpdateResRequestInfo(request_->main_page.spec(), - preload_info_); - } else { - ohos_prp_preload::PRParallelPreloadMgr::GetInstance().StopMainPage(request_->main_page.spec()); - } +#if BUILDFLAG(IS_OHOS_PRPP) + if (!update_res_request_info_callback_.is_null() && preload_info_) { + update_res_request_info_callback_.Run(request_->main_url.spec(), preload_info_); } #endif @@ -2006,8 +1999,8 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() { return ERR_CACHE_AUTH_FAILURE_AFTER_READ; } -#if BUILDFLAG(IS_OHOS) - if (request_->allow_preload_record && preload_info_ != nullptr && +#if BUILDFLAG(IS_OHOS_PRPP) + if (request_ && request_->allow_preload_record && preload_info_ && !ShouldDisableCaching(*new_response->headers)) { UpdateCacheInfo(*new_response); } @@ -2829,8 +2822,8 @@ int HttpCache::Transaction::BeginCacheValidation() { bool skip_validation = (required_validation == VALIDATION_NONE); bool needs_stale_while_revalidate_cache_update = false; -#if BUILDFLAG(IS_OHOS) - if (request_->allow_preload_record && preload_info_ != nullptr && skip_validation) { +#if BUILDFLAG(IS_OHOS_PRPP) + if (request_ && request_->allow_preload_record && preload_info_ && skip_validation) { UpdateCacheInfo(response_); } #endif @@ -4249,9 +4242,9 @@ void HttpCache::Transaction::EndDiskCacheAccessTimeCount( last_disk_cache_access_start_time_ = TimeTicks(); } -#if BUILDFLAG(IS_OHOS) +#if BUILDFLAG(IS_OHOS_PRPP) void HttpCache::Transaction::UpdateCacheInfo(const HttpResponseInfo& response) { - if (preload_info_ == nullptr) { + if (preload_info_ == nullptr || response.headers == nullptr) { return; } @@ -4260,22 +4253,22 @@ void HttpCache::Transaction::UpdateCacheInfo(const HttpResponseInfo& response) { int64_t freshness_life_times = 0; base::TimeDelta freshnessLifetimes = response.headers-> GetFreshnessLifetimes(response.response_time).freshness; - if (freshnessLifetimes.is_zero()) { - cache_type = ohos_prp_preload::PRRequestCacheType::FORCE_CACHE; - } else { - DCHECK(freshnessLifetimes.is_positive()); + if (!freshnessLifetimes.is_zero()) { freshness_life_times = (response.response_time + freshnessLifetimes - response.headers ->GetCurrentAge(response.request_time, response.response_time, response.response_time)).ToInternalValue(); + cache_type = ohos_prp_preload::PRRequestCacheType::FORCE_CACHE; + } else if (response.headers->HasHeader("etag") || + response.headers->HasHeader("last-modified")) { cache_type = ohos_prp_preload::PRRequestCacheType::NEGOTIATION_CACHE; } std::string e_tag; response.headers->EnumerateHeader(nullptr, "etag", &e_tag); - + std::string last_modified; response.headers->EnumerateHeader(nullptr, "last-modified", &last_modified); diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h index e3dc7eea5a..ab4fca3698 100644 --- a/net/http/http_cache_transaction.h +++ b/net/http/http_cache_transaction.h @@ -37,8 +37,8 @@ #include "net/socket/connection_attempts.h" #include "net/websockets/websocket_handshake_stream_base.h" -#if BUILDFLAG(IS_OHOS) -#include "net/prp_preload/include/page_res_parallel_preload_mgr.h" +#if BUILDFLAG(IS_OHOS_PRPP) +#include "net/base/page_res_request_info.h" #endif namespace crypto { @@ -613,9 +613,18 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { void BeginDiskCacheAccessTimeCount(); void EndDiskCacheAccessTimeCount(DiskCacheAccessType type); -#if BUILDFLAG(IS_OHOS) +#if BUILDFLAG(IS_OHOS_PRPP) + void SetUpdateResRequestInfoCallback( + HttpTransaction::UpdateResRequestInfoCallback callback) override { + update_res_request_info_callback_ = std::move(callback); + } + + void SetPreloadInfo( + const std::shared_ptr& preload_info) override { + preload_info_ = preload_info; + } + void UpdateCacheInfo(const HttpResponseInfo& response); - void UpdateValidatorsInfo(const HttpResponseHeaders& headers); #endif State next_state_{STATE_NONE}; @@ -755,8 +764,9 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { // True if the Transaction is currently processing the DoLoop. bool in_do_loop_ = false; -#if BUILDFLAG(IS_OHOS) +#if BUILDFLAG(IS_OHOS_PRPP) std::shared_ptr preload_info_; + HttpTransaction::UpdateResRequestInfoCallback update_res_request_info_callback_; #endif base::WeakPtrFactory weak_factory_{this}; diff --git a/net/http/http_request_info.h b/net/http/http_request_info.h index 25db06583e..5e62a7de47 100644 --- a/net/http/http_request_info.h +++ b/net/http/http_request_info.h @@ -13,6 +13,7 @@ #include "net/base/network_anonymization_key.h" #include "net/base/network_isolation_key.h" #include "net/base/privacy_mode.h" +#include "net/base/prp_preload_buildflags.h" #include "net/base/request_priority.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/http_request_headers.h" @@ -119,10 +120,10 @@ struct NET_EXPORT HttpRequestInfo { // number once set. absl::optional browser_run_id; -#if BUILDFLAG(IS_OHOS) +#if BUILDFLAG(IS_OHOS_PRPP) bool allow_preload_record = true; - GURL main_page; + GURL main_url; #endif }; diff --git a/net/http/http_transaction.h b/net/http/http_transaction.h index bf59d6f6b6..a47a628f68 100644 --- a/net/http/http_transaction.h +++ b/net/http/http_transaction.h @@ -12,6 +12,7 @@ #include "net/base/load_states.h" #include "net/base/net_error_details.h" #include "net/base/net_export.h" +#include "net/base/prp_preload_buildflags.h" #include "net/base/request_priority.h" #include "net/base/upload_progress.h" #include "net/http/http_raw_request_headers.h" @@ -19,6 +20,12 @@ #include "net/socket/connection_attempts.h" #include "net/websockets/websocket_handshake_stream_base.h" +#if BUILDFLAG(IS_OHOS_PRPP) +namespace ohos_prp_preload { +class PRRequestInfo; +} +#endif + namespace net { class AuthCredentials; @@ -60,6 +67,12 @@ class NET_EXPORT_PRIVATE HttpTransaction { base::RepeatingCallback; +#if BUILDFLAG(IS_OHOS_PRPP) + using UpdateResRequestInfoCallback = + base::RepeatingCallback& info)>; +#endif + // Stops any pending IO and destroys the transaction object. virtual ~HttpTransaction() = default; @@ -219,6 +232,13 @@ class NET_EXPORT_PRIVATE HttpTransaction { // byte of the response body has been read, as the connection is no longer in // use at that point. virtual void CloseConnectionOnDestruction() = 0; + +#if BUILDFLAG(IS_OHOS_PRPP) + virtual void SetUpdateResRequestInfoCallback( + HttpTransaction::UpdateResRequestInfoCallback callback) { } + virtual void SetPreloadInfo( + const std::shared_ptr& preload_info) { } +#endif }; } // namespace net diff --git a/net/prp_preload/include/page_res_parallel_preload_mgr.h b/net/prp_preload/include/page_res_parallel_preload_mgr.h deleted file mode 100644 index 3323ed6425..0000000000 --- a/net/prp_preload/include/page_res_parallel_preload_mgr.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_PRP_PRELOAD_INCLUDE_PAGR_RES_PARALLEL_PRELOAD_MGR_H -#define NET_PRP_PRELOAD_INCLUDE_PAGR_RES_PARALLEL_PRELOAD_MGR_H - -#include "base/task/thread_pool.h" -#include "net/base/network_anonymization_key.h" -#include "page_res_request_info.h" - -namespace net { -class URLRequestContext; -} // namespace net - -namespace ohos_prp_preload { -class PRParallelPreloadMgr { - public: - static PRParallelPreloadMgr& GetInstance(); - static bool PRParallelPreloadEnabled(); - virtual ~PRParallelPreloadMgr() = default; - virtual void Init(const scoped_refptr& net_task_runner) = 0; - virtual void StartMainPage(const std::string& url, const net::NetworkAnonymizationKey& networkAnonymizationKey, - base::WeakPtr url_request_context, - uint64_t addr_web_handle) = 0; - virtual void StopMainPage(const std::string& url) = 0; - virtual void StopMainPage(uint64_t addr_web_handle) = 0; - virtual void UpdateResRequestInfo(const std::string& key, - const std::shared_ptr& info) = 0; -}; - -} // namespace ohos_prp_preload - -#endif // NET_PRP_PRELOAD_INCLUDE_PAGR_RES_PARALLEL_PRELOAD_MGR_H diff --git a/net/prp_preload/include/page_res_request_info.h b/net/prp_preload/include/page_res_request_info.h deleted file mode 100644 index aa90508c74..0000000000 --- a/net/prp_preload/include/page_res_request_info.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_PRP_PRELOAD_INCLUDE_PAGR_RES_REQUEST_INFO_H -#define NET_PRP_PRELOAD_INCLUDE_PAGR_RES_REQUEST_INFO_H - -#include -#include "url/gurl.h" - -namespace ohos_prp_preload { -enum PRRequestCacheType { - NEGOTIATION_CACHE, - FORCE_CACHE, - DISABLE_CACHE, -}; -struct CacheInfo { - PRRequestCacheType cache_type = PRRequestCacheType::DISABLE_CACHE; - int64_t freshness_life_times = 0; - std::string e_tag; - std::string last_modified; -}; -class PRRequestInfo { - public: - PRRequestInfo() = default; - PRRequestInfo(const GURL& url, bool allow_credentials) : - url_(url), allow_credentials_(allow_credentials) {} - ~PRRequestInfo() = default; - - const GURL& url() const { return url_; } - void set_url(const GURL& url) { url_ = url; } - bool allow_credentials() const { return allow_credentials_; } - void set_allow_credentials(bool allow_credentials) { - allow_credentials_ = allow_credentials; - } - PRRequestCacheType cache_type() const { return cache_type_; } - void set_cache_type(PRRequestCacheType cache_type) { cache_type_ = cache_type; } - int64_t freshness_life_times() const { return freshness_life_times_; } - void set_freshness_life_times(int64_t freshness_life_times) { - freshness_life_times_ = freshness_life_times; - } - const std::string& e_tag() const { return e_tag_; } - void set_e_tag(const std::string& e_tag) { e_tag_ = e_tag; } - const std::string& last_modified() const { return last_modified_; } - void set_last_modified(const std::string& last_modified) { - last_modified_ = last_modified; - } - - // for multi-thread read/write scenarios - CacheInfo cache_info() { - std::lock_guard cache_info_guard(cache_info_mutex_); - return CacheInfo {cache_type_, freshness_life_times_, e_tag_, last_modified_}; - } - void set_cache_info(PRRequestCacheType cache_type, - int64_t freshness_life_times, - const std::string& e_tag, - const std::string& last_modified) { - std::lock_guard cache_info_guard(cache_info_mutex_); - cache_type_ = cache_type; - freshness_life_times_ = freshness_life_times; - e_tag_ = e_tag; - last_modified_ = last_modified; - } - - private: - std::mutex cache_info_mutex_; - GURL url_ = GURL::EmptyGURL(); - bool allow_credentials_ = false; - PRRequestCacheType cache_type_ = PRRequestCacheType::DISABLE_CACHE; - int64_t freshness_life_times_ = 0; - std::string e_tag_; - std::string last_modified_; -}; - -} // namespace ohos_prp_preload - -#endif // NET_PRP_PRELOAD_INCLUDE_PAGR_RES_REQUEST_INFO_H diff --git a/net/prp_preload/src/res_preload_scheduler.cc b/net/prp_preload/src/res_preload_scheduler.cc deleted file mode 100644 index 75b79d77c9..0000000000 --- a/net/prp_preload/src/res_preload_scheduler.cc +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "res_preload_scheduler.h" - -#include "base/logging.h" -#include "preconnect_runner.h" -#include "url/origin.h" - -namespace { -constexpr uint8_t SOCKET_LIMIT = 30; -constexpr uint8_t DELAYED_TIME = 5; -constexpr uint8_t MAX_PRECONNECT_NUM = 6; -const std::string PRIVACY_TAG = "ac/"; -} // namespace - -namespace ohos_prp_preload { - -ResPreloadScheduler::ResPreloadScheduler(const scoped_refptr& sth_task_runner, - const scoped_refptr& net_task_runner, - base::WeakPtr url_request_context) : - sth_task_runner_(sth_task_runner), net_task_runner_(net_task_runner), url_request_context_(url_request_context) {} - -void ResPreloadScheduler::PreloadSchedule( - const std::list>& res_req_info_list, - const net::NetworkAnonymizationKey& networkAnonymizationKey) { - LOG(DEBUG) << "PRPPreload.ResPreloadScheduler::PreloadSchedule " << res_req_info_list.size(); - if (preload_triggered_) { - LOG(DEBUG) << "PRPPreload.ResPreloadScheduler::PreloadSchedule called more than once"; - return; - } - preload_triggered_ = true; - info_list_ = res_req_info_list; - ++info_list_version_; - socket_connected_ = 0; - InfoIter iter = info_list_.begin(); - - while (iter != info_list_.end()) { - auto info = *iter; - if (info->cache_type() != PRRequestCacheType::NEGOTIATION_CACHE || - base::Time::Now().ToInternalValue() > info->freshness_life_times()) { - if (socket_connected_ <= SOCKET_LIMIT) { - auto url = url::Origin::Create(info->url()); - if (NeedToPreconnect(url.GetURL(), info->allow_credentials()) && net_task_runner_ != nullptr) { - ++socket_connected_; - net_task_runner_->PostTask(FROM_HERE, base::BindOnce(&PreconnectRunner::PreconnectSocket, - url.GetURL(), info->allow_credentials(), url_request_context_, - networkAnonymizationKey)); - } - } else { - if (sth_task_runner_ != nullptr) { - sth_task_runner_->PostDelayedTask(FROM_HERE, - base::BindOnce(&ResPreloadScheduler::PreconnectBeyondLimit, weak_factory_.GetWeakPtr(), - iter, info_list_version_, networkAnonymizationKey), base::Milliseconds(DELAYED_TIME)); - } - return; - } - } - ++iter; - } -} - -void ResPreloadScheduler::StopPreload() { - preload_triggered_ = false; - info_list_.clear(); - idle_connect_list_.clear(); -} - -bool ResPreloadScheduler::NeedToPreconnect(const GURL& url, bool allow_credentials) { - std::string info = allow_credentials ? PRIVACY_TAG + url.spec() : url.spec(); - auto it = idle_connect_list_.find(info); - if (it != idle_connect_list_.end()) { - return --it->second > 0 ? true : false; - } else { - idle_connect_list_[info] = MAX_PRECONNECT_NUM; - return true; - } -} - -void ResPreloadScheduler::PreconnectBeyondLimit(InfoIter info_iter, - const int info_list_version, - const net::NetworkAnonymizationKey& networkAnonymizationKey) { - if (info_list_version != info_list_version_ || info_iter == info_list_.end() || - !preload_triggered_) { - return; - } - - auto info = *info_iter; - if (info != nullptr && (info->cache_type() != PRRequestCacheType::NEGOTIATION_CACHE || - base::Time::Now().ToInternalValue() > info->freshness_life_times())) { - auto url = url::Origin::Create(info->url()); - if (NeedToPreconnect(url.GetURL(), info->allow_credentials()) && net_task_runner_ != nullptr) { - ++socket_connected_; - net_task_runner_->PostTask(FROM_HERE, base::BindOnce(&PreconnectRunner::PreconnectSocket, - url.GetURL(), info->allow_credentials(), url_request_context_, - networkAnonymizationKey)); - } - } - ++info_iter; - if (sth_task_runner_ != nullptr && info_iter != info_list_.end()) { - sth_task_runner_->PostDelayedTask(FROM_HERE, - base::BindOnce(&ResPreloadScheduler::PreconnectBeyondLimit, weak_factory_.GetWeakPtr(), - info_iter, info_list_version, networkAnonymizationKey), base::Milliseconds(DELAYED_TIME)); - } -} - -} // namespace ohos_prp_preload \ No newline at end of file diff --git a/net/prp_preload/src/res_request_info_updater.cc b/net/prp_preload/src/res_request_info_updater.cc deleted file mode 100644 index 4ff6f191b5..0000000000 --- a/net/prp_preload/src/res_request_info_updater.cc +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "res_request_info_updater.h" - -#include "base/logging.h" - -namespace ohos_prp_preload { -ResRequestInfoUpdater::ResRequestInfoUpdater(const std::string& url, - const net::NetworkAnonymizationKey& networkAnonymizationKey, - const scoped_refptr& sth_task_runner, - const scoped_refptr& disk_cache_backend_factory, - const ResRequestInfoListCB& res_req_info_list_cb) : - res_req_info_list_cb_(res_req_info_list_cb) { - res_req_info_cache_mgr_ = base::WrapRefCounted(new (std::nothrow) ResReqInfoCacheMgr(url, networkAnonymizationKey, - sth_task_runner, disk_cache_backend_factory, - base::BindRepeating(&ResRequestInfoUpdater::OnResRequestInfoCacheLoaded, weak_factory_.GetWeakPtr()))); - if (res_req_info_cache_mgr_ == nullptr) { - LOG(ERROR) << "PRPPreload.ResRequestInfoUpdater::ResRequestInfoUpdater new ResReqInfoCacheMgr failed"; - } -} - -void ResRequestInfoUpdater::Start() { - if (res_req_info_cache_mgr_ == nullptr) { - return; - } - res_req_info_cache_mgr_->Start(); -} - -void ResRequestInfoUpdater::UpdateResRequestInfo(const std::shared_ptr& info) { - if (res_req_info_cache_mgr_ == nullptr) { - return; - } - res_req_info_cache_mgr_->UpdateResRequestInfo(info); -} - -void ResRequestInfoUpdater::Stop() { - if (res_req_info_cache_mgr_ == nullptr) { - return; - } - res_req_info_cache_mgr_->Stop(); -} - -void ResRequestInfoUpdater::OnResRequestInfoCacheLoaded(const std::list>& load_info_list, - const net::NetworkAnonymizationKey& networkAnonymizationKey) { - if (!res_req_info_list_cb_.is_null()) { - res_req_info_list_cb_.Run(load_info_list, networkAnonymizationKey); - } -} - -} // namespace ohos_prp_preload diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index f9c3794941..1a588e14ab 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h @@ -33,6 +33,7 @@ #include "net/base/net_export.h" #include "net/base/network_delegate.h" #include "net/base/proxy_server.h" +#include "net/base/prp_preload_buildflags.h" #include "net/base/request_priority.h" #include "net/base/upload_progress.h" #include "net/cookies/canonical_cookie.h" @@ -58,6 +59,11 @@ #include "url/gurl.h" #include "url/origin.h" +#if BUILDFLAG(IS_OHOS_PRPP) +#include "net/base/page_res_request_info.h" +#include "net/http/http_transaction.h" +#endif + namespace net { class CookieOptions; @@ -854,12 +860,24 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { } bool has_storage_access() const { return has_storage_access_; } -#if BUILDFLAG(IS_OHOS) +#if BUILDFLAG(IS_OHOS_PRPP) + void set_update_res_request_info_callback(HttpTransaction::UpdateResRequestInfoCallback callback) { + update_res_request_info_callback_ = callback; + } + HttpTransaction::UpdateResRequestInfoCallback update_res_request_info_callback() { + return update_res_request_info_callback_; + } + void set_allow_preload_record(bool allow) { allow_preload_record_ = allow; } bool allow_preload_record() const { return allow_preload_record_; } - void set_main_page(const GURL& url) { main_page_ = url; } - const GURL& main_page() const { return main_page_; } + void set_main_url(const GURL& url) { main_url_ = url; } + const GURL& main_url() const { return main_url_; } + + void set_preload_info(const std::shared_ptr& preload_info) { + preload_info_ = preload_info; + } + std::shared_ptr preload_info() const { return preload_info_; } #endif static bool DefaultCanUseCookies(); @@ -1135,9 +1153,11 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // Idempotency of the request. Idempotency idempotency_ = DEFAULT_IDEMPOTENCY; -#if BUILDFLAG(IS_OHOS) +#if BUILDFLAG(IS_OHOS_PRPP) + HttpTransaction::UpdateResRequestInfoCallback update_res_request_info_callback_; bool allow_preload_record_ = false; - GURL main_page_; + GURL main_url_; + std::shared_ptr preload_info_; #endif THREAD_CHECKER(thread_checker_); diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc index b080d5133b..cfff4445e6 100644 --- a/net/url_request/url_request_context.cc +++ b/net/url_request/url_request_context.cc @@ -131,6 +131,20 @@ std::unique_ptr URLRequestContext::CreateRequest( traffic_annotation, is_for_websockets, net_log_source); } +#if BUILDFLAG(IS_OHOS_PRPP) +std::shared_ptr URLRequestContext::CreateRequestForPrpp( + const GURL& url, + RequestPriority priority, + URLRequest::Delegate* delegate, + NetworkTrafficAnnotationTag traffic_annotation, + bool is_for_websockets, + const absl::optional net_log_source) const { + return std::make_shared( + base::PassKey(), url, priority, delegate, this, + traffic_annotation, is_for_websockets, net_log_source); +} +#endif + void URLRequestContext::AssertNoURLRequests() const { int num_requests = url_requests_->size(); if (num_requests != 0) { diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h index a9853aec7b..ccbc38b6e3 100644 --- a/net/url_request/url_request_context.h +++ b/net/url_request/url_request_context.h @@ -124,6 +124,17 @@ class NET_EXPORT URLRequestContext final { const absl::optional net_log_source = absl::nullopt) const; +#if BUILDFLAG(IS_OHOS_PRPP) + std::shared_ptr CreateRequestForPrpp( + const GURL& url, + RequestPriority priority, + URLRequest::Delegate* delegate, + NetworkTrafficAnnotationTag traffic_annotation, + bool is_for_websockets = false, + const absl::optional net_log_source = + absl::nullopt) const; +#endif + NetLog* net_log() const { return net_log_; } HostResolver* host_resolver() const { return host_resolver_.get(); } diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 5141bfdf1a..4e6f417981 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc @@ -99,6 +99,10 @@ #include "net/android/network_library.h" #endif +#if BUILDFLAG(IS_OHOS_PRPP) +#include "net/base/page_res_request_info.h" +#endif + namespace { base::Value::Dict CookieInclusionStatusNetLogParams( @@ -274,9 +278,9 @@ void URLRequestHttpJob::Start() { request_info_.pervasive_payloads_index_for_logging = request_->pervasive_payloads_index_for_logging(); request_info_.checksum = request_->expected_response_checksum(); -#if BUILDFLAG(IS_OHOS) +#if BUILDFLAG(IS_OHOS_PRPP) request_info_.allow_preload_record = request_->allow_preload_record(); - request_info_.main_page = request_->main_page(); + request_info_.main_url = request_->main_url(); #endif #if BUILDFLAG(ENABLE_REPORTING) request_info_.reporting_upload_depth = request_->reporting_upload_depth(); @@ -592,6 +596,13 @@ void URLRequestHttpJob::StartTransactionInternal() { if (!throttling_entry_.get() || !throttling_entry_->ShouldRejectRequest(*request_)) { +#if BUILDFLAG(IS_OHOS_PRPP) + if (!request_->update_res_request_info_callback().is_null() && request_->preload_info()) { + request_->preload_info()->InitInfoFromUrlRequest(*request_); + transaction_->SetUpdateResRequestInfoCallback(request_->update_res_request_info_callback()); + transaction_->SetPreloadInfo(request_->preload_info()); + } +#endif rv = transaction_->Start( &request_info_, base::BindOnce(&URLRequestHttpJob::OnStartCompleted, diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn index b52e377869..e041756ddf 100644 --- a/services/network/BUILD.gn +++ b/services/network/BUILD.gn @@ -304,6 +304,7 @@ component("network_service") { "//mojo/public/cpp/system", "//net", "//net:extras", + "//net:prp_preload_buildflags", "//services/network/attribution", "//services/network/first_party_sets:first_party_sets_manager", "//services/network/public/cpp", @@ -324,6 +325,10 @@ component("network_service") { ] } + if (enable_prp_preload) { + deps += [ "//services/network/prp_preload:prp_preload", ] + } + public_deps = [ "//services/network/public/cpp:buildflags" ] if (is_ct_supported) { @@ -510,6 +515,7 @@ source_set("tests") { "//mojo/public/cpp/test_support:test_utils", "//net", "//net:extras", + "//net:prp_preload_buildflags", "//net:quic_test_tools", "//net:simple_quic_tools", "//net:test_support", @@ -540,6 +546,10 @@ source_set("tests") { deps += [ "//components/certificate_transparency" ] } + if (enable_prp_preload) { + deps += [ "//services/network/prp_preload:prp_preload", ] + } + if (use_blink) { deps += [ "//services/proxy_resolver:lib" ] } diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc index 163e2fb36d..4b23bd5ffc 100644 --- a/services/network/cors/cors_url_loader.cc +++ b/services/network/cors/cors_url_loader.cc @@ -784,6 +784,10 @@ void CorsURLLoader::StartRequest() { // Since we're doing a preflight, we won't reuse the original request. Cancel // it now to free up the socket. +#if BUILDFLAG(IS_OHOS) + // for prp_preload performance tools, preflight request + TRACE_EVENT1("net", "CorsURLLoader::StartRequest", "id", request_id_); +#endif network_loader_.reset(); context_->cors_preflight_controller()->PerformPreflightCheck( diff --git a/services/network/cors/cors_url_loader_factory.cc b/services/network/cors/cors_url_loader_factory.cc index ae4d0157c5..1aa47b9bd6 100644 --- a/services/network/cors/cors_url_loader_factory.cc +++ b/services/network/cors/cors_url_loader_factory.cc @@ -284,6 +284,10 @@ void CorsURLLoaderFactory::CreateLoaderAndStart( const ResourceRequest& resource_request, mojo::PendingRemote client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { +#if BUILDFLAG(IS_OHOS) + // for prp_preload performance tools, kernel request + TRACE_EVENT1("net", "CorsURLLoaderFactory::CreateLoaderAndStart", "id", request_id); +#endif debug::ScopedResourceRequestCrashKeys request_crash_keys(resource_request); SCOPED_CRASH_KEY_NUMBER("net", "traffic_annotation_hash", traffic_annotation.unique_id_hash_code); diff --git a/services/network/cors/preflight_controller.cc b/services/network/cors/preflight_controller.cc index b25d2ef02a..979671e9e5 100644 --- a/services/network/cors/preflight_controller.cc +++ b/services/network/cors/preflight_controller.cc @@ -148,6 +148,12 @@ std::unique_ptr CreatePreflightRequest( preflight_request->resource_type = request.resource_type; preflight_request->fetch_window_id = request.fetch_window_id; +#if BUILDFLAG(IS_OHOS_PRPP) + preflight_request->allow_preload_record = request.allow_preload_record; + preflight_request->main_url = request.main_url; + preflight_request->is_preflight = true; +#endif + preflight_request->headers.SetHeader(net::HttpRequestHeaders::kAccept, kDefaultAcceptHeaderValue); diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 681cd80702..1da7b1b1a9 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc @@ -180,9 +180,9 @@ #include "base/android/application_status_listener.h" #endif // BUILDFLAG(IS_ANDROID) -#if BUILDFLAG(IS_OHOS) -#include "net/prp_preload/include/page_res_parallel_preload_mgr.h" -#endif // BUILDFLAG(IS_OHOS) +#if BUILDFLAG(IS_OHOS_PRPP) +#include "services/network/prp_preload/include/page_res_parallel_preload_mgr.h" +#endif // BUILDFLAG(IS_OHOS_PRPP) namespace network { @@ -717,9 +717,29 @@ void NetworkContext::CreateURLLoaderFactory( mojo::PendingReceiver receiver, mojom::URLLoaderFactoryParamsPtr params, scoped_refptr resource_scheduler_client) { +#if BUILDFLAG(IS_OHOS_PRPP) + if (ohos_prp_preload::PRParallelPreloadMgr::GetInstance().GetPRParallelPreloadMode() != + ohos_prp_preload::PRPPreloadMode::PRELOAD || !params) { +#endif url_loader_factories_.emplace(std::make_unique( this, std::move(params), std::move(resource_scheduler_client), std::move(receiver), &cors_origin_access_list_)); +#if BUILDFLAG(IS_OHOS_PRPP) + return; + } + auto main_url = params->main_url; + auto addr_web_handle = params->addr_web_handle; + net::IsolationInfo isolation_info(params->isolation_info); + auto url_loader_factory = std::make_unique( + this, std::move(params), std::move(resource_scheduler_client), + std::move(receiver), &cors_origin_access_list_); + url_loader_factories_.emplace(std::move(url_loader_factory)); + if (addr_web_handle != 0 && !main_url.empty()) { + if (isolation_info.frame_origin().has_value()) { + ohos_prp_preload::PRParallelPreloadMgr::GetInstance().SetPageOrigin(main_url, isolation_info); + } + } +#endif } void NetworkContext::CreateURLLoaderFactoryForCertNetFetcher( @@ -1794,19 +1814,23 @@ void NetworkContext::ClearHostIP(const std::string& host_name) { } #endif -#if BUILDFLAG(IS_OHOS) +#if BUILDFLAG(IS_OHOS_PRPP) void NetworkContext::InitPRParallelPreloadMgr() { ohos_prp_preload::PRParallelPreloadMgr::GetInstance().Init(base::SingleThreadTaskRunner::GetCurrentDefault()); } -void NetworkContext::StartMainPage(const std::string& url, - const net::NetworkAnonymizationKey& networkAnonymizationKey, uint64_t addr_web_handle) { - ohos_prp_preload::PRParallelPreloadMgr::GetInstance().StartMainPage(url, - networkAnonymizationKey, url_request_context()->GetWeakPtr(), addr_web_handle); +void NetworkContext::StartPage(const std::string& url, uint64_t addr_web_handle, + StartPageCallback page_origin_cb) { + ohos_prp_preload::PRParallelPreloadMgr::GetInstance().StartPage(url, + url_request_context()->GetWeakPtr(), weak_factory_.GetWeakPtr(), addr_web_handle, std::move(page_origin_cb)); +} + +void NetworkContext::StopPage(uint64_t addr_web_handle) { + ohos_prp_preload::PRParallelPreloadMgr::GetInstance().StopPage(addr_web_handle); } -void NetworkContext::StopMainPage(uint64_t addr_web_handle) { - ohos_prp_preload::PRParallelPreloadMgr::GetInstance().StopMainPage(addr_web_handle); +void NetworkContext::SetParam(mojom::URLLoaderFactoryParamsPtr params) { + ohos_prp_preload::PRParallelPreloadMgr::GetInstance().SetURLLoaderFactoryParam(std::move(params)); } #endif diff --git a/services/network/network_context.h b/services/network/network_context.h index 4256ddcf6f..ef2ce6f458 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h @@ -34,6 +34,7 @@ #include "mojo/public/cpp/bindings/remote_set.h" #include "mojo/public/cpp/bindings/unique_receiver_set.h" #include "net/base/network_isolation_key.h" +#include "net/base/prp_preload_buildflags.h" #include "net/cert/cert_verifier.h" #include "net/cert/cert_verify_result.h" #include "net/cookies/cookie_setting_override.h" @@ -412,11 +413,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext uint32_t alive_time) override; void ClearHostIP(const std::string& host_name) override; #endif -#if BUILDFLAG(IS_OHOS) +#if BUILDFLAG(IS_OHOS_PRPP) void InitPRParallelPreloadMgr() override; - void StartMainPage(const std::string& url, - const net::NetworkAnonymizationKey& networkAnonymizationKey, uint64_t addr_web_handle) override; - void StopMainPage(uint64_t addr_web_handle) override; + void StartPage(const std::string& url, uint64_t addr_web_handle, + StartPageCallback page_origin_cb) override; + void StopPage(uint64_t addr_web_handle) override; + void SetParam(mojom::URLLoaderFactoryParamsPtr params) override; #endif void CreateHostResolver( const absl::optional& config_overrides, diff --git a/net/prp_preload/BUILD.gn b/services/network/prp_preload/BUILD.gn similarity index 59% rename from net/prp_preload/BUILD.gn rename to services/network/prp_preload/BUILD.gn index fb6dbcb4de..0be6c00155 100644 --- a/net/prp_preload/BUILD.gn +++ b/services/network/prp_preload/BUILD.gn @@ -4,17 +4,16 @@ import("//build/buildflag_header.gni") -buildflag_header("buildflags") { - header = "buildflags.h" -} - source_set("prp_preload") { visibility = [ - "//net:net", - "//cef:make_pack_header_resources" + "//services/network:network_service", + "//services/network:tests", ] - include_dirs = [ "//net/prp_preload/include" ] + include_dirs = [ + "//services/network/prp_preload/include", + "//services/network/prp_preload/include/preload_runner", + ] deps = [ "//base", @@ -24,9 +23,12 @@ source_set("prp_preload") { sources = [ "src/disk_cache_backend_factory.cc", "src/disk_cache_file.cc", + "src/disk_cache_info_parser.cc", "src/page_res_parallel_preload_mgr_impl.cc", + "src/preload_runner/preconnect_runner.cc", + "src/preload_runner/prpp_request_loader_factory_impl.cc", + "src/preload_runner/prpp_request_loader_impl.cc", "src/res_parallel_preload_ctrler.cc", - "src/preconnect_runner.cc", "src/res_preload_scheduler.cc", "src/res_request_info_cache_mgr.cc", "src/res_request_info_updater.cc", diff --git a/services/network/prp_preload/include/page_res_parallel_preload_mgr.h b/services/network/prp_preload/include/page_res_parallel_preload_mgr.h new file mode 100644 index 0000000000..795bff186b --- /dev/null +++ b/services/network/prp_preload/include/page_res_parallel_preload_mgr.h @@ -0,0 +1,78 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_NETWORK_PRP_PRELOAD_INCLUDE_PAGE_RES_PARALLEL_PRELOAD_MGR_H +#define SERVICES_NETWORK_PRP_PRELOAD_INCLUDE_PAGE_RES_PARALLEL_PRELOAD_MGR_H + +#include "base/task/thread_pool.h" +#include "services/network/public/mojom/network_context.mojom.h" + +namespace net { +class URLRequestContext; +} // namespace net + +namespace network { +class NetworkContext; +} // namespace network + +namespace ohos_prp_preload { +class PRRequestInfo; +class PRPPRequestLoaderFactory; +enum class PRPPreloadMode { + NONE, // close preload + PRECONNECT, // only preconnect + PRELOAD, // preconnect and prevalidate +}; +using PageOriginCallback = base::OnceCallback; +class PRParallelPreloadMgr { + public: + // get single instance of PRParallelPreloadMgr + static PRParallelPreloadMgr& GetInstance(); + + // get preload mode: none, preconnect or preload + static PRPPreloadMode GetPRParallelPreloadMode(); + + // destroy the PRParallelPreloadMgr object + virtual ~PRParallelPreloadMgr() = default; + + // init preload module, load preload info cache index and start preload thread + virtual void Init(const scoped_refptr& net_task_runner) = 0; + + // start preload page sub_request + virtual void StartPage(const std::string& url, + base::WeakPtr url_request_context, + base::WeakPtr network_context, + uint64_t addr_web_handle, + PageOriginCallback callback) = 0; + + // stop preload page + virtual void StopPage(uint64_t addr_web_handle) = 0; + + // update preload request info + virtual void UpdateResRequestInfo(const std::string& key, + const std::shared_ptr& info) = 0; + + // update preload url for redirect page + virtual void UpdateRedirectUrl(const std::string& org_url, + const std::string& redirect_url, + bool replace = false) = 0; + + // set URLLoaderFactoryParam, update isolation info + virtual void SetURLLoaderFactoryParam(network::mojom::URLLoaderFactoryParamsPtr params) = 0; + + // set isolation info and origin + virtual void SetPageOrigin(const std::string& url, const net::IsolationInfo& isl) = 0; + + // excute callback NavigationRequest::OnGetIsolation, create isolation info and set + // callback by ResPreloadScheduler + virtual void OnPageOrigin(const std::string& url, const std::string& page_origin) = 0; + + // get PRPPRequestLoaderFactory for page + virtual base::WeakPtr GetRequestLoaderFactory( + const std::string& main_url) = 0; +}; + +} // namespace ohos_prp_preload + +#endif // SERVICES_NETWORK_PRP_PRELOAD_INCLUDE_PAGE_RES_PARALLEL_PRELOAD_MGR_H diff --git a/services/network/prp_preload/include/preload_runner/prpp_request_loader.h b/services/network/prp_preload/include/preload_runner/prpp_request_loader.h new file mode 100644 index 0000000000..176381af10 --- /dev/null +++ b/services/network/prp_preload/include/preload_runner/prpp_request_loader.h @@ -0,0 +1,85 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_NETWORK_PRP_PRELOAD_INCLUDE_PRELOAD_RUNNER_PRPP_REQUEST_LOADER_H +#define SERVICES_NETWORK_PRP_PRELOAD_INCLUDE_PRELOAD_RUNNER_PRPP_REQUEST_LOADER_H + +#include "net/url_request/url_request.h" + +namespace net { +class URLRequestContext; +} // namespace net + +// only run in network thread +namespace ohos_prp_preload { +class PRPPRequestLoader; +class PRRequestInfo; +using ResPreloadedCB = base::OnceCallback; + +constexpr int32_t PRPP_ERROR = -3000; // considering range of NET_ERROR in "net/base/net_error_list.h" +class PRPPRequestLoader { + public: + enum PRPPReqLoaderState : uint8_t { + STATE_IDLE, + STATE_CONNECTED, + STATE_REQ_SENT, + STATE_ERALY_HEAD_RESPONSED, + STATE_HEAD_RESPONSED, + STATE_RESPONSE_STARTED, + STATE_RESPONSED, + STATE_UNSUPPORT, + STATE_ERROR, + }; + + // create PRPPRequestLoader + static std::shared_ptr CreatePRPPRequestLoader( + const std::string& main_url, + const std::shared_ptr& info, + const net::IsolationInfo& isolation_info, + base::WeakPtr url_request_context, + ResPreloadedCB res_loaded_cb); + + // destroy the PRPPRequestLoader object + virtual ~PRPPRequestLoader() = default; + + // init and start preload request + virtual bool Init(const net::IsolationInfo& isolation_info) = 0; + + // binding the url loader of formal request + virtual void SetRequestDelegate(net::URLRequest::Delegate* delegate) = 0; + + // start replay recorded message + virtual bool StartReplay() = 0; + + // set the RequestHeadersCallback of formal request + virtual void SetRequestHeadersCallback(net::RequestHeadersCallback callback) = 0; + + // set the ResponseHeadersCallback of formal request + virtual void SetResponseHeadersCallback(net::ResponseHeadersCallback callback) = 0; + + // set the EarlyResponseHeadersCallback of formal request + virtual void SetEarlyResponseHeadersCallback(net::ResponseHeadersCallback callback) = 0; + + // read response body to the buffer of formal request + virtual int Read(net::IOBuffer* buf, int max_bytes) = 0; + + // get preload URLRequest + virtual std::shared_ptr GetURLRequest() = 0; + + // get PRRequestInfo + virtual std::shared_ptr GetPRRequestInfo() = 0; + + // get preload timing info + virtual void GetLoadTimingInfo(net::LoadTimingInfo* load_timing_info) const = 0; + + // get preload state + virtual PRPPReqLoaderState GetState() const = 0; + + // clear callback + virtual void ClearLoaderCallback(bool has_devtools_request_id) = 0; +}; + +} // namespace ohos_prp_preload + +#endif // SERVICES_NETWORK_PRP_PRELOAD_INCLUDE_PRELOAD_RUNNER_PRPP_REQUEST_LOADER_H \ No newline at end of file diff --git a/services/network/prp_preload/include/preload_runner/prpp_request_loader_factory.h b/services/network/prp_preload/include/preload_runner/prpp_request_loader_factory.h new file mode 100644 index 0000000000..95adae6d16 --- /dev/null +++ b/services/network/prp_preload/include/preload_runner/prpp_request_loader_factory.h @@ -0,0 +1,61 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_NETWORK_PRP_PRELOAD_INCLUDE_PRELOAD_RUNNER_PRPP_REQUEST_LOADER_FACTORY_H +#define SERVICES_NETWORK_PRP_PRELOAD_INCLUDE_PRELOAD_RUNNER_PRPP_REQUEST_LOADER_FACTORY_H + +#include "services/network/public/mojom/network_context.mojom.h" +#include "net/base/page_res_request_info.h" + +namespace net { +class URLRequestContext; +} // namespace net + +namespace network { +class NetworkContext; +class URLLoaderContext; +} // namespace network + +namespace ohos_prp_preload { +class PRPPRequestLoader; +// only run in network thread +class PRPPRequestLoaderFactory { + public: + + // create PRPPRequestLoaderFactory + static std::shared_ptr CreatePRPPRequestLoaderFactory( + const std::string& url, + base::WeakPtr url_request_context, + base::WeakPtr network_context); + + // destroy PRPPRequestLoaderFactory object + virtual ~PRPPRequestLoaderFactory() = default; + + // create preload loader and start + virtual void CreateReqLoaderAndStart(const std::shared_ptr& info, + bool only_send_reuse_request, + const std::set& need_record_header_urls) = 0; + + // set isolation info created with cached origin + virtual void SetPRPPIsolation(const net::IsolationInfo& isl) = 0; + + // get preload loader + virtual std::shared_ptr GetPRPPReqLoader( + const network::URLLoaderContext& context, + const network::ResourceRequest& resource_request, + std::shared_ptr req_info_binding) = 0; + + // get weak ptr of PRPPRequestLoaderFactory + virtual base::WeakPtr GetWeak() = 0; + + // get main url of page + virtual const std::string& GetMainUrl() const = 0; + + // get the count of prerequest can be send + virtual uint32_t GetAndClearPreloadedCount() = 0; +}; + +} // namespace ohos_prp_preload + +#endif // SERVICES_NETWORK_PRP_PRELOAD_INCLUDE_PRELOAD_RUNNER_PRPP_REQUEST_LOADER_FACTORY_H \ No newline at end of file diff --git a/net/prp_preload/src/disk_cache_backend_factory.cc b/services/network/prp_preload/src/disk_cache_backend_factory.cc similarity index 85% rename from net/prp_preload/src/disk_cache_backend_factory.cc rename to services/network/prp_preload/src/disk_cache_backend_factory.cc index 24287cc335..681a8c9491 100644 --- a/net/prp_preload/src/disk_cache_backend_factory.cc +++ b/services/network/prp_preload/src/disk_cache_backend_factory.cc @@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "disk_cache_backend_factory.h" +#include "services/network/prp_preload/src/disk_cache_backend_factory.h" #include "base/logging.h" #include "base/path_service.h" -#include "net/base/io_buffer.h" namespace { const size_t DEFAULT_PRELOAD_DISK_CACHE_BYTES = 12 * 1024 * 1024; @@ -16,11 +15,10 @@ const base::FilePath::CharType PRELOAD_CACHE_DIRNAME[] = FILE_PATH_LITERAL("Prel namespace ohos_prp_preload { void DiskCacheBackendFactory::CreateBackend() { if (!base::PathService::Get(base::DIR_CACHE, &cache_path_)) { - LOG(ERROR) << "PRPPreload.DiskCacheBackendFactory::CreateBackend get cache path failed"; + LOG(WARNING) << "PRPPreload.DiskCacheBackendFactory::CreateBackend get cache path failed"; return; } cache_path_ = cache_path_.Append(PRELOAD_CACHE_DIRNAME); - LOG(DEBUG) << "PRPPreload.DiskCacheBackendFactory::CreateBackend cache path success"; disk_cache::BackendResult rv = disk_cache::CreateCacheBackend( net::DISK_CACHE, net::CACHE_BACKEND_SIMPLE, /*file_operations=*/nullptr, cache_path_, DEFAULT_PRELOAD_DISK_CACHE_BYTES, @@ -38,8 +36,7 @@ bool DiskCacheBackendFactory::WaitInitedTimeout() { return true; } constexpr int32_t WAIT_INITED_TIME_OUT = 200; // 200ms - std::mutex mutex; - std::unique_lock lk(mutex); + std::unique_lock lk(fac_mutex_); bool ret = cv_backend_ready_.wait_until(lk, std::chrono::steady_clock::now() + std::chrono::milliseconds(WAIT_INITED_TIME_OUT), [&] { return is_inited_.load(); }); diff --git a/net/prp_preload/src/disk_cache_backend_factory.h b/services/network/prp_preload/src/disk_cache_backend_factory.h similarity index 75% rename from net/prp_preload/src/disk_cache_backend_factory.h rename to services/network/prp_preload/src/disk_cache_backend_factory.h index 3e8c834a19..8c8c9d0b59 100644 --- a/net/prp_preload/src/disk_cache_backend_factory.h +++ b/services/network/prp_preload/src/disk_cache_backend_factory.h @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_PRP_PRELOAD_SRC_DISK_CACHE_BACKEND_FACTORY_H -#define NET_PRP_PRELOAD_SRC_DISK_CACHE_BACKEND_FACTORY_H +#ifndef SERVICES_NETWORK_PRP_PRELOAD_SRC_DISK_CACHE_BACKEND_FACTORY_H +#define SERVICES_NETWORK_PRP_PRELOAD_SRC_DISK_CACHE_BACKEND_FACTORY_H -#include -#include #include "base/files/file_path.h" +#include "net/base/io_buffer.h" #include "net/disk_cache/disk_cache.h" namespace ohos_prp_preload { @@ -24,11 +23,12 @@ class DiskCacheBackendFactory : public base::RefCounted void CacheCreatedCallback(disk_cache::BackendResult result); base::FilePath cache_path_; - std::atomic_bool is_inited_ { false }; + std::atomic is_inited_ { false }; std::unique_ptr backend_; std::condition_variable cv_backend_ready_; + std::mutex fac_mutex_; }; } // namespace ohos_prp_preload -#endif // NET_PRP_PRELOAD_SRC_DISK_CACHE_BACKEND_FACTORY_H \ No newline at end of file +#endif // SERVICES_NETWORK_PRP_PRELOAD_SRC_DISK_CACHE_BACKEND_FACTORY_H \ No newline at end of file diff --git a/net/prp_preload/src/disk_cache_file.cc b/services/network/prp_preload/src/disk_cache_file.cc similarity index 92% rename from net/prp_preload/src/disk_cache_file.cc rename to services/network/prp_preload/src/disk_cache_file.cc index b507fbb006..74df38611a 100644 --- a/net/prp_preload/src/disk_cache_file.cc +++ b/services/network/prp_preload/src/disk_cache_file.cc @@ -7,7 +7,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "disk_cache_file.h" +#include "services/network/prp_preload/src/disk_cache_file.h" #include "base/logging.h" @@ -24,7 +24,7 @@ DiskCacheEntry::~DiskCacheEntry() { entry_ = nullptr; } } - + void DiskCacheEntry::Cache() { OnOpComplete(net::OK); } @@ -154,6 +154,9 @@ int DiskCacheReadHelper::OpenCallback(int rv) { int DiskCacheReadHelper::ReadCallback(int rv) { if (rv != net::OK) { LOG(DEBUG) << "PRPPreload.DiskCacheReadHelper::ReadCallback load cache entry failed: " << rv; + if (!entry_loaded_cb_.is_null()) { + entry_loaded_cb_.Run(std::string()); + } cache_->EntryReadComplete(); return rv; } @@ -166,8 +169,14 @@ int DiskCacheReadHelper::ReadCallback(int rv) { } int DiskCacheReadHelper::IOComplete(int rv) { - if (rv && buf_ != nullptr && rv == buf_->size() && !entry_loaded_cb_.is_null()) { - entry_loaded_cb_.Run(std::string(buf_->data(), buf_->size())); + if (rv && buf_ != nullptr && rv == buf_->size()) { + if (!entry_loaded_cb_.is_null()) { + entry_loaded_cb_.Run(std::string(buf_->data(), buf_->size())); + } + } else { + if (!entry_loaded_cb_.is_null()) { + entry_loaded_cb_.Run(std::string()); + } } cache_->EntryReadComplete(); @@ -181,7 +190,7 @@ DiskCacheFile::DiskCacheFile(const scoped_refptr& disk_ void DiskCacheFile::StoreInfoAsync(const std::string& entry_content) { if (!disk_cache_backend_factory_->WaitInitedTimeout()) { - LOG(ERROR) << "PRPPreload.DiskCacheFile::StoreInfoAsync backend not ready"; + LOG(WARNING) << "PRPPreload.DiskCacheFile::StoreInfoAsync backend not ready"; return; } entry_ = std::make_unique(this, url_, entry_content); diff --git a/net/prp_preload/src/disk_cache_file.h b/services/network/prp_preload/src/disk_cache_file.h similarity index 92% rename from net/prp_preload/src/disk_cache_file.h rename to services/network/prp_preload/src/disk_cache_file.h index e04cfa5e03..e4e5504aee 100644 --- a/net/prp_preload/src/disk_cache_file.h +++ b/services/network/prp_preload/src/disk_cache_file.h @@ -2,12 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_PRP_PRELOAD_SRC_DISK_CACHE_FILE_H -#define NET_PRP_PRELOAD_SRC_DISK_CACHE_FILE_H +#ifndef SERVICES_NETWORK_PRP_PRELOAD_SRC_DISK_CACHE_FILE_H +#define SERVICES_NETWORK_PRP_PRELOAD_SRC_DISK_CACHE_FILE_H -#include -#include "disk_cache_backend_factory.h" -#include "net/base/io_buffer.h" +#include "services/network/prp_preload/src/disk_cache_backend_factory.h" namespace ohos_prp_preload { class DiskCacheFile; @@ -108,4 +106,4 @@ class DiskCacheFile : public base::RefCounted { } // namespace ohos_prp_preload -#endif // NET_PRP_PRELOAD_SRC_DISK_CACHE_FILE_H \ No newline at end of file +#endif // SERVICES_NETWORK_PRP_PRELOAD_SRC_DISK_CACHE_FILE_H \ No newline at end of file diff --git a/services/network/prp_preload/src/disk_cache_info_parser.cc b/services/network/prp_preload/src/disk_cache_info_parser.cc new file mode 100644 index 0000000000..9fb02f078e --- /dev/null +++ b/services/network/prp_preload/src/disk_cache_info_parser.cc @@ -0,0 +1,1131 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/prp_preload/src/disk_cache_info_parser.h" + +namespace ohos_prp_preload { +using SetParamToJsonFunc = void (*)(const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); +using GetParamFromJsonFunc = + bool (*)(const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); +struct ParseFunc { + SetParamToJsonFunc set_to_json_func_; + GetParamFromJsonFunc get_from_json_func_; +}; + +const std::unordered_map + PRECONNECT_PARSE_FUNC_MAP = { + { "allow_credentials", + { &DiskCacheInfoParser::SetAllowCredentialsToJson, + &DiskCacheInfoParser::GetAllowCredentialsFromJson } }, + { "cache_info", + { &DiskCacheInfoParser::SetCacheInfoToJson, + &DiskCacheInfoParser::GetCacheInfoFromJson } }, + { "url", + { &DiskCacheInfoParser::SetUrlToJson, + &DiskCacheInfoParser::GetUrlFromJson } }, +}; + +const std::unordered_map + PRELOAD_PARSE_FUNC_MAP = { + { "accepted_stream_types", + { &DiskCacheInfoParser::SetAcceptedStreamTypesToJson, + &DiskCacheInfoParser::GetAcceptedStreamTypesFromJson } }, + { "cookie_setting_overrides", + { &DiskCacheInfoParser::SetCookieSettingOverridesToJson, + &DiskCacheInfoParser::GetCookieSettingOverridesFromJson } }, + { "corb_detachable", + { &DiskCacheInfoParser::SetCorbDetachableToJson, + &DiskCacheInfoParser::GetCorbDetachableFromJson } }, + { "do_not_prompt_for_login", + { &DiskCacheInfoParser::SetDoNotPromptForLoginToJson, + &DiskCacheInfoParser::GetDoNotPromptForLoginFromJson } }, + { "dynamic_header_keys", + { &DiskCacheInfoParser::SetDynamicHeaderKeysToJson, + &DiskCacheInfoParser::GetDynamicHeaderKeysFromJson } }, + { "extra_request_headers", + { &DiskCacheInfoParser::SetExtraRequestHeadersToJson, + &DiskCacheInfoParser::GetExtraRequestHeadersFromJson } }, + { "first_party_url_policy", + { &DiskCacheInfoParser::SetFirstPartyUrlPolicyToJson, + &DiskCacheInfoParser::GetFirstPartyUrlPolicyFromJson } }, + { "force_ignore_site_for_cookies", + { &DiskCacheInfoParser::SetForceIgnoreSiteForCookiesToJson, + &DiskCacheInfoParser::GetForceIgnoreSiteForCookiesFromJson } }, + { "force_ignore_top_frame_party_for_cookies", + { &DiskCacheInfoParser::SetForceIgnoreTopFramePartyForCookiesToJson, + &DiskCacheInfoParser::GetForceIgnoreTopFramePartyForCookiesFromJson } }, + { "force_main_frame_for_same_site_cookies", + { &DiskCacheInfoParser::SetForceMainFrameForSameSiteCookiesToJson, + &DiskCacheInfoParser::GetForceMainFrameForSameSiteCookiesFromJson } }, + { "has_storage_access", + { &DiskCacheInfoParser::SetHasStorageAccessToJson, + &DiskCacheInfoParser::GetHasStorageAccessFromJson } }, + { "idempotency", + { &DiskCacheInfoParser::SetIdempotencyToJson, + &DiskCacheInfoParser::GetIdempotencyFromJson } }, + { "initiator", + { &DiskCacheInfoParser::SetInitiatorToJson, + &DiskCacheInfoParser::GetInitiatorFromJson } }, + { "is_for_websockets", + { &DiskCacheInfoParser::SetIsForWebsocketsToJson, + &DiskCacheInfoParser::GetIsForWebsocketsFromJson } }, + { "keepalive", + { &DiskCacheInfoParser::SetKeepaliveToJson, + &DiskCacheInfoParser::GetKeepaliveFromJson } }, + { "load_flags", + { &DiskCacheInfoParser::SetLoadFlagsToJson, + &DiskCacheInfoParser::GetLoadFlagsFromJson } }, + { "method", + { &DiskCacheInfoParser::SetMethodToJson, + &DiskCacheInfoParser::GetMethodFromJson } }, + { "preload_flag", + { &DiskCacheInfoParser::SetPreloadFlagsToJson, + &DiskCacheInfoParser::GetPreloadFlagsFromJson } }, + { "referrer", + { &DiskCacheInfoParser::SetReferrerToJson, + &DiskCacheInfoParser::GetReferrerFromJson } }, + { "referrer_policy", + { &DiskCacheInfoParser::SetReferrerPolicyToJson, + &DiskCacheInfoParser::GetReferrerPolicyFromJson } }, + { "request_credentials_mode", + { &DiskCacheInfoParser::SetRequestCredentialsModeToJson, + &DiskCacheInfoParser::GetRequestCredentialsModeFromJson } }, + { "request_destination", + { &DiskCacheInfoParser::SetRequestDestinationToJson, + &DiskCacheInfoParser::GetRequestDestinationFromJson } }, + { "request_end_time", + { &DiskCacheInfoParser::SetRequestEndTimeToJson, + &DiskCacheInfoParser::GetRequestEndTimeFromJson } }, + { "request_info_type", + { &DiskCacheInfoParser::SetRequestInfoTypeToJson, + &DiskCacheInfoParser::GetRequestInfoTypeFromJson } }, + { "request_mode", + { &DiskCacheInfoParser::SetRequestModeToJson, + &DiskCacheInfoParser::GetRequestModeFromJson } }, + { "request_start_time", + { &DiskCacheInfoParser::SetRequestStartTimeToJson, + &DiskCacheInfoParser::GetRequestStartTimeFromJson } }, + { "resource_type", + { &DiskCacheInfoParser::SetResourceTypeToJson, + &DiskCacheInfoParser::GetResourceTypeFromJson } }, + { "secure_dns_policy", + { &DiskCacheInfoParser::SetSecureDnsPolicyToJson, + &DiskCacheInfoParser::GetSecureDnsPolicyFromJson } }, + { "send_client_certs", + { &DiskCacheInfoParser::SetSendClientCertsToJson, + &DiskCacheInfoParser::GetSendClientCertsFromJson } }, + { "upgrade_if_insecure", + { &DiskCacheInfoParser::SetUpgradeIfInsecureToJson, + &DiskCacheInfoParser::GetUpgradeIfInsecureFromJson } }, +}; + +void DiskCacheInfoParser::ParseResReqPreloadInfoForPreconnect( + const std::shared_ptr& info, + base::Value::Dict& dict) { + for (const auto& it : PRECONNECT_PARSE_FUNC_MAP) { + it.second.set_to_json_func_(info, it.first, dict); + } +} + +bool DiskCacheInfoParser::ParseJsonForPreconnect( + const base::Value& json, + const std::shared_ptr& info) { + for (const auto& it : PRECONNECT_PARSE_FUNC_MAP) { + if (!it.second.get_from_json_func_(json, it.first, info)) { + return false; + } + } + return true; +} + +void DiskCacheInfoParser::ParseResReqPreloadInfoForPreload( + const std::shared_ptr& info, + base::Value::Dict& dict) { + for (const auto& it : PRELOAD_PARSE_FUNC_MAP) { + it.second.set_to_json_func_(info, it.first, dict); + } +} + +bool DiskCacheInfoParser::ParseJsonForPreload( + const base::Value& json, + const std::shared_ptr& info) { + for (const auto& it : PRELOAD_PARSE_FUNC_MAP) { + if (!it.second.get_from_json_func_(json, it.first, info)) { + return false; + } + } + return true; +} + +void DiskCacheInfoParser::SetAcceptedStreamTypesToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + if (info->accepted_stream_types().has_value()) { + base::Value::List accepted_stream_types_list; + for (const auto& accepted_stream_type : + info->accepted_stream_types().value()) { + accepted_stream_types_list.Append(static_cast(accepted_stream_type)); + } + dict.Set(param_name, std::move(accepted_stream_types_list)); + } +} + +bool DiskCacheInfoParser::GetAcceptedStreamTypesFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const base::Value::List* accepted_stream_types_list = + json.GetDict().FindList(param_name); + if (accepted_stream_types_list != nullptr) { + std::vector accepted_stream_types; + for (const auto& accepted_stream_type : *accepted_stream_types_list) { + accepted_stream_types.push_back( + static_cast( + accepted_stream_type.GetInt())); + } + if (accepted_stream_types.size()) { + info->set_accepted_stream_types(accepted_stream_types); + } + } + // accepted_stream_types_list can be null, always return true + return true; +} + +void DiskCacheInfoParser::SetAllowCredentialsToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->allow_credentials()); +} + +bool DiskCacheInfoParser::GetAllowCredentialsFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional allow_credentials = + json.GetDict().FindBool(param_name); + if (!allow_credentials.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetAllowCredentialsFromJson allow_credentials is invalid"; + return false; + } + info->set_allow_credentials(allow_credentials.value()); + return true; +} +void DiskCacheInfoParser::SetCacheInfoToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + using SetCacheInfoParamToJsonFunc = + void (*)(const CacheInfo& cache_info, const std::string& param_name, + base::Value::Dict& dict); + static const std::unordered_map + SET_CACHE_INFO_PARAM_TO_JSON_FUNC_MAP = { + { "cache_type", &DiskCacheInfoParser::SetCacheTypeToJson }, + { "e_tag", &DiskCacheInfoParser::SetETagToJson }, + { "freshness_life_times", + &DiskCacheInfoParser::SetFreshnessLifeTimesToJson }, + { "last_modified", &DiskCacheInfoParser::SetLastModifiedToJson }, + }; + auto cache_info = info->cache_info(); + for (const auto& it : SET_CACHE_INFO_PARAM_TO_JSON_FUNC_MAP) { + it.second(cache_info, it.first, dict); + } +} + +bool DiskCacheInfoParser::GetCacheInfoFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + using GetCacheInfoParamFromJsonFunc = + bool (*)(const base::Value& json, const std::string& param_name, + const std::shared_ptr& info); + static const std::unordered_map + GET_CACHE_INFO_PARAM_FROM_JSON_FUNC_MAP = { + { "cache_type", &DiskCacheInfoParser::GetCacheTypeFromJson }, + { "e_tag", &DiskCacheInfoParser::GetETagFromJson }, + { "freshness_life_times", + &DiskCacheInfoParser::GetFreshnessLifeTimesFromJson }, + { "last_modified", &DiskCacheInfoParser::GetLastModifiedFromJson }, + }; + for (const auto& it : GET_CACHE_INFO_PARAM_FROM_JSON_FUNC_MAP) { + if (!it.second(json, it.first, info)) { + return false; + } + } + return true; +} + +void DiskCacheInfoParser::SetCacheTypeToJson( + const CacheInfo& cache_info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, static_cast(cache_info.cache_type_)); +} + +bool DiskCacheInfoParser::GetCacheTypeFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional cache_type = json.GetDict().FindInt(param_name); + if (!cache_type.has_value() || + cache_type.value() < + static_cast(PRRequestCacheType::NEGOTIATION_CACHE) || + cache_type.value() > + static_cast(PRRequestCacheType::DISABLE_CACHE)) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::GetCacheTypeFromJson " << + "cache_type is invalid"; + return false; + } + info->set_cache_type(static_cast(cache_type.value())); + return true; +} + +void DiskCacheInfoParser::SetETagToJson( + const CacheInfo& cache_info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, cache_info.e_tag_); +} + +bool DiskCacheInfoParser::GetETagFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const std::string* e_tag = json.GetDict().FindString(param_name); + if (!e_tag) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::GetETagFromJson e_tag is invalid"; + return false; + } + info->set_e_tag(*e_tag); + return true; +} + +void DiskCacheInfoParser::SetFreshnessLifeTimesToJson( + const CacheInfo& cache_info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, std::to_string(cache_info.freshness_life_times_)); +} + +bool DiskCacheInfoParser::GetFreshnessLifeTimesFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const std::string* freshness_life_times_str = + json.GetDict().FindString(param_name); + if (!freshness_life_times_str || freshness_life_times_str->empty()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::GetFreshnessLifeTimesFromJson " << + "fresness_life_times_str is none"; + return false; + } + char* end = nullptr; + errno = 0; // system global variables + int64_t freshness_life_times = + std::strtoll(freshness_life_times_str->c_str(), &end, 10); + if (errno != 0 || !end || *end) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::GetFreshnessLifeTimesFromJson " << + "freshness_life_timesr is invalid"; + return false; + } + + info->set_freshness_life_times(freshness_life_times); + return true; +} + +void DiskCacheInfoParser::SetLastModifiedToJson( + const CacheInfo& cache_info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, cache_info.last_modified_); +} + +bool DiskCacheInfoParser::GetLastModifiedFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const std::string* last_modified = json.GetDict().FindString(param_name); + if (!last_modified) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetLastModifiedFromJson last_modified is invalid"; + return false; + } + info->set_last_modified(*last_modified); + return true; +} + +void DiskCacheInfoParser::SetCookieSettingOverridesToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + base::Value::List cookie_setting_overrides_list; + for (auto cookie_setting_override : info->cookie_setting_overrides()) { + cookie_setting_overrides_list.Append( + static_cast(cookie_setting_override)); + } + dict.Set(param_name, std::move(cookie_setting_overrides_list)); +} + +bool DiskCacheInfoParser::GetCookieSettingOverridesFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const base::Value::List* cookie_setting_overrides_list = + json.GetDict().FindList(param_name); + net::CookieSettingOverrides cookie_setting_overrides; + if (!cookie_setting_overrides_list) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetCookieSettingOverridesFromJson " << + "cookie_setting_overrides is invalid"; + return false; + } + for (const auto& cookie_setting_override : *cookie_setting_overrides_list) { + cookie_setting_overrides.Put(static_cast( + cookie_setting_override.GetInt())); + } + info->set_cookie_setting_overrides(cookie_setting_overrides); + return true; +} + +void DiskCacheInfoParser::SetCorbDetachableToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->corb_detachable()); +} + +bool DiskCacheInfoParser::GetCorbDetachableFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional corb_detachable = + json.GetDict().FindBool(param_name); + if (!corb_detachable.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetCorbDetachableFromJson corb_detachable is invalid"; + return false; + } + info->set_corb_detachable(corb_detachable.value()); + return true; +} + +void DiskCacheInfoParser::SetDoNotPromptForLoginToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->do_not_prompt_for_login()); +} + +bool DiskCacheInfoParser::GetDoNotPromptForLoginFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional do_not_prompt_for_login = + json.GetDict().FindBool(param_name); + if (!do_not_prompt_for_login.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetDoNotPromptForLoginFromJson do_not_prompt_for_login is invalid"; + return false; + } + info->set_do_not_prompt_for_login(do_not_prompt_for_login.value()); + return true; +} + +void DiskCacheInfoParser::SetDynamicHeaderKeysToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + base::Value::List key_list; + for (const auto& key : info->dynamic_header_keys()) { + key_list.Append(key); + } + dict.Set(param_name, std::move(key_list)); +} + +bool DiskCacheInfoParser::GetDynamicHeaderKeysFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const base::Value::List* dynamic_header_key_list = + json.GetDict().FindList(param_name); + if (!dynamic_header_key_list) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetDynamicHeaderKeysFromJson dynamic_header_keys is invalid"; + return false; + } + std::set dynamic_header_keys; + for (const auto& dynamic_header_key : *dynamic_header_key_list) { + (void)dynamic_header_keys.emplace(dynamic_header_key.GetString()); + } + if (!dynamic_header_keys.empty()) { + info->set_dynamic_header_keys(dynamic_header_keys); + } + return true; +} + +void DiskCacheInfoParser::SetExtraRequestHeadersToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + net::HttpRequestHeaders::Iterator it(info->extra_request_headers()); + base::Value::Dict extra_request_headers_dict; + while (it.GetNext()) { + extra_request_headers_dict.Set(it.name(), it.value()); + }; + dict.Set(param_name, std::move(extra_request_headers_dict)); +} + +bool DiskCacheInfoParser::GetExtraRequestHeadersFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const base::Value::Dict* extra_request_headers_dict = + json.GetDict().FindDict(param_name); + net::HttpRequestHeaders extra_request_headers; + if (!extra_request_headers_dict) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetExtraRequestHeadersFromJson extra_request_headers " << + "is invalid"; + return false; + } + for (std::pair extra_request_header : + *extra_request_headers_dict) { + extra_request_headers.SetHeader(extra_request_header.first, + extra_request_header.second.GetString()); + } + info->set_extra_request_headers(std::move(extra_request_headers)); + return true; +} +void DiskCacheInfoParser::SetFirstPartyUrlPolicyToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, static_cast(info->first_party_url_policy())); +} + +bool DiskCacheInfoParser::GetFirstPartyUrlPolicyFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional first_party_url_policy = + json.GetDict().FindInt(param_name); + if (!first_party_url_policy.has_value() || + first_party_url_policy.value() < + static_cast( + net::RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL) || + first_party_url_policy.value() > + static_cast( + net::RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT)) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetFirstPartyUrlPolicyFromJson first_party_url_policy " << + "is invalid"; + return false; + } + info->set_first_party_url_policy( + static_cast( + first_party_url_policy.value())); + return true; +} + +void DiskCacheInfoParser::SetForceIgnoreSiteForCookiesToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->force_ignore_site_for_cookies()); +} + +bool DiskCacheInfoParser::GetForceIgnoreSiteForCookiesFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional force_ignore_site_for_cookies = + json.GetDict().FindBool(param_name); + if (!force_ignore_site_for_cookies.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetForceIgnoreSiteForCookiesFromJson force_ignore_site_for_cookies " << + "is invalid"; + return false; + } + info->set_force_ignore_site_for_cookies( + force_ignore_site_for_cookies.value()); + return true; +} + +void DiskCacheInfoParser::SetForceIgnoreTopFramePartyForCookiesToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->force_ignore_top_frame_party_for_cookies()); +} + +bool DiskCacheInfoParser::GetForceIgnoreTopFramePartyForCookiesFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional force_ignore_top_frame_party_for_cookies = + json.GetDict().FindBool(param_name); + if (!force_ignore_top_frame_party_for_cookies.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetForceIgnoreTopFramePartyForCookiesFromJson " << + "force_ignore_top_frame_party_for_cookies " << + "is invalid"; + return false; + } + info->set_force_ignore_top_frame_party_for_cookies( + force_ignore_top_frame_party_for_cookies.value()); + return true; +} + +void DiskCacheInfoParser::SetForceMainFrameForSameSiteCookiesToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->force_main_frame_for_same_site_cookies()); +} + +bool DiskCacheInfoParser::GetForceMainFrameForSameSiteCookiesFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional force_main_frame_for_same_site_cookies = + json.GetDict().FindBool(param_name); + if (!force_main_frame_for_same_site_cookies.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetForceMainFrameForSameSiteCookiesFromJson " << + "force_main_frame_for_same_site_cookies " << + "is invalid"; + return false; + } + info->set_force_main_frame_for_same_site_cookies( + force_main_frame_for_same_site_cookies.value()); + return true; +} +void DiskCacheInfoParser::SetHasStorageAccessToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->has_storage_access()); +} + +bool DiskCacheInfoParser::GetHasStorageAccessFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional has_storage_access = + json.GetDict().FindBool(param_name); + if (!has_storage_access.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetHasStorageAccessFromJson " << + "has_storage_access " << + "is invalid"; + return false; + } + info->set_has_storage_access(has_storage_access.value()); + return true; +} + +void DiskCacheInfoParser::SetIdempotencyToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, static_cast(info->idempotency())); +} + +bool DiskCacheInfoParser::GetIdempotencyFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional idempotency = json.GetDict().FindInt(param_name); + if (!idempotency.has_value() || + idempotency.value() < net::Idempotency::DEFAULT_IDEMPOTENCY || + idempotency.value() > net::Idempotency::NOT_IDEMPOTENT) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetIdempotencyFromJson " << + "idempotency " << + "is invalid"; + return false; + } + info->set_idempotency(static_cast(idempotency.value())); + return true; +} + +void DiskCacheInfoParser::SetInitiatorToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + std::string initiator = info->initiator().has_value() + ? info->initiator().value().GetURL().spec() + : ""; + dict.Set(param_name, initiator); +} + +bool DiskCacheInfoParser::GetInitiatorFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const std::string* initiator = json.GetDict().FindString(param_name); + if (!initiator) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetInitiatorFromJson " << + "initiator " << + "is invalid"; + return false; + } + info->set_initiator(url::Origin::Create(GURL(*initiator))); + return true; +} + +void DiskCacheInfoParser::SetIsForWebsocketsToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->is_for_websockets()); +} + +bool DiskCacheInfoParser::GetIsForWebsocketsFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional is_for_websockets = + json.GetDict().FindBool(param_name); + if (!is_for_websockets.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetIsForWebsocketsFromJson " << + "is_for_websockets " << + "is invalid"; + return false; + } + + info->set_is_for_websockets(is_for_websockets.value()); + return true; +} + +void DiskCacheInfoParser::SetKeepaliveToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->keepalive()); +} + +bool DiskCacheInfoParser::GetKeepaliveFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional keepalive = json.GetDict().FindBool(param_name); + if (!keepalive.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetKeepaliveFromJson " << + "keepalive " << + "is invalid"; + return false; + } + info->set_keepalive(keepalive.value()); + return true; +} + +void DiskCacheInfoParser::SetLoadFlagsToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->load_flags()); +} +bool DiskCacheInfoParser::GetLoadFlagsFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional load_flags = json.GetDict().FindInt(param_name); + if (!load_flags.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetLoadFlagsFromJson " << + "load_flags " << + "is invalid"; + return false; + } + info->set_load_flags(load_flags.value()); + return true; +} + +void DiskCacheInfoParser::SetMethodToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->method()); +} + +bool DiskCacheInfoParser::GetMethodFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const std::string* method = json.GetDict().FindString(param_name); + if (!method) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetMethodFromJson method " << + "is invalid"; + return false; + } + info->set_method(*method); + return true; +} + +void DiskCacheInfoParser::SetPreloadFlagsToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, static_cast(info->preload_flag())); +} + +bool DiskCacheInfoParser::GetPreloadFlagsFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional preload_flag = json.GetDict().FindInt(param_name); + if (!preload_flag.has_value() || + preload_flag.value() < static_cast(PRRequestFlags::PRPP_FLAGS_NONE) || + preload_flag.value() > static_cast(PRRequestFlags::PRPP_FLAGS_URL_DYNAMIC)) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetPreloadFlagsFromJson preload_flag " << + "is invalid"; + return false; + } + info->set_preload_flag(static_cast(preload_flag.value())); + return true; +} + +void DiskCacheInfoParser::SetReferrerToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->referrer()); +} + +bool DiskCacheInfoParser::GetReferrerFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const std::string* referrer = json.GetDict().FindString(param_name); + if (!referrer) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetReferrerFromJson referrer " << + "is invalid"; + return false; + } + info->set_referrer(*referrer); + return true; +} + +void DiskCacheInfoParser::SetReferrerPolicyToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, static_cast(info->referrer_policy())); +} + +bool DiskCacheInfoParser::GetReferrerPolicyFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional referrer_policy = + json.GetDict().FindInt(param_name); + if (!referrer_policy.has_value() || + referrer_policy.value() < + static_cast(net::ReferrerPolicy:: + CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE) || + referrer_policy.value() > static_cast(net::ReferrerPolicy::MAX)) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetReferrerPolicyFromJson referrer_policy " << + "is invalid"; + return false; + } + info->set_referrer_policy( + static_cast(referrer_policy.value())); + return true; +} + +void DiskCacheInfoParser::SetRequestCredentialsModeToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->request_credentials_mode()); +} + +bool DiskCacheInfoParser::GetRequestCredentialsModeFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional request_credentials_mode = + json.GetDict().FindInt(param_name); + if (!request_credentials_mode.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetRequestCredentialsModeFromJson request_credentials_mode " << + "is invalid"; + return false; + } + info->set_request_credentials_mode(request_credentials_mode.value()); + return true; +} + +void DiskCacheInfoParser::SetRequestDestinationToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->request_destination()); +} + +bool DiskCacheInfoParser::GetRequestDestinationFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional request_destination = + json.GetDict().FindInt(param_name); + if (!request_destination.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetRequestDestinationFromJson request_destination " << + "is invalid"; + return false; + } + info->set_request_destination(request_destination.value()); + return true; +} + +void DiskCacheInfoParser::SetRequestEndTimeToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, std::to_string(info->request_end_time())); +} + +bool DiskCacheInfoParser::GetRequestEndTimeFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const std::string* request_end_time_str = + json.GetDict().FindString(param_name); + if (!request_end_time_str || request_end_time_str->empty()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetRequestEndTimeFromJson request_end_time " << + "is none"; + return false; + } + + char* end = nullptr; + errno = 0; // system global variables + int64_t request_end_time = + std::strtoll(request_end_time_str->c_str(), &end, 10); + if (errno != 0 || !end || *end) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetRequestEndTimeFromJson request_end_time " << + "is invalid"; + return false; + } + + info->set_request_end_time(request_end_time); + return true; +} + +void DiskCacheInfoParser::SetRequestInfoTypeToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, static_cast(info->type())); +} + +bool DiskCacheInfoParser::GetRequestInfoTypeFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional type = json.GetDict().FindInt(param_name); + if (!type.has_value() || + type.value() < static_cast(PRRequestInfoType::TYPE_DEFAULT) || + type.value() > static_cast(PRRequestInfoType::TYPE_PAGE_PREFLIGHT)) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetRequestInfoTypeFromJson type is invalid"; + return false; + } + info->set_type(static_cast(type.value())); + return true; +} + +void DiskCacheInfoParser::SetRequestModeToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set("request_mode", info->request_mode()); +} +bool DiskCacheInfoParser::GetRequestModeFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional request_mode = json.GetDict().FindInt(param_name); + if (!request_mode.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::GetRequestModeFromJson " << + "request_mode is invalid"; + return false; + } + info->set_request_mode(request_mode.value()); + return true; +} + +void DiskCacheInfoParser::SetRequestStartTimeToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, std::to_string(info->request_start_time())); +} + +bool DiskCacheInfoParser::GetRequestStartTimeFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const std::string* request_start_time_str = + json.GetDict().FindString(param_name); + if (!request_start_time_str || request_start_time_str->empty()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetRequestStartTimeFromJson request_start_time " << + "is none"; + return false; + } + + char* end = nullptr; + errno = 0; // system global variables + int64_t request_start_time = + std::strtoll(request_start_time_str->c_str(), &end, 10); + if (errno != 0 || !end || *end) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetRequestStartTimeFromJson request_start_time " << + "is invalid"; + return false; + } + + info->set_request_start_time(request_start_time); + return true; +} + +void DiskCacheInfoParser::SetResourceTypeToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->resource_type()); +} + +bool DiskCacheInfoParser::GetResourceTypeFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional resource_type = json.GetDict().FindInt(param_name); + if (!resource_type.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::GetResourceTypeFromJson " << + "resource_type is invalid"; + return false; + } + info->set_resource_type(resource_type.value()); + return true; +} + +void DiskCacheInfoParser::SetSecureDnsPolicyToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, static_cast(info->secure_dns_policy())); +} + +bool DiskCacheInfoParser::GetSecureDnsPolicyFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional secure_dns_policy = + json.GetDict().FindInt(param_name); + if (!secure_dns_policy.has_value() || + secure_dns_policy.value() < + static_cast(net::SecureDnsPolicy::kAllow) || + secure_dns_policy.value() > + static_cast(net::SecureDnsPolicy::kBootstrap)) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetSecureDnsPolicyFromJson secure_dns_policy " << + "is invalid"; + return false; + } + info->set_secure_dns_policy( + static_cast(secure_dns_policy.value())); + return true; +} + +void DiskCacheInfoParser::SetSendClientCertsToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->send_client_certs()); +} + +bool DiskCacheInfoParser::GetSendClientCertsFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional send_client_certs = + json.GetDict().FindBool(param_name); + if (!send_client_certs.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetSendClientCertsFromJson send_client_certs " << + "is invalid"; + return false; + } + info->set_send_client_certs(send_client_certs.value()); + return true; +} + +void DiskCacheInfoParser::SetUpgradeIfInsecureToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + dict.Set(param_name, info->upgrade_if_insecure()); +} +bool DiskCacheInfoParser::GetUpgradeIfInsecureFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const absl::optional upgrade_if_insecure = + json.GetDict().FindBool(param_name); + if (!upgrade_if_insecure.has_value()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::" << + "GetUpgradeIfInsecureFromJson upgrade_if_insecure " << + "is invalid"; + return false; + } + info->set_upgrade_if_insecure(upgrade_if_insecure.value()); + return true; +} + +void DiskCacheInfoParser::SetUrlToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict) { + if ((info->type() == PRRequestInfoType::TYPE_PAGE_PREFLIGHT) && + !info->url().spec().starts_with(PRPP_PREFLIGHT_PREFIX)) { + dict.Set(param_name, + std::string(PRPP_PREFLIGHT_PREFIX) + info->url().spec()); + } else { + dict.Set(param_name, info->url().spec()); + } +} + +bool DiskCacheInfoParser::GetUrlFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info) { + const std::string* url = json.GetDict().FindString(param_name); + if (!url || url->empty()) { + LOG(WARNING) << "PRPPreload.DiskCacheInfoParser::GetUrlFromJson " << + "url is invalid"; + return false; + } + + info->set_url(GURL(*url)); + return true; +} + +} // namespace ohos_prp_preload \ No newline at end of file diff --git a/services/network/prp_preload/src/disk_cache_info_parser.h b/services/network/prp_preload/src/disk_cache_info_parser.h new file mode 100644 index 0000000000..145b0cdddf --- /dev/null +++ b/services/network/prp_preload/src/disk_cache_info_parser.h @@ -0,0 +1,303 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_NETWORK_PRP_PRELOAD_SRC_DISK_CACHE_INFO_PARSER_H +#define SERVICES_NETWORK_PRP_PRELOAD_SRC_DISK_CACHE_INFO_PARSER_H + +#include "base/values.h" +#include "net/base/page_res_request_info.h" + +namespace ohos_prp_preload { + +class DiskCacheInfoParser { + public: + static void ParseResReqPreloadInfoForPreconnect( + const std::shared_ptr& info, + base::Value::Dict& dict); + static bool ParseJsonForPreconnect( + const base::Value& json, + const std::shared_ptr& info); + static void ParseResReqPreloadInfoForPreload( + const std::shared_ptr& info, + base::Value::Dict& dict); + static bool ParseJsonForPreload(const base::Value& json, + const std::shared_ptr& info); + static void SetAcceptedStreamTypesToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetAcceptedStreamTypesFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetAllowCredentialsToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetAllowCredentialsFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetCacheInfoToJson(const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetCacheInfoFromJson(const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetCacheTypeToJson(const CacheInfo& cache_info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetCacheTypeFromJson(const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetETagToJson(const CacheInfo& cache_info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetETagFromJson(const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetFreshnessLifeTimesToJson(const CacheInfo& cache_info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetFreshnessLifeTimesFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetLastModifiedToJson(const CacheInfo& cache_info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetLastModifiedFromJson(const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetCookieSettingOverridesToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetCookieSettingOverridesFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetCorbDetachableToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetCorbDetachableFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetDoNotPromptForLoginToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetDoNotPromptForLoginFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetDynamicHeaderKeysToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetDynamicHeaderKeysFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetExtraRequestHeadersToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetExtraRequestHeadersFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetFirstPartyUrlPolicyToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetFirstPartyUrlPolicyFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetForceIgnoreSiteForCookiesToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetForceIgnoreSiteForCookiesFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetForceIgnoreTopFramePartyForCookiesToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetForceIgnoreTopFramePartyForCookiesFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetForceMainFrameForSameSiteCookiesToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetForceMainFrameForSameSiteCookiesFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetHasStorageAccessToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetHasStorageAccessFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetIdempotencyToJson(const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetIdempotencyFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetInitiatorToJson(const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetInitiatorFromJson(const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetIsForWebsocketsToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetIsForWebsocketsFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetKeepaliveToJson(const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetKeepaliveFromJson(const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetLoadFlagsToJson(const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetLoadFlagsFromJson(const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetMethodToJson(const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetMethodFromJson(const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetReferrerToJson(const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetReferrerFromJson(const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetReferrerPolicyToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetReferrerPolicyFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetRequestCredentialsModeToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetRequestCredentialsModeFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetRequestDestinationToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetRequestDestinationFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetRequestEndTimeToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetRequestEndTimeFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetPreloadFlagsToJson(const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetPreloadFlagsFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetRequestInfoTypeToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetRequestInfoTypeFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetRequestModeToJson(const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetRequestModeFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetRequestStartTimeToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetRequestStartTimeFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetResourceTypeToJson(const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetResourceTypeFromJson(const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetSecureDnsPolicyToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetSecureDnsPolicyFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetSendClientCertsToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetSendClientCertsFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetUpgradeIfInsecureToJson( + const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetUpgradeIfInsecureFromJson( + const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + static void SetUrlToJson(const std::shared_ptr& info, + const std::string& param_name, + base::Value::Dict& dict); + static bool GetUrlFromJson(const base::Value& json, + const std::string& param_name, + const std::shared_ptr& info); + + private: + DiskCacheInfoParser() = default; + ~DiskCacheInfoParser() = default; +}; +} // namespace ohos_prp_preload + +#endif // SERVICES_NETWORK_PRP_PRELOAD_SRC_DISK_CACHE_INFO_PARSER_H \ No newline at end of file diff --git a/services/network/prp_preload/src/page_res_parallel_preload_mgr_impl.cc b/services/network/prp_preload/src/page_res_parallel_preload_mgr_impl.cc new file mode 100644 index 0000000000..8a5830172b --- /dev/null +++ b/services/network/prp_preload/src/page_res_parallel_preload_mgr_impl.cc @@ -0,0 +1,340 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/prp_preload/src/page_res_parallel_preload_mgr_impl.h" + +#include "base/ohos/sys_info_utils.h" +#include "ohos_adapter_helper.h" + +#define SAFE_RUN_GET_ISOLATION_CB(callback, origin) \ + if (!callback.is_null()) { \ + std::move(callback).Run(origin); \ + } + +namespace { +static ohos_prp_preload::PRParallelPreloadMgrImpl g_prp_preload_mgr_impl; +const size_t MAX_PAGE_COUNT = 100; +const std::string CANCEL_ORIGIN = "origin.DEFAULT.Cancel"; +const std::string PRP_PRELOAD_MODE_PRECONNECT = "preconnect"; +const std::string PRP_PRELOAD_MODE_PRELOAD = "preload"; +} // namespace + +namespace ohos_prp_preload { +PRParallelPreloadMgr& PRParallelPreloadMgr::GetInstance() { + return g_prp_preload_mgr_impl; +} + +PRPPreloadMode GetPRParallelPreloadModeInner() { + std::string prp_preload_mode = + OHOS::NWeb::OhosAdapterHelper::GetInstance().GetSystemPropertiesInstance().GetPRPPreloadMode(); + bool isMobile = base::ohos::IsMobileDevice(); + if (!isMobile) { + LOG(DEBUG) << "PRPPreload.GetPRParallelPreloadModeInner is not Mobile, NONE"; + return PRPPreloadMode::NONE; + } + + if (prp_preload_mode == PRP_PRELOAD_MODE_PRECONNECT) { + LOG(DEBUG) << "PRPPreload.GetPRParallelPreloadModeInner PRECONNECT"; + return PRPPreloadMode::PRECONNECT; + } + + if (prp_preload_mode == PRP_PRELOAD_MODE_PRELOAD) { + LOG(DEBUG) << "PRPPreload.GetPRParallelPreloadModeInner PRELOAD"; + return PRPPreloadMode::PRELOAD; + } + + LOG(DEBUG) << "PRPPreload.GetPRParallelPreloadModeInner NONE"; + return PRPPreloadMode::NONE; +} + +PRPPreloadMode PRParallelPreloadMgr::GetPRParallelPreloadMode() { + static PRPPreloadMode mode = GetPRParallelPreloadModeInner(); + return mode; +} + +void PRParallelPreloadMgrImpl::Init(const scoped_refptr& net_task_runner) { + if (PRParallelPreloadMgr::GetInstance().GetPRParallelPreloadMode() == PRPPreloadMode::NONE) { + LOG(DEBUG) << "PRPPreload.PRParallelPreloadMgrImpl::Init NOT ENABLE"; + return; + } + LOG(DEBUG) << "PRPPreload.PRParallelPreloadMgrImpl::Init ENABLE"; + if (!is_inited_) { + is_inited_ = true; + disk_cache_backend_factory_ = base::WrapRefCounted(new (std::nothrow) DiskCacheBackendFactory()); + if (disk_cache_backend_factory_ == nullptr) { + is_inited_ = false; + LOG(WARNING) << "PRPPreload.PRParallelPreloadMgrImpl::Init failed no mem"; + return; + } + disk_cache_backend_factory_->CreateBackend(); + + sth_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner( + {base::TaskPriority::USER_VISIBLE}, base::SingleThreadTaskRunnerThreadMode::DEDICATED); + if (sth_task_runner_ == nullptr || net_task_runner == nullptr) { + is_inited_ = false; + LOG(WARNING) << "PRPPreload.PRParallelPreloadMgrImpl::Init failed"; + return; + } + net_task_runner_ = net_task_runner; + } +} + +void PRParallelPreloadMgrImpl::StartPage(const std::string& url, + base::WeakPtr url_request_context, + base::WeakPtr network_context, + uint64_t addr_web_handle, PageOriginCallback callback) { + void* web_handle = reinterpret_cast(addr_web_handle); + LOG(DEBUG) << "PRPPreload.PRParallelPreloadMgrImpl::StartPage, is_inited = " << is_inited_ << + ", current page num = " << prp_preload_info_map_.size() << ", web_handle_valid = " << !web_handle; + if (url.empty() || web_handle == nullptr || + !is_inited_ || prp_preload_info_map_.size() >= MAX_PAGE_COUNT) { + LOG(WARNING) << "PRPPreload.PRParallelPreloadMgrImpl::StartPage failed"; + SAFE_RUN_GET_ISOLATION_CB(callback, CANCEL_ORIGIN); + return; + } + std::string main_url = url; + auto it = prp_preload_info_map_.find(main_url); + if (it != prp_preload_info_map_.end()) { + LOG(DEBUG) << "PRPPreload.PRParallelPreloadMgrImpl::StartPage already"; + SAFE_RUN_GET_ISOLATION_CB(it->second.callback_, CANCEL_ORIGIN); + it->second.callback_ = std::move(callback); + return; + } + + auto it_web = web_handle_pages_map_.find(web_handle); + if (it_web != web_handle_pages_map_.end()) { + auto iter_page_urls = prp_page_url_.find(main_url); + if ((iter_page_urls == prp_page_url_.end()) && (it_web->second != main_url)) { + StopPageInternal(it_web->second); + it_web->second = main_url; + } else if (iter_page_urls != prp_page_url_.end()) { + main_url = iter_page_urls->second; + auto it_info = prp_preload_info_map_.find(main_url); + if (it_info != prp_preload_info_map_.end()) { + LOG(DEBUG) << "PRPPreload.PRParallelPreloadMgrImpl::StartPage org already"; + SAFE_RUN_GET_ISOLATION_CB(it_info->second.callback_, CANCEL_ORIGIN); + it_info->second.callback_ = std::move(callback); + return; + } + } + } + + scoped_refptr rp_preload_ctrler = base::WrapRefCounted( + new (std::nothrow) ResParallelPreloadCtrler(main_url, sth_task_runner_, + base::BindRepeating(&PRParallelPreloadMgrImpl::OnRPPCtrlerTimeout, base::Unretained(this)))); + if (rp_preload_ctrler == nullptr || + !rp_preload_ctrler->Init(disk_cache_backend_factory_, net_task_runner_, url_request_context, + base::BindRepeating(&PRParallelPreloadMgrImpl::OnPageOrigin, base::Unretained(this)))) { + LOG(DEBUG) << "PRPPreload.PRParallelPreloadMgrImpl::StartPage new ResParallelPreloadCtrler failed"; + SAFE_RUN_GET_ISOLATION_CB(callback, CANCEL_ORIGIN); + return; + } + + web_handle_pages_map_[web_handle] = main_url; + + rp_preload_ctrler->Start(); + prp_preload_info_map_[main_url].rp_preload_ctrler_ = rp_preload_ctrler; + prp_preload_info_map_[main_url].start_page_ = true; + if (PRParallelPreloadMgr::GetInstance().GetPRParallelPreloadMode() == PRPPreloadMode::PRELOAD) { + prp_preload_info_map_[main_url].callback_ = std::move(callback); + prp_preload_info_map_[main_url].prpp_req_loader_fac_ = + PRPPRequestLoaderFactory::CreatePRPPRequestLoaderFactory(main_url, url_request_context, network_context); + } else { + SAFE_RUN_GET_ISOLATION_CB(callback, CANCEL_ORIGIN); + prp_preload_info_map_[main_url].prpp_req_loader_fac_ = nullptr; + } +} + +void PRParallelPreloadMgrImpl::StopPage(uint64_t addr_web_handle) { + void* web_handle = reinterpret_cast(addr_web_handle); + LOG(DEBUG) << "PRPPreload.PRParallelPreloadMgrImpl::StopPage is_inited = " << is_inited_ << + ", web_handle_valid = " << !web_handle; + if (!is_inited_ || !web_handle) { + return; + } + + auto it_web = web_handle_pages_map_.find(web_handle); + if (it_web != web_handle_pages_map_.end()) { + StopPageInternal(it_web->second); + (void)web_handle_pages_map_.erase(it_web); + } +} + +void PRParallelPreloadMgrImpl::UpdateResRequestInfo(const std::string& key, + const std::shared_ptr& info) { + if (!is_inited_) { + return; + } + FindCurPreloadInfoAndRun(key, [&](PRParallelPreloadInfo& prp_preload_info) { + prp_preload_info.rp_preload_ctrler_->UpdateResRequestInfo(info); + }); +} + +void PRParallelPreloadMgrImpl::UpdateRedirectUrl(const std::string& org_url, const std::string& redirect_url, + bool replace) +{ + if (!is_inited_) { + return; + } + + const std::string* key = &org_url; + bool need_rm = false; + if (replace) { + if (prp_page_url_.find(org_url) != prp_page_url_.end()) { + key = &prp_page_url_[org_url]; + need_rm = true; + } else { + LOG(WARNING) << "PRPPreload.PRParallelPreloadMgrImpl::UpdateRedirectUrl replace but not find"; + return; + } + } + + auto it = prp_preload_info_map_.find(*key); + if (it != prp_preload_info_map_.end()) { + if (!it->second.start_page_) { + return; + } else { + prp_page_url_[redirect_url] = *key; + } + } + if (need_rm) { + (void)prp_page_url_.erase(org_url); + } +} + +void PRParallelPreloadMgrImpl::DoRmPageUrl(const std::string& in_org_url) +{ + if (!is_inited_) { + return; + } + for (auto it = prp_page_url_.begin(); it != prp_page_url_.end();) { + if (in_org_url == it->second) { + (void)prp_page_url_.erase(it++); + } else { + it++; + } + } +} + +void PRParallelPreloadMgrImpl::SetPageOrigin(const std::string& url, const net::IsolationInfo& isl) +{ + if (!is_inited_ || !isl.frame_origin().has_value()) { + return; + } + + FindCurPreloadInfoAndRun(url, [&](PRParallelPreloadInfo& prp_preload_info) { + if (prp_preload_info.prpp_req_loader_fac_) { + if (!prp_preload_info.page_origin_ready_) { + prp_preload_info.page_origin_ready_ = true; + prp_preload_info.prpp_req_loader_fac_->SetPRPPIsolation(isl); + prp_preload_info.rp_preload_ctrler_->SetPRPPReqLoaderFac(prp_preload_info.prpp_req_loader_fac_->GetWeak()); + } + prp_preload_info.rp_preload_ctrler_->SetPageOrigin(isl.frame_origin().value().GetURL().spec()); + } + }); +} + +void PRParallelPreloadMgrImpl::StopPageInternal(const std::string& url) { + auto it = prp_preload_info_map_.find(url); + if (it != prp_preload_info_map_.end() && it->second.start_page_) { + it->second.rp_preload_ctrler_->Stop(); + it->second.start_page_ = false; + SAFE_RUN_GET_ISOLATION_CB(it->second.callback_, CANCEL_ORIGIN); + auto ctrler = it->second.rp_preload_ctrler_; + auto loader_fac = it->second.prpp_req_loader_fac_; + it->second.prpp_req_loader_fac_ = nullptr; + DoRmPageUrl(it->first); + (void)prp_preload_info_map_.erase(it); + if (sth_task_runner_ != nullptr) { + sth_task_runner_->PostTask(FROM_HERE, base::BindOnce([] + (const scoped_refptr& ctrler, + const std::shared_ptr& loader_fac) {}, ctrler, loader_fac)); + } + } +} + +void PRParallelPreloadMgrImpl::OnRPPCtrlerTimeout(const std::string& url) { + if (net_task_runner_ == nullptr) { + return; + } + net_task_runner_->PostTask(FROM_HERE, + base::BindOnce(&PRParallelPreloadMgrImpl::DoRPPCtrlerTimeout, weak_factory_.GetWeakPtr(), std::move(url))); +} + +void PRParallelPreloadMgrImpl::DoRPPCtrlerTimeout(const std::string& url) +{ + StopPageInternal(url); +} + +void PRParallelPreloadMgrImpl::OnPageOrigin(const std::string& url, const std::string& page_origin) +{ + if (!is_inited_) { + return; + } + + FindCurPreloadInfoAndRun(url, [&](PRParallelPreloadInfo& prp_preload_info) { + if (page_origin.empty()) { + SAFE_RUN_GET_ISOLATION_CB(prp_preload_info.callback_, CANCEL_ORIGIN); + } else { + SAFE_RUN_GET_ISOLATION_CB(prp_preload_info.callback_, page_origin); + } + }); +} + +void PRParallelPreloadMgrImpl::SetURLLoaderFactoryParam(network::mojom::URLLoaderFactoryParamsPtr params) +{ + if (!is_inited_ || !params) { + return; + } + + FindCurPreloadInfoAndRun(params->main_url, [&](PRParallelPreloadInfo& prp_preload_info) { + if (prp_preload_info.prpp_req_loader_fac_ && !prp_preload_info.page_origin_ready_) { + prp_preload_info.page_origin_ready_ = true; + prp_preload_info.prpp_req_loader_fac_->SetPRPPIsolation(params->isolation_info); + prp_preload_info.rp_preload_ctrler_->SetPRPPReqLoaderFac(prp_preload_info.prpp_req_loader_fac_->GetWeak()); + } + }); +} + +base::WeakPtr PRParallelPreloadMgrImpl::GetRequestLoaderFactory(const std::string& main_url) +{ + if (!is_inited_) { + return nullptr; + } + base::WeakPtr factory = nullptr; + FindCurPreloadInfoAndRun(main_url, [&](PRParallelPreloadInfo& prp_preload_info) { + if (prp_preload_info.prpp_req_loader_fac_) { + LOG(DEBUG) << "PRPPreload.PRParallelPreloadMgrImpl::GetRequestLoaderFactory got loader fac"; + factory = prp_preload_info.prpp_req_loader_fac_->GetWeak(); + } + }); + return factory; +} + +void PRParallelPreloadMgrImpl::FindCurPreloadInfoAndRun(const std::string& key, + std::function func) +{ + auto it = prp_preload_info_map_.find(key); + bool check_redirect = false; + do { + if (it != prp_preload_info_map_.end()) { + if (!it->second.start_page_) { + break; + } + func(it->second); + break; + } + if (check_redirect) { + break; + } + auto iter = prp_page_url_.find(key); + if (iter == prp_page_url_.end()) { + break; + } + check_redirect = true; + it = prp_preload_info_map_.find(iter->second); + } while (check_redirect); +} + +} // namespace ohos_prp_preload \ No newline at end of file diff --git a/net/prp_preload/src/page_res_parallel_preload_mgr_impl.h b/services/network/prp_preload/src/page_res_parallel_preload_mgr_impl.h similarity index 42% rename from net/prp_preload/src/page_res_parallel_preload_mgr_impl.h rename to services/network/prp_preload/src/page_res_parallel_preload_mgr_impl.h index 16960e6d5a..c35b2166c8 100644 --- a/net/prp_preload/src/page_res_parallel_preload_mgr_impl.h +++ b/services/network/prp_preload/src/page_res_parallel_preload_mgr_impl.h @@ -2,14 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_PRP_PRELOAD_SRC_PAGR_RES_PARALLEL_PRELOAD_MGR_IMPL_H -#define NET_PRP_PRELOAD_SRC_PAGR_RES_PARALLEL_PRELOAD_MGR_IMPL_H +#ifndef SERVICES_NETWORK_PRP_PRELOAD_SRC_PAGR_RES_PARALLEL_PRELOAD_MGR_IMPL_H +#define SERVICES_NETWORK_PRP_PRELOAD_SRC_PAGR_RES_PARALLEL_PRELOAD_MGR_IMPL_H -#include #include -#include "disk_cache_backend_factory.h" -#include "page_res_parallel_preload_mgr.h" -#include "res_parallel_preload_ctrler.h" +#include "services/network/prp_preload/include/page_res_parallel_preload_mgr.h" +#include "services/network/prp_preload/src/res_parallel_preload_ctrler.h" namespace ohos_prp_preload { class PRParallelPreloadMgrImpl : public PRParallelPreloadMgr { @@ -17,33 +15,43 @@ class PRParallelPreloadMgrImpl : public PRParallelPreloadMgr { PRParallelPreloadMgrImpl() = default; ~PRParallelPreloadMgrImpl() = default; void Init(const scoped_refptr& net_task_runner) override; - void StartMainPage(const std::string& url, - const net::NetworkAnonymizationKey& networkAnonymizationKey, + void StartPage(const std::string& url, base::WeakPtr url_request_context, - uint64_t addr_web_handle) override; - void StopMainPage(const std::string& url) override; - void StopMainPage(uint64_t addr_web_handle) override; + base::WeakPtr network_context, + uint64_t addr_web_handle, + PageOriginCallback callback) override; + void StopPage(uint64_t addr_web_handle) override; void UpdateResRequestInfo(const std::string& key, const std::shared_ptr& info) override; + void UpdateRedirectUrl(const std::string& org_url, const std::string& redirect_url, bool replace = false) override; + void SetPageOrigin(const std::string& url, const net::IsolationInfo& isl) override; + void OnPageOrigin(const std::string& url, const std::string& page_origin) override; + void SetURLLoaderFactoryParam(network::mojom::URLLoaderFactoryParamsPtr params) override; + base::WeakPtr GetRequestLoaderFactory(const std::string& main_url) override; private: - void StopMainPageInternal(const std::string& url); - void OnRPPCtrlerTimeout(const std::string& url); - bool RecycleRPPCtrler(); struct PRParallelPreloadInfo { scoped_refptr rp_preload_ctrler_; bool start_page_ { false }; + PageOriginCallback callback_; + std::shared_ptr prpp_req_loader_fac_; + bool page_origin_ready_ { false }; }; - - std::unordered_map prp_preload_info_map_; - std::unordered_map web_handle_pages_map_; + void StopPageInternal(const std::string& url); + void OnRPPCtrlerTimeout(const std::string& url); + void DoRPPCtrlerTimeout(const std::string& url); + void DoRmPageUrl(const std::string& in_org_url); + void FindCurPreloadInfoAndRun(const std::string& key, + std::function func); + bool is_inited_ { false }; scoped_refptr sth_task_runner_; scoped_refptr net_task_runner_; scoped_refptr disk_cache_backend_factory_; - std::atomic_bool is_inited_ { false }; - std::mutex mgr_mutex_; - std::list stopped_pages_; + std::unordered_map prp_preload_info_map_; + std::unordered_map web_handle_pages_map_; + base::WeakPtrFactory weak_factory_ { this }; + std::unordered_map prp_page_url_; }; } // namespace ohos_prp_preload -#endif // NET_PRP_PRELOAD_SRC_PAGR_RES_PARALLEL_PRELOAD_MGR_IMPL_H +#endif // SERVICES_NETWORK_PRP_PRELOAD_SRC_PAGR_RES_PARALLEL_PRELOAD_MGR_IMPL_H \ No newline at end of file diff --git a/net/prp_preload/src/preconnect_runner.cc b/services/network/prp_preload/src/preload_runner/preconnect_runner.cc similarity index 81% rename from net/prp_preload/src/preconnect_runner.cc rename to services/network/prp_preload/src/preload_runner/preconnect_runner.cc index 816902353a..9f205ccefc 100644 --- a/net/prp_preload/src/preconnect_runner.cc +++ b/services/network/prp_preload/src/preload_runner/preconnect_runner.cc @@ -2,11 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "preconnect_runner.h" +#include "services/network/prp_preload/src/preload_runner/preconnect_runner.h" -#include "base/ohos/sys_info_utils.h" #include "net/base/http_user_agent_settings.h" -#include "net/base/network_anonymization_key.h" #include "net/http/http_network_session.h" #include "net/http/http_transaction_factory.h" #include "net/http/transport_security_state.h" @@ -17,16 +15,11 @@ namespace ohos_prp_preload { void PreconnectRunner::PreconnectSocket( const GURL& original_url, bool allow_credentials, - base::WeakPtr url_request_context, - const net::NetworkAnonymizationKey& networkAnonymizationKey) { + const net::NetworkAnonymizationKey& network_anonymization_key, + base::WeakPtr url_request_context) { if (url_request_context.get() == nullptr) { return; } - net::NetworkAnonymizationKey key = - net::NetworkAnonymizationKey::CreateSameSite(net::SchemefulSite(original_url)); - if (base::ohos::IsPcDevice() == true ) { - key = networkAnonymizationKey; - } GURL url = GetHSTSRedirect(original_url, url_request_context); @@ -48,8 +41,8 @@ void PreconnectRunner::PreconnectSocket( request_info.load_flags = net::LOAD_DO_NOT_SAVE_COOKIES; request_info.privacy_mode = net::PRIVACY_MODE_ENABLED; } - - request_info.network_anonymization_key = key; + + request_info.network_anonymization_key = network_anonymization_key; net::HttpTransactionFactory* factory = url_request_context->http_transaction_factory(); diff --git a/net/prp_preload/src/preconnect_runner.h b/services/network/prp_preload/src/preload_runner/preconnect_runner.h similarity index 67% rename from net/prp_preload/src/preconnect_runner.h rename to services/network/prp_preload/src/preload_runner/preconnect_runner.h index 8e094f0f16..03a8c95a4b 100644 --- a/net/prp_preload/src/preconnect_runner.h +++ b/services/network/prp_preload/src/preload_runner/preconnect_runner.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_PRP_PRELOAD_SRC_PRECONNECT_RUNNER_H -#define NET_PRP_PRELOAD_SRC_PRECONNECT_RUNNER_H +#ifndef SERVICES_NETWORK_PRP_PRELOAD_SRC_PRELOAD_RUNNER_PRECONNECT_RUNNER_H +#define SERVICES_NETWORK_PRP_PRELOAD_SRC_PRELOAD_RUNNER_PRECONNECT_RUNNER_H #include "base/memory/weak_ptr.h" #include "net/base/network_anonymization_key.h" @@ -20,8 +20,8 @@ class PreconnectRunner { public: static void PreconnectSocket(const GURL& original_url, bool allow_credentials, - base::WeakPtr url_request_context, - const net::NetworkAnonymizationKey& networkAnonymizationKey); + const net::NetworkAnonymizationKey& network_anonymization_key, + base::WeakPtr url_request_context); static GURL GetHSTSRedirect(const GURL& original_url, base::WeakPtr url_request_context); private: @@ -31,4 +31,4 @@ class PreconnectRunner { } // namespace ohos_prp_preload -#endif // NET_PRP_PRELOAD_SRC_PRECONNECT_RUNNER_H \ No newline at end of file +#endif // SERVICES_NETWORK_PRP_PRELOAD_SRC_PRELOAD_RUNNER_PRECONNECT_RUNNER_H \ No newline at end of file diff --git a/services/network/prp_preload/src/preload_runner/prpp_request_loader_factory_impl.cc b/services/network/prp_preload/src/preload_runner/prpp_request_loader_factory_impl.cc new file mode 100644 index 0000000000..ee64c26b7d --- /dev/null +++ b/services/network/prp_preload/src/preload_runner/prpp_request_loader_factory_impl.cc @@ -0,0 +1,289 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/prp_preload/src/preload_runner/prpp_request_loader_factory_impl.h" + +#include "base/logging.h" +#include "base/trace_event/trace_event.h" +#include "services/network/network_context.h" +#include "net/http/http_util.h" + +namespace ohos_prp_preload { +std::shared_ptr PRPPRequestLoaderFactory::CreatePRPPRequestLoaderFactory( + const std::string& url, + base::WeakPtr url_request_context, + base::WeakPtr network_context) +{ + std::shared_ptr prpp_req_loader_fac = std::make_shared( + url, url_request_context, network_context); + return prpp_req_loader_fac; +} +PRPPRequestLoaderFactoryImpl::PRPPRequestLoaderFactoryImpl(const std::string& url, + base::WeakPtr url_request_context, + base::WeakPtr network_context) + : main_url_(url), url_request_context_(url_request_context), network_context_(network_context) {} + +void PRPPRequestLoaderFactoryImpl::CreateReqLoaderAndStart(const std::shared_ptr& info, + bool only_send_reuse_request, const std::set& need_record_header_urls) +{ + if (!url_request_context_ || !network_context_ || !info) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderFactoryImpl::CreateReqLoaderAndStart failed, " << + "invalid context or info"; + return; + } + + only_send_reuse_request_ = only_send_reuse_request; + + std::string sub_url = info->url().spec(); + if (requests_already_start_set_.find(sub_url) != requests_already_start_set_.end()) { + return; + } + + if (!need_record_header_urls.empty() && need_record_header_urls_.empty()) { + need_record_header_urls_ = need_record_header_urls; + } + + if (info->preload_flag() == + (PRRequestFlags)(PRPP_FLAGS_VISIBLE | PRPP_FLAGS_URL_DYNAMIC) && + only_send_reuse_request_) { + (void)dynamic_urls_.emplace(sub_url); + } + + if (info->preload_flag() == (PRRequestFlags)(PRPP_FLAGS_VISIBLE | PRPP_FLAGS_HDR_DYNAMIC)) { + auto item = can_reuse_headers_map_.find(info->parent_for_dynamic_header().spec()); + if (item == can_reuse_headers_map_.end()) { + RecordPendingPRPPLoader(info); + return; + } + ReplaceHeaders(item->second, info); + } + std::shared_ptr prpp_req_loader = PRPPRequestLoader::CreatePRPPRequestLoader( + main_url_, info, isolation_info_, url_request_context_, + base::BindOnce(&PRPPRequestLoaderFactoryImpl::OnResPreloaded, weak_factory_.GetWeakPtr())); + (void)prpp_req_loaders_.emplace(sub_url, prpp_req_loader); +} + +void PRPPRequestLoaderFactoryImpl::SetPRPPIsolation(const net::IsolationInfo& isl) +{ + if (isl.IsEmpty()) { + return; + } + + isolation_info_ = isl; +} + +std::shared_ptr PRPPRequestLoaderFactoryImpl::GetPRPPReqLoader( + const network::URLLoaderContext& context, + const network::ResourceRequest& resource_request, + std::shared_ptr req_info_binding) +{ + if (need_record_header_urls_.find(resource_request.url.spec()) != need_record_header_urls_.end()) { + (void)can_reuse_headers_map_.emplace(resource_request.url.spec(), resource_request.headers); + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&PRPPRequestLoaderFactoryImpl::DoPendingCreateTask, + weak_factory_.GetWeakPtr(), resource_request.url.spec())); + (void)need_record_header_urls_.erase(resource_request.url.spec()); + } + + req_info_binding->set_only_send_reuse_request(only_send_reuse_request_); + + if (!net::HttpUtil::IsMethodSafe(resource_request.method)) { + LOG(DEBUG) << "PRPPreload.PRPPRequestLoaderFactoryImpl::GetPRPPReqLoader not support method:" << + resource_request.method; + return nullptr; + } + if (!isolation_info_.IsEmpty() && !context.GetFactoryParams().isolation_info.IsEmpty()) { + std::string prp_isolationinfo = isolation_info_.Serialize(); + std::string sub_isolationinfo = context.GetFactoryParams().isolation_info.Serialize(); + if (prp_isolationinfo != sub_isolationinfo) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderFactoryImpl::GetPRPPReqLoader isolationinfo not match"; + return nullptr; + } + } + + std::string sub_url = resource_request.url.spec(); + PRPPReqLoaderMap::iterator it = prpp_req_loaders_.end(); + if (resource_request.is_preflight) { + it = prpp_req_loaders_.find(std::string(PRPP_PREFLIGHT_PREFIX) + sub_url); + } else { + it = prpp_req_loaders_.find(sub_url); + } + if (it == prpp_req_loaders_.end()) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderFactoryImpl::GetPRPPReqLoader not find"; + (void)requests_already_start_set_.emplace(sub_url); + if (dynamic_urls_.find(sub_url) != dynamic_urls_.end() && only_send_reuse_request_) { + req_info_binding->set_preload_flag(PRPP_FLAGS_VISIBLE); + } + return nullptr; + } + + std::shared_ptr loader = it->second; + if (!loader.get()) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderFactoryImpl::GetPRPPReqLoader loader is null"; + return nullptr; + } + if (loader->GetState() >= PRPPRequestLoader::STATE_UNSUPPORT) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderFactoryImpl::GetPRPPReqLoader loader invalid state"; + (void)prpp_req_loaders_.erase(it); + return nullptr; + } + + std::shared_ptr info = loader->GetPRRequestInfo(); + if (!IsInfoMatched(info, context, resource_request, req_info_binding)) { + (void)prpp_req_loaders_.erase(it); + return nullptr; + } + (void)prpp_req_loaders_.erase(it); + return loader; +} + +bool PRPPRequestLoaderFactoryImpl::IsInfoMatched(std::shared_ptr& req_info, + const network::URLLoaderContext& context, const network::ResourceRequest& resource_request, + std::shared_ptr& req_info_binding) +{ + if (!req_info) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderFactoryImpl::IsInfoMatched no reqinfo"; + return false; + } + + if (req_info->method() != resource_request.method) { + LOG(DEBUG) << "PRPPreload.PRPPRequestLoaderFactoryImpl::IsInfoMatched check method failed"; + return false; + } + + if (resource_request.request_body.get()) { + LOG(DEBUG) << "PRPPreload.PRPPRequestLoaderFactoryImpl::IsInfoMatched has request body, not support"; + return false; + } + + if (resource_request.trust_token_params) { + req_info_binding->or_preload_flag(PRPP_FLAGS_HDR_NOT_MATCH); + LOG(DEBUG) << "PRPPreload.PRPPRequestLoaderFactoryImpl::IsInfoMatched trust_token_params, not support"; + return false; + } + + if ((req_info->cache_type() == PRRequestCacheType::FORCE_CACHE) && + (base::Time::Now().ToInternalValue() < req_info->freshness_life_times()) && + (((req_info->load_flags() & net::LOAD_BYPASS_CACHE) == 0) && + ((req_info->load_flags() & net::LOAD_DISABLE_CACHE) == 0))) { + return true; + } + + return MatchRequestHeaders(req_info, resource_request, req_info_binding); +} + +bool PRPPRequestLoaderFactoryImpl::MatchRequestHeaders(std::shared_ptr& req_info, + const network::ResourceRequest& resource_request, + std::shared_ptr& req_info_binding) +{ + bool match = true; + std::set dynamic_header_keys; + for (auto item : resource_request.headers.GetHeaderVector()) { + net::HttpRequestHeaders::HeaderVector::const_iterator iter = + req_info->extra_request_headers().GetHeaderVector().end(); + for (auto it = req_info->extra_request_headers().GetHeaderVector().begin(); + it != req_info->extra_request_headers().GetHeaderVector().end(); ++it) { + if (base::EqualsCaseInsensitiveASCII(item.key, it->key)) { + iter = it; + break; + } + } + if (iter == req_info->extra_request_headers().GetHeaderVector().end()) { + req_info_binding->or_preload_flag(PRPP_FLAGS_HDR_NOT_MATCH); + LOG(DEBUG) << "PRPPreload.PRPPRequestLoaderFactoryImpl::MatchRequestHeaders header not match, " << + "can not reuse " << item.key; + req_info->extra_request_headers().SetHeader(item.key, item.value); + return false; + } + + if (item.value != iter->value) { + LOG(DEBUG) << "PRPPreload.PRPPRequestLoaderFactoryImpl::MatchRequestHeaders header value not match, " << + "can not reuse " << item.key; + match = false; + (void)dynamic_header_keys.emplace(item.key); + req_info->extra_request_headers().RemoveHeader(item.key); + req_info->extra_request_headers().SetHeader(item.key, item.value); + } + } + + if (!match) { + req_info_binding->set_preload_flag(PRPP_FLAGS_HDR_DYNAMIC); + req_info_binding->set_dynamic_header_keys(dynamic_header_keys); + } + return match; +} + +void PRPPRequestLoaderFactoryImpl::OnResPreloaded(PRPPRequestLoader* prpp_loader) +{ + if (!prpp_loader) { + return; + } + preloaded_new_res_count_++; +} + +uint32_t PRPPRequestLoaderFactoryImpl::GetAndClearPreloadedCount() +{ + return preloaded_new_res_count_.exchange(0); +} + +void PRPPRequestLoaderFactoryImpl::DoPendingCreateTask(const std::string& key) +{ + auto list_item = pending_prpp_loader_list_.find(key); + if (list_item == pending_prpp_loader_list_.end()) { + return; + } + for (auto info : list_item->second) { + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&PRPPRequestLoaderFactoryImpl::CreatePendingReqLoaderAndStart, + weak_factory_.GetWeakPtr(), info)); + } +} + +void PRPPRequestLoaderFactoryImpl::CreatePendingReqLoaderAndStart(const std::shared_ptr& info) +{ + if (!url_request_context_ || !network_context_) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderFactoryImpl::CreatePendingReqLoaderAndStart failed, " << + "invalid context or info"; + return; + } + + std::string sub_url = info->url().spec(); + if (requests_already_start_set_.find(sub_url) != requests_already_start_set_.end()) { + return; + } + + auto item = can_reuse_headers_map_.find(info->parent_for_dynamic_header().spec()); + if (item != can_reuse_headers_map_.end()) { + ReplaceHeaders(item->second, info); + } + + std::shared_ptr prpp_req_loader = PRPPRequestLoader::CreatePRPPRequestLoader( + main_url_, info, isolation_info_, url_request_context_, + base::BindOnce(&PRPPRequestLoaderFactoryImpl::OnResPreloaded, weak_factory_.GetWeakPtr())); + (void)prpp_req_loaders_.emplace(sub_url, prpp_req_loader); +} + +void PRPPRequestLoaderFactoryImpl::ReplaceHeaders(const net::HttpRequestHeaders& headers, + const std::shared_ptr& info) +{ + for (auto key : info->dynamic_header_keys()) { + std::string record_header; + headers.GetHeader(key, &record_header); + info->extra_request_headers().RemoveHeader(key); + info->extra_request_headers().SetHeader(key, record_header); + } +} + +void PRPPRequestLoaderFactoryImpl::RecordPendingPRPPLoader(const std::shared_ptr& info) +{ + auto it = pending_prpp_loader_list_.find(info->parent_for_dynamic_header().spec()); + if (it != pending_prpp_loader_list_.end()) { + it->second.push_back(info); + } else { + pending_prpp_loader_list_[info->parent_for_dynamic_header().spec()] = + std::list>({info}); + } +} + +} // namespace ohos_prp_preload \ No newline at end of file diff --git a/services/network/prp_preload/src/preload_runner/prpp_request_loader_factory_impl.h b/services/network/prp_preload/src/preload_runner/prpp_request_loader_factory_impl.h new file mode 100644 index 0000000000..fa8b616917 --- /dev/null +++ b/services/network/prp_preload/src/preload_runner/prpp_request_loader_factory_impl.h @@ -0,0 +1,71 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_NETWORK_PRP_PRELOAD_SRC_PRELOAD_RUNNER_PRPP_REQUEST_LOADER_FACTORY_IMPL_H +#define SERVICES_NETWORK_PRP_PRELOAD_SRC_PRELOAD_RUNNER_PRPP_REQUEST_LOADER_FACTORY_IMPL_H + +#include "services/network/url_loader_context.h" +#include "services/network/prp_preload/include/preload_runner/prpp_request_loader_factory.h" +#include "services/network/prp_preload/include/preload_runner/prpp_request_loader.h" + +namespace net { +class URLRequestContext; +} // namespace net + +namespace network { +class NetworkContext; +} // namespace network + +namespace ohos_prp_preload { + +// only run in network thread +class PRPPRequestLoaderFactoryImpl : public PRPPRequestLoaderFactory { +public: + PRPPRequestLoaderFactoryImpl(const std::string& url, + base::WeakPtr url_request_context, + base::WeakPtr network_context); + ~PRPPRequestLoaderFactoryImpl() = default; + void CreateReqLoaderAndStart(const std::shared_ptr& info, + bool only_send_reuse_request, + const std::set& need_record_header_urls) override; + void SetPRPPIsolation(const net::IsolationInfo& isl) override; + std::shared_ptr GetPRPPReqLoader(const network::URLLoaderContext& context, + const network::ResourceRequest& resource_request, + std::shared_ptr req_info_binding) override; + base::WeakPtr GetWeak() override { return weak_factory_.GetWeakPtr(); } + const std::string& GetMainUrl() const override { return main_url_; } + uint32_t GetAndClearPreloadedCount() override; +private: + bool IsInfoMatched(std::shared_ptr& req_info, const network::URLLoaderContext& context, + const network::ResourceRequest& resource_request, + std::shared_ptr& req_info_binding); + bool MatchRequestHeaders(std::shared_ptr& req_info, + const network::ResourceRequest& resource_request, + std::shared_ptr& req_info_binding); + void OnResPreloaded(PRPPRequestLoader* prpp_loader); + void DoPendingCreateTask(const std::string& key); + void CreatePendingReqLoaderAndStart(const std::shared_ptr& info); + void ReplaceHeaders(const net::HttpRequestHeaders& headers, + const std::shared_ptr& info); + void RecordPendingPRPPLoader(const std::shared_ptr& info); + + using PRPPReqLoaderMap = std::unordered_map>; + std::string main_url_; + net::IsolationInfo isolation_info_; + base::WeakPtr url_request_context_; + base::WeakPtr network_context_; + PRPPReqLoaderMap prpp_req_loaders_; + std::set requests_already_start_set_; + base::WeakPtrFactory weak_factory_ { this }; + std::atomic preloaded_new_res_count_ { 0 }; + std::unordered_map can_reuse_headers_map_; + std::unordered_map>> pending_prpp_loader_list_; + std::set need_record_header_urls_; // key of can_reuse_headers_map_ + bool only_send_reuse_request_ { false }; + std::set dynamic_urls_; +}; + +} // namespace ohos_prp_preload + +#endif // SERVICES_NETWORK_PRP_PRELOAD_SRC_PRELOAD_RUNNER_PRPP_REQUEST_LOADER_FACTORY_IMPL_H \ No newline at end of file diff --git a/services/network/prp_preload/src/preload_runner/prpp_request_loader_impl.cc b/services/network/prp_preload/src/preload_runner/prpp_request_loader_impl.cc new file mode 100644 index 0000000000..025b8902b8 --- /dev/null +++ b/services/network/prp_preload/src/preload_runner/prpp_request_loader_impl.cc @@ -0,0 +1,646 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Based on url_loader.cc originally written by +// Copyright 2017 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/prp_preload/src/preload_runner/prpp_request_loader_impl.h" + +#include "base/logging.h" +#include "services/network/prp_preload/src/page_res_parallel_preload_mgr_impl.h" +#include "third_party/bounds_checking_function/include/securec.h" + +namespace { +const int32_t CACHE_BLOCK_SIZE = 64 * 1024; +} + +namespace ohos_prp_preload { +std::shared_ptr PRPPRequestLoader::CreatePRPPRequestLoader( + const std::string& main_url, + const std::shared_ptr& info, + const net::IsolationInfo& isolation_info, + base::WeakPtr url_request_context, + ResPreloadedCB res_loaded_cb) +{ + std::shared_ptr prpp_req_loader = std::make_shared( + main_url, info, url_request_context, std::move(res_loaded_cb)); + if (prpp_req_loader->Init(isolation_info)) { + return prpp_req_loader; + } + return nullptr; +} + +PRPPRequestLoaderImpl::PRPPRequestLoaderImpl(const std::string& main_url, + const std::shared_ptr& info, + base::WeakPtr url_request_context, + ResPreloadedCB res_loaded_cb) + : main_url_(main_url), sub_url_(info->url().spec()), url_request_context_(url_request_context), + res_loaded_cb_(std::move(res_loaded_cb)), prpp_req_info_(info) { } + +bool PRPPRequestLoaderImpl::Init(const net::IsolationInfo& isolation_info) +{ + if (!prpp_req_info_ || !url_request_context_.get()) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderImpl::Init, invalid args"; + return false; + } + real_load_flags_ = prpp_req_info_->load_flags(); + InitAndStartUrlRequest(prpp_req_info_, isolation_info); + return true; +} + +void PRPPRequestLoaderImpl::InitAndStartUrlRequest(const std::shared_ptr& info, + const net::IsolationInfo& isolation_info) +{ + if (info->type() == PRRequestInfoType::TYPE_PAGE_PREFLIGHT) { + sub_url_ = info->url().spec().substr(strlen(PRPP_PREFLIGHT_PREFIX)); + } + url_request_ = url_request_context_.get()->CreateRequestForPrpp(GURL(sub_url_), + net::MEDIUM, this, MISSING_TRAFFIC_ANNOTATION, false); + url_request_->set_method(info->method()); + url_request_->set_force_ignore_site_for_cookies(info->force_ignore_site_for_cookies()); + url_request_->SetURLChain( { GURL(sub_url_) } ); + url_request_->SetReferrer(info->referrer()); + url_request_->set_referrer_policy(info->referrer_policy()); + url_request_->set_upgrade_if_insecure(info->upgrade_if_insecure()); + if (isolation_info.IsEmpty()) { + url::Origin origin = url::Origin::Create(GURL(sub_url_)); + net::IsolationInfo iso_info = net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + origin, origin, net::SiteForCookies()); + url_request_->set_site_for_cookies(iso_info.site_for_cookies()); + url_request_->set_isolation_info(iso_info); + } else { + url_request_->set_site_for_cookies(isolation_info.site_for_cookies()); + url_request_->set_isolation_info(isolation_info); + } + url_request_->set_force_main_frame_for_same_site_cookies(info->force_main_frame_for_same_site_cookies()); + url_request_->SetSecureDnsPolicy(info->secure_dns_policy()); + url_request_->SetExtraRequestHeaders(info->extra_request_headers()); + + if (info->accepted_stream_types().has_value()) { + url_request_->set_accepted_stream_types(info->accepted_stream_types()); + } + if (info->initiator().has_value()) { + url_request_->set_initiator(info->initiator()); + } + url_request_->set_first_party_url_policy(info->first_party_url_policy()); + url_request_->SetLoadFlags(real_load_flags_); + if (!info->allow_credentials()) { + url_request_->set_allow_credentials(false); + } + url_request_->set_send_client_certs(info->send_client_certs()); + url_request_->SetRequestHeadersCallback(base::BindRepeating( + &PRPPRequestLoaderImpl::SetRawRequestHeadersAndNotify, base::Unretained(this))); + url_request_->SetResponseHeadersCallback(base::BindRepeating( + &PRPPRequestLoaderImpl::SetRawResponseHeaders, base::Unretained(this))); + url_request_->SetEarlyResponseHeadersCallback(base::BindRepeating( + &PRPPRequestLoaderImpl::NotifyEarlyResponse, base::Unretained(this))); + url_request_->set_has_storage_access(info->has_storage_access()); + url_request_->cookie_setting_overrides().PutAll(info->cookie_setting_overrides()); + url_request_->set_update_res_request_info_callback( + base::BindRepeating(&PRPPRequestLoaderImpl::UpdateResRequestInfo, + weak_ptr_factory_.GetWeakPtr())); + url_request_->set_allow_preload_record(true); + url_request_->set_main_url(GURL(main_url_)); + url_request_->set_preload_info(prpp_req_info_); + + BeginTrustTokenOperationIfNecessaryAndThenScheduleStart(); +} + +void PRPPRequestLoaderImpl::ReInitAndStartUrlRequest() +{ + preload_state_ = STATE_IDLE; + ClearLoader(); + InitAndStartUrlRequest(prpp_req_info_, url_request_->isolation_info()); +} + +void PRPPRequestLoaderImpl::BeginTrustTokenOperationIfNecessaryAndThenScheduleStart() +{ + // only support no trust token params now. + BeginAttributionIfNecessaryAndThenScheduleStart(); +} + +void PRPPRequestLoaderImpl::BeginAttributionIfNecessaryAndThenScheduleStart() +{ + // only support !attribution_request_helper_ + ScheduleStart(); +} + +void PRPPRequestLoaderImpl::ScheduleStart() +{ + // for sub resource start directly. + url_request_->Start(); +} + +void PRPPRequestLoaderImpl::SetRawRequestHeadersAndNotify(net::HttpRawRequestHeaders headers) +{ + if (preload_state_ >= STATE_REQ_SENT) { + LOG(DEBUG) << "PRPPreload.PRPPRequestLoaderImpl::SetRawRequestHeadersAndNotify, invalid state:" << + (int32_t)preload_state_; + return; + } + raw_req_headers_ = std::move(headers); + rec_msg_list_.push(MSG_RAW_REQ_HDR); + preload_state_ = STATE_REQ_SENT; + if (need_do_replay_self_) { + DoReplay(); + } +} + +void PRPPRequestLoaderImpl::NotifyEarlyResponse(scoped_refptr headers) +{ + if (preload_state_ >= STATE_ERALY_HEAD_RESPONSED) { + LOG(DEBUG) << "PRPPreload.PRPPRequestLoaderImpl::NotifyEarlyResponse, invalid state:" << + (int32_t)preload_state_; + return; + } + early_response_headers_ = headers; + rec_msg_list_.push(MSG_EARLY_RESP_HDR); + preload_state_ = STATE_ERALY_HEAD_RESPONSED; + if (need_do_replay_self_) { + DoReplay(); + } +} + +void PRPPRequestLoaderImpl::SetRawResponseHeaders(scoped_refptr headers) +{ + if (preload_state_ >= STATE_HEAD_RESPONSED) { + LOG(DEBUG) << "PRPPreload.PRPPRequestLoaderImpl::SetRawResponseHeaders, invalid state:" << + (int32_t)preload_state_; + return; + } + raw_response_headers_ = headers; + rec_msg_list_.push(MSG_RAW_RESP_HDR); + preload_state_ = STATE_HEAD_RESPONSED; + if (need_do_replay_self_) { + DoReplay(); + } +} + +int PRPPRequestLoaderImpl::OnConnected(net::URLRequest* url_request, + const net::TransportInfo& info, + net::CompletionOnceCallback callback) +{ + int ret = net::OK; + if (preload_state_ >= STATE_CONNECTED) { + LOG(DEBUG) << "PRPPreload.PRPPRequestLoaderImpl::OnConnected, invalid state:" << + (int32_t)preload_state_; + return ret; + } + transport_info_ = info; + completion_once_callback_ = std::move(callback); + rec_msg_list_.push(MSG_CONNECTED); + preload_state_ = STATE_CONNECTED; + if (need_do_replay_self_) { + DoReplay(); + } + return ret; +} + +void PRPPRequestLoaderImpl::OnReceivedRedirect(net::URLRequest* url_request, + const net::RedirectInfo& redirect_info, + bool* defer_redirect) +{ + if (!res_loaded_cb_.is_null()) { + std::move(res_loaded_cb_).Run(this); + } + PushFailure(STATE_UNSUPPORT, need_do_replay_self_); +} + +void PRPPRequestLoaderImpl::OnAuthRequired(net::URLRequest* request, + const net::AuthChallengeInfo& info) +{ + if (!res_loaded_cb_.is_null()) { + std::move(res_loaded_cb_).Run(this); + } + PushFailure(STATE_UNSUPPORT, need_do_replay_self_); +} + +void PRPPRequestLoaderImpl::OnCertificateRequested(net::URLRequest* request, + net::SSLCertRequestInfo* info) +{ + if (!res_loaded_cb_.is_null()) { + std::move(res_loaded_cb_).Run(this); + } + PushFailure(STATE_UNSUPPORT, need_do_replay_self_); +} + +void PRPPRequestLoaderImpl::OnSSLCertificateError(net::URLRequest* request, + int net_error, + const net::SSLInfo& info, + bool fatal) +{ + if (!res_loaded_cb_.is_null()) { + std::move(res_loaded_cb_).Run(this); + } + PushFailure(STATE_UNSUPPORT, need_do_replay_self_); +} + +void PRPPRequestLoaderImpl::OnResponseStarted(net::URLRequest* url_request, int net_error) +{ + if ((net_error == net::ERR_CACHE_MISS) && + ((real_load_flags_ & net::LOAD_ONLY_FROM_CACHE) == net::LOAD_ONLY_FROM_CACHE)) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderImpl::OnResponseStarted, ERR_CACHE_MISS try restart"; + real_load_flags_ &= (~net::LOAD_ONLY_FROM_CACHE); + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&PRPPRequestLoaderImpl::ReInitAndStartUrlRequest, weak_ptr_factory_.GetWeakPtr())); + return; + } + + if (preload_state_ >= STATE_RESPONSE_STARTED) { + LOG(DEBUG) << "PRPPreload.PRPPRequestLoaderImpl::OnResponseStarted, invalid state:" << + (int32_t)preload_state_; + return; + } + + if (net_error != net::OK) { + PushFailure(STATE_UNSUPPORT, need_do_replay_self_); + return; + } + preload_state_ = STATE_RESPONSE_STARTED; + rec_msg_list_.push(MSG_RESPONSE_STARTED); + if (need_do_replay_self_) { + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&PRPPRequestLoaderImpl::DoReplay, weak_ptr_factory_.GetWeakPtr())); + } + FinalizeAttributionIfNecessaryAndThenContinueOnResponseStarted(); +} + +void PRPPRequestLoaderImpl::FinalizeAttributionIfNecessaryAndThenContinueOnResponseStarted() +{ + // only support !attribution_request_helper_ + ContinueOnResponseStarted(); +} + +void PRPPRequestLoaderImpl::ContinueOnResponseStarted() +{ + StartReading(); +} + +void PRPPRequestLoaderImpl::StartReading() +{ + ReadMore(); +} + +void PRPPRequestLoaderImpl::ReadMore() +{ + if (!cur_write_block_) { + cur_write_block_ = base::MakeRefCounted(); + if (!cur_write_block_) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderImpl::ReadMore, make cache block failed"; + PushFailure(STATE_ERROR); + return; + } + cur_write_block_->SetCapacity(CACHE_BLOCK_SIZE); + cur_write_block_->set_offset(0); + if (!cur_write_block_->StartOfBuffer()) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderImpl::ReadMore, allocate cache block failed"; + PushFailure(STATE_ERROR); + cur_write_block_ = nullptr; + return; + } + } else if (cur_write_block_->RemainingCapacity() == 0) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderImpl::ReadMore, no left cache block"; + PushFailure(STATE_ERROR); + return; + } + + int bytes_read = url_request_->Read(cur_write_block_.get(), cur_write_block_->RemainingCapacity()); + if (bytes_read != net::ERR_IO_PENDING) { + DidRead(bytes_read, true); + } +} + +void PRPPRequestLoaderImpl::DidRead(int num_bytes, bool completed_synchronously) +{ + if (num_bytes > cur_write_block_->RemainingCapacity() || num_bytes < 0) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderImpl::DidRead, left cache block not enough"; + PushFailure(STATE_ERROR); + return; + } + + if (num_bytes == 0) { + total_size_ += (cur_write_block_->capacity() - cur_write_block_->RemainingCapacity()); + body_cache_.push(cur_write_block_); + cur_write_block_ = nullptr; + preload_state_ = STATE_RESPONSED; + if (out_buf_ && delegate_) { + int len = Read(out_buf_.get(), out_max_bytes_); + delegate_->OnReadCompleted(url_request_.get(), len); + } + return; + } + + cur_write_block_->set_offset(cur_write_block_->offset() + num_bytes); + if (cur_write_block_->RemainingCapacity() == 0) { + total_size_ += cur_write_block_->capacity(); + body_cache_.push(cur_write_block_); + cur_write_block_ = nullptr; + if (out_buf_ && delegate_) { + int len = Read(out_buf_.get(), out_max_bytes_); + delegate_->OnReadCompleted(url_request_.get(), len); + } + } + if (completed_synchronously) { + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE, + base::BindOnce(&PRPPRequestLoaderImpl::ReadMore, weak_ptr_factory_.GetWeakPtr())); + } else { + ReadMore(); + } +} + +void PRPPRequestLoaderImpl::OnReadCompleted(net::URLRequest* request, int bytes_read) +{ + if (!res_loaded_cb_.is_null()) { + std::move(res_loaded_cb_).Run(this); + } + + if ((preload_state_ == STATE_UNSUPPORT) || (preload_state_ == STATE_ERROR)) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderImpl::OnReadCompleted, invalid state:" << + (int32_t)preload_state_; + return; + } + DidRead(bytes_read, false); +} + +void PRPPRequestLoaderImpl::SetRequestDelegate(net::URLRequest::Delegate* delegate) +{ + delegate_ = delegate; +} + +void PRPPRequestLoaderImpl::SetRequestHeadersCallback(net::RequestHeadersCallback callback) +{ + request_headers_callback_ = std::move(callback); +} + +void PRPPRequestLoaderImpl::SetResponseHeadersCallback(net::ResponseHeadersCallback callback) +{ + response_headers_callback_ = std::move(callback); +} + +void PRPPRequestLoaderImpl::SetEarlyResponseHeadersCallback(net::ResponseHeadersCallback callback) +{ + early_response_headers_callback_ = std::move(callback); +} + +bool PRPPRequestLoaderImpl::StartReplay() +{ + load_timing_info_.request_start_time = base::Time::Now(); + load_timing_info_.request_start = base::TimeTicks::Now(); + + if (!delegate_ || (preload_state_ == STATE_UNSUPPORT) || (preload_state_ == STATE_ERROR)) { + return false; + } + + prpp_req_info_->or_preload_flag(ohos_prp_preload::PRPP_FLAGS_VISIBLE); + prpp_req_info_->set_request_start_time(base::Time::Now().ToInternalValue()); + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE, + base::BindOnce(&PRPPRequestLoaderImpl::DoReplay, weak_ptr_factory_.GetWeakPtr())); + if (need_update_req_info_) { + PRParallelPreloadMgr::GetInstance().UpdateResRequestInfo(main_url_, prpp_req_info_); + } + return true; +} + +void PRPPRequestLoaderImpl::DoReplay() +{ + if (rec_msg_list_.empty()) { + if (preload_state_ != STATE_RESPONSED && preload_state_ != STATE_UNSUPPORT && + preload_state_ != STATE_ERROR) { + need_do_replay_self_ = true; + } + return; + } + if (!delegate_) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderImpl::DoReplay, no delegate"; + return; + } + PRPPRecorderMsg cur_msg = rec_msg_list_.front(); + rec_msg_list_.pop(); + switch (cur_msg) { + case MSG_CONNECTED: + delegate_->OnConnected(url_request_.get(), transport_info_, std::move(completion_once_callback_)); + break; + case MSG_RAW_REQ_HDR: + if (!request_headers_callback_.is_null()) { + request_headers_callback_.Run(std::move(raw_req_headers_)); + } + break; + case MSG_EARLY_RESP_HDR: + if (!early_response_headers_callback_.is_null()) { + early_response_headers_callback_.Run(early_response_headers_); + } + break; + case MSG_RAW_RESP_HDR: + if (!response_headers_callback_.is_null()) { + response_headers_callback_.Run(raw_response_headers_); + } + break; + case MSG_RESPONSE_STARTED: + need_do_replay_self_ = false; + delegate_->OnResponseStarted(url_request_.get(), net::OK); + break; + case MSG_RESPONSE_BODY: + break; + case MSG_ERROR: + default: + delegate_->OnResponseStarted(url_request_.get(), PRPP_ERROR); + break; + } + if (!rec_msg_list_.empty() || + ((preload_state_ != STATE_RESPONSE_STARTED) && (preload_state_ != STATE_RESPONSED))) { + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE, + base::BindOnce(&PRPPRequestLoaderImpl::DoReplay, weak_ptr_factory_.GetWeakPtr())); + } +} + +int PRPPRequestLoaderImpl::Read(net::IOBuffer* buf, int max_bytes) +{ + int ret = net::OK; + do { + if (max_bytes <= 0) { + break; + } + + if (body_cache_.empty()) { + if (preload_state_ != STATE_RESPONSED && preload_state_ != STATE_UNSUPPORT && + preload_state_ != STATE_ERROR) { + ret = net::ERR_IO_PENDING; + } + break; + } + scoped_refptr cur_block = body_cache_.front(); + if (!cur_block) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderImpl::Read, cur block is null, cache block size:" << + (int)body_cache_.size() << ", max_bytes:" << max_bytes; + break; + } + int block_offset = - cur_block->offset() + cur_read_offset_; + if (cur_block->offset() <= max_bytes + cur_read_offset_) { + int len = cur_block->offset() - cur_read_offset_; + if (memcpy_s(buf->data(), len, cur_block->data() + block_offset, len) != EOK) { + break; + } + body_cache_.pop(); + cur_read_offset_ = 0; + ret = len; + break; + } + if (memcpy_s(buf->data(), max_bytes, cur_block->data() + block_offset, max_bytes) != EOK) { + break; + } + cur_read_offset_ += max_bytes; + ret = max_bytes; + } while (false); + + if (ret == net::ERR_IO_PENDING) { + out_buf_ = buf; + out_max_bytes_ = max_bytes; + } else { + out_buf_ = nullptr; + out_max_bytes_ = 0; + } + + return ret; +} + +void PRPPRequestLoaderImpl::UpdateResRequestInfo(const std::string& key, const std::shared_ptr& info) +{ + if (delegate_) { + PRParallelPreloadMgr::GetInstance().UpdateResRequestInfo(key, info); + return; + } + need_update_req_info_ = true; +} + +void PRPPRequestLoaderImpl::PushFailure(PRPPReqLoaderState state, bool need_do_replay_self) +{ + if ((preload_state_ == STATE_UNSUPPORT) || (preload_state_ == STATE_ERROR)) { + return; + } + preload_state_ = state; + ClearMsgList(); + rec_msg_list_.push(MSG_ERROR); + if (need_do_replay_self) { + DoReplay(); + } +} + +void PRPPRequestLoaderImpl::ClearMsgList() +{ + std::queue msg_list; + rec_msg_list_.swap(msg_list); +} + +void PRPPRequestLoaderImpl::ClearBodyCache() +{ + std::queue> body_cache; + body_cache_.swap(body_cache); +} + +void PRPPRequestLoaderImpl::ClearLoader() +{ + ClearMsgList(); + ClearBodyCache(); + cur_write_block_ = nullptr; + out_buf_ = nullptr; + out_max_bytes_ = 0; + cur_read_offset_ = 0; + total_size_ = 0; +} + +void PRPPRequestLoaderImpl::GetLoadTimingInfo(net::LoadTimingInfo* load_timing_info) const +{ + if (!load_timing_info || !url_request_) { + LOG(WARNING) << "PRPPreload.PRPPRequestLoaderImpl::GetLoadTimingInfo, load_timing_info invalid"; + return; + } + + url_request_->GetLoadTimingInfo(load_timing_info); + load_timing_info->request_start_time = load_timing_info_.request_start_time; + load_timing_info->request_start = load_timing_info_.request_start; + + if (!load_timing_info->proxy_resolve_start.is_null()) { + load_timing_info->proxy_resolve_start = base::TimeTicks(); + } + if (!load_timing_info->proxy_resolve_end.is_null()) { + load_timing_info->proxy_resolve_end = base::TimeTicks(); + } + if (!load_timing_info->connect_timing.domain_lookup_start.is_null()) { + load_timing_info->connect_timing.domain_lookup_start = base::TimeTicks(); + } + if (!load_timing_info->connect_timing.domain_lookup_end.is_null()) { + load_timing_info->connect_timing.domain_lookup_end = base::TimeTicks(); + } + if (!load_timing_info->connect_timing.connect_start.is_null()) { + load_timing_info->connect_timing.connect_start = base::TimeTicks(); + } + if (!load_timing_info->connect_timing.connect_end.is_null()) { + load_timing_info->connect_timing.connect_end = base::TimeTicks(); + } + if (!load_timing_info->connect_timing.ssl_start.is_null()) { + load_timing_info->connect_timing.ssl_start = base::TimeTicks(); + } + if (!load_timing_info->connect_timing.ssl_end.is_null()) { + load_timing_info->connect_timing.ssl_end = base::TimeTicks(); + } + if (load_timing_info->connect_timing.connect_end.is_null()) { + load_timing_info->socket_reused = true; + } + + if (!load_timing_info->send_start.is_null() && + (load_timing_info->send_start.ToInternalValue() < + load_timing_info->request_start.ToInternalValue())) { + load_timing_info->send_start = load_timing_info->request_start; + } + if (!load_timing_info->send_end.is_null() && + (load_timing_info->send_end.ToInternalValue() < + load_timing_info->request_start.ToInternalValue())) { + load_timing_info->send_end = load_timing_info->request_start; + } + if (!load_timing_info->receive_headers_start.is_null() && + (load_timing_info->receive_headers_start.ToInternalValue() < + load_timing_info->request_start.ToInternalValue())) { + load_timing_info->receive_headers_start = load_timing_info->request_start; + } + if (!load_timing_info->receive_headers_end.is_null() && + (load_timing_info->receive_headers_end.ToInternalValue() < + load_timing_info->request_start.ToInternalValue())) { + load_timing_info->receive_headers_end = load_timing_info->request_start; + } + if (!load_timing_info->receive_non_informational_headers_start.is_null() && + (load_timing_info->receive_non_informational_headers_start.ToInternalValue() < + load_timing_info->request_start.ToInternalValue())) { + load_timing_info->receive_non_informational_headers_start = + load_timing_info->request_start; + } + if (!load_timing_info->first_early_hints_time.is_null() && + (load_timing_info->first_early_hints_time.ToInternalValue() < + load_timing_info->request_start.ToInternalValue())) { + load_timing_info->first_early_hints_time = load_timing_info->request_start; + } + if (!load_timing_info->push_start.is_null() && + (load_timing_info->push_start.ToInternalValue() < + load_timing_info->request_start.ToInternalValue())) { + load_timing_info->push_start = load_timing_info->request_start; + } + if (!load_timing_info->push_end.is_null() && + (load_timing_info->push_end.ToInternalValue() < + load_timing_info->request_start.ToInternalValue())) { + load_timing_info->push_end = load_timing_info->request_start; + } +} + +void PRPPRequestLoaderImpl::ClearLoaderCallback(bool has_devtools_request_id) +{ + SetRequestDelegate(nullptr); + SetRequestHeadersCallback(net::RequestHeadersCallback()); + if (has_devtools_request_id) { + SetResponseHeadersCallback(net::ResponseHeadersCallback()); + } + SetEarlyResponseHeadersCallback(net::ResponseHeadersCallback()); +} + +} // namespace ohos_prp_preload \ No newline at end of file diff --git a/services/network/prp_preload/src/preload_runner/prpp_request_loader_impl.h b/services/network/prp_preload/src/preload_runner/prpp_request_loader_impl.h new file mode 100644 index 0000000000..0d643f5b64 --- /dev/null +++ b/services/network/prp_preload/src/preload_runner/prpp_request_loader_impl.h @@ -0,0 +1,125 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_NETWORK_PRP_PRELOAD_SRC_PRELOAD_RUNNER_PRPP_REQUEST_LOADER_IMPL_H +#define SERVICES_NETWORK_PRP_PRELOAD_SRC_PRELOAD_RUNNER_PRPP_REQUEST_LOADER_IMPL_H + +#include "base/memory/scoped_refptr.h" +#include "services/network/prp_preload/include/preload_runner/prpp_request_loader.h" +#include "net/base/transport_info.h" +#include "net/url_request/url_request_context.h" + +namespace net { +class URLRequestContext; +} // namespace net + +namespace network { +class NetworkContext; +} // namespace network + +// only run in network thread +namespace ohos_prp_preload { +class PRPPRequestLoaderImpl : public PRPPRequestLoader, + public net::URLRequest::Delegate { + public: + enum PRPPRecorderMsg { + MSG_CONNECTED, + MSG_RAW_REQ_HDR, + MSG_EARLY_RESP_HDR, + MSG_RAW_RESP_HDR, + MSG_RESPONSE_STARTED, + MSG_RESPONSE_BODY, + MSG_ERROR, + }; + + PRPPRequestLoaderImpl(const std::string& main_url, + const std::shared_ptr& info, + base::WeakPtr url_request_context, + ResPreloadedCB res_loaded_cb); + ~PRPPRequestLoaderImpl() = default; + bool Init(const net::IsolationInfo& isolation_info) override; + void SetRequestDelegate(net::URLRequest::Delegate* delegate) override; + bool StartReplay() override; + void SetRequestHeadersCallback(net::RequestHeadersCallback callback) override; + void SetResponseHeadersCallback(net::ResponseHeadersCallback callback) override; + void SetEarlyResponseHeadersCallback(net::ResponseHeadersCallback callback) override; + int Read(net::IOBuffer* buf, int max_bytes) override; + std::shared_ptr GetURLRequest() override { return url_request_; } + std::shared_ptr GetPRRequestInfo() override { return prpp_req_info_; } + void GetLoadTimingInfo(net::LoadTimingInfo* load_timing_info) const override; + PRPPReqLoaderState GetState() const override { return preload_state_; } + void ClearLoaderCallback(bool has_devtools_request_id) override; + private: + void BeginTrustTokenOperationIfNecessaryAndThenScheduleStart(); + void BeginAttributionIfNecessaryAndThenScheduleStart(); + void ScheduleStart(); + void SetRawRequestHeadersAndNotify(net::HttpRawRequestHeaders headers); + void SetRawResponseHeaders(scoped_refptr headers); + void NotifyEarlyResponse(scoped_refptr headers); + void FinalizeAttributionIfNecessaryAndThenContinueOnResponseStarted(); + void ContinueOnResponseStarted(); + void StartReading(); + void ReadMore(); + void DidRead(int num_bytes, bool completed_synchronously); + void DoReplay(); + void UpdateResRequestInfo(const std::string& key, const std::shared_ptr& info); + void InitAndStartUrlRequest(const std::shared_ptr& info, + const net::IsolationInfo& isolation_info); + void ReInitAndStartUrlRequest(); + + // derived from net::URLRequest::Delegate + int OnConnected(net::URLRequest* url_request, + const net::TransportInfo& info, + net::CompletionOnceCallback callback) override; + void OnReceivedRedirect(net::URLRequest* url_request, + const net::RedirectInfo& redirect_info, + bool* defer_redirect) override; + void OnAuthRequired(net::URLRequest* request, + const net::AuthChallengeInfo& info) override; + void OnCertificateRequested(net::URLRequest* request, + net::SSLCertRequestInfo* info) override; + void OnSSLCertificateError(net::URLRequest* request, + int net_error, + const net::SSLInfo& info, + bool fatal) override; + void OnResponseStarted(net::URLRequest* url_request, int net_error) override; + void OnReadCompleted(net::URLRequest* request, int bytes_read) override; + void PushFailure(PRPPReqLoaderState state, bool need_do_replay_self = false); + void ClearMsgList(); + void ClearBodyCache(); + void ClearLoader(); + + std::string main_url_; + std::string sub_url_; + base::WeakPtr url_request_context_; + ResPreloadedCB res_loaded_cb_; + raw_ptr delegate_ { nullptr }; + std::shared_ptr url_request_ { nullptr }; + net::HttpRawRequestHeaders raw_req_headers_; + scoped_refptr early_response_headers_; + scoped_refptr raw_response_headers_; + net::TransportInfo transport_info_ {}; + PRPPReqLoaderState preload_state_ { STATE_IDLE }; + std::queue> body_cache_; + scoped_refptr cur_write_block_; + int cur_read_offset_ { 0 }; + uint32_t total_size_ { 0 }; + base::WeakPtrFactory weak_ptr_factory_ { this }; + std::queue rec_msg_list_; + net::CompletionOnceCallback completion_once_callback_; + net::RequestHeadersCallback request_headers_callback_; + net::ResponseHeadersCallback early_response_headers_callback_; + net::ResponseHeadersCallback response_headers_callback_; + scoped_refptr out_buf_ { nullptr }; + int out_max_bytes_ { 0 }; + bool need_do_replay_self_ { false }; + std::shared_ptr prpp_req_info_; + bool need_update_req_info_ { false }; + net::LoadTimingInfo load_timing_info_; + uint32_t real_load_flags_ { 0 }; +}; + +} // namespace ohos_prp_preload + +#endif // SERVICES_NETWORK_PRP_PRELOAD_SRC_PRELOAD_RUNNER_PRPP_REQUEST_LOADER_IMPL_H \ No newline at end of file diff --git a/net/prp_preload/src/res_parallel_preload_ctrler.cc b/services/network/prp_preload/src/res_parallel_preload_ctrler.cc similarity index 37% rename from net/prp_preload/src/res_parallel_preload_ctrler.cc rename to services/network/prp_preload/src/res_parallel_preload_ctrler.cc index f5c35ea5de..68ddecc716 100644 --- a/net/prp_preload/src/res_parallel_preload_ctrler.cc +++ b/services/network/prp_preload/src/res_parallel_preload_ctrler.cc @@ -2,37 +2,40 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "res_parallel_preload_ctrler.h" +#include "services/network/prp_preload/src/res_parallel_preload_ctrler.h" #include "base/logging.h" namespace { static constexpr base::TimeDelta MAX_CHECK_FLUSH_TO_DISK_TIME = base::Seconds(5); +static constexpr uint32_t MAX_FILTER_INFO_COUNT = 30; +static constexpr base::TimeDelta MAX_FILTER_INFO_TIME = base::Seconds(2); } // namespace namespace ohos_prp_preload { ResParallelPreloadCtrler::ResParallelPreloadCtrler(const std::string& url, - const net::NetworkAnonymizationKey& networkAnonymizationKey, - base::WeakPtr url_request_context, const scoped_refptr& sth_task_runner, - const scoped_refptr& net_task_runner, - const scoped_refptr& disk_cache_backend_factory, - const RPPCtrlerTimeoutCB& timeout_cb) : - url_(url), networkAnonymizationKey_(networkAnonymizationKey), - sth_task_runner_(sth_task_runner), timeout_cb_(timeout_cb) { + const PRPPCtrlerTimeoutCB& timeout_cb) : + url_(url), sth_task_runner_(sth_task_runner), timeout_cb_(timeout_cb) { } + +bool ResParallelPreloadCtrler::Init(const scoped_refptr& disk_cache_backend_factory, + const scoped_refptr& net_task_runner, + base::WeakPtr url_request_context, + const PRPPOnPageOriginCB& on_page_origin_cb) { res_req_info_updater_ = base::WrapRefCounted(new (std::nothrow) ResRequestInfoUpdater( - url_, networkAnonymizationKey_, sth_task_runner, disk_cache_backend_factory, - base::BindRepeating(&ResParallelPreloadCtrler::OnResRequestInfoList, weak_factory_.GetWeakPtr()))); + url_, sth_task_runner_, disk_cache_backend_factory, + base::BindRepeating(&ResParallelPreloadCtrler::OnResPreloadInfos, weak_factory_.GetWeakPtr()))); if (res_req_info_updater_ == nullptr) { - LOG(ERROR) << "PRPPreload.ResParallelPreloadCtrler::ResParallelPreloadCtrler new ResRequestInfoUpdater failed"; - return; + LOG(WARNING) << "PRPPreload.ResParallelPreloadCtrler::ResParallelPreloadCtrler new ResRequestInfoUpdater failed"; + return false; } res_preload_scheduler_ = base::WrapRefCounted(new (std::nothrow) ResPreloadScheduler( - sth_task_runner, net_task_runner, url_request_context)); + url_, sth_task_runner_, net_task_runner, url_request_context, on_page_origin_cb)); if (res_preload_scheduler_ == nullptr) { - LOG(ERROR) << "PRPPreload.ResParallelPreloadCtrler::ResParallelPreloadCtrler new ResPreloadScheduler failed"; - return; + LOG(WARNING) << "PRPPreload.ResParallelPreloadCtrler::ResParallelPreloadCtrler new ResPreloadScheduler failed"; + return false; } + return true; } void ResParallelPreloadCtrler::Start() { @@ -60,33 +63,101 @@ void ResParallelPreloadCtrler::Stop() { } void ResParallelPreloadCtrler::UpdateResRequestInfo(const std::shared_ptr& info) { - if ((res_req_info_updater_ == nullptr) || (res_preload_scheduler_ == nullptr)) { + if ((res_req_info_updater_ == nullptr) || + (res_preload_scheduler_ == nullptr) || + (sth_task_runner_ == nullptr)) { return; } sth_task_runner_->PostTask(FROM_HERE, base::BindOnce(&ResParallelPreloadCtrler::DoUpdateResRequestInfo, weak_factory_.GetWeakPtr(), info)); } +void ResParallelPreloadCtrler::SetPageOrigin(const std::string& page_origin) +{ + if ((res_req_info_updater_ == nullptr) || + (res_preload_scheduler_ == nullptr) || + (sth_task_runner_ == nullptr)) { + return; + } + sth_task_runner_->PostTask(FROM_HERE, base::BindOnce(&ResParallelPreloadCtrler::DoSetPageOrigin, + weak_factory_.GetWeakPtr(), std::move(page_origin))); +} + +void ResParallelPreloadCtrler::SetPRPPReqLoaderFac(base::WeakPtr loader_fac_weak) +{ + if ((res_req_info_updater_ == nullptr) || + (res_preload_scheduler_ == nullptr) || + (sth_task_runner_ == nullptr)) { + return; + } + sth_task_runner_->PostTask(FROM_HERE, base::BindOnce(&ResParallelPreloadCtrler::DoSetPRPPReqLoaderFac, + weak_factory_.GetWeakPtr(), loader_fac_weak)); +} + +void ResParallelPreloadCtrler::DoSetPageOrigin(const std::string& page_origin) +{ + if (res_req_info_updater_ == nullptr) { + return; + } + res_req_info_updater_->SetPageOrigin(page_origin); +} + +void ResParallelPreloadCtrler::DoSetPRPPReqLoaderFac(base::WeakPtr loader_fac_weak) +{ + if (res_preload_scheduler_ == nullptr) { + return; + } + res_preload_scheduler_->SetPRPPReqLoaderFac(loader_fac_weak); +} + void ResParallelPreloadCtrler::DoStart() { + if (res_req_info_updater_ == nullptr) { + return; + } res_req_info_updater_->Start(); } void ResParallelPreloadCtrler::DoStop() { + if ((res_req_info_updater_ == nullptr) || + (res_preload_scheduler_ == nullptr)) { + return; + } res_preload_scheduler_->StopPreload(); res_req_info_updater_->Stop(); } void ResParallelPreloadCtrler::DoUpdateResRequestInfo(const std::shared_ptr& info) { - res_req_info_updater_->UpdateResRequestInfo(info); + if ((info->preload_flag() == PRPP_FLAGS_NONE) && !start_filter_info_ + && sth_task_runner_ != nullptr) { + start_filter_info_ = true; + sth_task_runner_->PostDelayedTask(FROM_HERE, + base::BindOnce(&ResParallelPreloadCtrler::OnTimeout, weak_factory_.GetWeakPtr()), + MAX_FILTER_INFO_TIME); + } + if (start_filter_info_) { + if (filter_count_ > MAX_FILTER_INFO_COUNT) { + return; + } + ++filter_count_; + if (filter_count_ == MAX_FILTER_INFO_COUNT && sth_task_runner_ != nullptr) { + sth_task_runner_->PostTask(FROM_HERE, + base::BindOnce(&ResParallelPreloadCtrler::OnTimeout, weak_factory_.GetWeakPtr())); + } + } + + if (res_req_info_updater_ != nullptr) { + res_req_info_updater_->UpdateResRequestInfo(info); + } } -void ResParallelPreloadCtrler::OnResRequestInfoList( - const std::list>& res_req_info_list, - const net::NetworkAnonymizationKey& networkAnonymizationKey) { - if ((res_req_info_updater_ == nullptr) || (res_preload_scheduler_ == nullptr)) { +void ResParallelPreloadCtrler::OnResPreloadInfos(const PRPPPreconnectInfoList& preconnect_info_list, + const std::shared_ptr& preload_info_tree, bool only_send_reuse_request, + const std::set& need_record_header_urls) { + if (res_preload_scheduler_ == nullptr) { return; } - res_preload_scheduler_->PreloadSchedule(res_req_info_list, networkAnonymizationKey); + res_preload_scheduler_->SchedulePreloads(preconnect_info_list, preload_info_tree, + only_send_reuse_request, need_record_header_urls); } void ResParallelPreloadCtrler::OnTimeout() { diff --git a/net/prp_preload/src/res_parallel_preload_ctrler.h b/services/network/prp_preload/src/res_parallel_preload_ctrler.h similarity index 42% rename from net/prp_preload/src/res_parallel_preload_ctrler.h rename to services/network/prp_preload/src/res_parallel_preload_ctrler.h index 479d47ce4b..512f59f396 100644 --- a/net/prp_preload/src/res_parallel_preload_ctrler.h +++ b/services/network/prp_preload/src/res_parallel_preload_ctrler.h @@ -2,46 +2,50 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_PRP_PRELOAD_SRC_RES_PARALLEL_PRELOAD_CTRLER_H -#define NET_PRP_PRELOAD_SRC_RES_PARALLEL_PRELOAD_CTRLER_H +#ifndef SERVICES_NETWORK_PRP_PRELOAD_SRC_RES_PARALLEL_PRELOAD_CTRLER_H +#define SERVICES_NETWORK_PRP_PRELOAD_SRC_RES_PARALLEL_PRELOAD_CTRLER_H -#include "disk_cache_backend_factory.h" -#include "res_preload_scheduler.h" -#include "res_request_info_updater.h" +#include "services/network/prp_preload/src/res_preload_scheduler.h" +#include "services/network/prp_preload/src/res_request_info_updater.h" namespace ohos_prp_preload { -using RPPCtrlerTimeoutCB = base::RepeatingCallback; +using PRPPCtrlerTimeoutCB = base::RepeatingCallback; class ResParallelPreloadCtrler : public base::RefCounted { public: ResParallelPreloadCtrler(const std::string& url, - const net::NetworkAnonymizationKey& networkAnonymizationKey, - base::WeakPtr url_request_context, const scoped_refptr& sth_task_runner, - const scoped_refptr& net_task_runner, - const scoped_refptr& disk_cache_backend_factory, - const RPPCtrlerTimeoutCB& timeout_cb); + const PRPPCtrlerTimeoutCB& timeout_cb); ~ResParallelPreloadCtrler() = default; - + + bool Init(const scoped_refptr& disk_cache_backend_factory, + const scoped_refptr& net_task_runner, + base::WeakPtr url_request_context, + const PRPPOnPageOriginCB& on_page_origin_cb); void Start(); void Stop(); void UpdateResRequestInfo(const std::shared_ptr& info); + void SetPageOrigin(const std::string& page_origin); + void SetPRPPReqLoaderFac(base::WeakPtr loader_fac_weak); private: void DoStart(); void DoStop(); void DoUpdateResRequestInfo(const std::shared_ptr& info); - void OnResRequestInfoList(const std::list>& res_req_info_list, - const net::NetworkAnonymizationKey& networkAnonymizationKey); + void DoSetPageOrigin(const std::string& page_origin); + void DoSetPRPPReqLoaderFac(base::WeakPtr loader_fac_weak); + void OnResPreloadInfos(const PRPPPreconnectInfoList& preconnect_info_list, + const std::shared_ptr& preload_info_tree, bool only_send_reuse_request, + const std::set& need_record_header_urls); void OnTimeout(); - std::string url_; - const net::NetworkAnonymizationKey& networkAnonymizationKey_; scoped_refptr sth_task_runner_; scoped_refptr res_req_info_updater_; scoped_refptr res_preload_scheduler_; - RPPCtrlerTimeoutCB timeout_cb_; + PRPPCtrlerTimeoutCB timeout_cb_; base::WeakPtrFactory weak_factory_{this}; + bool start_filter_info_ { false }; + uint32_t filter_count_ { 0 }; }; } // namespace ohos_prp_preload -#endif // NET_PRP_PRELOAD_SRC_RES_PARALLEL_PRELOAD_CTRLER_H \ No newline at end of file +#endif // SERVICES_NETWORK_PRP_PRELOAD_SRC_RES_PARALLEL_PRELOAD_CTRLER_H \ No newline at end of file diff --git a/services/network/prp_preload/src/res_preload_scheduler.cc b/services/network/prp_preload/src/res_preload_scheduler.cc new file mode 100644 index 0000000000..4b6fbf3c50 --- /dev/null +++ b/services/network/prp_preload/src/res_preload_scheduler.cc @@ -0,0 +1,219 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/prp_preload/src/res_preload_scheduler.h" + +#include "base/logging.h" +#include "services/network/prp_preload/include/page_res_parallel_preload_mgr.h" +#include "services/network/prp_preload/src/preload_runner/preconnect_runner.h" +#include "net/http/http_util.h" + +namespace { +constexpr uint8_t SOCKET_LIMIT = 30; +constexpr uint8_t MAX_REQUEST_COUNT = 12; +constexpr uint8_t DELAYED_TIME = 5; +const std::string PRIVACY_TAG = "ac/"; +const std::string CANCEL_ORIGIN = "origin.DEFAULT.Cancel"; +} // namespace + +namespace ohos_prp_preload { + +ResPreloadScheduler::ResPreloadScheduler(const std::string& url, + const scoped_refptr& sth_task_runner, + const scoped_refptr& net_task_runner, + base::WeakPtr url_request_context, + const PRPPOnPageOriginCB& on_page_origin_cb) : + url_(url), sth_task_runner_(sth_task_runner), net_task_runner_(net_task_runner), + url_request_context_(url_request_context), on_page_origin_cb_(on_page_origin_cb) {} + +void ResPreloadScheduler::CreateReqLoaderAndStart(const std::shared_ptr& info) +{ + if (net_task_runner_ == nullptr) { + return; + } + if (loader_fac_weak_.get() == nullptr) { + prerequest_info_list_.push_back(info); + return; + } + + net_task_runner_->PostTask(FROM_HERE, base::BindOnce(&PRPPRequestLoaderFactory::CreateReqLoaderAndStart, + loader_fac_weak_, info, only_send_reuse_request_, need_record_header_urls_)); +} + +void ResPreloadScheduler::StopPreload() +{ + preload_triggered_ = false; + idle_connect_list_.clear(); + prerequest_info_list_.clear(); + prpp_preconnect_info_list_.clear(); + preload_info_tree_ = nullptr; + cur_parent_ = nullptr; + need_record_header_urls_.clear(); +} + +void ResPreloadScheduler::DoPendingPreRequest() +{ + if (net_task_runner_ == nullptr) { + return; + } + for (InfoIter it = prerequest_info_list_.begin(); it != prerequest_info_list_.end();) { + std::shared_ptr info = *it; + net_task_runner_->PostTask(FROM_HERE, base::BindOnce(&PRPPRequestLoaderFactory::CreateReqLoaderAndStart, + loader_fac_weak_, info, only_send_reuse_request_, need_record_header_urls_)); + (void)prerequest_info_list_.erase(it++); + } +} + +void ResPreloadScheduler::SetPRPPReqLoaderFac(base::WeakPtr loader_fac_weak) +{ + loader_fac_weak_ = loader_fac_weak; + PRPPRequestLoaderFactory* loader_fac = loader_fac_weak_.get(); + if (loader_fac == nullptr) { + LOG(WARNING) << "PRPPreload.ResPreloadScheduler::SetPRPPReqLoaderFac invalid loader_fac_weak"; + return; + } + DoPendingPreRequest(); + if (preload_triggered_) { + SchedulePrerequests(MAX_REQUEST_COUNT, info_list_version_); + } +} + +void ResPreloadScheduler::SchedulePreloads(const PRPPPreconnectInfoList& preconnect_info_list, + const std::shared_ptr& preload_info_tree, + bool only_send_reuse_request, + const std::set& need_record_header_urls) +{ + if (preload_triggered_ || net_task_runner_ == nullptr || + sth_task_runner_ == nullptr) { + return; + } + preload_triggered_ = true; + prpp_preconnect_info_list_ = preconnect_info_list; + preload_info_tree_ = preload_info_tree; + ++info_list_version_; + only_send_reuse_request_ = only_send_reuse_request; + need_record_header_urls_ = need_record_header_urls; + + SchedulePreconnects(); + if (!preload_info_tree_ || + !preload_info_tree_->req_info_ || + (preload_info_tree_->req_info_->type() != PRRequestInfoType::TYPE_PAGE_ORIGIN) || + (preload_info_tree_->children_.size() == 0)) { + if (!on_page_origin_cb_.is_null()) { + net_task_runner_->PostTask(FROM_HERE, base::BindOnce(on_page_origin_cb_, url_, CANCEL_ORIGIN)); + } + LOG(WARNING) << "PRPPreload.ResPreloadScheduler::SchedulePreloads invalid tree or no TYPE_PAGE_ORIGIN"; + return; + } + + std::string origin = preload_info_tree_->req_info_->page_origin(); + if (!on_page_origin_cb_.is_null()) { + net_task_runner_->PostTask(FROM_HERE, base::BindOnce(on_page_origin_cb_, url_, std::move(origin))); + } + cur_parent_ = preload_info_tree_; + cur_node_iter_ = preload_info_tree_->children_.begin(); + sth_task_runner_->PostTask(FROM_HERE, base::BindOnce(&ResPreloadScheduler::SchedulePrerequests, + weak_factory_.GetWeakPtr(), MAX_REQUEST_COUNT, info_list_version_)); +} + + +void ResPreloadScheduler::SchedulePreconnects() +{ + if (net_task_runner_ == nullptr || sth_task_runner_ == nullptr) { + return; + } + PreconnectInfoListIter iter = prpp_preconnect_info_list_.begin(); + int32_t preconnect_num = 0; + while (iter != prpp_preconnect_info_list_.end()) { + PRPPPreconnectInfo& info = *iter; + preconnect_num++; + if (preconnect_num <= SOCKET_LIMIT) { + net_task_runner_->PostTask(FROM_HERE, base::BindOnce(&PreconnectRunner::PreconnectSocket, + info.origin_url_, info.allow_credential_, info.net_anonymization_key_, url_request_context_)); + } else { + if (sth_task_runner_ != nullptr) { + sth_task_runner_->PostDelayedTask(FROM_HERE, + base::BindOnce(&ResPreloadScheduler::ContinueSchedulePreconnects, weak_factory_.GetWeakPtr(), + iter, info_list_version_), base::Milliseconds(DELAYED_TIME)); + } + break; + } + ++iter; + } +} + +void ResPreloadScheduler::ContinueSchedulePreconnects(PreconnectInfoListIter preconnect_infos_iter, + int32_t info_list_version) +{ + if (info_list_version != info_list_version_ || + (preconnect_infos_iter == prpp_preconnect_info_list_.end()) || + !preload_triggered_ || + net_task_runner_ == nullptr || sth_task_runner_ == nullptr) { + return; + } + + PRPPPreconnectInfo& info = *preconnect_infos_iter; + + net_task_runner_->PostTask(FROM_HERE, base::BindOnce(&PreconnectRunner::PreconnectSocket, + info.origin_url_, info.allow_credential_, info.net_anonymization_key_, url_request_context_)); + + ++preconnect_infos_iter; + if (preconnect_infos_iter != prpp_preconnect_info_list_.end()) { + sth_task_runner_->PostDelayedTask(FROM_HERE, + base::BindOnce(&ResPreloadScheduler::ContinueSchedulePreconnects, weak_factory_.GetWeakPtr(), + preconnect_infos_iter, info_list_version), base::Milliseconds(DELAYED_TIME)); + } +} + +void ResPreloadScheduler::SchedulePrerequests(uint32_t limit, int32_t info_list_version) +{ + if ((info_list_version != info_list_version_) || + !preload_triggered_ || !cur_parent_ || + net_task_runner_ == nullptr || sth_task_runner_ == nullptr) { + return; + } + + uint32_t prerequest_num = 0; + uint32_t continue_count = 0; + PRPPRequestLoaderFactory* loader_fac = loader_fac_weak_.get(); + if (loader_fac != nullptr) { + continue_count = loader_fac->GetAndClearPreloadedCount(); + } + if ((limit == 0) && (continue_count == 0)) { + sth_task_runner_->PostDelayedTask(FROM_HERE, + base::BindOnce(&ResPreloadScheduler::SchedulePrerequests, + weak_factory_.GetWeakPtr(), 0, info_list_version), + base::Milliseconds(DELAYED_TIME)); + return; + } + limit += continue_count; + bool need_continue = false; + + while (cur_parent_->children_.size() > 0) { + for (auto child = cur_node_iter_; child != cur_parent_->children_.end(); child++) { + cur_node_iter_ = child; + if (!net::HttpUtil::IsMethodSafe((*child)->req_info_->method()) || + (((*child)->req_info_->preload_flag() & PRPP_FLAGS_HDR_NOT_MATCH) == + PRPP_FLAGS_HDR_NOT_MATCH)) { + continue; + } + prerequest_num++; + if (prerequest_num > limit) { + need_continue = true; + break; + } + CreateReqLoaderAndStart((*child)->req_info_); + } + if (need_continue) { + sth_task_runner_->PostDelayedTask(FROM_HERE, + base::BindOnce(&ResPreloadScheduler::SchedulePrerequests, weak_factory_.GetWeakPtr(), + 0, info_list_version), base::Milliseconds(DELAYED_TIME)); + break; + } + cur_parent_ = *(cur_parent_->children_.begin()); + cur_node_iter_ = cur_parent_->children_.begin(); + } +} + +} // namespace ohos_prp_preload \ No newline at end of file diff --git a/net/prp_preload/src/res_preload_scheduler.h b/services/network/prp_preload/src/res_preload_scheduler.h similarity index 31% rename from net/prp_preload/src/res_preload_scheduler.h rename to services/network/prp_preload/src/res_preload_scheduler.h index d442e38166..32abd4b3b0 100644 --- a/net/prp_preload/src/res_preload_scheduler.h +++ b/services/network/prp_preload/src/res_preload_scheduler.h @@ -2,48 +2,63 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_PRP_PRELOAD_SRC_RES_PRELOAD_SCHEDULER_H -#define NET_PRP_PRELOAD_SRC_RES_PRELOAD_SCHEDULER_H +#ifndef SERVICES_NETWORK_PRP_PRELOAD_SRC_RES_PRELOAD_SCHEDULER_H +#define SERVICES_NETWORK_PRP_PRELOAD_SRC_RES_PRELOAD_SCHEDULER_H -#include -#include "base/memory/weak_ptr.h" #include "base/task/thread_pool.h" -#include "page_res_request_info.h" -#include "net/base/network_anonymization_key.h" +#include "services/network/prp_preload/include/preload_runner/prpp_request_loader_factory.h" namespace net { class URLRequestContext; } // namespace net namespace ohos_prp_preload { +using PRPPOnPageOriginCB = base::RepeatingCallback; class ResPreloadScheduler : public base::RefCounted { public: - ResPreloadScheduler(const scoped_refptr& sth_task_runner, - const scoped_refptr& net_task_runner, - base::WeakPtr url_request_context); + ResPreloadScheduler(const std::string& url, + const scoped_refptr& sth_task_runner, + const scoped_refptr& net_task_runner, + base::WeakPtr url_request_context, + const PRPPOnPageOriginCB& on_page_origin_cb); ResPreloadScheduler() = delete; ~ResPreloadScheduler() = default; - - void PreloadSchedule(const std::list>& res_req_info_list, - const net::NetworkAnonymizationKey& networkAnonymizationKey); + void StopPreload(); + void SetPRPPReqLoaderFac(base::WeakPtr loader_fac_weak); + void SchedulePreloads(const PRPPPreconnectInfoList& preconnect_info_list, + const std::shared_ptr& preload_info_tree, + bool only_send_reuse_request, + const std::set& need_record_header_urls); private: using InfoIter = std::list>::iterator; - bool NeedToPreconnect(const GURL& url, bool allow_credentials); - void PreconnectBeyondLimit(InfoIter info_iter, const int info_list_version, - const net::NetworkAnonymizationKey& networkAnonymizationKey); + using PreconnectInfoListIter = PRPPPreconnectInfoList::iterator; + void DoPendingPreRequest(); + void CreateReqLoaderAndStart(const std::shared_ptr& info); + void SchedulePreconnects(); + void SchedulePrerequests(uint32_t limit, int32_t info_list_version); + void ContinueSchedulePreconnects(PreconnectInfoListIter preconnect_infos_iter, int32_t info_list_version); - std::list> info_list_; + const std::string& url_; + std::list> prerequest_info_list_; std::unordered_map idle_connect_list_; scoped_refptr sth_task_runner_; scoped_refptr net_task_runner_; base::WeakPtr url_request_context_; - size_t socket_connected_ = 0; - bool preload_triggered_ = false; - int info_list_version_ = 0; + bool preload_triggered_ { false }; + int info_list_version_ { 0 }; + base::WeakPtr loader_fac_weak_ { nullptr }; + PRPPPreconnectInfoList prpp_preconnect_info_list_; + std::shared_ptr preload_info_tree_; + std::shared_ptr cur_parent_; + std::list>::iterator cur_node_iter_; + bool only_send_reuse_request_ { false }; + std::set need_record_header_urls_; + PRPPOnPageOriginCB on_page_origin_cb_; base::WeakPtrFactory weak_factory_{this}; }; } // namespace ohos_prp_preload -#endif // NET_PRP_PRELOAD_SRC_RES_PRELOAD_SCHEDULER_H \ No newline at end of file +#endif // SERVICES_NETWORK_PRP_PRELOAD_SRC_RES_PRELOAD_SCHEDULER_H \ No newline at end of file diff --git a/services/network/prp_preload/src/res_request_info_cache_mgr.cc b/services/network/prp_preload/src/res_request_info_cache_mgr.cc new file mode 100644 index 0000000000..451da22325 --- /dev/null +++ b/services/network/prp_preload/src/res_request_info_cache_mgr.cc @@ -0,0 +1,214 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/prp_preload/src/res_request_info_cache_mgr.h" + +#include "base/logging.h" +#include "base/json/json_writer.h" +#include "base/json/json_reader.h" +#include "services/network/prp_preload/include/page_res_parallel_preload_mgr.h" + +namespace { +constexpr base::TimeDelta CHECK_FLUSH_TO_DISK_TIMEOUT = base::Milliseconds(200); +const std::string PARAM_REQUEST_INFO_TYPE = "request_info_type"; +const std::string PARAM_PAGE_ORIGIN = "page_origin"; +const std::string PARAM_ONLY_SEND_REUSE_REQUEST = "only_send_reuse_request"; +} // namespace + +namespace ohos_prp_preload { +bool ResReqPreloadInfoListToJson(const std::string& page_origin, + const std::list>& info_list, + std::string& entry_content) { + bool need_store = false; + entry_content = ""; + base::Value::List list; + PRPPreloadMode mode = + ohos_prp_preload::PRParallelPreloadMgr::GetInstance().GetPRParallelPreloadMode(); + if (mode == PRPPreloadMode::PRELOAD) { + if (!page_origin.empty()) { + base::Value::Dict dict; + dict.Set(PARAM_PAGE_ORIGIN, page_origin); + dict.Set(PARAM_REQUEST_INFO_TYPE, static_cast(PRRequestInfoType::TYPE_PAGE_ORIGIN)); + list.Append(std::move(dict)); + } else { + LOG(WARNING) << "PRPPreload.ResReqPreloadInfoListToJson, page_origin empty"; + return false; + } + } + + bool only_send_reuse_request = false; + int visible_num = 0; + int none_num = 0; + for (std::shared_ptr info : info_list) { + if (mode == PRPPreloadMode::PRELOAD && info->preload_flag() == PRPP_FLAGS_NONE) { + none_num++; + continue; + } + if ((PRRequestFlags)(info->preload_flag() & PRPP_FLAGS_URL_DYNAMIC) == PRPP_FLAGS_URL_DYNAMIC) { + only_send_reuse_request = true; + } else if (info->preload_flag() == PRPP_FLAGS_VISIBLE) { + visible_num++; + } + + base::Value::Dict dict; + list.Append(std::move(dict)); + DiskCacheInfoParser::ParseResReqPreloadInfoForPreconnect(info, list.back().GetDict()); + if (mode == PRPPreloadMode::PRELOAD) { + DiskCacheInfoParser::ParseResReqPreloadInfoForPreload(info, list.back().GetDict()); + } + need_store = true; + } + if (mode == PRPPreloadMode::PRELOAD) { + if (visible_num + none_num == (int)(info_list.size())) { + only_send_reuse_request = true; + } + list.front().GetDict().Set(PARAM_ONLY_SEND_REUSE_REQUEST, only_send_reuse_request); + } + bool write_success = base::JSONWriter::Write(list, &entry_content); + if (!write_success) { + LOG(WARNING) << "PRPPreload.ResReqPreloadInfoListToJson failed"; + need_store = false; + } + LOG(DEBUG) << "PRPPreload.ResReqPreloadInfoListToJson size:" << list.size() << + ", need_store:" << need_store; + return need_store; +} + +void JsonToResReqPreloadInfoList(const std::string& content, + std::list>& info_list) { + if (content.empty()) { + info_list.clear(); + return; + } + absl::optional json_value = base::JSONReader::Read(content); + if (!json_value || !json_value->is_list()) { + LOG(WARNING) << "PRPPreload.JsonToResReqPreloadInfoList failed"; + return; + } + base::Value::List::iterator it = json_value->GetList().begin(); + if (it == json_value->GetList().end()) { + return; + } + PRPPreloadMode mode = + ohos_prp_preload::PRParallelPreloadMgr::GetInstance().GetPRParallelPreloadMode(); + std::shared_ptr origin_info = std::make_shared(); + if (!DiskCacheInfoParser::GetRequestInfoTypeFromJson(*it, PARAM_REQUEST_INFO_TYPE, origin_info) && + mode == PRPPreloadMode::PRELOAD) { + LOG(WARNING) << "PRPPreload.JsonToResReqPreloadInfoList failed to parse incorrect format json"; + mode = PRPPreloadMode::PRECONNECT; + } + + if (origin_info->type() == PRRequestInfoType::TYPE_PAGE_ORIGIN && mode == PRPPreloadMode::PRELOAD) { + const std::string* page_origin = (*it).GetDict().FindString(PARAM_PAGE_ORIGIN); + if (!page_origin) { + LOG(WARNING) << "PRPPreload.JsonToResReqPreloadInfoList json parse page_origin failed"; + mode = PRPPreloadMode::PRECONNECT; + } + origin_info->set_page_origin(*page_origin); + const absl::optional only_send_reuse_request = + (*it).GetDict().FindBool(PARAM_ONLY_SEND_REUSE_REQUEST); + if (!only_send_reuse_request.has_value()) { + LOG(WARNING) << "PRPPreload.JsonToResReqPreloadInfoList json parse only_send_reuse_request failed"; + mode = PRPPreloadMode::PRECONNECT; + } + origin_info->set_only_send_reuse_request(only_send_reuse_request.value()); + info_list.push_back(origin_info); + it++; + } + + for (base::Value::List::iterator json_item = it; + json_item != json_value->GetList().end(); ++json_item) { + std::shared_ptr info = std::make_shared(); + if (!DiskCacheInfoParser::ParseJsonForPreconnect(*json_item, info)) { + continue; + } + if (mode == PRPPreloadMode::PRELOAD && !DiskCacheInfoParser::ParseJsonForPreload(*json_item, info)) { + continue; + } + info_list.push_back(info); + } + LOG(DEBUG) << "PRPPreload.JsonToResReqPreloadInfoList size:" << info_list.size(); +} + +ResReqInfoCacheMgr::ResReqInfoCacheMgr(const std::string& url, + const scoped_refptr& sth_task_runner, + const scoped_refptr& disk_cache_backend_factory, + const ResRequestInfoCacheLoadedCB& info_cache_cb) : + sth_task_runner_(sth_task_runner), info_cache_loaded_cb_(info_cache_cb) { + disk_cache_ = base::WrapRefCounted(new (std::nothrow) DiskCacheFile(disk_cache_backend_factory, url, + base::BindRepeating(&ResReqInfoCacheMgr::OnEntryLoadedCallback, weak_factory_.GetWeakPtr()))); + if (disk_cache_ == nullptr) { + LOG(WARNING) << "PRPPreload.ResReqInfoCacheMgr::ResReqInfoCacheMgr new DiskCacheFile failed"; + } +} + +void ResReqInfoCacheMgr::Start() { + if ((disk_cache_ == nullptr) || (load_info_list_.size() > 0) || is_start_) { + return; + } + is_start_ = true; + disk_cache_->LoadInfoAsync(); + if (sth_task_runner_ != nullptr) { + sth_task_runner_->PostDelayedTask(FROM_HERE, + base::BindOnce(&ResReqInfoCacheMgr::CheckFlush, weak_factory_.GetWeakPtr()), + CHECK_FLUSH_TO_DISK_TIMEOUT); + } +} + +void ResReqInfoCacheMgr::UpdateResRequestInfo(const std::shared_ptr& info) { + if (disk_cache_ == nullptr || !is_start_) { + return; + } + new_info_list_.push_back(info); +} + +void ResReqInfoCacheMgr::SetPageOrigin(const std::string& page_origin) { + if (disk_cache_ == nullptr || !is_start_) { + return; + } + page_origin_ = page_origin; +} + +void ResReqInfoCacheMgr::Stop() { + if (disk_cache_ == nullptr || !is_start_) { + return; + } + is_start_ = false; + std::string entry_content; + if ((last_flush_len_ < new_info_list_.size()) && + ResReqPreloadInfoListToJson(page_origin_, new_info_list_, entry_content)) { + disk_cache_->StoreInfoAsync(entry_content); + } + load_info_list_.clear(); + new_info_list_.clear(); + last_flush_len_ = 0; +} + +void ResReqInfoCacheMgr::OnEntryLoadedCallback(const std::string& entry_content) { + if (load_info_list_.size() > 0 || !is_start_) { + return; + } + JsonToResReqPreloadInfoList(entry_content, load_info_list_); + if (!info_cache_loaded_cb_.is_null()) { + info_cache_loaded_cb_.Run(load_info_list_); + } +} + +void ResReqInfoCacheMgr::CheckFlush() { + if (!is_start_) { + return; + } + std::string entry_content; + if ((last_flush_len_ < new_info_list_.size()) && + ResReqPreloadInfoListToJson(page_origin_, new_info_list_, entry_content)) { + disk_cache_->StoreInfoAsync(entry_content); + last_flush_len_ = new_info_list_.size(); + } + if (sth_task_runner_ != nullptr) { + sth_task_runner_->PostDelayedTask(FROM_HERE, + base::BindOnce(&ResReqInfoCacheMgr::CheckFlush, weak_factory_.GetWeakPtr()), + CHECK_FLUSH_TO_DISK_TIMEOUT); + } +} +} // namespace ohos_prp_preload diff --git a/net/prp_preload/src/res_request_info_cache_mgr.h b/services/network/prp_preload/src/res_request_info_cache_mgr.h similarity index 66% rename from net/prp_preload/src/res_request_info_cache_mgr.h rename to services/network/prp_preload/src/res_request_info_cache_mgr.h index 378ffd9f09..b0da77dd18 100644 --- a/net/prp_preload/src/res_request_info_cache_mgr.h +++ b/services/network/prp_preload/src/res_request_info_cache_mgr.h @@ -2,29 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_PRP_PRELOAD_SRC_RES_REQUEST_INFO_CACHE_MGR_H -#define NET_PRP_PRELOAD_SRC_RES_REQUEST_INFO_CACHE_MGR_H +#ifndef SERVICES_NETWORK_PRP_PRELOAD_SRC_RES_REQUEST_INFO_CACHE_MGR_H +#define SERVICES_NETWORK_PRP_PRELOAD_SRC_RES_REQUEST_INFO_CACHE_MGR_H -#include -#include -#include #include "base/task/thread_pool.h" -#include "base/types/optional_util.h" -#include "base/json/json_writer.h" -#include "base/json/json_reader.h" -#include "base/values.h" -#include "net/base/network_anonymization_key.h" -#include "disk_cache_file.h" -#include "page_res_request_info.h" +#include "services/network/prp_preload/src/disk_cache_file.h" +#include "services/network/prp_preload/src/disk_cache_info_parser.h" namespace ohos_prp_preload { using ResRequestInfoCacheLoadedCB = - base::RepeatingCallback>& load_info_list, - const net::NetworkAnonymizationKey& networkAnonymizationKey)>; + base::RepeatingCallback>& load_info_list)>; class ResReqInfoCacheMgr : public base::RefCounted { public: ResReqInfoCacheMgr(const std::string& url, - const net::NetworkAnonymizationKey& networkAnonymizationKey, const scoped_refptr& sth_task_runner, const scoped_refptr& disk_cache_backend_factory, const ResRequestInfoCacheLoadedCB& info_list_cb); @@ -33,11 +23,11 @@ class ResReqInfoCacheMgr : public base::RefCounted { void Start(); void UpdateResRequestInfo(const std::shared_ptr& info); void Stop(); + void SetPageOrigin(const std::string& page_origin); private: void OnEntryLoadedCallback(const std::string& entry_content); void CheckFlush(); - const net::NetworkAnonymizationKey& networkAnonymizationKey_; scoped_refptr sth_task_runner_; scoped_refptr disk_cache_; std::list> new_info_list_; @@ -45,9 +35,10 @@ class ResReqInfoCacheMgr : public base::RefCounted { size_t last_flush_len_{0}; ResRequestInfoCacheLoadedCB info_cache_loaded_cb_; bool is_start_{false}; + std::string page_origin_; base::WeakPtrFactory weak_factory_{this}; }; } // namespace ohos_prp_preload -#endif // NET_PRP_PRELOAD_SRC_RES_REQUEST_INFO_CACHE_MGR_H +#endif // SERVICES_NETWORK_PRP_PRELOAD_SRC_RES_REQUEST_INFO_CACHE_MGR_H diff --git a/services/network/prp_preload/src/res_request_info_updater.cc b/services/network/prp_preload/src/res_request_info_updater.cc new file mode 100644 index 0000000000..24e46ca4bd --- /dev/null +++ b/services/network/prp_preload/src/res_request_info_updater.cc @@ -0,0 +1,189 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/prp_preload/src/res_request_info_updater.h" + +#include "base/logging.h" +#include "net/http/http_util.h" +#include "services/network/prp_preload/include/page_res_parallel_preload_mgr.h" + +namespace { +constexpr int32_t MAX_LEVEL_INTERVAL_US = 100000; +const std::string PRIVACY_TAG = "ac/"; +constexpr int32_t MAX_RESERVED_COUNT = 1; +constexpr int32_t MAX_PRECONNECT_COUNT = 5; +} // namespace + +namespace ohos_prp_preload { +ResRequestInfoUpdater::ResRequestInfoUpdater(const std::string& url, + const scoped_refptr& sth_task_runner, + const scoped_refptr& disk_cache_backend_factory, + const ResPreloadInfosCB& preload_infos_cb) : preload_infos_cb_(preload_infos_cb) { + res_req_info_cache_mgr_ = base::WrapRefCounted(new (std::nothrow) ResReqInfoCacheMgr(url, + sth_task_runner, disk_cache_backend_factory, + base::BindRepeating(&ResRequestInfoUpdater::OnResRequestInfoCacheLoaded, weak_factory_.GetWeakPtr()))); + if (res_req_info_cache_mgr_ == nullptr) { + LOG(WARNING) << "PRPPreload.ResRequestInfoUpdater::ResRequestInfoUpdater new ResReqInfoCacheMgr failed"; + } +} + +void ResRequestInfoUpdater::Start() { + if (res_req_info_cache_mgr_ == nullptr) { + return; + } + res_req_info_cache_mgr_->Start(); +} + +void ResRequestInfoUpdater::UpdateResRequestInfo(const std::shared_ptr& info) { + if (res_req_info_cache_mgr_ == nullptr) { + return; + } + res_req_info_cache_mgr_->UpdateResRequestInfo(info); +} + +void ResRequestInfoUpdater::SetPageOrigin(const std::string& page_origin) { + if (res_req_info_cache_mgr_ == nullptr) { + return; + } + res_req_info_cache_mgr_->SetPageOrigin(page_origin); +} + +void ResRequestInfoUpdater::Stop() { + if (res_req_info_cache_mgr_ == nullptr) { + return; + } + res_req_info_cache_mgr_->Stop(); +} + +void ResRequestInfoUpdater::OnResRequestInfoCacheLoaded( + const std::list>& load_info_list) { + if (preload_infos_cb_.is_null()) { + return; + } + bool need_to_build_preload_tree = + ohos_prp_preload::PRParallelPreloadMgr::GetInstance().GetPRParallelPreloadMode() == + PRPPreloadMode::PRELOAD; + // build preconnect list and preload tree + std::shared_ptr cur_parent = nullptr; + std::shared_ptr cur_first = nullptr; + std::shared_ptr current = nullptr; + bool only_send_reuse_request = false; + int64_t cur_level_end_time = 0; + for (auto info : load_info_list) { + if (info->type() == PRRequestInfoType::TYPE_PAGE_ORIGIN) { + if (need_to_build_preload_tree) { + only_send_reuse_request = info->only_send_reuse_request(); + if (preload_info_tree_ == nullptr) { + preload_info_tree_ = std::make_shared(); + preload_info_tree_->req_info_ = info; + cur_parent = preload_info_tree_; + } + } + continue; + } + + // build preconnect list step + GURL origin_url = url::Origin::Create(info->url()).GetURL(); + bool need_connect = false; + bool need_add_connect = false; + if (!net::HttpUtil::IsMethodSafe(info->method()) || + (info->cache_type() != PRRequestCacheType::FORCE_CACHE) || + (base::Time::Now().ToInternalValue() > info->freshness_life_times())) { + need_connect = true; + } + + std::string key = info->allow_credentials() ? + PRIVACY_TAG + origin_url.spec() : origin_url.spec(); + if (preconnect_org_url_map_.count(key) != 0) { + PreconnectCount& cur_count = preconnect_org_url_map_[key]; + if (cur_count.need_count_ + cur_count.reserved_count_ < MAX_PRECONNECT_COUNT) { + if (need_connect) { + cur_count.need_count_++; + need_add_connect = true; + } else if (cur_count.reserved_count_ < MAX_RESERVED_COUNT) { + cur_count.reserved_count_++; + need_add_connect = true; + } + } + } else { + need_add_connect = true; + if (need_connect) { + preconnect_org_url_map_[key] = PreconnectCount{1, 0}; + } else { + preconnect_org_url_map_[key] = PreconnectCount{0, 1}; + } + } + + if (need_add_connect) { + prpp_preconnect_info_list_.emplace_back(PRPPPreconnectInfo{origin_url, + info->allow_credentials(), + net::NetworkAnonymizationKey::CreateSameSite(net::SchemefulSite(origin_url))}); + } + + // build tree step + if (!need_to_build_preload_tree || cur_parent == nullptr) { + continue; + } + current = std::make_shared(); + current->req_info_ = info; + int64_t cur_request_start_time = current->req_info_->request_start_time(); + int64_t cur_request_end_time = current->req_info_->request_end_time(); + if (cur_first == nullptr) { + cur_first = current; + cur_first->parent_ = cur_parent.get(); + cur_parent->children_.emplace_back(cur_first); + cur_level_end_time = cur_request_end_time; + continue; + } + + if ((cur_request_start_time > cur_first->req_info_->request_start_time() + MAX_LEVEL_INTERVAL_US) || + (cur_level_end_time > 0 && cur_request_start_time > cur_level_end_time)) { + // new level + cur_parent = cur_first; + cur_first = current; + cur_first->parent_ = cur_parent.get(); + cur_parent->children_.emplace_back(cur_first); + cur_level_end_time = cur_request_end_time; + } else { + cur_parent->children_.emplace_back(current); + if (cur_request_end_time > 0) { + cur_level_end_time = cur_level_end_time > 0 ? + std::min(cur_request_end_time, cur_level_end_time) : cur_request_end_time; + } + } + + if (current->req_info_->preload_flag() == + (PRRequestFlags)(PRPP_FLAGS_VISIBLE | PRPP_FLAGS_HDR_DYNAMIC)) { + UpdateResRequestInfoForDynamicHeaders(cur_parent, current->req_info_); + } + } + preload_infos_cb_.Run(prpp_preconnect_info_list_, preload_info_tree_, + only_send_reuse_request, need_record_header_urls_); +} + +void ResRequestInfoUpdater::UpdateResRequestInfoForDynamicHeaders( + std::shared_ptr parent, std::shared_ptr child_info) +{ + if (parent == nullptr || parent->parent_ == nullptr || parent->parent_->children_.empty()) { + return; + } + for (auto it : parent->parent_->children_) { + if (it->req_info_->cache_type() == PRRequestCacheType::FORCE_CACHE) { + continue; + } + bool match = true; + for (auto header : child_info->dynamic_header_keys()) { + if (!it->req_info_->extra_request_headers().HasHeader(header)) { + match = false; + break; + } + } + if (match) { + child_info->set_parent_for_dynamic_header(it->req_info_->url()); + (void)need_record_header_urls_.emplace(it->req_info_->url().spec()); + return; + } + } +} +} // namespace ohos_prp_preload diff --git a/net/prp_preload/src/res_request_info_updater.h b/services/network/prp_preload/src/res_request_info_updater.h similarity index 44% rename from net/prp_preload/src/res_request_info_updater.h rename to services/network/prp_preload/src/res_request_info_updater.h index 340e8f38e4..ab6ecc48a0 100644 --- a/net/prp_preload/src/res_request_info_updater.h +++ b/services/network/prp_preload/src/res_request_info_updater.h @@ -2,36 +2,49 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_PRP_PRELOAD_SRC_RES_REQUEST_INFO_UPDATER_H -#define NET_PRP_PRELOAD_SRC_RES_REQUEST_INFO_UPDATER_H +#ifndef SERVICES_NETWORK_PRP_PRELOAD_SRC_RES_REQUEST_INFO_UPDATER_H +#define SERVICES_NETWORK_PRP_PRELOAD_SRC_RES_REQUEST_INFO_UPDATER_H -#include "res_request_info_cache_mgr.h" +#include "services/network/prp_preload/src/res_request_info_cache_mgr.h" namespace ohos_prp_preload { using ResRequestInfoListCB = - base::RepeatingCallback>& res_req_info_list, - const net::NetworkAnonymizationKey& networkAnonymizationKey)>; + base::RepeatingCallback>& res_req_info_list)>; +using ResPreloadInfosCB = + base::RepeatingCallback& preload_info_tree, + bool only_send_reuse_request, + const std::set& need_record_header_urls)>; class ResRequestInfoUpdater : public base::RefCounted { public: ResRequestInfoUpdater(const std::string& url, - const net::NetworkAnonymizationKey& networkAnonymizationKey, const scoped_refptr& sth_task_runner, const scoped_refptr& disk_cache_backend_factory, - const ResRequestInfoListCB& res_req_info_list_cb); + const ResPreloadInfosCB& preload_infos_cb); ~ResRequestInfoUpdater() = default; void Start(); void UpdateResRequestInfo(const std::shared_ptr& info); void Stop(); + void SetPageOrigin(const std::string& page_origin); private: - void OnResRequestInfoCacheLoaded(const std::list>& load_info_list, - const net::NetworkAnonymizationKey& networkAnonymizationKey); + void UpdateResRequestInfoForDynamicHeaders(std::shared_ptr parent, + std::shared_ptr child_info); + struct PreconnectCount { + int32_t need_count_ { 0 }; + int32_t reserved_count_ { 0 }; + }; + void OnResRequestInfoCacheLoaded(const std::list>& load_info_list); scoped_refptr res_req_info_cache_mgr_; - ResRequestInfoListCB res_req_info_list_cb_; + PRPPPreconnectInfoList prpp_preconnect_info_list_; + std::shared_ptr preload_info_tree_; + std::unordered_map preconnect_org_url_map_; + ResPreloadInfosCB preload_infos_cb_; + std::set need_record_header_urls_; base::WeakPtrFactory weak_factory_{this}; }; } // namespace ohos_prp_preload -#endif // NET_PRP_PRELOAD_SRC_RES_REQUEST_INFO_UPDATER_H \ No newline at end of file +#endif // SERVICES_NETWORK_PRP_PRELOAD_SRC_RES_REQUEST_INFO_UPDATER_H \ No newline at end of file diff --git a/services/network/public/cpp/resource_request.h b/services/network/public/cpp/resource_request.h index 00f08db9b3..7755561bfe 100644 --- a/services/network/public/cpp/resource_request.h +++ b/services/network/public/cpp/resource_request.h @@ -14,6 +14,7 @@ #include "base/unguessable_token.h" #include "mojo/public/cpp/bindings/remote.h" #include "net/base/isolation_info.h" +#include "net/base/prp_preload_buildflags.h" #include "net/base/request_priority.h" #include "net/cookies/site_for_cookies.h" #include "net/filter/source_stream.h" @@ -202,10 +203,13 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest { mojom::AttributionReportingEligibility attribution_reporting_eligibility = mojom::AttributionReportingEligibility::kUnset; #if BUILDFLAG(IS_OHOS) - bool allow_preload_record = false; - GURL main_page; bool is_sync_mode = false; #endif +#if BUILDFLAG(IS_OHOS_PRPP) + bool allow_preload_record = false; + GURL main_url; + bool is_preflight = false; +#endif #if defined(OHOS_EX_DOWNLOAD) bool is_download_request = false; #endif // OHOS_EX_DOWNLOAD diff --git a/services/network/public/cpp/url_request_mojom_traits.cc b/services/network/public/cpp/url_request_mojom_traits.cc index 327073115f..bea4779c25 100644 --- a/services/network/public/cpp/url_request_mojom_traits.cc +++ b/services/network/public/cpp/url_request_mojom_traits.cc @@ -165,12 +165,12 @@ bool StructTraits< network::debug::SetDeserializationCrashKeyString("referrer"); return false; } -#if BUILDFLAG(IS_OHOS) - if (!data.ReadMainPage(&out->main_page)) { - network::debug::SetDeserializationCrashKeyString("main_page"); +#if BUILDFLAG(IS_OHOS_PRPP) + if (!data.ReadMainUrl(&out->main_url)) { + network::debug::SetDeserializationCrashKeyString("main_url"); return false; } -#endif // IS_OHOS +#endif // IS_OHOS_PRPP if (!data.ReadReferrerPolicy(&out->referrer_policy) || !data.ReadHeaders(&out->headers) || !data.ReadCorsExemptHeaders(&out->cors_exempt_headers) || @@ -233,9 +233,12 @@ bool StructTraits< out->attribution_reporting_eligibility = data.attribution_reporting_eligibility(); #if BUILDFLAG(IS_OHOS) - out->allow_preload_record = data.allow_preload_record(); out->is_sync_mode = data.is_sync_mode(); #endif // IS_OHOS +#if BUILDFLAG(IS_OHOS_PRPP) + out->allow_preload_record = data.allow_preload_record(); + out->is_preflight = data.is_preflight(); +#endif // IS_OHOS_PRPP #if defined(OHOS_EX_DOWNLOAD) out->is_download_request = data.is_download_request(); #endif // OHOS_EX_DOWNLOAD diff --git a/services/network/public/cpp/url_request_mojom_traits.h b/services/network/public/cpp/url_request_mojom_traits.h index fc0ea8948d..cf9ecd2315 100644 --- a/services/network/public/cpp/url_request_mojom_traits.h +++ b/services/network/public/cpp/url_request_mojom_traits.h @@ -383,16 +383,21 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) return request.attribution_reporting_eligibility; } #if BUILDFLAG(IS_OHOS) + static bool is_sync_mode(const network::ResourceRequest& request) { + return request.is_sync_mode; + } +#endif // IS_OHOS +#if BUILDFLAG(IS_OHOS_PRPP) static bool allow_preload_record(const network::ResourceRequest& request) { return request.allow_preload_record; } - static const GURL& main_page(const network::ResourceRequest& request) { - return request.main_page; + static const GURL& main_url(const network::ResourceRequest& request) { + return request.main_url; } - static bool is_sync_mode(const network::ResourceRequest& request) { - return request.is_sync_mode; + static bool is_preflight(const network::ResourceRequest& request) { + return request.is_preflight; } -#endif // IS_OHOS +#endif // IS_OHOS_PRPP #if defined(OHOS_EX_DOWNLOAD) static bool is_download_request(const network::ResourceRequest& request) { return request.is_download_request; diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn index 6322a324da..ae2394ae0d 100644 --- a/services/network/public/mojom/BUILD.gn +++ b/services/network/public/mojom/BUILD.gn @@ -480,6 +480,10 @@ mojom("url_loader_base") { enabled_features += ["is_ohos_network_load"] } + if (enable_prp_preload) { + enabled_features += [ "is_ohos_prpp" ] + } + # Shared by cpp_typemaps and blink_cpp_typemaps. shared_typemaps = [ { @@ -1373,6 +1377,10 @@ mojom("mojom") { ] } + if (enable_prp_preload) { + enabled_features += [ "is_ohos_prpp" ] + } + has_dchecks = is_debug || dcheck_always_on if (has_dchecks && is_win) { enabled_features += [ "win_permissions_validation" ] diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom index 048bf6ec75..6176b192b3 100644 --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom @@ -801,6 +801,11 @@ struct URLLoaderFactoryParams { // Lists all the cookie setting overrides that should be specified on // each URLRequest. CookieSettingOverrides cookie_setting_overrides; + [EnableIf=is_ohos_prpp] + string main_url = ""; + + [EnableIf=is_ohos_prpp] + uint64 addr_web_handle; }; // Callback interface for NetworkContext when routing identifiers aren't @@ -1378,14 +1383,17 @@ interface NetworkContext { [EnableIf=ohos_custom_dns] ClearHostIP(string HostName); - [EnableIf=is_ohos] + [EnableIf=is_ohos_prpp] InitPRParallelPreloadMgr(); - [EnableIf=is_ohos] - StartMainPage(string url, NetworkAnonymizationKey networkAnonymizationKey, uint64 addr_web_handle); + [EnableIf=is_ohos_prpp] + StartPage(string url, uint64 addr_web_handle) => (string page_origin_url); + + [EnableIf=is_ohos_prpp] + StopPage(uint64 addr_web_handle); - [EnableIf=is_ohos] - StopMainPage(uint64 addr_web_handle); + [EnableIf=is_ohos_prpp] + SetParam(URLLoaderFactoryParams params); // Creates a HostResolver interface that can be passed to code/processes // without direct access to NetworkContext to make ResolveHost requests. diff --git a/services/network/public/mojom/url_request.mojom b/services/network/public/mojom/url_request.mojom index 24a8028019..f565004c20 100644 --- a/services/network/public/mojom/url_request.mojom +++ b/services/network/public/mojom/url_request.mojom @@ -507,11 +507,14 @@ struct URLRequest { [EnableIf=ohos_ex_download] bool is_download_request; - [EnableIf=is_ohos] + [EnableIf=is_ohos_prpp] bool allow_preload_record; - [EnableIf=is_ohos] - url.mojom.Url main_page; + [EnableIf=is_ohos_prpp] + url.mojom.Url main_url; + + [EnableIf=is_ohos_prpp] + bool is_preflight; [EnableIf=is_ohos] bool is_sync_mode; diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h index be23d9e4a2..54dd42b8eb 100644 --- a/services/network/test/test_network_context.h +++ b/services/network/test/test_network_context.h @@ -321,8 +321,12 @@ class TestNetworkContext : public mojom::NetworkContext { uint32_t AliveTime) override {} void ClearHostIP(const std::string& HostName) override {} void InitPRParallelPreloadMgr() override {} - void StartMainPage(const std::string& url, uint64_t addr_web_handle) override {} - void StopMainPage(uint64_t addr_web_handle) override {} + void StartPage( + const std::string& url, + uint64_t addr_web_handle, + StartPageCallback page_origin_cb) override {} + void StopPage(uint64_t addr_web_handle) override {} + void SetParam(mojom::URLLoaderFactoryParamsPtr params) override {} #endif // OHOS_UNITTESTS }; diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index 02bb4c78cc..e553763d01 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc @@ -99,6 +99,11 @@ #include "third_party/abseil-cpp/absl/types/optional.h" #include "url/origin.h" +#if BUILDFLAG(IS_OHOS_PRPP) +#include "base/functional/callback.h" +#include "services/network/prp_preload/include/page_res_parallel_preload_mgr.h" +#endif + namespace network { namespace { @@ -107,6 +112,11 @@ namespace { // mojo::core::Core::CreateDataPipe constexpr size_t kBlockedBodyAllocationSize = 1; +#if BUILDFLAG(IS_OHOS_PRPP) +const std::string SECURITY_URL = + "https://lfbrowsertestelbnew.hwcloudtest.cn/security/v1/oh/securityurls"; +#endif + // A subclass of net::UploadBytesElementReader which owns // ResourceRequestBody. class BytesElementReader : public net::UploadBytesElementReader { @@ -488,7 +498,14 @@ URLLoader::URLLoader( bool third_party_cookies_enabled, net::CookieSettingOverrides cookie_setting_overrides, const CacheTransparencySettings* cache_transparency_settings, - std::unique_ptr attribution_request_helper) + std::unique_ptr attribution_request_helper +#if BUILDFLAG(IS_OHOS_PRPP) + , + std::shared_ptr prpp_loader, + const std::string& org_main_url, + std::shared_ptr preload_info +#endif + ) : url_request_context_(context.GetUrlRequestContext()), network_context_client_(context.GetNetworkContextClient()), delete_callback_(std::move(delete_callback)), @@ -577,10 +594,40 @@ URLLoader::URLLoader( } receiver_.set_disconnect_handler( base::BindOnce(&URLLoader::OnMojoDisconnect, base::Unretained(this))); +#if BUILDFLAG(IS_OHOS_PRPP) + if (prpp_loader.get()) { + prpp_loader_ = prpp_loader; + url_request_ = prpp_loader_->GetURLRequest(); + prpp_loader_->SetRequestDelegate(this); + prpp_loader_->SetRequestHeadersCallback(base::BindRepeating( + &URLLoader::SetRawRequestHeadersAndNotify, base::Unretained(this))); + if (devtools_request_id()) { + prpp_loader_->SetResponseHeadersCallback(base::BindRepeating( + &URLLoader::SetRawResponseHeaders, base::Unretained(this))); + } + prpp_loader_->SetEarlyResponseHeadersCallback(base::BindRepeating( + &URLLoader::NotifyEarlyResponse, base::Unretained(this))); + if (prpp_loader_->StartReplay()) { + InitUrlRequestForRollback( + context, request, traffic_annotation, third_party_cookies_enabled, + cookie_setting_overrides, org_main_url, preload_info); + return; + } + prpp_loader_->SetRequestDelegate(nullptr); + prpp_loader_ = nullptr; + } + if (preload_info->only_send_reuse_request() && + preload_info->preload_flag() == ohos_prp_preload::PRPP_FLAGS_NONE) { + preload_info->set_preload_flag(ohos_prp_preload::PRPP_FLAGS_URL_DYNAMIC); + } + url_request_ = url_request_context_->CreateRequestForPrpp( + GURL(request.url), request.priority, this, traffic_annotation, + /*is_for_websockets=*/false, request.net_log_create_info); +#else url_request_ = url_request_context_->CreateRequest( GURL(request.url), request.priority, this, traffic_annotation, /*is_for_websockets=*/false, request.net_log_create_info); - +#endif url_request_->set_method(request.method); url_request_->set_site_for_cookies(request.site_for_cookies); if (ShouldForceIgnoreSiteForCookies(request)) @@ -739,9 +786,8 @@ URLLoader::URLLoader( url_request_->set_has_storage_access(request.has_storage_access); -#if BUILDFLAG(IS_OHOS) - url_request_->set_allow_preload_record(request.allow_preload_record); - url_request_->set_main_page(request.main_page); +#if BUILDFLAG(IS_OHOS_PRPP) + SetUrlRequestForPRPP(request, url_request_, org_main_url, preload_info); #endif url_request_->cookie_setting_overrides().PutAll(cookie_setting_overrides); @@ -951,6 +997,14 @@ void URLLoader::BeginTrustTokenOperationIfNecessaryAndThenScheduleStart( return; } +#if BUILDFLAG(IS_OHOS) + // for prp_preload performance tools, trust token request + TRACE_EVENT1( + "net", + "URLLoader::BeginTrustTokenOperationIfNecessaryAndThenScheduleStart", + "id", request_id_); +#endif + // Trust token operations other than signing cannot be served from cache // because it needs to send the server the Trust Tokens request header and // get the corresponding response header. It is okay to cache the results in @@ -1177,6 +1231,20 @@ void URLLoader::FollowRedirect( void URLLoader::SetPriority(net::RequestPriority priority, int32_t intra_priority_value) { +#if BUILDFLAG(IS_OHOS_PRPP) + // "4" means blink::mojom::ResourceType::kImage. here not depend blink. + if ((resource_type_ == 4) && (priority >= net::MEDIUM) && url_request_ && + url_request_->preload_info() && + (url_request_->preload_info()->preload_flag() == + ohos_prp_preload::PRPP_FLAGS_NONE)) { + url_request_->preload_info()->or_preload_flag( + ohos_prp_preload::PRPP_FLAGS_VISIBLE); + if (already_update_info_) { + ohos_prp_preload::PRParallelPreloadMgr::GetInstance().UpdateResRequestInfo( + url_request_->url().spec(), url_request_->preload_info()); + } + } +#endif if (url_request_ && resource_scheduler_client_) { resource_scheduler_client_->ReprioritizeRequest( url_request_.get(), priority, intra_priority_value); @@ -1318,9 +1386,25 @@ int URLLoader::OnConnected(net::URLRequest* url_request, mojom::URLResponseHeadPtr URLLoader::BuildResponseHead() const { auto response = mojom::URLResponseHead::New(); - +#if BUILDFLAG(IS_OHOS_PRPP) + net::LoadTimingInfo load_timing_info = net::LoadTimingInfo(); + if (prpp_loader_.get()) { + prpp_loader_->GetLoadTimingInfo(&load_timing_info); + if (url_request_->was_cached()) { + response->request_time = url_request_->request_time(); + response->response_time = url_request_->response_time(); + } else { + response->request_time = load_timing_info.request_start_time; + response->response_time = base::Time::Now(); + } + } else { + response->request_time = url_request_->request_time(); + response->response_time = url_request_->response_time(); + } +#else response->request_time = url_request_->request_time(); response->response_time = url_request_->response_time(); +#endif response->headers = url_request_->response_headers(); response->parsed_headers = PopulateParsedHeaders(response->headers.get(), url_request_->url()); @@ -1374,10 +1458,18 @@ mojom::URLResponseHeadPtr URLLoader::BuildResponseHead() const { break; } } - +#if BUILDFLAG(IS_OHOS_PRPP) + if (is_load_timing_enabled_) { + if (prpp_loader_.get()) { + prpp_loader_->GetLoadTimingInfo(&response->load_timing); + } else { + url_request_->GetLoadTimingInfo(&response->load_timing); + } + } +#else if (is_load_timing_enabled_) url_request_->GetLoadTimingInfo(&response->load_timing); - +#endif if (url_request_->ssl_info().cert.get()) { response->ct_policy_compliance = url_request_->ssl_info().ct_policy_compliance; @@ -1388,8 +1480,15 @@ mojom::URLResponseHeadPtr URLLoader::BuildResponseHead() const { response->ssl_info = url_request_->ssl_info(); } } - +#if BUILDFLAG(IS_OHOS_PRPP) + if (prpp_loader_.get()) { + response->request_start = load_timing_info.request_start; + } else { + response->request_start = url_request_->creation_time(); + } +#else response->request_start = url_request_->creation_time(); +#endif response->response_start = base::TimeTicks::Now(); response->encoded_data_length = url_request_->GetTotalReceivedBytes(); response->auth_challenge_info = url_request_->auth_challenge_info(); @@ -1417,6 +1516,10 @@ void URLLoader::OnReceivedRedirect(net::URLRequest* url_request, DCHECK(url_request == url_request_.get()); DCHECK(!deferred_redirect_url_); +#if BUILDFLAG(IS_OHOS) + // for prp_preload performance tools, redirect request + TRACE_EVENT1("net", "URLLoader::OnReceivedRedirect", "id", request_id_); +#endif deferred_redirect_url_ = std::make_unique(redirect_info.new_url); // Send the redirect response to the client, allowing them to inspect it and @@ -1483,6 +1586,16 @@ void URLLoader::OnReceivedRedirect(net::URLRequest* url_request, // Ensure that the redirect target is not treated as a pervasive payload. url_request_->set_expected_response_checksum(std::string()); +#if BUILDFLAG(IS_OHOS_PRPP) + if (url_request_->main_url().spec().empty() && + !redirect_info.new_url.spec().empty() && + redirect_info.new_url.spec() != url_request_->url().spec()) { + ohos_prp_preload::PRParallelPreloadMgr::GetInstance().UpdateRedirectUrl( + url_request_->url().spec(), redirect_info.new_url.spec(), + redirect_updated_); + redirect_updated_ = true; + } +#endif RedirectAttributionIfNecessaryAndThenContinueOnReceiveRedirect( redirect_info, std::move(response)); } @@ -1567,6 +1680,11 @@ void URLLoader::OnAuthRequired(net::URLRequest* url_request, DCHECK(!auth_challenge_responder_receiver_.is_bound()); +#if BUILDFLAG(IS_OHOS) + // for prp_preload performance tools,auth required request + TRACE_EVENT1("net", "URLLoader::OnAuthRequired", "id", request_id_); +#endif + url_loader_network_observer_->OnAuthRequired( fetch_window_id_, request_id_, url_request_->url(), first_auth_attempt_, auth_info, url_request->response_headers(), @@ -1597,6 +1715,10 @@ void URLLoader::OnCertificateRequested(net::URLRequest* unused, // Set up mojo endpoints for ClientCertificateResponder and bind to the // Receiver. This enables us to receive messages regarding the client // certificate selection. +#if BUILDFLAG(IS_OHOS) + // for prp_preload performance tools, certificate request + TRACE_EVENT1("net", "URLLoader::OnCertificateRequested", "id", request_id_); +#endif url_loader_network_observer_->OnCertificateRequested( fetch_window_id_, cert_info, client_cert_responder_receiver_.BindNewPipeAndPassRemote()); @@ -1636,6 +1758,19 @@ void URLLoader:: void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) { DCHECK(url_request == url_request_.get()); +#if BUILDFLAG(IS_OHOS_PRPP) + if (prpp_loader_.get() && (net_error == ohos_prp_preload::PRPP_ERROR) && + !has_received_response_) { + // roll-back + LOG(DEBUG) << "PRPPreload.URLLoader::OnResponseStarted roll-back from prpp"; + prpp_loader_->ClearLoaderCallback(devtools_request_id().has_value()); + prpp_loader_ = nullptr; + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&URLLoader::RollbackFromPPRP, + weak_ptr_factory_.GetWeakPtr())); + return; + } +#endif has_received_response_ = true; // Use `true` to force sending the cookie accessed update now. This is because @@ -1839,9 +1974,22 @@ void URLLoader::ReadMore() { auto buf = base::MakeRefCounted( pending_write_.get(), pending_write_buffer_offset_); read_in_progress_ = true; +#if BUILDFLAG(IS_OHOS_PRPP) + int bytes_read = 0; + if (prpp_loader_.get()) { + bytes_read = prpp_loader_->Read( + buf.get(), static_cast(pending_write_buffer_size_ - + pending_write_buffer_offset_)); + } else { + bytes_read = url_request_->Read( + buf.get(), static_cast(pending_write_buffer_size_ - + pending_write_buffer_offset_)); + } +#else int bytes_read = url_request_->Read( buf.get(), static_cast(pending_write_buffer_size_ - pending_write_buffer_offset_)); +#endif if (bytes_read != net::ERR_IO_PENDING) { DidRead(bytes_read, true); // |this| may have been deleted. @@ -2183,6 +2331,12 @@ void URLLoader::NotifyCompleted(int error_code) { url_loader_client_.Get()->OnComplete(status); #if BUILDFLAG(IS_OHOS) if (url_request_) { +#if BUILDFLAG(IS_OHOS_PRPP) + if (url_request_->preload_info()) { + url_request_->preload_info()->set_request_end_time( + base::Time::Now().ToInternalValue()); + } +#endif if (url_request_->response_headers()) { const net::HttpResponseHeaders* response_headers = raw_response_headers_ && enable_reporting_raw_headers_ @@ -2200,6 +2354,12 @@ void URLLoader::NotifyCompleted(int error_code) { #endif } +#if BUILDFLAG(IS_OHOS_PRPP) + if (prpp_loader_.get()) { + prpp_loader_->ClearLoaderCallback(devtools_request_id().has_value()); + } +#endif + DeleteSelf(); } @@ -2334,6 +2494,11 @@ void URLLoader::NotifyEarlyResponse( void URLLoader::SetRawRequestHeadersAndNotify( net::HttpRawRequestHeaders headers) { +#if BUILDFLAG(IS_OHOS) + // for prp_preload performance tools, real network request + TRACE_EVENT1("net", "URLLoader::SetRawRequestHeadersAndNotify", "id", + request_id_); +#endif // If we have seen_raw_request_headers_, then don't notify DevTools to prevent // duplicate ExtraInfo events. if (!seen_raw_request_headers_ && devtools_observer_ && @@ -2382,7 +2547,15 @@ void URLLoader::DispatchOnRawRequest( seen_raw_request_headers_ = true; net::LoadTimingInfo load_timing_info; +#if BUILDFLAG(IS_OHOS_PRPP) + if (prpp_loader_.get()) { + prpp_loader_->GetLoadTimingInfo(&load_timing_info); + } else { + url_request_->GetLoadTimingInfo(&load_timing_info); + } +#else url_request_->GetLoadTimingInfo(&load_timing_info); +#endif emitted_devtools_raw_request_ = true; @@ -2899,4 +3072,251 @@ bool URLLoader::CoepAllowCredentials(const GURL& url) { return false; } +#if BUILDFLAG(IS_OHOS_PRPP) +void URLLoader::UpdateResRequestInfo( + const std::string& key, + const std::shared_ptr& info) { + // "4" means blink::mojom::ResourceType::kImage. here not depend blink. + if ((info->preload_flag() != ohos_prp_preload::PRPP_FLAGS_NONE) || + (resource_type_ == 4)) { + already_update_info_ = true; + ohos_prp_preload::PRParallelPreloadMgr::GetInstance().UpdateResRequestInfo( + key, info); + } +} + +void URLLoader::InitUrlRequestForRollback( + URLLoaderContext& context, + const ResourceRequest& request, + const net::NetworkTrafficAnnotationTag& traffic_annotation, + bool third_party_cookies_enabled, + net::CookieSettingOverrides cookie_setting_overrides, + const std::string& org_main_url, + std::shared_ptr preload_info) { + url_request_rollback_ = url_request_context_->CreateRequestForPrpp( + GURL(request.url), request.priority, this, traffic_annotation, + /*is_for_websockets=*/false, request.net_log_create_info); + url_request_rollback_->set_method(request.method); + url_request_rollback_->set_site_for_cookies(request.site_for_cookies); + if (ShouldForceIgnoreSiteForCookies(request)) { + url_request_rollback_->set_force_ignore_site_for_cookies(true); + } + if (!request.navigation_redirect_chain.empty()) { + DCHECK_EQ(request.mode, mojom::RequestMode::kNavigate); + url_request_rollback_->SetURLChain(request.navigation_redirect_chain); + } + url_request_rollback_->SetReferrer(request.referrer.GetAsReferrer().spec()); + url_request_rollback_->set_referrer_policy(request.referrer_policy); + url_request_rollback_->set_upgrade_if_insecure(request.upgrade_if_insecure); + auto isolation_info = GetIsolationInfo( + factory_params_->isolation_info, + factory_params_->automatically_assign_isolation_info, request); + if (isolation_info) { + url_request_rollback_->set_isolation_info(isolation_info.value()); + } + if (context.ShouldRequireNetworkIsolationKey()) { + DCHECK(!url_request_rollback_->isolation_info().IsEmpty()); + } + if (ShouldForceIgnoreTopFramePartyForCookies()) { + url_request_rollback_->set_force_ignore_top_frame_party_for_cookies(true); + } + + // When a service worker forwards a navigation request it uses the + // service worker's IsolationInfo. This causes the cookie code to fail + // to send SameSite=Lax cookies for main-frame navigations passed through + // a service worker. To fix this we check to see if the original destination + // of the request was a main frame document and then set a flag indicating + // SameSite cookies should treat it as a main frame navigation. + + if (request.mode == mojom::RequestMode::kNavigate && + request.destination == mojom::RequestDestination::kEmpty && + request.original_destination == mojom::RequestDestination::kDocument) { + url_request_rollback_->set_force_main_frame_for_same_site_cookies(true); + } + + if (factory_params_->disable_secure_dns || + (request.trusted_params && + request.trusted_params->disable_secure_dns)) { + url_request_rollback_->SetSecureDnsPolicy(net::SecureDnsPolicy::kDisable); + } + + // |cors_exempt_headers| must be merged here to avoid breaking CORS checks. + // They are non-empty when the values are given by the UA code, therefore + // they should be ignored by CORS checks. + net::HttpRequestHeaders merged_headers = request.headers; + merged_headers.MergeFrom(request.cors_exempt_headers); + + // This should be ensured by the CorsURLLoaderFactory(), which is called + // before URLLoaders are created. + DCHECK(AreRequestHeadersSafe(merged_headers)); + + url_request_rollback_->SetExtraRequestHeaders(merged_headers); + url_request_rollback_->SetUserData(kUserDataKey, + std::make_unique(this)); + url_request_rollback_->set_accepted_stream_types( + request.devtools_accepted_stream_types); + + if (request.trusted_params) { + has_user_activation_ = request.trusted_params->has_user_activation; + allow_cookies_from_browser_ = + request.trusted_params->allow_cookies_from_browser; + } + + // Store any cookies passed from the browser process to later attach them to + // the request. + if (allow_cookies_from_browser_) { + cookies_from_browser_ = + GetCookiesFromHeaders(request.headers, request.cors_exempt_headers); + } + + throttling_token_ = network::ScopedThrottlingToken::MaybeCreate( + url_request_rollback_->net_log().source().id, + request.throttling_profile_id); + + url_request_rollback_->set_initiator(request.request_initiator); + SetFetchMetadataHeaders(url_request_rollback_.get(), request_mode_, + has_user_activation_, request_destination_, nullptr, + *factory_params_, *origin_access_list_); + + SetAttributionReportingHeaders(*url_request_rollback_, request); + if (request.update_first_party_url_on_redirect) { + url_request_rollback_->set_first_party_url_policy( + net::RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT); + } + + int request_load_flags = request.load_flags; + + if (cache_transparency_settings_ && + cache_transparency_settings_->pervasive_payloads_enabled()) { + auto index = cache_transparency_settings_->GetIndexForURL(request.url); + if (index.has_value()) { + // Remember that a pervasive payload was found so we can annotate the + // URLLoaderCompletionStatus with it later. + pervasive_payload_requested_ = true; + url_request_rollback_->set_pervasive_payloads_index_for_logging( + index.value()); + base::UmaHistogramCustomCounts("Network.CacheTransparency2.URLMatched", + index.value(), 1, 323, 323); + DVLOG(2) << "Found pervasive payload: " << request.url.spec(); + } + } + if (cache_transparency_settings_ && + cache_transparency_settings_->cache_transparency_enabled() && + third_party_cookies_enabled && + !(options_ & (mojom::kURLLoadOptionBlockThirdPartyCookies | + mojom::kURLLoadOptionBlockAllCookies))) { + auto checksum = + cache_transparency_settings_->GetChecksumForURL(request.url); + if (checksum.has_value()) { + CacheTransparencyCacheNotUsedReason cache_not_used_reason = + CacheTransparencyCacheNotUsedReason::kTryingSingleKeyedCache; + if (request.method != net::HttpRequestHeaders::kGetMethod) { + cache_not_used_reason = + CacheTransparencyCacheNotUsedReason::kIncompatibleRequestType; + } else if (HasFlagsIncompatibleWithSingleKeyedCache(request_load_flags)) { + cache_not_used_reason = + CacheTransparencyCacheNotUsedReason::kIncompatibleRequestLoadFlags; + } else if (HasHeadersIncompatibleWithSingleKeyedCache(request.headers)) { + cache_not_used_reason = + CacheTransparencyCacheNotUsedReason::kIncompatibleRequestHeaders; + } else { + url_request_rollback_->set_expected_response_checksum(checksum.value()); + } + base::UmaHistogramEnumeration("Network.CacheTransparency.CacheNotUsed", + cache_not_used_reason); + } + } + url_request_rollback_->SetLoadFlags(request_load_flags); + url_request_rollback_->SetPriorityIncremental(request.priority_incremental); + SetRequestCredentials(request.url); + url_request_rollback_->SetRequestHeadersCallback(base::BindRepeating( + &URLLoader::SetRawRequestHeadersAndNotify, base::Unretained(this))); + if (devtools_request_id()) { + url_request_rollback_->SetResponseHeadersCallback(base::BindRepeating( + &URLLoader::SetRawResponseHeaders, base::Unretained(this))); + } + + url_request_rollback_->SetEarlyResponseHeadersCallback(base::BindRepeating( + &URLLoader::NotifyEarlyResponse, base::Unretained(this))); + if (keepalive_ && keepalive_statistics_recorder_) { + keepalive_statistics_recorder_->OnLoadStarted( + *factory_params_->top_frame_id, keepalive_request_size_); + } + + if (request.net_log_reference_info) { + // Log source object that created the request, if avairable. + url_request_rollback_->net_log().AddEventReferencingSource( + net::NetLogEventType::CREATED_BY, + request.net_log_reference_info.value()); + } + url_request_rollback_->set_has_storage_access(request.has_storage_access); + + // add for prpp + SetUrlRequestForPRPP(request, url_request_rollback_, org_main_url, + preload_info); + // end for prpp + url_request_rollback_->cookie_setting_overrides().PutAll( + cookie_setting_overrides); + + if (request.is_outermost_main_frame && + network::cors::IsCorsEnabledRequestMode(request_mode_)) { + url_request_rollback_->cookie_setting_overrides().Put( + net::CookieSettingOverride::kTopLevelStorageAccessGrantEligible); + } + + // The `kStorageAccessGrantEligible` override will be applied (in-place) by + // individual request jobs as appropriate, but should not be present + // initially. + DCHECK(!url_request_rollback_->cookie_setting_overrides().Has( + net::CookieSettingOverride::kStorageAccessGrantEligible)); +} + +void URLLoader::SetUrlRequestForPRPP( + const ResourceRequest& request, + const std::shared_ptr& url_request, + const std::string& org_main_url, + std::shared_ptr& preload_info) { + if (ohos_prp_preload::PRParallelPreloadMgr::GetInstance() + .GetPRParallelPreloadMode() == + ohos_prp_preload::PRPPreloadMode::NONE) { + return; + } + if (!request.main_url.spec().empty() && + request.main_url.spec() != request.url.spec() && + (request.url.spec() != SECURITY_URL)) { + ohos_prp_preload::LoaderInfo loader_info { + corb_detachable_, + resource_type_, + keepalive_, + do_not_prompt_for_login_, + static_cast(request_mode_), + static_cast(request_credentials_mode_), + static_cast(request_destination_)}; + preload_info->set_loader_info(loader_info); + url_request->set_update_res_request_info_callback(base::BindRepeating( + &URLLoader::UpdateResRequestInfo, weak_ptr_factory_.GetWeakPtr())); + if (request.allow_preload_record) { + preload_info->or_preload_flag(ohos_prp_preload::PRPP_FLAGS_VISIBLE); + } + if (request.is_preflight) { + preload_info->set_type( + ohos_prp_preload::PRRequestInfoType::TYPE_PAGE_PREFLIGHT); + } + preload_info->set_request_start_time(base::Time::Now().ToInternalValue()); + url_request->set_preload_info(preload_info); + url_request->set_allow_preload_record(request.allow_preload_record); + if (!org_main_url.empty() && org_main_url != request.main_url.spec()) { + url_request->set_main_url(GURL(org_main_url)); + } else { + url_request->set_main_url(request.main_url); + } + } +} +void URLLoader::RollbackFromPPRP() { + url_request_ = url_request_rollback_; + url_request_rollback_ = nullptr; + BeginAttributionIfNecessaryAndThenScheduleStart(); +} +#endif + } // namespace network diff --git a/services/network/url_loader.h b/services/network/url_loader.h index 3fae515fe7..53a7cc9b53 100644 --- a/services/network/url_loader.h +++ b/services/network/url_loader.h @@ -26,6 +26,7 @@ #include "mojo/public/cpp/system/simple_watcher.h" #include "net/base/load_states.h" #include "net/base/network_delegate.h" +#include "net/base/prp_preload_buildflags.h" #include "net/base/transport_info.h" #include "net/cookies/cookie_setting_override.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -60,6 +61,11 @@ #include "services/network/url_loader_context.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#if BUILDFLAG(IS_OHOS_PRPP) +#include "services/network/prp_preload/include/preload_runner/prpp_request_loader.h" +#include "services/network/prp_preload/include/preload_runner/prpp_request_loader_factory.h" +#endif + namespace net { class HttpResponseHeaders; class IPEndPoint; @@ -169,7 +175,14 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader bool third_party_cookies_enabled, net::CookieSettingOverrides cookie_setting_overrides, const CacheTransparencySettings* cache_transparency_settings, - std::unique_ptr attribution_request_helper); + std::unique_ptr attribution_request_helper +#if BUILDFLAG(IS_OHOS_PRPP) + , + std::shared_ptr prpp_loader, + const std::string& org_main_url, + std::shared_ptr preload_info +#endif + ); URLLoader(const URLLoader&) = delete; URLLoader& operator=(const URLLoader&) = delete; @@ -519,7 +532,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader const int keepalive_request_size_; const bool keepalive_; const bool do_not_prompt_for_login_; +#if BUILDFLAG(IS_OHOS_PRPP) + std::shared_ptr url_request_; +#else std::unique_ptr url_request_; +#endif mojo::Receiver receiver_; mojo::Receiver auth_challenge_responder_receiver_{this}; @@ -690,6 +707,30 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader const bool provide_data_use_updates_; +#if BUILDFLAG(IS_OHOS_PRPP) + void UpdateResRequestInfo( + const std::string& key, + const std::shared_ptr& info); + void InitUrlRequestForRollback( + URLLoaderContext& context, + const ResourceRequest& request, + const net::NetworkTrafficAnnotationTag& traffic_annotation, + bool third_party_cookies_enabled, + net::CookieSettingOverrides cookie_setting_overrides, + const std::string& org_main_url, + std::shared_ptr preload_info); + void SetUrlRequestForPRPP( + const ResourceRequest& request, + const std::shared_ptr& url_request, + const std::string& org_main_url, + std::shared_ptr& preload_info); + void RollbackFromPPRP(); + std::shared_ptr prpp_loader_ { nullptr }; + bool redirect_updated_ { false }; + bool already_update_info_ { false }; + std::shared_ptr url_request_rollback_; +#endif + base::WeakPtrFactory weak_ptr_factory_{this}; }; diff --git a/services/network/url_loader_factory.cc b/services/network/url_loader_factory.cc index 53e0cb982e..c733f4c5fe 100644 --- a/services/network/url_loader_factory.cc +++ b/services/network/url_loader_factory.cc @@ -38,6 +38,10 @@ #include "url/gurl.h" #include "url/origin.h" +#if BUILDFLAG(IS_OHOS_PRPP) +#include "services/network/prp_preload/include/page_res_parallel_preload_mgr.h" +#endif + namespace network { namespace { @@ -362,6 +366,28 @@ void URLLoaderFactory::CreateLoaderAndStartWithSyncClient( context_->network_service()->trust_token_key_commitments()); } +#if BUILDFLAG(IS_OHOS_PRPP) + std::shared_ptr prpp_loader = nullptr; + std::shared_ptr preload_info = + std::make_shared(); + preload_info->set_preload_flag(ohos_prp_preload::PRPP_FLAGS_NONE); + if (!resource_request.main_url.spec().empty() && + ohos_prp_preload::PRParallelPreloadMgr::GetInstance() + .GetPRParallelPreloadMode() == + ohos_prp_preload::PRPPreloadMode::PRELOAD) { + if (!weak_prpp_req_loader_fac_.get()) { + weak_prpp_req_loader_fac_ = + ohos_prp_preload::PRParallelPreloadMgr::GetInstance() + .GetRequestLoaderFactory(resource_request.main_url.spec()); + } + + if (weak_prpp_req_loader_fac_.get()) { + prpp_loader = weak_prpp_req_loader_fac_.get()->GetPRPPReqLoader( + *this, resource_request, preload_info); + } + } +#endif + auto loader = std::make_unique( *this, base::BindOnce(&cors::CorsURLLoaderFactory::DestroyURLLoader, @@ -376,7 +402,14 @@ void URLLoaderFactory::CreateLoaderAndStartWithSyncClient( std::move(accept_ch_frame_observer), third_party_cookies_enabled, params_->cookie_setting_overrides, context_->cache_transparency_settings(), - std::move(attribution_request_helper)); + std::move(attribution_request_helper) +#if BUILDFLAG(IS_OHOS_PRPP) + , + prpp_loader, + weak_prpp_req_loader_fac_.get() ? weak_prpp_req_loader_fac_.get()->GetMainUrl() : "", + preload_info +#endif + ); if (context_->GetMemoryCache()) loader->SetMemoryCache(context_->GetMemoryCache()->GetWeakPtr()); diff --git a/services/network/url_loader_factory.h b/services/network/url_loader_factory.h index 2c2e820882..68db89c9a2 100644 --- a/services/network/url_loader_factory.h +++ b/services/network/url_loader_factory.h @@ -10,6 +10,7 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" +#include "net/base/prp_preload_buildflags.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/corb/corb_api.h" #include "services/network/public/mojom/cookie_access_observer.mojom.h" @@ -20,6 +21,10 @@ #include "services/network/public/mojom/url_loader_network_service_observer.mojom.h" #include "services/network/url_loader_context.h" +#if BUILDFLAG(IS_OHOS_PRPP) +#include "services/network/prp_preload/include/preload_runner/prpp_request_loader_factory.h" +#endif + namespace network { class NetworkContext; @@ -143,6 +148,10 @@ class URLLoaderFactory : public mojom::URLLoaderFactory, base::OneShotTimer update_load_info_timer_; bool waiting_on_load_state_ack_ = false; + +#if BUILDFLAG(IS_OHOS_PRPP) + base::WeakPtr weak_prpp_req_loader_fac_; +#endif }; } // namespace network diff --git a/ui/events/blink/fling_booster_unittest.cc b/ui/events/blink/fling_booster_unittest.cc index 19f1e91e27..90c948033c 100644 --- a/ui/events/blink/fling_booster_unittest.cc +++ b/ui/events/blink/fling_booster_unittest.cc @@ -64,6 +64,7 @@ class MockSystemPropertiesAdapter : public OHOS::NWeb::SystemPropertiesAdapter { MOCK_METHOD(std::string, GetUserAgentBaseOSName, (), (override)); MOCK_METHOD(std::string, GetUserAgentOSVersion, (), (override)); MOCK_METHOD(std::string, GetDeviceInfoApiVersion, (), (override)); + MOCK_METHOD(std::string, GetPRPPreloadMode, (), (override)); }; } // namespace OHOS::NWeb #endif // OHOS_UNITTESTS -- Gitee From 8ac89b245dc1dbf6758e47f23453376171fda918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=96=87=E9=9B=AA?= Date: Thu, 26 Dec 2024 09:47:39 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20net/?= =?UTF-8?q?prp=5Fpreload/src?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/page_res_parallel_preload_mgr_impl.cc | 184 ------------------ .../src/res_request_info_cache_mgr.cc | 170 ---------------- 2 files changed, 354 deletions(-) delete mode 100644 net/prp_preload/src/page_res_parallel_preload_mgr_impl.cc delete mode 100644 net/prp_preload/src/res_request_info_cache_mgr.cc diff --git a/net/prp_preload/src/page_res_parallel_preload_mgr_impl.cc b/net/prp_preload/src/page_res_parallel_preload_mgr_impl.cc deleted file mode 100644 index eb468512a1..0000000000 --- a/net/prp_preload/src/page_res_parallel_preload_mgr_impl.cc +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "page_res_parallel_preload_mgr_impl.h" - -#include "base/logging.h" -#include "ohos_adapter_helper.h" - -namespace { -static ohos_prp_preload::PRParallelPreloadMgrImpl g_prp_preload_mgr_impl; -const size_t MAX_PAGE_COUNT = 100; -} // namespace - -namespace ohos_prp_preload { -PRParallelPreloadMgr& PRParallelPreloadMgr::GetInstance() { - return g_prp_preload_mgr_impl; -} -bool PRParallelPreloadMgr::PRParallelPreloadEnabled() { - static bool res = OHOS::NWeb::OhosAdapterHelper::GetInstance().GetSystemPropertiesInstance().GetBoolParameter( - "web.PRPPreload.enable", false); - return res; -} - -void PRParallelPreloadMgrImpl::Init(const scoped_refptr& net_task_runner) { - if (!PRParallelPreloadMgr::GetInstance().PRParallelPreloadEnabled()) { - LOG(ERROR) << "PRPPreload.PRParallelPreloadMgrImpl::Init NOT ENABLE"; - return; - } - bool inited = false; - if (is_inited_.compare_exchange_strong(inited, true)) { - disk_cache_backend_factory_ = base::WrapRefCounted(new (std::nothrow) DiskCacheBackendFactory()); - if (disk_cache_backend_factory_ == nullptr) { - is_inited_.store(false); - LOG(ERROR) << "PRPPreload.PRParallelPreloadMgrImpl::Init failed no mem"; - return; - } - disk_cache_backend_factory_->CreateBackend(); - - sth_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner( - {base::TaskPriority::USER_VISIBLE}, base::SingleThreadTaskRunnerThreadMode::DEDICATED); - if (sth_task_runner_ == nullptr) { - is_inited_.store(false); - LOG(ERROR) << "PRPPreload.PRParallelPreloadMgrImpl::Init failed"; - return; - } - net_task_runner_ = net_task_runner; - } -} - -void PRParallelPreloadMgrImpl::StartMainPage(const std::string& url, - const net::NetworkAnonymizationKey& networkAnonymizationKey, - base::WeakPtr url_request_context, - uint64_t addr_web_handle) { - void* web_handle = reinterpret_cast(addr_web_handle); - if (url.empty() || web_handle == nullptr) { - LOG(ERROR) << "PRPPreload.PRParallelPreloadMgrImpl::StartMainPage failed, invalid args"; - return; - } - if (!is_inited_) { - return; - } - - std::lock_guard mgr_guard(mgr_mutex_); - if (!RecycleRPPCtrler()) { - LOG(ERROR) << "PRPPreload.PRParallelPreloadMgrImpl::StartMainPage RecycleRPPCtrler failed"; - return; - } - auto it = prp_preload_info_map_.find(url); - if (it != prp_preload_info_map_.end()) { - return; - } - - scoped_refptr rp_preload_ctrler = base::WrapRefCounted( - new (std::nothrow) ResParallelPreloadCtrler(url, networkAnonymizationKey, url_request_context, - sth_task_runner_, net_task_runner_, disk_cache_backend_factory_, - base::BindRepeating(&PRParallelPreloadMgrImpl::OnRPPCtrlerTimeout, base::Unretained(this)))); - if (rp_preload_ctrler == nullptr) { - LOG(ERROR) << "PRPPreload.PRParallelPreloadMgrImpl::StartMainPage new ResParallelPreloadCtrler failed"; - return; - } - - auto it_web = web_handle_pages_map_.find(web_handle); - if (it_web != web_handle_pages_map_.end()) { - if (it_web->second != url) { - StopMainPageInternal(it_web->second); - it_web->second = url; - } - } else { - web_handle_pages_map_[web_handle] = url; - } - rp_preload_ctrler->Start(); - prp_preload_info_map_[url].rp_preload_ctrler_ = rp_preload_ctrler; - prp_preload_info_map_[url].start_page_ = true; -} - -void PRParallelPreloadMgrImpl::StopMainPage(const std::string& url) { - if (!is_inited_) { - return; - } - - std::lock_guard mgr_guard(mgr_mutex_); - StopMainPageInternal(url); -} - -void PRParallelPreloadMgrImpl::StopMainPage(uint64_t addr_web_handle) { - if (!is_inited_) { - return; - } - - std::lock_guard mgr_guard(mgr_mutex_); - void* web_handle = reinterpret_cast(addr_web_handle); - if (web_handle == nullptr) { - return; - } - - auto it_web = web_handle_pages_map_.find(web_handle); - if (it_web != web_handle_pages_map_.end()) { - StopMainPageInternal(it_web->second); - (void)web_handle_pages_map_.erase(it_web); - } -} - -void PRParallelPreloadMgrImpl::UpdateResRequestInfo(const std::string& key, - const std::shared_ptr& info) { - if (!is_inited_) { - return; - } - - std::lock_guard mgr_guard(mgr_mutex_); - auto it = prp_preload_info_map_.find(key); - if (it != prp_preload_info_map_.end()) { - if (!it->second.start_page_) { - return; - } else { - it->second.rp_preload_ctrler_->UpdateResRequestInfo(info); - } - } -} - -void PRParallelPreloadMgrImpl::StopMainPageInternal(const std::string& url) { - auto it = prp_preload_info_map_.find(url); - if (it != prp_preload_info_map_.end()) { - if (it->second.start_page_) { - it->second.rp_preload_ctrler_->Stop(); - it->second.start_page_ = false; - stopped_pages_.push_back(url); - } - } -} - -void PRParallelPreloadMgrImpl::OnRPPCtrlerTimeout(const std::string& url) { - std::lock_guard mgr_guard(mgr_mutex_); - stopped_pages_.emplace_back(url); -} - -bool PRParallelPreloadMgrImpl::RecycleRPPCtrler() { - if ((stopped_pages_.size() <= 0) || (prp_preload_info_map_.size() <= MAX_PAGE_COUNT)) { - return true; - } - bool recycled = false; - do { - auto it = prp_preload_info_map_.find(stopped_pages_.front()); - stopped_pages_.pop_front(); - if (it == prp_preload_info_map_.end()) { - continue; - } - auto ctrler = it->second.rp_preload_ctrler_; - prp_preload_info_map_.erase(it); - recycled = true; - sth_task_runner_->PostTask(FROM_HERE, - base::BindOnce([] - (const scoped_refptr& ctrler) {}, - ctrler)); - break; - } while (stopped_pages_.size() > 0); - if (!recycled) { - LOG(ERROR) << "PRPPreload.PRParallelPreloadMgrImpl::RecycleRPPCtrler failed"; - } - - return recycled; -} - -} // namespace ohos_prp_preload diff --git a/net/prp_preload/src/res_request_info_cache_mgr.cc b/net/prp_preload/src/res_request_info_cache_mgr.cc deleted file mode 100644 index 89efb2c2ca..0000000000 --- a/net/prp_preload/src/res_request_info_cache_mgr.cc +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "res_request_info_cache_mgr.h" - -#include "base/logging.h" -#include "url/origin.h" - -namespace { -static constexpr base::TimeDelta CHECK_FLUSH_TO_DISK_TIMEOUT = base::Milliseconds(200); -} // namespace - -namespace ohos_prp_preload { -void ResReqPreloadInfoListToJson(const std::list>& info_list, - std::string& entry_content) { - entry_content = ""; - base::Value::List list; - for (auto info : info_list) { - base::Value::Dict dict; - dict.Set("url", url::Origin::Create(info->url()).GetURL().spec()); - dict.Set("allow_credentials", info->allow_credentials()); - auto cache_info = info->cache_info(); - dict.Set("cache_type", static_cast(cache_info.cache_type)); - dict.Set("freshness_life_times", std::to_string(cache_info.freshness_life_times)); - dict.Set("e_tag", cache_info.e_tag); - dict.Set("last_modified", cache_info.last_modified); - list.Append(std::move(dict)); - } - bool write_success = base::JSONWriter::Write(list, &entry_content); - if (!write_success) { - LOG(ERROR) << "PRPPreload.ResReqPreloadInfoListToJson failed"; - } -} - -void JsonToResReqPreloadInfoList(const std::string& json, - std::list>& info_list) { - absl::optional json_value = base::JSONReader::Read(json); - if (!json_value || !json_value->is_list()) { - LOG(ERROR) << "PRPPreload.JsonToResReqPreloadInfoList failed"; - return; - } - - for (const auto& json_item : json_value->GetList()) { - auto info = std::make_shared(); - const std::string* url = json_item.GetDict().FindString("url"); - if (!url || url->empty()) { - LOG(WARNING) << "PRPPreload.JsonToResReqPreloadInfoList url is invalid"; - continue; - } - info->set_url(GURL(*url)); - const absl::optional allow_credentials = json_item.GetDict().FindBool("allow_credentials"); - if (!allow_credentials.has_value()) { - LOG(WARNING) << "PRPPreload.JsonToResReqPreloadInfoList allow_credentials is invalid"; - continue; - } - info->set_allow_credentials(allow_credentials.value()); - const absl::optional cache_type = json_item.GetDict().FindInt("cache_type"); - if (!cache_type.has_value() || - cache_type.value() < PRRequestCacheType::NEGOTIATION_CACHE || - cache_type.value() > PRRequestCacheType::DISABLE_CACHE) { - LOG(WARNING) << "PRPPreload.JsonToResReqPreloadInfoList cache_type is invalid"; - continue; - } - info->set_cache_type(static_cast(cache_type.value())); - const std::string* freshness_life_times_str = json_item.GetDict().FindString("freshness_life_times"); - if (!freshness_life_times_str || freshness_life_times_str->empty()) { - LOG(WARNING) << "PRPPreload.JsonToResReqPreloadInfoList freshness_life_times is none"; - continue; - } - char* end = nullptr; - errno = 0; - int64_t freshness_life_times = std::strtoll(freshness_life_times_str->c_str(), &end, 10); - if (errno != 0 || !end || *end) { - LOG(WARNING) << "PRPPreload.JsonToResReqPreloadInfoList freshness_life_times is invalid"; - continue; - } - info->set_freshness_life_times(freshness_life_times); - const std::string* e_tag = json_item.GetDict().FindString("e_tag"); - if (!e_tag) { - LOG(WARNING) << "PRPPreload.JsonToResReqPreloadInfoList e_tag is invalid"; - continue; - } - info->set_e_tag(*e_tag); - const std::string* last_modified = json_item.GetDict().FindString("last_modified"); - if (!last_modified) { - LOG(WARNING) << "PRPPreload.JsonToResReqPreloadInfoList last_modified is invalid"; - continue; - } - info->set_last_modified(*last_modified); - info_list.push_back(info); - } -} -ResReqInfoCacheMgr::ResReqInfoCacheMgr(const std::string& url, - const net::NetworkAnonymizationKey& networkAnonymizationKey, - const scoped_refptr& sth_task_runner, - const scoped_refptr& disk_cache_backend_factory, - const ResRequestInfoCacheLoadedCB& info_cache_cb) : - networkAnonymizationKey_(networkAnonymizationKey), - sth_task_runner_(sth_task_runner), info_cache_loaded_cb_(info_cache_cb) { - disk_cache_ = base::WrapRefCounted(new (std::nothrow) DiskCacheFile(disk_cache_backend_factory, url, - base::BindRepeating(&ResReqInfoCacheMgr::OnEntryLoadedCallback, weak_factory_.GetWeakPtr()))); - if (disk_cache_ == nullptr) { - LOG(ERROR) << "PRPPreload.ResReqInfoCacheMgr::ResReqInfoCacheMgr new DiskCacheFile failed"; - } -} - -void ResReqInfoCacheMgr::Start() { - if ((disk_cache_ == nullptr) || (load_info_list_.size() > 0) || is_start_) { - return; - } - is_start_ = true; - disk_cache_->LoadInfoAsync(); - if (sth_task_runner_ != nullptr) { - sth_task_runner_->PostDelayedTask(FROM_HERE, - base::BindOnce(&ResReqInfoCacheMgr::CheckFlush, weak_factory_.GetWeakPtr()), - CHECK_FLUSH_TO_DISK_TIMEOUT); - } -} - -void ResReqInfoCacheMgr::UpdateResRequestInfo(const std::shared_ptr& info) { - if (disk_cache_ == nullptr || !is_start_) { - return; - } - new_info_list_.push_back(info); -} - -void ResReqInfoCacheMgr::Stop() { - if (disk_cache_ == nullptr || !is_start_) { - return; - } - is_start_ = false; - if (last_flush_len_ < new_info_list_.size()) { - std::string entry_content; - ResReqPreloadInfoListToJson(new_info_list_, entry_content); - disk_cache_->StoreInfoAsync(entry_content); - } - load_info_list_.clear(); - new_info_list_.clear(); - last_flush_len_ = 0; -} - -void ResReqInfoCacheMgr::OnEntryLoadedCallback(const std::string& entry_content) { - if (load_info_list_.size() > 0 || !is_start_) { - return; - } - JsonToResReqPreloadInfoList(entry_content, load_info_list_); - if (!info_cache_loaded_cb_.is_null()) { - info_cache_loaded_cb_.Run(load_info_list_, networkAnonymizationKey_); - } -} - -void ResReqInfoCacheMgr::CheckFlush() { - if (!is_start_) { - LOG(DEBUG) << "PRPPreload.ResReqInfoCacheMgr::CheckFlush no need to flush"; - return; - } - if (last_flush_len_ < new_info_list_.size()) { - std::string entry_content; - ResReqPreloadInfoListToJson(new_info_list_, entry_content); - disk_cache_->StoreInfoAsync(entry_content); - last_flush_len_ = new_info_list_.size(); - } - if (sth_task_runner_ != nullptr) { - sth_task_runner_->PostDelayedTask(FROM_HERE, - base::BindOnce(&ResReqInfoCacheMgr::CheckFlush, weak_factory_.GetWeakPtr()), - CHECK_FLUSH_TO_DISK_TIMEOUT); - } -} -} // namespace ohos_prp_preload -- Gitee