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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/service.h ('k') | runtime/vm/service_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/service.cc
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 7596e7aab7f683d8eeaaef25bc719fbc61f5ee18..2c231cd047c9e37b3894941b93025b6a2342aef8 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,13 @@ static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name,
}
+EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL;
+EmbedderServiceHandler* Service::root_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));
@@ -527,13 +569,20 @@ void Service::HandleIsolateMessage(Isolate* isolate, const Instance& msg) {
{
JSONStream js;
js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values);
-
if (handler == NULL) {
- PrintError(&js, "Unrecognized path");
+ // Check for an embedder handler.
+ EmbedderServiceHandler* e_handler =
+ FindIsolateEmbedderHandler(path_segment_c);
+ if (e_handler != NULL) {
+ EmbedderHandleMessage(e_handler, &js);
+ } else {
+ PrintError(&js, "Unrecognized path");
+ }
js.PostReply();
} else {
if (handler(isolate, &js)) {
// Handler returns true if the reply is ready to be posted.
+ // TODO(johnmccutchan): Support asynchronous replies.
js.PostReply();
}
}
@@ -1096,21 +1145,33 @@ void Service::HandleRootMessage(const Instance& msg) {
ASSERT(option_keys.Length() == option_values.Length());
String& path_segment = String::Handle();
- path_segment ^= path.At(0);
+ if (path.Length() > 0) {
+ path_segment ^= path.At(0);
+ } else {
+ path_segment ^= Symbols::Empty().raw();
+ }
ASSERT(!path_segment.IsNull());
const char* path_segment_c = path_segment.ToCString();
+
RootMessageHandler handler =
FindRootMessageHandler(path_segment_c);
-
{
JSONStream js;
js.Setup(zone.GetZone(), reply_port, path, option_keys, option_values);
if (handler == NULL) {
- PrintError(&js, "Unrecognized path");
+ // Check for an embedder handler.
+ EmbedderServiceHandler* e_handler =
+ FindRootEmbedderHandler(path_segment_c);
+ if (e_handler != NULL) {
+ EmbedderHandleMessage(e_handler, &js);
+ } else {
+ PrintError(&js, "Unrecognized path");
+ }
js.PostReply();
} else {
if (handler(&js)) {
// Handler returns true if the reply is ready to be posted.
+ // TODO(johnmccutchan): Support asynchronous replies.
js.PostReply();
}
}
@@ -1156,4 +1217,100 @@ static RootMessageHandler FindRootMessageHandler(const char* command) {
return NULL;
}
+
+void Service::EmbedderHandleMessage(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::RegisterIsolateEmbedderCallback(
+ const char* name,
+ Dart_ServiceRequestCallback callback,
+ void* user_data) {
+ if (name == NULL) {
+ return;
+ }
+ EmbedderServiceHandler* handler = FindIsolateEmbedderHandler(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 isolate_service_handler_head_ list.
+ handler->set_next(isolate_service_handler_head_);
+ isolate_service_handler_head_ = handler;
+}
+
+
+EmbedderServiceHandler* Service::FindIsolateEmbedderHandler(
+ const char* name) {
+ EmbedderServiceHandler* current = isolate_service_handler_head_;
+ while (current != NULL) {
+ if (!strcmp(name, current->name())) {
+ return current;
+ }
+ current = current->next();
+ }
+ return NULL;
+}
+
+
+void Service::RegisterRootEmbedderCallback(
+ const char* name,
+ Dart_ServiceRequestCallback callback,
+ void* user_data) {
+ if (name == NULL) {
+ return;
+ }
+ EmbedderServiceHandler* handler = FindRootEmbedderHandler(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 root_service_handler_head_ list.
+ handler->set_next(root_service_handler_head_);
+ root_service_handler_head_ = handler;
+}
+
+
+EmbedderServiceHandler* Service::FindRootEmbedderHandler(
+ const char* name) {
+ EmbedderServiceHandler* current = root_service_handler_head_;
+ while (current != NULL) {
+ if (!strcmp(name, current->name())) {
+ return current;
+ }
+ current = current->next();
+ }
+ return NULL;
+}
+
} // namespace dart
« 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