Skip to content

Commit

Permalink
Add plumbing for command line arguments on Windows (#22094)
Browse files Browse the repository at this point in the history
  • Loading branch information
George Wright authored Oct 29, 2020
1 parent 632354d commit 62d50af
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 0 deletions.
13 changes: 13 additions & 0 deletions shell/platform/windows/client_wrapper/flutter_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ FlutterEngine::FlutterEngine(const DartProject& project) {
c_engine_properties.icu_data_path = project.icu_data_path().c_str();
c_engine_properties.aot_library_path = project.aot_library_path().c_str();

const std::vector<std::string>& entrypoint_args =
project.dart_entrypoint_arguments();
std::vector<const char*> entrypoint_argv;
std::transform(
entrypoint_args.begin(), entrypoint_args.end(),
std::back_inserter(entrypoint_argv),
[](const std::string& arg) -> const char* { return arg.c_str(); });

c_engine_properties.dart_entrypoint_argc =
static_cast<int>(entrypoint_argv.size());
c_engine_properties.dart_entrypoint_argv =
entrypoint_argv.size() > 0 ? entrypoint_argv.data() : nullptr;

engine_ = FlutterDesktopEngineCreate(c_engine_properties);

auto core_messenger = FlutterDesktopEngineGetMessenger(engine_);
Expand Down
30 changes: 30 additions & 0 deletions shell/platform/windows/client_wrapper/flutter_engine_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ class TestFlutterWindowsApi : public testing::StubFlutterWindowsApi {
FlutterDesktopEngineRef EngineCreate(
const FlutterDesktopEngineProperties& engine_properties) {
create_called_ = true;

// dart_entrypoint_argv is only guaranteed to exist until this method
// returns, so copy it here for unit test validation
dart_entrypoint_arguments_.clear();
for (int i = 0; i < engine_properties.dart_entrypoint_argc; i++) {
dart_entrypoint_arguments_.push_back(
std::string(engine_properties.dart_entrypoint_argv[i]));
}
return reinterpret_cast<FlutterDesktopEngineRef>(1);
}

Expand Down Expand Up @@ -49,11 +57,16 @@ class TestFlutterWindowsApi : public testing::StubFlutterWindowsApi {

bool reload_fonts_called() { return reload_fonts_called_; }

const std::vector<std::string>& dart_entrypoint_arguments() {
return dart_entrypoint_arguments_;
}

private:
bool create_called_ = false;
bool run_called_ = false;
bool destroy_called_ = false;
bool reload_fonts_called_ = false;
std::vector<std::string> dart_entrypoint_arguments_;
};

} // namespace
Expand Down Expand Up @@ -121,4 +134,21 @@ TEST(FlutterEngineTest, GetMessenger) {
EXPECT_NE(engine.messenger(), nullptr);
}

TEST(FlutterEngineTest, DartEntrypointArgs) {
testing::ScopedStubFlutterWindowsApi scoped_api_stub(
std::make_unique<TestFlutterWindowsApi>());
auto test_api = static_cast<TestFlutterWindowsApi*>(scoped_api_stub.stub());

DartProject project(L"data");
std::vector<std::string> arguments = {"one", "two"};
project.set_dart_entrypoint_arguments(arguments);

FlutterEngine engine(project);
const std::vector<std::string>& arguments_ref =
test_api->dart_entrypoint_arguments();
ASSERT_EQ(2, arguments_ref.size());
EXPECT_TRUE(arguments[0] == arguments_ref[0]);
EXPECT_TRUE(arguments[1] == arguments_ref[1]);
}

} // namespace flutter
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ class DartProject {

~DartProject() = default;

// Sets the command line arguments that should be passed to the Dart
// entrypoint.
void set_dart_entrypoint_arguments(std::vector<std::string> arguments) {
dart_entrypoint_arguments_ = std::move(arguments);
}

// Returns any command line arguments that should be passed to the Dart
// entrypoint.
const std::vector<std::string>& dart_entrypoint_arguments() const {
return dart_entrypoint_arguments_;
}

private:
// Accessors for internals are private, so that they can be changed if more
// flexible options for project structures are needed later without it
Expand All @@ -49,6 +61,8 @@ class DartProject {
// The path to the AOT library. This will always return a path, but non-AOT
// builds will not be expected to actually have a library at that path.
std::wstring aot_library_path_;
// The list of arguments to pass through to the Dart entrypoint.
std::vector<std::string> dart_entrypoint_arguments_;
};

} // namespace flutter
Expand Down
5 changes: 5 additions & 0 deletions shell/platform/windows/flutter_project_bundle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ FlutterProjectBundle::FlutterProjectBundle(
aot_library_path_ = std::filesystem::path(properties.aot_library_path);
}

for (int i = 0; i < properties.dart_entrypoint_argc; i++) {
dart_entrypoint_arguments_.push_back(
std::string(properties.dart_entrypoint_argv[i]));
}

// Resolve any relative paths.
if (assets_path_.is_relative() || icu_path_.is_relative() ||
(!aot_library_path_.empty() && aot_library_path_.is_relative())) {
Expand Down
9 changes: 9 additions & 0 deletions shell/platform/windows/flutter_project_bundle.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,21 @@ class FlutterProjectBundle {
// Logs and returns nullptr on failure.
UniqueAotDataPtr LoadAotData();

// Returns the command line arguments to be passed through to the Dart
// entrypoint.
const std::vector<std::string>& dart_entrypoint_arguments() const {
return dart_entrypoint_arguments_;
}

private:
std::filesystem::path assets_path_;
std::filesystem::path icu_path_;

// Path to the AOT library file, if any.
std::filesystem::path aot_library_path_;

// Dart entrypoint arguments.
std::vector<std::string> dart_entrypoint_arguments_;
};

} // namespace flutter
Expand Down
11 changes: 11 additions & 0 deletions shell/platform/windows/flutter_windows_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,14 @@ bool FlutterWindowsEngine::RunWithEntrypoint(const char* entrypoint) {
switches.begin(), switches.end(), std::back_inserter(argv),
[](const std::string& arg) -> const char* { return arg.c_str(); });

const std::vector<std::string>& entrypoint_args =
project_->dart_entrypoint_arguments();
std::vector<const char*> entrypoint_argv;
std::transform(
entrypoint_args.begin(), entrypoint_args.end(),
std::back_inserter(entrypoint_argv),
[](const std::string& arg) -> const char* { return arg.c_str(); });

// Configure task runners.
FlutterTaskRunnerDescription platform_task_runner = {};
platform_task_runner.struct_size = sizeof(FlutterTaskRunnerDescription);
Expand All @@ -166,6 +174,9 @@ bool FlutterWindowsEngine::RunWithEntrypoint(const char* entrypoint) {
args.icu_data_path = icu_path_string.c_str();
args.command_line_argc = static_cast<int>(argv.size());
args.command_line_argv = argv.size() > 0 ? argv.data() : nullptr;
args.dart_entrypoint_argc = static_cast<int>(entrypoint_argv.size());
args.dart_entrypoint_argv =
entrypoint_argv.size() > 0 ? entrypoint_argv.data() : nullptr;
args.platform_message_callback =
[](const FlutterPlatformMessage* engine_message,
void* user_data) -> void {
Expand Down
7 changes: 7 additions & 0 deletions shell/platform/windows/public/flutter_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ typedef struct {
// containing the executable. This can be nullptr for a non-AOT build, as
// it will be ignored in that case.
const wchar_t* aot_library_path;

// Number of elements in the array passed in as dart_entrypoint_argv.
int dart_entrypoint_argc;

// Array of Dart entrypoint arguments. This is deep copied during the call
// to FlutterDesktopEngineCreate.
const char** dart_entrypoint_argv;
} FlutterDesktopEngineProperties;

// ========== View Controller ==========
Expand Down

0 comments on commit 62d50af

Please sign in to comment.