Flutter Engine
The Flutter Engine
callback_cache.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#include "flutter/lib/ui/plugins/callback_cache.h"
6
7#include <fstream>
8#include <iterator>
9
10#include "flutter/fml/build_config.h"
11#include "flutter/fml/logging.h"
12#include "flutter/fml/paths.h"
13#include "rapidjson/document.h"
14#include "rapidjson/stringbuffer.h"
15#include "rapidjson/writer.h"
17
18using rapidjson::Document;
19using rapidjson::StringBuffer;
20using rapidjson::Writer;
21using tonic::ToDart;
22
23namespace flutter {
24
25static const char* kHandleKey = "handle";
26static const char* kRepresentationKey = "representation";
27static const char* kNameKey = "name";
28static const char* kClassNameKey = "class_name";
29static const char* kLibraryPathKey = "library_path";
30static const char* kCacheName = "flutter_callback_cache.json";
31std::mutex DartCallbackCache::mutex_;
32std::string DartCallbackCache::cache_path_;
33std::map<int64_t, DartCallbackRepresentation> DartCallbackCache::cache_;
34
35void DartCallbackCache::SetCachePath(const std::string& path) {
36 cache_path_ = fml::paths::JoinPaths({path, kCacheName});
37}
38
40 std::scoped_lock lock(mutex_);
41 auto iterator = cache_.find(handle);
42 if (iterator != cache_.end()) {
43 DartCallbackRepresentation cb = iterator->second;
44 return LookupDartClosure(cb.name, cb.class_name, cb.library_path);
45 }
46 return Dart_Null();
47}
48
49int64_t DartCallbackCache::GetCallbackHandle(const std::string& name,
50 const std::string& class_name,
51 const std::string& library_path) {
52 std::scoped_lock lock(mutex_);
53 std::hash<std::string> hasher;
54 int64_t hash = hasher(name);
55 hash += hasher(class_name);
56 hash += hasher(library_path);
57
58 if (cache_.find(hash) == cache_.end()) {
59 cache_[hash] = {name, class_name, library_path};
60 SaveCacheToDisk();
61 }
62 return hash;
63}
64
65std::unique_ptr<DartCallbackRepresentation>
67 std::scoped_lock lock(mutex_);
68 auto iterator = cache_.find(handle);
69 if (iterator != cache_.end()) {
70 return std::make_unique<DartCallbackRepresentation>(iterator->second);
71 }
72 return nullptr;
73}
74
75void DartCallbackCache::SaveCacheToDisk() {
76 // Cache JSON format
77 // [
78 // {
79 // "hash": 42,
80 // "representation": {
81 // "name": "...",
82 // "class_name": "...",
83 // "library_path": "..."
84 // }
85 // },
86 // {
87 // ...
88 // }
89 // ]
91 Writer<StringBuffer> writer(s);
92 writer.StartArray();
93 for (auto iterator = cache_.begin(); iterator != cache_.end(); ++iterator) {
94 int64_t hash = iterator->first;
95 DartCallbackRepresentation cb = iterator->second;
96 writer.StartObject();
97 writer.Key(kHandleKey);
98 writer.Int64(hash);
99 writer.Key(kRepresentationKey);
100 writer.StartObject();
101 writer.Key(kNameKey);
102 writer.String(cb.name.c_str());
103 writer.Key(kClassNameKey);
104 writer.String(cb.class_name.c_str());
105 writer.Key(kLibraryPathKey);
106 writer.String(cb.library_path.c_str());
107 writer.EndObject();
108 writer.EndObject();
109 }
110 writer.EndArray();
111
112 std::ofstream output(cache_path_);
113 output << s.GetString();
114 output.close();
115}
116
118 std::scoped_lock lock(mutex_);
119
120 // Don't reload the cache if it's already populated.
121 if (!cache_.empty()) {
122 return;
123 }
124 std::ifstream input(cache_path_);
125 if (!input) {
126 return;
127 }
128 std::string cache_contents{std::istreambuf_iterator<char>(input),
129 std::istreambuf_iterator<char>()};
130 Document d;
131 d.Parse(cache_contents.c_str());
132 if (d.HasParseError() || !d.IsArray()) {
133 // Could not parse callback cache, aborting restore.
134 return;
135 }
136 const auto entries = d.GetArray();
137 for (auto* it = entries.begin(); it != entries.end(); ++it) {
138 const auto root_obj = it->GetObject();
139 const auto representation = root_obj[kRepresentationKey].GetObject();
140
141 const int64_t hash = root_obj[kHandleKey].GetInt64();
143 cb.name = representation[kNameKey].GetString();
144 cb.class_name = representation[kClassNameKey].GetString();
145 cb.library_path = representation[kLibraryPathKey].GetString();
146 cache_[hash] = cb;
147 }
148}
149
150Dart_Handle DartCallbackCache::LookupDartClosure(
151 const std::string& name,
152 const std::string& class_name,
153 const std::string& library_path) {
154 Dart_Handle closure_name = ToDart(name);
155 if (Dart_IsError(closure_name)) {
156 return closure_name;
157 }
158 Dart_Handle library_name =
159 library_path.empty() ? Dart_Null() : ToDart(library_path);
160 if (Dart_IsError(library_name)) {
161 return library_name;
162 }
163 Dart_Handle cls_name = class_name.empty() ? Dart_Null() : ToDart(class_name);
164 if (Dart_IsError(cls_name)) {
165 return cls_name;
166 }
167
168 Dart_Handle library;
169 if (library_name == Dart_Null()) {
170 library = Dart_RootLibrary();
171 } else {
172 library = Dart_LookupLibrary(library_name);
173 }
174 if (Dart_IsError(library)) {
175 return library;
176 }
177
179 if (Dart_IsNull(cls_name)) {
180 closure = Dart_GetField(library, closure_name);
181 } else {
182 Dart_Handle cls = Dart_GetClass(library, cls_name);
183 if (Dart_IsError(cls)) {
184 return cls;
185 }
186 if (Dart_IsNull(cls)) {
187 closure = Dart_Null();
188 } else {
189 closure = Dart_GetStaticMethodClosure(library, cls, closure_name);
190 }
191 }
192 return closure;
193}
194
195} // namespace flutter
static uint32_t hash(const SkShaderBase::GradientInfo &v)
static std::unique_ptr< DartCallbackRepresentation > GetCallbackInformation(int64_t handle)
static int64_t GetCallbackHandle(const std::string &name, const std::string &class_name, const std::string &library_path)
static Dart_Handle GetCallback(int64_t handle)
static void SetCachePath(const std::string &path)
DART_EXPORT Dart_Handle Dart_GetStaticMethodClosure(Dart_Handle library, Dart_Handle cls_type, Dart_Handle function_name)
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url)
DART_EXPORT Dart_Handle Dart_Null(void)
DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library, Dart_Handle class_name)
DART_EXPORT bool Dart_IsNull(Dart_Handle object)
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT Dart_Handle Dart_RootLibrary(void)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
struct MyStruct s
const char *const class_name
static const char * kCacheName
static const char * kHandleKey
static const char * kLibraryPathKey
static const char * kClassNameKey
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
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
static const char * kNameKey
static const char * kRepresentationKey
std::string JoinPaths(std::initializer_list< std::string > components)
Definition: paths.cc:14
std::function< void()> closure
Definition: closure.h:14
Dart_Handle ToDart(const T &object)