Index: runtime/vm/service.cc |
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc |
index 61d0e07f91a60d8908eb891bee0dc2ec01beabcd..ae4ce21dc172e3b407d1e1f5401df69192d950e1 100644 |
--- a/runtime/vm/service.cc |
+++ b/runtime/vm/service.cc |
@@ -585,6 +585,15 @@ void Service::InvokeMethod(Isolate* isolate, const Array& msg) { |
return; |
} |
+ if (ExtensionHandlerExists(method_name)) { |
+ const Array& response = |
+ Array::Handle(Array::New(3)); |
+ InvokeExtensionHandler(method_name, param_keys, param_values, response); |
+ PostExtensionResponse(response, &js); |
+ js.PostReply(); |
+ return; |
+ } |
+ |
PrintUnrecognizedMethodError(&js); |
js.PostReply(); |
return; |
@@ -869,6 +878,78 @@ EmbedderServiceHandler* Service::FindRootEmbedderHandler( |
} |
+#define EXTENSION_HANDLER_RESPONSE_LENGTH 3 |
+ |
+bool Service::ExtensionHandlerExists(const String& method) { |
+ ASSERT(!method.IsNull()); |
+ const Library& developer_lib = Library::Handle(Library::DeveloperLibrary()); |
+ ASSERT(!developer_lib.IsNull()); |
+ const Function& extension_exists = Function::Handle( |
+ developer_lib.LookupLocalFunction(Symbols::_extensionExists())); |
+ ASSERT(!extension_exists.IsNull()); |
+ const Array& arguments = Array::Handle(Array::New(1)); |
+ ASSERT(!arguments.IsNull()); |
+ arguments.SetAt(0, method); |
+ return (DartEntry::InvokeFunction(extension_exists, arguments) == |
+ Object::bool_true().raw()); |
+} |
+ |
+ |
+bool Service::InvokeExtensionHandler(const String& method_name, |
+ const Array& parameter_keys, |
+ const Array& parameter_values, |
+ const Array& response) { |
+ ASSERT(!method_name.IsNull()); |
+ ASSERT(!parameter_keys.IsNull()); |
+ ASSERT(!parameter_values.IsNull()); |
+ ASSERT(!response.IsNull()); |
+ ASSERT(response.Length() == EXTENSION_HANDLER_RESPONSE_LENGTH); |
+ const Library& developer_lib = Library::Handle(Library::DeveloperLibrary()); |
+ ASSERT(!developer_lib.IsNull()); |
+ const Function& invoke_extension = Function::Handle( |
+ developer_lib.LookupLocalFunction(Symbols::_invokeExtension())); |
+ ASSERT(!invoke_extension.IsNull()); |
+ const Array& arguments = Array::Handle(Array::New(4)); |
+ arguments.SetAt(0, method_name); |
+ arguments.SetAt(1, parameter_keys); |
+ arguments.SetAt(2, parameter_values); |
+ arguments.SetAt(3, response); |
+ return (DartEntry::InvokeFunction(invoke_extension, arguments) == |
+ Object::bool_true().raw()); |
+} |
+ |
+ |
+void Service::PostExtensionResponse(const Array& response, JSONStream* js) { |
+ ASSERT(!response.IsNull()); |
+ ASSERT(response.Length() == EXTENSION_HANDLER_RESPONSE_LENGTH); |
+ const Object& result = Object::Handle(response.At(0)); |
+ const Object& error_code = Object::Handle(response.At(1)); |
+ const Object& error_message = Object::Handle(response.At(2)); |
+ if (!result.IsNull()) { |
+ if (!result.IsString()) { |
+ js->PrintError(kInternalError, |
+ "Extension error: response[0] must be a String."); |
+ return; |
+ } |
+ TextBuffer* buffer = js->buffer(); |
+ buffer->AddString(String::Cast(result).ToCString()); |
+ } else { |
+ if (!error_code.IsInteger()) { |
+ js->PrintError(kInternalError, |
+ "Extension error: response[1] must be an int."); |
+ return; |
+ } |
+ if (!error_message.IsString()) { |
+ js->PrintError(kInternalError, |
+ "Extension error: response[2] must be a String."); |
+ return; |
+ } |
+ js->PrintError(Integer::Cast(error_code).AsInt64Value(), |
+ String::Cast(error_message).ToCString()); |
+ } |
+} |
+ |
+ |
static const MethodParameter* get_isolate_params[] = { |
ISOLATE_PARAMETER, |
NULL, |