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

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 const char* DartService::m_errorMsg = 0;
97
98
99 bool DartService::Start(Document* document)
100 {
101 if (m_isolate) {
102 // Already running.
103 return true;
104 }
105 {
106 char* error = 0;
107
108 m_isolate = DartController::createIsolate(kScriptUri, "main", document, true, &error);
109 if (!m_isolate) {
110 m_errorMsg = error;
111 return false;
112 }
113
114 Dart_EnterScope();
115 // Set up the library tag handler for this isolate.
116 Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler);
117 SHUTDOWN_ON_ERROR(result);
118
119 {
120 // Load source into service isolate.
121 Dart_Handle library =
122 LoadScript(kVMServiceDartiumLibraryScriptResourceName);
123 SHUTDOWN_ON_ERROR(library);
124 result = Dart_SetNativeResolver(library, DartService::NativeResolver );
125 SHUTDOWN_ON_ERROR(result);
126 }
127 // Make the isolate runnable so that it is ready to handle messages.
128 Dart_ExitScope();
129 Dart_ExitIsolate();
130
131 bool retval = Dart_IsolateMakeRunnable(m_isolate);
132 if (!retval) {
133 Dart_EnterIsolate(m_isolate);
134 Dart_ShutdownIsolate();
135 m_errorMsg = "Invalid isolate state - Unable to make it runnable.";
136 return false;
137 }
138
139 Dart_EnterIsolate(m_isolate);
140 Dart_EnterScope();
141
142 // Invoke main.
143 Dart_Handle library = Dart_RootLibrary();
144 Dart_Handle entryFunctioName = Dart_NewStringFromCString("main");
145 SHUTDOWN_ON_ERROR(entryFunctioName);
146 result = Dart_Invoke(library, entryFunctioName, 0, 0);
147 SHUTDOWN_ON_ERROR(result);
148
149 // Retrieve the ReceivePort that the service is waiting on. The _receive Port
150 // variable is setup in the call to main.
151 Dart_Handle portFieldName = Dart_NewStringFromCString("_receivePort");
152 SHUTDOWN_ON_ERROR(portFieldName);
153 Dart_Handle receivePort = Dart_GetField(library, portFieldName);
154 SHUTDOWN_ON_ERROR(receivePort);
155
156 m_port = DartServiceInternal::GetPortIdFromPort(receivePort);
157 if (m_port == ILLEGAL_PORT) {
158 Dart_ExitScope();
159 Dart_ShutdownIsolate();
160 m_errorMsg = "Invalid isolate state - Unable to get receivePort";
161 return false;
162 }
163
164 {
165 // Retrieve the ReceivePort that the service is waiting on. The _rec eivePort
166 // variable is setup in the call to main.
167 Dart_Handle portFieldName = Dart_NewStringFromCString("_requestPort" );
168 SHUTDOWN_ON_ERROR(portFieldName);
169 Dart_Handle receivePort = Dart_GetField(library, portFieldName);
170 SHUTDOWN_ON_ERROR(receivePort);
171 m_requestPort = DartServiceInternal::GetPortIdFromPort(receivePort);
172 ASSERT(m_requestPort != ILLEGAL_PORT);
173 }
174
175 Dart_ExitScope();
176 Dart_ExitIsolate();
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 {
191 if (!m_isolate) {
192 // Already shutdown.
193 return true;
194 }
195 m_port = ILLEGAL_PORT;
196 m_requestPort = ILLEGAL_PORT;
197 Dart_Isolate isolate = m_isolate;
198 m_isolate = 0;
199 Dart_EnterIsolate(isolate);
200 DartController::shutdownIsolate(isolate);
201 return true;
202 }
203
204
205 const char* DartService::GetErrorMessage()
206 {
207 return m_errorMsg ? m_errorMsg : "No error.";
208 }
209
210
211 Dart_Port DartService::port()
212 {
213 return m_port;
214 }
215
216
217 bool DartService::IsRunning()
218 {
219 return m_port != ILLEGAL_PORT;
220 }
221
222
223 static Dart_Handle MakeServiceControlMessage(Dart_Port portId, intptr_t code, Da rt_Handle name)
224 {
225 Dart_Handle result;
226 Dart_Handle list = Dart_NewList(4);
227 ASSERT(!Dart_IsError(list));
228 Dart_Handle codeHandle = Dart_NewInteger(code);
229 ASSERT(!Dart_IsError(codeHandle));
230 result = Dart_ListSetAt(list, 0, codeHandle);
231 ASSERT(!Dart_IsError(result));
232 Dart_Handle portIdHandle = Dart_NewInteger(portId);
233 ASSERT(!Dart_IsError(portIdHandle));
234 result = Dart_ListSetAt(list, 1, portIdHandle);
235 ASSERT(!Dart_IsError(result));
236 Dart_Handle sendPort = Dart_NewSendPort(portId);
237 ASSERT(!Dart_IsError(sendPort));
238 result = Dart_ListSetAt(list, 2, sendPort);
239 ASSERT(!Dart_IsError(result));
240 result = Dart_ListSetAt(list, 3, name);
241 ASSERT(!Dart_IsError(result));
242 return list;
243 }
244
245
246 bool DartService::SendIsolateStartupMessage()
247 {
248 if (!IsRunning()) {
249 return false;
250 }
251 Dart_Handle name = Dart_DebugName();
252 ASSERT(!Dart_IsError(name));
253 Dart_Handle list = MakeServiceControlMessage(Dart_GetMainPortId(), VM_SERVIC E_ISOLATE_STARTUP_MESSAGE_ID, name);
254 ASSERT(!Dart_IsError(list));
255 return Dart_Post(m_port, list);
256 }
257
258
259 bool DartService::SendIsolateShutdownMessage()
260 {
261 if (!IsRunning())
262 return false;
263 Dart_Handle list = MakeServiceControlMessage(Dart_GetMainPortId(), VM_SERVIC E_ISOLATE_SHUTDOWN_MESSAGE_ID, Dart_Null());
264 ASSERT(!Dart_IsError(list));
265 return Dart_Post(m_port, list);
266 }
267
268
269 DartServiceRequest::DartServiceRequest(const char* request)
270 {
271 ASSERT(request);
272 m_request = strdup(request);
273 ASSERT(m_request);
274 }
275
276 DartServiceRequest::~DartServiceRequest()
277 {
278 free(m_request);
279 }
280
281
282
283 // The format of the message is:
284 // [request string, address of DartServiceRequest].
285 static Dart_Handle MakeServiceRequestMessage(DartServiceRequest* request)
286 {
287 intptr_t requestAddress = reinterpret_cast<intptr_t>(request);
288 int64_t requestAddress64 = static_cast<int64_t>(requestAddress);
289 Dart_Handle result;
290 Dart_Handle list = Dart_NewList(2);
291 ASSERT(!Dart_IsError(list));
292 Dart_Handle requestHandle = Dart_NewStringFromCString(request->GetRequestStr ing());
293 ASSERT(!Dart_IsError(requestHandle));
294 Dart_Handle addressHandle = Dart_NewInteger(requestAddress64);
295 ASSERT(!Dart_IsError(addressHandle));
296 result = Dart_ListSetAt(list, 0, requestHandle);
297 ASSERT(!Dart_IsError(result));
298 result = Dart_ListSetAt(list, 1, addressHandle);
299 ASSERT(!Dart_IsError(result));
300 return list;
301 }
302
303
304 void DartService::MakeServiceRequest(DartServiceRequest* request)
305 {
306 // TODO(johnmccutchan): Once the VM service is no longer a DOM isolate,
307 // we must be careful about entering the isolate.
308 DartIsolateScope isolateScope(m_isolate);
309 {
310 DartApiScope apiScope;
311 Dart_Handle message = MakeServiceRequestMessage(request);
312 Dart_Post(m_requestPort, message);
313 }
314 }
315
316
317 Dart_Handle DartService::GetSource(const char* name)
318 {
319 const char* vmserviceSource = 0;
320 int r = dart::bin::Resources::ResourceLookup(name, &vmserviceSource);
321 ASSERT(r != dart::bin::Resources::kNoSuchInstance);
322 return Dart_NewStringFromCString(vmserviceSource);
323 }
324
325
326 Dart_Handle DartService::LoadScript(const char* name)
327 {
328 Dart_Handle url = Dart_NewStringFromCString(name);
329 Dart_Handle source = GetSource(name);
330 return Dart_LoadScript(url, source, 0, 0);
331 }
332
333
334 Dart_Handle DartService::LoadSource(Dart_Handle library, const char* name)
335 {
336 Dart_Handle url = Dart_NewStringFromCString(name);
337 Dart_Handle source = GetSource(name);
338 return Dart_LoadSource(library, url, source);
339 }
340
341
342 Dart_Handle DartService::LoadSources(Dart_Handle library, const char* names[])
343 {
344 Dart_Handle result = Dart_Null();
345 for (int i = 0; names[i]; i++) {
346 result = LoadSource(library, names[i]);
347 if (Dart_IsError(result))
348 break;
349 }
350 return result;
351 }
352
353
354 static bool IsVMServiceURL(const char* url)
355 {
356 static const intptr_t kLibraryResourceNamePrefixLen = strlen(kLibraryResourc eNamePrefix);
357 return !strncmp(kLibraryResourceNamePrefix, url, kLibraryResourceNamePrefixL en);
358 }
359
360
361 static bool IsVMServiceLibrary(const char* url)
362 {
363 return !strcmp(kVMServiceLibraryName, url);
364 }
365
366 static bool IsDartLibrary(const char* url)
367 {
368 static const char* kDartPrefix = "dart:";
369 static const intptr_t kDartPrefixLen = strlen(kDartPrefix);
370 return !strncmp(kDartPrefix, url, kDartPrefixLen);
371 }
372
373 static Dart_Handle Canonicalize(const char* url)
374 {
375 if (IsVMServiceURL(url)) {
376 // Already canonicalized.
377 return Dart_NewStringFromCString(url);
378 }
379 // FIXME(johnmccutchan): Remove hard coded 1024 character limit.
380 char buffer[1024];
381 snprintf(&buffer[0], sizeof(buffer), "%s/%s", kLibraryResourceNamePrefix, ur l);
382 return Dart_NewStringFromCString(buffer);
383 }
384
385
386 Dart_Handle DartService::LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle libr ary, Dart_Handle url)
387 {
388 if (!Dart_IsLibrary(library))
389 return Dart_NewApiError("not a library");
390 if (!Dart_IsString(url))
391 return Dart_NewApiError("url is not a string");
392 const char* urlString = 0;
393 Dart_Handle result = Dart_StringToCString(url, &urlString);
394 if (Dart_IsError(result))
395 return result;
396 Dart_Handle libraryUrl = Dart_LibraryUrl(library);
397 const char* libraryUrlString = 0;
398 result = Dart_StringToCString(libraryUrl, &libraryUrlString);
399 if (Dart_IsError(result))
400 return result;
401 if (IsDartLibrary(urlString))
402 return DartApplicationLoader::libraryTagHandlerCallback(tag, library, ur l);
403 switch (tag) {
404 case Dart_kCanonicalizeUrl:
405 return Canonicalize(urlString);
406 break;
407 case Dart_kImportTag: {
408 Dart_Handle source = GetSource(urlString);
409 if (Dart_IsError(source))
410 return source;
411 Dart_Handle lib = Dart_LoadLibrary(url, source);
412 if (Dart_IsError(lib))
413 return lib;
414 if (IsVMServiceLibrary(urlString)) {
415 // Install native resolver for this library.
416 result = Dart_SetNativeResolver(lib, DartService::NativeResolver);
417 if (Dart_IsError(result))
418 return result;
419 }
420 return lib;
421 }
422 break;
423 case Dart_kSourceTag: {
424 Dart_Handle source = GetSource(urlString);
425 if (Dart_IsError(source))
426 return source;
427 return Dart_LoadSource(library, url, source);
428 }
429 break;
430 default:
431 DART_UNIMPLEMENTED();
432 break;
433 }
434 ASSERT_NOT_REACHED();
435 return result;
436 }
437
438
439 void DartService::VmServiceShutdownCallback(void* callbackData)
440 {
441 ASSERT(Dart_CurrentIsolate());
442 Dart_EnterScope();
443 SendIsolateShutdownMessage();
444 Dart_ExitScope();
445 }
446
447 static void SendServiceMessage(Dart_NativeArguments args)
448 {
449 Dart_Handle sp = Dart_GetNativeArgument(args, 0);
450 Dart_Handle rp = Dart_GetNativeArgument(args, 1);
451 Dart_Handle message = Dart_GetNativeArgument(args, 2);
452 DartServiceInternal::PostOOB(sp, rp, message);
453 }
454
455 static void PostResponse(Dart_NativeArguments args)
456 {
457 Dart_Handle result;
458 Dart_Handle response = Dart_GetNativeArgument(args, 0);
459 ASSERT(!Dart_IsError(response));
460 Dart_Handle cookie = Dart_GetNativeArgument(args, 1);
461 ASSERT(!Dart_IsError(cookie));
462 int64_t requestAddress64 = 0;
463 result = Dart_IntegerToInt64(cookie, &requestAddress64);
464 ASSERT(!Dart_IsError(result));
465 ASSERT(requestAddress64);
466 intptr_t requestAddress = static_cast<intptr_t>(requestAddress64);
467 ASSERT(requestAddress);
468 DartServiceRequest* request = reinterpret_cast<DartServiceRequest*>(requestA ddress);
469 const char* responseString = 0;
470 result = Dart_StringToCString(response, &responseString);
471 ASSERT(!Dart_IsError(result));
472 ASSERT(responseString);
473 request->ResponseReady(responseString);
474 }
475
476 struct VmServiceNativeEntry {
477 const char* name;
478 int numArguments;
479 Dart_NativeFunction function;
480 };
481
482
483 static VmServiceNativeEntry VmServiceNativeEntries[] = {
484 {"SendServiceMessage", 3, SendServiceMessage},
485 {"PostResponse", 2, PostResponse}
486 };
487
488
489 Dart_NativeFunction DartService::NativeResolver(Dart_Handle name, int numArgumen ts)
490 {
491 const char* functionName = 0;
492 Dart_Handle result = Dart_StringToCString(name, &functionName);
493 ASSERT(!Dart_IsError(result));
494 ASSERT(functionName);
495 intptr_t n = sizeof(VmServiceNativeEntries) / sizeof(VmServiceNativeEntries[ 0]);
496 for (intptr_t i = 0; i < n; i++) {
497 VmServiceNativeEntry entry = VmServiceNativeEntries[i];
498 if (!strcmp(functionName, entry.name) && (numArguments == entry.numArgum ents)) {
499 return entry.function;
500 }
501 }
502 return 0;
503 }
504
505 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698