chromium/content/public/browser/document_user_data.h

// Copyright 2020 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_PUBLIC_BROWSER_DOCUMENT_USER_DATA_H_
#define CONTENT_PUBLIC_BROWSER_DOCUMENT_USER_DATA_H_

#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/supports_user_data.h"
#include "content/common/content_export.h"
#include "url/origin.h"

namespace content {

class RenderFrameHost;

CONTENT_EXPORT base::SupportsUserData::Data* GetDocumentUserData(
    const RenderFrameHost* rfh,
    const void* key);

CONTENT_EXPORT void SetDocumentUserData(
    RenderFrameHost* rfh,
    const void* key,
    std::unique_ptr<base::SupportsUserData::Data> data);

CONTENT_EXPORT void RemoveDocumentUserData(RenderFrameHost* rfh,
                                           const void* key);

// This class approximates the lifetime of a single blink::Document in the
// browser process. At the moment RenderFrameHost can correspond to multiple
// blink::Documents (when RenderFrameHost is reused for same-process
// navigation). DocumentUserData is created when a user of an API
// inherits this class and calls CreateForCurrentDocument.
//
// DocumentUserData is cleared when either:
// - RenderFrameHost is deleted, or
// - A cross-document non-bfcached navigation is committed in the same
// RenderFrameHost i.e., DocumentUserData persists when a document is
// put in the BackForwardCache. It will still be present when the user navigates
// back to the document.
//
// DocumentUserData is assumed to be associated with the document in
// the RenderFrameHost. It can be associated even before RenderFrameHost commits
// i.e., on speculative RFHs and gets destroyed along with speculative RFHs if
// it ends up never committing.
//
// In case of crashes, DocumentUserData's lifetime doesn't match blink::Document
// lifetime. DocumentUserData is not cleared when the RenderFrame is deleted but
// is cleared on a subsequent navigation after a crash. This is done to ensure
// that the data associated with RenderFrameHost is not reset when the non-live
// RenderFrameHost is still in use by browser features like permissions or
// settings, which continue to work on the crashed pages. For more details,
// please refer to crbug.com/1099237.
//
// Note: RenderFrameHost is being replaced with RenderDocumentHost
// [https://crbug.com/936696]. After this is completed, every
// DocumentUserData object will be 1:1 with RenderFrameHost. Also
// RenderFrameHost/RenderDocument would start inheriting directly from
// SupportsUserData then we wouldn't need the use of
// GetDocumentUserData/SetDocumentUserData anymore.
//
// This is similar to WebContentsUserData but attached to a document instead.
// Example usage of DocumentUserData:
//
// --- in foo_document_helper.h ---
// class FooDocumentHelper
//     : public content::DocumentUserData<FooDocumentHelper> {
//  public:
//   ~FooDocumentHelper() override;
//
//   // ... more public stuff here ...
//
//  private:
//   // No public constructors to force going through static methods of
//   // DocumentUserData (e.g. CreateForCurrentDocument).
//   explicit FooDocumentHelper(content::RenderFrameHost* rfh);
//
//   friend DocumentUserData;
//   DOCUMENT_USER_DATA_KEY_DECL();
//
//   // ... more private stuff here ...
// };
//
// --- in foo_document_helper.cc ---
// DOCUMENT_USER_DATA_KEY_IMPL(FooDocumentHelper);
//
// FooDocumentHelper::FooDocumentHelper(content::RenderFrameHost* rfh)
//     : DocumentUserData(rfh) {}
//
// FooDocumentHelper::~FooDocumentHelper() {}
//
template <typename T>
class DocumentUserData : public base::SupportsUserData::Data {};

// Users won't be able to instantiate the template if they miss declaring the
// user data key.
// This macro declares a static variable inside the class that inherits from
// DocumentUserData. The address of this static variable is used as
// the key to store/retrieve an instance of the class on/from a WebState.
#define DOCUMENT_USER_DATA_KEY_DECL()

// This macro instantiates the static variable declared by the previous macro.
// It must live in a .cc file to ensure that there is only one instantiation
// of the static variable.
#define DOCUMENT_USER_DATA_KEY_IMPL(Type)

}  // namespace content

#endif  // CONTENT_PUBLIC_BROWSER_DOCUMENT_USER_DATA_H_