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