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

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 String& request) : m_request(reques t)
270 {
271 }
272
273 DartServiceRequest::~DartServiceRequest()
274 {
275 }
276
277
278
279 // The format of the message is:
280 // [request string, address of DartServiceRequest].
281 static Dart_Handle MakeServiceRequestMessage(DartServiceRequest* request)
282 {
283 intptr_t requestAddress = reinterpret_cast<intptr_t>(request);
284 int64_t requestAddress64 = static_cast<int64_t>(requestAddress);
285 Dart_Handle result;
286 Dart_Handle list = Dart_NewList(2);
287 ASSERT(!Dart_IsError(list));
288 Dart_Handle requestHandle = DartUtilities::stringToDartString(request->GetRe questString());
289 ASSERT(!Dart_IsError(requestHandle));
290 Dart_Handle addressHandle = Dart_NewInteger(requestAddress64);
291 ASSERT(!Dart_IsError(addressHandle));
292 result = Dart_ListSetAt(list, 0, requestHandle);
293 ASSERT(!Dart_IsError(result));
294 result = Dart_ListSetAt(list, 1, addressHandle);
295 ASSERT(!Dart_IsError(result));
296 return list;
297 }
298
299
300 void DartService::MakeServiceRequest(DartServiceRequest* request)
301 {
302 // TODO(johnmccutchan): Once the VM service is no longer a DOM isolate,
303 // we must be careful about entering the isolate.
304 DartIsolateScope isolateScope(m_isolate);
305 DartApiScope apiScope;
306 Dart_Handle message = MakeServiceRequestMessage(request);
307 Dart_Post(m_requestPort, message);
308 }
309
310
311 Dart_Handle DartService::GetSource(const char* name)
312 {
313 const char* vmserviceSource = 0;
314 int r = dart::bin::Resources::ResourceLookup(name, &vmserviceSource);
315 ASSERT(r != dart::bin::Resources::kNoSuchInstance);
316 return Dart_NewStringFromCString(vmserviceSource);
317 }
318
319
320 Dart_Handle DartService::LoadScript(const char* name)
321 {
322 Dart_Handle url = Dart_NewStringFromCString(name);
323 Dart_Handle source = GetSource(name);
324 return Dart_LoadScript(url, source, 0, 0);
325 }
326
327
328 Dart_Handle DartService::LoadSource(Dart_Handle library, const char* name)
329 {
330 Dart_Handle url = Dart_NewStringFromCString(name);
331 Dart_Handle source = GetSource(name);
332 return Dart_LoadSource(library, url, source);
333 }
334
335
336 Dart_Handle DartService::LoadSources(Dart_Handle library, const char* names[])
337 {
338 Dart_Handle result = Dart_Null();
339 for (int i = 0; names[i]; i++) {
340 result = LoadSource(library, names[i]);
341 if (Dart_IsError(result))
342 break;
343 }
344 return result;
345 }
346
347
348 static bool IsVMServiceURL(const char* url)
349 {
350 static const intptr_t kLibraryResourceNamePrefixLen = strlen(kLibraryResourc eNamePrefix);
351 return !strncmp(kLibraryResourceNamePrefix, url, kLibraryResourceNamePrefixL en);
352 }
353
354
355 static bool IsVMServiceLibrary(const char* url)
356 {
357 return !strcmp(kVMServiceLibraryName, url);
358 }
359
360 static bool IsDartLibrary(const char* url)
361 {
362 static const char* kDartPrefix = "dart:";
363 static const intptr_t kDartPrefixLen = strlen(kDartPrefix);
364 return !strncmp(kDartPrefix, url, kDartPrefixLen);
365 }
366
367 static Dart_Handle Canonicalize(const char* url)
368 {
369 if (IsVMServiceURL(url)) {
370 // Already canonicalized.
371 return Dart_NewStringFromCString(url);
372 }
373 // FIXME(johnmccutchan): Remove hard coded 1024 character limit.
374 char buffer[1024];
375 snprintf(&buffer[0], sizeof(buffer), "%s/%s", kLibraryResourceNamePrefix, ur l);
376 return Dart_NewStringFromCString(buffer);
377 }
378
379
380 Dart_Handle DartService::LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle libr ary, Dart_Handle url)
381 {
382 if (!Dart_IsLibrary(library))
383 return Dart_NewApiError("not a library");
384 if (!Dart_IsString(url))
385 return Dart_NewApiError("url is not a string");
386 const char* urlString = 0;
387 Dart_Handle result = Dart_StringToCString(url, &urlString);
388 if (Dart_IsError(result))
389 return result;
390 Dart_Handle libraryUrl = Dart_LibraryUrl(library);
391 const char* libraryUrlString = 0;
392 result = Dart_StringToCString(libraryUrl, &libraryUrlString);
393 if (Dart_IsError(result))
394 return result;
395 if (IsDartLibrary(urlString))
396 return DartApplicationLoader::libraryTagHandlerCallback(tag, library, ur l);
397 switch (tag) {
398 case Dart_kCanonicalizeUrl:
399 return Canonicalize(urlString);
400 break;
401 case Dart_kImportTag: {
402 Dart_Handle source = GetSource(urlString);
403 if (Dart_IsError(source))
404 return source;
405 Dart_Handle lib = Dart_LoadLibrary(url, source);
406 if (Dart_IsError(lib))
407 return lib;
408 if (IsVMServiceLibrary(urlString)) {
409 // Install native resolver for this library.
410 result = Dart_SetNativeResolver(lib, DartService::NativeResolver);
411 if (Dart_IsError(result))
412 return result;
413 }
414 return lib;
415 }
416 break;
417 case Dart_kSourceTag: {
418 Dart_Handle source = GetSource(urlString);
419 if (Dart_IsError(source))
420 return source;
421 return Dart_LoadSource(library, url, source);
422 }
423 break;
424 default:
425 DART_UNIMPLEMENTED();
426 break;
427 }
428 ASSERT_NOT_REACHED();
429 return result;
430 }
431
432
433 void DartService::VmServiceShutdownCallback(void* callbackData)
434 {
435 ASSERT(Dart_CurrentIsolate());
436 DartApiScope apiScope;
437 SendIsolateShutdownMessage();
438 }
439
440 static void SendServiceMessage(Dart_NativeArguments args)
441 {
442 Dart_Handle sp = Dart_GetNativeArgument(args, 0);
443 Dart_Handle rp = Dart_GetNativeArgument(args, 1);
444 Dart_Handle message = Dart_GetNativeArgument(args, 2);
445 DartServiceInternal::PostOOB(sp, rp, message);
446 }
447
448 static void PostResponse(Dart_NativeArguments args)
449 {
450 Dart_Handle result;
451 Dart_Handle response = Dart_GetNativeArgument(args, 0);
452 ASSERT(!Dart_IsError(response));
453 Dart_Handle cookie = Dart_GetNativeArgument(args, 1);
454 ASSERT(!Dart_IsError(cookie));
455 int64_t requestAddress64 = 0;
456 result = Dart_IntegerToInt64(cookie, &requestAddress64);
457 ASSERT(!Dart_IsError(result));
458 ASSERT(requestAddress64);
459 intptr_t requestAddress = static_cast<intptr_t>(requestAddress64);
460 ASSERT(requestAddress);
461 DartServiceRequest* request = reinterpret_cast<DartServiceRequest*>(requestA ddress);
462 const char* responseString = 0;
463 result = Dart_StringToCString(response, &responseString);
464 ASSERT(!Dart_IsError(result));
465 ASSERT(responseString);
466 request->ResponseReady(responseString);
467 }
468
469 struct VmServiceNativeEntry {
470 const char* name;
471 int numArguments;
472 Dart_NativeFunction function;
473 };
474
475
476 static VmServiceNativeEntry VmServiceNativeEntries[] = {
477 {"SendServiceMessage", 3, SendServiceMessage},
478 {"PostResponse", 2, PostResponse}
479 };
480
481
482 Dart_NativeFunction DartService::NativeResolver(Dart_Handle name, int numArgumen ts)
483 {
484 const char* functionName = 0;
485 Dart_Handle result = Dart_StringToCString(name, &functionName);
486 ASSERT(!Dart_IsError(result));
487 ASSERT(functionName);
488 intptr_t n = sizeof(VmServiceNativeEntries) / sizeof(VmServiceNativeEntries[ 0]);
489 for (intptr_t i = 0; i < n; i++) {
490 VmServiceNativeEntry entry = VmServiceNativeEntries[i];
491 if (!strcmp(functionName, entry.name) && (numArguments == entry.numArgum ents)) {
492 return entry.function;
493 }
494 }
495 return 0;
496 }
497
498 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698