| 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 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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); |
| 527 { | 569 { |
| 528 JSONStream js; | 570 JSONStream js; |
| 529 js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values); | 571 js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values); |
| 530 | |
| 531 if (handler == NULL) { | 572 if (handler == NULL) { |
| 532 PrintError(&js, "Unrecognized path"); | 573 // Check for an embedder handler. |
| 574 EmbedderServiceHandler* e_handler = |
| 575 FindIsolateEmbedderHandler(path_segment_c); |
| 576 if (e_handler != NULL) { |
| 577 EmbedderHandleMessage(e_handler, &js); |
| 578 } else { |
| 579 PrintError(&js, "Unrecognized path"); |
| 580 } |
| 533 js.PostReply(); | 581 js.PostReply(); |
| 534 } else { | 582 } else { |
| 535 if (handler(isolate, &js)) { | 583 if (handler(isolate, &js)) { |
| 536 // Handler returns true if the reply is ready to be posted. | 584 // Handler returns true if the reply is ready to be posted. |
| 585 // TODO(johnmccutchan): Support asynchronous replies. |
| 537 js.PostReply(); | 586 js.PostReply(); |
| 538 } | 587 } |
| 539 } | 588 } |
| 540 } | 589 } |
| 541 } | 590 } |
| 542 } | 591 } |
| 543 | 592 |
| 544 | 593 |
| 545 static bool HandleIsolate(Isolate* isolate, JSONStream* js) { | 594 static bool HandleIsolate(Isolate* isolate, JSONStream* js) { |
| 546 isolate->PrintToJSONStream(js); | 595 isolate->PrintToJSONStream(js); |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 | 1138 |
| 1090 ASSERT(!path.IsNull()); | 1139 ASSERT(!path.IsNull()); |
| 1091 ASSERT(!option_keys.IsNull()); | 1140 ASSERT(!option_keys.IsNull()); |
| 1092 ASSERT(!option_values.IsNull()); | 1141 ASSERT(!option_values.IsNull()); |
| 1093 // Path always has at least one entry in it. | 1142 // Path always has at least one entry in it. |
| 1094 ASSERT(path.Length() > 0); | 1143 ASSERT(path.Length() > 0); |
| 1095 // Same number of option keys as values. | 1144 // Same number of option keys as values. |
| 1096 ASSERT(option_keys.Length() == option_values.Length()); | 1145 ASSERT(option_keys.Length() == option_values.Length()); |
| 1097 | 1146 |
| 1098 String& path_segment = String::Handle(); | 1147 String& path_segment = String::Handle(); |
| 1099 path_segment ^= path.At(0); | 1148 if (path.Length() > 0) { |
| 1149 path_segment ^= path.At(0); |
| 1150 } else { |
| 1151 path_segment ^= Symbols::Empty().raw(); |
| 1152 } |
| 1100 ASSERT(!path_segment.IsNull()); | 1153 ASSERT(!path_segment.IsNull()); |
| 1101 const char* path_segment_c = path_segment.ToCString(); | 1154 const char* path_segment_c = path_segment.ToCString(); |
| 1155 |
| 1102 RootMessageHandler handler = | 1156 RootMessageHandler handler = |
| 1103 FindRootMessageHandler(path_segment_c); | 1157 FindRootMessageHandler(path_segment_c); |
| 1104 | |
| 1105 { | 1158 { |
| 1106 JSONStream js; | 1159 JSONStream js; |
| 1107 js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values); | 1160 js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values); |
| 1108 if (handler == NULL) { | 1161 if (handler == NULL) { |
| 1109 PrintError(&js, "Unrecognized path"); | 1162 // Check for an embedder handler. |
| 1163 EmbedderServiceHandler* e_handler = |
| 1164 FindRootEmbedderHandler(path_segment_c); |
| 1165 if (e_handler != NULL) { |
| 1166 EmbedderHandleMessage(e_handler, &js); |
| 1167 } else { |
| 1168 PrintError(&js, "Unrecognized path"); |
| 1169 } |
| 1110 js.PostReply(); | 1170 js.PostReply(); |
| 1111 } else { | 1171 } else { |
| 1112 if (handler(&js)) { | 1172 if (handler(&js)) { |
| 1113 // Handler returns true if the reply is ready to be posted. | 1173 // Handler returns true if the reply is ready to be posted. |
| 1174 // TODO(johnmccutchan): Support asynchronous replies. |
| 1114 js.PostReply(); | 1175 js.PostReply(); |
| 1115 } | 1176 } |
| 1116 } | 1177 } |
| 1117 } | 1178 } |
| 1118 } | 1179 } |
| 1119 } | 1180 } |
| 1120 | 1181 |
| 1121 | 1182 |
| 1122 static bool HandleRootEcho(JSONStream* js) { | 1183 static bool HandleRootEcho(JSONStream* js) { |
| 1123 JSONObject jsobj(js); | 1184 JSONObject jsobj(js); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1149 if (!strcmp(command, entry.command)) { | 1210 if (!strcmp(command, entry.command)) { |
| 1150 return entry.handler; | 1211 return entry.handler; |
| 1151 } | 1212 } |
| 1152 } | 1213 } |
| 1153 if (FLAG_trace_service) { | 1214 if (FLAG_trace_service) { |
| 1154 OS::Print("Service has no root message handler for <%s>\n", command); | 1215 OS::Print("Service has no root message handler for <%s>\n", command); |
| 1155 } | 1216 } |
| 1156 return NULL; | 1217 return NULL; |
| 1157 } | 1218 } |
| 1158 | 1219 |
| 1220 |
| 1221 void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler, |
| 1222 JSONStream* js) { |
| 1223 ASSERT(handler != NULL); |
| 1224 Dart_ServiceRequestCallback callback = handler->callback(); |
| 1225 ASSERT(callback != NULL); |
| 1226 const char* r = NULL; |
| 1227 const char* name = js->command(); |
| 1228 const char** arguments = js->arguments(); |
| 1229 const char** keys = js->option_keys(); |
| 1230 const char** values = js->option_values(); |
| 1231 r = callback(name, arguments, js->num_arguments(), keys, values, |
| 1232 js->num_options(), handler->user_data()); |
| 1233 ASSERT(r != NULL); |
| 1234 // TODO(johnmccutchan): Allow for NULL returns? |
| 1235 TextBuffer* buffer = js->buffer(); |
| 1236 buffer->AddString(r); |
| 1237 free(const_cast<char*>(r)); |
| 1238 } |
| 1239 |
| 1240 |
| 1241 void Service::RegisterIsolateEmbedderCallback( |
| 1242 const char* name, |
| 1243 Dart_ServiceRequestCallback callback, |
| 1244 void* user_data) { |
| 1245 if (name == NULL) { |
| 1246 return; |
| 1247 } |
| 1248 EmbedderServiceHandler* handler = FindIsolateEmbedderHandler(name); |
| 1249 if (handler != NULL) { |
| 1250 // Update existing handler entry. |
| 1251 handler->set_callback(callback); |
| 1252 handler->set_user_data(user_data); |
| 1253 return; |
| 1254 } |
| 1255 // Create a new handler. |
| 1256 handler = new EmbedderServiceHandler(name); |
| 1257 handler->set_callback(callback); |
| 1258 handler->set_user_data(user_data); |
| 1259 |
| 1260 // Insert into isolate_service_handler_head_ list. |
| 1261 handler->set_next(isolate_service_handler_head_); |
| 1262 isolate_service_handler_head_ = handler; |
| 1263 } |
| 1264 |
| 1265 |
| 1266 EmbedderServiceHandler* Service::FindIsolateEmbedderHandler( |
| 1267 const char* name) { |
| 1268 EmbedderServiceHandler* current = isolate_service_handler_head_; |
| 1269 while (current != NULL) { |
| 1270 if (!strcmp(name, current->name())) { |
| 1271 return current; |
| 1272 } |
| 1273 current = current->next(); |
| 1274 } |
| 1275 return NULL; |
| 1276 } |
| 1277 |
| 1278 |
| 1279 void Service::RegisterRootEmbedderCallback( |
| 1280 const char* name, |
| 1281 Dart_ServiceRequestCallback callback, |
| 1282 void* user_data) { |
| 1283 if (name == NULL) { |
| 1284 return; |
| 1285 } |
| 1286 EmbedderServiceHandler* handler = FindRootEmbedderHandler(name); |
| 1287 if (handler != NULL) { |
| 1288 // Update existing handler entry. |
| 1289 handler->set_callback(callback); |
| 1290 handler->set_user_data(user_data); |
| 1291 return; |
| 1292 } |
| 1293 // Create a new handler. |
| 1294 handler = new EmbedderServiceHandler(name); |
| 1295 handler->set_callback(callback); |
| 1296 handler->set_user_data(user_data); |
| 1297 |
| 1298 // Insert into root_service_handler_head_ list. |
| 1299 handler->set_next(root_service_handler_head_); |
| 1300 root_service_handler_head_ = handler; |
| 1301 } |
| 1302 |
| 1303 |
| 1304 EmbedderServiceHandler* Service::FindRootEmbedderHandler( |
| 1305 const char* name) { |
| 1306 EmbedderServiceHandler* current = root_service_handler_head_; |
| 1307 while (current != NULL) { |
| 1308 if (!strcmp(name, current->name())) { |
| 1309 return current; |
| 1310 } |
| 1311 current = current->next(); |
| 1312 } |
| 1313 return NULL; |
| 1314 } |
| 1315 |
| 1159 } // namespace dart | 1316 } // namespace dart |
| OLD | NEW |