Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 | |
|
Jacob
2013/12/04 20:39:52
nit: these could be kept in sync automatically by
Cutch
2013/12/04 21:20:50
Done.
| |
| 18 #define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1 | |
| 19 #define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2 | |
| 20 | |
| 21 // The following Resources class is used in combination with a generated | |
| 22 // source file that expects underscores in names. The NOLINT tags are | |
| 23 // used to suppress the errors. | |
| 24 namespace dart { | |
|
Jacob
2013/12/04 20:39:52
having files with the namespace dart::bin
seems st
Cutch
2013/12/04 21:20:50
Added TODO. Moving the namespace requires surgery
| |
| 25 namespace bin { | |
| 26 class Resources { | |
| 27 public: | |
| 28 static const int kNoSuchInstance = -1; | |
| 29 | |
| 30 static int ResourceLookup(const char* path, const char** resource) | |
| 31 { | |
| 32 for (int i = 0; i < get_resource_count(); i++) { | |
| 33 resource_map_entry* entry = get_resource(i); | |
| 34 if (!strcmp(path, entry->path_)) { | |
| 35 *resource = entry->resource_; | |
| 36 ASSERT(entry->length_ > 0); | |
| 37 return entry->length_; | |
| 38 } | |
| 39 } | |
| 40 return kNoSuchInstance; | |
| 41 } | |
| 42 | |
| 43 static intptr_t get_resource_count() // NOLINT. | |
| 44 { | |
| 45 return builtin_resources_count_; | |
| 46 } | |
| 47 | |
| 48 static const char* get_resource_path(intptr_t i) // NOLINT. | |
| 49 { | |
| 50 return get_resource(i)->path_; | |
| 51 } | |
| 52 | |
| 53 private: | |
| 54 struct resource_map_entry { // NOLINT. | |
| 55 const char* path_; // NOLINT. | |
| 56 const char* resource_; // NOLINT. | |
| 57 intptr_t length_; // NOLINT. | |
| 58 }; | |
| 59 | |
| 60 // These fields are generated by resources_gen.cc. | |
| 61 static resource_map_entry builtin_resources_[]; // NOLINT. | |
| 62 static const intptr_t builtin_resources_count_; // NOLINT. | |
| 63 | |
| 64 static resource_map_entry* get_resource(int i) // NOLINT. | |
| 65 { | |
| 66 ASSERT(i >= 0 && i < builtin_resources_count_); | |
| 67 return &builtin_resources_[i]; | |
| 68 } | |
| 69 | |
| 70 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources); | |
| 71 }; | |
| 72 | |
| 73 } | |
| 74 } | |
| 75 namespace WebCore { | |
| 76 | |
| 77 #define RETURN_ERROR_HANDLE(handle) \ | |
| 78 if (Dart_IsError(handle)) { \ | |
| 79 return handle; \ | |
| 80 } | |
| 81 | |
| 82 #define SHUTDOWN_ON_ERROR(handle) \ | |
| 83 if (Dart_IsError(handle)) { \ | |
| 84 m_errorMsg = strdup(Dart_GetError(handle)); \ | |
| 85 Dart_ExitScope(); \ | |
| 86 Dart_ShutdownIsolate(); \ | |
| 87 return false; \ | |
| 88 } | |
| 89 | |
| 90 #define kLibraryResourceNamePrefix "/vmservice" | |
| 91 static const char* kVMServiceDartiumLibraryScriptResourceName = | |
| 92 kLibraryResourceNamePrefix "/vmservice_dartium.dart"; | |
| 93 static const char* kVMServiceLibraryName = | |
| 94 kLibraryResourceNamePrefix "/vmservice.dart"; | |
| 95 | |
| 96 | |
| 97 Dart_Isolate DartService::m_isolate = 0; | |
| 98 Dart_Port DartService::m_port = ILLEGAL_PORT; | |
| 99 Dart_Port DartService::m_requestPort = ILLEGAL_PORT; | |
| 100 const char* DartService::m_errorMsg = 0; | |
| 101 | |
| 102 | |
| 103 bool DartService::Start(Document* document) | |
| 104 { | |
| 105 ASSERT(!m_isolate); | |
| 106 char* error = 0; | |
| 107 const char* scriptUri = "vmservice:"; | |
|
Jacob
2013/12/04 20:39:52
move this constant outside of the method
Cutch
2013/12/04 21:20:50
Done.
| |
| 108 m_isolate = DartController::createIsolate(scriptUri, "main", document, true, &error); | |
| 109 if (!m_isolate) { | |
| 110 m_errorMsg = error; | |
| 111 return false; | |
| 112 } | |
| 113 | |
| 114 | |
| 115 Dart_EnterScope(); | |
| 116 | |
| 117 // Set up the library tag handler for this isolate. | |
| 118 Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler); | |
| 119 SHUTDOWN_ON_ERROR(result); | |
|
Jacob
2013/12/04 20:39:52
for consistency use the
Scope auto-release helper
Cutch
2013/12/04 21:20:50
Done.
| |
| 120 | |
| 121 { | |
| 122 // Load source into service isolate. | |
| 123 Dart_Handle library = | |
| 124 LoadScript(kVMServiceDartiumLibraryScriptResourceName); | |
| 125 SHUTDOWN_ON_ERROR(library); | |
| 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 _receivePort | |
| 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 _receive Port | |
| 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 | |
| 180 | |
| 181 bool DartService::Stop() | |
| 182 { | |
| 183 // TODO: Properly cleanup VM service isolate. | |
| 184 m_port = ILLEGAL_PORT; | |
| 185 return true; | |
| 186 } | |
| 187 | |
| 188 | |
| 189 const char* DartService::GetErrorMessage() | |
| 190 { | |
| 191 return m_errorMsg ? m_errorMsg : "No error."; | |
| 192 } | |
| 193 | |
| 194 | |
| 195 Dart_Port DartService::port() | |
| 196 { | |
| 197 return m_port; | |
| 198 } | |
| 199 | |
| 200 | |
| 201 bool DartService::IsRunning() | |
| 202 { | |
| 203 return m_port != ILLEGAL_PORT; | |
| 204 } | |
| 205 | |
| 206 | |
| 207 static Dart_Handle MakeServiceControlMessage(Dart_Port portId, intptr_t code, Da rt_Handle name) | |
| 208 { | |
| 209 Dart_Handle result; | |
| 210 Dart_Handle list = Dart_NewList(4); | |
| 211 ASSERT(!Dart_IsError(list)); | |
| 212 Dart_Handle codeHandle = Dart_NewInteger(code); | |
| 213 ASSERT(!Dart_IsError(codeHandle)); | |
| 214 result = Dart_ListSetAt(list, 0, codeHandle); | |
| 215 ASSERT(!Dart_IsError(result)); | |
| 216 Dart_Handle portIdHandle = Dart_NewInteger(portId); | |
| 217 ASSERT(!Dart_IsError(portIdHandle)); | |
| 218 result = Dart_ListSetAt(list, 1, portIdHandle); | |
| 219 ASSERT(!Dart_IsError(result)); | |
| 220 Dart_Handle sendPort = Dart_NewSendPort(portId); | |
| 221 ASSERT(!Dart_IsError(sendPort)); | |
| 222 result = Dart_ListSetAt(list, 2, sendPort); | |
| 223 ASSERT(!Dart_IsError(result)); | |
| 224 result = Dart_ListSetAt(list, 3, name); | |
| 225 ASSERT(!Dart_IsError(result)); | |
| 226 return list; | |
| 227 } | |
| 228 | |
| 229 | |
| 230 bool DartService::SendIsolateStartupMessage() | |
| 231 { | |
| 232 if (!IsRunning()) { | |
| 233 return false; | |
| 234 } | |
| 235 Dart_Handle name = Dart_DebugName(); | |
| 236 ASSERT(!Dart_IsError(name)); | |
| 237 Dart_Handle list = MakeServiceControlMessage( | |
|
Jacob
2013/12/04 20:39:52
there isn't an 80 char line limit in this director
Cutch
2013/12/04 21:20:50
Done.
| |
| 238 Dart_GetMainPortId(), | |
| 239 VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID, | |
| 240 name); | |
| 241 ASSERT(!Dart_IsError(list)); | |
| 242 return Dart_Post(m_port, list); | |
| 243 } | |
| 244 | |
| 245 | |
| 246 bool DartService::SendIsolateShutdownMessage() | |
| 247 { | |
| 248 if (!IsRunning()) { | |
| 249 return false; | |
| 250 } | |
| 251 Dart_Handle list = MakeServiceControlMessage(Dart_GetMainPortId(), VM_SERVIC E_ISOLATE_SHUTDOWN_MESSAGE_ID, Dart_Null()); | |
| 252 ASSERT(!Dart_IsError(list)); | |
| 253 return Dart_Post(m_port, list); | |
| 254 } | |
| 255 | |
| 256 | |
| 257 Dart_Handle DartService::GetSource(const char* name) | |
| 258 { | |
| 259 const char* vmserviceSource = 0; | |
| 260 int r = dart::bin::Resources::ResourceLookup(name, &vmserviceSource); | |
| 261 ASSERT(r != dart::bin::Resources::kNoSuchInstance); | |
| 262 return Dart_NewStringFromCString(vmserviceSource); | |
| 263 } | |
| 264 | |
| 265 | |
| 266 Dart_Handle DartService::LoadScript(const char* name) | |
| 267 { | |
| 268 Dart_Handle url = Dart_NewStringFromCString(name); | |
| 269 Dart_Handle source = GetSource(name); | |
| 270 return Dart_LoadScript(url, source, 0, 0); | |
| 271 } | |
| 272 | |
| 273 | |
| 274 Dart_Handle DartService::LoadSource(Dart_Handle library, const char* name) | |
| 275 { | |
| 276 Dart_Handle url = Dart_NewStringFromCString(name); | |
| 277 Dart_Handle source = GetSource(name); | |
| 278 return Dart_LoadSource(library, url, source); | |
| 279 } | |
| 280 | |
| 281 | |
| 282 Dart_Handle DartService::LoadSources(Dart_Handle library, const char* names[]) | |
| 283 { | |
| 284 Dart_Handle result = Dart_Null(); | |
| 285 for (int i = 0; names[i]; i++) { | |
| 286 result = LoadSource(library, names[i]); | |
| 287 if (Dart_IsError(result)) { | |
| 288 break; | |
|
Jacob
2013/12/04 20:39:52
here and elsewhere, remove {
}
for single line
Cutch
2013/12/04 21:20:50
Done.
| |
| 289 } | |
| 290 } | |
| 291 return result; | |
| 292 } | |
| 293 | |
| 294 | |
| 295 static bool IsVMServiceURL(const char* url) | |
| 296 { | |
| 297 static const intptr_t kLibraryResourceNamePrefixLen = strlen(kLibraryResourc eNamePrefix); | |
| 298 return !strncmp(kLibraryResourceNamePrefix, url, kLibraryResourceNamePrefixL en); | |
| 299 } | |
| 300 | |
| 301 | |
| 302 static bool IsVMServiceLibrary(const char* url) | |
| 303 { | |
| 304 return !strcmp(kVMServiceLibraryName, url); | |
| 305 } | |
| 306 | |
| 307 static bool IsDartLibrary(const char* url) | |
|
Jacob
2013/12/04 20:39:52
I assume this is probably defined somewhere else a
Cutch
2013/12/04 21:20:50
It actually is not.
| |
| 308 { | |
| 309 static const char* kDartPrefix = "dart:"; | |
| 310 static const intptr_t kDartPrefixLen = strlen(kDartPrefix); | |
| 311 return !strncmp(kDartPrefix, url, kDartPrefixLen); | |
| 312 } | |
| 313 | |
| 314 static Dart_Handle Canonicalize(const char* url) | |
| 315 { | |
| 316 if (IsVMServiceURL(url)) { | |
| 317 // Already canonicalized. | |
| 318 return Dart_NewStringFromCString(url); | |
| 319 } | |
| 320 char buffer[1024]; | |
|
Jacob
2013/12/04 20:39:52
add FIXME to not hardcode 1024 here.
Cutch
2013/12/04 21:20:50
Done.
| |
| 321 snprintf(&buffer[0], sizeof(buffer), "%s/%s", kLibraryResourceNamePrefix, ur l); | |
| 322 return Dart_NewStringFromCString(buffer); | |
| 323 } | |
| 324 | |
| 325 | |
| 326 Dart_Handle DartService::LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle libr ary, Dart_Handle url) | |
| 327 { | |
| 328 if (!Dart_IsLibrary(library)) { | |
| 329 return Dart_NewApiError("not a library"); | |
| 330 } | |
| 331 if (!Dart_IsString(url)) { | |
| 332 return Dart_NewApiError("url is not a string"); | |
| 333 } | |
| 334 const char* urlString = 0; | |
| 335 Dart_Handle result = Dart_StringToCString(url, &urlString); | |
| 336 if (Dart_IsError(result)) { | |
| 337 return result; | |
| 338 } | |
| 339 Dart_Handle libraryUrl = Dart_LibraryUrl(library); | |
| 340 const char* libraryUrlString = 0; | |
| 341 result = Dart_StringToCString(libraryUrl, &libraryUrlString); | |
| 342 if (Dart_IsError(result)) { | |
| 343 return result; | |
| 344 } | |
| 345 if (IsDartLibrary(urlString)) { | |
| 346 return DartApplicationLoader::libraryTagHandlerCallback(tag, library, ur l); | |
| 347 } | |
| 348 switch (tag) { | |
| 349 case Dart_kCanonicalizeUrl: | |
| 350 return Canonicalize(urlString); | |
| 351 break; | |
| 352 case Dart_kImportTag: { | |
| 353 Dart_Handle source = GetSource(urlString); | |
| 354 if (Dart_IsError(source)) { | |
| 355 return source; | |
| 356 } | |
| 357 Dart_Handle lib = Dart_LoadLibrary(url, source); | |
| 358 if (Dart_IsError(lib)) { | |
| 359 return lib; | |
| 360 } | |
| 361 if (IsVMServiceLibrary(urlString)) { | |
| 362 // Install native resolver for this library. | |
| 363 result = Dart_SetNativeResolver(lib, DartService::NativeResolver); | |
| 364 if (Dart_IsError(result)) { | |
| 365 return result; | |
| 366 } | |
| 367 } | |
| 368 return lib; | |
| 369 } | |
| 370 break; | |
| 371 case Dart_kSourceTag: { | |
| 372 Dart_Handle source = GetSource(urlString); | |
| 373 if (Dart_IsError(source)) { | |
| 374 return source; | |
| 375 } | |
| 376 return Dart_LoadSource(library, url, source); | |
| 377 } | |
| 378 break; | |
| 379 default: | |
| 380 DART_UNIMPLEMENTED(); | |
| 381 break; | |
| 382 } | |
| 383 DART_UNIMPLEMENTED(); | |
|
Jacob
2013/12/04 20:39:52
DART_UNIMPLEMENTED seems wrong here. this is hitti
Cutch
2013/12/04 21:20:50
Replaced with ASSERT_NOT_REACHED
| |
| 384 return result; | |
| 385 } | |
| 386 | |
| 387 | |
| 388 void DartService::VmServiceShutdownCallback(void* callbackData) | |
| 389 { | |
| 390 ASSERT(Dart_CurrentIsolate()); | |
| 391 Dart_EnterScope(); | |
| 392 SendIsolateShutdownMessage(); | |
| 393 Dart_ExitScope(); | |
| 394 } | |
| 395 | |
| 396 static void SendServiceMessage(Dart_NativeArguments args) | |
| 397 { | |
| 398 Dart_Handle sp = Dart_GetNativeArgument(args, 0); | |
| 399 Dart_Handle rp = Dart_GetNativeArgument(args, 1); | |
| 400 Dart_Handle message = Dart_GetNativeArgument(args, 2); | |
| 401 DartServiceInternal::PostOOB(sp, rp, message); | |
| 402 } | |
| 403 | |
| 404 | |
| 405 struct VmServiceNativeEntry { | |
| 406 const char* name; | |
| 407 int numArguments; | |
| 408 Dart_NativeFunction function; | |
| 409 }; | |
| 410 | |
| 411 | |
| 412 static VmServiceNativeEntry VmServiceNativeEntries[] = { | |
| 413 {"SendServiceMessage", 3, SendServiceMessage} | |
| 414 }; | |
| 415 | |
| 416 | |
| 417 Dart_NativeFunction DartService::NativeResolver(Dart_Handle name, int numArgumen ts) | |
| 418 { | |
| 419 const char* functionName = 0; | |
| 420 Dart_Handle result = Dart_StringToCString(name, &functionName); | |
| 421 ASSERT(!Dart_IsError(result)); | |
| 422 ASSERT(functionName); | |
| 423 intptr_t n = sizeof(VmServiceNativeEntries) / sizeof(VmServiceNativeEntries[ 0]); | |
| 424 for (intptr_t i = 0; i < n; i++) { | |
| 425 VmServiceNativeEntry entry = VmServiceNativeEntries[i]; | |
| 426 if (!strcmp(functionName, entry.name) && (numArguments == entry.numArgum ents)) { | |
| 427 return entry.function; | |
| 428 } | |
| 429 } | |
| 430 return 0; | |
| 431 } | |
| 432 | |
| 433 } | |
| OLD | NEW |