Wire up the Skia persistent GPU related artifacts cache. (flutter/engine#6278)

Also teaches FML to create files and directories.
This commit is contained in:
Chinmay Garde
2018-09-26 14:54:09 -07:00
committed by GitHub
parent e02ba7472a
commit 74c44fa72a
42 changed files with 1427 additions and 234 deletions

View File

@@ -35,10 +35,8 @@ std::unique_ptr<fml::Mapping> DirectoryAssetBundle::GetAsMapping(
return nullptr;
}
auto mapping = std::make_unique<fml::FileMapping>(
fml::OpenFile(descriptor_, asset_name.c_str(), fml::OpenPermission::kRead,
false /* directory */),
false /* executable */);
auto mapping = std::make_unique<fml::FileMapping>(fml::OpenFile(
descriptor_, asset_name.c_str(), false, fml::FilePermission::kRead));
if (mapping->GetMapping() == nullptr) {
return nullptr;

View File

@@ -532,11 +532,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
====================================================================================================
LIBRARY: engine
ORIGIN: ../../../flutter/fml/platform/darwin/scoped_block.h + ../../../LICENSE
ORIGIN: ../../../flutter/fml/platform/android/paths_android.h + ../../../LICENSE
TYPE: LicenseType.bsd
FILE: ../../../flutter/fml/platform/darwin/scoped_block.h
FILE: ../../../flutter/fml/base32.cc
FILE: ../../../flutter/fml/base32.h
FILE: ../../../flutter/fml/base32_unittest.cc
FILE: ../../../flutter/fml/file.cc
FILE: ../../../flutter/fml/file.h
FILE: ../../../flutter/fml/file_unittest.cc
FILE: ../../../flutter/fml/macros.h
FILE: ../../../flutter/fml/mapping.cc
FILE: ../../../flutter/fml/message.cc
FILE: ../../../flutter/fml/message.h
FILE: ../../../flutter/fml/message_unittests.cc
FILE: ../../../flutter/fml/native_library.h
FILE: ../../../flutter/fml/paths.cc
FILE: ../../../flutter/fml/platform/android/paths_android.h
FILE: ../../../flutter/fml/platform/fuchsia/paths_fuchsia.cc
FILE: ../../../flutter/fml/platform/posix/file_posix.cc
FILE: ../../../flutter/fml/platform/posix/native_library_posix.cc
FILE: ../../../flutter/fml/platform/posix/paths_posix.cc
FILE: ../../../flutter/fml/platform/win/errors_win.cc
FILE: ../../../flutter/fml/platform/win/errors_win.h
FILE: ../../../flutter/fml/platform/win/file_win.cc
FILE: ../../../flutter/fml/platform/win/native_library_win.cc
FILE: ../../../flutter/fml/platform/win/wstring_conversion.h
FILE: ../../../flutter/fml/unique_fd.cc
FILE: ../../../flutter/fml/unique_fd.h
FILE: ../../../flutter/fml/unique_object.h
FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server.cc
FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server.h
FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server_natives.cc
FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server_natives.h
FILE: ../../../flutter/lib/ui/plugins/callback_cache.cc
FILE: ../../../flutter/lib/ui/plugins/callback_cache.h
FILE: ../../../flutter/shell/common/isolate_configuration.cc
FILE: ../../../flutter/shell/common/isolate_configuration.h
FILE: ../../../flutter/shell/common/persistent_cache.cc
FILE: ../../../flutter/shell/common/persistent_cache.h
FILE: ../../../flutter/shell/platform/android/android_shell_holder.cc
FILE: ../../../flutter/shell/platform/android/android_shell_holder.h
FILE: ../../../flutter/shell/platform/android/platform_message_response_android.cc
FILE: ../../../flutter/shell/platform/android/platform_message_response_android.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Internal.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.mm
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.h
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_gl.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_gl.h
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.h
FILE: ../../../flutter/shell/version/version.cc
FILE: ../../../flutter/shell/version/version.h
----------------------------------------------------------------------------------------------------
Copyright (c) 2013 The Chromium Authors. All rights reserved.
Copyright 2018 The Flutter Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -567,51 +617,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
====================================================================================================
LIBRARY: engine
ORIGIN: ../../../flutter/fml/platform/fuchsia/paths_fuchsia.cc + ../../../LICENSE
ORIGIN: ../../../flutter/fml/platform/darwin/scoped_block.h + ../../../LICENSE
TYPE: LicenseType.bsd
FILE: ../../../flutter/fml/file.h
FILE: ../../../flutter/fml/macros.h
FILE: ../../../flutter/fml/mapping.cc
FILE: ../../../flutter/fml/message.cc
FILE: ../../../flutter/fml/message.h
FILE: ../../../flutter/fml/message_unittests.cc
FILE: ../../../flutter/fml/native_library.h
FILE: ../../../flutter/fml/paths.cc
FILE: ../../../flutter/fml/platform/fuchsia/paths_fuchsia.cc
FILE: ../../../flutter/fml/platform/posix/file_posix.cc
FILE: ../../../flutter/fml/platform/posix/native_library_posix.cc
FILE: ../../../flutter/fml/platform/posix/paths_posix.cc
FILE: ../../../flutter/fml/platform/win/file_win.cc
FILE: ../../../flutter/fml/platform/win/native_library_win.cc
FILE: ../../../flutter/fml/platform/win/wstring_conversion.h
FILE: ../../../flutter/fml/unique_fd.cc
FILE: ../../../flutter/fml/unique_fd.h
FILE: ../../../flutter/fml/unique_object.h
FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server.cc
FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server.h
FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server_natives.cc
FILE: ../../../flutter/lib/ui/isolate_name_server/isolate_name_server_natives.h
FILE: ../../../flutter/lib/ui/plugins/callback_cache.cc
FILE: ../../../flutter/lib/ui/plugins/callback_cache.h
FILE: ../../../flutter/shell/common/isolate_configuration.cc
FILE: ../../../flutter/shell/common/isolate_configuration.h
FILE: ../../../flutter/shell/platform/android/android_shell_holder.cc
FILE: ../../../flutter/shell/platform/android/android_shell_holder.h
FILE: ../../../flutter/shell/platform/android/platform_message_response_android.cc
FILE: ../../../flutter/shell/platform/android/platform_message_response_android.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Internal.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.mm
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.h
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_gl.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_gl.h
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.h
FILE: ../../../flutter/shell/version/version.cc
FILE: ../../../flutter/shell/version/version.h
FILE: ../../../flutter/fml/platform/darwin/scoped_block.h
----------------------------------------------------------------------------------------------------
Copyright 2018 The Flutter Authors. All rights reserved.
Copyright (c) 2013 The Chromium Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are

View File

@@ -5,6 +5,8 @@
source_set("fml") {
sources = [
"arraysize.h",
"base32.cc",
"base32.h",
"build_config.h",
"closure.h",
"command_line.cc",
@@ -12,6 +14,7 @@ source_set("fml") {
"compiler_specific.h",
"eintr_wrapper.h",
"export.h",
"file.cc",
"file.h",
"icu_util.cc",
"icu_util.h",
@@ -104,6 +107,7 @@ source_set("fml") {
"platform/android/message_loop_android.cc",
"platform/android/message_loop_android.h",
"platform/android/paths_android.cc",
"platform/android/paths_android.h",
"platform/android/scoped_java_ref.cc",
"platform/android/scoped_java_ref.h",
]
@@ -139,6 +143,8 @@ source_set("fml") {
if (is_win) {
sources += [
"platform/win/errors_win.cc",
"platform/win/errors_win.h",
"platform/win/file_win.cc",
"platform/win/mapping_win.cc",
"platform/win/message_loop_win.cc",
@@ -161,7 +167,9 @@ executable("fml_unittests") {
testonly = true
sources = [
"base32_unittest.cc",
"command_line_unittest.cc",
"file_unittest.cc",
"memory/ref_counted_unittest.cc",
"memory/weak_ptr_unittest.cc",
"message_loop_unittests.cc",

View File

@@ -0,0 +1,46 @@
// Copyright 2018 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/fml/base32.h"
#include <limits>
#include "flutter/fml/macros.h"
namespace fml {
static constexpr char kEncoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
std::pair<bool, std::string> Base32Encode(StringView input) {
if (input.empty()) {
return {true, ""};
}
if (input.size() > std::numeric_limits<size_t>::max() / 8) {
return {false, ""};
}
std::string output;
const size_t encoded_length = (input.size() * 8 + 4) / 5;
output.reserve(encoded_length);
uint16_t bit_stream = (static_cast<uint8_t>(input[0]) << 8);
size_t next_byte_index = 1;
int free_bits = 8;
while (free_bits < 16) {
output.push_back(kEncoding[(bit_stream & 0xf800) >> 11]);
bit_stream <<= 5;
free_bits += 5;
if (free_bits >= 8 && next_byte_index < input.size()) {
free_bits -= 8;
bit_stream += static_cast<uint8_t>(input[next_byte_index++]) << free_bits;
}
}
return {true, output};
}
} // namespace fml

View File

@@ -0,0 +1,19 @@
// Copyright 2018 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_FML_BASE32_H_
#define FLUTTER_FML_BASE32_H_
#include <string>
#include <utility>
#include "flutter/fml/string_view.h"
namespace fml {
std::pair<bool, std::string> Base32Encode(StringView input);
} // namespace fml
#endif // FLUTTER_FML_BASE32_H_

View File

@@ -0,0 +1,38 @@
// Copyright 2018 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/fml/base32.h"
#include "gtest/gtest.h"
TEST(Base32Test, CanEncode) {
{
auto result = fml::Base32Encode("hello");
ASSERT_TRUE(result.first);
ASSERT_EQ(result.second, "NBSWY3DP");
}
{
auto result = fml::Base32Encode("helLo");
ASSERT_TRUE(result.first);
ASSERT_EQ(result.second, "NBSWYTDP");
}
{
auto result = fml::Base32Encode("");
ASSERT_TRUE(result.first);
ASSERT_EQ(result.second, "");
}
{
auto result = fml::Base32Encode("1");
ASSERT_TRUE(result.first);
ASSERT_EQ(result.second, "GE");
}
{
auto result = fml::Base32Encode("helLo");
ASSERT_TRUE(result.first);
ASSERT_EQ(result.second, "NBSWYTDP");
}
}

View File

@@ -0,0 +1,46 @@
// Copyright 2018 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/fml/file.h"
#include "flutter/fml/logging.h"
namespace fml {
static fml::UniqueFD CreateDirectory(const fml::UniqueFD& base_directory,
const std::vector<std::string>& components,
FilePermission permission,
size_t index) {
FML_DCHECK(index <= components.size());
const char* file_path = components[index].c_str();
auto directory = OpenDirectory(base_directory, file_path, true, permission);
if (!directory.is_valid()) {
return {};
}
if (index == components.size() - 1) {
return directory;
}
return CreateDirectory(directory, components, permission, index + 1);
}
fml::UniqueFD CreateDirectory(const fml::UniqueFD& base_directory,
const std::vector<std::string>& components,
FilePermission permission) {
if (!IsDirectory(base_directory)) {
return {};
}
if (components.size() == 0) {
return {};
}
return CreateDirectory(base_directory, components, permission, 0);
}
} // namespace fml

View File

@@ -5,26 +5,46 @@
#ifndef FLUTTER_FML_FILE_H_
#define FLUTTER_FML_FILE_H_
#include <initializer_list>
#include <string>
#include <vector>
#include "flutter/fml/macros.h"
#include "flutter/fml/unique_fd.h"
#ifdef ERROR
#undef ERROR
#endif
namespace fml {
enum class OpenPermission {
kRead = 1,
kWrite = 1 << 1,
kReadWrite = kRead | kWrite,
kExecute,
class Mapping;
enum class FilePermission {
kRead,
kWrite,
kReadWrite,
};
std::string CreateTemporaryDirectory();
fml::UniqueFD OpenFile(const char* path,
OpenPermission permission,
bool is_directory = false);
bool create_if_necessary,
FilePermission permission);
fml::UniqueFD OpenFile(const fml::UniqueFD& base_directory,
const char* path,
OpenPermission permission,
bool is_directory = false);
bool create_if_necessary,
FilePermission permission);
fml::UniqueFD OpenDirectory(const char* path,
bool create_if_necessary,
FilePermission permission);
fml::UniqueFD OpenDirectory(const fml::UniqueFD& base_directory,
const char* path,
bool create_if_necessary,
FilePermission permission);
fml::UniqueFD Duplicate(fml::UniqueFD::element_type descriptor);
@@ -33,6 +53,50 @@ bool IsDirectory(const fml::UniqueFD& directory);
// Returns whether the given path is a file.
bool IsFile(const std::string& path);
bool TruncateFile(const fml::UniqueFD& file, size_t size);
bool FileExists(const fml::UniqueFD& base_directory, const char* path);
bool UnlinkDirectory(const char* path);
bool UnlinkDirectory(const fml::UniqueFD& base_directory, const char* path);
bool UnlinkFile(const char* path);
bool UnlinkFile(const fml::UniqueFD& base_directory, const char* path);
fml::UniqueFD CreateDirectory(const fml::UniqueFD& base_directory,
const std::vector<std::string>& components,
FilePermission permission);
bool WriteAtomically(const fml::UniqueFD& base_directory,
const char* file_name,
const Mapping& mapping);
class ScopedTemporaryDirectory {
public:
ScopedTemporaryDirectory() {
path_ = CreateTemporaryDirectory();
if (path_ != "") {
dir_fd_ = OpenDirectory(path_.c_str(), false, FilePermission::kRead);
}
}
~ScopedTemporaryDirectory() {
if (path_ != "") {
if (!UnlinkDirectory(path_.c_str())) {
FML_LOG(ERROR) << "Could not remove directory: " << path_;
}
}
}
const UniqueFD& fd() { return dir_fd_; }
private:
std::string path_;
UniqueFD dir_fd_;
};
} // namespace fml
#endif // FLUTTER_FML_FILE_H_

View File

@@ -0,0 +1,157 @@
// Copyright 2018 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <vector>
#include "gtest/gtest.h"
#include "flutter/fml/build_config.h"
#include "flutter/fml/file.h"
#include "flutter/fml/mapping.h"
static bool WriteStringToFile(const fml::UniqueFD& fd,
const std::string& contents) {
if (!fml::TruncateFile(fd, contents.size())) {
return false;
}
fml::FileMapping mapping(fd, {fml::FileMapping::Protection::kWrite});
if (mapping.GetSize() != contents.size()) {
return false;
}
if (mapping.GetMutableMapping() == nullptr) {
return false;
}
::memmove(mapping.GetMutableMapping(), contents.data(), contents.size());
return true;
}
static std::string ReadStringFromFile(const fml::UniqueFD& fd) {
fml::FileMapping mapping(fd);
if (mapping.GetMapping() == nullptr) {
return nullptr;
}
return {reinterpret_cast<const char*>(mapping.GetMapping()),
mapping.GetSize()};
}
TEST(FileTest, CreateTemporaryAndUnlink) {
auto dir_name = fml::CreateTemporaryDirectory();
ASSERT_NE(dir_name, "");
auto dir =
fml::OpenDirectory(dir_name.c_str(), false, fml::FilePermission::kRead);
ASSERT_TRUE(dir.is_valid());
dir.reset();
ASSERT_TRUE(fml::UnlinkDirectory(dir_name.c_str()));
}
TEST(FileTest, ScopedTempDirIsValid) {
fml::ScopedTemporaryDirectory dir;
ASSERT_TRUE(dir.fd().is_valid());
}
TEST(FileTest, CanOpenFileForWriting) {
fml::ScopedTemporaryDirectory dir;
ASSERT_TRUE(dir.fd().is_valid());
auto fd =
fml::OpenFile(dir.fd(), "some.txt", true, fml::FilePermission::kWrite);
ASSERT_TRUE(fd.is_valid());
fd.reset();
ASSERT_TRUE(fml::UnlinkFile(dir.fd(), "some.txt"));
}
TEST(FileTest, CanTruncateAndWrite) {
fml::ScopedTemporaryDirectory dir;
ASSERT_TRUE(dir.fd().is_valid());
std::string contents = "some contents here";
{
auto fd = fml::OpenFile(dir.fd(), "some.txt", true,
fml::FilePermission::kReadWrite);
ASSERT_TRUE(fd.is_valid());
ASSERT_TRUE(fml::TruncateFile(fd, contents.size()));
fml::FileMapping mapping(fd, {fml::FileMapping::Protection::kWrite});
ASSERT_EQ(mapping.GetSize(), contents.size());
ASSERT_NE(mapping.GetMutableMapping(), nullptr);
::memcpy(mapping.GetMutableMapping(), contents.data(), contents.size());
}
{
auto fd =
fml::OpenFile(dir.fd(), "some.txt", false, fml::FilePermission::kRead);
ASSERT_TRUE(fd.is_valid());
fml::FileMapping mapping(fd);
ASSERT_EQ(mapping.GetSize(), contents.size());
ASSERT_EQ(0,
::memcmp(mapping.GetMapping(), contents.data(), contents.size()));
}
fml::UnlinkFile(dir.fd(), "some.txt");
}
TEST(FileTest, CreateDirectoryStructure) {
fml::ScopedTemporaryDirectory dir;
std::string contents = "These are my contents";
{
auto sub = fml::CreateDirectory(dir.fd(), {"a", "b", "c"},
fml::FilePermission::kReadWrite);
ASSERT_TRUE(sub.is_valid());
auto file = fml::OpenFile(sub, "my_contents", true,
fml::FilePermission::kReadWrite);
ASSERT_TRUE(file.is_valid());
ASSERT_TRUE(WriteStringToFile(file, contents));
}
const char* file_path = "a/b/c/my_contents";
{
auto contents_file =
fml::OpenFile(dir.fd(), file_path, false, fml::FilePermission::kRead);
ASSERT_EQ(ReadStringFromFile(contents_file), contents);
}
// Cleanup.
ASSERT_TRUE(fml::UnlinkFile(dir.fd(), file_path));
ASSERT_TRUE(fml::UnlinkDirectory(dir.fd(), "a/b/c"));
ASSERT_TRUE(fml::UnlinkDirectory(dir.fd(), "a/b"));
ASSERT_TRUE(fml::UnlinkDirectory(dir.fd(), "a"));
}
#if OS_WIN
#define AtomicWriteTest DISABLED_AtomicWriteTest
#else
#define AtomicWriteTest AtomicWriteTest
#endif
TEST(FileTest, AtomicWriteTest) {
fml::ScopedTemporaryDirectory dir;
const std::string contents = "These are my contents.";
auto data = std::make_unique<fml::DataMapping>(
std::vector<uint8_t>{contents.begin(), contents.end()});
// Write.
ASSERT_TRUE(fml::WriteAtomically(dir.fd(), "precious_data", *data));
// Read and verify.
ASSERT_EQ(contents,
ReadStringFromFile(fml::OpenFile(dir.fd(), "precious_data", false,
fml::FilePermission::kRead)));
// Cleanup.
ASSERT_TRUE(fml::UnlinkFile(dir.fd(), "precious_data"));
}

View File

@@ -16,12 +16,6 @@
namespace fml {
namespace icu {
#if OS_WIN
static constexpr char kPathSeparator = '\\';
#else
static constexpr char kPathSeparator = '/';
#endif
class ICUContext {
public:
ICUContext(const std::string& icu_data_path) : valid_(false) {
@@ -31,25 +25,37 @@ class ICUContext {
~ICUContext() = default;
bool SetupMapping(const std::string& icu_data_path) {
// Check if the explicit path specified exists.
auto path_mapping = std::make_unique<FileMapping>(icu_data_path, false);
if (path_mapping->GetSize() != 0) {
mapping_ = std::move(path_mapping);
return true;
// Check if the path exists and it readable directly.
auto fd =
fml::OpenFile(icu_data_path.c_str(), false, fml::FilePermission::kRead);
// Check the path relative to the current executable.
if (!fd.is_valid()) {
auto directory = fml::paths::GetExecutableDirectoryPath();
if (!directory.first) {
return false;
}
std::string path_relative_to_executable =
paths::JoinPaths({directory.second, icu_data_path});
fd = fml::OpenFile(path_relative_to_executable.c_str(), false,
fml::FilePermission::kRead);
}
// Check if the mapping can by directly accessed via a file path. In this
// case, the data file needs to be next to the executable.
auto directory = fml::paths::GetExecutableDirectoryPath();
if (!directory.first) {
if (!fd.is_valid()) {
return false;
}
auto file = std::make_unique<FileMapping>(
directory.second + kPathSeparator + icu_data_path, false);
if (file->GetSize() != 0) {
mapping_ = std::move(file);
std::initializer_list<FileMapping::Protection> protection = {
fml::FileMapping::Protection::kRead};
auto file_mapping =
std::make_unique<FileMapping>(fd, std::move(protection));
if (file_mapping->GetSize() != 0) {
mapping_ = std::move(file_mapping);
return true;
}

View File

@@ -6,6 +6,10 @@
namespace fml {
uint8_t* FileMapping::GetMutableMapping() {
return mutable_mapping_;
}
DataMapping::DataMapping(std::vector<uint8_t> data) : data_(std::move(data)) {}
DataMapping::~DataMapping() = default;
@@ -17,4 +21,5 @@ size_t DataMapping::GetSize() const {
const uint8_t* DataMapping::GetMapping() const {
return data_.data();
}
} // namespace fml

View File

@@ -5,11 +5,13 @@
#ifndef FLUTTER_FML_MAPPING_H_
#define FLUTTER_FML_MAPPING_H_
#include <initializer_list>
#include <memory>
#include <string>
#include <vector>
#include "flutter/fml/build_config.h"
#include "flutter/fml/file.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/unique_fd.h"
@@ -31,9 +33,15 @@ class Mapping {
class FileMapping : public Mapping {
public:
FileMapping(const std::string& path, bool executable = false);
enum class Protection {
kRead,
kWrite,
kExecute,
};
FileMapping(const fml::UniqueFD& fd, bool executable = false);
FileMapping(const fml::UniqueFD& fd,
std::initializer_list<Protection> protection = {
Protection::kRead});
~FileMapping() override;
@@ -41,9 +49,12 @@ class FileMapping : public Mapping {
const uint8_t* GetMapping() const override;
uint8_t* GetMutableMapping();
private:
size_t size_ = 0;
uint8_t* mapping_ = nullptr;
uint8_t* mutable_mapping_ = nullptr;
#if OS_WIN
fml::UniqueFD mapping_handle_;
@@ -68,6 +79,22 @@ class DataMapping : public Mapping {
FML_DISALLOW_COPY_AND_ASSIGN(DataMapping);
};
class NonOwnedMapping : public Mapping {
public:
NonOwnedMapping(const uint8_t* data, size_t size)
: data_(data), size_(size) {}
size_t GetSize() const override { return size_; }
const uint8_t* GetMapping() const override { return data_; }
private:
const uint8_t* const data_;
const size_t size_;
FML_DISALLOW_COPY_AND_ASSIGN(NonOwnedMapping);
};
} // namespace fml
#endif // FLUTTER_FML_MAPPING_H_

View File

@@ -8,11 +8,16 @@
#include <string>
#include <utility>
#include "flutter/fml/unique_fd.h"
namespace fml {
namespace paths {
std::pair<bool, std::string> GetExecutableDirectoryPath();
// Get the directory to the application's caches directory.
fml::UniqueFD GetCachesDirectory();
std::string JoinPaths(std::initializer_list<std::string> components);
// Returns the absolute path of a possibly relative path.

View File

@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/fml/paths.h"
#include "flutter/fml/platform/android/paths_android.h"
#include "flutter/fml/file.h"
namespace fml {
namespace paths {
@@ -11,5 +13,17 @@ std::pair<bool, std::string> GetExecutableDirectoryPath() {
return {false, ""};
}
static std::string gCachesPath;
void InitializeAndroidCachesPath(std::string caches_path) {
gCachesPath = std::move(caches_path);
}
fml::UniqueFD GetCachesDirectory() {
// If the caches path is not initialized, the FD will be invalid and caching
// will be disabled throughout the system.
return OpenDirectory(gCachesPath.c_str(), false, fml::FilePermission::kRead);
}
} // namespace paths
} // namespace fml

View File

@@ -0,0 +1,19 @@
// Copyright 2018 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_FML_PLATFORM_ANDROID_PATHS_ANDROID_H_
#define FLUTTER_FML_PLATFORM_ANDROID_PATHS_ANDROID_H_
#include "flutter/fml/macros.h"
#include "flutter/fml/paths.h"
namespace fml {
namespace paths {
void InitializeAndroidCachesPath(std::string caches_path);
} // namespace paths
} // namespace fml
#endif // FLUTTER_FML_PLATFORM_ANDROID_PATHS_ANDROID_H_

View File

@@ -6,11 +6,27 @@
#include <Foundation/Foundation.h>
#include "flutter/fml/file.h"
namespace fml {
namespace paths {
std::pair<bool, std::string> GetExecutableDirectoryPath() {
return {true, GetDirectoryName([NSBundle mainBundle].executablePath.UTF8String)};
@autoreleasepool {
return {true, GetDirectoryName([NSBundle mainBundle].executablePath.UTF8String)};
}
}
fml::UniqueFD GetCachesDirectory() {
@autoreleasepool {
auto items = [[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory
inDomains:NSUserDomainMask];
if (items.count == 0) {
return {};
}
return OpenDirectory(items[0].fileSystemRepresentation, false, FilePermission::kRead);
}
}
} // namespace paths

View File

@@ -11,5 +11,10 @@ std::pair<bool, std::string> GetExecutableDirectoryPath() {
return {false, ""};
}
fml::UniqueFD GetCachesDirectory() {
// Unsupported on this platform.
return {};
}
} // namespace paths
} // namespace fml

View File

@@ -22,5 +22,10 @@ std::pair<bool, std::string> GetExecutableDirectoryPath() {
std::string{path, static_cast<size_t>(read_size)})};
}
fml::UniqueFD GetCachesDirectory() {
// Unsupported on this platform.
return {};
}
} // namespace paths
} // namespace fml

View File

@@ -5,49 +5,113 @@
#include "flutter/fml/file.h"
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <memory>
#include <sstream>
#include "flutter/fml/eintr_wrapper.h"
#include "flutter/fml/mapping.h"
namespace fml {
std::string CreateTemporaryDirectory() {
char directory_name[] = "/tmp/flutter_XXXXXXXX";
auto result = ::mkdtemp(directory_name);
if (result == nullptr) {
return "";
}
return {result};
}
static int ToPosixAccessFlags(FilePermission permission) {
int flags = 0;
switch (permission) {
case FilePermission::kRead:
flags |= O_RDONLY; // read only
break;
case FilePermission::kWrite:
flags |= O_WRONLY; // write only
break;
case FilePermission::kReadWrite:
flags |= O_RDWR; // read-write
break;
}
return flags;
}
static int ToPosixCreateModeFlags(FilePermission permission) {
int mode = 0;
switch (permission) {
case FilePermission::kRead:
mode |= S_IRUSR;
break;
case FilePermission::kWrite:
mode |= S_IWUSR;
break;
case FilePermission::kReadWrite:
mode |= S_IRUSR | S_IWUSR;
break;
}
return mode;
}
fml::UniqueFD OpenFile(const char* path,
OpenPermission permission,
bool is_directory) {
return OpenFile(fml::UniqueFD{AT_FDCWD}, path, permission, is_directory);
bool create_if_necessary,
FilePermission permission) {
return OpenFile(fml::UniqueFD{AT_FDCWD}, path, create_if_necessary,
permission);
}
fml::UniqueFD OpenFile(const fml::UniqueFD& base_directory,
const char* path,
OpenPermission permission,
bool is_directory) {
bool create_if_necessary,
FilePermission permission) {
if (path == nullptr) {
return fml::UniqueFD{};
return {};
}
int flags = 0;
switch (permission) {
case OpenPermission::kRead:
flags = O_RDONLY;
break;
case OpenPermission::kWrite:
flags = O_WRONLY;
break;
case OpenPermission::kReadWrite:
flags = O_RDWR;
break;
case OpenPermission::kExecute:
flags = O_RDONLY;
break;
}
int mode = 0;
if (is_directory) {
flags |= O_DIRECTORY;
if (create_if_necessary && !FileExists(base_directory, path)) {
flags = ToPosixAccessFlags(permission) | O_CREAT | O_TRUNC;
mode = ToPosixCreateModeFlags(permission);
} else {
flags = ToPosixAccessFlags(permission);
mode = 0; // Not creating since it already exists.
}
return fml::UniqueFD{
FML_HANDLE_EINTR(::openat(base_directory.get(), path, flags))};
FML_HANDLE_EINTR(::openat(base_directory.get(), path, flags, mode))};
}
fml::UniqueFD OpenDirectory(const char* path,
bool create_if_necessary,
FilePermission permission) {
return OpenDirectory(fml::UniqueFD{AT_FDCWD}, path, create_if_necessary,
permission);
}
fml::UniqueFD OpenDirectory(const fml::UniqueFD& base_directory,
const char* path,
bool create_if_necessary,
FilePermission permission) {
if (path == nullptr) {
return {};
}
if (create_if_necessary && !FileExists(base_directory, path)) {
if (::mkdirat(base_directory.get(), path,
ToPosixCreateModeFlags(permission) | S_IXUSR) != 0) {
return {};
}
}
return fml::UniqueFD{FML_HANDLE_EINTR(
::openat(base_directory.get(), path, O_RDONLY | O_DIRECTORY))};
}
fml::UniqueFD Duplicate(fml::UniqueFD::element_type descriptor) {
@@ -70,9 +134,80 @@ bool IsDirectory(const fml::UniqueFD& directory) {
bool IsFile(const std::string& path) {
struct stat buf;
if (stat(path.c_str(), &buf) != 0)
if (stat(path.c_str(), &buf) != 0) {
return false;
}
return S_ISREG(buf.st_mode);
}
bool TruncateFile(const fml::UniqueFD& file, size_t size) {
if (!file.is_valid()) {
return false;
}
return ::ftruncate(file.get(), size) == 0;
}
bool UnlinkDirectory(const char* path) {
return UnlinkDirectory(fml::UniqueFD{AT_FDCWD}, path);
}
bool UnlinkDirectory(const fml::UniqueFD& base_directory, const char* path) {
return ::unlinkat(base_directory.get(), path, AT_REMOVEDIR) == 0;
}
bool UnlinkFile(const char* path) {
return UnlinkFile(fml::UniqueFD{AT_FDCWD}, path);
}
bool UnlinkFile(const fml::UniqueFD& base_directory, const char* path) {
return ::unlinkat(base_directory.get(), path, 0) == 0;
}
bool FileExists(const fml::UniqueFD& base_directory, const char* path) {
if (!base_directory.is_valid()) {
return false;
}
return ::faccessat(base_directory.get(), path, F_OK, 0) == 0;
}
bool WriteAtomically(const fml::UniqueFD& base_directory,
const char* file_name,
const Mapping& data) {
if (file_name == nullptr || data.GetMapping() == nullptr) {
return false;
}
std::stringstream stream;
stream << file_name << ".temp";
const auto temp_file_name = stream.str();
auto temp_file = OpenFile(base_directory, temp_file_name.c_str(), true,
FilePermission::kReadWrite);
if (!temp_file.is_valid()) {
return false;
}
if (!TruncateFile(temp_file, data.GetSize())) {
return false;
}
FileMapping mapping(temp_file, {FileMapping::Protection::kWrite});
if (mapping.GetMutableMapping() == nullptr ||
data.GetSize() != mapping.GetSize()) {
return false;
}
::memcpy(mapping.GetMutableMapping(), data.GetMapping(), data.GetSize());
if (::msync(mapping.GetMutableMapping(), data.GetSize(), MS_SYNC) != 0) {
return false;
}
return ::renameat(base_directory.get(), temp_file_name.c_str(),
base_directory.get(), file_name) == 0;
}
} // namespace fml

View File

@@ -17,16 +17,41 @@
namespace fml {
static int ToPosixProtectionFlags(
std::initializer_list<FileMapping::Protection> protection_flags) {
int flags = 0;
for (auto protection : protection_flags) {
switch (protection) {
case FileMapping::Protection::kRead:
flags |= PROT_READ;
break;
case FileMapping::Protection::kWrite:
flags |= PROT_WRITE;
break;
case FileMapping::Protection::kExecute:
flags |= PROT_READ | PROT_EXEC;
break;
}
}
return flags;
}
static bool IsWritable(
std::initializer_list<FileMapping::Protection> protection_flags) {
for (auto protection : protection_flags) {
if (protection == FileMapping::Protection::kWrite) {
return true;
}
}
return false;
}
Mapping::Mapping() = default;
Mapping::~Mapping() = default;
FileMapping::FileMapping(const std::string& path, bool executable)
: FileMapping(
fml::UniqueFD{FML_HANDLE_EINTR(::open(path.c_str(), O_RDONLY))},
executable) {}
FileMapping::FileMapping(const fml::UniqueFD& handle, bool executable)
FileMapping::FileMapping(const fml::UniqueFD& handle,
std::initializer_list<Protection> protection)
: size_(0), mapping_(nullptr) {
if (!handle.is_valid()) {
return;
@@ -42,13 +67,11 @@ FileMapping::FileMapping(const fml::UniqueFD& handle, bool executable)
return;
}
int flags = PROT_READ;
if (executable) {
flags |= PROT_EXEC;
}
const auto is_writable = IsWritable(protection);
auto mapping =
::mmap(nullptr, stat_buffer.st_size, flags, MAP_PRIVATE, handle.get(), 0);
::mmap(nullptr, stat_buffer.st_size, ToPosixProtectionFlags(protection),
is_writable ? MAP_SHARED : MAP_PRIVATE, handle.get(), 0);
if (mapping == MAP_FAILED) {
return;
@@ -56,6 +79,9 @@ FileMapping::FileMapping(const fml::UniqueFD& handle, bool executable)
mapping_ = static_cast<uint8_t*>(mapping);
size_ = stat_buffer.st_size;
if (is_writable) {
mutable_mapping_ = mapping_;
}
}
FileMapping::~FileMapping() {

View File

@@ -0,0 +1,46 @@
// Copyright 2018 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/fml/platform/win/errors_win.h"
#include <Windows.h>
#include <sstream>
#include "flutter/fml/platform/win/wstring_conversion.h"
namespace fml {
std::string GetLastErrorMessage() {
DWORD last_error = ::GetLastError();
if (last_error == 0) {
return {};
}
const DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS;
wchar_t* buffer = nullptr;
size_t size = ::FormatMessage(
flags, // dwFlags
NULL, // lpSource
last_error, // dwMessageId
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // dwLanguageId
(LPWSTR)&buffer, // lpBuffer
0, // nSize
NULL // Arguments
);
std::wstring message(buffer, size);
::LocalFree(buffer);
std::wstringstream stream;
stream << message << " (" << last_error << ").";
return WideStringToString(stream.str());
}
} // namespace fml

View File

@@ -0,0 +1,16 @@
// Copyright 2018 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_FML_PLATFORM_WIN_ERRORS_WIN_H_
#define FLUTTER_FML_PLATFORM_WIN_ERRORS_WIN_H_
#include <string>
namespace fml {
std::string GetLastErrorMessage();
} // namespace fml
#endif // FLUTTER_FML_PLATFORM_WIN_ERRORS_WIN_H_

View File

@@ -4,6 +4,7 @@
#include "flutter/fml/file.h"
#include <Fileapi.h>
#include <Shlwapi.h>
#include <fcntl.h>
#include <limits.h>
@@ -13,6 +14,8 @@
#include <sstream>
#include "flutter/fml/build_config.h"
#include "flutter/fml/mapping.h"
#include "flutter/fml/platform/win/errors_win.h"
#include "flutter/fml/platform/win/wstring_conversion.h"
#if defined(OS_WIN)
@@ -21,85 +24,200 @@
namespace fml {
static fml::UniqueFD OpenFile(std::wstring path,
OpenPermission permission,
bool is_directory) {
if (path.size() == 0) {
return fml::UniqueFD{};
}
DWORD desired_access = 0;
switch (permission) {
case OpenPermission::kRead:
desired_access = GENERIC_READ;
break;
case OpenPermission::kWrite:
desired_access = GENERIC_WRITE;
break;
case OpenPermission::kReadWrite:
desired_access = GENERIC_WRITE | GENERIC_READ;
break;
case OpenPermission::kExecute:
desired_access = GENERIC_READ | GENERIC_EXECUTE;
break;
}
DWORD flags = FILE_ATTRIBUTE_NORMAL;
if (is_directory) {
flags |= FILE_FLAG_BACKUP_SEMANTICS;
static std::string GetFullHandlePath(const fml::UniqueFD& handle) {
wchar_t buffer[MAX_PATH] = {0};
const DWORD buffer_size = ::GetFinalPathNameByHandle(
handle.get(), buffer, MAX_PATH, FILE_NAME_NORMALIZED);
if (buffer_size == 0) {
FML_DLOG(ERROR) << "Could not get file handle path. "
<< GetLastErrorMessage();
return {};
}
return WideStringToString({buffer, buffer_size});
}
static std::string GetAbsolutePath(const fml::UniqueFD& base_directory,
const char* subpath) {
std::stringstream stream;
stream << GetFullHandlePath(base_directory) << "\\" << subpath;
auto path = stream.str();
std::replace(path.begin(), path.end(), '/', '\\');
return fml::UniqueFD{::CreateFile(path.c_str(), // lpFileName
desired_access, // dwDesiredAccess
FILE_SHARE_READ, // dwShareMode
0, // lpSecurityAttributes
OPEN_EXISTING, // dwCreationDisposition
flags, // dwFlagsAndAttributes
0 // hTemplateFile
)};
return path;
}
fml::UniqueFD OpenFile(const char* path,
OpenPermission permission,
bool is_directory) {
return OpenFile(ConvertToWString(path), permission, is_directory);
static std::wstring GetTemporaryDirectoryPath() {
wchar_t wchar_path[MAX_PATH];
auto result_size = ::GetTempPath(MAX_PATH, wchar_path);
if (result_size > 0) {
return {wchar_path, result_size};
}
FML_DLOG(ERROR) << "Could not get temporary directory path. "
<< GetLastErrorMessage();
return {};
}
static std::wstring GetFullHandlePath(const fml::UniqueFD& handle) {
wchar_t buffer[MAX_PATH];
static DWORD GetDesiredAccessFlags(FilePermission permission) {
switch (permission) {
case FilePermission::kRead:
return GENERIC_READ;
case FilePermission::kWrite:
return GENERIC_WRITE;
case FilePermission::kReadWrite:
return GENERIC_READ | GENERIC_WRITE;
}
return GENERIC_READ;
}
DWORD returned = ::GetFinalPathNameByHandle(handle.get(), buffer, MAX_PATH,
FILE_NAME_NORMALIZED);
if (returned == 0 || returned > MAX_PATH) {
static DWORD GetShareFlags(FilePermission permission) {
switch (permission) {
case FilePermission::kRead:
return FILE_SHARE_READ;
case FilePermission::kWrite:
return FILE_SHARE_WRITE;
case FilePermission::kReadWrite:
return FILE_SHARE_READ | FILE_SHARE_WRITE;
}
return FILE_SHARE_READ;
}
std::string CreateTemporaryDirectory() {
// Get the system temporary directory.
auto temp_dir_container = GetTemporaryDirectoryPath();
if (temp_dir_container.size() == 0) {
FML_DLOG(ERROR) << "Could not get system temporary directory.";
return {};
}
return {buffer};
// Create a UUID.
UUID uuid;
RPC_STATUS status = UuidCreateSequential(&uuid);
if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
FML_DLOG(ERROR) << "Could not create UUID";
return {};
}
RPC_WSTR uuid_string;
status = UuidToString(&uuid, &uuid_string);
if (status != RPC_S_OK) {
FML_DLOG(ERROR) << "Could not create UUID to string.";
return {};
}
std::wstring uuid_str(reinterpret_cast<wchar_t*>(uuid_string));
RpcStringFree(&uuid_string);
// Join the two and create a path to the new temporary directory.
std::wstringstream stream;
stream << temp_dir_container << "\\" << uuid_str;
auto temp_dir = stream.str();
auto dir_fd = OpenDirectory(WideStringToString(temp_dir).c_str(), true,
FilePermission::kReadWrite);
if (!dir_fd.is_valid()) {
FML_DLOG(ERROR) << "Could not get temporary directory FD. "
<< GetLastErrorMessage();
return {};
}
return WideStringToString(std::move(temp_dir));
}
fml::UniqueFD OpenFile(const fml::UniqueFD& base_directory,
const char* path,
OpenPermission permission,
bool is_directory) {
// If the base directory is invalid or the path is absolute, use the generic
// open file variant.
if (!base_directory.is_valid()) {
return OpenFile(path, permission, is_directory);
bool create_if_necessary,
FilePermission permission) {
return OpenFile(GetAbsolutePath(base_directory, path).c_str(),
create_if_necessary, permission);
}
fml::UniqueFD OpenFile(const char* path,
bool create_if_necessary,
FilePermission permission) {
if (path == nullptr || strlen(path) == 0) {
return {};
}
const auto wpath = ConvertToWString(path);
auto file_name = StringToWideString({path});
if (!::PathIsRelative(wpath.c_str())) {
return OpenFile(path, permission, is_directory);
if (file_name.size() == 0) {
return {};
}
std::wstringstream stream;
stream << GetFullHandlePath(base_directory) << "\\" << path;
return OpenFile(stream.str(), permission, is_directory);
const DWORD creation_disposition =
create_if_necessary ? CREATE_NEW : OPEN_EXISTING;
const DWORD flags = FILE_ATTRIBUTE_NORMAL;
auto handle =
CreateFile(file_name.c_str(), // lpFileName
GetDesiredAccessFlags(permission), // dwDesiredAccess
GetShareFlags(permission), // dwShareMode
nullptr, // lpSecurityAttributes //
creation_disposition, // dwCreationDisposition //
flags, // dwFlagsAndAttributes //
nullptr // hTemplateFile //
);
if (handle == INVALID_HANDLE_VALUE) {
FML_DLOG(ERROR) << "Could not open file. " << GetLastErrorMessage();
return {};
}
return fml::UniqueFD{handle};
}
fml::UniqueFD OpenDirectory(const fml::UniqueFD& base_directory,
const char* path,
bool create_if_necessary,
FilePermission permission) {
return OpenDirectory(GetAbsolutePath(base_directory, path).c_str(),
create_if_necessary, permission);
}
fml::UniqueFD OpenDirectory(const char* path,
bool create_if_necessary,
FilePermission permission) {
if (path == nullptr || strlen(path) == 0) {
return {};
}
auto file_name = StringToWideString({path});
if (file_name.size() == 0) {
return {};
}
if (create_if_necessary) {
if (!::CreateDirectory(file_name.c_str(), nullptr)) {
if (GetLastError() != ERROR_ALREADY_EXISTS) {
FML_DLOG(ERROR) << "Could not create directory. "
<< GetLastErrorMessage();
return {};
}
}
}
const DWORD creation_disposition = OPEN_EXISTING;
const DWORD flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS;
auto handle =
CreateFile(file_name.c_str(), // lpFileName
GetDesiredAccessFlags(permission), // dwDesiredAccess
GetShareFlags(permission), // dwShareMode
nullptr, // lpSecurityAttributes //
creation_disposition, // dwCreationDisposition //
flags, // dwFlagsAndAttributes //
nullptr // hTemplateFile //
);
if (handle == INVALID_HANDLE_VALUE) {
FML_DLOG(ERROR) << "Could not open file. " << GetLastErrorMessage();
return {};
}
return fml::UniqueFD{handle};
}
fml::UniqueFD Duplicate(fml::UniqueFD::element_type descriptor) {
@@ -127,6 +245,8 @@ fml::UniqueFD Duplicate(fml::UniqueFD::element_type descriptor) {
bool IsDirectory(const fml::UniqueFD& directory) {
BY_HANDLE_FILE_INFORMATION info;
if (!::GetFileInformationByHandle(directory.get(), &info)) {
FML_DLOG(ERROR) << "Could not get file information. "
<< GetLastErrorMessage();
return false;
}
return info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
@@ -139,4 +259,134 @@ bool IsFile(const std::string& path) {
return S_ISREG(buf.st_mode);
}
bool UnlinkDirectory(const char* path) {
if (!::RemoveDirectory(ConvertToWString(path).c_str())) {
FML_DLOG(ERROR) << "Could not remove directory: '" << path << "'. "
<< GetLastErrorMessage();
return false;
}
return true;
}
bool UnlinkDirectory(const fml::UniqueFD& base_directory, const char* path) {
if (!::RemoveDirectory(
StringToWideString(GetAbsolutePath(base_directory, path)).c_str())) {
FML_DLOG(ERROR) << "Could not remove directory: '" << path << "'. "
<< GetLastErrorMessage();
return false;
}
return true;
}
bool UnlinkFile(const char* path) {
if (!::DeleteFile(ConvertToWString(path).c_str())) {
FML_DLOG(ERROR) << "Could not remove file: '" << path << "'. "
<< GetLastErrorMessage();
return false;
}
return true;
}
bool UnlinkFile(const fml::UniqueFD& base_directory, const char* path) {
if (!::DeleteFile(
StringToWideString(GetAbsolutePath(base_directory, path)).c_str())) {
FML_DLOG(ERROR) << "Could not remove file: '" << path << "'. "
<< GetLastErrorMessage();
return false;
}
return true;
}
bool TruncateFile(const fml::UniqueFD& file, size_t size) {
LARGE_INTEGER large_size;
large_size.QuadPart = size;
large_size.LowPart = SetFilePointer(file.get(), large_size.LowPart,
&large_size.HighPart, FILE_BEGIN);
if (large_size.LowPart == INVALID_SET_FILE_POINTER &&
GetLastError() != NO_ERROR) {
FML_DLOG(ERROR) << "Could not update file size. " << GetLastErrorMessage();
return false;
}
if (!::SetEndOfFile(file.get())) {
FML_DLOG(ERROR) << "Could not commit file size update. "
<< GetLastErrorMessage();
return false;
}
return true;
}
bool WriteAtomically(const fml::UniqueFD& base_directory,
const char* file_name,
const Mapping& mapping) {
if (file_name == nullptr) {
return false;
}
auto file_path = GetAbsolutePath(base_directory, file_name);
std::stringstream stream;
stream << file_path << ".temp";
auto temp_file_path = stream.str();
auto temp_file =
OpenFile(temp_file_path.c_str(), true, FilePermission::kReadWrite);
if (!temp_file.is_valid()) {
FML_DLOG(ERROR) << "Could not create temporary file.";
return false;
}
if (!TruncateFile(temp_file, mapping.GetSize())) {
FML_DLOG(ERROR) << "Could not truncate the file to the correct size. "
<< GetLastErrorMessage();
return false;
}
{
FileMapping temp_file_mapping(temp_file, {FileMapping::Protection::kRead,
FileMapping::Protection::kWrite});
if (temp_file_mapping.GetSize() != mapping.GetSize()) {
FML_DLOG(ERROR) << "Temporary file mapping size was incorrect. Is "
<< temp_file_mapping.GetSize() << ". Should be "
<< mapping.GetSize() << ".";
return false;
}
if (temp_file_mapping.GetMutableMapping() == nullptr) {
FML_DLOG(ERROR) << "Temporary file does not have a mutable mapping.";
return false;
}
::memcpy(temp_file_mapping.GetMutableMapping(), mapping.GetMapping(),
mapping.GetSize());
if (!::FlushViewOfFile(temp_file_mapping.GetMutableMapping(),
mapping.GetSize())) {
FML_DLOG(ERROR) << "Could not flush file view. " << GetLastErrorMessage();
return false;
}
if (!::FlushFileBuffers(temp_file.get())) {
FML_DLOG(ERROR) << "Could not flush file buffers. "
<< GetLastErrorMessage();
return false;
}
// File mapping is detroyed.
}
temp_file.reset();
if (!::MoveFile(StringToWideString(temp_file_path).c_str(),
StringToWideString(file_path).c_str())) {
FML_DLOG(ERROR)
<< "Could not replace temp file at correct path. File path: "
<< file_path << ". Temp file path: " << temp_file_path << " "
<< GetLastErrorMessage();
return false;
}
return true;
}
} // namespace fml

View File

@@ -11,6 +11,7 @@
#include <type_traits>
#include "flutter/fml/file.h"
#include "flutter/fml/platform/win/errors_win.h"
#include "flutter/fml/platform/win/wstring_conversion.h"
namespace fml {
@@ -19,45 +20,79 @@ Mapping::Mapping() = default;
Mapping::~Mapping() = default;
FileMapping::FileMapping(const std::string& path, bool executable)
: FileMapping(OpenFile(path.c_str(),
executable ? OpenPermission::kExecute
: OpenPermission::kRead,
false),
executable) {}
static bool IsWritable(
std::initializer_list<FileMapping::Protection> protection_flags) {
for (auto protection : protection_flags) {
if (protection == FileMapping::Protection::kWrite) {
return true;
}
}
return false;
}
FileMapping::FileMapping(const fml::UniqueFD& fd, bool executable)
static bool IsExecutable(
std::initializer_list<FileMapping::Protection> protection_flags) {
for (auto protection : protection_flags) {
if (protection == FileMapping::Protection::kExecute) {
return true;
}
}
return false;
}
FileMapping::FileMapping(const fml::UniqueFD& fd,
std::initializer_list<Protection> protections)
: size_(0), mapping_(nullptr) {
if (!fd.is_valid()) {
return;
}
if (auto size = ::GetFileSize(fd.get(), nullptr)) {
if (size > 0) {
size_ = size;
} else {
return;
}
const auto mapping_size = ::GetFileSize(fd.get(), nullptr);
if (mapping_size == INVALID_FILE_SIZE) {
FML_DLOG(ERROR) << "Invalid file size. " << GetLastErrorMessage();
return;
}
const DWORD protect = executable ? PAGE_EXECUTE_READ : PAGE_READONLY;
DWORD protect_flags = 0;
bool read_only = !IsWritable(protections);
mapping_handle_.reset(::CreateFileMapping(fd.get(), // hFile
nullptr, // lpAttributes
protect, // flProtect
0, // dwMaximumSizeHigh
0, // dwMaximumSizeLow
nullptr // lpName
if (IsExecutable(protections)) {
protect_flags = PAGE_EXECUTE_READ;
} else if (read_only) {
protect_flags = PAGE_READONLY;
} else {
protect_flags = PAGE_READWRITE;
}
mapping_handle_.reset(::CreateFileMapping(fd.get(), // hFile
nullptr, // lpAttributes
protect_flags, // flProtect
0, // dwMaximumSizeHigh
0, // dwMaximumSizeLow
nullptr // lpName
));
if (!mapping_handle_.is_valid()) {
return;
}
const DWORD desired_access = executable ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ;
const DWORD desired_access = read_only ? FILE_MAP_READ : FILE_MAP_WRITE;
mapping_ = reinterpret_cast<uint8_t*>(
MapViewOfFile(mapping_handle_.get(), desired_access, 0, 0, size_));
auto mapping = reinterpret_cast<uint8_t*>(
MapViewOfFile(mapping_handle_.get(), desired_access, 0, 0, mapping_size));
if (mapping == nullptr) {
FML_DLOG(ERROR) << "Could not setup file mapping. "
<< GetLastErrorMessage();
return;
}
mapping_ = mapping;
size_ = mapping_size;
if (IsWritable(protections)) {
mutable_mapping_ = mapping_;
}
}
FileMapping::~FileMapping() {

View File

@@ -90,5 +90,10 @@ std::string FromURI(const std::string& uri) {
return SanitizeURIEscapedCharacters(file_path);
}
fml::UniqueFD GetCachesDirectory() {
// Unsupported on this platform.
return {};
}
} // namespace paths
} // namespace fml

View File

@@ -11,6 +11,9 @@
namespace fml {
using WideStringConvertor =
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>;
inline std::wstring ConvertToWString(const char* path) {
if (path == nullptr) {
return {};
@@ -20,6 +23,16 @@ inline std::wstring ConvertToWString(const char* path) {
return wchar_conv.from_bytes(path8);
}
inline std::wstring StringToWideString(const std::string& str) {
WideStringConvertor converter;
return converter.from_bytes(str);
}
inline std::string WideStringToString(const std::wstring& wstr) {
WideStringConvertor converter;
return converter.to_bytes(wstr);
}
} // namespace fml
#endif // FLUTTER_FML_PLATFORM_WIN_WSTRING_CONVERSION_H_

View File

@@ -43,7 +43,9 @@ static const char* kIsolateInstructionsSymbolSo =
std::unique_ptr<DartSnapshotBuffer> ResolveVMData(const Settings& settings) {
if (settings.vm_snapshot_data_path.size() > 0) {
if (auto source = DartSnapshotBuffer::CreateWithContentsOfFile(
settings.vm_snapshot_data_path.c_str(), false /* executable */)) {
fml::OpenFile(settings.vm_snapshot_data_path.c_str(), false,
fml::FilePermission::kRead),
{fml::FileMapping::Protection::kRead})) {
return source;
}
}
@@ -66,7 +68,9 @@ std::unique_ptr<DartSnapshotBuffer> ResolveVMInstructions(
const Settings& settings) {
if (settings.vm_snapshot_instr_path.size() > 0) {
if (auto source = DartSnapshotBuffer::CreateWithContentsOfFile(
settings.vm_snapshot_instr_path.c_str(), true /* executable */)) {
fml::OpenFile(settings.vm_snapshot_instr_path.c_str(), false,
fml::FilePermission::kRead),
{fml::FileMapping::Protection::kExecute})) {
return source;
}
}
@@ -89,8 +93,9 @@ std::unique_ptr<DartSnapshotBuffer> ResolveIsolateData(
const Settings& settings) {
if (settings.isolate_snapshot_data_path.size() > 0) {
if (auto source = DartSnapshotBuffer::CreateWithContentsOfFile(
settings.isolate_snapshot_data_path.c_str(),
false /* executable */)) {
fml::OpenFile(settings.isolate_snapshot_data_path.c_str(), false,
fml::FilePermission::kRead),
{fml::FileMapping::Protection::kRead})) {
return source;
}
}
@@ -113,8 +118,9 @@ std::unique_ptr<DartSnapshotBuffer> ResolveIsolateInstructions(
const Settings& settings) {
if (settings.isolate_snapshot_instr_path.size() > 0) {
if (auto source = DartSnapshotBuffer::CreateWithContentsOfFile(
settings.isolate_snapshot_instr_path.c_str(),
true /* executable */)) {
fml::OpenFile(settings.isolate_snapshot_instr_path.c_str(), false,
fml::FilePermission::kRead),
{fml::FileMapping::Protection::kExecute})) {
return source;
}
}

View File

@@ -33,8 +33,10 @@ class NativeLibrarySnapshotBuffer final : public DartSnapshotBuffer {
class FileSnapshotBuffer final : public DartSnapshotBuffer {
public:
FileSnapshotBuffer(const char* path, bool executable)
: mapping_(path, executable) {
FileSnapshotBuffer(
const fml::UniqueFD& fd,
std::initializer_list<fml::FileMapping::Protection> protection)
: mapping_(fd, protection) {
if (mapping_.GetSize() > 0) {
symbol_ = mapping_.GetMapping();
}
@@ -75,9 +77,10 @@ DartSnapshotBuffer::CreateWithSymbolInLibrary(
}
std::unique_ptr<DartSnapshotBuffer>
DartSnapshotBuffer::CreateWithContentsOfFile(const char* file_path,
bool executable) {
auto source = std::make_unique<FileSnapshotBuffer>(file_path, executable);
DartSnapshotBuffer::CreateWithContentsOfFile(
const fml::UniqueFD& fd,
std::initializer_list<fml::FileMapping::Protection> protection) {
auto source = std::make_unique<FileSnapshotBuffer>(fd, protection);
return source->GetSnapshotPointer() == nullptr ? nullptr : std::move(source);
}

View File

@@ -5,9 +5,12 @@
#ifndef FLUTTER_RUNTIME_DART_SNAPSHOT_BUFFER_H_
#define FLUTTER_RUNTIME_DART_SNAPSHOT_BUFFER_H_
#include <initializer_list>
#include <memory>
#include "flutter/fml/file.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/mapping.h"
#include "flutter/fml/native_library.h"
namespace blink {
@@ -19,8 +22,8 @@ class DartSnapshotBuffer {
const char* symbol_name);
static std::unique_ptr<DartSnapshotBuffer> CreateWithContentsOfFile(
const char* file_path,
bool executable);
const fml::UniqueFD& fd,
std::initializer_list<fml::FileMapping::Protection> protection);
static std::unique_ptr<DartSnapshotBuffer> CreateWithUnmanagedAllocation(
const uint8_t* allocation);

View File

@@ -67,6 +67,8 @@ source_set("common") {
"io_manager.h",
"isolate_configuration.cc",
"isolate_configuration.h",
"persistent_cache.cc",
"persistent_cache.h",
"platform_view.cc",
"platform_view.h",
"rasterizer.cc",

View File

@@ -5,6 +5,7 @@
#include "flutter/shell/common/io_manager.h"
#include "flutter/fml/message_loop.h"
#include "flutter/shell/common/persistent_cache.h"
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
namespace shell {
@@ -17,6 +18,8 @@ sk_sp<GrContext> IOManager::CreateCompatibleResourceLoadingContext(
GrContextOptions options = {};
options.fPersistentCache = PersistentCache::GetCacheForProcess();
// There is currently a bug with doing GPU YUV to RGB conversions on the IO
// thread. The necessary work isn't being flushed or synchronized with the
// other threads correctly, so the textures end up blank. For now, suppress

View File

@@ -0,0 +1,102 @@
// Copyright 2018 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/common/persistent_cache.h"
#include <memory>
#include <string>
#include "flutter/fml/base32.h"
#include "flutter/fml/file.h"
#include "flutter/fml/mapping.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/trace_event.h"
#include "flutter/shell/version/version.h"
namespace shell {
static std::string SkKeyToFilePath(const SkData& data) {
if (data.data() == nullptr || data.size() == 0) {
return "";
}
fml::StringView view(reinterpret_cast<const char*>(data.data()), data.size());
auto encode_result = fml::Base32Encode(view);
if (!encode_result.first) {
return "";
}
return encode_result.second;
}
PersistentCache* PersistentCache::GetCacheForProcess() {
static std::unique_ptr<PersistentCache> gPersistentCache;
static std::once_flag once = {};
std::call_once(once, []() { gPersistentCache.reset(new PersistentCache()); });
return gPersistentCache.get();
}
PersistentCache::PersistentCache()
: cache_directory_(CreateDirectory(fml::paths::GetCachesDirectory(),
{
"flutter_engine", //
GetFlutterEngineVersion(), //
"skia", //
GetSkiaVersion() //
},
fml::FilePermission::kReadWrite)) {
if (!cache_directory_.is_valid()) {
FML_LOG(ERROR) << "Could not acquire the persistent cache directory. "
"Caching of GPU resources on disk is disabled.";
}
}
PersistentCache::~PersistentCache() = default;
// |GrContextOptions::PersistentCache|
sk_sp<SkData> PersistentCache::load(const SkData& key) {
TRACE_EVENT0("flutter", "PersistentCacheLoad");
if (!cache_directory_.is_valid()) {
return nullptr;
}
auto file_name = SkKeyToFilePath(key);
if (file_name.size() == 0) {
return nullptr;
}
auto file = fml::OpenFile(cache_directory_, file_name.c_str(), false,
fml::FilePermission::kRead);
if (!file.is_valid()) {
return nullptr;
}
auto mapping = std::make_unique<fml::FileMapping>(file);
if (mapping->GetSize() == 0) {
return nullptr;
}
TRACE_EVENT0("flutter", "PersistentCacheLoadHit");
return SkData::MakeWithCopy(mapping->GetMapping(), mapping->GetSize());
}
// |GrContextOptions::PersistentCache|
void PersistentCache::store(const SkData& key, const SkData& data) {
TRACE_EVENT0("flutter", "PersistentCacheStore");
if (!cache_directory_.is_valid()) {
return;
}
auto file_name = SkKeyToFilePath(key);
auto mapping =
std::make_unique<fml::NonOwnedMapping>(data.bytes(), data.size());
if (!fml::WriteAtomically(cache_directory_, //
file_name.c_str(), //
*mapping) //
) {
FML_DLOG(ERROR) << "Could not write cache contents to persistent store.";
}
}
} // namespace shell

View File

@@ -0,0 +1,38 @@
// Copyright 2018 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_COMMON_PERSISTENT_CACHE_H_
#define FLUTTER_SHELL_COMMON_PERSISTENT_CACHE_H_
#include <mutex>
#include "flutter/fml/macros.h"
#include "flutter/fml/unique_fd.h"
#include "third_party/skia/include/gpu/GrContextOptions.h"
namespace shell {
class PersistentCache : public GrContextOptions::PersistentCache {
public:
static PersistentCache* GetCacheForProcess();
~PersistentCache() override;
private:
fml::UniqueFD cache_directory_;
PersistentCache();
// |GrContextOptions::PersistentCache|
sk_sp<SkData> load(const SkData& key) override;
// |GrContextOptions::PersistentCache|
void store(const SkData& key, const SkData& data) override;
FML_DISALLOW_COPY_AND_ASSIGN(PersistentCache);
};
} // namespace shell
#endif // FLUTTER_SHELL_COMMON_PERSISTENT_CACHE_H_

View File

@@ -20,8 +20,8 @@ RunConfiguration RunConfiguration::InferFromSettings(
fml::Duplicate(settings.assets_dir)));
asset_manager->PushBack(
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenFile(
settings.assets_path.c_str(), fml::OpenPermission::kRead, true)));
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenDirectory(
settings.assets_path.c_str(), false, fml::FilePermission::kRead)));
return {IsolateConfiguration::InferFromSettings(settings, asset_manager),
asset_manager};

View File

@@ -873,7 +873,8 @@ bool Shell::OnServiceProtocolRunInView(
fml::paths::FromURI(params.at("assetDirectory").ToString());
auto main_script_file_mapping =
std::make_unique<fml::FileMapping>(main_script_path, false);
std::make_unique<fml::FileMapping>(fml::OpenFile(
main_script_path.c_str(), false, fml::FilePermission::kRead));
auto isolate_configuration = IsolateConfiguration::CreateForKernel(
std::move(main_script_file_mapping));
@@ -881,8 +882,8 @@ bool Shell::OnServiceProtocolRunInView(
RunConfiguration configuration(std::move(isolate_configuration));
configuration.AddAssetResolver(
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenFile(
asset_directory_path.c_str(), fml::OpenPermission::kRead, true)));
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenDirectory(
asset_directory_path.c_str(), false, fml::FilePermission::kRead)));
auto& allocator = response.GetAllocator();
response.SetObject();
@@ -938,8 +939,8 @@ bool Shell::OnServiceProtocolSetAssetBundlePath(
auto asset_manager = fml::MakeRefCounted<blink::AssetManager>();
asset_manager->PushFront(std::make_unique<blink::DirectoryAssetBundle>(
fml::OpenFile(params.at("assetDirectory").ToString().c_str(),
fml::OpenPermission::kRead, true)));
fml::OpenDirectory(params.at("assetDirectory").ToString().c_str(), false,
fml::FilePermission::kRead)));
if (engine_->UpdateAssetManager(std::move(asset_manager))) {
response.AddMember("type", "Success", allocator);

View File

@@ -7,6 +7,7 @@
#include "flutter/fml/arraysize.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "flutter/shell/common/persistent_cache.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
@@ -46,6 +47,9 @@ GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate)
proc_resolver_ = delegate_->GetGLProcResolver();
GrContextOptions options;
options.fPersistentCache = PersistentCache::GetCacheForProcess();
options.fAvoidStencilBuffers = true;
// To get video playback on the widest range of devices, we limit Skia to

View File

@@ -15,6 +15,7 @@
#include "flutter/fml/message_loop.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/platform/android/jni_util.h"
#include "flutter/fml/platform/android/paths_android.h"
#include "flutter/lib/ui/plugins/callback_cache.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/runtime/start_up.h"
@@ -46,7 +47,8 @@ void FlutterMain::Init(JNIEnv* env,
jobject context,
jobjectArray jargs,
jstring bundlePath,
jstring appStoragePath) {
jstring appStoragePath,
jstring engineCachesPath) {
std::vector<std::string> args;
args.push_back("flutter");
for (auto& arg : fml::jni::StringArrayToVector(env, jargs)) {
@@ -59,8 +61,14 @@ void FlutterMain::Init(JNIEnv* env,
settings.assets_path = fml::jni::JavaStringToString(env, bundlePath);
// Restore the callback cache.
// TODO(chinmaygarde): Route all cache file access through FML and remove this
// setter.
blink::DartCallbackCache::SetCachePath(
fml::jni::JavaStringToString(env, appStoragePath));
fml::paths::InitializeAndroidCachesPath(
fml::jni::JavaStringToString(env, engineCachesPath));
blink::DartCallbackCache::LoadCacheFromDisk();
if (!blink::DartVM::IsRunningPrecompiledCode()) {
@@ -99,7 +107,7 @@ bool FlutterMain::Register(JNIEnv* env) {
{
.name = "nativeInit",
.signature = "(Landroid/content/Context;[Ljava/lang/String;Ljava/"
"lang/String;Ljava/lang/String;)V",
"lang/String;Ljava/lang/String;Ljava/lang/String;)V",
.fnPtr = reinterpret_cast<void*>(&Init),
},
{

View File

@@ -32,7 +32,8 @@ class FlutterMain {
jobject context,
jobjectArray jargs,
jstring bundlePath,
jstring appRootPath);
jstring appRootPath,
jstring engineCachesPath);
FML_DISALLOW_COPY_AND_ASSIGN(FlutterMain);
};

View File

@@ -214,8 +214,9 @@ public class FlutterMain {
String appBundlePath = findAppBundlePath(applicationContext);
String appStoragePath = PathUtils.getFilesDir(applicationContext);
String engineCachesPath = PathUtils.getCacheDirectory(applicationContext);
nativeInit(applicationContext, shellArgs.toArray(new String[0]),
appBundlePath, appStoragePath);
appBundlePath, appStoragePath, engineCachesPath);
sInitialized = true;
} catch (Exception e) {
@@ -224,7 +225,7 @@ public class FlutterMain {
}
}
private static native void nativeInit(Context context, String[] args, String bundlePath, String appStoragePath);
private static native void nativeInit(Context context, String[] args, String bundlePath, String appStoragePath, String engineCachesPath);
private static native void nativeRecordStartTimestamp(long initTimeMillis);
/**

View File

@@ -252,8 +252,9 @@ static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
asset_manager->PushBack(
std::make_unique<blink::ZipAssetStore>(bundlepath));
} else {
asset_manager->PushBack(std::make_unique<blink::DirectoryAssetBundle>(
fml::OpenFile(bundlepath.c_str(), fml::OpenPermission::kRead, true)));
asset_manager->PushBack(
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenDirectory(
bundlepath.c_str(), false, fml::FilePermission::kRead)));
}
// Use the last path component of the bundle path to determine the
@@ -273,8 +274,9 @@ static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
const auto defaultpath = fml::jni::JavaStringToString(env, jdefaultPath);
if (defaultpath.size() > 0) {
asset_manager->PushBack(std::make_unique<blink::DirectoryAssetBundle>(
fml::OpenFile(defaultpath.c_str(), fml::OpenPermission::kRead, true)));
asset_manager->PushBack(
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenDirectory(
defaultpath.c_str(), false, fml::FilePermission::kRead)));
}
auto isolate_configuration = CreateIsolateConfiguration(*asset_manager);

View File

@@ -370,8 +370,8 @@ FlutterResult FlutterEngineRun(size_t version,
fml::Duplicate(settings.assets_dir)));
run_configuration.AddAssetResolver(
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenFile(
settings.assets_path.c_str(), fml::OpenPermission::kRead, true)));
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenDirectory(
settings.assets_path.c_str(), false, fml::FilePermission::kRead)));
if (!embedder_engine->Run(std::move(run_configuration))) {
return kInvalidArguments;

View File

@@ -129,8 +129,13 @@ int RunTester(const blink::Settings& settings, bool run_forever) {
return EXIT_FAILURE;
}
std::initializer_list<fml::FileMapping::Protection> protection = {
fml::FileMapping::Protection::kRead};
auto main_dart_file_mapping = std::make_unique<fml::FileMapping>(
fml::paths::AbsolutePath(settings.main_dart_file_path), false);
fml::OpenFile(
fml::paths::AbsolutePath(settings.main_dart_file_path).c_str(), false,
fml::FilePermission::kRead),
protection);
auto isolate_configuration =
IsolateConfiguration::CreateForKernel(std::move(main_dart_file_mapping));
@@ -144,8 +149,8 @@ int RunTester(const blink::Settings& settings, bool run_forever) {
asset_manager->PushBack(std::make_unique<blink::DirectoryAssetBundle>(
fml::Duplicate(settings.assets_dir)));
asset_manager->PushBack(
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenFile(
settings.assets_path.c_str(), fml::OpenPermission::kRead, true)));
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenDirectory(
settings.assets_path.c_str(), false, fml::FilePermission::kRead)));
RunConfiguration run_configuration(std::move(isolate_configuration),
std::move(asset_manager));