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

Side by Side Diff: runtime/vm/service.cc

Issue 170943003: Allow for embedder provided service request handlers (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 months 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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698