forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dart_service_isolate.cc
202 lines (166 loc) · 6.01 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
// Copyright 2015 The Chromium 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 <string.h>
#include <algorithm>
#include "flutter/fml/logging.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 = strdup(Dart_GetError(handle)); \
Dart_ExitScope(); \
Dart_ShutdownIsolate(); \
return false; \
}
namespace blink {
namespace {
static Dart_LibraryTagHandler g_embedder_tag_handler;
static tonic::DartLibraryNatives* g_natives;
static std::string 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_;
FML_GUARDED_BY(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;
}
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::lock_guard<std::mutex> lock(callbacks_mutex_);
for (auto& callback : callbacks_) {
callbacks_to_fire.push_back(*callback.get());
}
}
for (auto callback_to_fire : callbacks_to_fire) {
callback_to_fire(uri);
}
}
std::string DartServiceIsolate::GetObservatoryUri() {
return observatory_uri_;
}
DartServiceIsolate::CallbackHandle DartServiceIsolate::AddServerStatusCallback(
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::lock_guard<std::mutex> lock(callbacks_mutex_);
callbacks_.insert(std::move(callback_pointer));
}
if (!observatory_uri_.empty()) {
callback(observatory_uri_);
}
return handle;
}
bool DartServiceIsolate::RemoveServerStatusCallback(
CallbackHandle callback_handle) {
std::lock_guard<std::mutex> 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,
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);
return true;
}
} // namespace blink