Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
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";
43 "_flutter.getPipelineUsage";
44
45static constexpr std::string_view kViewIdPrefx = "_flutterView/";
46static constexpr std::string_view kListViewsExtensionName =
47 "_flutter.listViews";
48
66
70
72 const Handler::Description& description) {
73 std::unique_lock lock(handlers_mutex_);
74 handlers_.emplace(handler, description);
75}
76
78 std::unique_lock lock(handlers_mutex_);
79 handlers_.erase(handler);
80}
81
84 const Handler::Description& description) {
85 std::shared_lock lock(handlers_mutex_);
86 auto it = handlers_.find(handler);
87 if (it != handlers_.end()) {
88 it->second.Store(description);
89 }
90}
91
93 for (const auto& endpoint : endpoints_) {
94 Dart_RegisterIsolateServiceRequestCallback(
95 endpoint.data(), // method
96 &ServiceProtocol::HandleMessage, // callback
97 set ? this : nullptr // user data
98 );
99 }
100}
101
102static void WriteServerErrorResponse(rapidjson::Document* document,
103 const char* message) {
104 document->SetObject();
105 document->AddMember("code", -32000, document->GetAllocator());
106 rapidjson::Value message_value;
107 message_value.SetString(message, document->GetAllocator());
108 document->AddMember("message", message_value, document->GetAllocator());
109}
110
111bool ServiceProtocol::HandleMessage(const char* method,
112 const char** param_keys,
113 const char** param_values,
114 intptr_t num_params,
115 void* user_data,
116 const char** json_object) {
118 for (intptr_t i = 0; i < num_params; i++) {
119 params[std::string_view{param_keys[i]}] = std::string_view{param_values[i]};
120 }
121
122#ifndef NDEBUG
123 FML_DLOG(INFO) << "Service protcol method: " << method;
124 FML_DLOG(INFO) << "Arguments: " << params.size();
125 for (intptr_t i = 0; i < num_params; i++) {
126 FML_DLOG(INFO) << " " << i + 1 << ": " << param_keys[i] << " = "
127 << param_values[i];
128 }
129#endif // NDEBUG
130
131 rapidjson::Document document;
132 bool result = HandleMessage(std::string_view{method}, //
133 params, //
134 static_cast<ServiceProtocol*>(user_data), //
135 &document //
136 );
137 rapidjson::StringBuffer buffer;
138 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
139 document.Accept(writer);
140 *json_object = fml::strdup(buffer.GetString());
141
142#ifndef NDEBUG
143 FML_DLOG(INFO) << "Response: " << *json_object;
144 FML_DLOG(INFO) << "RPC Result: " << result;
145#endif // NDEBUG
146
147 return result;
148}
149
150bool ServiceProtocol::HandleMessage(std::string_view method,
151 const Handler::ServiceProtocolMap& params,
152 ServiceProtocol* service_protocol,
153 rapidjson::Document* response) {
154 if (service_protocol == nullptr) {
155 WriteServerErrorResponse(response, "Service protocol unavailable.");
156 return false;
157 }
158
159 return service_protocol->HandleMessage(method, params, response);
160}
161
162[[nodiscard]] static bool HandleMessageOnHandler(
164 std::string_view method,
166 rapidjson::Document* document) {
169 bool result = false;
171 handler->GetServiceProtocolHandlerTaskRunner(method),
172 [&latch, //
173 &result, //
174 &handler, //
175 &method, //
176 &params, //
177 &document //
178 ]() {
179 result =
180 handler->HandleServiceProtocolMessage(method, params, document);
181 latch.Signal();
182 });
183 latch.Wait();
184 return result;
185}
186
187bool ServiceProtocol::HandleMessage(std::string_view method,
188 const Handler::ServiceProtocolMap& params,
189 rapidjson::Document* response) const {
190 if (method == kListViewsExtensionName) {
191 // So far, this is the only built-in method that does not forward to the
192 // dynamic set of handlers.
193 return HandleListViewsMethod(response);
194 }
195
196 std::shared_lock lock(handlers_mutex_);
197
198 if (handlers_.empty()) {
200 "There are no running service protocol handlers.");
201 return false;
202 }
203
204 // Find the handler by its "viewId" in the params.
205 auto view_id_param_found = params.find(std::string_view{"viewId"});
206 if (view_id_param_found != params.end()) {
207 auto* handler = reinterpret_cast<Handler*>(std::stoull(
208 view_id_param_found->second.data() + kViewIdPrefx.size(), nullptr, 16));
209 auto handler_found = handlers_.find(handler);
210 if (handler_found != handlers_.end()) {
211 return HandleMessageOnHandler(handler, method, params, response);
212 }
213 }
214
215 // Handle legacy calls that do not specify a handler in their args.
216 // TODO(chinmaygarde): Deprecate these calls in the tools and remove these
217 // fallbacks.
218 if (method == kScreenshotExtensionName ||
219 method == kScreenshotSkpExtensionName ||
221 return HandleMessageOnHandler(handlers_.begin()->first, method, params,
222 response);
223 }
224
226 response,
227 "Service protocol could not handle or find a handler for the "
228 "requested method.");
229 return false;
230}
231
232static std::string CreateFlutterViewID(intptr_t handler) {
233 std::stringstream stream;
234 stream << kViewIdPrefx << "0x" << std::hex << handler;
235 return stream.str();
236}
237
238static std::string CreateIsolateID(int64_t isolate) {
239 std::stringstream stream;
240 stream << "isolates/" << isolate;
241 return stream.str();
242}
243
246 rapidjson::Value& view,
247 rapidjson::MemoryPoolAllocator<>& allocator) const {
248 view.SetObject();
249 view.AddMember("type", "FlutterView", allocator);
250 view.AddMember("id", CreateFlutterViewID(reinterpret_cast<intptr_t>(handler)),
251 allocator);
252 if (isolate_port != 0) {
253 rapidjson::Value isolate(rapidjson::Type::kObjectType);
254 {
255 isolate.AddMember("type", "@Isolate", allocator);
256 isolate.AddMember("fixedId", true, allocator);
257 isolate.AddMember("id", CreateIsolateID(isolate_port), allocator);
258 isolate.AddMember("name", isolate_name, allocator);
259 isolate.AddMember("number", isolate_port, allocator);
260 }
261 view.AddMember("isolate", isolate, allocator);
262 }
263}
264
265bool ServiceProtocol::HandleListViewsMethod(
266 rapidjson::Document* response) const {
267 std::shared_lock lock(handlers_mutex_);
268 std::vector<std::pair<intptr_t, Handler::Description>> descriptions;
269 descriptions.reserve(handlers_.size());
270 for (const auto& handler : handlers_) {
271 descriptions.emplace_back(reinterpret_cast<intptr_t>(handler.first),
272 handler.second.Load());
273 }
274
275 auto& allocator = response->GetAllocator();
276
277 // Construct the response objects.
278 response->SetObject();
279 response->AddMember("type", "FlutterViewList", allocator);
280
281 rapidjson::Value viewsList(rapidjson::Type::kArrayType);
282 for (const auto& description : descriptions) {
283 rapidjson::Value view(rapidjson::Type::kObjectType);
284 description.second.Write(reinterpret_cast<Handler*>(description.first),
285 view, allocator);
286 viewsList.PushBack(view, allocator);
287 }
288
289 response->AddMember("views", viewsList, allocator);
290
291 return true;
292}
293
294} // namespace flutter
std::map< std::string_view, std::string_view > ServiceProtocolMap
static const std::string_view kGetPipelineUsageExtensionName
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 char * message
const gchar FlBinaryMessengerMessageHandler handler
#define FML_DLOG(severity)
Definition logging.h:121
#define FML_DCHECK(condition)
Definition logging.h:122
std::shared_ptr< ImpellerAllocator > allocator
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