Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: Source/bindings/dart/DartService.cpp

Issue 104433004: Enable VM service inside Dartium Renderer processes (Closed) Base URL: svn://svn.chromium.org/multivm/branches/1650/blink
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "config.h"
6
7 #include "bindings/dart/DartService.h"
8
9 #include "DartApplicationLoader.h"
10 #include "DartController.h"
11 #include "DartDocument.h"
12 #include "DartServiceInternal.h"
13 #include "DartUtilities.h"
14 #include "DartWindow.h"
15
16
17 // These must be kept in sync with vmservice/constants.dart
18 // TODO(johnmccutchan): Put these constants in one place.
19 #define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1
20 #define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2
21
22 // The following Resources class is used in combination with a generated
23 // source file that expects underscores in names. The NOLINT tags are
24 // used to suppress the errors.
25 // TODO(johnmccutchan): Move VM service source into runtime and out of bin.
26 namespace dart {
27 namespace bin {
28 class Resources {
29 public:
30 static const int kNoSuchInstance = -1;
31
32 static int ResourceLookup(const char* path, const char** resource)
33 {
34 for (int i = 0; i < get_resource_count(); i++) {
35 resource_map_entry* entry = get_resource(i);
36 if (!strcmp(path, entry->path_)) {
37 *resource = entry->resource_;
38 ASSERT(entry->length_ > 0);
39 return entry->length_;
40 }
41 }
42 return kNoSuchInstance;
43 }
44
45 static intptr_t get_resource_count() // NOLINT.
46 {
47 return builtin_resources_count_;
48 }
49
50 static const char* get_resource_path(intptr_t i) // NOLINT.
51 {
52 return get_resource(i)->path_;
53 }
54
55 private:
56 struct resource_map_entry { // NOLINT.
57 const char* path_; // NOLINT.
58 const char* resource_; // NOLINT.
59 intptr_t length_; // NOLINT.
60 };
61
62 // These fields are generated by resources_gen.cc.
63 static resource_map_entry builtin_resources_[]; // NOLINT.
64 static const intptr_t builtin_resources_count_; // NOLINT.
65
66 static resource_map_entry* get_resource(int i) // NOLINT.
67 {
68 ASSERT(i >= 0 && i < builtin_resources_count_);
69 return &builtin_resources_[i];
70 }
71
72 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources);
73 };
74
75 }
76 }
77 namespace WebCore {
78
79 #define SHUTDOWN_ON_ERROR(handle) \
80 if (Dart_IsError(handle)) { \
81 m_errorMsg = strdup(Dart_GetError(handle)); \
82 goto error; \
83 }
84
85 static const char* kScriptUri = "vmservice:";
86 #define kLibraryResourceNamePrefix "/vmservice"
87 static const char* kVMServiceDartiumLibraryScriptResourceName =
88 kLibraryResourceNamePrefix "/vmservice_dartium.dart";
89 static const char* kVMServiceLibraryName =
90 kLibraryResourceNamePrefix "/vmservice.dart";
91
92
93 Dart_Isolate DartService::m_isolate = 0;
94 Dart_Port DartService::m_port = ILLEGAL_PORT;
95 Dart_Port DartService::m_requestPort = ILLEGAL_PORT;
96 Dart_Port DartService::m_nativePort = ILLEGAL_PORT;
97 const char* DartService::m_errorMsg = 0;
98
99
100 bool DartService::Start(Document* document)
101 {
102 if (m_isolate) {
103 // Already running.
104 return true;
105 }
106 {
107 char* error = 0;
108
109 m_isolate = DartController::createIsolate(kScriptUri, "main", document, true, &error);
110 if (!m_isolate) {
111 m_errorMsg = error;
112 return false;
Jacob 2013/12/05 19:31:31 Use Scope auto close opbjects here and elsewhere t
Cutch 2013/12/05 22:48:15 Everywhere but the startup and shutdown of the VM
113 }
114
115 Dart_EnterScope();
116 // Set up the library tag handler for this isolate.
117 Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler);
118 SHUTDOWN_ON_ERROR(result);
119
120 {
121 // Load source into service isolate.
122 Dart_Handle library =
123 LoadScript(kVMServiceDartiumLibraryScriptResourceName);
124 SHUTDOWN_ON_ERROR(library);
125 }
126 // Make the isolate runnable so that it is ready to handle messages.
127 Dart_ExitScope();
128 Dart_ExitIsolate();
129
130 bool retval = Dart_IsolateMakeRunnable(m_isolate);
131 if (!retval) {
132 Dart_EnterIsolate(m_isolate);
133 Dart_ShutdownIsolate();
134 m_errorMsg = "Invalid isolate state - Unable to make it runnable.";
135 return false;
136 }
137
138 Dart_EnterIsolate(m_isolate);
139 Dart_EnterScope();
140
141 // Invoke main.
142 Dart_Handle library = Dart_RootLibrary();
143 Dart_Handle entryFunctioName = Dart_NewStringFromCString("main");
144 SHUTDOWN_ON_ERROR(entryFunctioName);
145 result = Dart_Invoke(library, entryFunctioName, 0, 0);
146 SHUTDOWN_ON_ERROR(result);
147
148 // Retrieve the ReceivePort that the service is waiting on. The _receive Port
149 // variable is setup in the call to main.
150 Dart_Handle portFieldName = Dart_NewStringFromCString("_receivePort");
151 SHUTDOWN_ON_ERROR(portFieldName);
152 Dart_Handle receivePort = Dart_GetField(library, portFieldName);
153 SHUTDOWN_ON_ERROR(receivePort);
154
155 m_port = DartServiceInternal::GetPortIdFromPort(receivePort);
156 if (m_port == ILLEGAL_PORT) {
157 Dart_ExitScope();
158 Dart_ShutdownIsolate();
159 m_errorMsg = "Invalid isolate state - Unable to get receivePort";
160 return false;
161 }
162
163 {
164 // Retrieve the ReceivePort that the service is waiting on. The _rec eivePort
165 // variable is setup in the call to main.
166 Dart_Handle portFieldName = Dart_NewStringFromCString("_requestPort" );
167 SHUTDOWN_ON_ERROR(portFieldName);
168 Dart_Handle receivePort = Dart_GetField(library, portFieldName);
169 SHUTDOWN_ON_ERROR(receivePort);
170 m_requestPort = DartServiceInternal::GetPortIdFromPort(receivePort);
171 ASSERT(m_requestPort != ILLEGAL_PORT);
172 }
173
174 Dart_ExitScope();
175 Dart_ExitIsolate();
176 SetupNativePort();
177 return true;
178 }
179 error:
180 Dart_ExitScope();
181 Dart_ShutdownIsolate();
182 m_isolate = 0;
183 m_port = ILLEGAL_PORT;
184 m_requestPort = ILLEGAL_PORT;
185 return false;
186 }
187
188
189 bool DartService::Stop()
190 {
Jacob 2013/12/05 19:31:31 remove return values that provide no value.
191 if (!m_isolate) {
192 // Already shutdown.
193 return true;
194 }
195 ShutdownNativePort();
196 m_port = ILLEGAL_PORT;
197 m_requestPort = ILLEGAL_PORT;
198 Dart_Isolate isolate = m_isolate;
199 m_isolate = 0;
200 Dart_EnterIsolate(isolate);
201 DartController::shutdownIsolate(isolate);
202 return true;
203 }
204
205
206 void DartService::SetupNativePort()
207 {
208 if (m_nativePort != ILLEGAL_PORT) {
209 // Already running.
210 return;
211 }
212 const char* nativePortName = "VMServiceNativePort";
213 m_nativePort = Dart_NewNativePort(nativePortName, NativePortMessageHandler, false);
214 ASSERT(m_nativePort != ILLEGAL_PORT);
215 }
216
217
218 void DartService::ShutdownNativePort()
219 {
220 if (m_nativePort == ILLEGAL_PORT) {
221 return;
222 }
223 Dart_CloseNativePort(m_nativePort);
224 m_nativePort = ILLEGAL_PORT;
225 }
226
227
228 const char* DartService::GetErrorMessage()
229 {
230 return m_errorMsg ? m_errorMsg : "No error.";
231 }
232
233
234 Dart_Port DartService::port()
235 {
236 return m_port;
237 }
238
239
240 bool DartService::IsRunning()
241 {
242 return m_port != ILLEGAL_PORT;
243 }
244
245
246 static Dart_Handle MakeServiceControlMessage(Dart_Port portId, intptr_t code, Da rt_Handle name)
247 {
248 Dart_Handle result;
249 Dart_Handle list = Dart_NewList(4);
250 ASSERT(!Dart_IsError(list));
251 Dart_Handle codeHandle = Dart_NewInteger(code);
252 ASSERT(!Dart_IsError(codeHandle));
253 result = Dart_ListSetAt(list, 0, codeHandle);
254 ASSERT(!Dart_IsError(result));
255 Dart_Handle portIdHandle = Dart_NewInteger(portId);
256 ASSERT(!Dart_IsError(portIdHandle));
257 result = Dart_ListSetAt(list, 1, portIdHandle);
258 ASSERT(!Dart_IsError(result));
259 Dart_Handle sendPort = Dart_NewSendPort(portId);
260 ASSERT(!Dart_IsError(sendPort));
261 result = Dart_ListSetAt(list, 2, sendPort);
262 ASSERT(!Dart_IsError(result));
263 result = Dart_ListSetAt(list, 3, name);
264 ASSERT(!Dart_IsError(result));
265 return list;
266 }
267
268
269 bool DartService::SendIsolateStartupMessage()
270 {
271 if (!IsRunning()) {
272 return false;
273 }
274 Dart_Handle name = Dart_DebugName();
275 ASSERT(!Dart_IsError(name));
276 Dart_Handle list = MakeServiceControlMessage(Dart_GetMainPortId(), VM_SERVIC E_ISOLATE_STARTUP_MESSAGE_ID, name);
277 ASSERT(!Dart_IsError(list));
278 return Dart_Post(m_port, list);
279 }
280
281
282 bool DartService::SendIsolateShutdownMessage()
283 {
284 if (!IsRunning())
285 return false;
286 Dart_Handle list = MakeServiceControlMessage(Dart_GetMainPortId(), VM_SERVIC E_ISOLATE_SHUTDOWN_MESSAGE_ID, Dart_Null());
287 ASSERT(!Dart_IsError(list));
288 return Dart_Post(m_port, list);
289 }
290
291
292 DartServiceRequest::DartServiceRequest(const char* request)
293 {
294 ASSERT(request);
295 m_request = strdup(request);
296 ASSERT(m_request);
297 }
298
299 DartServiceRequest::~DartServiceRequest()
300 {
301 free(m_request);
302 }
303
304
305
306 // The format of the message is:
307 // [send port, request string, address of DartServiceRequest].
308 static Dart_Handle MakeServiceRequestMessage(Dart_Port port, DartServiceRequest* request)
309 {
310 intptr_t requestAddress = reinterpret_cast<intptr_t>(request);
311 int64_t requestAddress64 = static_cast<int64_t>(requestAddress);
312 Dart_Handle result;
313 Dart_Handle list = Dart_NewList(3);
314 ASSERT(!Dart_IsError(list));
315 Dart_Handle portHandle = Dart_NewSendPort(port);
316 ASSERT(!Dart_IsError(portHandle));
317 Dart_Handle requestHandle = Dart_NewStringFromCString(request->GetRequestStr ing());
318 ASSERT(!Dart_IsError(requestHandle));
319 Dart_Handle addressHandle = Dart_NewInteger(requestAddress64);
320 ASSERT(!Dart_IsError(addressHandle));
321 result = Dart_ListSetAt(list, 0, portHandle);
322 ASSERT(!Dart_IsError(result));
323 result = Dart_ListSetAt(list, 1, requestHandle);
324 ASSERT(!Dart_IsError(result));
325 result = Dart_ListSetAt(list, 2, addressHandle);
326 ASSERT(!Dart_IsError(result));
327 return list;
328 }
329
330
331 void DartService::MakeServiceRequest(DartServiceRequest* request)
332 {
333 // TODO(johnmccutchan): Once the VM service is no longer a DOM isolate,
334 // we must be careful about entering the isolate.
335 DartIsolateScope isolateScope(m_isolate);
336 {
Jacob 2013/12/05 19:31:31 no need for the extra { } here.
Cutch 2013/12/05 22:48:15 Done.
337 DartApiScope apiScope;
338 Dart_Handle message = MakeServiceRequestMessage(m_nativePort, request);
339 Dart_Post(m_requestPort, message);
340 }
341 }
342
343
344 void DartService::NativePortMessageHandler(Dart_Port destPortId, Dart_CObject* m essage)
345 {
346 // The format of the reply message is:
347 // [response string, address of DartServiceRequest].
348 ASSERT(destPortId == m_nativePort);
349 ASSERT(message->type == Dart_CObject_kArray);
350 ASSERT(message->value.as_array.length == 2);
351 ASSERT(message->value.as_array.values[0]->type == Dart_CObject_kString);
352 intptr_t requestAddress = 0;
353 if (message->value.as_array.values[1]->type == Dart_CObject_kInt32) {
354 requestAddress = static_cast<intptr_t>(message->value.as_array.values[1] ->value.as_int32);
355 } else {
356 ASSERT(message->value.as_array.values[1]->type == Dart_CObject_kInt64);
357 requestAddress = static_cast<intptr_t>(message->value.as_array.values[1] ->value.as_int64);
358 }
359 ASSERT(request_address);
360 DartServiceRequest* request = reinterpret_cast<DartServiceRequest*>(requestA ddress);
361 request->ResponseReady(message->value.as_array.values[0]->value.as_string);
362 }
363
364
365 Dart_Handle DartService::GetSource(const char* name)
366 {
367 const char* vmserviceSource = 0;
368 int r = dart::bin::Resources::ResourceLookup(name, &vmserviceSource);
369 ASSERT(r != dart::bin::Resources::kNoSuchInstance);
370 return Dart_NewStringFromCString(vmserviceSource);
371 }
372
373
374 Dart_Handle DartService::LoadScript(const char* name)
375 {
376 Dart_Handle url = Dart_NewStringFromCString(name);
377 Dart_Handle source = GetSource(name);
378 return Dart_LoadScript(url, source, 0, 0);
379 }
380
381
382 Dart_Handle DartService::LoadSource(Dart_Handle library, const char* name)
383 {
384 Dart_Handle url = Dart_NewStringFromCString(name);
385 Dart_Handle source = GetSource(name);
386 return Dart_LoadSource(library, url, source);
387 }
388
389
390 Dart_Handle DartService::LoadSources(Dart_Handle library, const char* names[])
391 {
392 Dart_Handle result = Dart_Null();
393 for (int i = 0; names[i]; i++) {
394 result = LoadSource(library, names[i]);
395 if (Dart_IsError(result))
396 break;
397 }
398 return result;
399 }
400
401
402 static bool IsVMServiceURL(const char* url)
403 {
404 static const intptr_t kLibraryResourceNamePrefixLen = strlen(kLibraryResourc eNamePrefix);
405 return !strncmp(kLibraryResourceNamePrefix, url, kLibraryResourceNamePrefixL en);
406 }
407
408
409 static bool IsVMServiceLibrary(const char* url)
410 {
411 return !strcmp(kVMServiceLibraryName, url);
412 }
413
414 static bool IsDartLibrary(const char* url)
415 {
416 static const char* kDartPrefix = "dart:";
417 static const intptr_t kDartPrefixLen = strlen(kDartPrefix);
418 return !strncmp(kDartPrefix, url, kDartPrefixLen);
419 }
420
421 static Dart_Handle Canonicalize(const char* url)
422 {
423 if (IsVMServiceURL(url)) {
424 // Already canonicalized.
425 return Dart_NewStringFromCString(url);
426 }
427 // FIXME(johnmccutchan): Remove hard coded 1024 character limit.
428 char buffer[1024];
429 snprintf(&buffer[0], sizeof(buffer), "%s/%s", kLibraryResourceNamePrefix, ur l);
430 return Dart_NewStringFromCString(buffer);
431 }
432
433
434 Dart_Handle DartService::LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle libr ary, Dart_Handle url)
435 {
436 if (!Dart_IsLibrary(library))
437 return Dart_NewApiError("not a library");
438 if (!Dart_IsString(url))
439 return Dart_NewApiError("url is not a string");
440 const char* urlString = 0;
441 Dart_Handle result = Dart_StringToCString(url, &urlString);
442 if (Dart_IsError(result))
443 return result;
444 Dart_Handle libraryUrl = Dart_LibraryUrl(library);
445 const char* libraryUrlString = 0;
446 result = Dart_StringToCString(libraryUrl, &libraryUrlString);
447 if (Dart_IsError(result))
448 return result;
449 if (IsDartLibrary(urlString))
450 return DartApplicationLoader::libraryTagHandlerCallback(tag, library, ur l);
451 switch (tag) {
452 case Dart_kCanonicalizeUrl:
453 return Canonicalize(urlString);
454 break;
455 case Dart_kImportTag: {
456 Dart_Handle source = GetSource(urlString);
457 if (Dart_IsError(source))
458 return source;
459 Dart_Handle lib = Dart_LoadLibrary(url, source);
460 if (Dart_IsError(lib))
461 return lib;
462 if (IsVMServiceLibrary(urlString)) {
463 // Install native resolver for this library.
464 result = Dart_SetNativeResolver(lib, DartService::NativeResolver);
465 if (Dart_IsError(result))
466 return result;
467 }
468 return lib;
469 }
470 break;
471 case Dart_kSourceTag: {
472 Dart_Handle source = GetSource(urlString);
473 if (Dart_IsError(source))
474 return source;
475 return Dart_LoadSource(library, url, source);
476 }
477 break;
478 default:
479 DART_UNIMPLEMENTED();
480 break;
481 }
482 ASSERT_NOT_REACHED();
483 return result;
484 }
485
486
487 void DartService::VmServiceShutdownCallback(void* callbackData)
488 {
489 ASSERT(Dart_CurrentIsolate());
490 Dart_EnterScope();
491 SendIsolateShutdownMessage();
492 Dart_ExitScope();
493 }
494
495 static void SendServiceMessage(Dart_NativeArguments args)
496 {
497 Dart_Handle sp = Dart_GetNativeArgument(args, 0);
498 Dart_Handle rp = Dart_GetNativeArgument(args, 1);
499 Dart_Handle message = Dart_GetNativeArgument(args, 2);
500 DartServiceInternal::PostOOB(sp, rp, message);
501 }
502
503
504 struct VmServiceNativeEntry {
505 const char* name;
506 int numArguments;
507 Dart_NativeFunction function;
508 };
509
510
511 static VmServiceNativeEntry VmServiceNativeEntries[] = {
512 {"SendServiceMessage", 3, SendServiceMessage}
513 };
514
515
516 Dart_NativeFunction DartService::NativeResolver(Dart_Handle name, int numArgumen ts)
517 {
518 const char* functionName = 0;
519 Dart_Handle result = Dart_StringToCString(name, &functionName);
520 ASSERT(!Dart_IsError(result));
521 ASSERT(functionName);
522 intptr_t n = sizeof(VmServiceNativeEntries) / sizeof(VmServiceNativeEntries[ 0]);
523 for (intptr_t i = 0; i < n; i++) {
524 VmServiceNativeEntry entry = VmServiceNativeEntries[i];
525 if (!strcmp(functionName, entry.name) && (numArguments == entry.numArgum ents)) {
526 return entry.function;
527 }
528 }
529 return 0;
530 }
531
532 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698