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
|
// 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_CONTENT_BROWSER_TEST_AUTOFILL_CLIENT_INJECTOR_H_
#define COMPONENTS_AUTOFILL_CONTENT_BROWSER_TEST_AUTOFILL_CLIENT_INJECTOR_H_
#include <concepts>
#include "components/autofill/content/browser/content_autofill_client.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
namespace autofill {
// Asserts that at construction time, no other TestAutofillClientInjector, no
// other TestAutofillDriverInjector, and no TestAutofillManagerInjector are
// alive.
class TestAutofillClientInjectorBase {
public:
static bool some_instance_is_alive() { return num_instances_ > 0; }
TestAutofillClientInjectorBase(const TestAutofillClientInjectorBase&) =
delete;
TestAutofillClientInjectorBase& operator=(
const TestAutofillClientInjectorBase&) = delete;
protected:
TestAutofillClientInjectorBase();
~TestAutofillClientInjectorBase();
private:
static size_t num_instances_;
};
// RAII type that installs new AutofillClients of type `T` in all newly created
// WebContents.
//
// This happens *before* the production-code ContentAutofillClient is
// associated. It thus avoids dangling pointers to the production-code
// ContentAutofillClient.
//
// To prevent hard-to-find bugs, only one TestAutofillClientInjector may be
// alive at a time. It is compatible with TestAutofillDriverInjector and/or
// TestAutofillManagerInjector, but the client injector must be created first.
// These conditions are CHECKed.
//
// Usage:
//
// class AutofillFooTest : public ... {
// public:
// TestContentAutofillClient* autofill_client(
// content::WebContents* web_contents) {
// return autofill_client_injector_[web_contents];
// }
//
// private:
// TestAutofillClientInjector<TestContentAutofillClient>
// autofill_client_injector_;
// };
template <std::derived_from<ContentAutofillClient> T>
class TestAutofillClientInjector : public TestAutofillClientInjectorBase {
public:
TestAutofillClientInjector() = default;
TestAutofillClientInjector(const TestAutofillClientInjector&) = delete;
TestAutofillClientInjector& operator=(const TestAutofillClientInjector&) =
delete;
~TestAutofillClientInjector() = default;
T* operator[](content::WebContents* web_contents) const {
auto it = clients_.find(web_contents);
return it != clients_.end() ? it->second : nullptr;
}
private:
void InjectClient(content::WebContents* web_contents) {
auto client = std::make_unique<T>(web_contents);
clients_[web_contents] = client.get();
web_contents->SetUserData(T::UserDataKey(), std::move(client));
}
std::map<content::WebContents*, T*> clients_;
// Registers the lambda for the lifetime of `subscription_`.
base::CallbackListSubscription subscription_ =
content::RegisterWebContentsCreationCallback(
base::BindRepeating(&TestAutofillClientInjector::InjectClient,
base::Unretained(this)));
};
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CONTENT_BROWSER_TEST_AUTOFILL_CLIENT_INJECTOR_H_
|