Flutter Engine
 
Loading...
Searching...
No Matches
service_protocol.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#define RAPIDJSON_HAS_STDSTRING 1
6
8
9#include <cstring>
10#include <sstream>
11#include <string>
12#include <utility>
13#include <vector>
14
17#include "rapidjson/stringbuffer.h"
18#include "rapidjson/writer.h"
19#include "third_party/dart/runtime/include/dart_tools_api.h"
20
21namespace flutter {
22
23const std::string_view ServiceProtocol::kScreenshotExtensionName =
24 "_flutter.screenshot";
26 "_flutter.screenshotSkp";
27const std::string_view ServiceProtocol::kRunInViewExtensionName =
28 "_flutter.runInView";
30 "_flutter.flushUIThreadTasks";
32 "_flutter.setAssetBundlePath";
34 "_flutter.getDisplayRefreshRate";
35const std::string_view ServiceProtocol::kGetSkSLsExtensionName =
36 "_flutter.getSkSLs";
37const std::string_view
39 "_flutter.estimateRasterCacheMemory";
40const std::string_view ServiceProtocol::kReloadAssetFonts =
41 "_flutter.reloadAssetFonts";
42
43static constexpr std::string_view kViewIdPrefx = "_flutterView/";
44static constexpr std::string_view kListViewsExtensionName =
45 "_flutter.listViews";
46
63
67
69 const Handler::Description& description) {
70 std::unique_lock lock(handlers_mutex_);
71 handlers_.emplace(handler, description);
72}
73
75 std::unique_lock lock(handlers_mutex_);
76 handlers_.erase(handler);
77}
78
81 const Handler::Description& description) {
82 std::shared_lock lock(handlers_mutex_);
83 auto it = handlers_.find(handler);
84 if (it != handlers_.end()) {
85 it->second.Store(description);
86 }
87}
88
90 for (const auto& endpoint : endpoints_) {
91 Dart_RegisterIsolateServiceRequestCallback(
92 endpoint.data(), // method
93 &ServiceProtocol::HandleMessage, // callback
94 set ? this : nullptr // user data
95 );
96 }
97}
98
99static void WriteServerErrorResponse(rapidjson::Document* document,
100 const char* message) {
101 document->SetObject();
102 document->AddMember("code", -32000, document->GetAllocator());
103 rapidjson::Value message_value;
104 message_value.SetString(message, document->GetAllocator());
105 document->AddMember("message", message_value, document->GetAllocator());
106}
107
108bool ServiceProtocol::HandleMessage(const char* method,
109 const char** param_keys,
110 const char** param_values,
111 intptr_t num_params,
112 void* user_data,
113 const char** json_object) {
115 for (intptr_t i = 0; i < num_params; i++) {
116 params[std::string_view{param_keys[i]}] = std::string_view{param_values[i]};
117 }
118
119#ifndef NDEBUG
120 FML_DLOG(INFO) << "Service protcol method: " << method;
121 FML_DLOG(INFO) << "Arguments: " << params.size();
122 for (intptr_t i = 0; i < num_params; i++) {
123 FML_DLOG(INFO) << " " << i + 1 << ": " << param_keys[i] << " = "
124 << param_values[i];
125 }
126#endif // NDEBUG
127
128 rapidjson::Document document;
129 bool result = HandleMessage(std::string_view{method}, //
130 params, //
131 static_cast<ServiceProtocol*>(user_data), //
132 &document //
133 );
134 rapidjson::StringBuffer buffer;
135 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
136 document.Accept(writer);
137 *json_object = fml::strdup(buffer.GetString());
138
139#ifndef NDEBUG
140 FML_DLOG(INFO) << "Response: " << *json_object;
141 FML_DLOG(INFO) << "RPC Result: " << result;
142#endif // NDEBUG
143
144 return result;
145}
146
147bool ServiceProtocol::HandleMessage(std::string_view method,
148 const Handler::ServiceProtocolMap& params,
149 ServiceProtocol* service_protocol,
150 rapidjson::Document* response) {
151 if (service_protocol == nullptr) {
152 WriteServerErrorResponse(response, "Service protocol unavailable.");
153 return false;
154 }
155
156 return service_protocol->HandleMessage(method, params, response);
157}
158
159[[nodiscard]] static bool HandleMessageOnHandler(
161 std::string_view method,
163 rapidjson::Document* document) {
166 bool result = false;
168 handler->GetServiceProtocolHandlerTaskRunner(method),
169 [&latch, //
170 &result, //
171 &handler, //
172 &method, //
173 &params, //
174 &document //
175 ]() {
176 result =
177 handler->HandleServiceProtocolMessage(method, params, document);
178 latch.Signal();
179 });
180 latch.Wait();
181 return result;
182}
183
184bool ServiceProtocol::HandleMessage(std::string_view method,
185 const Handler::ServiceProtocolMap& params,
186 rapidjson::Document* response) const {
187 if (method == kListViewsExtensionName) {
188 // So far, this is the only built-in method that does not forward to the
189 // dynamic set of handlers.
190 return HandleListViewsMethod(response);
191 }
192
193 std::shared_lock lock(handlers_mutex_);
194
195 if (handlers_.empty()) {
197 "There are no running service protocol handlers.");
198 return false;
199 }
200
201 // Find the handler by its "viewId" in the params.
202 auto view_id_param_found = params.find(std::string_view{"viewId"});
203 if (view_id_param_found != params.end()) {
204 auto* handler = reinterpret_cast<Handler*>(std::stoull(
205 view_id_param_found->second.data() + kViewIdPrefx.size(), nullptr, 16));
206 auto handler_found = handlers_.find(handler);
207 if (handler_found != handlers_.end()) {
208 return HandleMessageOnHandler(handler, method, params, response);
209 }
210 }
211
212 // Handle legacy calls that do not specify a handler in their args.
213 // TODO(chinmaygarde): Deprecate these calls in the tools and remove these
214 // fallbacks.
215 if (method == kScreenshotExtensionName ||
216 method == kScreenshotSkpExtensionName ||
218 return HandleMessageOnHandler(handlers_.begin()->first, method, params,
219 response);
220 }
221
223 response,
224 "Service protocol could not handle or find a handler for the "
225 "requested method.");
226 return false;
227}
228
229static std::string CreateFlutterViewID(intptr_t handler) {
230 std::stringstream stream;
231 stream << kViewIdPrefx << "0x" << std::hex << handler;
232 return stream.str();
233}
234
235static std::string CreateIsolateID(int64_t isolate) {
236 std::stringstream stream;
237 stream << "isolates/" << isolate;
238 return stream.str();
239}
240
243 rapidjson::Value& view,
244 rapidjson::MemoryPoolAllocator<>& allocator) const {
245 view.SetObject();
246 view.AddMember("type", "FlutterView", allocator);
247 view.AddMember("id", CreateFlutterViewID(reinterpret_cast<intptr_t>(handler)),
248 allocator);
249 if (isolate_port != 0) {
250 rapidjson::Value isolate(rapidjson::Type::kObjectType);
251 {
252 isolate.AddMember("type", "@Isolate", allocator);
253 isolate.AddMember("fixedId", true, allocator);
254 isolate.AddMember("id", CreateIsolateID(isolate_port), allocator);
255 isolate.AddMember("name", isolate_name, allocator);
256 isolate.AddMember("number", isolate_port, allocator);
257 }
258 view.AddMember("isolate", isolate, allocator);
259 }
260}
261
262bool ServiceProtocol::HandleListViewsMethod(
263 rapidjson::Document* response) const {
264 std::shared_lock lock(handlers_mutex_);
265 std::vector<std::pair<intptr_t, Handler::Description>> descriptions;
266 descriptions.reserve(handlers_.size());
267 for (const auto& handler : handlers_) {
268 descriptions.emplace_back(reinterpret_cast<intptr_t>(handler.first),
269 handler.second.Load());
270 }
271
272 auto& allocator = response->GetAllocator();
273
274 // Construct the response objects.
275 response->SetObject();
276 response->AddMember("type", "FlutterViewList", allocator);
277
278 rapidjson::Value viewsList(rapidjson::Type::kArrayType);
279 for (const auto& description : descriptions) {
280 rapidjson::Value view(rapidjson::Type::kObjectType);
281 description.second.Write(reinterpret_cast<Handler*>(description.first),
282 view, allocator);
283 viewsList.PushBack(view, allocator);
284 }
285
286 response->AddMember("views", viewsList, allocator);
287
288 return true;
289}
290
291} // namespace flutter
std::map< std::string_view, std::string_view > ServiceProtocolMap
void AddHandler(Handler *handler, const Handler::Description &description)
static const std::string_view kSetAssetBundlePathExtensionName
static const std::string_view kReloadAssetFonts
static const std::string_view kScreenshotSkpExtensionName
static const std::string_view kScreenshotExtensionName
static const std::string_view kGetDisplayRefreshRateExtensionName
static const std::string_view kRunInViewExtensionName
static const std::string_view kEstimateRasterCacheMemoryExtensionName
static const std::string_view kGetSkSLsExtensionName
void RemoveHandler(Handler *handler)
void SetHandlerDescription(Handler *handler, const Handler::Description &description)
static const std::string_view kFlushUIThreadTasksExtensionName
static void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
const EmbeddedViewParams * params
FlView * view
const gchar FlBinaryMessengerMessageHandler handler
G_BEGIN_DECLS GBytes * message
#define FML_DLOG(severity)
Definition logging.h:121
#define FML_DCHECK(condition)
Definition logging.h:122
static std::string CreateIsolateID(int64_t isolate)
static std::string CreateFlutterViewID(intptr_t handler)
static void WriteServerErrorResponse(rapidjson::Document *document, const char *message)
static constexpr std::string_view kListViewsExtensionName
static constexpr std::string_view kViewIdPrefx
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
Definition switch_defs.h:71
static bool HandleMessageOnHandler(ServiceProtocol::Handler *handler, std::string_view method, const ServiceProtocol::Handler::ServiceProtocolMap &params, rapidjson::Document *document)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
char * strdup(const char *str1)
void Write(Handler *handler, rapidjson::Value &value, rapidjson::MemoryPoolAllocator<> &allocator) const