未验证 提交 a3327bff 编写于 作者: C Chinmay Garde 提交者: GitHub

Re-land "Support multiple shells in a single process. (#4932)" (#4977)

This reverts commit 9199b40f.
上级 13fd804e
......@@ -10,14 +10,12 @@ group("flutter") {
public_deps = [
"$flutter_root/lib/snapshot:generate_snapshot_bin",
"$flutter_root/lib/snapshot:kernel_platform_files",
"$flutter_root/shell/testing",
"$flutter_root/sky",
"$flutter_root/third_party/txt",
]
if (flutter_runtime_mode != "debug") {
public_deps += [
"$flutter_root/lib/snapshot:entry_points_json_files",
]
public_deps += [ "$flutter_root/lib/snapshot:entry_points_json_files" ]
}
if (!is_fuchsia && !is_fuchsia_host) {
......@@ -45,20 +43,24 @@ group("flutter") {
"$flutter_root/shell/platform/embedder:flutter_embedder_framework",
]
}
if (!is_win) {
public_deps += [
"$flutter_root/shell/platform/embedder:embedder_unittests",
"$flutter_root/shell/platform/embedder:flutter_engine",
]
}
public_deps += [
"$flutter_root/flow:flow_unittests",
"$flutter_root/fml:fml_unittests",
"$flutter_root/runtime:runtime_unittests",
"$flutter_root/shell/common:shell_unittests",
"$flutter_root/sky/engine/wtf:wtf_unittests",
"$flutter_root/synchronization:synchronization_unittests",
"$flutter_root/third_party/txt:txt_unittests",
"//garnet/public/lib/fxl:fxl_unittests",
]
if (!is_win) {
public_deps += [
"$flutter_root/shell/platform/embedder:embedder_unittests",
"$flutter_root/shell/platform/embedder:flutter_engine",
]
}
}
}
......@@ -74,29 +76,23 @@ if (is_fuchsia) {
"$flutter_root/content_handler:aot",
]
if (flutter_runtime_mode != "release") {
deps += [
"//third_party/dart/runtime/observatory:embedded_archive_observatory",
]
deps += [ "//third_party/dart/runtime/observatory:embedded_archive_observatory" ]
}
binary = "flutter_aot_runner"
if (flutter_runtime_mode != "release") {
resources = [
{
path = rebase_path(
"$root_gen_dir/observatory/embedded_archive_observatory.tar")
dest = "observatory.tar"
},
]
resources = [ {
path = rebase_path(
"$root_gen_dir/observatory/embedded_archive_observatory.tar")
dest = "observatory.tar"
} ]
}
meta = [
{
path = rebase_path("content_handler/meta/sandbox")
dest = "sandbox"
},
]
meta = [ {
path = rebase_path("content_handler/meta/sandbox")
dest = "sandbox"
} ]
}
package("flutter_jit_runner") {
......@@ -104,29 +100,23 @@ if (is_fuchsia) {
"$flutter_root/content_handler:jit",
]
if (flutter_runtime_mode != "release") {
deps += [
"//third_party/dart/runtime/observatory:embedded_archive_observatory",
]
deps += [ "//third_party/dart/runtime/observatory:embedded_archive_observatory" ]
}
binary = "flutter_jit_runner"
if (flutter_runtime_mode != "release") {
resources = [
{
path = rebase_path(
"$root_gen_dir/observatory/embedded_archive_observatory.tar")
dest = "observatory.tar"
},
]
resources = [ {
path = rebase_path(
"$root_gen_dir/observatory/embedded_archive_observatory.tar")
dest = "observatory.tar"
} ]
}
meta = [
{
path = rebase_path("content_handler/meta/sandbox")
dest = "sandbox"
},
]
meta = [ {
path = rebase_path("content_handler/meta/sandbox")
dest = "sandbox"
} ]
}
} else {
group("dist") {
......
......@@ -115,7 +115,7 @@ allowed_hosts = [
]
deps = {
'src': 'https://github.com/flutter/buildroot.git' + '@' + '8dddd90bf943a8174913564353b30a3b11ee0f7a',
'src': 'https://github.com/flutter/buildroot.git' + '@' + '3cf97e01cdbd4bb920fa3d40282a56c4b2d62a58',
# Fuchsia compatibility
#
......
......@@ -4,16 +4,18 @@
source_set("assets") {
sources = [
"asset_provider.h",
"asset_manager.cc",
"asset_manager.h",
"asset_resolver.h",
"directory_asset_bundle.cc",
"directory_asset_bundle.h",
"unzipper_provider.cc",
"unzipper_provider.h",
"zip_asset_store.cc",
"zip_asset_store.h",
]
deps = [
"$flutter_root/common",
"$flutter_root/fml",
"$flutter_root/glue",
"//garnet/public/lib/fxl",
"//garnet/public/lib/zip",
......@@ -23,7 +25,5 @@ source_set("assets") {
"//third_party/zlib:minizip",
]
public_configs = [
"$flutter_root:config",
]
public_configs = [ "$flutter_root:config" ]
}
// Copyright 2017 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/assets/asset_manager.h"
#include "flutter/assets/directory_asset_bundle.h"
#include "flutter/assets/zip_asset_store.h"
#include "flutter/glue/trace_event.h"
#include "lib/fxl/files/path.h"
#ifdef ERROR
#undef ERROR
#endif
namespace blink {
AssetManager::AssetManager() = default;
AssetManager::~AssetManager() = default;
void AssetManager::PushFront(std::unique_ptr<AssetResolver> resolver) {
if (resolver == nullptr || !resolver->IsValid()) {
return;
}
resolvers_.push_front(std::move(resolver));
}
void AssetManager::PushBack(std::unique_ptr<AssetResolver> resolver) {
if (resolver == nullptr || !resolver->IsValid()) {
return;
}
resolvers_.push_back(std::move(resolver));
}
// |blink::AssetResolver|
bool AssetManager::GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const {
if (asset_name.size() == 0) {
return false;
}
TRACE_EVENT0("flutter", "AssetManager::GetAsBuffer");
for (const auto& resolver : resolvers_) {
if (resolver->GetAsBuffer(asset_name, data)) {
return true;
}
}
FXL_DLOG(ERROR) << "Could not find asset: " << asset_name;
return false;
}
// |blink::AssetResolver|
bool AssetManager::IsValid() const {
return resolvers_.size() > 0;
}
} // namespace blink
// Copyright 2017 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_ASSETS_ASSET_MANAGER_H_
#define FLUTTER_ASSETS_ASSET_MANAGER_H_
#include <deque>
#include <memory>
#include <string>
#include "flutter/assets/asset_resolver.h"
#include "lib/fxl/files/unique_fd.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/memory/ref_counted.h"
namespace blink {
class AssetManager final : public AssetResolver,
public fxl::RefCountedThreadSafe<AssetManager> {
public:
void PushFront(std::unique_ptr<AssetResolver> resolver);
void PushBack(std::unique_ptr<AssetResolver> resolver);
// |blink::AssetResolver|
bool IsValid() const override;
// |blink::AssetResolver|
bool GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const override;
private:
std::deque<std::unique_ptr<AssetResolver>> resolvers_;
AssetManager();
~AssetManager();
FXL_DISALLOW_COPY_AND_ASSIGN(AssetManager);
FRIEND_MAKE_REF_COUNTED(AssetManager);
FRIEND_REF_COUNTED_THREAD_SAFE(AssetManager);
};
} // namespace blink
#endif // FLUTTER_ASSETS_ASSET_MANAGER_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Copyright 2017 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_ASSETS_ASSET_PROVIDER_H_
#define FLUTTER_ASSETS_ASSET_PROVIDER_H_
#ifndef FLUTTER_ASSETS_ASSET_RESOLVER_H_
#define FLUTTER_ASSETS_ASSET_RESOLVER_H_
#include <string>
#include <vector>
#include "lib/fxl/memory/ref_counted.h"
#include "lib/fxl/macros.h"
namespace blink {
class AssetProvider
: public fxl::RefCountedThreadSafe<AssetProvider>
{
class AssetResolver {
public:
AssetResolver() = default;
virtual ~AssetResolver() = default;
virtual bool IsValid() const = 0;
virtual bool GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) = 0;
virtual ~AssetProvider() = default;
std::vector<uint8_t>* data) const = 0;
private:
FXL_DISALLOW_COPY_AND_ASSIGN(AssetResolver);
};
} // namespace blink
#endif // FLUTTER_ASSETS_ASSET_PROVIDER_H
#endif // FLUTTER_ASSETS_ASSET_RESOLVER_H_
......@@ -3,73 +3,54 @@
// found in the LICENSE file.
#include "flutter/assets/directory_asset_bundle.h"
#include "lib/fxl/build_config.h"
#include <fcntl.h>
#include <utility>
#include "flutter/fml/file.h"
#include "flutter/fml/mapping.h"
#include "lib/fxl/files/eintr_wrapper.h"
#include "lib/fxl/files/file.h"
#include "lib/fxl/files/path.h"
#include "lib/fxl/files/unique_fd.h"
#include "lib/fxl/portable_unistd.h"
namespace blink {
bool DirectoryAssetBundle::GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) {
if (fd_.is_valid()) {
#if defined(OS_WIN)
// This code path is not valid in a Windows environment.
return false;
#else
fxl::UniqueFD asset_file(openat(fd_.get(), asset_name.c_str(), O_RDONLY));
if (!asset_file.is_valid())
return false;
constexpr size_t kBufferSize = 1 << 16;
size_t offset = 0;
ssize_t bytes_read = 0;
do {
offset += bytes_read;
data->resize(offset + kBufferSize);
bytes_read = read(asset_file.get(), &(*data)[offset], kBufferSize);
} while (bytes_read > 0);
DirectoryAssetBundle::DirectoryAssetBundle(fml::UniqueFD descriptor)
: descriptor_(std::move(descriptor)) {
if (!fml::IsDirectory(descriptor_)) {
return;
}
is_valid_ = true;
}
if (bytes_read < 0) {
FXL_LOG(ERROR) << "Reading " << asset_name << " failed";
data->clear();
return false;
}
DirectoryAssetBundle::~DirectoryAssetBundle() = default;
data->resize(offset + bytes_read);
return true;
#endif
}
std::string asset_path = GetPathForAsset(asset_name);
if (asset_path.empty())
return false;
return files::ReadFileToVector(asset_path, data);
// |blink::AssetResolver|
bool DirectoryAssetBundle::IsValid() const {
return is_valid_;
}
DirectoryAssetBundle::~DirectoryAssetBundle() {}
// |blink::AssetResolver|
bool DirectoryAssetBundle::GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const {
if (data == nullptr) {
return false;
}
DirectoryAssetBundle::DirectoryAssetBundle(std::string directory)
: directory_(std::move(directory)), fd_() {}
if (!is_valid_) {
FXL_DLOG(WARNING) << "Asset bundle was not valid.";
return false;
}
DirectoryAssetBundle::DirectoryAssetBundle(fxl::UniqueFD fd)
: fd_(std::move(fd)) {}
fml::FileMapping mapping(
fml::OpenFile(descriptor_, asset_name.c_str(), fml::OpenPermission::kRead,
false /* directory */),
false /* executable */);
std::string DirectoryAssetBundle::GetPathForAsset(
const std::string& asset_name) {
std::string asset_path = files::SimplifyPath(directory_ + "/" + asset_name);
if (asset_path.find(directory_) != 0u) {
FXL_LOG(ERROR) << "Asset name '" << asset_name
<< "' attempted to traverse outside asset bundle.";
return std::string();
if (mapping.GetMapping() == nullptr) {
return false;
}
return asset_path;
data->resize(mapping.GetSize());
memmove(data->data(), mapping.GetMapping(), mapping.GetSize());
return true;
}
} // namespace blink
......@@ -5,31 +5,31 @@
#ifndef FLUTTER_ASSETS_DIRECTORY_ASSET_BUNDLE_H_
#define FLUTTER_ASSETS_DIRECTORY_ASSET_BUNDLE_H_
#include <string>
#include <vector>
#include "flutter/assets/asset_provider.h"
#include "lib/fxl/files/unique_fd.h"
#include "flutter/assets/asset_resolver.h"
#include "flutter/fml/unique_fd.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/memory/ref_counted.h"
namespace blink {
class DirectoryAssetBundle
: public AssetProvider {
class DirectoryAssetBundle : public AssetResolver {
public:
explicit DirectoryAssetBundle(std::string directory);
// Expects fd to be valid, otherwise the file descriptor is ignored.
explicit DirectoryAssetBundle(fxl::UniqueFD fd);
virtual ~DirectoryAssetBundle();
virtual bool GetAsBuffer(const std::string& asset_name, std::vector<uint8_t>* data);
explicit DirectoryAssetBundle(fml::UniqueFD descriptor);
std::string GetPathForAsset(const std::string& asset_name);
~DirectoryAssetBundle() override;
private:
const std::string directory_;
fxl::UniqueFD fd_;
const fml::UniqueFD descriptor_;
bool is_valid_ = false;
std::string GetPathForAsset(const std::string& asset_name) const;
// |blink::AssetResolver|
bool IsValid() const override;
// |blink::AssetResolver|
bool GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const override;
FXL_DISALLOW_COPY_AND_ASSIGN(DirectoryAssetBundle);
};
......
// Copyright 2016 The Chromium 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/assets/unzipper_provider.h"
#include "lib/fxl/logging.h"
#include "third_party/zlib/contrib/minizip/unzip.h"
namespace blink {
UnzipperProvider GetUnzipperProviderForPath(std::string zip_path) {
return [zip_path]() {
zip::UniqueUnzipper unzipper(unzOpen2(zip_path.c_str(), nullptr));
if (!unzipper.is_valid())
FXL_LOG(ERROR) << "Unable to open zip file: " << zip_path;
return unzipper;
};
}
} // namespace blink
// Copyright 2016 The Chromium 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_ASSETS_UNZIP_PROVIDER_H_
#define FLUTTER_ASSETS_UNZIP_PROVIDER_H_
#include <functional>
#include "lib/zip/unique_unzipper.h"
namespace blink {
using UnzipperProvider = std::function<zip::UniqueUnzipper()>;
UnzipperProvider GetUnzipperProviderForPath(std::string zip_path);
} // namespace blink
#endif // FLUTTER_ASSETS_UNZIP_PROVIDER_H_
......@@ -15,21 +15,28 @@
#include <utility>
#include "flutter/glue/trace_event.h"
#include "lib/fxl/files/eintr_wrapper.h"
#include "lib/fxl/files/unique_fd.h"
#include "lib/zip/unique_unzipper.h"
namespace blink {
ZipAssetStore::ZipAssetStore(UnzipperProvider unzipper_provider)
: unzipper_provider_(std::move(unzipper_provider)) {
ZipAssetStore::ZipAssetStore(std::string file_path)
: file_path_(std::move(file_path)) {
BuildStatCache();
}
ZipAssetStore::~ZipAssetStore() = default;
zip::UniqueUnzipper ZipAssetStore::CreateUnzipper() const {
return zip::UniqueUnzipper{::unzOpen2(file_path_.c_str(), nullptr)};
}
// |blink::AssetResolver|
bool ZipAssetStore::IsValid() const {
return stat_cache_.size() > 0;
}
// |blink::AssetResolver|
bool ZipAssetStore::GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) {
std::vector<uint8_t>* data) const {
TRACE_EVENT0("flutter", "ZipAssetStore::GetAsBuffer");
auto found = stat_cache_.find(asset_name);
......@@ -37,7 +44,7 @@ bool ZipAssetStore::GetAsBuffer(const std::string& asset_name,
return false;
}
auto unzipper = unzipper_provider_();
auto unzipper = CreateUnzipper();
if (!unzipper.is_valid()) {
return false;
......@@ -73,7 +80,8 @@ bool ZipAssetStore::GetAsBuffer(const std::string& asset_name,
void ZipAssetStore::BuildStatCache() {
TRACE_EVENT0("flutter", "ZipAssetStore::BuildStatCache");
auto unzipper = unzipper_provider_();
auto unzipper = CreateUnzipper();
if (!unzipper.is_valid()) {
return;
......
......@@ -6,21 +6,20 @@
#define FLUTTER_ASSETS_ZIP_ASSET_STORE_H_
#include <map>
#include <vector>
#include "flutter/assets/unzipper_provider.h"
#include "flutter/assets/asset_resolver.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/memory/ref_counted.h"
#include "lib/zip/unique_unzipper.h"
#include "third_party/zlib/contrib/minizip/unzip.h"
namespace blink {
class ZipAssetStore : public fxl::RefCountedThreadSafe<ZipAssetStore> {
class ZipAssetStore final : public AssetResolver {
public:
explicit ZipAssetStore(UnzipperProvider unzipper_provider);
~ZipAssetStore();
ZipAssetStore(std::string file_path);
bool GetAsBuffer(const std::string& asset_name, std::vector<uint8_t>* data);
~ZipAssetStore() override;
private:
struct CacheEntry {
......@@ -30,11 +29,20 @@ class ZipAssetStore : public fxl::RefCountedThreadSafe<ZipAssetStore> {
: file_pos(p_file_pos), uncompressed_size(p_uncompressed_size) {}
};
UnzipperProvider unzipper_provider_;
std::map<std::string, CacheEntry> stat_cache_;
std::string file_path_;
mutable std::map<std::string, CacheEntry> stat_cache_;
// |blink::AssetResolver|
bool IsValid() const override;
// |blink::AssetResolver|
bool GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const override;
void BuildStatCache();
zip::UniqueUnzipper CreateUnzipper() const;
FXL_DISALLOW_COPY_AND_ASSIGN(ZipAssetStore);
};
......
......@@ -12,11 +12,12 @@ source_set("common") {
sources = [
"settings.cc",
"settings.h",
"threads.cc",
"threads.h",
"task_runners.cc",
"task_runners.h",
]
deps = [
"$flutter_root/fml",
"//garnet/public/lib/fxl",
]
......
......@@ -4,26 +4,50 @@
#include "flutter/common/settings.h"
#include <memory>
#include "lib/fxl/logging.h"
#include <sstream>
namespace blink {
namespace {
Settings* g_settings = nullptr;
} // namespace
const Settings& Settings::Get() {
FXL_CHECK(g_settings);
return *g_settings;
}
void Settings::Set(const Settings& settings) {
FXL_CHECK(!g_settings);
g_settings = new Settings();
*g_settings = settings;
std::string Settings::ToString() const {
std::stringstream stream;
stream << "Settings: " << std::endl;
stream << "aot_snapshot_path: " << aot_snapshot_path << std::endl;
stream << "script_snapshot_path: " << script_snapshot_path << std::endl;
stream << "aot_vm_snapshot_data_filename: " << aot_vm_snapshot_data_filename
<< std::endl;
stream << "aot_vm_snapshot_instr_filename: " << aot_vm_snapshot_instr_filename
<< std::endl;
stream << "aot_isolate_snapshot_data_filename: "
<< aot_isolate_snapshot_data_filename << std::endl;
stream << "aot_isolate_snapshot_instr_filename: "
<< aot_isolate_snapshot_instr_filename << std::endl;
stream << "application_library_path: " << application_library_path
<< std::endl;
stream << "main_dart_file_path: " << main_dart_file_path << std::endl;
stream << "packages_file_path: " << packages_file_path << std::endl;
stream << "temp_directory_path: " << temp_directory_path << std::endl;
stream << "dart_flags:" << std::endl;
for (const auto& dart_flag : dart_flags) {
stream << " " << dart_flag << std::endl;
}
stream << "start_paused: " << start_paused << std::endl;
stream << "trace_skia: " << trace_skia << std::endl;
stream << "trace_startup: " << trace_startup << std::endl;
stream << "endless_trace_buffer: " << endless_trace_buffer << std::endl;
stream << "enable_dart_profiling: " << enable_dart_profiling << std::endl;
stream << "dart_non_checked_mode: " << dart_non_checked_mode << std::endl;
stream << "enable_observatory: " << enable_observatory << std::endl;
stream << "observatory_port: " << observatory_port << std::endl;
stream << "ipv6: " << ipv6 << std::endl;
stream << "use_test_fonts: " << use_test_fonts << std::endl;
stream << "enable_software_rendering: " << enable_software_rendering
<< std::endl;
stream << "using_blink: " << using_blink << std::endl;
stream << "log_tag: " << log_tag << std::endl;
stream << "icu_data_path: " << icu_data_path << std::endl;
stream << "assets_dir: " << assets_dir << std::endl;
stream << "assets_path: " << assets_path << std::endl;
return stream.str();
}
} // namespace blink
......@@ -5,40 +5,82 @@
#ifndef FLUTTER_COMMON_SETTINGS_H_
#define FLUTTER_COMMON_SETTINGS_H_
#include <fcntl.h>
#include <stdint.h>
#include <memory>
#include <string>
#include <vector>
#include "flutter/fml/unique_fd.h"
#include "lib/fxl/functional/closure.h"
namespace blink {
using TaskObserverAdd =
std::function<void(intptr_t /* key */, fxl::Closure /* callback */)>;
using TaskObserverRemove = std::function<void(intptr_t /* key */)>;
struct Settings {
bool enable_observatory = false;
// Port on target will be auto selected by the OS. A message will be printed
// on the target with the port after it has been selected.
uint32_t observatory_port = 0;
bool ipv6 = false;
bool start_paused = false;
bool trace_startup = false;
bool endless_trace_buffer = false;
bool enable_dart_profiling = false;
bool use_test_fonts = false;
bool dart_non_checked_mode = false;
bool enable_software_rendering = false;
bool using_blink = true;
std::string aot_shared_library_path;
// VM settings
std::string script_snapshot_path;
std::string kernel_snapshot_path;
std::string aot_snapshot_path;
std::string aot_vm_snapshot_data_filename;
std::string aot_vm_snapshot_instr_filename;
std::string aot_isolate_snapshot_data_filename;
std::string aot_isolate_snapshot_instr_filename;
std::string application_library_path;
std::string application_kernel_asset;
std::string main_dart_file_path;
std::string packages_file_path;
std::string temp_directory_path;
std::vector<std::string> dart_flags;
// Isolate settings
bool start_paused = false;
bool trace_skia = false;
bool trace_startup = false;
bool endless_trace_buffer = false;
bool enable_dart_profiling = false;
bool dart_non_checked_mode = false;
// Observatory settings
bool enable_observatory = false;
// Port on target will be auto selected by the OS. A message will be printed
// on the target with the port after it has been selected.
uint32_t observatory_port = 0;
bool ipv6 = false;
// Font settings
bool use_test_fonts = false;
// Engine settings
TaskObserverAdd task_observer_add;
TaskObserverRemove task_observer_remove;
// The main isolate is current when this callback is made. This is a good spot
// to perform native Dart bindings for libraries not built in.
fxl::Closure root_isolate_create_callback;
// The isolate is not current and may have already been destroyed when this
// call is made.
fxl::Closure root_isolate_shutdown_callback;
bool enable_software_rendering = false;
bool using_blink = false;
bool skia_deterministic_rendering_on_cpu = false;
std::string log_tag = "flutter";
std::string icu_data_path;
// Assets settings
fml::UniqueFD::element_type assets_dir =
fml::UniqueFD::traits_type::InvalidValue();
std::string assets_path;
std::string flx_path;
static const Settings& Get();
static void Set(const Settings& settings);
std::string ToString() const;
};
} // namespace blink
......
// Copyright 2017 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/common/task_runners.h"
#include <utility>
namespace blink {
TaskRunners::TaskRunners(std::string label,
fxl::RefPtr<fxl::TaskRunner> platform,
fxl::RefPtr<fxl::TaskRunner> gpu,
fxl::RefPtr<fxl::TaskRunner> ui,
fxl::RefPtr<fxl::TaskRunner> io)
: label_(std::move(label)),
platform_(std::move(platform)),
gpu_(std::move(gpu)),
ui_(std::move(ui)),
io_(std::move(io)) {}
TaskRunners::~TaskRunners() = default;
const std::string& TaskRunners::GetLabel() const {
return label_;
}
fxl::RefPtr<fxl::TaskRunner> TaskRunners::GetPlatformTaskRunner() const {
return platform_;
}
fxl::RefPtr<fxl::TaskRunner> TaskRunners::GetUITaskRunner() const {
return ui_;
}
fxl::RefPtr<fxl::TaskRunner> TaskRunners::GetIOTaskRunner() const {
return io_;
}
fxl::RefPtr<fxl::TaskRunner> TaskRunners::GetGPUTaskRunner() const {
return gpu_;
}
bool TaskRunners::IsValid() const {
return platform_ && gpu_ && ui_ && io_;
}
} // namespace blink
// Copyright 2017 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_COMMON_TASK_RUNNERS_H_
#define FLUTTER_COMMON_TASK_RUNNERS_H_
#include <string>
#include "lib/fxl/macros.h"
#include "lib/fxl/tasks/task_runner.h"
namespace blink {
class TaskRunners {
public:
TaskRunners(std::string label,
fxl::RefPtr<fxl::TaskRunner> platform,
fxl::RefPtr<fxl::TaskRunner> gpu,
fxl::RefPtr<fxl::TaskRunner> ui,
fxl::RefPtr<fxl::TaskRunner> io);
~TaskRunners();
const std::string& GetLabel() const;
fxl::RefPtr<fxl::TaskRunner> GetPlatformTaskRunner() const;
fxl::RefPtr<fxl::TaskRunner> GetUITaskRunner() const;
fxl::RefPtr<fxl::TaskRunner> GetIOTaskRunner() const;
fxl::RefPtr<fxl::TaskRunner> GetGPUTaskRunner() const;
bool IsValid() const;
private:
const std::string label_;
fxl::RefPtr<fxl::TaskRunner> platform_;
fxl::RefPtr<fxl::TaskRunner> gpu_;
fxl::RefPtr<fxl::TaskRunner> ui_;
fxl::RefPtr<fxl::TaskRunner> io_;
};
} // namespace blink
#endif // FLUTTER_COMMON_TASK_RUNNERS_H_
// Copyright 2016 The Chromium 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/common/threads.h"
#include <utility>
namespace blink {
namespace {
Threads* g_threads = nullptr;
} // namespace
Threads::Threads() {}
Threads::Threads(fxl::RefPtr<fxl::TaskRunner> platform,
fxl::RefPtr<fxl::TaskRunner> gpu,
fxl::RefPtr<fxl::TaskRunner> ui,
fxl::RefPtr<fxl::TaskRunner> io)
: platform_(std::move(platform)),
gpu_(std::move(gpu)),
ui_(std::move(ui)),
io_(std::move(io)) {}
Threads::~Threads() {}
const fxl::RefPtr<fxl::TaskRunner>& Threads::Platform() {
return Get().platform_;
}
const fxl::RefPtr<fxl::TaskRunner>& Threads::Gpu() {
return Get().gpu_;
}
const fxl::RefPtr<fxl::TaskRunner>& Threads::UI() {
return Get().ui_;
}
const fxl::RefPtr<fxl::TaskRunner>& Threads::IO() {
return Get().io_;
}
const Threads& Threads::Get() {
FXL_CHECK(g_threads);
return *g_threads;
}
void Threads::Set(const Threads& threads) {
FXL_CHECK(!g_threads);
g_threads = new Threads();
*g_threads = threads;
}
} // namespace blink
// Copyright 2016 The Chromium 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_COMMON_THREADS_H_
#define FLUTTER_COMMON_THREADS_H_
#include "lib/fxl/tasks/task_runner.h"
#define ASSERT_IS_PLATFORM_THREAD \
FXL_DCHECK(::blink::Threads::Platform()->RunsTasksOnCurrentThread());
#define ASSERT_IS_GPU_THREAD \
FXL_DCHECK(::blink::Threads::Gpu()->RunsTasksOnCurrentThread());
#define ASSERT_IS_UI_THREAD \
FXL_DCHECK(::blink::Threads::UI()->RunsTasksOnCurrentThread());
#define ASSERT_IS_IO_THREAD \
FXL_DCHECK(::blink::Threads::IO()->RunsTasksOnCurrentThread());
namespace blink {
class Threads {
public:
Threads();
Threads(fxl::RefPtr<fxl::TaskRunner> platform,
fxl::RefPtr<fxl::TaskRunner> gpu,
fxl::RefPtr<fxl::TaskRunner> ui,
fxl::RefPtr<fxl::TaskRunner> io);
~Threads();
static const fxl::RefPtr<fxl::TaskRunner>& Platform();
static const fxl::RefPtr<fxl::TaskRunner>& Gpu();
static const fxl::RefPtr<fxl::TaskRunner>& UI();
static const fxl::RefPtr<fxl::TaskRunner>& IO();
static void Set(const Threads& settings);
private:
static const Threads& Get();
fxl::RefPtr<fxl::TaskRunner> platform_;
fxl::RefPtr<fxl::TaskRunner> gpu_;
fxl::RefPtr<fxl::TaskRunner> ui_;
fxl::RefPtr<fxl::TaskRunner> io_;
};
} // namespace blink
#endif // FLUTTER_COMMON_THREADS_H_
......@@ -20,23 +20,28 @@ template("flutter_content_handler") {
sources = [
"accessibility_bridge.cc",
"accessibility_bridge.h",
"app.cc",
"app.h",
"application_controller_impl.cc",
"application_controller_impl.h",
"application.cc",
"application.h",
"application_runner.cc",
"application_runner.h",
"compositor_context.cc",
"compositor_context.h",
"engine.cc",
"engine.h",
"fuchsia_font_manager.cc",
"fuchsia_font_manager.h",
"isolate_configurator.cc",
"isolate_configurator.h",
"main.cc",
"rasterizer.cc",
"rasterizer.h",
"runtime_holder.cc",
"runtime_holder.h",
"service_protocol_hooks.cc",
"service_protocol_hooks.h",
"platform_view.cc",
"platform_view.h",
"session_connection.cc",
"session_connection.h",
"vulkan_rasterizer.cc",
"vulkan_rasterizer.h",
"surface.cc",
"surface.h",
"task_observers.cc",
"task_observers.h",
"unique_fdio_ns.h",
"vulkan_surface.cc",
"vulkan_surface.h",
"vulkan_surface_pool.cc",
......@@ -45,18 +50,26 @@ template("flutter_content_handler") {
"vulkan_surface_producer.h",
]
# The use of these dependencies is temporary and will be moved behind the
# embedder API.
flutter_deps = [
"$flutter_root/assets",
"$flutter_root/common",
"$flutter_root/flow",
"$flutter_root/glue",
"$flutter_root/lib/ui",
"$flutter_root/runtime",
"$flutter_root/sky/engine/platform",
"$flutter_root/third_party/txt",
"$flutter_root/vulkan",
"$flutter_root/fml",
"$flutter_root/shell/common",
"$flutter_root/shell/gpu",
]
deps = [
"//third_party/dart/runtime/bin:libdart_builtin",
"//third_party/dart/runtime/platform:libdart_platform",
"$flutter_root/assets",
"$flutter_root/common",
"$flutter_root/flow",
"$flutter_root/glue",
"$flutter_root/lib/ui",
"$flutter_root/runtime",
"$flutter_root/sky/engine/platform",
"$flutter_root/third_party/txt",
"$flutter_root/vulkan",
"//garnet/public/lib/app/cpp",
"//garnet/public/lib/fsl",
"//garnet/public/lib/fxl",
......@@ -73,8 +86,10 @@ template("flutter_content_handler") {
"//topaz/lib/tonic",
"//topaz/public/dart-pkg/fuchsia",
"//topaz/public/lib/ui/flutter/sdk_ext",
"//third_party/skia:gpu",
"//third_party/zlib:minizip",
"//zircon/public/lib/trace-provider",
] + extra_deps
] + extra_deps + flutter_deps
# The flags below are needed so that Dart's CPU profiler can walk the
# C++ stack.
......
Flutter Application Runner
==========================
Implements the `component::ApplicationRunner` FIDL interface to launch and run mutliple Flutter applications within the same process.
......@@ -2,21 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/content_handler/accessibility_bridge.h"
#include "accessibility_bridge.h"
#include <unordered_set>
#include "flutter/lib/ui/semantics/semantics_node.h"
#include "lib/app/cpp/application_context.h"
#include "lib/fxl/macros.h"
#include "lib/context/fidl/context_writer.fidl.h"
#include "third_party/rapidjson/rapidjson/document.h"
#include "third_party/rapidjson/rapidjson/stringbuffer.h"
#include "third_party/rapidjson/rapidjson/writer.h"
namespace flutter_runner {
namespace flutter {
AccessibilityBridge::AccessibilityBridge(component::ApplicationContext* context)
: writer_(context->ConnectToEnvironmentService<modular::ContextWriter>()) {}
AccessibilityBridge::AccessibilityBridge(maxwell::ContextWriterPtr writer)
: writer_(std::move(writer)) {}
AccessibilityBridge::~AccessibilityBridge() = default;
void AccessibilityBridge::UpdateSemantics(
const blink::SemanticsNodeUpdates& update) {
......@@ -77,4 +78,4 @@ void AccessibilityBridge::EraseUnvisitedNodes(
}
}
} // namespace flutter_runner
} // namespace flutter
......@@ -2,28 +2,32 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_CONTENT_HANDLER_ACCESSIBILITY_BRIDGE_H_
#define FLUTTER_CONTENT_HANDLER_ACCESSIBILITY_BRIDGE_H_
#pragma once
#include <map>
#include "flutter/lib/ui/semantics/semantics_node.h"
#include "lib/app/cpp/application_context.h"
#include <fuchsia/cpp/modular.h>
#include "lib/context/fidl/context_writer.fidl.h"
#include "lib/fxl/macros.h"
namespace flutter_runner {
namespace flutter {
// Maintain an up-to-date list of SemanticsNodes on screen, and communicate
// with the Context Service.
class AccessibilityBridge {
class AccessibilityBridge final {
public:
explicit AccessibilityBridge(component::ApplicationContext* context);
AccessibilityBridge(maxwell::ContextWriterPtr writer);
~AccessibilityBridge();
// Update the internal representation of the semantics nodes, and write the
// semantics to Context Service.
void UpdateSemantics(const blink::SemanticsNodeUpdates& update);
private:
maxwell::ContextWriterPtr writer_;
std::map<int, blink::SemanticsNode> semantics_nodes_;
// Walk the semantics node tree starting at |id|, and store the id of each
// visited child in |visited_nodes|.
void UpdateVisitedForNodeAndChildren(const int id,
......@@ -33,10 +37,7 @@ class AccessibilityBridge {
// |visited_nodes|.
void EraseUnvisitedNodes(const std::vector<int>& visited_nodes);
std::map<int, blink::SemanticsNode> semantics_nodes_;
modular::ContextWriterPtr writer_;
FXL_DISALLOW_COPY_AND_ASSIGN(AccessibilityBridge);
};
} // namespace flutter_runner
#endif // FLUTTER_CONTENT_HANDLER_ACCESSIBILITY_BRIDGE_H_
} // namespace flutter
// Copyright 2016 The Chromium 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/content_handler/app.h"
#include <thread>
#include <utility>
#include "flutter/common/settings.h"
#include "flutter/common/threads.h"
#include "flutter/content_handler/fuchsia_font_manager.h"
#include "flutter/lib/ui/text/font_collection.h"
#include "flutter/sky/engine/platform/fonts/fuchsia/FontCacheFuchsia.h"
#include "lib/fsl/tasks/message_loop.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/tasks/task_runner.h"
#include "lib/icu_data/cpp/icu_data.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"
namespace flutter_runner {
namespace {
static App* g_app = nullptr;
void QuitMessageLoop() {
fsl::MessageLoop::GetCurrent()->QuitNow();
}
std::string GetLabelFromURL(const std::string& url) {
size_t last_slash = url.rfind('/');
if (last_slash == std::string::npos || last_slash + 1 == url.length())
return url;
return url.substr(last_slash + 1);
}
} // namespace
App::App() {
g_app = this;
context_ = component::ApplicationContext::CreateFromStartupInfo();
gpu_thread_ = std::make_unique<fsl::Thread>();
io_thread_ = std::make_unique<fsl::Thread>();
auto gpu_thread_success = gpu_thread_->Run();
auto io_thread_success = io_thread_->Run();
FXL_CHECK(gpu_thread_success) << "Must be able to create the GPU thread";
FXL_CHECK(io_thread_success) << "Must be able to create the IO thread";
auto ui_task_runner = fsl::MessageLoop::GetCurrent()->task_runner();
auto gpu_task_runner = gpu_thread_->TaskRunner();
auto io_task_runner = io_thread_->TaskRunner();
// Notice that the Platform and UI threads are actually the same.
blink::Threads::Set(blink::Threads(ui_task_runner, // Platform
gpu_task_runner, // GPU
ui_task_runner, // UI
io_task_runner // IO
));
if (!icu_data::Initialize(context_.get())) {
FXL_LOG(ERROR) << "Could not initialize ICU data.";
}
blink::Settings settings;
settings.enable_observatory = true;
blink::Settings::Set(settings);
fonts::FontProviderPtr font_provider(
context_->ConnectToEnvironmentService<fonts::FontProvider>());
if (settings.using_blink) {
blink::SetFontProvider(std::move(font_provider));
} else {
blink::FontCollection::ForProcess().GetFontCollection()->
SetAssetFontManager(
sk_make_sp<txt::FuchsiaFontManager>(std::move(font_provider)));
}
context_->outgoing_services()->AddService<component::ApplicationRunner>(
[this](fidl::InterfaceRequest<component::ApplicationRunner> request) {
runner_bindings_.AddBinding(this, std::move(request));
});
}
App::~App() {
icu_data::Release();
blink::Threads::Gpu()->PostTask(QuitMessageLoop);
blink::Threads::IO()->PostTask(QuitMessageLoop);
g_app = nullptr;
}
App& App::Shared() {
FXL_DCHECK(g_app);
return *g_app;
}
void App::WaitForPlatformViewIds(
std::vector<PlatformViewInfo>* platform_view_ids) {
fxl::AutoResetWaitableEvent latch;
blink::Threads::UI()->PostTask([this, platform_view_ids, &latch]() {
WaitForPlatformViewsIdsUIThread(platform_view_ids, &latch);
});
latch.Wait();
}
void App::WaitForPlatformViewsIdsUIThread(
std::vector<PlatformViewInfo>* platform_view_ids,
fxl::AutoResetWaitableEvent* latch) {
for (auto it = controllers_.begin(); it != controllers_.end(); it++) {
ApplicationControllerImpl* controller = it->first;
if (!controller) {
continue;
}
PlatformViewInfo info;
// TODO(zra): We should create real IDs for these instead of relying on the
// address of the controller. Maybe just use the UI Isolate main port?
info.view_id = reinterpret_cast<uintptr_t>(controller);
info.isolate_id = controller->GetUIIsolateMainPort();
info.isolate_name = controller->GetUIIsolateName();
platform_view_ids->push_back(info);
}
latch->Signal();
}
void App::StartApplication(
component::ApplicationPackage application,
component::ApplicationStartupInfo startup_info,
fidl::InterfaceRequest<component::ApplicationController> controller) {
if (controllers_.empty()) {
// Name this process after the url of the first application being launched.
base_label_ = "flutter:" + GetLabelFromURL(startup_info.launch_info.url);
}
std::unique_ptr<ApplicationControllerImpl> impl =
std::make_unique<ApplicationControllerImpl>(this, std::move(application),
std::move(startup_info),
std::move(controller));
ApplicationControllerImpl* key = impl.get();
controllers_.emplace(key, std::move(impl));
UpdateProcessLabel();
}
void App::Destroy(ApplicationControllerImpl* controller) {
auto it = controllers_.find(controller);
if (it == controllers_.end())
return;
controllers_.erase(it);
UpdateProcessLabel();
}
void App::UpdateProcessLabel() {
std::string label;
if (controllers_.size() < 2) {
label = base_label_;
} else {
std::string suffix = " (+" + std::to_string(controllers_.size() - 1) + ")";
if (base_label_.size() + suffix.size() <= ZX_MAX_NAME_LEN - 1) {
label = base_label_ + suffix;
} else {
label = base_label_.substr(0, ZX_MAX_NAME_LEN - 1 - suffix.size() - 3) +
"..." + suffix;
}
}
zx::process::self().set_property(ZX_PROP_NAME, label.c_str(), label.size());
}
} // namespace flutter_runner
// Copyright 2016 The Chromium 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_CONTENT_HANDLER_APP_H_
#define FLUTTER_CONTENT_HANDLER_APP_H_
#include <memory>
#include <unordered_set>
#include "flutter/content_handler/application_controller_impl.h"
#include "lib/app/cpp/application_context.h"
#include <fuchsia/cpp/component.h>
#include "lib/fsl/threading/thread.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/synchronization/waitable_event.h"
namespace flutter_runner {
class App : public component::ApplicationRunner {
public:
App();
~App();
static App& Shared();
// |component::ApplicationRunner| implementation:
void StartApplication(
component::ApplicationPackage application,
component::ApplicationStartupInfo startup_info,
fidl::InterfaceRequest<component::ApplicationController> controller) override;
void Destroy(ApplicationControllerImpl* controller);
struct PlatformViewInfo {
uintptr_t view_id;
int64_t isolate_id;
std::string isolate_name;
};
void WaitForPlatformViewIds(std::vector<PlatformViewInfo>* platform_view_ids);
private:
void WaitForPlatformViewsIdsUIThread(
std::vector<PlatformViewInfo>* platform_view_ids,
fxl::AutoResetWaitableEvent* latch);
void UpdateProcessLabel();
std::unique_ptr<component::ApplicationContext> context_;
std::unique_ptr<fsl::Thread> gpu_thread_;
std::unique_ptr<fsl::Thread> io_thread_;
fidl::BindingSet<component::ApplicationRunner> runner_bindings_;
std::unordered_map<ApplicationControllerImpl*,
std::unique_ptr<ApplicationControllerImpl>>
controllers_;
std::string base_label_;
FXL_DISALLOW_COPY_AND_ASSIGN(App);
};
} // namespace flutter_runner
#endif // FLUTTER_CONTENT_HANDLER_APP_H_
// Copyright 2018 The Fuchsia 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 "application.h"
#include <dlfcn.h>
#include <zircon/dlfcn.h>
#include <sstream>
#include "flutter/shell/common/switches.h"
#include "lib/fsl/vmo/file.h"
#include "lib/fsl/vmo/vector.h"
#include "lib/fxl/command_line.h"
#include "lib/fxl/synchronization/waitable_event.h"
#include "task_observers.h"
namespace flutter {
std::pair<std::unique_ptr<fsl::Thread>, std::unique_ptr<Application>>
Application::Create(
Application::Delegate& delegate,
component::ApplicationPackagePtr package,
component::ApplicationStartupInfoPtr startup_info,
f1dl::InterfaceRequest<component::ApplicationController> controller) {
auto thread = std::make_unique<fsl::Thread>();
std::unique_ptr<Application> application;
fxl::AutoResetWaitableEvent latch;
thread->TaskRunner()->PostTask([&]() mutable {
application.reset(new Application(delegate, //
std::move(package), //
std::move(startup_info), //
std::move(controller) //
));
latch.Signal();
});
thread->Run();
latch.Wait();
return {std::move(thread), std::move(application)};
}
static std::string DebugLabelForURL(const std::string url) {
auto found = url.rfind("/");
if (found == std::string::npos) {
return url;
} else {
return {url, found + 1};
}
}
Application::Application(
Application::Delegate& delegate,
component::ApplicationPackagePtr package,
component::ApplicationStartupInfoPtr startup_info,
f1dl::InterfaceRequest<component::ApplicationController>
application_controller_request)
: delegate_(delegate),
debug_label_(DebugLabelForURL(startup_info->launch_info->url)),
application_controller_(this) {
application_controller_.set_error_handler([this]() { Kill(); });
FXL_DCHECK(fdio_ns_.is_valid());
// ApplicationLaunchInfo::url non-optional.
auto& launch_info = startup_info->launch_info;
// ApplicationLaunchInfo::arguments optional.
if (auto& arguments = launch_info->arguments) {
settings_ = shell::SettingsFromCommandLine(
fxl::CommandLineFromIterators(arguments->begin(), arguments->end()));
}
// TODO: ApplicationLaunchInfo::out optional.
// TODO: ApplicationLaunchInfo::err optional.
// ApplicationLaunchInfo::service_request optional.
if (launch_info->directory_request) {
service_provider_bridge_.ServeDirectory(
std::move(launch_info->directory_request));
}
// ApplicationLaunchInfo::flat_namespace optional.
if (auto& flat_namespace = startup_info->flat_namespace) {
for (size_t i = 0; i < flat_namespace->paths->size(); ++i) {
const auto& path = flat_namespace->paths->at(i);
if (path == "/svc") {
continue;
}
zx::channel dir = std::move(flat_namespace->directories->at(i));
zx_handle_t dir_handle = dir.release();
if (fdio_ns_bind(fdio_ns_.get(), path->data(), dir_handle) != ZX_OK) {
FXL_DLOG(ERROR) << "Could not bind path to namespace: " << path;
zx_handle_close(dir_handle);
}
}
} else {
FXL_DLOG(ERROR) << "There was no flat namespace.";
}
application_directory_.reset(fdio_ns_opendir(fdio_ns_.get()));
FXL_DCHECK(application_directory_.is_valid());
application_assets_directory_.reset(
openat(application_directory_.get(), "pkg/data", O_RDONLY | O_DIRECTORY));
// TODO: ApplicationLaunchInfo::additional_services optional.
// ApplicationPackage::data: This is legacy FLX data. Ensure that we dont have
// any.
FXL_DCHECK(!package->data) << "Legacy FLX data must not be supplied.";
// All launch arguments have been read. Perform service binding and
// final settings configuration. The next call will be to create a view
// for this application.
service_provider_bridge_.AddService<mozart::ViewProvider>(
std::bind(&Application::CreateShellForView, this, std::placeholders::_1));
component::ServiceProviderPtr outgoing_services;
outgoing_services_request_ = outgoing_services.NewRequest();
service_provider_bridge_.set_backend(std::move(outgoing_services));
// Setup the application controller binding.
if (application_controller_request) {
application_controller_.Bind(std::move(application_controller_request));
}
application_context_ =
component::ApplicationContext::CreateFrom(std::move(startup_info));
settings_.enable_observatory = true;
settings_.icu_data_path = "";
settings_.using_blink = false;
settings_.assets_dir = application_assets_directory_.get();
settings_.script_snapshot_path = "snapshot_blob.bin";
settings_.log_tag = debug_label_ + std::string{"(flutter)"};
#ifndef NDEBUG
// Debug mode
settings_.dart_non_checked_mode = false;
#else // NDEBUG
// Release mode
settings_.dart_non_checked_mode = true;
#endif // NDEBUG
settings_.task_observer_add =
std::bind(&CurrentMessageLoopAddAfterTaskObserver, std::placeholders::_1,
std::placeholders::_2);
settings_.task_observer_remove = std::bind(
&CurrentMessageLoopRemoveAfterTaskObserver, std::placeholders::_1);
AttemptVMLaunchWithCurrentSettings(settings_);
}
Application::~Application() = default;
void Application::AttemptVMLaunchWithCurrentSettings(
const blink::Settings& settings) const {
if (blink::DartVM::ForProcessIfInitialized()) {
return;
}
if (!blink::DartVM::IsRunningPrecompiledCode()) {
// We will be initializing the VM lazily in this case.
return;
}
fsl::SizedVmo dylib_vmo;
if (!fsl::VmoFromFilenameAt(
application_assets_directory_.get() /* /pkg/data */, "libapp.so",
&dylib_vmo)) {
FXL_LOG(ERROR) << "Dylib containing VM and isolate snapshots does not "
"exist. Will not be able to launch VM.";
return;
}
dlerror();
auto library_handle = dlopen_vmo(dylib_vmo.vmo().get(), RTLD_LAZY);
if (library_handle == nullptr) {
FXL_LOG(ERROR) << "Could not open dylib: " << dlerror();
return;
}
auto lib = fxl::MakeRefCounted<fml::NativeLibrary>(
library_handle, // library handle
true // close the handle when done
);
auto symbol = [](const char* str) {
return std::string{"_"} + std::string{str};
};
fxl::RefPtr<blink::DartSnapshot> vm_snapshot =
fxl::MakeRefCounted<blink::DartSnapshot>(
blink::DartSnapshotBuffer::CreateWithSymbolInLibrary(
lib, symbol(blink::DartSnapshot::kVMDataSymbol).c_str()),
blink::DartSnapshotBuffer::CreateWithSymbolInLibrary(
lib, symbol(blink::DartSnapshot::kVMInstructionsSymbol).c_str()));
fxl::RefPtr<blink::DartSnapshot> isolate_snapshot =
fxl::MakeRefCounted<blink::DartSnapshot>(
blink::DartSnapshotBuffer::CreateWithSymbolInLibrary(
lib, symbol(blink::DartSnapshot::kIsolateDataSymbol).c_str()),
blink::DartSnapshotBuffer::CreateWithSymbolInLibrary(
lib,
symbol(blink::DartSnapshot::kIsolateInstructionsSymbol).c_str()));
blink::DartVM::ForProcess(settings_, //
std::move(vm_snapshot), //
std::move(isolate_snapshot) //
);
if (blink::DartVM::ForProcessIfInitialized()) {
FXL_DLOG(INFO) << "VM successfully initialized for AOT mode.";
} else {
FXL_LOG(ERROR) << "VM could not be initialized for AOT mode.";
}
}
// |component::ApplicationController|
void Application::Kill() {
if (last_return_code_.first) {
for (auto wait_callback : wait_callbacks_) {
wait_callback(last_return_code_.second);
}
}
wait_callbacks_.clear();
delegate_.OnApplicationTerminate(this);
// WARNING: Don't do anything past this point as this instance may have been
// collected.
}
// |component::ApplicationController|
void Application::Detach() {
application_controller_.set_error_handler(nullptr);
}
// |component::ApplicationController|
void Application::Wait(const WaitCallback& callback) {
wait_callbacks_.emplace_back(std::move(callback));
}
// |flutter::Engine::Delegate|
void Application::OnEngineTerminate(const Engine* shell_holder) {
auto found = std::find_if(shell_holders_.begin(), shell_holders_.end(),
[shell_holder](const auto& holder) {
return holder.get() == shell_holder;
});
if (found == shell_holders_.end()) {
return;
}
// We may launch multiple shell in this application. However, we will
// terminate when the last shell goes away. The error code return to the
// application controller will be the last isolate that had an error.
auto return_code = shell_holder->GetEngineReturnCode();
if (return_code.first) {
last_return_code_ = return_code;
}
shell_holders_.erase(found);
if (shell_holders_.size() == 0) {
Kill();
// WARNING: Don't do anything past this point because the delegate may have
// collected this instance via the termination callback.
}
}
void Application::CreateShellForView(
f1dl::InterfaceRequest<mozart::ViewProvider> view_provider_request) {
shells_bindings_.AddBinding(this, std::move(view_provider_request));
}
// |mozart::ViewProvider|
void Application::CreateView(
f1dl::InterfaceRequest<mozart::ViewOwner> view_owner,
f1dl::InterfaceRequest<component::ServiceProvider>) {
if (!application_context_) {
FXL_DLOG(ERROR) << "Application context was invalid when attempting to "
"create a shell for a view provider request.";
return;
}
// This method may be called multiple times. Care must be taken to ensure that
// all arguments can be accessed or synthesized multiple times.
// TODO(chinmaygarde): Figure out how to re-create the outgoing service
// request handle.
shell_holders_.emplace(std::make_unique<Engine>(
*this, // delegate
debug_label_, // thread label
*application_context_, // application context
settings_, // settings
std::move(view_owner), // view owner
fdio_ns_, // FDIO namespace
std::move(outgoing_services_request_) // outgoing request
));
}
} // namespace flutter
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <array>
#include <memory>
#include <set>
#include "engine.h"
#include "flutter/common/settings.h"
#include "lib/app/cpp/application_context.h"
#include "lib/app/fidl/application_controller.fidl.h"
#include "lib/fidl/cpp/bindings/binding_set.h"
#include "lib/fsl/threading/thread.h"
#include "lib/fxl/files/unique_fd.h"
#include "lib/fxl/macros.h"
#include "lib/svc/cpp/service_provider_bridge.h"
#include "lib/ui/views/fidl/view_provider.fidl.h"
#include "unique_fdio_ns.h"
namespace flutter {
// Represents an instance of a Flutter application that contains one of more
// Flutter engine instances.
class Application final : public Engine::Delegate,
public component::ApplicationController,
public mozart::ViewProvider {
public:
class Delegate {
public:
virtual void OnApplicationTerminate(const Application* application) = 0;
};
// Creates a dedicated thread to run the application and constructions the
// application on it. The application can be accessed only on this thread.
// This is a synchronous operation.
static std::pair<std::unique_ptr<fsl::Thread>, std::unique_ptr<Application>>
Create(Application::Delegate& delegate,
component::ApplicationPackagePtr package,
component::ApplicationStartupInfoPtr startup_info,
f1dl::InterfaceRequest<component::ApplicationController> controller);
// Must be called on the same thread returned from the create call. The thread
// may be collected after.
~Application();
private:
blink::Settings settings_;
Delegate& delegate_;
const std::string debug_label_;
UniqueFDIONS fdio_ns_ = UniqueFDIONSCreate();
fxl::UniqueFD application_directory_;
fxl::UniqueFD application_assets_directory_;
f1dl::Binding<component::ApplicationController> application_controller_;
f1dl::InterfaceRequest<component::ServiceProvider> outgoing_services_request_;
component::ServiceProviderBridge service_provider_bridge_;
std::unique_ptr<component::ApplicationContext> application_context_;
f1dl::BindingSet<mozart::ViewProvider> shells_bindings_;
std::set<std::unique_ptr<Engine>> shell_holders_;
std::vector<WaitCallback> wait_callbacks_;
std::pair<bool, uint32_t> last_return_code_;
Application(
Application::Delegate& delegate,
component::ApplicationPackagePtr package,
component::ApplicationStartupInfoPtr startup_info,
f1dl::InterfaceRequest<component::ApplicationController> controller);
// |component::ApplicationController|
void Kill() override;
// |component::ApplicationController|
void Detach() override;
// |component::ApplicationController|
void Wait(const WaitCallback& callback) override;
// |mozart::ViewProvider|
void CreateView(
f1dl::InterfaceRequest<mozart::ViewOwner> view_owner,
f1dl::InterfaceRequest<component::ServiceProvider> services) override;
// |flutter::Engine::Delegate|
void OnEngineTerminate(const Engine* holder) override;
void CreateShellForView(
f1dl::InterfaceRequest<mozart::ViewProvider> view_provider_request);
void AttemptVMLaunchWithCurrentSettings(
const blink::Settings& settings) const;
FXL_DISALLOW_COPY_AND_ASSIGN(Application);
};
} // namespace flutter
// Copyright 2016 The Chromium 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/content_handler/application_controller_impl.h"
#include <utility>
#include <fdio/namespace.h>
#include <zircon/status.h>
#include "flutter/content_handler/app.h"
#include "flutter/content_handler/runtime_holder.h"
#include "lib/app/cpp/connect.h"
#include "lib/fsl/vmo/vector.h"
#include "lib/fxl/logging.h"
namespace flutter_runner {
ApplicationControllerImpl::ApplicationControllerImpl(
App* app,
component::ApplicationPackage application,
component::ApplicationStartupInfo startup_info,
fidl::InterfaceRequest<component::ApplicationController> controller)
: app_(app), binding_(this) {
if (controller.is_valid()) {
binding_.Bind(std::move(controller));
binding_.set_error_handler([this] {
app_->Destroy(this);
// |this| has been deleted at this point.
});
}
std::vector<char> bundle;
if (application.data) {
if (!fsl::VectorFromVmo(std::move(*application.data), &bundle)) {
FXL_LOG(ERROR) << "Failed to receive bundle.";
return;
}
}
// TODO(jeffbrown): Decide what to do with command-line arguments and
// startup handles.
if (startup_info.launch_info.directory_request.is_valid()) {
service_provider_bridge_.ServeDirectory(
std::move(startup_info.launch_info.directory_request));
}
service_provider_bridge_.AddService<views_v1::ViewProvider>(
[this](fidl::InterfaceRequest<views_v1::ViewProvider> request) {
view_provider_bindings_.AddBinding(this, std::move(request));
});
component::ServiceProviderPtr service_provider;
auto request = service_provider.NewRequest();
service_provider_bridge_.set_backend(std::move(service_provider));
fdio_ns_t* fdio_ns = SetupNamespace(&startup_info.flat_namespace);
if (fdio_ns == nullptr) {
FXL_LOG(ERROR) << "Failed to initialize namespace";
return;
}
url_ = startup_info.launch_info.url;
runtime_holder_.reset(new RuntimeHolder());
runtime_holder_->SetMainIsolateShutdownCallback([this]() { Kill(); });
runtime_holder_->Init(
fdio_ns,
component::ApplicationContext::CreateFrom(std::move(startup_info)),
std::move(request), std::move(bundle));
}
ApplicationControllerImpl::~ApplicationControllerImpl() = default;
constexpr char kServiceRootPath[] = "/svc";
fdio_ns_t* ApplicationControllerImpl::SetupNamespace(
component::FlatNamespace* flat) {
fdio_ns_t* fdio_namespc;
zx_status_t status = fdio_ns_create(&fdio_namespc);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Failed to create namespace";
return nullptr;
}
for (size_t i = 0; i < flat->paths->size(); ++i) {
if (flat->paths->at(i) == kServiceRootPath) {
// Ownership of /svc goes to the ApplicationContext created above.
continue;
}
zx::channel dir = std::move(flat->directories->at(i));
zx_handle_t dir_handle = dir.release();
const char* path = flat->paths->at(i)->data();
status = fdio_ns_bind(fdio_namespc, path, dir_handle);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Failed to bind " << flat->paths->at(i)
<< " to namespace";
zx_handle_close(dir_handle);
fdio_ns_destroy(fdio_namespc);
return nullptr;
}
}
return fdio_namespc;
}
void ApplicationControllerImpl::Kill() {
SendReturnCode(runtime_holder_->return_code());
runtime_holder_.reset();
app_->Destroy(this);
// |this| has been deleted at this point.
}
void ApplicationControllerImpl::Detach() {
binding_.set_error_handler(fxl::Closure());
}
void ApplicationControllerImpl::Wait(WaitCallback callback) {
wait_callbacks_.push_back(std::move(callback));
}
void ApplicationControllerImpl::SendReturnCode(int32_t return_code) {
for (const auto& iter : wait_callbacks_) {
iter(return_code);
}
wait_callbacks_.clear();
}
void ApplicationControllerImpl::CreateView(
fidl::InterfaceRequest<views_v1_token::ViewOwner> view_owner_request,
fidl::InterfaceRequest<component::ServiceProvider> services) {
runtime_holder_->CreateView(url_, std::move(view_owner_request),
std::move(services));
}
Dart_Port ApplicationControllerImpl::GetUIIsolateMainPort() {
if (!runtime_holder_)
return ILLEGAL_PORT;
return runtime_holder_->GetUIIsolateMainPort();
}
std::string ApplicationControllerImpl::GetUIIsolateName() {
if (!runtime_holder_) {
return "";
}
return runtime_holder_->GetUIIsolateName();
}
} // namespace flutter_runner
// Copyright 2016 The Chromium 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_CONTENT_HANDLER_APPLICATION_IMPL_H_
#define FLUTTER_CONTENT_HANDLER_APPLICATION_IMPL_H_
#include <memory>
#include <fdio/namespace.h>
#include <fuchsia/cpp/component.h>
#include <fuchsia/cpp/ui.h>
#include <fuchsia/cpp/views_v1.h>
#include "lib/fidl/cpp/binding.h"
#include "lib/fidl/cpp/binding_set.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/synchronization/waitable_event.h"
#include "lib/svc/cpp/service_provider_bridge.h"
#include "third_party/dart/runtime/include/dart_api.h"
namespace flutter_runner {
class App;
class RuntimeHolder;
class ApplicationControllerImpl : public component::ApplicationController,
public views_v1::ViewProvider {
public:
ApplicationControllerImpl(
App* app,
component::ApplicationPackage application,
component::ApplicationStartupInfo startup_info,
fidl::InterfaceRequest<component::ApplicationController> controller);
~ApplicationControllerImpl() override;
// |component::ApplicationController| implementation
void Kill() override;
void Detach() override;
void Wait(WaitCallback callback) override;
// |views_v1::ViewProvider| implementation
void CreateView(
fidl::InterfaceRequest<views_v1_token::ViewOwner> view_owner_request,
fidl::InterfaceRequest<component::ServiceProvider> services) override;
Dart_Port GetUIIsolateMainPort();
std::string GetUIIsolateName();
private:
void StartRuntimeIfReady();
void SendReturnCode(int32_t return_code);
fdio_ns_t* SetupNamespace(component::FlatNamespace* flat);
App* app_;
fidl::Binding<component::ApplicationController> binding_;
component::ServiceProviderBridge service_provider_bridge_;
fidl::BindingSet<views_v1::ViewProvider> view_provider_bindings_;
std::string url_;
std::unique_ptr<RuntimeHolder> runtime_holder_;
std::vector<WaitCallback> wait_callbacks_;
FXL_DISALLOW_COPY_AND_ASSIGN(ApplicationControllerImpl);
};
} // namespace flutter_runner
#endif // FLUTTER_CONTENT_HANDLER_APPLICATION_IMPL_H_
// Copyright 2018 The Fuchsia 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 "application_runner.h"
#include <utility>
#include "flutter/lib/ui/text/font_collection.h"
#include "fuchsia_font_manager.h"
#include "lib/fonts/fidl/font_provider.fidl.h"
#include "lib/icu_data/cpp/icu_data.h"
namespace flutter {
ApplicationRunner::ApplicationRunner(fxl::Closure on_termination_callback)
: on_termination_callback_(std::move(on_termination_callback)),
host_context_(component::ApplicationContext::CreateFromStartupInfo()) {
SetupICU();
SetupGlobalFonts();
const std::string process_label = "flutter";
zx::process::self().set_property(ZX_PROP_NAME, process_label.c_str(),
process_label.size());
host_context_->outgoing_services()->AddService<component::ApplicationRunner>(
std::bind(&ApplicationRunner::RegisterApplication, this,
std::placeholders::_1));
active_applications_bindings_.set_empty_set_handler(
[this]() { FireTerminationCallbackIfNecessary(); });
}
ApplicationRunner::~ApplicationRunner() {
host_context_->outgoing_services()
->RemoveService<component::ApplicationRunner>();
}
void ApplicationRunner::RegisterApplication(
f1dl::InterfaceRequest<component::ApplicationRunner> request) {
active_applications_bindings_.AddBinding(this, std::move(request));
}
void ApplicationRunner::StartApplication(
component::ApplicationPackagePtr package,
component::ApplicationStartupInfoPtr startup_info,
f1dl::InterfaceRequest<component::ApplicationController> controller) {
auto thread_application_pair =
Application::Create(*this, // delegate
std::move(package), // application pacakge
std::move(startup_info), // startup info
std::move(controller) // controller request
);
active_applications_[thread_application_pair.second.get()] =
std::move(thread_application_pair);
}
void ApplicationRunner::OnApplicationTerminate(const Application* application) {
active_applications_.erase(application);
FireTerminationCallbackIfNecessary();
}
void ApplicationRunner::SetupICU() {
if (!icu_data::Initialize(host_context_.get())) {
FXL_LOG(ERROR) << "Could not initialize ICU data.";
}
}
void ApplicationRunner::SetupGlobalFonts() {
fonts::FontProviderPtr font_provider(
host_context_->ConnectToEnvironmentService<fonts::FontProvider>());
auto font_manager =
sk_make_sp<txt::FuchsiaFontManager>(std::move(font_provider));
blink::FontCollection::ForProcess()
.GetFontCollection()
->SetDefaultFontManager(std::move(font_manager));
}
void ApplicationRunner::FireTerminationCallbackIfNecessary() {
// We have no reason to exist if:
// 1: No previously launched applications are running.
// 2: No bindings exist that may require launching more applications.
if (on_termination_callback_ && active_applications_.size() == 0 &&
active_applications_bindings_.size() == 0) {
on_termination_callback_();
}
}
} // namespace flutter
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <memory>
#include <unordered_map>
#include "application.h"
#include "lib/app/cpp/application_context.h"
#include "lib/app/fidl/application_runner.fidl.h"
#include "lib/fidl/cpp/bindings/binding_set.h"
#include "lib/fsl/tasks/message_loop.h"
#include "lib/fxl/functional/make_copyable.h"
#include "lib/fxl/macros.h"
namespace flutter {
// Publishes the |component::ApplicationRunner| service and runs applications on
// their own threads.
class ApplicationRunner final : public Application::Delegate,
public component::ApplicationRunner {
public:
ApplicationRunner(fxl::Closure on_termination_callback);
~ApplicationRunner();
private:
struct ActiveApplication {
std::unique_ptr<fsl::Thread> thread;
std::unique_ptr<Application> application;
ActiveApplication(std::pair<std::unique_ptr<fsl::Thread>,
std::unique_ptr<Application>> pair)
: thread(std::move(pair.first)), application(std::move(pair.second)) {}
ActiveApplication() {
if (thread && application) {
thread->TaskRunner()->PostTask(
fxl::MakeCopyable([application = std::move(application)]() mutable {
application.reset();
fsl::MessageLoop::GetCurrent()->PostQuitTask();
}));
thread.reset(); // join
}
}
};
fxl::Closure on_termination_callback_;
std::unique_ptr<component::ApplicationContext> host_context_;
f1dl::BindingSet<component::ApplicationRunner> active_applications_bindings_;
std::unordered_map<const Application*, ActiveApplication>
active_applications_;
// |component::ApplicationRunner|
void StartApplication(component::ApplicationPackagePtr application,
component::ApplicationStartupInfoPtr startup_info,
f1dl::InterfaceRequest<component::ApplicationController>
controller) override;
void RegisterApplication(
f1dl::InterfaceRequest<component::ApplicationRunner> request);
void UnregisterApplication(const Application* application);
// |Application::Delegate|
void OnApplicationTerminate(const Application* application) override;
void SetupICU();
void SetupGlobalFonts();
void FireTerminationCallbackIfNecessary();
FXL_DISALLOW_COPY_AND_ASSIGN(ApplicationRunner);
};
} // namespace flutter
// Copyright 2018 The Fuchsia 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 "compositor_context.h"
#include "flutter/flow/layers/layer_tree.h"
#include "flutter/glue/trace_event.h"
namespace flutter {
class ScopedFrame final : public flow::CompositorContext::ScopedFrame {
public:
ScopedFrame(flow::CompositorContext& context,
bool instrumentation_enabled,
SessionConnection& session_connection)
: flow::CompositorContext::ScopedFrame(context,
nullptr,
nullptr,
instrumentation_enabled),
session_connection_(session_connection) {}
private:
SessionConnection& session_connection_;
bool Raster(flow::LayerTree& layer_tree, bool ignore_raster_cache) override {
if (!session_connection_.has_metrics()) {
return true;
}
{
// Preroll the Flutter layer tree. This allows Flutter to perform
// pre-paint optimizations.
TRACE_EVENT0("flutter", "Preroll");
layer_tree.Preroll(*this, true /* ignore raster cache */);
}
{
// Traverse the Flutter layer tree so that the necessary session ops to
// represent the frame are enqueued in the underlying session.
TRACE_EVENT0("flutter", "UpdateScene");
layer_tree.UpdateScene(session_connection_.scene_update_context(),
session_connection_.root_node());
}
{
// Flush all pending session ops.
TRACE_EVENT0("flutter", "SessionPresent");
session_connection_.Present(*this);
}
return true;
}
FXL_DISALLOW_COPY_AND_ASSIGN(ScopedFrame);
};
CompositorContext::CompositorContext(
const ui::ScenicPtr& scenic,
std::string debug_label,
zx::eventpair import_token,
OnMetricsUpdate session_metrics_did_change_callback,
fxl::Closure session_error_callback)
: debug_label_(std::move(debug_label)),
session_connection_(scenic,
debug_label_,
std::move(import_token),
std::move(session_metrics_did_change_callback),
std::move(session_error_callback)) {}
CompositorContext::~CompositorContext() = default;
std::unique_ptr<flow::CompositorContext::ScopedFrame>
CompositorContext::AcquireFrame(GrContext* gr_context,
SkCanvas* canvas,
bool instrumentation_enabled) {
// TODO: The AcquireFrame interface is too broad and must be refactored to get
// rid of the context and canvas arguments as those seem to be only used for
// colorspace correctness purposes on the mobile shells.
return std::make_unique<flutter::ScopedFrame>(*this, //
instrumentation_enabled, //
session_connection_ //
);
}
} // namespace flutter
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "flutter/flow/compositor_context.h"
#include "garnet/public/lib/ui/scenic/fidl/scenic.fidl-common.h"
#include "lib/fxl/macros.h"
#include "session_connection.h"
namespace flutter {
// Holds composition specific state and bindings specific to composition on
// Fuchsia.
class CompositorContext final : public flow::CompositorContext {
public:
CompositorContext(const ui::ScenicPtr& scenic,
std::string debug_label,
zx::eventpair import_token,
OnMetricsUpdate session_metrics_did_change_callback,
fxl::Closure session_error_callback);
~CompositorContext() override;
private:
const std::string debug_label_;
SessionConnection session_connection_;
// |flow::CompositorContext|
std::unique_ptr<ScopedFrame> AcquireFrame(
GrContext* gr_context,
SkCanvas* canvas,
bool instrumentation_enabled) override;
FXL_DISALLOW_COPY_AND_ASSIGN(CompositorContext);
};
} // namespace flutter
// Copyright 2018 The Fuchsia 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 "engine.h"
#include <sstream>
#include "flutter/common/task_runners.h"
#include "flutter/fml/task_runner.h"
#include "flutter/shell/common/rasterizer.h"
#include "flutter/shell/common/run_configuration.h"
#include "lib/fsl/tasks/message_loop.h"
#include "lib/fxl/functional/make_copyable.h"
#include "lib/fxl/synchronization/waitable_event.h"
#include "platform_view.h"
#ifdef ERROR
#undef ERROR
#endif
namespace flutter {
Engine::Engine(Delegate& delegate,
std::string thread_label,
component::ApplicationContext& application_context,
blink::Settings settings,
f1dl::InterfaceRequest<mozart::ViewOwner> view_owner,
const UniqueFDIONS& fdio_ns,
f1dl::InterfaceRequest<component::ServiceProvider>
outgoing_services_request)
: delegate_(delegate),
thread_label_(std::move(thread_label)),
settings_(std::move(settings)),
weak_factory_(this) {
// Launch the threads that will be used to run the shell. These threads will
// be joined in the destructor.
for (auto& thread : host_threads_) {
thread.Run();
}
mozart::ViewManagerPtr view_manager;
application_context.ConnectToEnvironmentService(view_manager.NewRequest());
zx::eventpair import_token, export_token;
if (zx::eventpair::create(0u, &import_token, &export_token) != ZX_OK) {
FXL_DLOG(ERROR) << "Could not create event pair.";
return;
}
// Setup the session connection.
ui::ScenicPtr scenic;
view_manager->GetScenic(scenic.NewRequest());
// Grab the parent environent services. The platform view may want to access
// some of these services.
component::ServiceProviderPtr parent_environment_service_provider;
application_context.environment()->GetServices(
parent_environment_service_provider.NewRequest());
// We need to manually schedule a frame when the session metrics change.
OnMetricsUpdate on_session_metrics_change_callback = std::bind(
&Engine::OnSessionMetricsDidChange, this, std::placeholders::_1);
fxl::Closure on_session_error_callback = std::bind(&Engine::Terminate, this);
// Grab the accessibilty context writer that can understand the semtics tree
// on the platform view.
maxwell::ContextWriterPtr accessibility_context_writer;
application_context.ConnectToEnvironmentService(
accessibility_context_writer.NewRequest());
// Setup the callback that will instantiate the platform view.
shell::Shell::CreateCallback<shell::PlatformView> on_create_platform_view =
fxl::MakeCopyable([debug_label = thread_label_, //
parent_environment_service_provider =
std::move(parent_environment_service_provider), //
view_manager = std::ref(view_manager), //
view_owner = std::move(view_owner), //
scenic = std::move(scenic), //
accessibility_context_writer =
std::move(accessibility_context_writer), //
export_token = std::move(export_token), //
import_token = std::move(import_token), //
on_session_metrics_change_callback, //
on_session_error_callback //
](shell::Shell& shell) mutable {
return std::make_unique<flutter::PlatformView>(
shell, // delegate
debug_label, // debug label
shell.GetTaskRunners(), // task runners
std::move(parent_environment_service_provider), // services
view_manager, // view manager
std::move(view_owner), // view owner
std::move(scenic), // scenic
std::move(export_token), // export token
std::move(import_token), // import token
std::move(
accessibility_context_writer), // accessibility context writer
std::move(on_session_metrics_change_callback), // metrics change
std::move(on_session_error_callback) // session_error
);
});
// Setup the callback that will instantiate the rasterizer.
shell::Shell::CreateCallback<shell::Rasterizer> on_create_rasterizer =
[](shell::Shell& shell) {
return std::make_unique<shell::Rasterizer>(
shell.GetTaskRunners() // task runners
);
};
// Get the task runners from the managed threads. The current thread will be
// used as the "platform" thread.
blink::TaskRunners task_runners(
thread_label_, // Dart thread labels
fsl::MessageLoop::GetCurrent()->task_runner(), // platform
host_threads_[0].TaskRunner(), // gpu
host_threads_[1].TaskRunner(), // ui
host_threads_[2].TaskRunner() // io
);
settings_.root_isolate_create_callback =
std::bind(&Engine::OnMainIsolateStart, this);
settings_.root_isolate_shutdown_callback =
std::bind([weak = weak_factory_.GetWeakPtr(),
runner = task_runners.GetPlatformTaskRunner()]() {
runner->PostTask([weak = std::move(weak)] {
if (weak) {
weak->OnMainIsolateShutdown();
}
});
});
shell_ = shell::Shell::Create(
task_runners, // host task runners
settings_, // shell launch settings
on_create_platform_view, // platform view create callback
on_create_rasterizer // rasterizer create callback
);
if (!shell_) {
FXL_LOG(ERROR) << "Could not launch the shell with settings: "
<< settings_.ToString();
return;
}
// Shell has been created. Before we run the engine, setup the isolate
// configurator.
{
PlatformView* platform_view =
static_cast<PlatformView*>(shell_->GetPlatformView().get());
auto& view = platform_view->GetMozartView();
component::ApplicationEnvironmentPtr application_environment;
application_context.ConnectToEnvironmentService(
application_environment.NewRequest());
isolate_configurator_ = std::make_unique<IsolateConfigurator>(
fdio_ns, //
view, //
std::move(application_environment), //
std::move(outgoing_services_request) //
);
}
// This platform does not get a separate surface platform view creation
// notification. Fire one eagerly.
shell_->GetPlatformView()->NotifyCreated();
// Launch the engine in the appropriate configuration.
auto run_configuration =
shell::RunConfiguration::InferFromSettings(settings_);
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
fxl::MakeCopyable([engine = shell_->GetEngine(), //
run_configuration = std::move(run_configuration) //
]() mutable {
if (!engine || !engine->Run(std::move(run_configuration))) {
FXL_LOG(ERROR) << "Could not (re)launch the engine in configuration";
}
}));
UpdateNativeThreadLabelNames();
}
Engine::~Engine() {
for (const auto& thread : host_threads_) {
thread.TaskRunner()->PostTask(
[]() { fsl::MessageLoop::GetCurrent()->PostQuitTask(); });
}
}
void Engine::UpdateNativeThreadLabelNames() const {
auto set_thread_name = [](fxl::RefPtr<fxl::TaskRunner> runner,
std::string prefix, std::string suffix) {
runner->PostTask([name = prefix + suffix]() {
zx::thread::self().set_property(ZX_PROP_NAME, name.c_str(), name.size());
});
};
auto runners = shell_->GetTaskRunners();
set_thread_name(runners.GetPlatformTaskRunner(), thread_label_, ".platform");
set_thread_name(runners.GetUITaskRunner(), thread_label_, ".ui");
set_thread_name(runners.GetGPUTaskRunner(), thread_label_, ".gpu");
set_thread_name(runners.GetIOTaskRunner(), thread_label_, ".io");
}
std::pair<bool, uint32_t> Engine::GetEngineReturnCode() const {
std::pair<bool, uint32_t> code(false, 0);
if (!shell_) {
return code;
}
fxl::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
shell_->GetTaskRunners().GetUITaskRunner(),
[&latch, &code, engine = shell_->GetEngine()]() {
if (engine) {
code = engine->GetUIIsolateReturnCode();
}
latch.Signal();
});
latch.Wait();
return code;
}
void Engine::OnMainIsolateStart() {
if (!isolate_configurator_ ||
!isolate_configurator_->ConfigureCurrentIsolate()) {
FXL_LOG(ERROR) << "Could not configure some native embedder bindings for a "
"new root isolate.";
}
}
void Engine::OnMainIsolateShutdown() {
Terminate();
}
void Engine::Terminate() {
delegate_.OnEngineTerminate(this);
// Warning. Do not do anything after this point as the delegate may have
// collected this object.
}
void Engine::OnSessionMetricsDidChange(double device_pixel_ratio) {
if (!shell_) {
return;
}
shell_->GetTaskRunners().GetPlatformTaskRunner()->PostTask(
[platform_view = shell_->GetPlatformView(), device_pixel_ratio]() {
if (platform_view) {
reinterpret_cast<flutter::PlatformView*>(platform_view.get())
->UpdateViewportMetrics(device_pixel_ratio);
}
});
}
} // namespace flutter
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "flutter/shell/common/shell.h"
#include "isolate_configurator.h"
#include "lib/app/cpp/application_context.h"
#include "lib/fsl/threading/thread.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/memory/weak_ptr.h"
#include "lib/ui/views/fidl/view_manager.fidl.h"
namespace flutter {
// Represents an instance of running Flutter engine along with the threads that
// host the same.
class Engine final {
public:
class Delegate {
public:
virtual void OnEngineTerminate(const Engine* holder) = 0;
};
Engine(Delegate& delegate,
std::string thread_label,
component::ApplicationContext& application_context,
blink::Settings settings,
f1dl::InterfaceRequest<mozart::ViewOwner> view_owner,
const UniqueFDIONS& fdio_ns,
f1dl::InterfaceRequest<component::ServiceProvider>
outgoing_services_request);
~Engine();
// Returns the Dart return code for the root isolate if one is present. This
// call is thread safe and synchronous. This call must be made infrequently.
std::pair<bool, uint32_t> GetEngineReturnCode() const;
private:
Delegate& delegate_;
const std::string thread_label_;
blink::Settings settings_;
std::array<fsl::Thread, 3> host_threads_;
std::unique_ptr<IsolateConfigurator> isolate_configurator_;
std::unique_ptr<shell::Shell> shell_;
fxl::WeakPtrFactory<Engine> weak_factory_;
void OnMainIsolateStart();
void OnMainIsolateShutdown();
void Terminate();
void OnSessionMetricsDidChange(double device_pixel_ratio);
void UpdateNativeThreadLabelNames() const;
FXL_DISALLOW_COPY_AND_ASSIGN(Engine);
};
} // namespace flutter
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "flutter/content_handler/fuchsia_font_manager.h"
#include "fuchsia_font_manager.h"
#include <zx/vmar.h>
......@@ -32,14 +32,14 @@ void UnmapMemory(const void* buffer, void* context) {
zx::vmar::root_self().unmap(reinterpret_cast<uintptr_t>(buffer), size);
}
sk_sp<SkData> MakeSkDataFromBuffer(mem::Buffer data) {
if (!fsl::SizedVmo::IsSizeValid(data.vmo, data.size) ||
data.size > std::numeric_limits<size_t>::max()) {
sk_sp<SkData> MakeSkDataFromVMO(const fsl::SizedVmoTransportPtr& vmo) {
if (!fsl::SizedVmo::IsSizeValid(vmo->vmo, vmo->size) ||
vmo->size > std::numeric_limits<size_t>::max()) {
return nullptr;
}
uint64_t size = data.size;
uint64_t size = vmo->size;
uintptr_t buffer = 0;
zx_status_t status = zx::vmar::root_self().map(0, data.vmo, 0, size,
zx_status_t status = zx::vmar::root_self().map(0, vmo->vmo, 0, size,
ZX_VM_FLAG_PERM_READ, &buffer);
if (status != ZX_OK)
return nullptr;
......@@ -49,7 +49,7 @@ sk_sp<SkData> MakeSkDataFromBuffer(mem::Buffer data) {
fonts::FontSlant ToFontSlant(SkFontStyle::Slant slant) {
return (slant == SkFontStyle::kItalic_Slant) ? fonts::FontSlant::ITALIC
: fonts::FontSlant::UPRIGHT;
: fonts::FontSlant::UPRIGHT;
}
} // anonymous namespace
......@@ -64,7 +64,8 @@ int FuchsiaFontManager::onCountFamilies() const {
return 0;
}
void FuchsiaFontManager::onGetFamilyName(int index, SkString* familyName) const {
void FuchsiaFontManager::onGetFamilyName(int index,
SkString* familyName) const {
FXL_DCHECK(false);
}
......@@ -87,12 +88,13 @@ SkFontStyleSet* FuchsiaFontManager::onMatchFamily(
}
SkTypeface* FuchsiaFontManager::onMatchFamilyStyle(
const char family_name[], const SkFontStyle& style) const {
fonts::FontRequest request;
request.family = family_name;
request.weight = style.weight();
request.width = style.width();
request.slant = ToFontSlant(style.slant());
const char family_name[],
const SkFontStyle& style) const {
auto request = fonts::FontRequest::New();
request->family = family_name;
request->weight = style.weight();
request->width = style.width();
request->slant = ToFontSlant(style.slant());
fonts::FontResponsePtr response;
font_provider_->GetFont(
......@@ -100,14 +102,13 @@ SkTypeface* FuchsiaFontManager::onMatchFamilyStyle(
[&response](fonts::FontResponsePtr r) { response = std::move(r); });
font_provider_.WaitForResponse();
FXL_DCHECK(response)
<< "Unable to contact the font provider. Did you run "
"Flutter in an environment that has a font manager?\n";
if (!response)
if (!response) {
FXL_DLOG(ERROR) << "Unable to contact the font provider. Did you run "
"Flutter in an environment that has a font manager?";
return nullptr;
}
sk_sp<SkData> data = MakeSkDataFromBuffer(std::move(response->data.buffer));
sk_sp<SkData> data = MakeSkDataFromVMO(response->data->vmo);
if (!data)
return nullptr;
......@@ -127,13 +128,13 @@ SkTypeface* FuchsiaFontManager::onMatchFamilyStyleCharacter(
}
SkTypeface* FuchsiaFontManager::onMatchFaceStyle(const SkTypeface*,
const SkFontStyle&) const {
const SkFontStyle&) const {
FXL_DCHECK(false);
return nullptr;
}
sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromData(sk_sp<SkData>,
int ttcIndex) const {
int ttcIndex) const {
FXL_DCHECK(false);
return nullptr;
}
......@@ -153,7 +154,7 @@ sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromStreamArgs(
}
sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromFile(const char path[],
int ttcIndex) const {
int ttcIndex) const {
FXL_DCHECK(false);
return nullptr;
}
......
......@@ -26,7 +26,7 @@
namespace txt {
class FuchsiaFontManager : public SkFontMgr {
class FuchsiaFontManager final : public SkFontMgr {
public:
FuchsiaFontManager(fonts::FontProviderPtr provider);
......
// Copyright 2018 The Fuchsia 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 "isolate_configurator.h"
#include "dart-pkg/fuchsia/sdk_ext/fuchsia.h"
#include "dart-pkg/zircon/sdk_ext/handle.h"
#include "lib/tonic/converter/dart_converter.h"
#include "lib/tonic/dart_state.h"
#include "lib/tonic/logging/dart_error.h"
#include "lib/ui/flutter/sdk_ext/src/natives.h"
#include "third_party/dart/runtime/include/dart_api.h"
namespace flutter {
IsolateConfigurator::IsolateConfigurator(
const UniqueFDIONS& fdio_ns,
mozart::ViewPtr& view,
component::ApplicationEnvironmentPtr application_environment,
f1dl::InterfaceRequest<component::ServiceProvider>
outgoing_services_request)
: fdio_ns_(fdio_ns),
view_(view),
application_environment_(std::move(application_environment)),
outgoing_services_request_(std::move(outgoing_services_request)) {}
IsolateConfigurator::~IsolateConfigurator() = default;
bool IsolateConfigurator::ConfigureCurrentIsolate() {
if (used_) {
return false;
}
used_ = true;
BindFuchsia();
BindZircon();
BindDartIO();
BindScenic();
return true;
}
// |mozart::NativesDelegate|
mozart::View* IsolateConfigurator::GetMozartView() {
return view_.get();
}
void IsolateConfigurator::BindFuchsia() {
fuchsia::dart::Initialize(application_environment_.Unbind(),
std::move(outgoing_services_request_));
}
void IsolateConfigurator::BindZircon() {
// Tell dart:zircon about the FDIO namespace configured for this instance.
Dart_Handle zircon_lib = Dart_LookupLibrary(tonic::ToDart("dart:zircon"));
DART_CHECK_VALID(zircon_lib);
Dart_Handle namespace_type =
Dart_GetType(zircon_lib, tonic::ToDart("_Namespace"), 0, nullptr);
DART_CHECK_VALID(namespace_type);
DART_CHECK_VALID(
Dart_SetField(namespace_type, //
tonic::ToDart("_namespace"), //
tonic::ToDart(reinterpret_cast<intptr_t>(fdio_ns_.get()))));
}
void IsolateConfigurator::BindDartIO() {
// Grab the dart:io lib.
Dart_Handle io_lib = Dart_LookupLibrary(tonic::ToDart("dart:io"));
DART_CHECK_VALID(io_lib);
// Disable dart:io exit()
Dart_Handle embedder_config_type =
Dart_GetType(io_lib, tonic::ToDart("_EmbedderConfig"), 0, nullptr);
DART_CHECK_VALID(embedder_config_type);
DART_CHECK_VALID(Dart_SetField(embedder_config_type,
tonic::ToDart("_mayExit"), Dart_False()));
// Tell dart:io about the FDIO namespace configured for this instance.
Dart_Handle namespace_type =
Dart_GetType(io_lib, tonic::ToDart("_Namespace"), 0, nullptr);
DART_CHECK_VALID(namespace_type);
Dart_Handle namespace_args[] = {
Dart_NewInteger(reinterpret_cast<intptr_t>(fdio_ns_.get())), //
};
DART_CHECK_VALID(namespace_args[0]);
DART_CHECK_VALID(Dart_Invoke(namespace_type, tonic::ToDart("_setupNamespace"),
1, namespace_args));
}
void IsolateConfigurator::BindScenic() {
Dart_Handle mozart_internal =
Dart_LookupLibrary(tonic::ToDart("dart:mozart.internal"));
DART_CHECK_VALID(mozart_internal);
DART_CHECK_VALID(Dart_SetNativeResolver(mozart_internal, //
mozart::NativeLookup, //
mozart::NativeSymbol) //
);
DART_CHECK_VALID(Dart_SetField(
mozart_internal, //
tonic::ToDart("_context"), //
tonic::DartConverter<uint64_t>::ToDart(reinterpret_cast<intptr_t>(
static_cast<mozart::NativesDelegate*>(this)))));
mozart::ViewContainerPtr view_container;
view_->GetContainer(view_container.NewRequest());
DART_CHECK_VALID(
Dart_SetField(mozart_internal, //
tonic::ToDart("_viewContainer"), //
tonic::ToDart(zircon::dart::Handle::Create(
view_container.Unbind().TakeChannel().release()))));
}
} // namespace flutter
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "lib/app/fidl/application_environment.fidl.h"
#include "lib/fxl/macros.h"
#include "lib/ui/flutter/sdk_ext/src/natives.h"
#include "lib/ui/views/fidl/view_containers.fidl.h"
#include "lib/ui/views/fidl/views.fidl.h"
#include "unique_fdio_ns.h"
namespace flutter {
// Contains all the information necessary to configure a new root isolate. This
// is a single use item. The lifetime of this object must extend past that of
// the root isolate.
class IsolateConfigurator final : mozart::NativesDelegate {
public:
IsolateConfigurator(
const UniqueFDIONS& fdio_ns,
mozart::ViewPtr& view,
component::ApplicationEnvironmentPtr application_environment,
f1dl::InterfaceRequest<component::ServiceProvider>
outgoing_services_request);
~IsolateConfigurator();
// Can be used only once and only on the UI thread with the newly created
// isolate already current.
bool ConfigureCurrentIsolate();
private:
bool used_ = false;
const UniqueFDIONS& fdio_ns_;
mozart::ViewPtr& view_;
component::ApplicationEnvironmentPtr application_environment_;
f1dl::InterfaceRequest<component::ServiceProvider> outgoing_services_request_;
// |mozart::NativesDelegate|
mozart::View* GetMozartView() override;
void BindFuchsia();
void BindZircon();
void BindDartIO();
void BindScenic();
FXL_DISALLOW_COPY_AND_ASSIGN(IsolateConfigurator);
};
} // namespace flutter
// Copyright 2016 The Chromium Authors. All rights reserved.
// Copyright 2018 The Fuchsia 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 <trace-provider/provider.h>
#include <cstdlib>
#include "flutter/content_handler/app.h"
#include "application_runner.h"
#include "lib/fsl/tasks/message_loop.h"
int main(int argc, const char** argv) {
int main(int argc, char const* argv[]) {
fsl::MessageLoop loop;
trace::TraceProvider provider(loop.async());
flutter_runner::App app;
FXL_DCHECK(provider.is_valid()) << "Trace provider must be valid.";
FXL_LOG(INFO) << "Flutter application services initialized.";
flutter::ApplicationRunner runner([&loop]() {
loop.PostQuitTask();
FXL_LOG(INFO) << "Flutter application services terminated. Good bye...";
});
loop.Run();
return 0;
return EXIT_SUCCESS;
}
此差异已折叠。
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <map>
#include <set>
#include "accessibility_bridge.h"
#include "flutter/lib/ui/window/viewport_metrics.h"
#include "flutter/shell/common/platform_view.h"
#include "lib/clipboard/fidl/clipboard.fidl.h"
#include "lib/fidl/cpp/bindings/binding.h"
#include "lib/fxl/macros.h"
#include "lib/ui/input/fidl/input_connection.fidl.h"
#include "lib/ui/views/fidl/view_manager.fidl.h"
#include "lib/ui/views/fidl/views.fidl.h"
#include "surface.h"
namespace flutter {
// The per engine component residing on the platform thread is responsible for
// all platform specific integrations.
class PlatformView final : public shell::PlatformView,
public mozart::ViewListener,
public mozart::InputMethodEditorClient,
public mozart::InputListener {
public:
PlatformView(
PlatformView::Delegate& delegate,
std::string debug_label,
blink::TaskRunners task_runners,
component::ServiceProviderPtr parent_environment_service_provider,
mozart::ViewManagerPtr& view_manager,
f1dl::InterfaceRequest<mozart::ViewOwner> view_owner,
ui::ScenicPtr scenic,
zx::eventpair export_token,
zx::eventpair import_token,
maxwell::ContextWriterPtr accessibility_context_writer,
OnMetricsUpdate on_session_metrics_did_change,
fxl::Closure session_error_callback);
~PlatformView();
void UpdateViewportMetrics(double pixel_ratio);
mozart::ViewPtr& GetMozartView();
private:
const std::string debug_label_;
mozart::ViewPtr view_;
f1dl::Binding<mozart::ViewListener> view_listener_;
mozart::InputConnectionPtr input_connection_;
f1dl::Binding<mozart::InputListener> input_listener_;
int current_text_input_client_ = 0;
f1dl::Binding<mozart::InputMethodEditorClient> ime_client_;
mozart::InputMethodEditorPtr ime_;
modular::ClipboardPtr clipboard_;
ui::ScenicPtr scenic_;
AccessibilityBridge accessibility_bridge_;
std::unique_ptr<Surface> surface_;
blink::LogicalMetrics metrics_;
std::set<int> down_pointers_;
std::map<
std::string /* channel */,
std::function<void(
fxl::RefPtr<blink::PlatformMessage> /* message */)> /* handler */>
platform_message_handlers_;
void RegisterPlatformMessageHandlers();
void UpdateViewportMetrics(const mozart::ViewLayoutPtr& layout);
void FlushViewportMetrics();
// |mozart::ViewListener|
void OnPropertiesChanged(
mozart::ViewPropertiesPtr properties,
const OnPropertiesChangedCallback& callback) override;
// |mozart::InputMethodEditorClient|
void DidUpdateState(mozart::TextInputStatePtr state,
mozart::InputEventPtr event) override;
// |mozart::InputMethodEditorClient|
void OnAction(mozart::InputMethodAction action) override;
// |mozart::InputListener|
void OnEvent(mozart::InputEventPtr event,
const OnEventCallback& callback) override;
bool OnHandlePointerEvent(const mozart::PointerEventPtr& pointer);
bool OnHandleKeyboardEvent(const mozart::KeyboardEventPtr& keyboard);
bool OnHandleFocusEvent(const mozart::FocusEventPtr& focus);
// |shell::PlatformView|
std::unique_ptr<shell::Surface> CreateRenderingSurface() override;
// |shell::PlatformView|
void HandlePlatformMessage(
fxl::RefPtr<blink::PlatformMessage> message) override;
// |shell::PlatformView|
void UpdateSemantics(blink::SemanticsNodeUpdates update) override;
// Channel handler for kFlutterPlatformChannel
void HandleFlutterPlatformChannelPlatformMessage(
fxl::RefPtr<blink::PlatformMessage> message);
// Channel handler for kTextInputChannel
void HandleFlutterTextInputChannelPlatformMessage(
fxl::RefPtr<blink::PlatformMessage> message);
FXL_DISALLOW_COPY_AND_ASSIGN(PlatformView);
};
} // namespace flutter
// Copyright 2016 The Chromium 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/content_handler/rasterizer.h"
#include "flutter/content_handler/vulkan_rasterizer.h"
namespace flutter_runner {
Rasterizer::~Rasterizer() = default;
std::unique_ptr<Rasterizer> Rasterizer::Create() {
auto vulkan_rasterizer = std::make_unique<VulkanRasterizer>();
FXL_CHECK(vulkan_rasterizer)
<< "The vulkan rasterizer must be correctly initialized.";
return vulkan_rasterizer;
}
} // namespace flutter_runner
// Copyright 2016 The Chromium 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_CONTENT_HANDLER_RASTERIZER_H_
#define FLUTTER_CONTENT_HANDLER_RASTERIZER_H_
#include <memory>
#include <zx/eventpair.h>
#include "flutter/flow/layers/layer_tree.h"
#include "lib/fxl/functional/closure.h"
#include "lib/fxl/macros.h"
namespace flutter_runner {
class Rasterizer {
public:
virtual ~Rasterizer();
static std::unique_ptr<Rasterizer> Create();
virtual void SetScene(
fidl::InterfaceHandle<ui::Scenic> mozart,
zx::eventpair import_token,
fxl::Closure metrics_changed_callback) = 0;
virtual void Draw(std::unique_ptr<flow::LayerTree> layer_tree,
fxl::Closure callback) = 0;
};
} // namespace flutter_runner
#endif // FLUTTER_CONTENT_HANDLER_RASTERIZER_H_
此差异已折叠。
// Copyright 2016 The Chromium 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_CONTENT_HANDLER_RUNTIME_HOLDER_H_
#define FLUTTER_CONTENT_HANDLER_RUNTIME_HOLDER_H_
#include <fdio/namespace.h>
#include <zx/channel.h>
#include <unordered_set>
#include "dart-pkg/fuchsia/sdk_ext/fuchsia.h"
#include "flutter/assets/asset_provider.h"
#include "flutter/assets/directory_asset_bundle.h"
#include "flutter/assets/unzipper_provider.h"
#include "flutter/assets/zip_asset_store.h"
#include "flutter/content_handler/accessibility_bridge.h"
#include "flutter/flow/layers/layer_tree.h"
#include "flutter/lib/ui/window/viewport_metrics.h"
#include "flutter/runtime/runtime_controller.h"
#include "flutter/runtime/runtime_delegate.h"
#include "lib/app/cpp/application_context.h"
#include <fuchsia/cpp/component.h>
#include <fuchsia/cpp/component.h>
#include <fuchsia/cpp/modular.h>
#include "lib/fidl/cpp/binding.h"
#include "lib/fxl/functional/closure.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/memory/weak_ptr.h"
#include "lib/ui/flutter/sdk_ext/src/natives.h"
#include <fuchsia/cpp/ui.h>
#include <fuchsia/cpp/ui.h>
#include <fuchsia/cpp/ui.h>
namespace flutter_runner {
class Rasterizer;
class RuntimeHolder : public blink::RuntimeDelegate,
public mozart::NativesDelegate,
public views_v1::ViewListener,
public input::InputListener,
public input::InputMethodEditorClient {
public:
RuntimeHolder();
~RuntimeHolder();
void Init(fdio_ns_t* namespc,
std::unique_ptr<component::ApplicationContext> context,
fidl::InterfaceRequest<component::ServiceProvider> outgoing_services,
std::vector<char> bundle);
void CreateView(const std::string& script_uri,
fidl::InterfaceRequest<views_v1_token::ViewOwner> view_owner_request,
fidl::InterfaceRequest<component::ServiceProvider> services);
Dart_Port GetUIIsolateMainPort();
std::string GetUIIsolateName();
int32_t return_code() { return return_code_; }
void SetMainIsolateShutdownCallback(std::function<void()> callback);
private:
// |blink::RuntimeDelegate| implementation:
std::string DefaultRouteName() override;
void ScheduleFrame(bool regenerate_layer_tree = true) override;
void Render(std::unique_ptr<flow::LayerTree> layer_tree) override;
void UpdateSemantics(blink::SemanticsNodeUpdates update) override;
void HandlePlatformMessage(
fxl::RefPtr<blink::PlatformMessage> message) override;
void DidCreateMainIsolate(Dart_Isolate isolate) override;
void DidShutdownMainIsolate() override;
// |mozart::NativesDelegate| implementation:
views_v1::View* GetMozartView() override;
// |input::InputListener| implementation:
void OnEvent(input::InputEvent event,
OnEventCallback callback) override;
// |views_v1::ViewListener| implementation:
void OnPropertiesChanged(
views_v1::ViewProperties properties,
OnPropertiesChangedCallback callback) override;
// |input::InputMethodEditorClient| implementation:
void DidUpdateState(input::TextInputState state,
input::InputEventPtr event) override;
void OnAction(input::InputMethodAction action) override;
fxl::WeakPtr<RuntimeHolder> GetWeakPtr();
void InitRootBundle(std::vector<char> bundle);
blink::UnzipperProvider GetUnzipperProviderForRootBundle();
bool HandleAssetPlatformMessage(blink::PlatformMessage* message);
bool GetAssetAsBuffer(const std::string& name, std::vector<uint8_t>* data);
bool HandleTextInputPlatformMessage(blink::PlatformMessage* message);
bool HandleFlutterPlatformMessage(blink::PlatformMessage* message);
void InitDartIoInternal();
void InitFuchsia();
void InitZircon();
void InitScenicInternal();
void PostBeginFrame();
void BeginFrame();
void OnFrameComplete();
void OnRedrawFrame();
void Invalidate();
fdio_ns_t* namespc_;
int dirfd_;
std::unique_ptr<component::ApplicationContext> context_;
fidl::InterfaceRequest<component::ServiceProvider> outgoing_services_;
std::vector<char> root_bundle_data_;
// TODO(zarah): Remove asset_store_ when flx is completely removed
fxl::RefPtr<blink::ZipAssetStore> asset_store_;
fxl::RefPtr<blink::AssetProvider> asset_provider_;
void* dylib_handle_ = nullptr;
std::unique_ptr<Rasterizer> rasterizer_;
std::unique_ptr<blink::RuntimeController> runtime_;
blink::ViewportMetrics viewport_metrics_;
views_v1::ViewManagerPtr view_manager_;
fidl::Binding<views_v1::ViewListener> view_listener_binding_;
fidl::Binding<input::InputListener> input_listener_binding_;
input::InputConnectionPtr input_connection_;
views_v1::ViewPtr view_;
std::unordered_set<int> down_pointers_;
input::InputMethodEditorPtr input_method_editor_;
fidl::Binding<input::InputMethodEditorClient> text_input_binding_;
int current_text_input_client_ = 0;
fxl::TimePoint last_begin_frame_time_;
bool frame_outstanding_ = false;
bool frame_scheduled_ = false;
bool frame_rendering_ = false;
int32_t return_code_ = 0;
fxl::WeakPtrFactory<RuntimeHolder> weak_factory_;
std::unique_ptr<AccessibilityBridge> accessibility_bridge_;
std::function<void()> main_isolate_shutdown_callback_;
modular::ClipboardPtr clipboard_;
FXL_DISALLOW_COPY_AND_ASSIGN(RuntimeHolder);
};
} // namespace flutter_runner
#endif // FLUTTER_CONTENT_HANDLER_RUNTIME_HOLDER_H_
// Copyright 2017 The Chromium 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/content_handler/service_protocol_hooks.h"
#include <string.h>
#include <string>
#include <vector>
#include "flutter/common/threads.h"
#include "flutter/content_handler/app.h"
#include "lib/fxl/memory/weak_ptr.h"
namespace flutter_runner {
namespace {
constexpr char kViewIdPrefx[] = "_flutterView/";
constexpr size_t kViewIdPrefxLength = sizeof(kViewIdPrefx) - 1;
static intptr_t KeyIndex(const char** param_keys,
intptr_t num_params,
const char* key) {
if (param_keys == NULL) {
return -1;
}
for (intptr_t i = 0; i < num_params; i++) {
if (strcmp(param_keys[i], key) == 0) {
return i;
}
}
return -1;
}
static const char* ValueForKey(const char** param_keys,
const char** param_values,
intptr_t num_params,
const char* key) {
intptr_t index = KeyIndex(param_keys, num_params, key);
if (index < 0) {
return NULL;
}
return param_values[index];
}
static void AppendIsolateRef(std::stringstream* stream,
int64_t main_port,
const std::string name) {
*stream << "{\"type\":\"@Isolate\",\"fixedId\":true,\"id\":\"isolates/";
*stream << main_port << "\",\"name\":\"" << name << "\",";
*stream << "\"number\":\"" << main_port << "\"}";
}
static void AppendFlutterView(std::stringstream* stream,
uintptr_t view_id,
int64_t isolate_id,
const std::string isolate_name) {
*stream << "{\"type\":\"FlutterView\", \"id\": \"" << kViewIdPrefx << "0x"
<< std::hex << view_id << std::dec << "\"";
if (isolate_id != ILLEGAL_PORT) {
// Append the isolate (if it exists).
*stream << ","
<< "\"isolate\":";
AppendIsolateRef(stream, isolate_id, isolate_name);
}
*stream << "}";
}
} // namespace
void ServiceProtocolHooks::RegisterHooks(bool running_precompiled_code) {
// Listing of FlutterViews.
Dart_RegisterRootServiceRequestCallback(kListViewsExtensionName, &ListViews,
nullptr);
Dart_RegisterRootServiceRequestCallback(kSetAssetBundlePathExtensionName,
&SetAssetBundlePath, nullptr);
}
const char* ServiceProtocolHooks::kListViewsExtensionName =
"_flutter.listViews";
bool ServiceProtocolHooks::ListViews(const char* method,
const char** param_keys,
const char** param_values,
intptr_t num_params,
void* user_data,
const char** json_object) {
// Ask the App for the list of platform views. This will run a task on
// the UI thread before returning.
App& app = App::Shared();
std::vector<App::PlatformViewInfo> platform_views;
app.WaitForPlatformViewIds(&platform_views);
std::stringstream response;
response << "{\"type\":\"FlutterViewList\",\"views\":[";
bool prefix_comma = false;
for (auto it = platform_views.begin(); it != platform_views.end(); it++) {
uintptr_t view_id = it->view_id;
int64_t isolate_id = it->isolate_id;
const std::string& isolate_name = it->isolate_name;
if (!view_id) {
continue;
}
if (prefix_comma) {
response << ',';
} else {
prefix_comma = true;
}
AppendFlutterView(&response, view_id, isolate_id, isolate_name);
}
response << "]}";
// Copy the response.
*json_object = strdup(response.str().c_str());
return true;
}
const char* ServiceProtocolHooks::kSetAssetBundlePathExtensionName =
"_flutter.setAssetBundlePath";
bool ServiceProtocolHooks::SetAssetBundlePath(const char* method,
const char** param_keys,
const char** param_values,
intptr_t num_params,
void* user_data,
const char** json_object) {
const char* view_id_str =
ValueForKey(param_keys, param_values, num_params, "viewId");
// Ask the App for the list of platform views. This will run a task on
// the UI thread before returning.
App& app = App::Shared();
std::vector<App::PlatformViewInfo> platform_views;
app.WaitForPlatformViewIds(&platform_views);
// Convert the actual flutter view hex id into a number.
uintptr_t view_id_as_num =
std::stoull((view_id_str + kViewIdPrefxLength), nullptr, 16);
// The view existed and the isolate was created. Success.
std::stringstream response;
response << "{\"type\":\"Success\","
<< "\"view\":";
for (auto it = platform_views.begin(); it != platform_views.end(); it++) {
uintptr_t view_id = it->view_id;
int64_t isolate_id = it->isolate_id;
const std::string& isolate_name = it->isolate_name;
if (!view_id || view_id != view_id_as_num) {
continue;
}
// TODO(DX): Set up asset bundle path for the isolate.
AppendFlutterView(&response, view_id, isolate_id, isolate_name);
break;
}
response << "}";
*json_object = strdup(response.str().c_str());
return true;
}
} // namespace flutter_runner
// Copyright 2017 The Chromium 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_CONTENT_HANDLER_SERVICE_PROTOCOL_HOOKS_H_
#define FLUTTER_CONTENT_HANDLER_SERVICE_PROTOCOL_HOOKS_H_
#include "lib/fxl/synchronization/waitable_event.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"
namespace flutter_runner {
class ServiceProtocolHooks {
public:
static void RegisterHooks(bool running_precompiled_code);
private:
static const char* kListViewsExtensionName;
static bool ListViews(const char* method,
const char** param_keys,
const char** param_values,
intptr_t num_params,
void* user_data,
const char** json_object);
static const char* kSetAssetBundlePathExtensionName;
static bool SetAssetBundlePath(const char* method,
const char** param_keys,
const char** param_values,
intptr_t num_params,
void* user_data,
const char** json_object);
};
} // namespace flutter_runner
#endif // FLUTTER_CONTENT_HANDLER_SERVICE_PROTOCOL_HOOKS_H_
此差异已折叠。
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "compositor_context.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/common/surface.h"
#include "lib/fxl/macros.h"
namespace flutter {
// The interface between the Flutter rasterizer and the underlying platform. May
// be constructed on any thread but will be used by the engine only on the GPU
// thread.
class Surface final : public shell::Surface {
public:
Surface(const ui::ScenicPtr& scenic,
std::string debug_label,
zx::eventpair import_token,
OnMetricsUpdate session_metrics_did_change_callback,
fxl::Closure session_error_callback);
~Surface() override;
private:
const bool valid_ = CanConnectToDisplay();
const std::string debug_label_;
std::unique_ptr<CompositorContext> compositor_context_;
// |shell::Surface|
bool IsValid() override;
// |shell::Surface|
std::unique_ptr<shell::SurfaceFrame> AcquireFrame(
const SkISize& size) override;
// |shell::Surface|
GrContext* GetContext() override;
static bool CanConnectToDisplay();
FXL_DISALLOW_COPY_AND_ASSIGN(Surface);
};
} // namespace flutter
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -80,3 +80,8 @@ std::ostream& operator<<(std::ostream& os, const flow::RasterCacheKey& k) {
;
return os;
}
std::ostream& operator<<(std::ostream& os, const SkISize& size) {
os << size.width() << ", " << size.height();
return os;
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册