1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
// 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 COMPONENTS_AUTOFILL_IOS_FORM_UTIL_CHILD_FRAME_REGISTRAR_H_
#define COMPONENTS_AUTOFILL_IOS_FORM_UTIL_CHILD_FRAME_REGISTRAR_H_
#import <map>
#import <optional>
#import "base/observer_list.h"
#import "base/scoped_multi_source_observation.h"
#import "base/scoped_observation.h"
#import "components/autofill/core/common/unique_ids.h"
#import "ios/web/public/js_messaging/java_script_feature.h"
#import "ios/web/public/js_messaging/web_frames_manager.h"
#import "ios/web/public/web_state_observer.h"
#import "ios/web/public/web_state_user_data.h"
namespace autofill {
// Observer of ChildFrameRegistrar events.
class ChildFrameRegistrarObserver : public base::CheckedObserver {
public:
// Called when there was an attempt made to register the same remote token
// twice with a different |local| token. This may mean spoofing so the
// receiver of this notification should act accordingly.
virtual void OnDidDoubleRegistration(LocalFrameToken local) = 0;
};
// Child frame registration is the process whereby a frame can assign an ID (a
// remote frame token) to a child frame, establishing a relationship between
// that frame in the DOM (and JS) and the corresponding WebFrame object in C++.
// This class maintains those mappings.
class ChildFrameRegistrar : public web::WebStateUserData<ChildFrameRegistrar>,
public web::WebFramesManager::Observer,
public web::WebStateObserver {
public:
~ChildFrameRegistrar() override;
// Maps from remote to local tokens for all registered frames, to allow
// lookup of a frame based on its remote token.
//
// Frame Tokens are used by browser-layer Autofill code to identify and
// interact with a specific frame. Local Frame Tokens must not leak to frames
// other than the ones they identify, while Remote Frame Tokens are also known
// to the parent frame.
//
// In the context of iOS, the LocalFrameToken is equal to the frameId and can
// be used to fetch the appropriate WebFrame from the WebFramesManager.
std::optional<LocalFrameToken> LookupChildFrame(RemoteFrameToken remote);
// Informs the Registrar that `remote` corresponds to the frame with frame ID
// `local`.
void RegisterMapping(RemoteFrameToken remote, LocalFrameToken local);
// Convenience method that looks for dict values with keys "local_frame_id"
// and "remote_frame_id" in the given `message`, converts them to the
// appropriate tokens, and calls `RegisterMapping` using them. No-op if
// `message` is not a dict, if the needed keys are not present, or if the
// values are malformed.
void ProcessRegistrationMessage(base::Value* message);
// Notifies the registrar that a remote token `remote` has been dispatched to
// a child frame. If the registrar already knows about this token, `callback`
// will be invoked immediately with the corresponding local token. If not,
// the registrar will hold on to the callback until it encounters `remote` and
// execute it at that time.
// Be careful what you bind to `callback`, and use WeakPtr as necessary, as
// it may be retained indefinitely.
void DeclareNewRemoteToken(
RemoteFrameToken remote,
base::OnceCallback<void(LocalFrameToken)> callback);
// Returns the existing registrar for the given `web_state`, if there is one,
// or creates a new one. May return nullptr if this functionality is not
// available.
static ChildFrameRegistrar* GetOrCreateForWebState(web::WebState* web_state);
// Adds the |observer| to the list of observers.
void AddObserver(ChildFrameRegistrarObserver* observer);
// Removes |observer| from the list of observers.
void RemoveObserver(ChildFrameRegistrarObserver* observer);
// web::WebFramesManager::Observer:
void WebFrameBecameUnavailable(web::WebFramesManager* web_frames_manager,
const std::string& frame_id) override;
// web::WebStateObserver
void WebStateDestroyed(web::WebState* web_state) override;
private:
explicit ChildFrameRegistrar(web::WebState* web_state);
friend class web::WebStateUserData<ChildFrameRegistrar>;
// Deletes all entries in `lookup_map_` that contain `frame_id` as local frame
// token.
void RemoveFrameID(const std::string& frame_id);
// Maintains the mapping used by `LookupChildFrame`. The value containing the
// local frame token is set to std::nullopt if there was at least one attempt
// to register the same remote token, as a security precaution, making the
// token and thus the frame invalid for the entire registrar's lifetime.
std::map<RemoteFrameToken, std::optional<LocalFrameToken>> lookup_map_;
// When `DeclareNewRemoteToken` is called, the RemoteFrameToken may not
// yet correspond to a known frame. In this case, the callback is stored in
// this map until a matching remote token is registered.
std::map<RemoteFrameToken, base::OnceCallback<void(LocalFrameToken)>>
pending_callbacks_;
base::ObserverList<ChildFrameRegistrarObserver> observers_;
// Observation for listening to WebFrame events. Multiple observations are
// required because there are two WebFramesManager per WebState, one for each
// ContentWorld.
base::ScopedMultiSourceObservation<web::WebFramesManager,
web::WebFramesManager::Observer>
web_frames_managers_observation_{this};
base::ScopedObservation<web::WebState, web::WebStateObserver>
web_state_observation_{this};
};
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_IOS_FORM_UTIL_CHILD_FRAME_REGISTRAR_H_
|