Skip to content

Commit 33a21d1

Browse files
Add DartProject for Windows embedding API (flutter#17210)
This is a step toward aligning the API with macOS, and will make it easier to add the precompiled library later for release mode (since it can just be added to the project directory, without any code changes required for wrapper clients). At the C API, uses a struct instead of individual arguments, mirroring a change that was already made on the Linux side to make the C API cleaner. Functional changes in addition to the restructuring: adds relative path support, as was recently added for GLFW Uses wstring, rather than string, for paths; the conversion to UTF-8 is actually a potential problem on Windows, so pushing it into the embedding allows us the possibility of removing it later (if we can figure out a good solution at the embedder.h layer) without API breakage. The old APIs used by the standard runner are left in place for now to avoid breaking the template on an engine roll. Once the framework template has been updated, the old API paths will be removed.
1 parent 8a8b298 commit 33a21d1

File tree

12 files changed

+281
-100
lines changed

12 files changed

+281
-100
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,9 +1145,11 @@ FILE: ../../../flutter/shell/platform/glfw/text_input_plugin.cc
11451145
FILE: ../../../flutter/shell/platform/glfw/text_input_plugin.h
11461146
FILE: ../../../flutter/shell/platform/windows/angle_surface_manager.cc
11471147
FILE: ../../../flutter/shell/platform/windows/angle_surface_manager.h
1148+
FILE: ../../../flutter/shell/platform/windows/client_wrapper/dart_project_unittests.cc
11481149
FILE: ../../../flutter/shell/platform/windows/client_wrapper/flutter_view_controller.cc
11491150
FILE: ../../../flutter/shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc
11501151
FILE: ../../../flutter/shell/platform/windows/client_wrapper/flutter_view_unittests.cc
1152+
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/dart_project.h
11511153
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h
11521154
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h
11531155
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/plugin_registrar_windows.h

shell/platform/darwin/macos/framework/Headers/FlutterDartProject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ FLUTTER_EXPORT
3636
* guarantee, and are subject to change without notice.
3737
*
3838
* Note: This property WILL BE REMOVED in the future. If you use this property, please see
39-
* https://github.com/flutter/flutter/issue/38569.
39+
* https://github.com/flutter/flutter/issues/38569.
4040
*/
4141
@property(nullable) NSArray<NSString*>* engineSwitches;
4242

shell/platform/windows/client_wrapper/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import("//flutter/shell/platform/common/cpp/client_wrapper/publish.gni")
66
import("//flutter/testing/testing.gni")
77

88
_wrapper_includes = [
9+
"include/flutter/dart_project.h",
910
"include/flutter/flutter_view_controller.h",
1011
"include/flutter/flutter_view.h",
1112
"include/flutter/plugin_registrar_windows.h",
@@ -69,6 +70,7 @@ executable("client_wrapper_windows_unittests") {
6970
testonly = true
7071

7172
sources = [
73+
"dart_project_unittests.cc",
7274
"flutter_view_controller_unittests.cc",
7375
"flutter_view_unittests.cc",
7476
"plugin_registrar_windows_unittests.cc",
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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 <memory>
6+
#include <string>
7+
8+
#include "flutter/shell/platform/windows/client_wrapper/include/flutter/dart_project.h"
9+
#include "gtest/gtest.h"
10+
11+
namespace flutter {
12+
13+
class DartProjectTest : public ::testing::Test {
14+
protected:
15+
// Wrapper for accessing private icu_data_path.
16+
std::wstring GetProjectIcuDataPath(const DartProject& project) {
17+
return project.icu_data_path();
18+
}
19+
20+
// Wrapper for accessing private assets_path.
21+
std::wstring GetProjectAssetsPath(const DartProject& project) {
22+
return project.assets_path();
23+
}
24+
25+
// Wrapper for accessing private engine_switches.
26+
std::vector<std::string> GetProjectEngineSwitches(
27+
const DartProject& project) {
28+
return project.engine_switches();
29+
}
30+
};
31+
32+
TEST_F(DartProjectTest, StandardProjectFormat) {
33+
DartProject project(L"test");
34+
EXPECT_EQ(GetProjectIcuDataPath(project), L"test\\icudtl.dat");
35+
EXPECT_EQ(GetProjectAssetsPath(project), L"test\\flutter_assets");
36+
}
37+
38+
TEST_F(DartProjectTest, Switches) {
39+
DartProject project(L"test");
40+
std::vector<std::string> switches = {"--foo", "--bar"};
41+
project.SetEngineSwitches(switches);
42+
EXPECT_EQ(GetProjectEngineSwitches(project).size(), 2);
43+
EXPECT_EQ(GetProjectEngineSwitches(project)[0], "--foo");
44+
}
45+
46+
} // namespace flutter

shell/platform/windows/client_wrapper/flutter_view_controller.cc

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,35 @@
99

1010
namespace flutter {
1111

12+
FlutterViewController::FlutterViewController(int width,
13+
int height,
14+
const DartProject& project) {
15+
std::vector<const char*> switches;
16+
std::transform(
17+
project.engine_switches().begin(), project.engine_switches().end(),
18+
std::back_inserter(switches),
19+
[](const std::string& arg) -> const char* { return arg.c_str(); });
20+
size_t switch_count = switches.size();
21+
22+
FlutterDesktopEngineProperties properties = {};
23+
properties.assets_path = project.assets_path().c_str();
24+
properties.icu_data_path = project.icu_data_path().c_str();
25+
properties.switches = switch_count > 0 ? switches.data() : nullptr;
26+
properties.switches_count = switch_count;
27+
controller_ = FlutterDesktopCreateViewController(width, height, properties);
28+
if (!controller_) {
29+
std::cerr << "Failed to create view controller." << std::endl;
30+
return;
31+
}
32+
view_ = std::make_unique<FlutterView>(FlutterDesktopGetView(controller_));
33+
}
34+
1235
FlutterViewController::FlutterViewController(
1336
const std::string& icu_data_path,
1437
int width,
1538
int height,
1639
const std::string& assets_path,
17-
const std::vector<std::string>& arguments)
18-
: icu_data_path_(icu_data_path) {
40+
const std::vector<std::string>& arguments) {
1941
if (controller_) {
2042
std::cerr << "Only one Flutter view can exist at a time." << std::endl;
2143
}
@@ -26,8 +48,8 @@ FlutterViewController::FlutterViewController(
2648
[](const std::string& arg) -> const char* { return arg.c_str(); });
2749
size_t arg_count = engine_arguments.size();
2850

29-
controller_ = FlutterDesktopCreateViewController(
30-
width, height, assets_path.c_str(), icu_data_path_.c_str(),
51+
controller_ = FlutterDesktopCreateViewControllerLegacy(
52+
width, height, assets_path.c_str(), icu_data_path.c_str(),
3153
arg_count > 0 ? &engine_arguments[0] : nullptr, arg_count);
3254
if (!controller_) {
3355
std::cerr << "Failed to create view controller." << std::endl;

shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,16 @@ namespace {
1616
// Stub implementation to validate calls to the API.
1717
class TestWindowsApi : public testing::StubFlutterWindowsApi {
1818
FlutterDesktopViewControllerRef CreateViewController(
19-
int initial_width,
20-
int initial_height,
21-
const char* assets_path,
22-
const char* icu_data_path,
23-
const char** arguments,
24-
size_t argument_count) override {
19+
int width,
20+
int height,
21+
const FlutterDesktopEngineProperties& engine_properties) override {
2522
return reinterpret_cast<FlutterDesktopViewControllerRef>(1);
2623
}
2724
};
2825

2926
} // namespace
3027

31-
TEST(FlutterViewControllerTest, CreateDestroy) {
28+
TEST(FlutterViewControllerTest, CreateDestroyLegacy) {
3229
testing::ScopedStubFlutterWindowsApi scoped_api_stub(
3330
std::make_unique<TestWindowsApi>());
3431
auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
@@ -38,13 +35,20 @@ TEST(FlutterViewControllerTest, CreateDestroy) {
3835
}
3936
}
4037

38+
TEST(FlutterViewControllerTest, CreateDestroy) {
39+
DartProject project(L"data");
40+
testing::ScopedStubFlutterWindowsApi scoped_api_stub(
41+
std::make_unique<TestWindowsApi>());
42+
auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
43+
{ FlutterViewController controller(100, 100, project); }
44+
}
45+
4146
TEST(FlutterViewControllerTest, GetView) {
42-
std::string icu_data_path = "fake_path_to_icu";
47+
DartProject project(L"data");
4348
testing::ScopedStubFlutterWindowsApi scoped_api_stub(
4449
std::make_unique<TestWindowsApi>());
4550
auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
46-
FlutterViewController controller("", 100, 100, "",
47-
std::vector<std::string>{});
51+
FlutterViewController controller(100, 100, project);
4852
EXPECT_NE(controller.view(), nullptr);
4953
}
5054

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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+
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_DART_PROJECT_H_
6+
#define FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_DART_PROJECT_H_
7+
8+
#include <string>
9+
#include <vector>
10+
11+
namespace flutter {
12+
13+
// A set of Flutter and Dart assets used to initialize a Flutter engine.
14+
class DartProject {
15+
public:
16+
// Creates a DartProject from a directory path. The directory should contain
17+
// the following top-level items:
18+
// - icudtl.dat (provided as a resource by the Flutter tool)
19+
// - flutter_assets (as built by the Flutter tool)
20+
//
21+
// The path can either be absolute, or relative to the directory containing
22+
// the running executable.
23+
explicit DartProject(const std::wstring& path) {
24+
assets_path_ = path + L"\\flutter_assets";
25+
icu_data_path_ = path + L"\\icudtl.dat";
26+
}
27+
28+
~DartProject() = default;
29+
30+
// Switches to pass to the Flutter engine. See
31+
// https://github.com/flutter/engine/blob/master/shell/common/switches.h
32+
// for details. Not all switches will apply to embedding mode. Switches have
33+
// not stability guarantee, and are subject to change without notice.
34+
//
35+
// Note: This WILL BE REMOVED in the future. If you call this, please see
36+
// https://github.com/flutter/flutter/issues/38569.
37+
void SetEngineSwitches(const std::vector<std::string>& switches) {
38+
engine_switches_ = switches;
39+
}
40+
41+
private:
42+
// Accessors for internals are private, so that they can be changed if more
43+
// flexible options for project structures are needed later without it
44+
// being a breaking change. Provide access to internal classes that need
45+
// them.
46+
friend class FlutterViewController;
47+
friend class DartProjectTest;
48+
49+
const std::wstring& assets_path() const { return assets_path_; }
50+
const std::wstring& icu_data_path() const { return icu_data_path_; }
51+
const std::vector<std::string>& engine_switches() const {
52+
return engine_switches_;
53+
}
54+
55+
// The path to the assets directory.
56+
std::wstring assets_path_;
57+
// The path to the ICU data.
58+
std::wstring icu_data_path_;
59+
// Switches to pass to the engine.
60+
std::vector<std::string> engine_switches_;
61+
};
62+
63+
} // namespace flutter
64+
65+
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_DART_PROJECT_H_

shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <string>
1212
#include <vector>
1313

14+
#include "dart_project.h"
1415
#include "flutter_view.h"
1516
#include "plugin_registrar.h"
1617
#include "plugin_registry.h"
@@ -24,20 +25,15 @@ namespace flutter {
2425
// methods in the C API directly, as this class will do that internally.
2526
class FlutterViewController : public PluginRegistry {
2627
public:
27-
// There must be only one instance of this class in an application at any
28-
// given time, as Flutter does not support multiple engines in one process,
29-
// or multiple views in one engine.
30-
3128
// Creates a FlutterView that can be parented into a Windows View hierarchy
3229
// either using HWNDs or in the future into a CoreWindow, or using compositor.
33-
34-
// The |assets_path| is the path to the flutter_assets folder for the Flutter
35-
// application to be run. |icu_data_path| is the path to the icudtl.dat file
36-
// for the version of Flutter you are using.
3730
//
38-
// The |arguments| are passed to the Flutter engine. See:
39-
// https://github.com/flutter/engine/blob/master/shell/common/switches.h for
40-
// for details. Not all arguments will apply to desktop.
31+
// |dart_project| will be used to configure the engine backing this view.
32+
explicit FlutterViewController(int width,
33+
int height,
34+
const DartProject& project);
35+
36+
// DEPRECATED. Will be removed soon; use the version above.
4137
explicit FlutterViewController(const std::string& icu_data_path,
4238
int width,
4339
int height,
@@ -65,10 +61,6 @@ class FlutterViewController : public PluginRegistry {
6561
const std::string& plugin_name) override;
6662

6763
private:
68-
// The path to the ICU data file. Set at creation time since it is the same
69-
// for any view created.
70-
std::string icu_data_path_;
71-
7264
// Handle for interacting with the C API's view controller, if any.
7365
FlutterDesktopViewControllerRef controller_ = nullptr;
7466

shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,29 @@ ScopedStubFlutterWindowsApi::~ScopedStubFlutterWindowsApi() {
3636
// Forwarding dummy implementations of the C API.
3737

3838
FlutterDesktopViewControllerRef FlutterDesktopCreateViewController(
39+
int width,
40+
int height,
41+
const FlutterDesktopEngineProperties& engine_properties) {
42+
if (s_stub_implementation) {
43+
return s_stub_implementation->CreateViewController(width, height,
44+
engine_properties);
45+
}
46+
return nullptr;
47+
}
48+
49+
FlutterDesktopViewControllerRef FlutterDesktopCreateViewControllerLegacy(
3950
int initial_width,
4051
int initial_height,
4152
const char* assets_path,
4253
const char* icu_data_path,
4354
const char** arguments,
4455
size_t argument_count) {
4556
if (s_stub_implementation) {
57+
// This stub will be removed shortly, and the current tests don't need the
58+
// arguments, so there's no need to translate them to engine_properties.
59+
FlutterDesktopEngineProperties engine_properties;
4660
return s_stub_implementation->CreateViewController(
47-
initial_width, initial_height, assets_path, icu_data_path, arguments,
48-
argument_count);
61+
initial_width, initial_height, engine_properties);
4962
}
5063
return nullptr;
5164
}
@@ -78,13 +91,10 @@ HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef controller) {
7891
return reinterpret_cast<HWND>(-1);
7992
}
8093

81-
FlutterDesktopEngineRef FlutterDesktopRunEngine(const char* assets_path,
82-
const char* icu_data_path,
83-
const char** arguments,
84-
size_t argument_count) {
94+
FlutterDesktopEngineRef FlutterDesktopRunEngine(
95+
const FlutterDesktopEngineProperties& engine_properties) {
8596
if (s_stub_implementation) {
86-
return s_stub_implementation->RunEngine(assets_path, icu_data_path,
87-
arguments, argument_count);
97+
return s_stub_implementation->RunEngine(engine_properties);
8898
}
8999
return nullptr;
90100
}

shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.h

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,11 @@ class StubFlutterWindowsApi {
2929

3030
virtual ~StubFlutterWindowsApi() {}
3131

32-
// Called for FlutterDesktopCreateView.
32+
// Called for FlutterDesktopCreateViewController.
3333
virtual FlutterDesktopViewControllerRef CreateViewController(
34-
int initial_width,
35-
int initial_height,
36-
const char* assets_path,
37-
const char* icu_data_path,
38-
const char** arguments,
39-
size_t argument_count) {
34+
int width,
35+
int height,
36+
const FlutterDesktopEngineProperties& engine_properties) {
4037
return nullptr;
4138
}
4239

@@ -50,10 +47,8 @@ class StubFlutterWindowsApi {
5047
virtual HWND ViewGetHWND() { return reinterpret_cast<HWND>(1); }
5148

5249
// Called for FlutterDesktopRunEngine.
53-
virtual FlutterDesktopEngineRef RunEngine(const char* assets_path,
54-
const char* icu_data_path,
55-
const char** arguments,
56-
size_t argument_count) {
50+
virtual FlutterDesktopEngineRef RunEngine(
51+
const FlutterDesktopEngineProperties& engine_properties) {
5752
return nullptr;
5853
}
5954

0 commit comments

Comments
 (0)