OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/dart/embedder/vmservice.h" | 5 #include "dart_service_isolate.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "dart/runtime/include/dart_api.h" | 8 #include "dart/runtime/include/dart_api.h" |
9 #include "mojo/dart/embedder/builtin.h" | 9 #include "sky/engine/tonic/dart_error.h" |
10 #include "mojo/dart/embedder/common.h" | 10 #include "sky/engine/tonic/dart_string.h" |
11 #include "mojo/dart/embedder/dart_controller.h" | |
12 | |
13 namespace mojo { | |
14 namespace dart { | |
15 | 11 |
16 #define RETURN_ERROR_HANDLE(handle) \ | 12 #define RETURN_ERROR_HANDLE(handle) \ |
17 if (Dart_IsError(handle)) { \ | 13 if (Dart_IsError(handle)) { \ |
18 return handle; \ | 14 return handle; \ |
19 } | 15 } |
20 | 16 |
21 #define SHUTDOWN_ON_ERROR(handle) \ | 17 #define SHUTDOWN_ON_ERROR(handle) \ |
22 if (Dart_IsError(handle)) { \ | 18 if (Dart_IsError(handle)) { \ |
23 error_msg_ = strdup(Dart_GetError(handle)); \ | 19 *error = strdup(Dart_GetError(handle)); \ |
24 Dart_ExitScope(); \ | 20 Dart_ExitScope(); \ |
25 Dart_ShutdownIsolate(); \ | 21 Dart_ShutdownIsolate(); \ |
26 return false; \ | 22 return false; \ |
27 } | 23 } |
28 | 24 |
29 #define kLibrarySourceNamePrefix "/vmservice" | 25 #define kLibrarySourceNamePrefix "/dart_service_isolate" |
30 static const char* kVMServiceIOLibraryScriptResourceName = "main.dart"; | 26 static const char* kServiceIsolateScript = "main.dart"; |
31 | 27 |
32 struct ResourcesEntry { | 28 struct ResourcesEntry { |
33 const char* path_; | 29 const char* path_; |
34 const char* resource_; | 30 const char* resource_; |
35 int length_; | 31 int length_; |
36 }; | 32 }; |
37 | 33 |
38 extern ResourcesEntry __dart_embedder_service_isolate_resources_[]; | 34 namespace mojo { |
| 35 namespace dart { |
| 36 extern ResourcesEntry __sky_embedder_service_isolate_resources_[]; |
| 37 } |
| 38 } |
| 39 |
| 40 namespace blink { |
39 | 41 |
40 class Resources { | 42 class Resources { |
41 public: | 43 public: |
42 static const int kNoSuchInstance = -1; | 44 static const int kNoSuchInstance = -1; |
43 static int ResourceLookup(const char* path, const char** resource) { | 45 static int ResourceLookup(const char* path, const char** resource) { |
44 ResourcesEntry* table = ResourcesTable(); | 46 ResourcesEntry* table = ResourcesTable(); |
45 for (int i = 0; table[i].path_ != NULL; i++) { | 47 for (int i = 0; table[i].path_ != NULL; i++) { |
46 const ResourcesEntry& entry = table[i]; | 48 const ResourcesEntry& entry = table[i]; |
47 if (strcmp(path, entry.path_) == 0) { | 49 if (strcmp(path, entry.path_) == 0) { |
48 *resource = entry.resource_; | 50 *resource = entry.resource_; |
(...skipping 19 matching lines...) Expand all Loading... |
68 DCHECK(idx >= 0); | 70 DCHECK(idx >= 0); |
69 ResourcesEntry* table = ResourcesTable(); | 71 ResourcesEntry* table = ResourcesTable(); |
70 for (int i = 0; table[i].path_ != NULL; i++) { | 72 for (int i = 0; table[i].path_ != NULL; i++) { |
71 if (idx == i) { | 73 if (idx == i) { |
72 return &table[i]; | 74 return &table[i]; |
73 } | 75 } |
74 } | 76 } |
75 return NULL; | 77 return NULL; |
76 } | 78 } |
77 static ResourcesEntry* ResourcesTable() { | 79 static ResourcesEntry* ResourcesTable() { |
78 return &__dart_embedder_service_isolate_resources_[0]; | 80 return &mojo::dart::__sky_embedder_service_isolate_resources_[0]; |
79 } | 81 } |
80 }; | 82 }; |
81 | 83 |
82 void ServiceIsolate_TriggerResourceLoad(Dart_NativeArguments args) { | 84 void DartServiceIsolate::TriggerResourceLoad(Dart_NativeArguments args) { |
83 Dart_Handle library = Dart_RootLibrary(); | 85 Dart_Handle library = Dart_RootLibrary(); |
84 DCHECK(!Dart_IsError(library)); | 86 DCHECK(!Dart_IsError(library)); |
85 Dart_Handle result = VmService::LoadResources(library); | 87 Dart_Handle result = LoadResources(library); |
86 DCHECK(!Dart_IsError(result)); | 88 DCHECK(!Dart_IsError(result)); |
87 } | 89 } |
88 | 90 |
89 void ServiceIsolate_NotifyServerState(Dart_NativeArguments args) { | 91 void DartServiceIsolate::NotifyServerState(Dart_NativeArguments args) { |
90 Dart_EnterScope(); | 92 // NO-OP. |
91 const char* ip_chars; | |
92 Dart_Handle ip_arg = Dart_GetNativeArgument(args, 0); | |
93 if (Dart_IsError(ip_arg)) { | |
94 VmService::SetServerIPAndPort("", 0); | |
95 Dart_ExitScope(); | |
96 return; | |
97 } | |
98 Dart_Handle result = Dart_StringToCString(ip_arg, &ip_chars); | |
99 if (Dart_IsError(result)) { | |
100 VmService::SetServerIPAndPort("", 0); | |
101 Dart_ExitScope(); | |
102 return; | |
103 } | |
104 Dart_Handle port_arg = Dart_GetNativeArgument(args, 1); | |
105 if (Dart_IsError(port_arg)) { | |
106 VmService::SetServerIPAndPort("", 0); | |
107 Dart_ExitScope(); | |
108 return; | |
109 } | |
110 int64_t port = DartEmbedder::GetInt64ValueCheckRange(port_arg, 0, 65535); | |
111 VmService::SetServerIPAndPort(ip_chars, port); | |
112 Dart_ExitScope(); | |
113 } | 93 } |
114 | 94 |
115 void ServiceIsolate_Shutdown(Dart_NativeArguments args) { | 95 void DartServiceIsolate::Shutdown(Dart_NativeArguments args) { |
116 Dart_EnterScope(); | 96 // NO-OP. |
117 DartController::ShutdownDartMojoIo(); | |
118 Dart_ExitScope(); | |
119 } | 97 } |
120 | 98 |
121 struct VmServiceIONativeEntry { | 99 DartBuiltin::Natives DartServiceIsolate::native_entries_[] = { |
122 const char* name; | 100 {"ServiceIsolate_TriggerResourceLoad", TriggerResourceLoad, 0 }, |
123 int num_arguments; | 101 {"ServiceIsolate_NotifyServerState", NotifyServerState, 2 }, |
124 Dart_NativeFunction function; | 102 {"ServiceIsolate_Shutdown", Shutdown, 0 }, |
125 }; | 103 }; |
126 | 104 |
127 | 105 Dart_NativeFunction DartServiceIsolate::NativeResolver(Dart_Handle name, |
128 static VmServiceIONativeEntry _VmServiceIONativeEntries[] = { | 106 int argument_count, |
129 {"ServiceIsolate_TriggerResourceLoad", 0, ServiceIsolate_TriggerResourceLoad}, | 107 bool* auto_setup_scope) { |
130 {"ServiceIsolate_NotifyServerState", 2, ServiceIsolate_NotifyServerState}, | 108 CHECK(builtins_); |
131 {"ServiceIsolate_Shutdown", 0, ServiceIsolate_Shutdown }, | 109 return builtins_->Resolver(name, argument_count, auto_setup_scope); |
132 }; | |
133 | |
134 | |
135 static Dart_NativeFunction VmServiceIONativeResolver(Dart_Handle name, | |
136 int num_arguments, | |
137 bool* auto_setup_scope) { | |
138 const char* function_name = NULL; | |
139 Dart_Handle result = Dart_StringToCString(name, &function_name); | |
140 DCHECK(!Dart_IsError(result)); | |
141 DCHECK(function_name != NULL); | |
142 *auto_setup_scope = true; | |
143 intptr_t n = | |
144 sizeof(_VmServiceIONativeEntries) / sizeof(_VmServiceIONativeEntries[0]); | |
145 for (intptr_t i = 0; i < n; i++) { | |
146 VmServiceIONativeEntry entry = _VmServiceIONativeEntries[i]; | |
147 if ((strcmp(function_name, entry.name) == 0) && | |
148 (num_arguments == entry.num_arguments)) { | |
149 return entry.function; | |
150 } | |
151 } | |
152 return NULL; | |
153 } | 110 } |
154 | 111 |
| 112 const uint8_t* DartServiceIsolate::NativeSymbolizer( |
| 113 Dart_NativeFunction native_function) { |
| 114 CHECK(builtins_); |
| 115 return builtins_->Symbolizer(native_function); |
| 116 } |
155 | 117 |
156 const char* VmService::error_msg_ = NULL; | 118 Dart_LibraryTagHandler DartServiceIsolate::embedder_tag_handler_ = nullptr; |
157 char VmService::server_ip_[kServerIpStringBufferSize]; | 119 DartBuiltin* DartServiceIsolate::builtins_ = nullptr; |
158 intptr_t VmService::server_port_ = 0; | |
159 | 120 |
160 bool VmService::Setup(const char* server_ip, intptr_t server_port) { | 121 bool DartServiceIsolate::Startup(std::string server_ip, |
| 122 intptr_t server_port, |
| 123 Dart_LibraryTagHandler embedder_tag_handler, |
| 124 char** error) { |
161 Dart_Isolate isolate = Dart_CurrentIsolate(); | 125 Dart_Isolate isolate = Dart_CurrentIsolate(); |
162 DCHECK(isolate != NULL); | 126 CHECK(isolate); |
163 SetServerIPAndPort("", 0); | 127 |
| 128 // Remember the embedder's library tag handler. |
| 129 embedder_tag_handler_ = embedder_tag_handler; |
| 130 CHECK(embedder_tag_handler_); |
| 131 |
| 132 // Setup native entries. |
| 133 builtins_ = |
| 134 new DartBuiltin(&DartServiceIsolate::native_entries_[0], |
| 135 sizeof(native_entries_) / sizeof(native_entries_[0])); |
164 | 136 |
165 Dart_Handle result; | 137 Dart_Handle result; |
166 | 138 |
| 139 // Use our own library tag handler when loading service isolate sources. |
| 140 Dart_SetLibraryTagHandler(DartServiceIsolate::LibraryTagHandler); |
167 // Load main script. | 141 // Load main script. |
168 Dart_SetLibraryTagHandler(VmService::LibraryTagHandler); | 142 Dart_Handle library = LoadScript(kServiceIsolateScript); |
169 Dart_Handle library = LoadScript(kVMServiceIOLibraryScriptResourceName); | |
170 DCHECK(library != Dart_Null()); | 143 DCHECK(library != Dart_Null()); |
171 SHUTDOWN_ON_ERROR(library); | 144 SHUTDOWN_ON_ERROR(library); |
172 result = Dart_SetNativeResolver(library, VmServiceIONativeResolver, NULL); | 145 // Setup native entry resolution. |
| 146 result = Dart_SetNativeResolver(library, NativeResolver, NativeSymbolizer); |
| 147 |
173 SHUTDOWN_ON_ERROR(result); | 148 SHUTDOWN_ON_ERROR(result); |
| 149 // Finalize loading. |
174 result = Dart_FinalizeLoading(false); | 150 result = Dart_FinalizeLoading(false); |
175 SHUTDOWN_ON_ERROR(result); | 151 SHUTDOWN_ON_ERROR(result); |
176 | 152 |
177 // Make runnable. | 153 // Make runnable. |
178 Dart_ExitScope(); | 154 Dart_ExitScope(); |
179 Dart_ExitIsolate(); | 155 Dart_ExitIsolate(); |
180 bool retval = Dart_IsolateMakeRunnable(isolate); | 156 bool retval = Dart_IsolateMakeRunnable(isolate); |
181 if (!retval) { | 157 if (!retval) { |
182 Dart_EnterIsolate(isolate); | 158 Dart_EnterIsolate(isolate); |
183 Dart_ShutdownIsolate(); | 159 Dart_ShutdownIsolate(); |
184 error_msg_ = "Invalid isolate state - Unable to make it runnable."; | 160 *error = strdup("Invalid isolate state - Unable to make it runnable."); |
185 return false; | 161 return false; |
186 } | 162 } |
187 Dart_EnterIsolate(isolate); | 163 Dart_EnterIsolate(isolate); |
188 Dart_EnterScope(); | 164 Dart_EnterScope(); |
189 | 165 |
190 library = Dart_RootLibrary(); | 166 library = Dart_RootLibrary(); |
191 SHUTDOWN_ON_ERROR(library); | 167 SHUTDOWN_ON_ERROR(library); |
192 | 168 |
193 // Set HTTP server state. | 169 // Set the HTTP server's ip. |
194 DartEmbedder::SetStringField(library, "_ip", server_ip); | 170 result = Dart_SetField(library, |
| 171 Dart_NewStringFromCString("_ip"), |
| 172 Dart_NewStringFromCString(server_ip.c_str())); |
| 173 SHUTDOWN_ON_ERROR(result); |
195 // If we have a port specified, start the server immediately. | 174 // If we have a port specified, start the server immediately. |
196 bool auto_start = server_port >= 0; | 175 bool auto_start = server_port >= 0; |
197 if (server_port < 0) { | 176 if (server_port < 0) { |
198 // Adjust server_port to port 0 which will result in the first available | 177 // Adjust server_port to port 0 which will result in the first available |
199 // port when the HTTP server is started. | 178 // port when the HTTP server is started. |
200 server_port = 0; | 179 server_port = 0; |
201 } | 180 } |
202 DartEmbedder::SetIntegerField(library, "_port", server_port); | 181 // Set the HTTP's servers port. |
203 result = Dart_SetField(library, | 182 result = Dart_SetField(library, |
204 DartEmbedder::NewCString("_autoStart"), | 183 Dart_NewStringFromCString("_port"), |
| 184 Dart_NewInteger(server_port)); |
| 185 SHUTDOWN_ON_ERROR(result); |
| 186 result = Dart_SetField(library, |
| 187 Dart_NewStringFromCString("_autoStart"), |
205 Dart_NewBoolean(auto_start)); | 188 Dart_NewBoolean(auto_start)); |
206 SHUTDOWN_ON_ERROR(result); | 189 SHUTDOWN_ON_ERROR(result); |
207 return true; | 190 return true; |
208 } | 191 } |
209 | 192 |
210 | 193 Dart_Handle DartServiceIsolate::GetSource(const char* name) { |
211 const char* VmService::GetErrorMessage() { | |
212 return error_msg_ == NULL ? "No error." : error_msg_; | |
213 } | |
214 | |
215 | |
216 void VmService::SetServerIPAndPort(const char* ip, intptr_t port) { | |
217 if (ip == NULL) { | |
218 ip = ""; | |
219 } | |
220 strncpy(server_ip_, ip, kServerIpStringBufferSize); | |
221 server_ip_[kServerIpStringBufferSize - 1] = '\0'; | |
222 server_port_ = port; | |
223 } | |
224 | |
225 | |
226 Dart_Handle VmService::GetSource(const char* name) { | |
227 const intptr_t kBufferSize = 512; | 194 const intptr_t kBufferSize = 512; |
228 char buffer[kBufferSize]; | 195 char buffer[kBufferSize]; |
229 snprintf(&buffer[0], kBufferSize-1, "%s/%s", kLibrarySourceNamePrefix, name); | 196 snprintf(&buffer[0], kBufferSize-1, "%s/%s", kLibrarySourceNamePrefix, name); |
230 const char* vmservice_source = NULL; | 197 const char* vmservice_source = NULL; |
231 int r = Resources::ResourceLookup(buffer, &vmservice_source); | 198 int r = Resources::ResourceLookup(buffer, &vmservice_source); |
232 DCHECK(r != Resources::kNoSuchInstance); | 199 DCHECK(r != Resources::kNoSuchInstance); |
233 return Dart_NewStringFromCString(vmservice_source); | 200 return Dart_NewStringFromCString(vmservice_source); |
234 } | 201 } |
235 | 202 |
236 | 203 Dart_Handle DartServiceIsolate::LoadScript(const char* name) { |
237 Dart_Handle VmService::LoadScript(const char* name) { | 204 Dart_Handle url = Dart_NewStringFromCString("dart:vmservice_sky"); |
238 Dart_Handle url = Dart_NewStringFromCString("dart:vmservice_io"); | |
239 Dart_Handle source = GetSource(name); | 205 Dart_Handle source = GetSource(name); |
240 return Dart_LoadScript(url, source, 0, 0); | 206 return Dart_LoadScript(url, source, 0, 0); |
241 } | 207 } |
242 | 208 |
243 | 209 Dart_Handle DartServiceIsolate::LoadSource(Dart_Handle library, const char* name
) { |
244 Dart_Handle VmService::LoadSource(Dart_Handle library, const char* name) { | |
245 Dart_Handle url = Dart_NewStringFromCString(name); | 210 Dart_Handle url = Dart_NewStringFromCString(name); |
246 Dart_Handle source = GetSource(name); | 211 Dart_Handle source = GetSource(name); |
247 return Dart_LoadSource(library, url, source, 0, 0); | 212 return Dart_LoadSource(library, url, source, 0, 0); |
248 } | 213 } |
249 | 214 |
250 | 215 Dart_Handle DartServiceIsolate::LoadResource(Dart_Handle library, |
251 Dart_Handle VmService::LoadResource(Dart_Handle library, | |
252 const char* resource_name) { | 216 const char* resource_name) { |
253 // Prepare for invoke call. | 217 // Prepare for invoke call. |
254 Dart_Handle name = Dart_NewStringFromCString(resource_name); | 218 Dart_Handle name = Dart_NewStringFromCString(resource_name); |
255 RETURN_ERROR_HANDLE(name); | 219 RETURN_ERROR_HANDLE(name); |
256 const char* data_buffer = NULL; | 220 const char* data_buffer = NULL; |
257 int data_buffer_length = Resources::ResourceLookup(resource_name, | 221 int data_buffer_length = Resources::ResourceLookup(resource_name, |
258 &data_buffer); | 222 &data_buffer); |
259 DCHECK(data_buffer_length != Resources::kNoSuchInstance); | 223 DCHECK(data_buffer_length != Resources::kNoSuchInstance); |
260 Dart_Handle data_list = Dart_NewTypedData(Dart_TypedData_kUint8, | 224 Dart_Handle data_list = Dart_NewTypedData(Dart_TypedData_kUint8, |
261 data_buffer_length); | 225 data_buffer_length); |
(...skipping 13 matching lines...) Expand all Loading... |
275 RETURN_ERROR_HANDLE(result); | 239 RETURN_ERROR_HANDLE(result); |
276 | 240 |
277 // Make invoke call. | 241 // Make invoke call. |
278 const intptr_t kNumArgs = 2; | 242 const intptr_t kNumArgs = 2; |
279 Dart_Handle args[kNumArgs] = { name, data_list }; | 243 Dart_Handle args[kNumArgs] = { name, data_list }; |
280 result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"), | 244 result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"), |
281 kNumArgs, args); | 245 kNumArgs, args); |
282 return result; | 246 return result; |
283 } | 247 } |
284 | 248 |
285 | 249 Dart_Handle DartServiceIsolate::LoadResources(Dart_Handle library) { |
286 Dart_Handle VmService::LoadResources(Dart_Handle library) { | |
287 Dart_Handle result = Dart_Null(); | 250 Dart_Handle result = Dart_Null(); |
288 intptr_t prefixLen = strlen(kLibrarySourceNamePrefix); | 251 intptr_t prefixLen = strlen(kLibrarySourceNamePrefix); |
289 for (intptr_t i = 0; Resources::Path(i) != NULL; i++) { | 252 for (intptr_t i = 0; Resources::Path(i) != NULL; i++) { |
290 const char* path = Resources::Path(i); | 253 const char* path = Resources::Path(i); |
291 // If it doesn't begin with kLibrarySourceNamePrefix it is a frontend | 254 // If it doesn't begin with kLibrarySourceNamePrefix it is a frontend |
292 // resource. | 255 // resource. |
293 if (strncmp(path, kLibrarySourceNamePrefix, prefixLen) != 0) { | 256 if (strncmp(path, kLibrarySourceNamePrefix, prefixLen) != 0) { |
294 result = LoadResource(library, path); | 257 result = LoadResource(library, path); |
295 if (Dart_IsError(result)) { | 258 if (Dart_IsError(result)) { |
296 break; | 259 break; |
297 } | 260 } |
298 } | 261 } |
299 } | 262 } |
300 return result; | 263 return result; |
301 } | 264 } |
302 | 265 |
303 | 266 Dart_Handle DartServiceIsolate::LibraryTagHandler(Dart_LibraryTag tag, |
304 Dart_Handle VmService::LibraryTagHandler(Dart_LibraryTag tag, | |
305 Dart_Handle library, | 267 Dart_Handle library, |
306 Dart_Handle url) { | 268 Dart_Handle url) { |
307 if (!Dart_IsLibrary(library)) { | 269 if (!Dart_IsLibrary(library)) { |
308 return Dart_NewApiError("not a library"); | 270 return Dart_NewApiError("not a library"); |
309 } | 271 } |
310 if (!Dart_IsString(url)) { | 272 if (!Dart_IsString(url)) { |
311 return Dart_NewApiError("url is not a string"); | 273 return Dart_NewApiError("url is not a string"); |
312 } | 274 } |
313 const char* url_string = NULL; | 275 const char* url_string = NULL; |
314 Dart_Handle result = Dart_StringToCString(url, &url_string); | 276 Dart_Handle result = Dart_StringToCString(url, &url_string); |
315 if (Dart_IsError(result)) { | 277 if (Dart_IsError(result)) { |
316 return result; | 278 return result; |
317 } | 279 } |
318 Dart_Handle library_url = Dart_LibraryUrl(library); | 280 Dart_Handle library_url = Dart_LibraryUrl(library); |
319 const char* library_url_string = NULL; | 281 const char* library_url_string = NULL; |
320 result = Dart_StringToCString(library_url, &library_url_string); | 282 result = Dart_StringToCString(library_url, &library_url_string); |
321 if (Dart_IsError(result)) { | 283 if (Dart_IsError(result)) { |
322 return result; | 284 return result; |
323 } | 285 } |
324 if (tag == Dart_kImportTag) { | 286 if (tag == Dart_kImportTag) { |
325 // Embedder handles all requests for external libraries. | 287 // Embedder handles all requests for external libraries. |
326 return DartController::LibraryTagHandler(tag, library, url); | 288 return embedder_tag_handler_(tag, library, url); |
327 } | 289 } |
328 DCHECK((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl)); | 290 DCHECK((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl)); |
329 if (tag == Dart_kCanonicalizeUrl) { | 291 if (tag == Dart_kCanonicalizeUrl) { |
330 // url is already canonicalized. | 292 // url is already canonicalized. |
331 return url; | 293 return url; |
332 } | 294 } |
| 295 // Get source from builtin resources. |
333 Dart_Handle source = GetSource(url_string); | 296 Dart_Handle source = GetSource(url_string); |
334 if (Dart_IsError(source)) { | 297 if (Dart_IsError(source)) { |
335 return source; | 298 return source; |
336 } | 299 } |
337 return Dart_LoadSource(library, url, source, 0, 0); | 300 return Dart_LoadSource(library, url, source, 0, 0); |
338 } | 301 } |
339 | 302 |
340 | 303 |
341 } // namespace dart | 304 } // namespace blink |
342 } // namespace mojo | |
OLD | NEW |