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
content / services / auction_worklet / lazy_filler.h [blame]
// Copyright 2024 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_SERVICES_AUCTION_WORKLET_LAZY_FILLER_H_
#define CONTENT_SERVICES_AUCTION_WORKLET_LAZY_FILLER_H_
#include <string_view>
#include "base/memory/raw_ptr.h"
#include "v8/include/v8-external.h"
#include "v8/include/v8-forward.h"
#include "v8/include/v8-function-callback.h"
#include "v8/include/v8-object.h"
namespace auction_worklet {
class AuctionV8Helper;
// Helper class to populate fields of one or more v8::Objects on first access.
// The associated v8::Context must be destroyed immediately after the LazyFiller
// to avoid a UAF. Before would be better, but LazyFiller subclasses often have
// raw pointers to other context-scoped variables (e.g., an AuctionV8Logger)
// which must be destroyed after the LazyFiller.
//
// API for implementers is as follows:
//
// 1) Call DefineLazyAttribute() and/or DefineLazyAttributeWithMetadata()
// for all relevant attributes. There's no requirement that all calls be
// on the same object (e.g., can defined lazy attributes on objects
// contained within the same top-level object).
//
// 2) In the static helpers registered with DefineLazyAttribute
// (which take (v8::Local<v8::Name> name,
// const v8::PropertyCallbackInfo<v8::Value>& info)
// Use GetSelf() / GetSelfWithMetadata() and SetResult() to provide value.
//
// If you use the JSON parser, make sure to eat exceptions with v8::TryCatch.
class LazyFiller {
public:
virtual ~LazyFiller();
protected:
explicit LazyFiller(AuctionV8Helper* v8_helper);
AuctionV8Helper* v8_helper() { return v8_helper_.get(); }
// Returns the C++ object DefineLazyAttribute() was invoked on, from the
// PropertyCallbackInfo passed a lazy callback configured via
// DefineLazyAttribute().
//
// Does not work with attributes set by DefineLazyAttributeWithMetadata().
template <typename T>
static T* GetSelf(const v8::PropertyCallbackInfo<v8::Value>& info) {
return static_cast<T*>(v8::External::Cast(*info.Data())->Value());
}
// Like GetSelf(), but for DefineLazyAttributeWithMetadata().
//
// Does not work with attributes set by DefineLazyAttribute().
template <typename T>
static T* GetSelfWithMetadata(const v8::PropertyCallbackInfo<v8::Value>& info,
v8::Local<v8::Value>& metadata) {
return static_cast<T*>(GetSelfWithMetadataInternal(info, metadata));
}
static void SetResult(const v8::PropertyCallbackInfo<v8::Value>& info,
v8::Local<v8::Value> result);
bool DefineLazyAttribute(v8::Local<v8::Object> object,
std::string_view name,
v8::AccessorNameGetterCallback getter);
// `lazy_filler_template` is used to construct an internal v8 object with a
// pointer to `this` and `metadata` stored internally. It should be empty on
// the first call, and reused across calls, to avoid having to repeatedly
// create a new template.
bool DefineLazyAttributeWithMetadata(
v8::Local<v8::Object> object,
v8::Local<v8::Value> metadata,
std::string_view name,
v8::AccessorNameGetterCallback getter,
v8::Local<v8::ObjectTemplate>& lazy_filler_template);
private:
static void* GetSelfWithMetadataInternal(
const v8::PropertyCallbackInfo<v8::Value>& info,
v8::Local<v8::Value>& metadata);
const raw_ptr<AuctionV8Helper> v8_helper_;
};
} // namespace auction_worklet
#endif // CONTENT_SERVICES_AUCTION_WORKLET_LAZY_FILLER_H_