blob: 171c8187497b1628234db62dea5c6a6f99ed5ee8 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_BASE_UNOWNED_USER_DATA_SCOPED_UNOWNED_USER_DATA_H_
#define UI_BASE_UNOWNED_USER_DATA_SCOPED_UNOWNED_USER_DATA_H_
#include <concepts>
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/types/pass_key.h"
#include "ui/base/interaction/typed_identifier.h"
#include "ui/base/unowned_user_data/unowned_user_data_host.h"
namespace ui {
// A scoped class to set and unset an UnownedUserData entry on an
// UnownedUserDataHost.
//
// Example Usage:
// class MyFeature {
// public:
// // This provides both the kDataKey and the Get() function.
// DECLARE_USER_DATA(MyFeature);
//
// // The class doesn't have to contain its own holder, but if you want you
// // can add one to the private data and initialize it in the constructor:
//
// explicit MyFeature(UnownedUserDataHost& host)
// : scoped_data_holder_(host, *this) {}
//
// private:
// ScopedUnownedUserData<MyFeature> scoped_data_holder_;
// };
//
// DEFINE_USER_DATA(MyFeature);
template <class T>
class ScopedUnownedUserData {
public:
using PassKey = base::PassKey<ScopedUnownedUserData<T>>;
ScopedUnownedUserData(UnownedUserDataHost& host, T& data)
: host_(host), data_(data) {
host_->Set(PassKey(), T::kDataKey, *data_);
}
virtual ~ScopedUnownedUserData() { host_->Erase(PassKey(), T::kDataKey); }
static T* Get(UnownedUserDataHost& host) {
return host.Get(PassKey(), T::kDataKey);
}
static const T* Get(const UnownedUserDataHost& host) {
return host.Get(PassKey(), T::kDataKey);
}
private:
raw_ref<UnownedUserDataHost> host_;
raw_ref<T> data_;
};
} // namespace ui
// Helper macros. See above for usage.
#define DECLARE_USER_DATA(ClassName) \
DECLARE_CLASS_TYPED_IDENTIFIER_VALUE(ClassName, kDataKey); \
static ClassName* Get(::ui::UnownedUserDataHost& host); \
static const ClassName* Get(const ::ui::UnownedUserDataHost& host)
#define DEFINE_USER_DATA(ClassName) \
ClassName* ClassName::Get(::ui::UnownedUserDataHost& host) { \
return ::ui::ScopedUnownedUserData<ClassName>::Get(host); \
} \
const ClassName* ClassName::Get(const ::ui::UnownedUserDataHost& host) { \
return ::ui::ScopedUnownedUserData<ClassName>::Get(host); \
} \
DEFINE_CLASS_TYPED_IDENTIFIER_VALUE(ClassName, ClassName, kDataKey)
#endif // UI_BASE_UNOWNED_USER_DATA_SCOPED_UNOWNED_USER_DATA_H_