Chromium Code Reviews| Index: runtime/vm/service.cc |
| diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc |
| index 7596e7aab7f683d8eeaaef25bc719fbc61f5ee18..4288556070b0f8d14b725e08799d842bff0f7cd0 100644 |
| --- a/runtime/vm/service.cc |
| +++ b/runtime/vm/service.cc |
| @@ -104,6 +104,45 @@ class Resources { |
| }; |
| +class EmbedderServiceHandler { |
| + public: |
| + explicit EmbedderServiceHandler(const char* name) : name_(NULL), |
| + callback_(NULL), |
| + user_data_(NULL), |
| + next_(NULL) { |
| + ASSERT(name != NULL); |
| + name_ = strdup(name); |
| + } |
| + |
| + ~EmbedderServiceHandler() { |
| + free(name_); |
| + } |
| + |
| + const char* name() const { return name_; } |
| + |
| + Dart_ServiceRequestCallback callback() const { return callback_; } |
| + void set_callback(Dart_ServiceRequestCallback callback) { |
| + callback_ = callback; |
| + } |
| + |
| + void* user_data() const { return user_data_; } |
| + void set_user_data(void* user_data) { |
| + user_data_ = user_data; |
| + } |
| + |
| + EmbedderServiceHandler* next() const { return next_; } |
| + void set_next(EmbedderServiceHandler* next) { |
| + next_ = next; |
| + } |
| + |
| + private: |
| + char* name_; |
| + Dart_ServiceRequestCallback callback_; |
| + void* user_data_; |
| + EmbedderServiceHandler* next_; |
| +}; |
| + |
| + |
| static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
| void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
| return reinterpret_cast<uint8_t*>(new_ptr); |
| @@ -186,10 +225,12 @@ static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name, |
| } |
| +EmbedderServiceHandler* Service::service_handler_head_ = NULL; |
| Isolate* Service::service_isolate_ = NULL; |
| Dart_LibraryTagHandler Service::default_handler_ = NULL; |
| Dart_Port Service::port_ = ILLEGAL_PORT; |
| + |
| static Dart_Port ExtractPort(Dart_Handle receivePort) { |
| HANDLESCOPE(Isolate::Current()); |
| const Object& unwrapped_rp = Object::Handle(Api::UnwrapHandle(receivePort)); |
| @@ -524,10 +565,19 @@ void Service::HandleIsolateMessage(Isolate* isolate, const Instance& msg) { |
| IsolateMessageHandler handler = |
| FindIsolateMessageHandler(path_segment_c); |
| + if (handler == NULL) { |
| + // Check for an embedder handler. |
| + EmbedderServiceHandler* e_handler = FindEmbedderHandler(path_segment_c); |
| + if (e_handler != NULL) { |
| + JSONStream js; |
| + js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values); |
| + EmbedderHandleIsolateMessage(e_handler, &js); |
|
turnidge
2014/02/18 21:27:05
Do we want to allow for asynchronous replies? Sho
|
| + js.PostReply(); |
| + } |
| + } |
| { |
| JSONStream js; |
| js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values); |
| - |
| if (handler == NULL) { |
| PrintError(&js, "Unrecognized path"); |
| js.PostReply(); |
| @@ -1156,4 +1206,61 @@ static RootMessageHandler FindRootMessageHandler(const char* command) { |
| return NULL; |
| } |
| + |
| +void Service::EmbedderHandleIsolateMessage(EmbedderServiceHandler* handler, |
| + JSONStream* js) { |
| + ASSERT(handler != NULL); |
| + Dart_ServiceRequestCallback callback = handler->callback(); |
| + ASSERT(callback != NULL); |
| + const char* r = NULL; |
| + const char* name = js->command(); |
| + const char** arguments = js->arguments(); |
| + const char** keys = js->option_keys(); |
| + const char** values = js->option_values(); |
| + r = callback(name, arguments, js->num_arguments(), keys, values, |
| + js->num_options(), handler->user_data()); |
| + ASSERT(r != NULL); |
| + // TODO(johnmccutchan): Allow for NULL returns? |
| + TextBuffer* buffer = js->buffer(); |
| + buffer->AddString(r); |
| + free(const_cast<char*>(r)); |
| +} |
| + |
| + |
| +void Service::RegisterEmbedderCallback(const char* name, |
| + Dart_ServiceRequestCallback callback, |
| + void* user_data) { |
|
turnidge
2014/02/18 21:27:05
Add a heartbeat unit test for embedder callbacks i
Cutch
2014/02/18 22:18:51
Done.
|
| + if (name == NULL) { |
| + return; |
| + } |
| + EmbedderServiceHandler* handler = FindEmbedderHandler(name); |
| + if (handler != NULL) { |
| + // Update existing handler entry. |
| + handler->set_callback(callback); |
| + handler->set_user_data(user_data); |
| + return; |
| + } |
| + // Create a new handler. |
| + handler = new EmbedderServiceHandler(name); |
| + handler->set_callback(callback); |
| + handler->set_user_data(user_data); |
| + |
| + // Insert into list. |
| + handler->set_next(service_handler_head_); |
| + service_handler_head_ = handler; |
| +} |
| + |
| + |
| +EmbedderServiceHandler* Service::FindEmbedderHandler( |
| + const char* name) { |
| + EmbedderServiceHandler* current = service_handler_head_; |
| + while (current != NULL) { |
| + if (!strcmp(name, current->name())) { |
| + return current; |
| + } |
| + } |
| + return NULL; |
| +} |
| + |
| + |
| } // namespace dart |