-
Notifications
You must be signed in to change notification settings - Fork 15k
/
render_frame_context_bridge_store.cc
155 lines (130 loc) · 4.57 KB
/
render_frame_context_bridge_store.cc
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright (c) 2019 Slack Technologies, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/renderer/api/context_bridge/render_frame_context_bridge_store.h"
#include <utility>
#include "shell/common/api/remote/object_life_monitor.h"
namespace electron {
namespace api {
namespace context_bridge {
namespace {
class CachedProxyLifeMonitor final : public ObjectLifeMonitor {
public:
static void BindTo(v8::Isolate* isolate,
v8::Local<v8::Object> target,
base::WeakPtr<RenderFramePersistenceStore> store,
WeakGlobalPairNode* node,
int hash) {
new CachedProxyLifeMonitor(isolate, target, store, node, hash);
}
protected:
CachedProxyLifeMonitor(v8::Isolate* isolate,
v8::Local<v8::Object> target,
base::WeakPtr<RenderFramePersistenceStore> store,
WeakGlobalPairNode* node,
int hash)
: ObjectLifeMonitor(isolate, target),
store_(store),
node_(node),
hash_(hash) {}
void RunDestructor() override {
if (!store_)
return;
if (node_->detached) {
delete node_;
return;
}
if (node_->prev) {
node_->prev->next = node_->next;
node_->prev = nullptr;
}
if (node_->next) {
node_->next->prev = node_->prev;
node_->next = nullptr;
}
if (!node_->prev && !node_->next) {
// Must be a single length linked list
store_->proxy_map()->erase(hash_);
}
node_->detached = true;
}
private:
base::WeakPtr<RenderFramePersistenceStore> store_;
WeakGlobalPairNode* node_;
int hash_;
};
} // namespace
std::map<int32_t, RenderFramePersistenceStore*>& GetStoreMap() {
static base::NoDestructor<std::map<int32_t, RenderFramePersistenceStore*>>
store_map;
return *store_map;
}
WeakGlobalPairNode::WeakGlobalPairNode(WeakGlobalPair pair) {
this->pair = std::move(pair);
}
WeakGlobalPairNode::~WeakGlobalPairNode() {}
RenderFramePersistenceStore::RenderFramePersistenceStore(
content::RenderFrame* render_frame)
: content::RenderFrameObserver(render_frame),
routing_id_(render_frame->GetRoutingID()) {}
RenderFramePersistenceStore::~RenderFramePersistenceStore() = default;
void RenderFramePersistenceStore::OnDestruct() {
GetStoreMap().erase(routing_id_);
delete this;
}
void RenderFramePersistenceStore::CacheProxiedObject(
v8::Local<v8::Value> from,
v8::Local<v8::Value> proxy_value) {
if (from->IsObject() && !from->IsNullOrUndefined()) {
auto obj = v8::Local<v8::Object>::Cast(from);
int hash = obj->GetIdentityHash();
auto global_from = v8::Global<v8::Value>(v8::Isolate::GetCurrent(), from);
auto global_proxy =
v8::Global<v8::Value>(v8::Isolate::GetCurrent(), proxy_value);
// Do not retain
global_from.SetWeak();
global_proxy.SetWeak();
auto iter = proxy_map_.find(hash);
auto* node = new WeakGlobalPairNode(
std::make_tuple(std::move(global_from), std::move(global_proxy)));
CachedProxyLifeMonitor::BindTo(v8::Isolate::GetCurrent(), obj,
weak_factory_.GetWeakPtr(), node, hash);
CachedProxyLifeMonitor::BindTo(v8::Isolate::GetCurrent(),
v8::Local<v8::Object>::Cast(proxy_value),
weak_factory_.GetWeakPtr(), node, hash);
if (iter == proxy_map_.end()) {
proxy_map_.emplace(hash, node);
} else {
WeakGlobalPairNode* target = iter->second;
while (target->next) {
target = target->next;
}
target->next = node;
node->prev = target;
}
}
}
v8::MaybeLocal<v8::Value> RenderFramePersistenceStore::GetCachedProxiedObject(
v8::Local<v8::Value> from) {
if (!from->IsObject() || from->IsNullOrUndefined())
return v8::MaybeLocal<v8::Value>();
auto obj = v8::Local<v8::Object>::Cast(from);
int hash = obj->GetIdentityHash();
auto iter = proxy_map_.find(hash);
if (iter == proxy_map_.end())
return v8::MaybeLocal<v8::Value>();
WeakGlobalPairNode* target = iter->second;
while (target) {
auto from_cmp = std::get<0>(target->pair).Get(v8::Isolate::GetCurrent());
if (from_cmp == from) {
if (std::get<1>(target->pair).IsEmpty())
return v8::MaybeLocal<v8::Value>();
return std::get<1>(target->pair).Get(v8::Isolate::GetCurrent());
}
target = target->next;
}
return v8::MaybeLocal<v8::Value>();
}
} // namespace context_bridge
} // namespace api
} // namespace electron