// 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 COMPONENTS_AUTOFILL_CORE_COMMON_UNIQUE_IDS_H_ #define COMPONENTS_AUTOFILL_CORE_COMMON_UNIQUE_IDS_H_ #include <ostream> #include <string> #include "base/types/id_type.h" #include "base/unguessable_token.h" #include "build/build_config.h" #include "third_party/abseil-cpp/absl/types/variant.h" namespace autofill { namespace internal { // TokenType wraps an base::UnguessableToken just like base::TokenType but // initializes to zero by default. We use it to define our own versions of // LocalFrameToken and RemoteFrameToken to avoid dependencies on blink here and // in the mojo code, since iOS depends on this code. template <typename TokenTypeMarker> class TokenType : public base::StrongAlias<TokenTypeMarker, base::UnguessableToken> { … }; } // namespace internal // LocalFrameToken and RemoteFrameToken identify AutofillDrivers and // AutofillAgents. // // TODO(crbug.com/40266699): Implement frame tokens as described below for iOS. // // Every pair of associated AutofillAgent and AutofillDriver has a // LocalFrameToken, which uniquely identifies them and remains stable for their // lifetime. // // In the //content layer, LocalFrameTokens are a secret between the browser // process and the renderer process hosting the respective AutofillAgent. // Therefore, cross-process AutofillAgents do not know each other's // LocalFrameToken. // // In such a case, an AutofillAgent A1 refers to another AutofillAgent A2 by // a RemoteFrameToken. The associated AutofillDriver D1 can obtain the // LocalFrameToken of A2 and its associated AutofillDriver D2 by calling // AutofillDriver::Resolve(). RemoteFrameTokens only have weak properties: // // 1. Different AutofillAgents may refer to A2 by different RemoteFrameTokens. // That is, D1.Resolve(R) == D3.Resolve(R') is possible for distinct // RemoteFrameTokens R, R', especially when A1 and A3 are hosted by different // renderer processes. // Therefore, RemoteFrameTokens are not suitable for discriminating between // AutofillAgents and AutofillDrivers in the browser process. // // 2. Over time, the same RemoteFrameToken may resolve to different // LocalFrameTokens. Suppose a navigation in A2's frame replaces A2 and D2 // with a new objects AutofillAgent A3 and AutofillDriver D3 (this happens on // a renderer process swap, which typically happens on cross-origin // navigations). Then A2 and A3 have distinct LocalFrameTokens, but A1 may // refer to A3 by the same RemoteFrameToken as it did to A2. That is, // D1.Resolve(R) may change over cross-origin navigations. // Therefore, AutofillDriver::Resolve() must not be cached. // // LocalFrameToken and RemoteFrameToken are Blink and //content layer concepts. // // If the //content layer is available, AutofillAgent and AutofillDriver inherit // their {Local,Remote}FrameToken from blink::Web{Local,Remote}Frame and // content::RenderFrameHost. // // On iOS, AutofillAgent and AutofillDriver inherit their LocalFrameToken from // web::WebFrame, and RemoteFrameTokens are generated during form extraction. // // FrameTokens must not be leaked to renderer processes other than the one // they originate from. Therefore, Autofill should generally not send // FrameTokens to any renderer process. RemoteFrameToken; LocalFrameToken; FrameToken; namespace internal { #if BUILDFLAG(IS_IOS) using FormRendererIdType = ::base::IdTypeU32<class FormRendererIdMarker>; using FieldRendererIdType = ::base::IdTypeU32<class FieldRendererIdMarker>; #else FormRendererIdType; FieldRendererIdType; #endif } // namespace internal // FormRendererId and FieldRendererId uniquely identify a DOM form or field // element, respectively, among all such elements in one frame. // // To uniquely identify forms and fields across frames, see FormGlobalId and // FieldGlobalId. // // As a sentinel value, the FormRendererId of a synthetic form converts to // `false` (== is_null()). A synthetic form is the collection of form fields // outside of the scope of any <form> tag in a document. // // Since each page can trigger an overflow, security must not rely on their // uniqueness. // // RendererIds are not necessarily persistent across page loads. // // The types are defined as subclasses instead of typedefs in order to avoid // having to define out-of-line constructors in all structs that contain // renderer IDs. class FormRendererId : public internal::FormRendererIdType { … }; class FieldRendererId : public internal::FieldRendererIdType { … }; namespace internal { template <typename RendererId> struct GlobalId { … }; } // namespace internal // FormGlobalId and FieldGlobalId uniquely identify a DOM form or field // element, respectively, among all such elements in all frames. // // As a sentinel value, the FormRendererId of a synthetic form converts to // `false`. A synthetic form is the collection of form fields outside of the // scope of any <form> tag in a page. // // GlobalIds are not necessarily persistent across page loads. // // Since LocalFrameTokens must not be leaked to renderer processes other than // the one they originate from, Autofill does not send GlobalIds to any renderer // process. // // TODO(crbug.com/40181498) Move to core/browser. FormGlobalId; FieldGlobalId; class LogBuffer; std::ostream& operator<<(std::ostream& os, const FormRendererId& form); std::ostream& operator<<(std::ostream& os, const FieldRendererId& field); std::ostream& operator<<(std::ostream& os, const FormGlobalId& form); std::ostream& operator<<(std::ostream& os, const FieldGlobalId& field); LogBuffer& operator<<(LogBuffer& buffer, const FormRendererId& form); LogBuffer& operator<<(LogBuffer& buffer, const FieldRendererId& field); LogBuffer& operator<<(LogBuffer& buffer, const FormGlobalId& form); LogBuffer& operator<<(LogBuffer& buffer, const FieldGlobalId& field); } // namespace autofill #endif // COMPONENTS_AUTOFILL_CORE_COMMON_UNIQUE_IDS_H_