Skip to content

Commit e3fdb23

Browse files
authored
[fuchsia] Add ability to configure separate data and asset dirs (flutter#18858)
This allows Fuchsia components executed by the Flutter runner to specify a directory containing assets if they wish to store assets separate from program data. This is specified in the program metadata field within the component's specification with the new "assets" attribute. If this attribute is absent, assets are loaded relative to the path specified in the "data" attribute as before. This is useful in the short term to use a location in the package where we can store small files more efficiently. It is also potentially useful longer term to enforce a stronger separatation between executable program data and non-executable assets. This commit adds some basic unit testing for the data parsing to the flutter_runner_tests suite.
1 parent 7cb7003 commit e3fdb23

File tree

5 files changed

+113
-26
lines changed

5 files changed

+113
-26
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@ FILE: ../../../flutter/shell/platform/fuchsia/flutter/accessibility_bridge_unitt
11011101
FILE: ../../../flutter/shell/platform/fuchsia/flutter/collect_traces.dart
11021102
FILE: ../../../flutter/shell/platform/fuchsia/flutter/component.cc
11031103
FILE: ../../../flutter/shell/platform/fuchsia/flutter/component.h
1104+
FILE: ../../../flutter/shell/platform/fuchsia/flutter/component_unittest.cc
11041105
FILE: ../../../flutter/shell/platform/fuchsia/flutter/compositor_context.cc
11051106
FILE: ../../../flutter/shell/platform/fuchsia/flutter/compositor_context.h
11061107
FILE: ../../../flutter/shell/platform/fuchsia/flutter/engine.cc

shell/platform/fuchsia/flutter/BUILD.gn

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ executable("flutter_runner_unittests") {
271271
"accessibility_bridge.cc",
272272
"accessibility_bridge.h",
273273
"accessibility_bridge_unittest.cc",
274+
"component.cc",
275+
"component.h",
276+
"component_unittest.cc",
274277
"flutter_runner_fakes.h",
275278
"flutter_runner_product_configuration.cc",
276279
"flutter_runner_product_configuration.h",
@@ -315,6 +318,7 @@ executable("flutter_runner_unittests") {
315318
"//build/fuchsia/pkg:async-loop-default",
316319
"//build/fuchsia/pkg:scenic_cpp",
317320
"//build/fuchsia/pkg:sys_cpp_testing",
321+
"//flutter/common",
318322
"//flutter/flow",
319323
"//flutter/lib/ui",
320324
"//flutter/runtime",

shell/platform/fuchsia/flutter/component.cc

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,33 @@ constexpr uint32_t OPEN_RIGHT_EXECUTABLE = 8u;
5151
namespace flutter_runner {
5252

5353
constexpr char kDataKey[] = "data";
54+
constexpr char kAssetsKey[] = "assets";
5455
constexpr char kTmpPath[] = "/tmp";
5556
constexpr char kServiceRootPath[] = "/svc";
5657

58+
// static
59+
void Application::ParseProgramMetadata(
60+
const fidl::VectorPtr<fuchsia::sys::ProgramMetadata>& program_metadata,
61+
std::string* data_path,
62+
std::string* assets_path) {
63+
if (!program_metadata.has_value()) {
64+
return;
65+
}
66+
for (const auto& pg : *program_metadata) {
67+
if (pg.key.compare(kDataKey) == 0) {
68+
*data_path = "pkg/" + pg.value;
69+
} else if (pg.key.compare(kAssetsKey) == 0) {
70+
*assets_path = "pkg/" + pg.value;
71+
}
72+
}
73+
74+
// assets_path defaults to the same as data_path if omitted.
75+
if (assets_path->empty()) {
76+
*assets_path = *data_path;
77+
}
78+
}
79+
80+
// static
5781
ActiveApplication Application::Create(
5882
TerminationCallback termination_callback,
5983
fuchsia::sys::Package package,
@@ -149,14 +173,11 @@ Application::Application(
149173
settings_.dart_entrypoint_args = arguments.value();
150174
}
151175

152-
// Determine /pkg/data directory from StartupInfo.
176+
// Determine where data and assets are stored within /pkg.
153177
std::string data_path;
154-
for (size_t i = 0; i < startup_info.program_metadata->size(); ++i) {
155-
auto pg = startup_info.program_metadata->at(i);
156-
if (pg.key.compare(kDataKey) == 0) {
157-
data_path = "pkg/" + pg.value;
158-
}
159-
}
178+
std::string assets_path;
179+
ParseProgramMetadata(startup_info.program_metadata, &data_path, &assets_path);
180+
160181
if (data_path.empty()) {
161182
FML_DLOG(ERROR) << "Could not find a /pkg/data directory for "
162183
<< package.resolved_url;
@@ -189,11 +210,20 @@ Application::Application(
189210
}
190211
}
191212

192-
application_directory_.reset(fdio_ns_opendir(fdio_ns_.get()));
193-
FML_DCHECK(application_directory_.is_valid());
213+
{
214+
fml::UniqueFD ns_fd(fdio_ns_opendir(fdio_ns_.get()));
215+
FML_DCHECK(ns_fd.is_valid());
216+
217+
constexpr mode_t mode = O_RDONLY | O_DIRECTORY;
194218

195-
application_assets_directory_.reset(openat(
196-
application_directory_.get(), data_path.c_str(), O_RDONLY | O_DIRECTORY));
219+
application_assets_directory_.reset(
220+
openat(ns_fd.get(), assets_path.c_str(), mode));
221+
FML_DCHECK(application_assets_directory_.is_valid());
222+
223+
application_data_directory_.reset(
224+
openat(ns_fd.get(), data_path.c_str(), mode));
225+
FML_DCHECK(application_data_directory_.is_valid());
226+
}
197227

198228
// TODO: LaunchInfo::out.
199229

@@ -294,7 +324,7 @@ Application::Application(
294324
std::string app_framework;
295325
if (dart_utils::ReadFileToString("pkg/data/runner.frameworkversion",
296326
&runner_framework) &&
297-
dart_utils::ReadFileToStringAt(application_assets_directory_.get(),
327+
dart_utils::ReadFileToStringAt(application_data_directory_.get(),
298328
"app.frameworkversion",
299329
&app_framework) &&
300330
(runner_framework.compare(app_framework) == 0)) {
@@ -509,7 +539,7 @@ void Application::AttemptVMLaunchWithCurrentSettings(
509539

510540
std::shared_ptr<dart_utils::ElfSnapshot> snapshot =
511541
std::make_shared<dart_utils::ElfSnapshot>();
512-
if (snapshot->Load(application_assets_directory_.get(),
542+
if (snapshot->Load(application_data_directory_.get(),
513543
"app_aot_snapshot.so")) {
514544
const uint8_t* isolate_data = snapshot->IsolateData();
515545
const uint8_t* isolate_instructions = snapshot->IsolateInstrs();
@@ -531,20 +561,16 @@ void Application::AttemptVMLaunchWithCurrentSettings(
531561
hold_snapshot));
532562
} else {
533563
vm_snapshot = fml::MakeRefCounted<flutter::DartSnapshot>(
534-
CreateWithContentsOfFile(
535-
application_assets_directory_.get() /* /pkg/data */,
536-
"vm_snapshot_data.bin", false),
537-
CreateWithContentsOfFile(
538-
application_assets_directory_.get() /* /pkg/data */,
539-
"vm_snapshot_instructions.bin", true));
564+
CreateWithContentsOfFile(application_data_directory_.get(),
565+
"vm_snapshot_data.bin", false),
566+
CreateWithContentsOfFile(application_data_directory_.get(),
567+
"vm_snapshot_instructions.bin", true));
540568

541569
isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
542-
CreateWithContentsOfFile(
543-
application_assets_directory_.get() /* /pkg/data */,
544-
"isolate_snapshot_data.bin", false),
545-
CreateWithContentsOfFile(
546-
application_assets_directory_.get() /* /pkg/data */,
547-
"isolate_snapshot_instructions.bin", true));
570+
CreateWithContentsOfFile(application_data_directory_.get(),
571+
"isolate_snapshot_data.bin", false),
572+
CreateWithContentsOfFile(application_data_directory_.get(),
573+
"isolate_snapshot_instructions.bin", true));
548574
}
549575

550576
auto vm = flutter::DartVMRef::Create(settings_, //

shell/platform/fuchsia/flutter/component.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ class Application final : public Engine::Delegate,
7070
// may be collected after.
7171
~Application();
7272

73+
static void ParseProgramMetadata(
74+
const fidl::VectorPtr<fuchsia::sys::ProgramMetadata>& program_metadata,
75+
std::string* data_path,
76+
std::string* assets_path);
77+
7378
const std::string& GetDebugLabel() const;
7479

7580
#if !defined(DART_PRODUCT)
@@ -82,7 +87,7 @@ class Application final : public Engine::Delegate,
8287
TerminationCallback termination_callback_;
8388
const std::string debug_label_;
8489
UniqueFDIONS fdio_ns_ = UniqueFDIONSCreate();
85-
fml::UniqueFD application_directory_;
90+
fml::UniqueFD application_data_directory_;
8691
fml::UniqueFD application_assets_directory_;
8792

8893
fidl::Binding<fuchsia::sys::ComponentController> application_controller_;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/shell/platform/fuchsia/flutter/component.h"
6+
7+
#include <gtest/gtest.h>
8+
9+
namespace flutter_runner {
10+
namespace {
11+
12+
TEST(Component, ParseProgramMetadata) {
13+
std::string data_path;
14+
std::string assets_path;
15+
16+
// The ProgramMetadata field may be null. We should parse this as if no
17+
// fields were specified.
18+
Application::ParseProgramMetadata(nullptr, &data_path, &assets_path);
19+
20+
EXPECT_EQ(data_path, "");
21+
EXPECT_EQ(assets_path, "");
22+
23+
// The ProgramMetadata field may be empty. Treat this the same as null.
24+
fidl::VectorPtr<fuchsia::sys::ProgramMetadata> program_metadata(size_t{0});
25+
26+
Application::ParseProgramMetadata(program_metadata, &data_path, &assets_path);
27+
28+
EXPECT_EQ(data_path, "");
29+
EXPECT_EQ(assets_path, "");
30+
31+
// The assets_path defaults to the "data" value if unspecified
32+
program_metadata = {{"data", "foobar"}};
33+
34+
Application::ParseProgramMetadata(program_metadata, &data_path, &assets_path);
35+
36+
EXPECT_EQ(data_path, "pkg/foobar");
37+
EXPECT_EQ(assets_path, "pkg/foobar");
38+
39+
data_path = "";
40+
assets_path = "";
41+
42+
program_metadata = {{"not_data", "foo"}, {"data", "bar"}, {"assets", "baz"}};
43+
44+
Application::ParseProgramMetadata(program_metadata, &data_path, &assets_path);
45+
46+
EXPECT_EQ(data_path, "pkg/bar");
47+
EXPECT_EQ(assets_path, "pkg/baz");
48+
}
49+
50+
} // anonymous namespace
51+
} // namespace flutter_runner

0 commit comments

Comments
 (0)