Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
16 changes: 16 additions & 0 deletions shell/common/fixtures/shell_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,19 @@ void localtimesMatch() {
// formatting since package:intl is not available.
notifyLocalTime(timeStr.split(":")[0]);
}

void notifyCanAccessResource(bool success) native 'NotifyCanAccessResource';

void notifySetAssetBundlePath() native 'NotifySetAssetBundlePath';

@pragma('vm:entry-point')
void canAccessResourceFromAssetDir() async {
notifySetAssetBundlePath();
window.sendPlatformMessage(
'flutter/assets',
Uint8List.fromList(utf8.encode('kernel_blob.bin')).buffer.asByteData(),
(ByteData byteData) {
notifyCanAccessResource(byteData != null);
},
);
}
22 changes: 22 additions & 0 deletions shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1404,6 +1404,17 @@ bool Shell::OnServiceProtocolRunInView(
configuration.AddAssetResolver(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all seems much simpler

std::make_unique<DirectoryAssetBundle>(fml::OpenDirectory(
asset_directory_path.c_str(), false, fml::FilePermission::kRead)));
// Add the original asset directory to the resolvers so that unmodified assets
// bundled with the application specific format (APK, IPA) can be used without
// syncing to the Dart devFS.
if (fml::UniqueFD::traits_type::IsValid(settings_.assets_dir)) {
configuration.AddAssetResolver(std::make_unique<DirectoryAssetBundle>(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the code that constructs this asset resolver be broken out into a function shared between this and OnServiceProtocolSetAssetBundlePath?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a function that creates the resolver, PTAL and let me know if I'm following the proper flutter engine/c++ idioms

fml::Duplicate(settings_.assets_dir)));
} else {
configuration.AddAssetResolver(
std::make_unique<DirectoryAssetBundle>(fml::OpenDirectory(
settings_.assets_path.c_str(), false, fml::FilePermission::kRead)));
}

auto& allocator = response->GetAllocator();
response->SetObject();
Expand Down Expand Up @@ -1516,6 +1527,17 @@ bool Shell::OnServiceProtocolSetAssetBundlePath(

auto asset_manager = std::make_shared<AssetManager>();

// Add the original asset directory to the resolvers so that unmodified assets
// bundled with the application specific format (APK, IPA) can be used without
// syncing to the Dart devFS.
if (fml::UniqueFD::traits_type::IsValid(settings_.assets_dir)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to settings_.assets_dir.is_valid()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

../../flutter/shell/common/shell.cc(1410,27): error: member reference base type 'const fml::UniqueFD::element_type' (aka 'void *const') is not a structure or union
  if (settings_.assets_dir.is_valid()) {
      ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~

Do I need to import another file for this to work?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my mistake - assets_dir is a UniqueFD::element_type, not a UniqueFD. So you will need to use UniqueFD::traits_type::IsValid

asset_manager->PushFront(std::make_unique<DirectoryAssetBundle>(
fml::Duplicate(settings_.assets_dir)));
} else {
asset_manager->PushFront(
std::make_unique<DirectoryAssetBundle>(fml::OpenDirectory(
settings_.assets_path.c_str(), false, fml::FilePermission::kRead)));
}
asset_manager->PushFront(std::make_unique<DirectoryAssetBundle>(
fml::OpenDirectory(params.at("assetDirectory").data(), false,
fml::FilePermission::kRead)));
Expand Down
49 changes: 49 additions & 0 deletions shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2135,5 +2135,54 @@ TEST_F(ShellTest, IgnoresInvalidMetrics) {
DestroyShell(std::move(shell), std::move(task_runners));
}

TEST_F(ShellTest, OnServiceProtocolSetAssetBundlePathWorks) {
Settings settings = CreateSettingsForFixture();
std::unique_ptr<Shell> shell = CreateShell(settings);
RunConfiguration configuration =
RunConfiguration::InferFromSettings(settings);
configuration.SetEntrypoint("canAccessResourceFromAssetDir");

// Verify isolate can load a known resource with the
// default asset directory - kernel_blob.bin
fml::AutoResetWaitableEvent latch;

// Callback used to signal whether the resource was loaded successfully.
bool can_access_resource = false;
auto native_can_access_resource = [&can_access_resource,
&latch](Dart_NativeArguments args) {
Dart_Handle exception = nullptr;
can_access_resource =
tonic::DartConverter<bool>::FromArguments(args, 0, exception);
latch.Signal();
};
AddNativeCallback("NotifyCanAccessResource",
CREATE_NATIVE_ENTRY(native_can_access_resource));

// Callback used to delay the asset load until after the service
// protocol method has finished.
auto native_notify_set_asset_bundle_path =
[&shell](Dart_NativeArguments args) {
// Update the asset directory to a bonus path.
ServiceProtocol::Handler::ServiceProtocolMap params;
params["assetDirectory"] = "assetDirectory";
rapidjson::Document document;
OnServiceProtocol(shell.get(), ServiceProtocolEnum::kSetAssetBundlePath,
shell->GetTaskRunners().GetUITaskRunner(), params,
&document);
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
document.Accept(writer);
};
AddNativeCallback("NotifySetAssetBundlePath",
CREATE_NATIVE_ENTRY(native_notify_set_asset_bundle_path));

RunEngine(shell.get(), std::move(configuration));

latch.Wait();
ASSERT_TRUE(can_access_resource);

DestroyShell(std::move(shell));
}

} // namespace testing
} // namespace flutter