forked from flutter/engine
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dart_service_isolate.cc
208 lines (173 loc) · 6.42 KB
/
dart_service_isolate.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// 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/dart_service_isolate.h"
#include <algorithm>
#include <cstring>
#include "flutter/fml/logging.h"
#include "flutter/fml/posix_wrappers.h"
#include "flutter/runtime/embedder_resources.h"
#include "third_party/dart/runtime/include/dart_api.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_library_natives.h"
#include "third_party/tonic/logging/dart_error.h"
#define RETURN_ERROR_HANDLE(handle) \
if (Dart_IsError(handle)) { \
return handle; \
}
#define SHUTDOWN_ON_ERROR(handle) \
if (Dart_IsError(handle)) { \
*error = fml::strdup(Dart_GetError(handle)); \
Dart_ExitScope(); \
Dart_ShutdownIsolate(); \
return false; \
}
namespace flutter {
namespace {
static Dart_LibraryTagHandler g_embedder_tag_handler;
static tonic::DartLibraryNatives* g_natives;
static std::string g_observatory_uri;
Dart_NativeFunction GetNativeFunction(Dart_Handle name,
int argument_count,
bool* auto_setup_scope) {
FML_CHECK(g_natives);
return g_natives->GetNativeFunction(name, argument_count, auto_setup_scope);
}
const uint8_t* GetSymbol(Dart_NativeFunction native_function) {
FML_CHECK(g_natives);
return g_natives->GetSymbol(native_function);
}
} // namespace
std::mutex DartServiceIsolate::callbacks_mutex_;
std::set<std::unique_ptr<DartServiceIsolate::ObservatoryServerStateCallback>>
DartServiceIsolate::callbacks_;
void DartServiceIsolate::NotifyServerState(Dart_NativeArguments args) {
Dart_Handle exception = nullptr;
std::string uri =
tonic::DartConverter<std::string>::FromArguments(args, 0, exception);
if (exception) {
return;
}
g_observatory_uri = uri;
// Collect callbacks to fire in a separate collection and invoke them outside
// the lock.
std::vector<DartServiceIsolate::ObservatoryServerStateCallback>
callbacks_to_fire;
{
std::scoped_lock lock(callbacks_mutex_);
for (auto& callback : callbacks_) {
callbacks_to_fire.push_back(*callback.get());
}
}
for (const auto& callback_to_fire : callbacks_to_fire) {
callback_to_fire(uri);
}
}
DartServiceIsolate::CallbackHandle DartServiceIsolate::AddServerStatusCallback(
const DartServiceIsolate::ObservatoryServerStateCallback& callback) {
if (!callback) {
return 0;
}
auto callback_pointer =
std::make_unique<DartServiceIsolate::ObservatoryServerStateCallback>(
callback);
auto handle = reinterpret_cast<CallbackHandle>(callback_pointer.get());
{
std::scoped_lock lock(callbacks_mutex_);
callbacks_.insert(std::move(callback_pointer));
}
if (!g_observatory_uri.empty()) {
callback(g_observatory_uri);
}
return handle;
}
bool DartServiceIsolate::RemoveServerStatusCallback(
CallbackHandle callback_handle) {
std::scoped_lock lock(callbacks_mutex_);
auto found = std::find_if(
callbacks_.begin(), callbacks_.end(),
[callback_handle](const auto& item) {
return reinterpret_cast<CallbackHandle>(item.get()) == callback_handle;
});
if (found == callbacks_.end()) {
return false;
}
callbacks_.erase(found);
return true;
}
void DartServiceIsolate::Shutdown(Dart_NativeArguments args) {
// NO-OP.
}
bool DartServiceIsolate::Startup(std::string server_ip,
intptr_t server_port,
Dart_LibraryTagHandler embedder_tag_handler,
bool disable_origin_check,
bool disable_service_auth_codes,
bool enable_service_port_fallback,
char** error) {
Dart_Isolate isolate = Dart_CurrentIsolate();
FML_CHECK(isolate);
// Remember the embedder's library tag handler.
g_embedder_tag_handler = embedder_tag_handler;
FML_CHECK(g_embedder_tag_handler);
// Setup native entries.
if (!g_natives) {
g_natives = new tonic::DartLibraryNatives();
g_natives->Register({
{"VMServiceIO_NotifyServerState", NotifyServerState, 1, true},
{"VMServiceIO_Shutdown", Shutdown, 0, true},
});
}
Dart_Handle uri = Dart_NewStringFromCString("dart:vmservice_io");
Dart_Handle library = Dart_LookupLibrary(uri);
SHUTDOWN_ON_ERROR(library);
Dart_Handle result = Dart_SetRootLibrary(library);
SHUTDOWN_ON_ERROR(result);
result = Dart_SetNativeResolver(library, GetNativeFunction, GetSymbol);
SHUTDOWN_ON_ERROR(result);
// Make runnable.
Dart_ExitScope();
Dart_ExitIsolate();
*error = Dart_IsolateMakeRunnable(isolate);
if (*error) {
Dart_EnterIsolate(isolate);
Dart_ShutdownIsolate();
return false;
}
Dart_EnterIsolate(isolate);
Dart_EnterScope();
library = Dart_RootLibrary();
SHUTDOWN_ON_ERROR(library);
// Set the HTTP server's ip.
result = Dart_SetField(library, Dart_NewStringFromCString("_ip"),
Dart_NewStringFromCString(server_ip.c_str()));
SHUTDOWN_ON_ERROR(result);
// If we have a port specified, start the server immediately.
bool auto_start = server_port >= 0;
if (server_port < 0) {
// Adjust server_port to port 0 which will result in the first available
// port when the HTTP server is started.
server_port = 0;
}
// Set the HTTP's servers port.
result = Dart_SetField(library, Dart_NewStringFromCString("_port"),
Dart_NewInteger(server_port));
SHUTDOWN_ON_ERROR(result);
result = Dart_SetField(library, Dart_NewStringFromCString("_autoStart"),
Dart_NewBoolean(auto_start));
SHUTDOWN_ON_ERROR(result);
result =
Dart_SetField(library, Dart_NewStringFromCString("_originCheckDisabled"),
Dart_NewBoolean(disable_origin_check));
SHUTDOWN_ON_ERROR(result);
result =
Dart_SetField(library, Dart_NewStringFromCString("_authCodesDisabled"),
Dart_NewBoolean(disable_service_auth_codes));
SHUTDOWN_ON_ERROR(result);
result = Dart_SetField(
library, Dart_NewStringFromCString("_enableServicePortFallback"),
Dart_NewBoolean(enable_service_port_fallback));
SHUTDOWN_ON_ERROR(result);
return true;
}
} // namespace flutter