Flutter Engine
The Flutter Engine
file_loader.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
6
7#include <iostream>
8#include <memory>
9#include <utility>
10
11#include "tonic/common/macros.h"
17
18namespace tonic {
19namespace {
20
21constexpr char kDartScheme[] = "dart:";
22
23constexpr char kFileScheme[] = "file:";
24constexpr size_t kFileSchemeLength = sizeof(kFileScheme) - 1;
25
26constexpr char kPackageScheme[] = "package:";
27constexpr size_t kPackageSchemeLength = sizeof(kPackageScheme) - 1;
28
29// Extract the scheme prefix ('package:' or 'file:' from )
30std::string ExtractSchemePrefix(std::string url) {
31 if (url.find(kPackageScheme) == 0u)
32 return kPackageScheme;
33 if (url.find(kFileScheme) == 0u)
34 return kFileScheme;
35 return std::string();
36}
37
38// Extract the path from a package: or file: url.
39std::string ExtractPath(std::string url) {
40 if (url.find(kPackageScheme) == 0u)
41 return url.substr(kPackageSchemeLength);
42 if (url.find(kFileScheme) == 0u)
43 return url.substr(kFileSchemeLength);
44 return url;
45}
46
47} // namespace
48
49FileLoader::FileLoader(int dirfd) : dirfd_(dirfd) {}
50
52 for (auto kernel_buffer : kernel_buffers_)
53 free(kernel_buffer);
54
55 if (dirfd_ >= 0)
56 close(dirfd_);
57}
58
59std::string FileLoader::SanitizeURIEscapedCharacters(const std::string& str) {
60 std::string result;
61 result.reserve(str.size());
62 for (std::string::size_type i = 0; i < str.size(); ++i) {
63 if (str[i] == '%') {
64 if (i > str.size() - 3 || !isxdigit(str[i + 1]) || !isxdigit(str[i + 2]))
65 return "";
66 const std::string hex = str.substr(i + 1, 2);
67 const unsigned char c = strtoul(hex.c_str(), nullptr, 16);
68 if (!c)
69 return "";
70 result += c;
71 i += 2;
72 } else {
73 result += str[i];
74 }
75 }
76 return result;
77}
78
79bool FileLoader::LoadPackagesMap(const std::string& packages) {
80 packages_ = packages;
81 std::string packages_source;
82 if (!ReadFileToString(packages_, &packages_source)) {
83 tonic::Log("error: Unable to load .packages file '%s'.", packages_.c_str());
84 return false;
85 }
86 packages_map_.reset(new PackagesMap());
87 std::string error;
88 if (!packages_map_->Parse(packages_source, &error)) {
89 tonic::Log("error: Unable to parse .packages file '%s'. %s",
90 packages_.c_str(), error.c_str());
91 return false;
92 }
93 return true;
94}
95
96std::string FileLoader::GetFilePathForPackageURL(std::string url) {
97 if (!packages_map_)
98 return std::string();
99 TONIC_DCHECK(url.find(kPackageScheme) == 0u);
100 url = url.substr(kPackageSchemeLength);
101
102 size_t slash = url.find(FileLoader::kPathSeparator);
103 if (slash == std::string::npos)
104 return std::string();
105 std::string package = url.substr(0, slash);
106 std::string library_path = url.substr(slash + 1);
107 std::string package_path = packages_map_->Resolve(package);
108 if (package_path.empty())
109 return std::string();
110 if (package_path.find(FileLoader::kFileURLPrefix) == 0u)
111 return SanitizePath(package_path.substr(FileLoader::kFileURLPrefixLength) +
112 library_path);
114 FileLoader::kPathSeparator + package_path +
115 FileLoader::kPathSeparator + library_path;
116}
117
119 Dart_Handle library,
120 Dart_Handle url) {
121 TONIC_DCHECK(Dart_IsNull(library) || Dart_IsLibrary(library) ||
122 Dart_IsString(library));
124 if (tag == Dart_kCanonicalizeUrl)
125 return CanonicalizeURL(library, url);
126 if (tag == Dart_kKernelTag)
127 return Kernel(url);
128 if (tag == Dart_kImportTag)
129 return Import(url);
130 return Dart_NewApiError("Unknown library tag.");
131}
132
134 std::string string = StdStringFromDart(url);
135 if (string.find(kDartScheme) == 0u)
136 return url;
137 if (string.find(kPackageScheme) == 0u)
138 return StdStringToDart(SanitizePath(string));
139
140 if (string.find(kFileScheme) == 0u) {
141 return StdStringToDart(SanitizeURIEscapedCharacters(string));
142 }
143
144 std::string library_url = StdStringFromDart(Dart_LibraryUrl(library));
145 std::string prefix = ExtractSchemePrefix(library_url);
146 std::string base_path = ExtractPath(library_url);
147 std::string simplified_path =
150 return StdStringToDart(SanitizePath(prefix + simplified_path));
151}
152
153std::string FileLoader::GetFilePathForURL(std::string url) {
154 if (url.find(kPackageScheme) == 0u)
155 return GetFilePathForPackageURL(std::move(url));
156 if (url.find(kFileScheme) == 0u)
157 return GetFilePathForFileURL(std::move(url));
158 return url;
159}
160
161Dart_Handle FileLoader::FetchBytes(const std::string& url,
162 uint8_t*& buffer,
163 intptr_t& buffer_size) {
164 buffer = nullptr;
165 buffer_size = -1;
166
167 std::string path = filesystem::SimplifyPath(GetFilePathForURL(url));
168 if (path.empty()) {
169 std::string error_message = "error: Unable to read '" + url + "'.";
171 Dart_NewStringFromCString(error_message.c_str()));
172 }
173 std::string absolute_path = filesystem::GetAbsoluteFilePath(path);
174 auto result = filesystem::ReadFileToBytes(absolute_path);
175 if (result.first == nullptr) {
176 std::string error_message =
177 "error: Unable to read '" + absolute_path + "'.";
179 Dart_NewStringFromCString(error_message.c_str()));
180 }
181 buffer = result.first;
182 buffer_size = result.second;
183 return Dart_True();
184}
185
187 std::string url_string = StdStringFromDart(url);
188 uint8_t* buffer = nullptr;
189 intptr_t buffer_size = -1;
191 if (Dart_IsError(result)) {
192 return result;
193 }
194 // The embedder must keep the buffer alive until isolate shutdown.
195 kernel_buffers_.push_back(buffer);
197}
198
199namespace {
200void MallocFinalizer(void* isolate_callback_data, void* peer) {
201 free(peer);
202}
203} // namespace
204
206 std::string url_string = StdStringFromDart(url);
207 uint8_t* buffer = nullptr;
208 intptr_t buffer_size = -1;
210 if (Dart_IsError(result)) {
211 return result;
212 }
213 result =
216 return result;
217}
218
219// This is invoked upon a reload request.
221 if (url == Dart_Null()) {
222 // No packages url specified.
224 return;
225 }
226 const std::string& packages_url = StdStringFromDart(url);
227 LoadPackagesMap(packages_url);
228}
229
230std::string FileLoader::GetFilePathForFileURL(std::string url) {
232 return SanitizePath(url.substr(FileLoader::kFileURLPrefixLength));
233}
234
235std::string FileLoader::GetFileURLForPath(const std::string& path) {
236 return std::string(FileLoader::kFileURLPrefix) + path;
237}
238
239} // namespace tonic
static uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment)
int find(T *array, int N, T item)
const std::string & packages() const
Definition: file_loader.h:27
FileLoader(int dirfd=-1)
Definition: file_loader.cc:49
Dart_Handle Import(Dart_Handle url)
Definition: file_loader.cc:186
void SetPackagesUrl(Dart_Handle url)
Definition: file_loader.cc:220
static const char kFileURLPrefix[]
Definition: file_loader.h:42
bool LoadPackagesMap(const std::string &packages)
Definition: file_loader.cc:79
Dart_Handle HandleLibraryTag(Dart_LibraryTag tag, Dart_Handle library, Dart_Handle url)
Definition: file_loader.cc:118
static const size_t kFileURLPrefixLength
Definition: file_loader.h:43
Dart_Handle CanonicalizeURL(Dart_Handle library, Dart_Handle url)
Definition: file_loader.cc:133
Dart_Handle Kernel(Dart_Handle url)
Definition: file_loader.cc:205
Dart_Handle FetchBytes(const std::string &url, uint8_t *&buffer, intptr_t &buffer_size)
Definition: file_loader.cc:161
static const std::string kPathSeparator
Definition: file_loader.h:44
DART_EXPORT Dart_FinalizableHandle Dart_NewFinalizableHandle(Dart_Handle object, void *peer, intptr_t external_allocation_size, Dart_HandleFinalizer callback)
DART_EXPORT Dart_Handle Dart_NewExternalTypedData(Dart_TypedData_Type type, void *data, intptr_t length)
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
DART_EXPORT Dart_Handle Dart_True(void)
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_LoadLibraryFromKernel(const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
@ Dart_TypedData_kUint8
Definition: dart_api.h:2615
DART_EXPORT Dart_Handle Dart_NewApiError(const char *error)
DART_EXPORT Dart_Handle Dart_Null(void)
Dart_LibraryTag
Definition: dart_api.h:3419
@ Dart_kImportTag
Definition: dart_api.h:3421
@ Dart_kCanonicalizeUrl
Definition: dart_api.h:3420
@ Dart_kKernelTag
Definition: dart_api.h:3422
DART_EXPORT bool Dart_IsNull(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char *str)
DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT bool Dart_IsString(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception)
DART_EXPORT bool Dart_IsLibrary(Dart_Handle object)
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
static void MallocFinalizer(void *isolate_callback_data, void *peer)
std::string AbsolutePath(const std::string &path)
Definition: path_posix.cc:147
std::string GetAbsoluteFilePath(const std::string &path)
Definition: path_posix.cc:176
std::string GetDirectoryName(const std::string &path)
Definition: path_posix.cc:160
std::string SimplifyPath(std::string path)
Definition: path_posix.cc:48
std::pair< uint8_t *, intptr_t > ReadFileToBytes(const std::string &path)
Definition: file.cc:94
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 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 vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
Dart_Handle StdStringToDart(const std::string &val)
void Log(const char *format,...)
Definition: log.cc:19
std::string StdStringFromDart(Dart_Handle handle)
#define TONIC_DCHECK
Definition: macros.h:32