Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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)
Dart_Handle Import(Dart_Handle url)
void SetPackagesUrl(Dart_Handle url)
static const char kFileURLPrefix[]
Definition file_loader.h:42
bool LoadPackagesMap(const std::string &packages)
Dart_Handle HandleLibraryTag(Dart_LibraryTag tag, Dart_Handle library, Dart_Handle url)
static const size_t kFileURLPrefixLength
Definition file_loader.h:43
Dart_Handle CanonicalizeURL(Dart_Handle library, Dart_Handle url)
Dart_Handle Kernel(Dart_Handle url)
Dart_Handle FetchBytes(const std::string &url, uint8_t *&buffer, intptr_t &buffer_size)
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:2606
DART_EXPORT Dart_Handle Dart_NewApiError(const char *error)
DART_EXPORT Dart_Handle Dart_Null(void)
Dart_LibraryTag
Definition dart_api.h:3339
@ Dart_kImportTag
Definition dart_api.h:3341
@ Dart_kCanonicalizeUrl
Definition dart_api.h:3340
@ Dart_kKernelTag
Definition dart_api.h:3342
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)
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
std::string AbsolutePath(const std::string &path)
std::string GetAbsoluteFilePath(const std::string &path)
std::string GetDirectoryName(const std::string &path)
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
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