blob: 9b953cdd9ed55b4f17a5075b758ed10b5aee50e2 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_RENDERER_HOST_DOCUMENT_ASSOCIATED_DATA_H_
#define CONTENT_BROWSER_RENDERER_HOST_DOCUMENT_ASSOCIATED_DATA_H_
#include <memory>
#include <optional>
#include <vector>
#include "base/containers/queue.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/safe_ref.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#include "base/types/pass_key.h"
#include "base/unguessable_token.h"
#include "content/browser/loader/keep_alive_url_loader_service.h"
#include "net/cookies/cookie_setting_override.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/confidence_level.mojom.h"
#include "url/gurl.h"
namespace content {
namespace internal {
class DocumentServiceBase;
}
class NavigationOrDocumentHandle;
class PageImpl;
class RenderFrameHostImpl;
// Container for arbitrary document-associated feature-specific data. Should
// be reset when committing a cross-document navigation in this
// RenderFrameHost. RenderFrameHostImpl stores internal members here
// directly while consumers of RenderFrameHostImpl should store data via
// GetDocumentUserData(). Please refer to the description at
// content/public/browser/document_user_data.h for more details.
class DocumentAssociatedData : public base::SupportsUserData {
public:
// Helper for looking up a RenderFrameHostImpl based on the DocumentToken.
// Restricted to RenderFrameHostImpl, which performs additional security
// checks.
static RenderFrameHostImpl* GetDocumentFromToken(
base::PassKey<RenderFrameHostImpl>,
const blink::DocumentToken& token);
explicit DocumentAssociatedData(RenderFrameHostImpl& document,
const blink::DocumentToken& token);
~DocumentAssociatedData() override;
DocumentAssociatedData(const DocumentAssociatedData&) = delete;
DocumentAssociatedData& operator=(const DocumentAssociatedData&) = delete;
// An opaque token that uniquely identifies the document currently
// associated with this RenderFrameHost. Note that in the case of
// speculative RenderFrameHost that has not yet committed, the renderer side
// will not have a document with a matching token!
const blink::DocumentToken& token() const { return token_; }
// The Page object associated with the main document. It is nullptr for
// subframes.
PageImpl* owned_page() { return owned_page_.get(); }
const PageImpl* owned_page() const { return owned_page_.get(); }
// Indicates whether `blink::mojom::DidDispatchDOMContentLoadedEvent` was
// called for this document or not.
bool dom_content_loaded() const { return dom_content_loaded_; }
void MarkDomContentLoaded() { dom_content_loaded_ = true; }
// Indicates whether a discard request has been dispatched for the current
// document.
bool is_discarded() const { return is_discarded_; }
void MarkDiscarded() { is_discarded_ = true; }
// Prerender2:
//
// The URL that `blink.mojom.LocalFrameHost::DidFinishLoad()` passed to
// DidFinishLoad, nullopt if DidFinishLoad wasn't called for this document
// or this document is not in prerendering. This is used to defer and
// dispatch DidFinishLoad notification on prerender activation.
const std::optional<GURL>& pending_did_finish_load_url_for_prerendering()
const {
return pending_did_finish_load_url_for_prerendering_;
}
void set_pending_did_finish_load_url_for_prerendering(const GURL& url) {
pending_did_finish_load_url_for_prerendering_.emplace(url);
}
void reset_pending_did_finish_load_url_for_prerendering() {
pending_did_finish_load_url_for_prerendering_.reset();
}
// Indicates whether `RenderFrameHostImpl::DidStopLoading` was called for this
// document while it's prerendering. This is used to defer and dispatch
// `WebContentsObserver::DidStopLoading` notification on prerender activation.
bool pending_did_stop_loading_for_prerendering() const {
return pending_did_stop_loading_for_prerendering_;
}
void set_pending_did_stop_loading_for_prerendering() {
pending_did_stop_loading_for_prerendering_ = true;
}
// Reporting API:
//
// Contains the reporting source token for this document, which will be
// associated with the reporting endpoint configuration in the network
// service, as well as with any reports which are queued by this document.
const base::UnguessableToken& reporting_source() const {
return token_.value();
}
// "Owned" but not with std::unique_ptr, as a DocumentServiceBase is
// allowed to delete itself directly.
std::vector<raw_ptr<internal::DocumentServiceBase, VectorExperimental>>&
services() {
return services_;
}
// This handle supports a seamless transfer from a navigation to a committed
// document.
const scoped_refptr<NavigationOrDocumentHandle>&
navigation_or_document_handle() const {
return navigation_or_document_handle_;
}
void set_navigation_or_document_handle(
scoped_refptr<NavigationOrDocumentHandle> handle);
// See comments for |RenderFrameHostImpl::GetDevToolsNavigationToken()| for
// more details.
const std::optional<base::UnguessableToken>& devtools_navigation_token()
const {
return devtools_navigation_token_;
}
void set_devtools_navigation_token(
const base::UnguessableToken& devtools_navigation_token) {
devtools_navigation_token_ = devtools_navigation_token;
}
blink::mojom::ConfidenceLevel navigation_confidence() const {
return confidence_level_;
}
void set_navigation_confidence(
blink::mojom::ConfidenceLevel confidence_level) {
confidence_level_ = confidence_level;
}
// fetch keepalive handing:
//
// Contains the weak pointer to the FactoryContext of the in-browser
// URLLoaderFactory implementation used by this document.
base::WeakPtr<KeepAliveURLLoaderService::FactoryContext>
keep_alive_url_loader_factory_context() const {
return keep_alive_url_loader_factory_context_;
}
void set_keep_alive_url_loader_factory_context(
base::WeakPtr<KeepAliveURLLoaderService::FactoryContext>
factory_context) {
DCHECK(!keep_alive_url_loader_factory_context_);
keep_alive_url_loader_factory_context_ = factory_context;
}
// Produces weak pointers to the hosting RenderFrameHostImpl. This is
// invalidated whenever DocumentAssociatedData is destroyed, due to
// RenderFrameHost deletion or cross-document navigation.
base::SafeRef<RenderFrameHostImpl> GetSafeRef() {
return weak_factory_.GetSafeRef();
}
base::WeakPtr<RenderFrameHostImpl> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
void AddService(internal::DocumentServiceBase* service,
base::PassKey<internal::DocumentServiceBase>);
void RemoveService(internal::DocumentServiceBase* service,
base::PassKey<internal::DocumentServiceBase>);
// Add `callback` to the callback queue to be run after prerendered page
// activation.
void AddPostPrerenderingActivationStep(base::OnceClosure callback);
// Run callback queue for post-prerendering activation.
void RunPostPrerenderingActivationSteps();
net::CookieSettingOverrides cookie_setting_overrides() const {
return cookie_setting_overrides_;
}
void PutCookieSettingOverride(
net::CookieSettingOverride cookie_setting_override);
void RemoveCookieSettingOverride(
net::CookieSettingOverride cookie_setting_override);
std::map<std::string, std::string>& crash_storage_map() {
return crash_storage_map_;
}
std::optional<uint64_t> crash_storage_requested_length() {
return crash_storage_requested_length_;
}
void set_crash_storage_requested_length(uint64_t length) {
crash_storage_requested_length_ = length;
}
private:
const blink::DocumentToken token_;
std::unique_ptr<PageImpl> owned_page_;
bool dom_content_loaded_ = false;
bool is_discarded_ = false;
std::optional<GURL> pending_did_finish_load_url_for_prerendering_;
bool pending_did_stop_loading_for_prerendering_ = false;
std::vector<raw_ptr<internal::DocumentServiceBase, VectorExperimental>>
services_;
scoped_refptr<NavigationOrDocumentHandle> navigation_or_document_handle_;
std::optional<base::UnguessableToken> devtools_navigation_token_;
blink::mojom::ConfidenceLevel confidence_level_ =
blink::mojom::ConfidenceLevel::kHigh;
base::WeakPtr<KeepAliveURLLoaderService::FactoryContext>
keep_alive_url_loader_factory_context_;
// The callback queue for post-prerendering activation.
base::queue<base::OnceClosure> post_prerendering_activation_callbacks_;
// The base set of overrides used by this document. This may be
// augmented/modified before being returned via
// `RenderFrameHostImpl::GetCookieSettingOverrides`.
net::CookieSettingOverrides cookie_setting_overrides_;
// This is written to by the `SetCrashReportStorageKey()` IPC, with data
// supplied by the renderer, and read from during
// `RenderFrameHostImpl::MaybeGenerateCrashReport()`, to supplement crash
// reports with this data.
std::map<std::string, std::string> crash_storage_map_;
// For now, this member is *only* used to track whether initialization has
// already occurred via this method. It will be more useful soon when it is
// used by `SetCrashReportStorageKey()` to actually enforce a cap on the
// number of bytes written to the backing crash report storage memory (for
// now, this is `crash_storage_map_`, but in the future it could be a shared
// memory region; see https://crrev.com/c/6788146 which is exploring this).
std::optional<uint64_t> crash_storage_requested_length_;
base::WeakPtrFactory<RenderFrameHostImpl> weak_factory_;
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_DOCUMENT_ASSOCIATED_DATA_H_