// Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "flutter/runtime/runtime_controller.h" #include "flutter/fml/message_loop.h" #include "flutter/fml/trace_event.h" #include "flutter/lib/ui/compositing/scene.h" #include "flutter/lib/ui/ui_dart_state.h" #include "flutter/lib/ui/window/window.h" #include "flutter/runtime/runtime_delegate.h" #include "third_party/tonic/dart_message_handler.h" namespace blink { RuntimeController::RuntimeController( RuntimeDelegate& p_client, DartVM* p_vm, fml::RefPtr p_isolate_snapshot, fml::RefPtr p_shared_snapshot, TaskRunners p_task_runners, fml::WeakPtr p_snapshot_delegate, fml::WeakPtr p_io_manager, std::string p_advisory_script_uri, std::string p_advisory_script_entrypoint, std::function p_idle_notification_callback) : RuntimeController(p_client, p_vm, std::move(p_isolate_snapshot), std::move(p_shared_snapshot), std::move(p_task_runners), std::move(p_snapshot_delegate), std::move(p_io_manager), std::move(p_advisory_script_uri), std::move(p_advisory_script_entrypoint), p_idle_notification_callback, WindowData{/* default window data */}) {} RuntimeController::RuntimeController( RuntimeDelegate& p_client, DartVM* p_vm, fml::RefPtr p_isolate_snapshot, fml::RefPtr p_shared_snapshot, TaskRunners p_task_runners, fml::WeakPtr p_snapshot_delegate, fml::WeakPtr p_io_manager, std::string p_advisory_script_uri, std::string p_advisory_script_entrypoint, std::function idle_notification_callback, WindowData p_window_data) : client_(p_client), vm_(p_vm), isolate_snapshot_(std::move(p_isolate_snapshot)), shared_snapshot_(std::move(p_shared_snapshot)), task_runners_(p_task_runners), snapshot_delegate_(p_snapshot_delegate), io_manager_(p_io_manager), advisory_script_uri_(p_advisory_script_uri), advisory_script_entrypoint_(p_advisory_script_entrypoint), idle_notification_callback_(idle_notification_callback), window_data_(std::move(p_window_data)), root_isolate_( DartIsolate::CreateRootIsolate(vm_->GetVMData()->GetSettings(), isolate_snapshot_, shared_snapshot_, task_runners_, std::make_unique(this), snapshot_delegate_, io_manager_, p_advisory_script_uri, p_advisory_script_entrypoint)) { std::shared_ptr root_isolate = root_isolate_.lock(); root_isolate->SetReturnCodeCallback([this](uint32_t code) { root_isolate_return_code_ = {true, code}; }); if (auto* window = GetWindowIfAvailable()) { tonic::DartState::Scope scope(root_isolate); window->DidCreateIsolate(); if (!FlushRuntimeStateToIsolate()) { FML_DLOG(ERROR) << "Could not setup intial isolate state."; } } else { FML_DCHECK(false) << "RuntimeController created without window binding."; } FML_DCHECK(Dart_CurrentIsolate() == nullptr); } RuntimeController::~RuntimeController() { FML_DCHECK(Dart_CurrentIsolate() == nullptr); std::shared_ptr root_isolate = root_isolate_.lock(); if (root_isolate) { root_isolate->SetReturnCodeCallback(nullptr); auto result = root_isolate->Shutdown(); if (!result) { FML_DLOG(ERROR) << "Could not shutdown the root isolate."; } root_isolate_ = {}; } } bool RuntimeController::IsRootIsolateRunning() const { std::shared_ptr root_isolate = root_isolate_.lock(); if (root_isolate) { return root_isolate->GetPhase() == DartIsolate::Phase::Running; } return false; } std::unique_ptr RuntimeController::Clone() const { return std::unique_ptr(new RuntimeController( client_, // vm_, // isolate_snapshot_, // shared_snapshot_, // task_runners_, // snapshot_delegate_, // io_manager_, // advisory_script_uri_, // advisory_script_entrypoint_, // idle_notification_callback_, // window_data_ // )); } bool RuntimeController::FlushRuntimeStateToIsolate() { return SetViewportMetrics(window_data_.viewport_metrics) && SetLocales(window_data_.locale_data) && SetSemanticsEnabled(window_data_.semantics_enabled) && SetAccessibilityFeatures(window_data_.accessibility_feature_flags_) && SetUserSettingsData(window_data_.user_settings_data) && SetLifecycleState(window_data_.lifecycle_state); } bool RuntimeController::SetViewportMetrics(const ViewportMetrics& metrics) { window_data_.viewport_metrics = metrics; if (auto* window = GetWindowIfAvailable()) { window->UpdateWindowMetrics(metrics); return true; } return false; } bool RuntimeController::SetLocales( const std::vector& locale_data) { window_data_.locale_data = locale_data; if (auto* window = GetWindowIfAvailable()) { window->UpdateLocales(locale_data); return true; } return false; } bool RuntimeController::SetUserSettingsData(const std::string& data) { window_data_.user_settings_data = data; if (auto* window = GetWindowIfAvailable()) { window->UpdateUserSettingsData(window_data_.user_settings_data); return true; } return false; } bool RuntimeController::SetLifecycleState(const std::string& data) { window_data_.lifecycle_state = data; if (auto* window = GetWindowIfAvailable()) { window->UpdateLifecycleState(window_data_.lifecycle_state); return true; } return false; } bool RuntimeController::SetSemanticsEnabled(bool enabled) { window_data_.semantics_enabled = enabled; if (auto* window = GetWindowIfAvailable()) { window->UpdateSemanticsEnabled(window_data_.semantics_enabled); return true; } return false; } bool RuntimeController::SetAccessibilityFeatures(int32_t flags) { window_data_.accessibility_feature_flags_ = flags; if (auto* window = GetWindowIfAvailable()) { window->UpdateAccessibilityFeatures( window_data_.accessibility_feature_flags_); return true; } return false; } bool RuntimeController::BeginFrame(fml::TimePoint frame_time) { if (auto* window = GetWindowIfAvailable()) { window->BeginFrame(frame_time); return true; } return false; } bool RuntimeController::NotifyIdle(int64_t deadline) { std::shared_ptr root_isolate = root_isolate_.lock(); if (!root_isolate) { return false; } tonic::DartState::Scope scope(root_isolate); Dart_NotifyIdle(deadline); // Idle notifications being in isolate scope are part of the contract. if (idle_notification_callback_) { TRACE_EVENT0("flutter", "EmbedderIdleNotification"); idle_notification_callback_(deadline); } return true; } bool RuntimeController::DispatchPlatformMessage( fml::RefPtr message) { if (auto* window = GetWindowIfAvailable()) { TRACE_EVENT1("flutter", "RuntimeController::DispatchPlatformMessage", "mode", "basic"); window->DispatchPlatformMessage(std::move(message)); return true; } return false; } bool RuntimeController::DispatchPointerDataPacket( const PointerDataPacket& packet) { if (auto* window = GetWindowIfAvailable()) { TRACE_EVENT1("flutter", "RuntimeController::DispatchPointerDataPacket", "mode", "basic"); window->DispatchPointerDataPacket(packet); return true; } return false; } bool RuntimeController::DispatchSemanticsAction(int32_t id, SemanticsAction action, std::vector args) { TRACE_EVENT1("flutter", "RuntimeController::DispatchSemanticsAction", "mode", "basic"); if (auto* window = GetWindowIfAvailable()) { window->DispatchSemanticsAction(id, action, std::move(args)); return true; } return false; } Window* RuntimeController::GetWindowIfAvailable() { std::shared_ptr root_isolate = root_isolate_.lock(); return root_isolate ? root_isolate->window() : nullptr; } std::string RuntimeController::DefaultRouteName() { return client_.DefaultRouteName(); } void RuntimeController::ScheduleFrame() { client_.ScheduleFrame(); } void RuntimeController::Render(Scene* scene) { client_.Render(scene->takeLayerTree()); } void RuntimeController::UpdateSemantics(SemanticsUpdate* update) { if (window_data_.semantics_enabled) { client_.UpdateSemantics(update->takeNodes(), update->takeActions()); } } void RuntimeController::HandlePlatformMessage( fml::RefPtr message) { client_.HandlePlatformMessage(std::move(message)); } FontCollection& RuntimeController::GetFontCollection() { return client_.GetFontCollection(); } void RuntimeController::UpdateIsolateDescription(const std::string isolate_name, int64_t isolate_port) { client_.UpdateIsolateDescription(isolate_name, isolate_port); } Dart_Port RuntimeController::GetMainPort() { std::shared_ptr root_isolate = root_isolate_.lock(); return root_isolate ? root_isolate->main_port() : ILLEGAL_PORT; } std::string RuntimeController::GetIsolateName() { std::shared_ptr root_isolate = root_isolate_.lock(); return root_isolate ? root_isolate->debug_name() : ""; } bool RuntimeController::HasLivePorts() { std::shared_ptr root_isolate = root_isolate_.lock(); if (!root_isolate) { return false; } tonic::DartState::Scope scope(root_isolate); return Dart_HasLivePorts(); } tonic::DartErrorHandleType RuntimeController::GetLastError() { std::shared_ptr root_isolate = root_isolate_.lock(); return root_isolate ? root_isolate->GetLastError() : tonic::kNoError; } std::weak_ptr RuntimeController::GetRootIsolate() { return root_isolate_; } std::pair RuntimeController::GetRootIsolateReturnCode() { return root_isolate_return_code_; } RuntimeController::Locale::Locale(std::string language_code_, std::string country_code_, std::string script_code_, std::string variant_code_) : language_code(language_code_), country_code(country_code_), script_code(script_code_), variant_code(variant_code_) {} RuntimeController::Locale::~Locale() = default; RuntimeController::WindowData::WindowData() = default; RuntimeController::WindowData::WindowData(const WindowData& other) = default; RuntimeController::WindowData::~WindowData() = default; } // namespace blink