@@ -19,24 +19,26 @@ namespace {
1919
2020struct SceneHostBindingKey {
2121 std::string isolate_service_id;
22- zx_koid_t koid ;
22+ scenic::ResourceId resource_id ;
2323
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) {
2726 this ->isolate_service_id = isolate_service_id;
27+ this ->resource_id = resource_id;
2828 }
2929
3030 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 ;
3233 }
3334};
3435
3536struct SceneHostBindingKeyHasher {
3637 std::size_t operator ()(const SceneHostBindingKey& key) const {
37- std::size_t koid_hash = std::hash<zx_koid_t >()(key.koid );
3838 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;
4042 }
4143};
4244
@@ -54,7 +56,7 @@ void SceneHost_constructor(Dart_NativeArguments args) {
5456flutter::SceneHost* GetSceneHost (scenic::ResourceId id,
5557 std::string isolate_service_id) {
5658 auto binding =
57- scene_host_bindings.find (SceneHostBindingKey (id, isolate_service_id ));
59+ scene_host_bindings.find (SceneHostBindingKey (isolate_service_id, id ));
5860 if (binding == scene_host_bindings.end ()) {
5961 return nullptr ;
6062 } else {
@@ -165,7 +167,8 @@ SceneHost::SceneHost(fml::RefPtr<zircon::dart::Handle> viewHolderToken,
165167 Dart_Handle viewStateChangedCallback)
166168 : raster_task_runner_(
167169 UIDartState::Current ()->GetTaskRunners().GetRasterTaskRunner()),
168- koid_(GetKoid(viewHolderToken->handle ())) {
170+ koid_(GetKoid(viewHolderToken->handle ())),
171+ weak_factory_(this ) {
169172 auto dart_state = UIDartState::Current ();
170173 isolate_service_id_ = Dart_IsolateServiceId (Dart_CurrentIsolate ());
171174
@@ -180,34 +183,47 @@ SceneHost::SceneHost(fml::RefPtr<zircon::dart::Handle> viewHolderToken,
180183 view_state_changed_callback_.Set (dart_state, viewStateChangedCallback);
181184 }
182185
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+ });
190206 };
191207
192208 // Pass the raw handle to the raster thread; destroying a
193209 // |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+ });
204217}
205218
206219SceneHost::~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+ }
208224
209225 raster_task_runner_->PostTask (
210- [id = koid_]() { flutter::ViewHolder::Destroy (id ); });
226+ [koid = koid_]() { flutter::ViewHolder::Destroy (koid, nullptr ); });
211227}
212228
213229void SceneHost::dispose () {
0 commit comments