1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #include "flutter/lib/ui/ui_dart_state.h" |
6 | |
7 | #include "flutter/fml/message_loop.h" |
8 | #include "flutter/lib/ui/window/platform_configuration.h" |
9 | #include "third_party/tonic/converter/dart_converter.h" |
10 | #include "third_party/tonic/dart_message_handler.h" |
11 | |
12 | using tonic::ToDart; |
13 | |
14 | namespace flutter { |
15 | |
16 | UIDartState::UIDartState( |
17 | TaskRunners task_runners, |
18 | TaskObserverAdd add_callback, |
19 | TaskObserverRemove remove_callback, |
20 | fml::WeakPtr<SnapshotDelegate> snapshot_delegate, |
21 | fml::WeakPtr<IOManager> io_manager, |
22 | fml::RefPtr<SkiaUnrefQueue> skia_unref_queue, |
23 | fml::WeakPtr<ImageDecoder> image_decoder, |
24 | std::string advisory_script_uri, |
25 | std::string advisory_script_entrypoint, |
26 | std::string logger_prefix, |
27 | UnhandledExceptionCallback unhandled_exception_callback, |
28 | std::shared_ptr<IsolateNameServer> isolate_name_server, |
29 | bool is_root_isolate) |
30 | : task_runners_(std::move(task_runners)), |
31 | add_callback_(std::move(add_callback)), |
32 | remove_callback_(std::move(remove_callback)), |
33 | snapshot_delegate_(std::move(snapshot_delegate)), |
34 | io_manager_(std::move(io_manager)), |
35 | skia_unref_queue_(std::move(skia_unref_queue)), |
36 | image_decoder_(std::move(image_decoder)), |
37 | advisory_script_uri_(std::move(advisory_script_uri)), |
38 | advisory_script_entrypoint_(std::move(advisory_script_entrypoint)), |
39 | logger_prefix_(std::move(logger_prefix)), |
40 | is_root_isolate_(is_root_isolate), |
41 | unhandled_exception_callback_(unhandled_exception_callback), |
42 | isolate_name_server_(std::move(isolate_name_server)) { |
43 | AddOrRemoveTaskObserver(true /* add */); |
44 | } |
45 | |
46 | UIDartState::~UIDartState() { |
47 | AddOrRemoveTaskObserver(false /* remove */); |
48 | } |
49 | |
50 | const std::string& UIDartState::GetAdvisoryScriptURI() const { |
51 | return advisory_script_uri_; |
52 | } |
53 | |
54 | const std::string& UIDartState::GetAdvisoryScriptEntrypoint() const { |
55 | return advisory_script_entrypoint_; |
56 | } |
57 | |
58 | void UIDartState::DidSetIsolate() { |
59 | main_port_ = Dart_GetMainPortId(); |
60 | std::ostringstream debug_name; |
61 | // main.dart$main-1234 |
62 | debug_name << advisory_script_uri_ << "$" << advisory_script_entrypoint_ |
63 | << "-" << main_port_; |
64 | SetDebugName(debug_name.str()); |
65 | } |
66 | |
67 | void UIDartState::ThrowIfUIOperationsProhibited() { |
68 | if (!UIDartState::Current()->IsRootIsolate()) { |
69 | Dart_ThrowException( |
70 | tonic::ToDart("UI actions are only available on root isolate." )); |
71 | } |
72 | } |
73 | |
74 | void UIDartState::SetDebugName(const std::string debug_name) { |
75 | debug_name_ = debug_name; |
76 | if (platform_configuration_) { |
77 | platform_configuration_->client()->UpdateIsolateDescription(debug_name_, |
78 | main_port_); |
79 | } |
80 | } |
81 | |
82 | UIDartState* UIDartState::Current() { |
83 | return static_cast<UIDartState*>(DartState::Current()); |
84 | } |
85 | |
86 | void UIDartState::SetPlatformConfiguration( |
87 | std::unique_ptr<PlatformConfiguration> platform_configuration) { |
88 | platform_configuration_ = std::move(platform_configuration); |
89 | if (platform_configuration_) { |
90 | platform_configuration_->client()->UpdateIsolateDescription(debug_name_, |
91 | main_port_); |
92 | } |
93 | } |
94 | |
95 | const TaskRunners& UIDartState::GetTaskRunners() const { |
96 | return task_runners_; |
97 | } |
98 | |
99 | fml::WeakPtr<IOManager> UIDartState::GetIOManager() const { |
100 | return io_manager_; |
101 | } |
102 | |
103 | fml::RefPtr<flutter::SkiaUnrefQueue> UIDartState::GetSkiaUnrefQueue() const { |
104 | return skia_unref_queue_; |
105 | } |
106 | |
107 | void UIDartState::ScheduleMicrotask(Dart_Handle closure) { |
108 | if (tonic::LogIfError(closure) || !Dart_IsClosure(closure)) { |
109 | return; |
110 | } |
111 | |
112 | microtask_queue_.ScheduleMicrotask(closure); |
113 | } |
114 | |
115 | void UIDartState::FlushMicrotasksNow() { |
116 | microtask_queue_.RunMicrotasks(); |
117 | } |
118 | |
119 | void UIDartState::AddOrRemoveTaskObserver(bool add) { |
120 | auto task_runner = task_runners_.GetUITaskRunner(); |
121 | if (!task_runner) { |
122 | // This may happen in case the isolate has no thread affinity (for example, |
123 | // the service isolate). |
124 | return; |
125 | } |
126 | FML_DCHECK(add_callback_ && remove_callback_); |
127 | if (add) { |
128 | add_callback_(reinterpret_cast<intptr_t>(this), |
129 | [this]() { this->FlushMicrotasksNow(); }); |
130 | } else { |
131 | remove_callback_(reinterpret_cast<intptr_t>(this)); |
132 | } |
133 | } |
134 | |
135 | fml::WeakPtr<SnapshotDelegate> UIDartState::GetSnapshotDelegate() const { |
136 | return snapshot_delegate_; |
137 | } |
138 | |
139 | fml::WeakPtr<GrDirectContext> UIDartState::GetResourceContext() const { |
140 | if (!io_manager_) { |
141 | return {}; |
142 | } |
143 | return io_manager_->GetResourceContext(); |
144 | } |
145 | |
146 | fml::WeakPtr<ImageDecoder> UIDartState::GetImageDecoder() const { |
147 | return image_decoder_; |
148 | } |
149 | |
150 | std::shared_ptr<IsolateNameServer> UIDartState::GetIsolateNameServer() const { |
151 | return isolate_name_server_; |
152 | } |
153 | |
154 | tonic::DartErrorHandleType UIDartState::GetLastError() { |
155 | tonic::DartErrorHandleType error = message_handler().isolate_last_error(); |
156 | if (error == tonic::kNoError) { |
157 | error = microtask_queue_.GetLastError(); |
158 | } |
159 | return error; |
160 | } |
161 | |
162 | void UIDartState::ReportUnhandledException(const std::string& error, |
163 | const std::string& stack_trace) { |
164 | if (unhandled_exception_callback_ && |
165 | unhandled_exception_callback_(error, stack_trace)) { |
166 | return; |
167 | } |
168 | |
169 | // Either the exception handler was not set or it could not handle the error, |
170 | // just log the exception. |
171 | FML_LOG(ERROR) << "Unhandled Exception: " << error << std::endl |
172 | << stack_trace; |
173 | } |
174 | |
175 | } // namespace flutter |
176 | |