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 "service_isolate.h"
6
7 #include "runtime/dart/utils/inlines.h"
8 #include "third_party/dart/runtime/include/bin/dart_io_api.h"
9 #include "third_party/tonic/converter/dart_converter.h"
10 #include "third_party/tonic/dart_library_natives.h"
11 #include "third_party/tonic/dart_microtask_queue.h"
12 #include "third_party/tonic/dart_state.h"
13 #include "third_party/tonic/typed_data/typed_list.h"
14
15 #include "builtin_libraries.h"
16 #include "dart_component_controller.h"
17 #include "logging.h"
18
19 namespace dart_runner {
20 namespace {
21
22 MappedResource mapped_isolate_snapshot_data;
23 MappedResource mapped_isolate_snapshot_instructions;
24 MappedResource mapped_shared_snapshot_data;
25 MappedResource mapped_shared_snapshot_instructions;
26 tonic::DartLibraryNatives* service_natives = nullptr;
27
GetNativeFunction(Dart_Handle name,int argument_count,bool * auto_setup_scope)28 Dart_NativeFunction GetNativeFunction(Dart_Handle name,
29 int argument_count,
30 bool* auto_setup_scope) {
31 dart_utils::Check(service_natives, LOG_TAG);
32 return service_natives->GetNativeFunction(name, argument_count,
33 auto_setup_scope);
34 }
35
GetSymbol(Dart_NativeFunction native_function)36 const uint8_t* GetSymbol(Dart_NativeFunction native_function) {
37 dart_utils::Check(service_natives, LOG_TAG);
38 return service_natives->GetSymbol(native_function);
39 }
40
41 #define SHUTDOWN_ON_ERROR(handle) \
42 if (Dart_IsError(handle)) { \
43 *error = strdup(Dart_GetError(handle)); \
44 FX_LOG(ERROR, LOG_TAG, *error); \
45 Dart_ExitScope(); \
46 Dart_ShutdownIsolate(); \
47 return nullptr; \
48 }
49
NotifyServerState(Dart_NativeArguments args)50 void NotifyServerState(Dart_NativeArguments args) {
51 // NOP.
52 }
53
Shutdown(Dart_NativeArguments args)54 void Shutdown(Dart_NativeArguments args) {
55 // NOP.
56 }
57
EmbedderInformationCallback(Dart_EmbedderInformation * info)58 void EmbedderInformationCallback(Dart_EmbedderInformation* info) {
59 info->version = DART_EMBEDDER_INFORMATION_CURRENT_VERSION;
60 info->name = "dart_runner";
61 info->current_rss = -1;
62 info->max_rss = -1;
63
64 zx_info_task_stats_t task_stats;
65 zx_handle_t process = zx_process_self();
66 zx_status_t status = zx_object_get_info(
67 process, ZX_INFO_TASK_STATS, &task_stats, sizeof(task_stats), NULL, NULL);
68 if (status == ZX_OK) {
69 info->current_rss =
70 task_stats.mem_private_bytes + task_stats.mem_shared_bytes;
71 }
72 }
73
74 } // namespace
75
CreateServiceIsolate(const char * uri,Dart_IsolateFlags * flags,char ** error)76 Dart_Isolate CreateServiceIsolate(const char* uri,
77 Dart_IsolateFlags* flags,
78 char** error) {
79 Dart_SetEmbedderInformationCallback(EmbedderInformationCallback);
80
81 #if defined(AOT_RUNTIME)
82 // The VM service was compiled as a separate app.
83 const char* snapshot_data_path =
84 "pkg/data/vmservice_isolate_snapshot_data.bin";
85 const char* snapshot_instructions_path =
86 "pkg/data/vmservice_isolate_snapshot_instructions.bin";
87 #else
88 // The VM service is embedded in the core snapshot.
89 const char* snapshot_data_path = "pkg/data/isolate_core_snapshot_data.bin";
90 const char* snapshot_instructions_path =
91 "pkg/data/isolate_core_snapshot_instructions.bin";
92 #endif
93
94 if (!MappedResource::LoadFromNamespace(nullptr, snapshot_data_path,
95 mapped_isolate_snapshot_data)) {
96 *error = strdup("Failed to load snapshot for service isolate");
97 FX_LOG(ERROR, LOG_TAG, *error);
98 return nullptr;
99 }
100 if (!MappedResource::LoadFromNamespace(nullptr, snapshot_instructions_path,
101 mapped_isolate_snapshot_instructions,
102 true /* executable */)) {
103 *error = strdup("Failed to load snapshot for service isolate");
104 FX_LOG(ERROR, LOG_TAG, *error);
105 return nullptr;
106 }
107
108 #if defined(AOT_RUNTIME)
109 if (!MappedResource::LoadFromNamespace(
110 nullptr, "pkg/data/vmservice_shared_snapshot_data.bin",
111 mapped_shared_snapshot_data)) {
112 *error = strdup("Failed to load snapshot for service isolate");
113 FX_LOG(ERROR, LOG_TAG, *error);
114 return nullptr;
115 }
116 if (!MappedResource::LoadFromNamespace(
117 nullptr, "pkg/data/vmservice_shared_snapshot_instructions.bin",
118 mapped_shared_snapshot_instructions, true /* executable */)) {
119 *error = strdup("Failed to load snapshot for service isolate");
120 FX_LOG(ERROR, LOG_TAG, *error);
121 return nullptr;
122 }
123 #endif
124
125 auto state = new std::shared_ptr<tonic::DartState>(new tonic::DartState());
126 Dart_Isolate isolate = Dart_CreateIsolateGroup(
127 uri, DART_VM_SERVICE_ISOLATE_NAME, mapped_isolate_snapshot_data.address(),
128 mapped_isolate_snapshot_instructions.address(),
129 mapped_shared_snapshot_data.address(),
130 mapped_shared_snapshot_instructions.address(), nullptr /* flags */,
131 state /* isolate_group_data */, state /* isolate_data */, error);
132 if (!isolate) {
133 FX_LOGF(ERROR, LOG_TAG, "Dart_CreateIsolateGroup failed: %s", *error);
134 return nullptr;
135 }
136
137 state->get()->SetIsolate(isolate);
138
139 // Setup native entries.
140 service_natives = new tonic::DartLibraryNatives();
141 service_natives->Register({
142 {"VMServiceIO_NotifyServerState", NotifyServerState, 1, true},
143 {"VMServiceIO_Shutdown", Shutdown, 0, true},
144 });
145
146 Dart_EnterScope();
147
148 Dart_Handle library =
149 Dart_LookupLibrary(Dart_NewStringFromCString("dart:vmservice_io"));
150 SHUTDOWN_ON_ERROR(library);
151 Dart_Handle result = Dart_SetRootLibrary(library);
152 SHUTDOWN_ON_ERROR(result);
153 result = Dart_SetNativeResolver(library, GetNativeFunction, GetSymbol);
154 SHUTDOWN_ON_ERROR(result);
155
156 // _ip = '127.0.0.1'
157 result = Dart_SetField(library, Dart_NewStringFromCString("_ip"),
158 Dart_NewStringFromCString("127.0.0.1"));
159 SHUTDOWN_ON_ERROR(result);
160
161 // _port = 0
162 result = Dart_SetField(library, Dart_NewStringFromCString("_port"),
163 Dart_NewInteger(0));
164 SHUTDOWN_ON_ERROR(result);
165
166 // _autoStart = true
167 result = Dart_SetField(library, Dart_NewStringFromCString("_autoStart"),
168 Dart_NewBoolean(true));
169 SHUTDOWN_ON_ERROR(result);
170
171 // _originCheckDisabled = false
172 result =
173 Dart_SetField(library, Dart_NewStringFromCString("_originCheckDisabled"),
174 Dart_NewBoolean(false));
175 SHUTDOWN_ON_ERROR(result);
176
177 // _authCodesDisabled = false
178 result =
179 Dart_SetField(library, Dart_NewStringFromCString("_authCodesDisabled"),
180 Dart_NewBoolean(false));
181 SHUTDOWN_ON_ERROR(result);
182
183 InitBuiltinLibrariesForIsolate(std::string(uri), nullptr, fileno(stdout),
184 fileno(stderr), nullptr, zx::channel(), true);
185
186 // Make runnable.
187 Dart_ExitScope();
188 Dart_ExitIsolate();
189 *error = Dart_IsolateMakeRunnable(isolate);
190 if (*error != nullptr) {
191 FX_LOG(ERROR, LOG_TAG, *error);
192 Dart_EnterIsolate(isolate);
193 Dart_ShutdownIsolate();
194 return nullptr;
195 }
196 return isolate;
197 } // namespace dart_runner
198
GetVMServiceAssetsArchiveCallback()199 Dart_Handle GetVMServiceAssetsArchiveCallback() {
200 MappedResource observatory_tar;
201 if (!MappedResource::LoadFromNamespace(nullptr, "pkg/data/observatory.tar",
202 observatory_tar)) {
203 FX_LOG(ERROR, LOG_TAG, "Failed to load Observatory assets");
204 return nullptr;
205 }
206 // TODO(rmacnak): Should we avoid copying the tar? Or does the service library
207 // not hold onto it anyway?
208 return tonic::DartConverter<tonic::Uint8List>::ToDart(
209 reinterpret_cast<const uint8_t*>(observatory_tar.address()),
210 observatory_tar.size());
211 }
212
213 } // namespace dart_runner
214