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);
},
);
}
14 changes: 14 additions & 0 deletions shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1404,6 +1404,7 @@ bool Shell::OnServiceProtocolRunInView(
configuration.AddAssetResolver(
Copy link
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)));
configuration.AddAssetResolver(RestoreOriginalAssetResolver());

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

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

asset_manager->PushFront(RestoreOriginalAssetResolver());
asset_manager->PushFront(std::make_unique<DirectoryAssetBundle>(
fml::OpenDirectory(params.at("assetDirectory").data(), false,
fml::FilePermission::kRead)));
Expand Down Expand Up @@ -1622,4 +1624,16 @@ void Shell::OnDisplayUpdates(DisplayUpdateType update_type,
display_manager_->HandleDisplayUpdates(update_type, displays);
}

// 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.
std::unique_ptr<DirectoryAssetBundle> Shell::RestoreOriginalAssetResolver() {
if (fml::UniqueFD::traits_type::IsValid(settings_.assets_dir)) {
return std::make_unique<DirectoryAssetBundle>(
fml::Duplicate(settings_.assets_dir));
}
return std::make_unique<DirectoryAssetBundle>(fml::OpenDirectory(
settings_.assets_path.c_str(), false, fml::FilePermission::kRead));
};

} // namespace flutter
5 changes: 5 additions & 0 deletions shell/common/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <string_view>
#include <unordered_map>

#include "flutter/assets/directory_asset_bundle.h"
#include "flutter/common/settings.h"
#include "flutter/common/task_runners.h"
#include "flutter/flow/surface.h"
Expand Down Expand Up @@ -612,6 +613,10 @@ class Shell final : public PlatformView::Delegate,
const ServiceProtocol::Handler::ServiceProtocolMap& params,
rapidjson::Document* response);

// Creates an asset bundle from the original settings asset path or
// directory.
std::unique_ptr<DirectoryAssetBundle> RestoreOriginalAssetResolver();

// For accessing the Shell via the raster thread, necessary for various
// rasterizer callbacks.
std::unique_ptr<fml::TaskRunnerAffineWeakPtrFactory<Shell>> weak_factory_gpu_;
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