22// Use of this source code is governed by a BSD-style license that can be
33// found in the LICENSE file.
44
5- #include " flutter/lib/ui/plugins/callback_cache.h"
5+ #include < fstream>
6+ #include < iterator>
7+
8+ #include " flutter/fml/build_config.h"
69#include " flutter/fml/logging.h"
10+ #include " flutter/fml/paths.h"
11+ #include " flutter/lib/ui/plugins/callback_cache.h"
12+ #include " third_party/rapidjson/rapidjson/document.h"
13+ #include " third_party/rapidjson/rapidjson/stringbuffer.h"
14+ #include " third_party/rapidjson/rapidjson/writer.h"
715#include " third_party/tonic/converter/dart_converter.h"
816
17+ using rapidjson::Document;
18+ using rapidjson::StringBuffer;
19+ using rapidjson::Writer;
920using tonic::ToDart;
1021
1122namespace blink {
1223
24+ static const char * kHandleKey = " handle" ;
25+ static const char * kRepresentationKey = " representation" ;
26+ static const char * kNameKey = " name" ;
27+ static const char * kClassNameKey = " class_name" ;
28+ static const char * kLibraryPathKey = " library_path" ;
29+ static const char * kCacheName = " flutter_callback_cache.json" ;
1330std::mutex DartCallbackCache::mutex_;
31+ std::string DartCallbackCache::cache_path_;
1432std::map<int64_t , DartCallbackRepresentation> DartCallbackCache::cache_;
1533
34+ void DartCallbackCache::SetCachePath (const std::string& path) {
35+ cache_path_ = fml::paths::JoinPaths ({path, kCacheName });
36+ }
37+
1638Dart_Handle DartCallbackCache::GetCallback (int64_t handle) {
1739 std::lock_guard<std::mutex> lock (mutex_);
1840 auto iterator = cache_.find (handle);
@@ -34,6 +56,7 @@ int64_t DartCallbackCache::GetCallbackHandle(const std::string& name,
3456
3557 if (cache_.find (hash) == cache_.end ()) {
3658 cache_[hash] = {name, class_name, library_path};
59+ SaveCacheToDisk ();
3760 }
3861 return hash;
3962}
@@ -48,6 +71,82 @@ DartCallbackCache::GetCallbackInformation(int64_t handle) {
4871 return nullptr ;
4972}
5073
74+ void DartCallbackCache::SaveCacheToDisk () {
75+ // Cache JSON format
76+ // [
77+ // {
78+ // "hash": 42,
79+ // "representation": {
80+ // "name": "...",
81+ // "class_name": "...",
82+ // "library_path": "..."
83+ // }
84+ // },
85+ // {
86+ // ...
87+ // }
88+ // ]
89+ StringBuffer s;
90+ Writer<StringBuffer> writer (s);
91+ writer.StartArray ();
92+ for (auto iterator = cache_.begin (); iterator != cache_.end (); ++iterator) {
93+ int64_t hash = iterator->first ;
94+ DartCallbackRepresentation cb = iterator->second ;
95+ writer.StartObject ();
96+ writer.Key (kHandleKey );
97+ writer.Int64 (hash);
98+ writer.Key (kRepresentationKey );
99+ writer.StartObject ();
100+ writer.Key (kNameKey );
101+ writer.String (cb.name .c_str ());
102+ writer.Key (kClassNameKey );
103+ writer.String (cb.class_name .c_str ());
104+ writer.Key (kLibraryPathKey );
105+ writer.String (cb.library_path .c_str ());
106+ writer.EndObject ();
107+ writer.EndObject ();
108+ }
109+ writer.EndArray ();
110+
111+ std::ofstream output (cache_path_);
112+ output << s.GetString ();
113+ output.close ();
114+ }
115+
116+ void DartCallbackCache::LoadCacheFromDisk () {
117+ std::lock_guard<std::mutex> lock (mutex_);
118+
119+ // Don't reload the cache if it's already populated.
120+ if (!cache_.empty ()) {
121+ return ;
122+ }
123+ std::ifstream input (cache_path_);
124+ if (!input) {
125+ return ;
126+ }
127+ std::string cache_contents{std::istreambuf_iterator<char >(input),
128+ std::istreambuf_iterator<char >()};
129+ Document d;
130+ d.Parse (cache_contents.c_str ());
131+ if (d.HasParseError () || !d.IsArray ()) {
132+ FML_LOG (WARNING) << " Could not parse callback cache, aborting restore" ;
133+ // TODO(bkonyi): log and bail (delete cache?)
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 ();
142+ DartCallbackRepresentation cb;
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+
51150Dart_Handle DartCallbackCache::LookupDartClosure (
52151 const std::string& name,
53152 const std::string& class_name,
0 commit comments