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

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
« no previous file with comments | « runtime/vm/service.h ('k') | runtime/vm/service_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/service.h ('k') | runtime/vm/service_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698