@@ -19,24 +19,26 @@ namespace {
19
19
20
20
struct SceneHostBindingKey {
21
21
std::string isolate_service_id;
22
- zx_koid_t koid ;
22
+ scenic::ResourceId resource_id ;
23
23
24
- SceneHostBindingKey (const zx_koid_t koid,
25
- const std::string isolate_service_id) {
26
- this ->koid = koid;
24
+ SceneHostBindingKey (const std::string isolate_service_id,
25
+ scenic::ResourceId resource_id) {
27
26
this ->isolate_service_id = isolate_service_id;
27
+ this ->resource_id = resource_id;
28
28
}
29
29
30
30
bool operator ==(const SceneHostBindingKey& other) const {
31
- return isolate_service_id == other.isolate_service_id && koid == other.koid ;
31
+ return isolate_service_id == other.isolate_service_id &&
32
+ resource_id == other.resource_id ;
32
33
}
33
34
};
34
35
35
36
struct SceneHostBindingKeyHasher {
36
37
std::size_t operator ()(const SceneHostBindingKey& key) const {
37
- std::size_t koid_hash = std::hash<zx_koid_t >()(key.koid );
38
38
std::size_t isolate_hash = std::hash<std::string>()(key.isolate_service_id );
39
- return koid_hash ^ isolate_hash;
39
+ std::size_t resource_id_hash =
40
+ std::hash<scenic::ResourceId>()(key.resource_id );
41
+ return isolate_hash ^ resource_id_hash;
40
42
}
41
43
};
42
44
@@ -54,7 +56,7 @@ void SceneHost_constructor(Dart_NativeArguments args) {
54
56
flutter::SceneHost* GetSceneHost (scenic::ResourceId id,
55
57
std::string isolate_service_id) {
56
58
auto binding =
57
- scene_host_bindings.find (SceneHostBindingKey (id, isolate_service_id ));
59
+ scene_host_bindings.find (SceneHostBindingKey (isolate_service_id, id ));
58
60
if (binding == scene_host_bindings.end ()) {
59
61
return nullptr ;
60
62
} else {
@@ -165,7 +167,8 @@ SceneHost::SceneHost(fml::RefPtr<zircon::dart::Handle> viewHolderToken,
165
167
Dart_Handle viewStateChangedCallback)
166
168
: raster_task_runner_(
167
169
UIDartState::Current ()->GetTaskRunners().GetRasterTaskRunner()),
168
- koid_(GetKoid(viewHolderToken->handle ())) {
170
+ koid_(GetKoid(viewHolderToken->handle ())),
171
+ weak_factory_(this ) {
169
172
auto dart_state = UIDartState::Current ();
170
173
isolate_service_id_ = Dart_IsolateServiceId (Dart_CurrentIsolate ());
171
174
@@ -180,34 +183,47 @@ SceneHost::SceneHost(fml::RefPtr<zircon::dart::Handle> viewHolderToken,
180
183
view_state_changed_callback_.Set (dart_state, viewStateChangedCallback);
181
184
}
182
185
183
- // This callback will be posted as a task when the |scenic::ViewHolder|
184
- // resource is created and given an id by the raster thread.
185
- auto bind_callback = [scene_host = this ,
186
- isolate_service_id =
187
- isolate_service_id_](scenic::ResourceId id) {
188
- const auto key = SceneHostBindingKey (id, isolate_service_id);
189
- scene_host_bindings.emplace (std::make_pair (key, scene_host));
186
+ // This callback is invoked on the raster thread when the |scenic::ViewHolder|
187
+ // resource is created and given an id.
188
+ auto bind_callback = [weak = weak_factory_.GetWeakPtr (),
189
+ ui_task_runner =
190
+ dart_state->GetTaskRunners ().GetUITaskRunner ()](
191
+ scenic::ResourceId id) {
192
+ ui_task_runner->PostTask ([weak, id]() {
193
+ if (!weak) {
194
+ FML_LOG (WARNING) << " ViewHolder bound to SceneHost after SceneHost was "
195
+ " destroyed; ignoring." ;
196
+ return ;
197
+ }
198
+
199
+ FML_DCHECK (weak->resource_id_ == 0 );
200
+ weak->resource_id_ = id;
201
+
202
+ const auto key =
203
+ SceneHostBindingKey (weak->isolate_service_id_ , weak->resource_id_ );
204
+ scene_host_bindings.emplace (std::make_pair (key, weak.get ()));
205
+ });
190
206
};
191
207
192
208
// Pass the raw handle to the raster thread; destroying a
193
209
// |zircon::dart::Handle| on that thread can cause a race condition.
194
- raster_task_runner_->PostTask (
195
- [id = koid_,
196
- ui_task_runner =
197
- UIDartState::Current ()->GetTaskRunners ().GetUITaskRunner (),
198
- raw_handle = viewHolderToken->ReleaseHandle (), bind_callback]() {
199
- flutter::ViewHolder::Create (
200
- id, std::move (ui_task_runner),
201
- scenic::ToViewHolderToken (zx::eventpair (raw_handle)),
202
- std::move (bind_callback));
203
- });
210
+ raster_task_runner_->PostTask ([koid = koid_,
211
+ raw_handle = viewHolderToken->ReleaseHandle (),
212
+ bind_callback = std::move (bind_callback)]() {
213
+ flutter::ViewHolder::Create (
214
+ koid, std::move (bind_callback),
215
+ scenic::ToViewHolderToken (zx::eventpair (raw_handle)));
216
+ });
204
217
}
205
218
206
219
SceneHost::~SceneHost () {
207
- scene_host_bindings.erase (SceneHostBindingKey (koid_, isolate_service_id_));
220
+ if (resource_id_ != 0 ) {
221
+ scene_host_bindings.erase (
222
+ SceneHostBindingKey (isolate_service_id_, resource_id_));
223
+ }
208
224
209
225
raster_task_runner_->PostTask (
210
- [id = koid_]() { flutter::ViewHolder::Destroy (id ); });
226
+ [koid = koid_]() { flutter::ViewHolder::Destroy (koid, nullptr ); });
211
227
}
212
228
213
229
void SceneHost::dispose () {
0 commit comments