Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/service.h" | 5 #include "vm/service.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 | 8 |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/coverage.h" | 10 #include "vm/coverage.h" |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 97 | 97 |
| 98 static ResourcesEntry* ResourceTable() { | 98 static ResourcesEntry* ResourceTable() { |
| 99 return &__service_resources_[0]; | 99 return &__service_resources_[0]; |
| 100 } | 100 } |
| 101 | 101 |
| 102 DISALLOW_ALLOCATION(); | 102 DISALLOW_ALLOCATION(); |
| 103 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources); | 103 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources); |
| 104 }; | 104 }; |
| 105 | 105 |
| 106 | 106 |
| 107 class EmbedderServiceHandler { | |
| 108 public: | |
| 109 explicit EmbedderServiceHandler(const char* name) : name_(NULL), | |
| 110 callback_(NULL), | |
| 111 user_data_(NULL), | |
| 112 next_(NULL) { | |
| 113 ASSERT(name != NULL); | |
| 114 name_ = strdup(name); | |
| 115 } | |
| 116 | |
| 117 ~EmbedderServiceHandler() { | |
| 118 free(name_); | |
| 119 } | |
| 120 | |
| 121 const char* name() const { return name_; } | |
| 122 | |
| 123 Dart_ServiceRequestCallback callback() const { return callback_; } | |
| 124 void set_callback(Dart_ServiceRequestCallback callback) { | |
| 125 callback_ = callback; | |
| 126 } | |
| 127 | |
| 128 void* user_data() const { return user_data_; } | |
| 129 void set_user_data(void* user_data) { | |
| 130 user_data_ = user_data; | |
| 131 } | |
| 132 | |
| 133 EmbedderServiceHandler* next() const { return next_; } | |
| 134 void set_next(EmbedderServiceHandler* next) { | |
| 135 next_ = next; | |
| 136 } | |
| 137 | |
| 138 private: | |
| 139 char* name_; | |
| 140 Dart_ServiceRequestCallback callback_; | |
| 141 void* user_data_; | |
| 142 EmbedderServiceHandler* next_; | |
| 143 }; | |
| 144 | |
| 145 | |
| 107 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { | 146 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
| 108 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | 147 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
| 109 return reinterpret_cast<uint8_t*>(new_ptr); | 148 return reinterpret_cast<uint8_t*>(new_ptr); |
| 110 } | 149 } |
| 111 | 150 |
| 112 | 151 |
| 113 static void SendIsolateServiceMessage(Dart_NativeArguments args) { | 152 static void SendIsolateServiceMessage(Dart_NativeArguments args) { |
| 114 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | 153 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
| 115 Isolate* isolate = arguments->isolate(); | 154 Isolate* isolate = arguments->isolate(); |
| 116 StackZone zone(isolate); | 155 StackZone zone(isolate); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 179 VmServiceNativeEntry entry = _VmServiceNativeEntries[i]; | 218 VmServiceNativeEntry entry = _VmServiceNativeEntries[i]; |
| 180 if (!strcmp(function_name, entry.name) && | 219 if (!strcmp(function_name, entry.name) && |
| 181 (num_arguments == entry.num_arguments)) { | 220 (num_arguments == entry.num_arguments)) { |
| 182 return entry.function; | 221 return entry.function; |
| 183 } | 222 } |
| 184 } | 223 } |
| 185 return NULL; | 224 return NULL; |
| 186 } | 225 } |
| 187 | 226 |
| 188 | 227 |
| 228 EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL; | |
| 229 EmbedderServiceHandler* Service::root_service_handler_head_ = NULL; | |
| 189 Isolate* Service::service_isolate_ = NULL; | 230 Isolate* Service::service_isolate_ = NULL; |
| 190 Dart_LibraryTagHandler Service::default_handler_ = NULL; | 231 Dart_LibraryTagHandler Service::default_handler_ = NULL; |
| 191 Dart_Port Service::port_ = ILLEGAL_PORT; | 232 Dart_Port Service::port_ = ILLEGAL_PORT; |
| 192 | 233 |
| 234 | |
| 193 static Dart_Port ExtractPort(Dart_Handle receivePort) { | 235 static Dart_Port ExtractPort(Dart_Handle receivePort) { |
| 194 HANDLESCOPE(Isolate::Current()); | 236 HANDLESCOPE(Isolate::Current()); |
| 195 const Object& unwrapped_rp = Object::Handle(Api::UnwrapHandle(receivePort)); | 237 const Object& unwrapped_rp = Object::Handle(Api::UnwrapHandle(receivePort)); |
| 196 const Instance& rp = Instance::Cast(unwrapped_rp); | 238 const Instance& rp = Instance::Cast(unwrapped_rp); |
| 197 // Extract RawReceivePort port id. | 239 // Extract RawReceivePort port id. |
| 198 const Object& rp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(rp)); | 240 const Object& rp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(rp)); |
| 199 if (rp_id_obj.IsError()) { | 241 if (rp_id_obj.IsError()) { |
| 200 return ILLEGAL_PORT; | 242 return ILLEGAL_PORT; |
| 201 } | 243 } |
| 202 ASSERT(rp_id_obj.IsSmi() || rp_id_obj.IsMint()); | 244 ASSERT(rp_id_obj.IsSmi() || rp_id_obj.IsMint()); |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 517 if (path.Length() > 0) { | 559 if (path.Length() > 0) { |
| 518 path_segment ^= path.At(0); | 560 path_segment ^= path.At(0); |
| 519 } else { | 561 } else { |
| 520 path_segment ^= Symbols::Empty().raw(); | 562 path_segment ^= Symbols::Empty().raw(); |
| 521 } | 563 } |
| 522 ASSERT(!path_segment.IsNull()); | 564 ASSERT(!path_segment.IsNull()); |
| 523 const char* path_segment_c = path_segment.ToCString(); | 565 const char* path_segment_c = path_segment.ToCString(); |
| 524 | 566 |
| 525 IsolateMessageHandler handler = | 567 IsolateMessageHandler handler = |
| 526 FindIsolateMessageHandler(path_segment_c); | 568 FindIsolateMessageHandler(path_segment_c); |
| 569 if (handler == NULL) { | |
| 570 // Check for an embedder handler. | |
| 571 EmbedderServiceHandler* e_handler = | |
| 572 FindIsolateEmbedderHandler(path_segment_c); | |
| 573 if (e_handler != NULL) { | |
| 574 JSONStream js; | |
| 575 js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values); | |
| 576 EmbedderHandleMessage(e_handler, &js); | |
| 577 // TODO(johnmccutchan): Support asynchronous replies. | |
| 578 js.PostReply(); | |
| 579 return; | |
| 580 } | |
| 581 } | |
| 527 { | 582 { |
| 528 JSONStream js; | 583 JSONStream js; |
| 529 js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values); | 584 js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values); |
| 530 | |
| 531 if (handler == NULL) { | 585 if (handler == NULL) { |
|
turnidge
2014/02/18 22:25:12
What if you moved the EmbedderServiceHandler looku
Cutch
2014/02/18 22:34:10
Done and it does!
| |
| 532 PrintError(&js, "Unrecognized path"); | 586 PrintError(&js, "Unrecognized path"); |
| 533 js.PostReply(); | 587 js.PostReply(); |
| 534 } else { | 588 } else { |
| 535 if (handler(isolate, &js)) { | 589 if (handler(isolate, &js)) { |
| 536 // Handler returns true if the reply is ready to be posted. | 590 // Handler returns true if the reply is ready to be posted. |
| 591 // TODO(johnmccutchan): Support asynchronous replies. | |
|
turnidge
2014/02/18 22:25:12
Do we need this TODO here?
Cutch
2014/02/18 22:34:10
Done.
| |
| 537 js.PostReply(); | 592 js.PostReply(); |
| 538 } | 593 } |
| 539 } | 594 } |
| 540 } | 595 } |
| 541 } | 596 } |
| 542 } | 597 } |
| 543 | 598 |
| 544 | 599 |
| 545 static bool HandleIsolate(Isolate* isolate, JSONStream* js) { | 600 static bool HandleIsolate(Isolate* isolate, JSONStream* js) { |
| 546 isolate->PrintToJSONStream(js); | 601 isolate->PrintToJSONStream(js); |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1089 | 1144 |
| 1090 ASSERT(!path.IsNull()); | 1145 ASSERT(!path.IsNull()); |
| 1091 ASSERT(!option_keys.IsNull()); | 1146 ASSERT(!option_keys.IsNull()); |
| 1092 ASSERT(!option_values.IsNull()); | 1147 ASSERT(!option_values.IsNull()); |
| 1093 // Path always has at least one entry in it. | 1148 // Path always has at least one entry in it. |
| 1094 ASSERT(path.Length() > 0); | 1149 ASSERT(path.Length() > 0); |
| 1095 // Same number of option keys as values. | 1150 // Same number of option keys as values. |
| 1096 ASSERT(option_keys.Length() == option_values.Length()); | 1151 ASSERT(option_keys.Length() == option_values.Length()); |
| 1097 | 1152 |
| 1098 String& path_segment = String::Handle(); | 1153 String& path_segment = String::Handle(); |
| 1099 path_segment ^= path.At(0); | 1154 if (path.Length() > 0) { |
| 1155 path_segment ^= path.At(0); | |
| 1156 } else { | |
| 1157 path_segment ^= Symbols::Empty().raw(); | |
| 1158 } | |
| 1100 ASSERT(!path_segment.IsNull()); | 1159 ASSERT(!path_segment.IsNull()); |
| 1101 const char* path_segment_c = path_segment.ToCString(); | 1160 const char* path_segment_c = path_segment.ToCString(); |
| 1161 | |
| 1102 RootMessageHandler handler = | 1162 RootMessageHandler handler = |
| 1103 FindRootMessageHandler(path_segment_c); | 1163 FindRootMessageHandler(path_segment_c); |
| 1104 | 1164 if (handler == NULL) { |
| 1165 // Check for an embedder handler. | |
| 1166 EmbedderServiceHandler* e_handler = | |
| 1167 FindRootEmbedderHandler(path_segment_c); | |
| 1168 if (e_handler != NULL) { | |
| 1169 JSONStream js; | |
| 1170 js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values); | |
| 1171 EmbedderHandleMessage(e_handler, &js); | |
| 1172 // TODO(johnmccutchan): Support asynchronous replies. | |
| 1173 js.PostReply(); | |
| 1174 return; | |
| 1175 } | |
| 1176 } | |
| 1105 { | 1177 { |
| 1106 JSONStream js; | 1178 JSONStream js; |
| 1107 js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values); | 1179 js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values); |
| 1108 if (handler == NULL) { | 1180 if (handler == NULL) { |
|
turnidge
2014/02/18 22:25:12
Similarly as above.
Cutch
2014/02/18 22:34:10
Done.
| |
| 1109 PrintError(&js, "Unrecognized path"); | 1181 PrintError(&js, "Unrecognized path"); |
| 1110 js.PostReply(); | 1182 js.PostReply(); |
| 1111 } else { | 1183 } else { |
| 1112 if (handler(&js)) { | 1184 if (handler(&js)) { |
| 1113 // Handler returns true if the reply is ready to be posted. | 1185 // Handler returns true if the reply is ready to be posted. |
| 1186 // TODO(johnmccutchan): Support asynchronous replies. | |
| 1114 js.PostReply(); | 1187 js.PostReply(); |
| 1115 } | 1188 } |
| 1116 } | 1189 } |
| 1117 } | 1190 } |
| 1118 } | 1191 } |
| 1119 } | 1192 } |
| 1120 | 1193 |
| 1121 | 1194 |
| 1122 static bool HandleRootEcho(JSONStream* js) { | 1195 static bool HandleRootEcho(JSONStream* js) { |
| 1123 JSONObject jsobj(js); | 1196 JSONObject jsobj(js); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1149 if (!strcmp(command, entry.command)) { | 1222 if (!strcmp(command, entry.command)) { |
| 1150 return entry.handler; | 1223 return entry.handler; |
| 1151 } | 1224 } |
| 1152 } | 1225 } |
| 1153 if (FLAG_trace_service) { | 1226 if (FLAG_trace_service) { |
| 1154 OS::Print("Service has no root message handler for <%s>\n", command); | 1227 OS::Print("Service has no root message handler for <%s>\n", command); |
| 1155 } | 1228 } |
| 1156 return NULL; | 1229 return NULL; |
| 1157 } | 1230 } |
| 1158 | 1231 |
| 1232 | |
| 1233 void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler, | |
| 1234 JSONStream* js) { | |
| 1235 ASSERT(handler != NULL); | |
| 1236 Dart_ServiceRequestCallback callback = handler->callback(); | |
| 1237 ASSERT(callback != NULL); | |
| 1238 const char* r = NULL; | |
| 1239 const char* name = js->command(); | |
| 1240 const char** arguments = js->arguments(); | |
| 1241 const char** keys = js->option_keys(); | |
| 1242 const char** values = js->option_values(); | |
| 1243 r = callback(name, arguments, js->num_arguments(), keys, values, | |
| 1244 js->num_options(), handler->user_data()); | |
| 1245 ASSERT(r != NULL); | |
| 1246 // TODO(johnmccutchan): Allow for NULL returns? | |
| 1247 TextBuffer* buffer = js->buffer(); | |
| 1248 buffer->AddString(r); | |
| 1249 free(const_cast<char*>(r)); | |
| 1250 } | |
| 1251 | |
| 1252 | |
| 1253 void Service::RegisterIsolateEmbedderCallback( | |
| 1254 const char* name, | |
| 1255 Dart_ServiceRequestCallback callback, | |
| 1256 void* user_data) { | |
| 1257 if (name == NULL) { | |
| 1258 return; | |
| 1259 } | |
| 1260 EmbedderServiceHandler* handler = FindIsolateEmbedderHandler(name); | |
| 1261 if (handler != NULL) { | |
| 1262 // Update existing handler entry. | |
| 1263 handler->set_callback(callback); | |
| 1264 handler->set_user_data(user_data); | |
| 1265 return; | |
| 1266 } | |
| 1267 // Create a new handler. | |
| 1268 handler = new EmbedderServiceHandler(name); | |
| 1269 handler->set_callback(callback); | |
| 1270 handler->set_user_data(user_data); | |
| 1271 | |
| 1272 // Insert into isolate_service_handler_head_ list. | |
| 1273 handler->set_next(isolate_service_handler_head_); | |
| 1274 isolate_service_handler_head_ = handler; | |
| 1275 } | |
| 1276 | |
| 1277 | |
| 1278 EmbedderServiceHandler* Service::FindIsolateEmbedderHandler( | |
| 1279 const char* name) { | |
| 1280 EmbedderServiceHandler* current = isolate_service_handler_head_; | |
| 1281 while (current != NULL) { | |
| 1282 if (!strcmp(name, current->name())) { | |
| 1283 return current; | |
| 1284 } | |
| 1285 current = current->next(); | |
| 1286 } | |
| 1287 return NULL; | |
| 1288 } | |
| 1289 | |
| 1290 | |
| 1291 void Service::RegisterRootEmbedderCallback( | |
| 1292 const char* name, | |
| 1293 Dart_ServiceRequestCallback callback, | |
| 1294 void* user_data) { | |
| 1295 if (name == NULL) { | |
| 1296 return; | |
| 1297 } | |
| 1298 EmbedderServiceHandler* handler = FindRootEmbedderHandler(name); | |
| 1299 if (handler != NULL) { | |
| 1300 // Update existing handler entry. | |
| 1301 handler->set_callback(callback); | |
| 1302 handler->set_user_data(user_data); | |
| 1303 return; | |
| 1304 } | |
| 1305 // Create a new handler. | |
| 1306 handler = new EmbedderServiceHandler(name); | |
| 1307 handler->set_callback(callback); | |
| 1308 handler->set_user_data(user_data); | |
| 1309 | |
| 1310 // Insert into root_service_handler_head_ list. | |
| 1311 handler->set_next(root_service_handler_head_); | |
| 1312 root_service_handler_head_ = handler; | |
| 1313 } | |
| 1314 | |
| 1315 | |
| 1316 EmbedderServiceHandler* Service::FindRootEmbedderHandler( | |
| 1317 const char* name) { | |
| 1318 EmbedderServiceHandler* current = root_service_handler_head_; | |
| 1319 while (current != NULL) { | |
| 1320 if (!strcmp(name, current->name())) { | |
| 1321 return current; | |
| 1322 } | |
| 1323 current = current->next(); | |
| 1324 } | |
| 1325 return NULL; | |
| 1326 } | |
| 1327 | |
| 1159 } // namespace dart | 1328 } // namespace dart |
| OLD | NEW |