Merge branch 'main' into zanderso-patch-4
diff --git a/.ci.yaml b/.ci.yaml
index 44feda6..424f41e 100644
--- a/.ci.yaml
+++ b/.ci.yaml
@@ -183,6 +183,7 @@
{"download_emsdk": true}
add_recipes_cq: "true"
build_host: "true"
+ cores: "32"
timeout: 60
- name: Linux Unopt
@@ -304,6 +305,7 @@
{"dependency": "firefox", "version": "version:106.0"},
{"dependency": "goldctl", "version": "git_revision:3a77d0b12c697a840ca0c7705208e8622dc94603"}
]
+ no_goma: "true"
timeout: 60
runIf:
- DEPS
@@ -321,6 +323,7 @@
- master
properties:
add_recipes_cq: "true"
+ cores: "32"
gclient_variables: >-
{"download_emsdk": true}
dependencies: >-
@@ -329,6 +332,7 @@
{"dependency": "curl", "version": "version:7.64.0"}
]
framework: "true"
+ no_goma: "true"
shard: web_tests
subshards: >-
["0", "1", "2", "3", "4", "5", "6", "7_last"]
@@ -448,6 +452,7 @@
[
{"dependency": "goldctl", "version": "git_revision:3a77d0b12c697a840ca0c7705208e8622dc94603"}
]
+ no_goma: "true"
timeout: 60
runIf:
- DEPS
@@ -525,6 +530,7 @@
[
{"dependency": "chrome_and_driver", "version": "version:111.0"}
]
+ no_goma: "true"
timeout: 60
runIf:
- DEPS
diff --git a/DEPS b/DEPS
index 6dcbfcc..70ca325 100644
--- a/DEPS
+++ b/DEPS
@@ -18,7 +18,7 @@
'llvm_git': 'https://llvm.googlesource.com',
# OCMock is for testing only so there is no google clone
'ocmock_git': 'https://github.com/erikdoe/ocmock.git',
- 'skia_revision': '529fb1efd882ab11e05bb97b81eaeb97f74e9d26',
+ 'skia_revision': '1c36c5c38ef4742a4e359484ab15a670c06902d9',
# WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY
# See `lib/web_ui/README.md` for how to roll CanvasKit to a new version.
@@ -48,7 +48,7 @@
# Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS
# You can use //tools/dart/create_updated_flutter_deps.py to produce
# updated revision list of existing dependencies.
- 'dart_revision': '7240b35cc401ad8cf3107e83c04b055ef3cc895d',
+ 'dart_revision': '689440e4d16326ed59fe8d7185a81ce1402a4430',
# WARNING: DO NOT EDIT MANUALLY
# The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py
@@ -61,14 +61,14 @@
'dart_devtools_rev': 'bf15e7348d53dc83531d503be94e0c035b604984',
'dart_libprotobuf_rev': '24487dd1045c7f3d64a21f38a3f0c06cc4cf2edb',
'dart_perfetto_rev': 'b8da07095979310818f0efde2ef3c69ea70d62c5',
- 'dart_protobuf_gn_rev': '5f87ef9990fc4f4ffd76b3f5b0138562178db8bc',
+ 'dart_protobuf_gn_rev': 'f872f05cb0378eef9a7a2609076929f0f35b4141',
'dart_protobuf_rev': '75bc380a6e9601565606a13dee16c5ab2bf5019c',
- 'dart_pub_rev': '048e3ad2b5e1b4ebe6883addbc95722be6904a7b',
+ 'dart_pub_rev': 'd69493e5163553bde53c0889b7479dee02f550bf',
'dart_root_certificates_rev': '692f6d6488af68e0121317a9c2c9eb393eb0ee50',
'dart_watcher_rev': '5968409e1d73e21e75fc22a6481d5efaef7f3558',
- 'dart_webdev_rev': 'c007560346a53728920362e5ccaa7eaae85301a7',
+ 'dart_webdev_rev': 'cfe97534b33d37c7e0bbac2a3576085f74f2eaa3',
'dart_webkit_inspection_protocol_rev': '8401098ace995e4dcd9855a2741c2dacccaa780b',
- 'dart_yaml_edit_rev': '998eea2e4fc474a5e95cfea117e4233d35c3069b',
+ 'dart_yaml_edit_rev': '6abc42a74b76700ad02fa1c1ebd94951b62626b9',
'dart_zlib_rev': '27c2f474b71d0d20764f86f60ef8b00da1a16cda',
'ocmock_rev': 'c4ec0e3a7a9f56cfdbd0aa01f4f97bb4b75c5ef8', # v3.7.1
@@ -239,7 +239,7 @@
]
deps = {
- 'src': 'https://github.com/flutter/buildroot.git' + '@' + '93f7f85422a8604bdc44ef76c3f105ead65e8c1c',
+ 'src': 'https://github.com/flutter/buildroot.git' + '@' + 'a357fb6285af70772dbca8b164cd61af16cc8af1',
# Fuchsia compatibility
#
@@ -449,13 +449,13 @@
Var('dart_git') + '/term_glyph.git@d275a8f7482b6a5e4f15d0da6feb66c24f52eb94',
'src/third_party/dart/third_party/pkg/test':
- Var('dart_git') + '/test.git@92da93a83615f2bc0483aa00e6a85c4f89d616e4',
+ Var('dart_git') + '/test.git@3ba78f15538399073d0b5aba4ec19b1378af1625',
'src/third_party/dart/third_party/pkg/test_reflective_loader':
Var('dart_git') + '/test_reflective_loader.git@c4c2d5c3f94a96f3fc79e9e28944fba391bc544c',
'src/third_party/dart/third_party/pkg/tools':
- Var('dart_git') + '/tools.git@a1c35060d920122ecbecb8c5a389b58ccbceb125',
+ Var('dart_git') + '/tools.git@bed358ea8ca10551c710282be96cf6e95620fb24',
'src/third_party/dart/third_party/pkg/typed_data':
Var('dart_git') + '/typed_data.git@f858046fb420cf644e7d8cb86b7893f2830d8a6c',
@@ -476,7 +476,7 @@
Var('dart_git') + '/external/github.com/google/webkit_inspection_protocol.dart.git' + '@' + Var('dart_webkit_inspection_protocol_rev'),
'src/third_party/dart/third_party/pkg/yaml':
- Var('dart_git') + '/yaml.git@a6d8781744d34c391368664b4c1e174f0433bbb6',
+ Var('dart_git') + '/yaml.git@0f80b12978f066b3547632dec4a273649138fae4',
'src/third_party/dart/third_party/pkg/yaml_edit':
Var('dart_git') + '/yaml_edit.git' + '@' + Var('dart_yaml_edit_rev'),
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 40329d6..1eeb5c8 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -95,6 +95,7 @@
- flutter_style_todos
- hash_and_equals
- implementation_imports
+ - invalid_case_patterns
- iterable_contains_unrelated_type
# - join_return_with_assignment # not required by flutter style
- leading_newlines_in_multiline_strings
diff --git a/ci/builders/linux_android_aot_engine.json b/ci/builders/linux_android_aot_engine.json
index d28dfc1..6523c0b 100644
--- a/ci/builders/linux_android_aot_engine.json
+++ b/ci/builders/linux_android_aot_engine.json
@@ -90,6 +90,7 @@
"out/android_release_arm64/zip_archives/android-arm64-release/artifacts.zip",
"out/android_release_arm64/zip_archives/android-arm64-release/linux-x64.zip",
"out/android_release_arm64/zip_archives/android-arm64-release/symbols.zip",
+ "out/android_release_arm64/zip_archives/android-arm64-release/analyze-snapshot-linux-x64.zip",
"out/android_release_arm64/zip_archives/download.flutter.io"
]
}
@@ -114,7 +115,8 @@
"targets": [
"default",
"clang_x64/gen_snapshot",
- "flutter/shell/platform/android:abi_jars"
+ "flutter/shell/platform/android:abi_jars",
+ "flutter/shell/platform/android:analyze_snapshot"
]
},
"tests": []
@@ -128,6 +130,7 @@
"include_paths": [
"out/android_profile_arm64/zip_archives/android-arm64-profile/artifacts.zip",
"out/android_profile_arm64/zip_archives/android-arm64-profile/linux-x64.zip",
+ "out/android_profile_arm64/zip_archives/android-arm64-profile/analyze-snapshot-linux-x64.zip",
"out/android_profile_arm64/zip_archives/download.flutter.io"
]
}
@@ -152,7 +155,8 @@
"targets": [
"default",
"clang_x64/gen_snapshot",
- "flutter/shell/platform/android:abi_jars"
+ "flutter/shell/platform/android:abi_jars",
+ "flutter/shell/platform/android:analyze_snapshot"
]
},
"tests": []
@@ -167,6 +171,7 @@
"out/android_profile_x64/zip_archives/android-x64-profile/artifacts.zip",
"out/android_profile_x64/zip_archives/android-x64-profile/linux-x64.zip",
"out/android_profile_x64/zip_archives/android-x64-profile/symbols.zip",
+ "out/android_profile_x64/zip_archives/android-x64-profile/analyze-snapshot-linux-x64.zip",
"out/android_profile_x64/zip_archives/download.flutter.io"
]
}
@@ -191,7 +196,8 @@
"targets": [
"default",
"clang_x64/gen_snapshot",
- "flutter/shell/platform/android:abi_jars"
+ "flutter/shell/platform/android:abi_jars",
+ "flutter/shell/platform/android:analyze_snapshot"
]
},
"tests": []
@@ -206,6 +212,7 @@
"out/android_release_x64/zip_archives/android-x64-release/artifacts.zip",
"out/android_release_x64/zip_archives/android-x64-release/linux-x64.zip",
"out/android_release_x64/zip_archives/android-x64-release/symbols.zip",
+ "out/android_release_x64/zip_archives/android-x64-release/analyze-snapshot-linux-x64.zip",
"out/android_release_x64/zip_archives/download.flutter.io"
]
}
@@ -230,7 +237,8 @@
"targets": [
"default",
"clang_x64/gen_snapshot",
- "flutter/shell/platform/android:abi_jars"
+ "flutter/shell/platform/android:abi_jars",
+ "flutter/shell/platform/android:analyze_snapshot"
]
},
"tests": []
diff --git a/ci/builders/linux_web_engine.json b/ci/builders/linux_web_engine.json
index e1b1c13..af80baa 100644
--- a/ci/builders/linux_web_engine.json
+++ b/ci/builders/linux_web_engine.json
@@ -8,7 +8,8 @@
"type": "gcs",
"include_paths": [
"out/wasm_release/zip_archives/flutter-web-sdk.zip"
- ]
+ ],
+ "realm": "production"
}
],
"drone_dimensions": [
diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files
index 11d1a1a..2d0dbbe 100644
--- a/ci/licenses_golden/excluded_files
+++ b/ci/licenses_golden/excluded_files
@@ -275,7 +275,6 @@
../../../flutter/shell/platform/fuchsia/flutter/accessibility_bridge_unittest.cc
../../../flutter/shell/platform/fuchsia/flutter/build/asset_package.py
../../../flutter/shell/platform/fuchsia/flutter/build/gen_debug_wrapper_main.py
-../../../flutter/shell/platform/fuchsia/flutter/component_v1_unittest.cc
../../../flutter/shell/platform/fuchsia/flutter/component_v2_unittest.cc
../../../flutter/shell/platform/fuchsia/flutter/focus_delegate_unittests.cc
../../../flutter/shell/platform/fuchsia/flutter/fuchsia_intl_unittest.cc
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index 5ab7c54..e0abd2e 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -2744,8 +2744,6 @@
ORIGIN: ../../../flutter/shell/platform/fuchsia/dart_runner/vmservice/empty.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/fuchsia/flutter/accessibility_bridge.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/fuchsia/flutter/accessibility_bridge.h + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/shell/platform/fuchsia/flutter/component_v1.cc + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/shell/platform/fuchsia/flutter/component_v1.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/fuchsia/flutter/component_v2.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/fuchsia/flutter/component_v2.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/fuchsia/flutter/engine.cc + ../../../flutter/LICENSE
@@ -5295,8 +5293,6 @@
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/vmservice/empty.dart
FILE: ../../../flutter/shell/platform/fuchsia/flutter/accessibility_bridge.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/accessibility_bridge.h
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/component_v1.cc
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/component_v1.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/component_v2.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/component_v2.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/engine.cc
@@ -5329,19 +5325,11 @@
FILE: ../../../flutter/shell/platform/fuchsia/flutter/keyboard.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/logging.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/main.cc
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/aot_product_runtime
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/aot_runtime
FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/common.shard.cml
FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/flutter_aot_product_runner.cml
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/flutter_aot_product_runner.cmx
FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/flutter_aot_runner.cml
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/flutter_aot_runner.cmx
FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/flutter_jit_product_runner.cml
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/flutter_jit_product_runner.cmx
FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/flutter_jit_runner.cml
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/flutter_jit_runner.cmx
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/jit_product_runtime
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/jit_runtime
FILE: ../../../flutter/shell/platform/fuchsia/flutter/platform_view.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/platform_view.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/pointer_delegate.cc
diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia
index e7c7512..35bdd6b 100644
--- a/ci/licenses_golden/licenses_skia
+++ b/ci/licenses_golden/licenses_skia
@@ -1,4 +1,4 @@
-Signature: 31a48d3b6608c2afe988dde9b6ed3d7a
+Signature: 0bb6840486c80db920cb2ed91500f705
====================================================================================================
LIBRARY: etc1
@@ -8416,6 +8416,8 @@
ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnCommandBuffer.h + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnGraphicsPipeline.cpp + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnGraphicsPipeline.h + ../../../third_party/skia/LICENSE
+ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnGraphiteUtils.cpp + ../../../third_party/skia/LICENSE
+ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnGraphiteUtilsPriv.h + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnQueueManager.cpp + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnQueueManager.h + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnResourceProvider.cpp + ../../../third_party/skia/LICENSE
@@ -8427,8 +8429,6 @@
ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnTexture.cpp + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnTexture.h + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnTypesPriv.cpp + ../../../third_party/skia/LICENSE
-ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnUtils.cpp + ../../../third_party/skia/LICENSE
-ORIGIN: ../../../third_party/skia/src/gpu/graphite/dawn/DawnUtilsPriv.h + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/geom/Geometry.h + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/geom/SubRunData.h + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/mtl/MtlComputePipeline.h + ../../../third_party/skia/LICENSE
@@ -8641,6 +8641,8 @@
FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnCommandBuffer.h
FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnGraphicsPipeline.cpp
FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnGraphicsPipeline.h
+FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnGraphiteUtils.cpp
+FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnGraphiteUtilsPriv.h
FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnQueueManager.cpp
FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnQueueManager.h
FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnResourceProvider.cpp
@@ -8652,8 +8654,6 @@
FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnTexture.cpp
FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnTexture.h
FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnTypesPriv.cpp
-FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnUtils.cpp
-FILE: ../../../third_party/skia/src/gpu/graphite/dawn/DawnUtilsPriv.h
FILE: ../../../third_party/skia/src/gpu/graphite/geom/Geometry.h
FILE: ../../../third_party/skia/src/gpu/graphite/geom/SubRunData.h
FILE: ../../../third_party/skia/src/gpu/graphite/mtl/MtlComputePipeline.h
@@ -8957,6 +8957,7 @@
ORIGIN: ../../../third_party/skia/fuzz/FuzzCubicQuadRoots.cpp + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/fuzz/oss_fuzz/FuzzCubicQuadRoots.cpp + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/gm/graphite_replay.cpp + ../../../third_party/skia/LICENSE
+ORIGIN: ../../../third_party/skia/include/gpu/graphite/YUVABackendTextures.h + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/include/private/base/SkCPUTypes.h + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/base/SkBezierCurves.h + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/base/SkCubics.cpp + ../../../third_party/skia/LICENSE
@@ -8976,6 +8977,7 @@
ORIGIN: ../../../third_party/skia/src/gpu/graphite/Image_YUVA_Graphite.cpp + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/Image_YUVA_Graphite.h + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/ReadWriteSwizzle.h + ../../../third_party/skia/LICENSE
+ORIGIN: ../../../third_party/skia/src/gpu/graphite/YUVABackendTextures.cpp + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/YUVATextureProxies.cpp + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/YUVATextureProxies.h + ../../../third_party/skia/LICENSE
ORIGIN: ../../../third_party/skia/src/gpu/graphite/compute/ComputeStep.cpp + ../../../third_party/skia/LICENSE
@@ -8992,6 +8994,7 @@
FILE: ../../../third_party/skia/fuzz/FuzzCubicQuadRoots.cpp
FILE: ../../../third_party/skia/fuzz/oss_fuzz/FuzzCubicQuadRoots.cpp
FILE: ../../../third_party/skia/gm/graphite_replay.cpp
+FILE: ../../../third_party/skia/include/gpu/graphite/YUVABackendTextures.h
FILE: ../../../third_party/skia/include/private/base/SkCPUTypes.h
FILE: ../../../third_party/skia/src/base/SkBezierCurves.h
FILE: ../../../third_party/skia/src/base/SkCubics.cpp
@@ -9011,6 +9014,7 @@
FILE: ../../../third_party/skia/src/gpu/graphite/Image_YUVA_Graphite.cpp
FILE: ../../../third_party/skia/src/gpu/graphite/Image_YUVA_Graphite.h
FILE: ../../../third_party/skia/src/gpu/graphite/ReadWriteSwizzle.h
+FILE: ../../../third_party/skia/src/gpu/graphite/YUVABackendTextures.cpp
FILE: ../../../third_party/skia/src/gpu/graphite/YUVATextureProxies.cpp
FILE: ../../../third_party/skia/src/gpu/graphite/YUVATextureProxies.h
FILE: ../../../third_party/skia/src/gpu/graphite/compute/ComputeStep.cpp
@@ -9057,6 +9061,45 @@
====================================================================================================
LIBRARY: skia
+ORIGIN: ../../../third_party/skia/src/core/SkFontMetricsPriv.cpp + ../../../third_party/skia/LICENSE
+ORIGIN: ../../../third_party/skia/src/core/SkFontMetricsPriv.h + ../../../third_party/skia/LICENSE
+TYPE: LicenseType.bsd
+FILE: ../../../third_party/skia/src/core/SkFontMetricsPriv.cpp
+FILE: ../../../third_party/skia/src/core/SkFontMetricsPriv.h
+----------------------------------------------------------------------------------------------------
+Copyright 2023 Google LLC.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+====================================================================================================
+
+====================================================================================================
+LIBRARY: skia
ORIGIN: ../../../third_party/skia/src/shaders/SkCoordClampShader.cpp + ../../../third_party/skia/LICENSE
TYPE: LicenseType.bsd
FILE: ../../../third_party/skia/src/shaders/SkCoordClampShader.cpp
@@ -9092,4 +9135,4 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
====================================================================================================
-Total license count: 66
+Total license count: 67
diff --git a/ci/licenses_golden/licenses_third_party b/ci/licenses_golden/licenses_third_party
index 8b25e72..a6e5009 100644
--- a/ci/licenses_golden/licenses_third_party
+++ b/ci/licenses_golden/licenses_third_party
@@ -1,4 +1,4 @@
-Signature: 479841c56f2e6285f5971d095ed2306c
+Signature: 692acb95337a57802d84427dbd848abf
====================================================================================================
LIBRARY: angle
diff --git a/display_list/display_list_builder.h b/display_list/display_list_builder.h
index 4226d6a..58e20f1 100644
--- a/display_list/display_list_builder.h
+++ b/display_list/display_list_builder.h
@@ -446,7 +446,7 @@
bool has_layer() const { return has_layer_; }
bool cannot_inherit_opacity() const { return cannot_inherit_opacity_; }
- bool has_compatible_op() const { return cannot_inherit_opacity_; }
+ bool has_compatible_op() const { return has_compatible_op_; }
bool is_group_opacity_compatible() const {
return !cannot_inherit_opacity_;
diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc
index c7b2311..9b942bb 100644
--- a/display_list/display_list_unittests.cc
+++ b/display_list/display_list_unittests.cc
@@ -2403,5 +2403,17 @@
}
}
+TEST(DisplayListTest, DrawSaveDrawCannotInheritOpacity) {
+ DisplayListBuilder builder;
+ builder.DrawCircle({10, 10}, 5, DlPaint());
+ builder.Save();
+ builder.ClipRect({0, 0, 20, 20}, DlCanvas::ClipOp::kIntersect, false);
+ builder.DrawRect({5, 5, 15, 15}, DlPaint());
+ builder.Restore();
+ auto display_list = builder.Build();
+
+ ASSERT_FALSE(display_list->can_apply_group_opacity());
+}
+
} // namespace testing
} // namespace flutter
diff --git a/fml/concurrent_message_loop.cc b/fml/concurrent_message_loop.cc
index 681b983..f553654 100644
--- a/fml/concurrent_message_loop.cc
+++ b/fml/concurrent_message_loop.cc
@@ -170,4 +170,14 @@
task();
}
+bool ConcurrentMessageLoop::RunsTasksOnCurrentThread() {
+ std::scoped_lock lock(tasks_mutex_);
+ for (const auto& worker_thread_id : worker_thread_ids_) {
+ if (worker_thread_id == std::this_thread::get_id()) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace fml
diff --git a/fml/concurrent_message_loop.h b/fml/concurrent_message_loop.h
index c043705..ab8534b 100644
--- a/fml/concurrent_message_loop.h
+++ b/fml/concurrent_message_loop.h
@@ -34,6 +34,8 @@
void PostTaskToAllWorkers(const fml::closure& task);
+ bool RunsTasksOnCurrentThread();
+
private:
friend ConcurrentTaskRunner;
diff --git a/impeller/entity/shaders/linear_gradient_ssbo_fill.frag b/impeller/entity/shaders/linear_gradient_ssbo_fill.frag
index 718e319..45e4f9c 100644
--- a/impeller/entity/shaders/linear_gradient_ssbo_fill.frag
+++ b/impeller/entity/shaders/linear_gradient_ssbo_fill.frag
@@ -21,7 +21,7 @@
vec2 end_point;
float alpha;
float tile_mode;
- float colors_length;
+ int colors_length;
}
frag_info;
diff --git a/impeller/entity/shaders/radial_gradient_ssbo_fill.frag b/impeller/entity/shaders/radial_gradient_ssbo_fill.frag
index e870d27..6a05b4b 100644
--- a/impeller/entity/shaders/radial_gradient_ssbo_fill.frag
+++ b/impeller/entity/shaders/radial_gradient_ssbo_fill.frag
@@ -21,7 +21,7 @@
float radius;
float tile_mode;
float alpha;
- float colors_length;
+ int colors_length;
}
frag_info;
diff --git a/impeller/entity/shaders/sweep_gradient_ssbo_fill.frag b/impeller/entity/shaders/sweep_gradient_ssbo_fill.frag
index 8370b3c..34bcb74 100644
--- a/impeller/entity/shaders/sweep_gradient_ssbo_fill.frag
+++ b/impeller/entity/shaders/sweep_gradient_ssbo_fill.frag
@@ -23,7 +23,7 @@
float scale;
float tile_mode;
float alpha;
- float colors_length;
+ int colors_length;
}
frag_info;
diff --git a/impeller/fixtures/stroke.comp b/impeller/fixtures/stroke.comp
index 57d9555..5a48a29 100644
--- a/impeller/fixtures/stroke.comp
+++ b/impeller/fixtures/stroke.comp
@@ -17,11 +17,15 @@
polyline;
layout(binding = 1) buffer VertexBuffer {
- uint count;
vec2 position[];
}
vertex_buffer;
+layout(binding = 2) buffer VertexBufferCount {
+ uint count;
+}
+vertex_buffer_count;
+
uniform Config {
float width;
uint cap;
@@ -41,7 +45,7 @@
return;
}
- atomicAdd(vertex_buffer.count, 4);
+ atomicAdd(vertex_buffer_count.count, 4);
vec2 offset = compute_offset(ident);
uint index = ident - 1;
diff --git a/impeller/playground/compute_playground_test.cc b/impeller/playground/compute_playground_test.cc
index 165a6f9..eda0b2c 100644
--- a/impeller/playground/compute_playground_test.cc
+++ b/impeller/playground/compute_playground_test.cc
@@ -24,6 +24,7 @@
}
SetupContext(GetParam());
+ SetupWindow();
start_time_ = fml::TimePoint::Now().ToEpochDelta();
}
diff --git a/impeller/playground/compute_playground_test.h b/impeller/playground/compute_playground_test.h
index 06c480b..af9edf7 100644
--- a/impeller/playground/compute_playground_test.h
+++ b/impeller/playground/compute_playground_test.h
@@ -11,6 +11,7 @@
#include "flutter/testing/testing.h"
#include "impeller/geometry/scalar.h"
#include "impeller/playground/playground.h"
+#include "impeller/renderer/device_buffer.h"
namespace impeller {
@@ -36,6 +37,18 @@
// |Playground|
std::string GetWindowTitle() const override;
+ template <typename T>
+ std::shared_ptr<DeviceBuffer> CreateHostVisibleDeviceBuffer(
+ std::shared_ptr<Context> context,
+ const std::string& label) {
+ DeviceBufferDescriptor desc;
+ desc.storage_mode = StorageMode::kHostVisible;
+ desc.size = sizeof(T);
+ auto buffer = context->GetResourceAllocator()->CreateBuffer(desc);
+ buffer->SetLabel(label);
+ return buffer;
+ }
+
private:
fml::TimeDelta start_time_;
diff --git a/impeller/renderer/BUILD.gn b/impeller/renderer/BUILD.gn
index 2ac5e90..792fc8e 100644
--- a/impeller/renderer/BUILD.gn
+++ b/impeller/renderer/BUILD.gn
@@ -121,6 +121,7 @@
deps = [
":renderer",
+ "../entity",
"../fixtures",
"../playground:playground_test",
"//flutter/testing:testing_lib",
diff --git a/impeller/renderer/backend/vulkan/allocator_vk.cc b/impeller/renderer/backend/vulkan/allocator_vk.cc
index 220eca3..f1c1e21 100644
--- a/impeller/renderer/backend/vulkan/allocator_vk.cc
+++ b/impeller/renderer/backend/vulkan/allocator_vk.cc
@@ -252,7 +252,7 @@
&allocation_info //
)};
if (result != vk::Result::eSuccess) {
- VALIDATION_LOG << "Unable to allocation Vulkan Image: "
+ VALIDATION_LOG << "Unable to allocate Vulkan Image: "
<< vk::to_string(result);
return;
}
diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc
index c1ac785..a797491 100644
--- a/impeller/renderer/backend/vulkan/context_vk.cc
+++ b/impeller/renderer/backend/vulkan/context_vk.cc
@@ -51,7 +51,7 @@
}
const auto prefix = impeller::vk::to_string(
- impeller::vk::DebugUtilsMessageSeverityFlagBitsEXT{severity});
+ impeller::vk::DebugUtilsMessageSeverityFlagBitsEXT(severity));
// Just so that the log doesn't say FML_DCHECK(false).
constexpr bool kVulkanValidationFailure = false;
FML_DCHECK(kVulkanValidationFailure)
diff --git a/impeller/renderer/compute_subgroup_unittests.cc b/impeller/renderer/compute_subgroup_unittests.cc
index 5ebcb33..1b93ae6 100644
--- a/impeller/renderer/compute_subgroup_unittests.cc
+++ b/impeller/renderer/compute_subgroup_unittests.cc
@@ -2,11 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <numeric>
+
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/time/time_point.h"
#include "flutter/testing/testing.h"
#include "gmock/gmock.h"
#include "impeller/base/strings.h"
+#include "impeller/entity/contents/content_context.h"
#include "impeller/fixtures/cubic_to_quads.comp.h"
#include "impeller/fixtures/golden_heart.h"
#include "impeller/fixtures/quad_polyline.comp.h"
@@ -22,6 +25,7 @@
#include "impeller/renderer/compute_pipeline_builder.h"
#include "impeller/renderer/formats.h"
#include "impeller/renderer/pipeline_library.h"
+#include "impeller/renderer/render_pass.h"
namespace impeller {
namespace testing {
@@ -44,27 +48,21 @@
static constexpr size_t kCubicCount = 6;
static constexpr Scalar kAccuracy = .1;
- DeviceBufferDescriptor quad_buffer_desc;
- quad_buffer_desc.storage_mode = StorageMode::kHostVisible;
- quad_buffer_desc.size = sizeof(CS::Quads<kCubicCount * 10>);
- auto quads = context->GetResourceAllocator()->CreateBuffer(quad_buffer_desc);
- quads->SetLabel("Quads");
+ auto quads = CreateHostVisibleDeviceBuffer<CS::Quads<kCubicCount * 10>>(
+ context, "Quads");
- DeviceBufferDescriptor point_buffer_desc;
- point_buffer_desc.storage_mode = StorageMode::kHostVisible;
// TODO(dnfield): Size this buffer more accurately.
- point_buffer_desc.size = sizeof(QS::Polyline<kCubicCount * 10 * 10>);
auto polyline =
- context->GetResourceAllocator()->CreateBuffer(point_buffer_desc);
- polyline->SetLabel("polyline");
+ CreateHostVisibleDeviceBuffer<QS::Polyline<kCubicCount * 10 * 10>>(
+ context, "polyline");
- DeviceBufferDescriptor vertex_buffer_desc;
- vertex_buffer_desc.storage_mode = StorageMode::kHostVisible;
+ auto vertex_buffer_count =
+ CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
+ "VertexBufferCount");
+
// TODO(dnfield): Size this buffer more accurately.
- vertex_buffer_desc.size = sizeof(SS::VertexBuffer<kCubicCount * 10 * 10 * 4>);
- auto vertex_buffer =
- context->GetResourceAllocator()->CreateBuffer(vertex_buffer_desc);
- vertex_buffer->SetLabel("VertexBuffer");
+ auto vertex_buffer = CreateHostVisibleDeviceBuffer<
+ SS::VertexBuffer<kCubicCount * 10 * 10 * 4>>(context, "VertexBuffer");
{
using CubicPipelineBuilder = ComputePipelineBuilder<CS>;
@@ -138,13 +136,14 @@
pass->SetThreadGroupSize(ISize(1024, 1));
ComputeCommand cmd;
- cmd.label = "Stroke";
+ cmd.label = "Draw Stroke";
cmd.pipeline = compute_pipeline;
SS::Config config{.width = 1.0f, .cap = 1, .join = 1, .miter_limit = 4.0f};
SS::BindConfig(cmd, pass->GetTransientsBuffer().EmplaceUniform(config));
SS::BindPolyline(cmd, polyline->AsBufferView());
+ SS::BindVertexBufferCount(cmd, vertex_buffer_count->AsBufferView());
SS::BindVertexBuffer(cmd, vertex_buffer->AsBufferView());
ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
@@ -154,7 +153,7 @@
fml::AutoResetWaitableEvent latch;
ASSERT_TRUE(cmd_buffer->SubmitCommands([&latch, quads, polyline,
- vertex_buffer](
+ vertex_buffer_count, vertex_buffer](
CommandBuffer::Status status) {
EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
@@ -183,7 +182,9 @@
auto* v = reinterpret_cast<SS::VertexBuffer<kCubicCount * 10 * 10 * 4>*>(
vertex_buffer->AsBufferView().contents);
- EXPECT_EQ(v->count, golden_heart_vertices.size());
+ auto* v_count = reinterpret_cast<SS::VertexBufferCount*>(
+ vertex_buffer_count->AsBufferView().contents);
+ EXPECT_EQ(v_count->count, golden_heart_vertices.size());
for (size_t i = 0; i < golden_heart_vertices.size(); i += 1) {
EXPECT_LT(std::abs(golden_heart_vertices[i].x - v->position[i].x), 1e-3);
EXPECT_LT(std::abs(golden_heart_vertices[i].y - v->position[i].y), 1e-3);
@@ -193,6 +194,64 @@
}));
latch.Wait();
+
+ auto callback = [&](RenderPass& pass) -> bool {
+ ContentContext renderer(context);
+ if (!renderer.IsValid()) {
+ return false;
+ }
+
+ using VS = SolidFillPipeline::VertexShader;
+ using FS = SolidFillPipeline::FragmentShader;
+
+ Command cmd;
+ cmd.label = "Draw Stroke";
+ cmd.stencil_reference = 0; // entity.GetStencilDepth();
+
+ ContentContextOptions options;
+ options.sample_count = pass.GetRenderTarget().GetSampleCount();
+ options.color_attachment_pixel_format =
+ pass.GetRenderTarget().GetRenderTargetPixelFormat();
+ options.has_stencil_attachment =
+ pass.GetRenderTarget().GetStencilAttachment().has_value();
+ options.blend_mode = BlendMode::kSourceIn; // entity.GetBlendMode();
+ options.primitive_type = PrimitiveType::kTriangleStrip;
+ options.stencil_compare = CompareFunction::kEqual;
+ options.stencil_operation = StencilOperation::kIncrementClamp;
+
+ cmd.pipeline = renderer.GetSolidFillPipeline(options);
+
+ auto count = golden_heart_vertices.size();
+ auto& host_buffer = pass.GetTransientsBuffer();
+ std::vector<uint16_t> indices(count);
+ std::iota(std::begin(indices), std::end(indices), 0);
+
+ VertexBuffer render_vertex_buffer{
+ .vertex_buffer = vertex_buffer->AsBufferView(),
+ .index_buffer = host_buffer.Emplace(
+ indices.data(), count * sizeof(uint16_t), alignof(uint16_t)),
+ .index_count = count,
+ .index_type = IndexType::k16bit};
+ cmd.BindVertices(render_vertex_buffer);
+
+ VS::FrameInfo frame_info;
+ auto world_matrix = Matrix::MakeScale(GetContentScale());
+ frame_info.mvp =
+ Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix;
+ VS::BindFrameInfo(cmd,
+ pass.GetTransientsBuffer().EmplaceUniform(frame_info));
+
+ FS::FragInfo frag_info;
+ frag_info.color = Color::Red().Premultiply();
+ FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info));
+
+ if (!pass.AddCommand(std::move(cmd))) {
+ return false;
+ }
+
+ return true;
+ };
+ ASSERT_TRUE(OpenPlaygroundHere(callback));
}
TEST_P(ComputeTest, QuadsToPolyline) {
@@ -215,12 +274,8 @@
golden_heart_quads[i].p2};
}
- DeviceBufferDescriptor point_buffer_desc;
- point_buffer_desc.storage_mode = StorageMode::kHostVisible;
- point_buffer_desc.size = sizeof(QS::Polyline<kPolylineCount>);
- auto polyline =
- context->GetResourceAllocator()->CreateBuffer(point_buffer_desc);
- polyline->SetLabel("polyline");
+ auto polyline = CreateHostVisibleDeviceBuffer<QS::Polyline<kPolylineCount>>(
+ context, "polyline");
{
using QuadPipelineBuilder = ComputePipelineBuilder<QS>;
diff --git a/impeller/renderer/compute_unittests.cc b/impeller/renderer/compute_unittests.cc
index cfa50e0..ffed4bd 100644
--- a/impeller/renderer/compute_unittests.cc
+++ b/impeller/renderer/compute_unittests.cc
@@ -54,7 +54,7 @@
CS::Info info{.count = kCount};
CS::Input0<kCount> input_0;
CS::Input1<kCount> input_1;
- for (uint i = 0; i < kCount; i++) {
+ for (size_t i = 0; i < kCount; i++) {
input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
}
@@ -64,13 +64,8 @@
input_0.some_int = 5;
input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
- DeviceBufferDescriptor buffer_desc;
- buffer_desc.storage_mode = StorageMode::kHostVisible;
- buffer_desc.size = sizeof(CS::Output<kCount>);
-
- auto output_buffer =
- context->GetResourceAllocator()->CreateBuffer(buffer_desc);
- output_buffer->SetLabel("Output Buffer");
+ auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
+ context, "Output Buffer");
CS::BindInfo(cmd, pass->GetTransientsBuffer().EmplaceUniform(info));
CS::BindInput0(cmd,
@@ -144,31 +139,20 @@
CS1::Input<kCount1> input_1;
input_1.count = kCount1;
- for (uint i = 0; i < kCount1; i++) {
+ for (size_t i = 0; i < kCount1; i++) {
input_1.elements[i] = i;
}
CS2::Input<kCount2> input_2;
input_2.count = kCount2;
- for (uint i = 0; i < kCount2; i++) {
+ for (size_t i = 0; i < kCount2; i++) {
input_2.elements[i] = i;
}
- DeviceBufferDescriptor output_desc_1;
- output_desc_1.storage_mode = StorageMode::kHostVisible;
- output_desc_1.size = sizeof(CS1::Output<kCount2>);
-
- auto output_buffer_1 =
- context->GetResourceAllocator()->CreateBuffer(output_desc_1);
- output_buffer_1->SetLabel("Output Buffer Stage 1");
-
- DeviceBufferDescriptor output_desc_2;
- output_desc_2.storage_mode = StorageMode::kHostVisible;
- output_desc_2.size = sizeof(CS2::Output<kCount2>);
-
- auto output_buffer_2 =
- context->GetResourceAllocator()->CreateBuffer(output_desc_2);
- output_buffer_2->SetLabel("Output Buffer Stage 2");
+ auto output_buffer_1 = CreateHostVisibleDeviceBuffer<CS1::Output<kCount2>>(
+ context, "Output Buffer Stage 1");
+ auto output_buffer_2 = CreateHostVisibleDeviceBuffer<CS2::Output<kCount2>>(
+ context, "Output Buffer Stage 2");
{
ComputeCommand cmd;
diff --git a/impeller/tools/impeller.gni b/impeller/tools/impeller.gni
index 4f864b4..14bbbc9 100644
--- a/impeller/tools/impeller.gni
+++ b/impeller/tools/impeller.gni
@@ -18,7 +18,7 @@
impeller_enable_opengles = is_mac || is_linux || is_win || is_android
# Whether the Vulkan backend is enabled.
- impeller_enable_vulkan = is_mac || is_linux || is_android
+ impeller_enable_vulkan = is_mac || is_linux || is_win || is_android
# Whether to use a prebuilt impellerc.
# If this is the empty string, impellerc will be built.
diff --git a/lib/ui/painting.dart b/lib/ui/painting.dart
index 30cc3d3..ee2d173 100644
--- a/lib/ui/painting.dart
+++ b/lib/ui/painting.dart
@@ -6294,7 +6294,12 @@
final ImmutableBuffer instance = ImmutableBuffer._(0);
return _futurize((_Callback<int> callback) {
return instance._initFromAsset(encodedKey, callback);
- }).then((int length) => instance.._length = length);
+ }).then((int length) {
+ if (length == -1) {
+ throw Exception('Asset not found');
+ }
+ return instance.._length = length;
+ });
}
/// Create a buffer from the file with [path].
diff --git a/lib/ui/painting/image_decoder_impeller.cc b/lib/ui/painting/image_decoder_impeller.cc
index bd94028..04c4cd8 100644
--- a/lib/ui/painting/image_decoder_impeller.cc
+++ b/lib/ui/painting/image_decoder_impeller.cc
@@ -54,9 +54,12 @@
// Source:
// https://source.chromium.org/chromium/_/skia/skia.git/+/393fb1ec80f41d8ad7d104921b6920e69749fda1:src/codec/SkAndroidCodec.cpp;l=67;drc=46572b4d445f41943059d0e377afc6d6748cd5ca;bpv=1;bpt=0
-bool IsWideGamut(const SkColorSpace& color_space) {
+bool IsWideGamut(const SkColorSpace* color_space) {
+ if (!color_space) {
+ return false;
+ }
skcms_Matrix3x3 xyzd50;
- color_space.toXYZD50(&xyzd50);
+ color_space->toXYZD50(&xyzd50);
SkPoint rgb[3];
LoadGamut(rgb, xyzd50);
float area = CalculateArea(rgb);
@@ -134,7 +137,7 @@
const auto base_image_info = descriptor->image_info();
const bool is_wide_gamut =
- supports_wide_gamut ? IsWideGamut(*base_image_info.colorSpace()) : false;
+ supports_wide_gamut ? IsWideGamut(base_image_info.colorSpace()) : false;
SkAlphaType alpha_type =
ChooseCompatibleAlphaType(base_image_info.alphaType());
SkImageInfo image_info;
diff --git a/lib/ui/painting/image_decoder_unittests.cc b/lib/ui/painting/image_decoder_unittests.cc
index 587ae4d..551947a 100644
--- a/lib/ui/painting/image_decoder_unittests.cc
+++ b/lib/ui/painting/image_decoder_unittests.cc
@@ -290,6 +290,31 @@
}
} // namespace
+TEST_F(ImageDecoderFixtureTest, ImpellerNullColorspace) {
+ auto info = SkImageInfo::Make(10, 10, SkColorType::kRGBA_8888_SkColorType,
+ SkAlphaType::kPremul_SkAlphaType);
+ SkBitmap bitmap;
+ bitmap.allocPixels(info, 10 * 4);
+ auto data = SkData::MakeWithoutCopy(bitmap.getPixels(), 10 * 10 * 4);
+ auto image = SkImage::MakeFromBitmap(bitmap);
+ ASSERT_TRUE(image != nullptr);
+ ASSERT_EQ(SkISize::Make(10, 10), image->dimensions());
+ ASSERT_EQ(nullptr, image->colorSpace());
+
+ auto descriptor = fml::MakeRefCounted<ImageDescriptor>(
+ std::move(data), image->imageInfo(), 10 * 4);
+
+#if IMPELLER_SUPPORTS_RENDERING
+ std::shared_ptr<SkBitmap> decompressed =
+ ImageDecoderImpeller::DecompressTexture(
+ descriptor.get(), SkISize::Make(100, 100), {100, 100},
+ /*supports_wide_gamut=*/true);
+ ASSERT_TRUE(decompressed);
+ ASSERT_EQ(decompressed->colorType(), kRGBA_8888_SkColorType);
+ ASSERT_EQ(decompressed->colorSpace(), nullptr);
+#endif // IMPELLER_SUPPORTS_RENDERING
+}
+
TEST_F(ImageDecoderFixtureTest, ImpellerWideGamutDisplayP3) {
auto data = OpenFixtureAsSkData("DisplayP3Logo.png");
auto image = SkImage::MakeFromEncoded(data);
diff --git a/lib/ui/painting/immutable_buffer.cc b/lib/ui/painting/immutable_buffer.cc
index 0d86b07..0f859f3 100644
--- a/lib/ui/painting/immutable_buffer.cc
+++ b/lib/ui/painting/immutable_buffer.cc
@@ -43,7 +43,7 @@
return Dart_Null();
}
-Dart_Handle ImmutableBuffer::initFromAsset(Dart_Handle buffer_handle,
+Dart_Handle ImmutableBuffer::initFromAsset(Dart_Handle raw_buffer_handle,
Dart_Handle asset_name_handle,
Dart_Handle callback_handle) {
UIDartState::ThrowIfUIOperationsProhibited();
@@ -62,21 +62,60 @@
std::string asset_name = std::string{reinterpret_cast<const char*>(chars),
static_cast<size_t>(asset_length)};
- std::shared_ptr<AssetManager> asset_manager = UIDartState::Current()
- ->platform_configuration()
- ->client()
- ->GetAssetManager();
- std::unique_ptr<fml::Mapping> data = asset_manager->GetAsMapping(asset_name);
- if (data == nullptr) {
- return tonic::ToDart("Asset not found");
- }
+ auto* dart_state = UIDartState::Current();
+ auto ui_task_runner = dart_state->GetTaskRunners().GetUITaskRunner();
+ auto* buffer_callback_ptr =
+ new tonic::DartPersistentValue(dart_state, callback_handle);
+ auto* buffer_handle_ptr =
+ new tonic::DartPersistentValue(dart_state, raw_buffer_handle);
+ auto asset_manager = UIDartState::Current()
+ ->platform_configuration()
+ ->client()
+ ->GetAssetManager();
- auto size = data->GetSize();
- const void* bytes = static_cast<const void*>(data->GetMapping());
- auto sk_data = MakeSkDataWithCopy(bytes, size);
- auto buffer = fml::MakeRefCounted<ImmutableBuffer>(sk_data);
- buffer->AssociateWithDartWrapper(buffer_handle);
- tonic::DartInvoke(callback_handle, {tonic::ToDart(size)});
+ auto ui_task = fml::MakeCopyable(
+ [buffer_callback_ptr, buffer_handle_ptr](const sk_sp<SkData>& sk_data,
+ size_t buffer_size) mutable {
+ std::unique_ptr<tonic::DartPersistentValue> buffer_handle(
+ buffer_handle_ptr);
+ std::unique_ptr<tonic::DartPersistentValue> buffer_callback(
+ buffer_callback_ptr);
+
+ auto dart_state = buffer_callback->dart_state().lock();
+ if (!dart_state) {
+ return;
+ }
+ tonic::DartState::Scope scope(dart_state);
+
+ if (!sk_data) {
+ // -1 is used as a sentinel that the file could not be opened.
+ tonic::DartInvoke(buffer_callback->Get(), {tonic::ToDart(-1)});
+ return;
+ }
+ auto buffer = fml::MakeRefCounted<ImmutableBuffer>(sk_data);
+ buffer->AssociateWithDartWrapper(buffer_handle->Get());
+ tonic::DartInvoke(buffer_callback->Get(), {tonic::ToDart(buffer_size)});
+ });
+
+ dart_state->GetConcurrentTaskRunner()->PostTask(
+ [asset_name = std::move(asset_name),
+ asset_manager = std::move(asset_manager),
+ ui_task_runner = std::move(ui_task_runner), ui_task] {
+ std::unique_ptr<fml::Mapping> mapping =
+ asset_manager->GetAsMapping(asset_name);
+
+ sk_sp<SkData> sk_data;
+ size_t buffer_size = 0;
+ if (mapping != nullptr) {
+ buffer_size = mapping->GetSize();
+ const void* bytes = static_cast<const void*>(mapping->GetMapping());
+ sk_data = MakeSkDataWithCopy(bytes, buffer_size);
+ }
+ ui_task_runner->PostTask(
+ [sk_data = std::move(sk_data), ui_task = ui_task, buffer_size]() {
+ ui_task(sk_data, buffer_size);
+ });
+ });
return Dart_Null();
}
@@ -101,20 +140,24 @@
auto* dart_state = UIDartState::Current();
auto ui_task_runner = dart_state->GetTaskRunners().GetUITaskRunner();
- auto buffer_callback =
- std::make_unique<tonic::DartPersistentValue>(dart_state, callback_handle);
- auto buffer_handle = std::make_unique<tonic::DartPersistentValue>(
- dart_state, raw_buffer_handle);
+ auto* buffer_callback_ptr =
+ new tonic::DartPersistentValue(dart_state, callback_handle);
+ auto* buffer_handle_ptr =
+ new tonic::DartPersistentValue(dart_state, raw_buffer_handle);
auto ui_task = fml::MakeCopyable(
- [buffer_callback = std::move(buffer_callback),
- buffer_handle = std::move(buffer_handle)](const sk_sp<SkData>& sk_data,
- size_t buffer_size) mutable {
+ [buffer_callback_ptr, buffer_handle_ptr](const sk_sp<SkData>& sk_data,
+ size_t buffer_size) mutable {
+ std::unique_ptr<tonic::DartPersistentValue> buffer_handle(
+ buffer_handle_ptr);
+ std::unique_ptr<tonic::DartPersistentValue> buffer_callback(
+ buffer_callback_ptr);
auto dart_state = buffer_callback->dart_state().lock();
if (!dart_state) {
return;
}
tonic::DartState::Scope scope(dart_state);
+
if (!sk_data) {
// -1 is used as a sentinel that the file could not be opened.
tonic::DartInvoke(buffer_callback->Get(), {tonic::ToDart(-1)});
diff --git a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart
index d588da5..c5f739d 100644
--- a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart
+++ b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart
@@ -1911,12 +1911,12 @@
// into a utf16 string.
String getText() => utf8.decode(getTextUtf8().codeUnits);
- external void setWordsUtf8(Uint32List words);
- external void setWordsUtf16(Uint32List words);
- external void setGraphemeBreaksUtf8(Uint32List graphemes);
- external void setGraphemeBreaksUtf16(Uint32List graphemes);
- external void setLineBreaksUtf8(Uint32List lineBreaks);
- external void setLineBreaksUtf16(Uint32List lineBreaks);
+ external void setWordsUtf8(SkUint32List words);
+ external void setWordsUtf16(SkUint32List words);
+ external void setGraphemeBreaksUtf8(SkUint32List graphemes);
+ external void setGraphemeBreaksUtf16(SkUint32List graphemes);
+ external void setLineBreaksUtf8(SkUint32List lineBreaks);
+ external void setLineBreaksUtf16(SkUint32List lineBreaks);
external SkParagraph build();
external void delete();
diff --git a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_canvas.dart b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_canvas.dart
index a27aa97..596e87b 100644
--- a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_canvas.dart
+++ b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_canvas.dart
@@ -389,8 +389,13 @@
'If non-null, "colors" length must be one fourth the length of "rstTransforms" and "rects".');
}
+ Uint32List? unsignedColors;
+ if (colors != null) {
+ unsignedColors = colors.buffer.asUint32List(colors.offsetInBytes, colors.length);
+ }
+
_drawAtlas(paint, atlas, rstTransforms, rects,
- colors?.buffer.asUint32List(), blendMode ?? ui.BlendMode.src);
+ unsignedColors, blendMode ?? ui.BlendMode.src);
}
// TODO(hterkelsen): Pass a cull_rect once CanvasKit supports that.
diff --git a/lib/web_ui/lib/src/engine/canvaskit/text_fragmenter.dart b/lib/web_ui/lib/src/engine/canvaskit/text_fragmenter.dart
index ef55f17..762b617 100644
--- a/lib/web_ui/lib/src/engine/canvaskit/text_fragmenter.dart
+++ b/lib/web_ui/lib/src/engine/canvaskit/text_fragmenter.dart
@@ -43,7 +43,7 @@
IntlSegmenterGranularity.word: createIntlSegmenter(granularity: 'word'),
};
-Uint32List fragmentUsingIntlSegmenter(
+SkUint32List fragmentUsingIntlSegmenter(
String text,
IntlSegmenterGranularity granularity,
) {
@@ -56,7 +56,9 @@
}
breaks.add(text.length);
- return mallocUint32List(breaks.length).toTypedArray()..setAll(0, breaks);
+ final SkUint32List mallocedList = mallocUint32List(breaks.length);
+ mallocedList.toTypedArray().setAll(0, breaks);
+ return mallocedList;
}
// These are the soft/hard line break values expected by Skia's SkParagraph.
@@ -65,12 +67,13 @@
final DomV8BreakIterator _v8LineBreaker = createV8BreakIterator();
-Uint32List fragmentUsingV8LineBreaker(String text) {
+SkUint32List fragmentUsingV8LineBreaker(String text) {
final List<LineBreakFragment> fragments =
breakLinesUsingV8BreakIterator(text, _v8LineBreaker);
final int size = (fragments.length + 1) * 2;
- final Uint32List typedArray = mallocUint32List(size).toTypedArray();
+ final SkUint32List mallocedList = mallocUint32List(size);
+ final Uint32List typedArray = mallocedList.toTypedArray();
typedArray[0] = 0; // start index
typedArray[1] = _kSoftLineBreak; // break type
@@ -84,5 +87,5 @@
: _kSoftLineBreak;
}
- return typedArray;
+ return mallocedList;
}
diff --git a/lib/web_ui/lib/src/engine/canvaskit/vertices.dart b/lib/web_ui/lib/src/engine/canvaskit/vertices.dart
index df2b38c..5c22556 100644
--- a/lib/web_ui/lib/src/engine/canvaskit/vertices.dart
+++ b/lib/web_ui/lib/src/engine/canvaskit/vertices.dart
@@ -62,11 +62,16 @@
'"indices" values must be valid indices in the positions list.');
}
+ Uint32List? unsignedColors;
+ if (colors != null) {
+ unsignedColors = colors.buffer.asUint32List(colors.offsetInBytes, colors.length);
+ }
+
return CkVertices._(
toSkVertexMode(mode),
positions,
textureCoordinates,
- colors?.buffer.asUint32List(),
+ unsignedColors,
indices,
);
}
diff --git a/lib/web_ui/test/canvaskit/text_fragmenter_test.dart b/lib/web_ui/test/canvaskit/text_fragmenter_test.dart
index 7d44c3b..e444321 100644
--- a/lib/web_ui/test/canvaskit/text_fragmenter_test.dart
+++ b/lib/web_ui/test/canvaskit/text_fragmenter_test.dart
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:typed_data';
-
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
@@ -17,25 +15,33 @@
void testMain() {
setUpCanvasKitTest();
+ late SkUint32List breaks;
+
+ tearDown(() {
+ if (browserSupportsCanvaskitChromium) {
+ free(breaks);
+ }
+ });
+
group('$fragmentUsingIntlSegmenter', () {
test('fragments text into words', () {
- final Uint32List breaks = fragmentUsingIntlSegmenter(
+ breaks = fragmentUsingIntlSegmenter(
'Hello world ä½ å¥½ä¸–ç•Œ',
IntlSegmenterGranularity.word,
);
expect(
- breaks,
+ breaks.toTypedArray(),
orderedEquals(<int>[0, 5, 6, 11, 12, 14, 16]),
);
});
test('fragments multi-line text into words', () {
- final Uint32List breaks = fragmentUsingIntlSegmenter(
+ breaks = fragmentUsingIntlSegmenter(
'Lorem ipsum\ndolor ä½ å¥½ä¸–ç•Œ sit\namet',
IntlSegmenterGranularity.word,
);
expect(
- breaks,
+ breaks.toTypedArray(),
orderedEquals(<int>[
0, 5, 6, 11, 12, // "Lorem ipsum\n"
17, 18, 20, 22, 23, 26, 27, // "dolor ä½ å¥½ä¸–ç•Œ sit\n"
@@ -47,12 +53,12 @@
test('fragments text into grapheme clusters', () {
// The smiley emoji has a length of 2.
// The family emoji has a length of 11.
- final Uint32List breaks = fragmentUsingIntlSegmenter(
+ breaks = fragmentUsingIntlSegmenter(
'Lorem🙂ipsum👨👩👧👦',
IntlSegmenterGranularity.grapheme,
);
expect(
- breaks,
+ breaks.toTypedArray(),
orderedEquals(<int>[
0, 1, 2, 3, 4, 5, 7, // "Lorem🙂"
8, 9, 10, 11, 12, 23, // "ipsum👨👩👧👦"
@@ -63,12 +69,12 @@
test('fragments multi-line text into grapheme clusters', () {
// The smiley emojis have a length of 2 each.
// The family emoji has a length of 11.
- final Uint32List breaks = fragmentUsingIntlSegmenter(
+ breaks = fragmentUsingIntlSegmenter(
'Lorem🙂\nipsum👨👩👧👦dolor\n😄',
IntlSegmenterGranularity.grapheme,
);
expect(
- breaks,
+ breaks.toTypedArray(),
orderedEquals(<int>[
0, 1, 2, 3, 4, 5, 7, 8, // "Lorem🙂\n"
9, 10, 11, 12, 13, 24, // "ipsum👨👩👧👦"
@@ -83,11 +89,11 @@
const int kHard = 1;
test('fragments text into soft and hard line breaks', () {
- final Uint32List breaks = fragmentUsingV8LineBreaker(
+ breaks = fragmentUsingV8LineBreaker(
'Lorem-ipsum ä½ å¥½ðŸ™‚\nDolor sit',
);
expect(
- breaks,
+ breaks.toTypedArray(),
orderedEquals(<int>[
0, kSoft,
6, kSoft, // "Lorem-"
diff --git a/shell/common/fixtures/shell_test.dart b/shell/common/fixtures/shell_test.dart
index 605e3d9..b88289a 100644
--- a/shell/common/fixtures/shell_test.dart
+++ b/shell/common/fixtures/shell_test.dart
@@ -470,3 +470,11 @@
}
notifyNativeBool(true);
}
+
+@pragma('vm:entry-point')
+Future<void> testThatAssetLoadingHappensOnWorkerThread() async {
+ try {
+ await ImmutableBuffer.fromAsset('DoesNotExist');
+ } catch (err) { /* Do nothing */ }
+ notifyNative();
+}
diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc
index 449822c..36c8646 100644
--- a/shell/common/shell_unittests.cc
+++ b/shell/common/shell_unittests.cc
@@ -19,6 +19,7 @@
#include "flutter/flow/layers/layer_raster_cache_item.h"
#include "flutter/flow/layers/platform_view_layer.h"
#include "flutter/flow/layers/transform_layer.h"
+#include "flutter/fml/backtrace.h"
#include "flutter/fml/command_line.h"
#include "flutter/fml/dart/dart_converter.h"
#include "flutter/fml/make_copyable.h"
@@ -194,6 +195,42 @@
AssetResolver::AssetResolverType type_;
};
+class ThreadCheckingAssetResolver : public AssetResolver {
+ public:
+ explicit ThreadCheckingAssetResolver(
+ std::shared_ptr<fml::ConcurrentMessageLoop> concurrent_loop)
+ : concurrent_loop_(std::move(concurrent_loop)) {}
+
+ // |AssetResolver|
+ bool IsValid() const override { return true; }
+
+ // |AssetResolver|
+ bool IsValidAfterAssetManagerChange() const override { return true; }
+
+ // |AssetResolver|
+ AssetResolverType GetType() const {
+ return AssetResolverType::kApkAssetProvider;
+ }
+
+ // |AssetResolver|
+ std::unique_ptr<fml::Mapping> GetAsMapping(
+ const std::string& asset_name) const override {
+ if (asset_name == "FontManifest.json") {
+ // This file is loaded directly by the engine.
+ return nullptr;
+ }
+ mapping_requests.push_back(asset_name);
+ EXPECT_TRUE(concurrent_loop_->RunsTasksOnCurrentThread())
+ << fml::BacktraceHere();
+ return nullptr;
+ }
+
+ mutable std::vector<std::string> mapping_requests;
+
+ private:
+ std::shared_ptr<fml::ConcurrentMessageLoop> concurrent_loop_;
+};
+
static bool ValidateShell(Shell* shell) {
if (!shell) {
return false;
@@ -3805,6 +3842,39 @@
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
}
+TEST_F(ShellTest, ImmutableBufferLoadsAssetOnBackgroundThread) {
+ Settings settings = CreateSettingsForFixture();
+ auto task_runner = CreateNewThread();
+ TaskRunners task_runners("test", task_runner, task_runner, task_runner,
+ task_runner);
+ std::unique_ptr<Shell> shell = CreateShell(settings, task_runners);
+
+ fml::CountDownLatch latch(1);
+ AddNativeCallback("NotifyNative",
+ CREATE_NATIVE_ENTRY([&](auto args) { latch.CountDown(); }));
+
+ // Create the surface needed by rasterizer
+ PlatformViewNotifyCreated(shell.get());
+
+ auto configuration = RunConfiguration::InferFromSettings(settings);
+ configuration.SetEntrypoint("testThatAssetLoadingHappensOnWorkerThread");
+ auto asset_manager = configuration.GetAssetManager();
+ auto test_resolver = std::make_unique<ThreadCheckingAssetResolver>(
+ shell->GetDartVM()->GetConcurrentMessageLoop());
+ auto leaked_resolver = test_resolver.get();
+ asset_manager->PushBack(std::move(test_resolver));
+
+ RunEngine(shell.get(), std::move(configuration));
+ PumpOneFrame(shell.get());
+
+ latch.Wait();
+
+ EXPECT_EQ(leaked_resolver->mapping_requests[0], "DoesNotExist");
+
+ PlatformViewNotifyDestroyed(shell.get());
+ DestroyShell(std::move(shell), task_runners);
+}
+
TEST_F(ShellTest, PictureToImageSync) {
#if !SHELL_ENABLE_GL
// This test uses the GL backend.
diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
index d22118d..0dbb457 100644
--- a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
+++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
@@ -235,9 +235,16 @@
DartExecutor.DartEntrypoint dartEntrypoint =
new DartExecutor.DartEntrypoint(
appBundlePathOverride, host.getDartEntrypointFunctionName());
+ String initialRoute = host.getInitialRoute();
+ if (initialRoute == null) {
+ initialRoute = maybeGetInitialRouteFromIntent(host.getActivity().getIntent());
+ if (initialRoute == null) {
+ initialRoute = DEFAULT_INITIAL_ROUTE;
+ }
+ }
return options
.setDartEntrypoint(dartEntrypoint)
- .setInitialRoute(host.getInitialRoute())
+ .setInitialRoute(initialRoute)
.setDartEntrypointArgs(host.getDartEntrypointArgs());
}
diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java
index e120d77..8c1f545 100644
--- a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java
+++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java
@@ -237,6 +237,47 @@
// Expect IllegalStateException.
}
+ // Bug: b/271100292
+ @Test
+ public void flutterEngineGroupGetsInitialRouteFromIntent() {
+ // ---- Test setup ----
+ FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
+ Activity mockActivity = mock(Activity.class);
+ Intent mockIntent = mock(Intent.class);
+ when(mockFlutterLoader.findAppBundlePath()).thenReturn("default_flutter_assets/path");
+ FlutterInjector.setInstance(
+ new FlutterInjector.Builder().setFlutterLoader(mockFlutterLoader).build());
+ FlutterEngineGroup flutterEngineGroup = mock(FlutterEngineGroup.class);
+ FlutterEngineGroupCache.getInstance().put("my_flutter_engine_group", flutterEngineGroup);
+
+ List<String> entryPointArgs = new ArrayList<>();
+ entryPointArgs.add("entrypoint-arg");
+
+ // Adjust fake host to request cached engine group.
+ when(mockHost.getInitialRoute()).thenReturn(null);
+ when(mockHost.getCachedEngineGroupId()).thenReturn("my_flutter_engine_group");
+ when(mockHost.provideFlutterEngine(any(Context.class))).thenReturn(null);
+ when(mockHost.shouldAttachEngineToActivity()).thenReturn(false);
+ when(mockHost.getDartEntrypointArgs()).thenReturn(entryPointArgs);
+ when(mockHost.shouldHandleDeeplinking()).thenReturn(true);
+ when(mockHost.getActivity()).thenReturn(mockActivity);
+ when(mockActivity.getIntent()).thenReturn(mockIntent);
+ when(mockIntent.getData()).thenReturn(Uri.parse("foo://example.com/initial_route"));
+
+ // Create the real object that we're testing.
+ FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost);
+
+ // --- Execute the behavior under test ---
+ // The FlutterEngine is obtained in onAttach().
+ delegate.onAttach(ctx);
+
+ DartExecutor.DartEntrypoint entrypoint = new DartExecutor.DartEntrypoint("/fake/path", "main");
+ ArgumentCaptor<FlutterEngineGroup.Options> optionsCaptor =
+ ArgumentCaptor.forClass(FlutterEngineGroup.Options.class);
+ verify(flutterEngineGroup, times(1)).createAndRunEngine(optionsCaptor.capture());
+ assertEquals("/initial_route", optionsCaptor.getValue().getInitialRoute());
+ }
+
@Test
public void itUsesNewEngineInGroupWhenProvided() {
// ---- Test setup ----
diff --git a/shell/platform/common/accessibility_bridge.cc b/shell/platform/common/accessibility_bridge.cc
index 8007460..765304e 100644
--- a/shell/platform/common/accessibility_bridge.cc
+++ b/shell/platform/common/accessibility_bridge.cc
@@ -37,13 +37,13 @@
}
void AccessibilityBridge::AddFlutterSemanticsNodeUpdate(
- const FlutterSemanticsNode* node) {
- pending_semantics_node_updates_[node->id] = FromFlutterSemanticsNode(node);
+ const FlutterSemanticsNode& node) {
+ pending_semantics_node_updates_[node.id] = FromFlutterSemanticsNode(node);
}
void AccessibilityBridge::AddFlutterSemanticsCustomActionUpdate(
- const FlutterSemanticsCustomAction* action) {
- pending_semantics_custom_action_updates_[action->id] =
+ const FlutterSemanticsCustomAction& action) {
+ pending_semantics_custom_action_updates_[action.id] =
FromFlutterSemanticsCustomAction(action);
}
@@ -578,66 +578,66 @@
AccessibilityBridge::SemanticsNode
AccessibilityBridge::FromFlutterSemanticsNode(
- const FlutterSemanticsNode* flutter_node) {
+ const FlutterSemanticsNode& flutter_node) {
SemanticsNode result;
- result.id = flutter_node->id;
- result.flags = flutter_node->flags;
- result.actions = flutter_node->actions;
- result.text_selection_base = flutter_node->text_selection_base;
- result.text_selection_extent = flutter_node->text_selection_extent;
- result.scroll_child_count = flutter_node->scroll_child_count;
- result.scroll_index = flutter_node->scroll_index;
- result.scroll_position = flutter_node->scroll_position;
- result.scroll_extent_max = flutter_node->scroll_extent_max;
- result.scroll_extent_min = flutter_node->scroll_extent_min;
- result.elevation = flutter_node->elevation;
- result.thickness = flutter_node->thickness;
- if (flutter_node->label) {
- result.label = std::string(flutter_node->label);
+ result.id = flutter_node.id;
+ result.flags = flutter_node.flags;
+ result.actions = flutter_node.actions;
+ result.text_selection_base = flutter_node.text_selection_base;
+ result.text_selection_extent = flutter_node.text_selection_extent;
+ result.scroll_child_count = flutter_node.scroll_child_count;
+ result.scroll_index = flutter_node.scroll_index;
+ result.scroll_position = flutter_node.scroll_position;
+ result.scroll_extent_max = flutter_node.scroll_extent_max;
+ result.scroll_extent_min = flutter_node.scroll_extent_min;
+ result.elevation = flutter_node.elevation;
+ result.thickness = flutter_node.thickness;
+ if (flutter_node.label) {
+ result.label = std::string(flutter_node.label);
}
- if (flutter_node->hint) {
- result.hint = std::string(flutter_node->hint);
+ if (flutter_node.hint) {
+ result.hint = std::string(flutter_node.hint);
}
- if (flutter_node->value) {
- result.value = std::string(flutter_node->value);
+ if (flutter_node.value) {
+ result.value = std::string(flutter_node.value);
}
- if (flutter_node->increased_value) {
- result.increased_value = std::string(flutter_node->increased_value);
+ if (flutter_node.increased_value) {
+ result.increased_value = std::string(flutter_node.increased_value);
}
- if (flutter_node->decreased_value) {
- result.decreased_value = std::string(flutter_node->decreased_value);
+ if (flutter_node.decreased_value) {
+ result.decreased_value = std::string(flutter_node.decreased_value);
}
- if (flutter_node->tooltip) {
- result.tooltip = std::string(flutter_node->tooltip);
+ if (flutter_node.tooltip) {
+ result.tooltip = std::string(flutter_node.tooltip);
}
- result.text_direction = flutter_node->text_direction;
- result.rect = flutter_node->rect;
- result.transform = flutter_node->transform;
- if (flutter_node->child_count > 0) {
+ result.text_direction = flutter_node.text_direction;
+ result.rect = flutter_node.rect;
+ result.transform = flutter_node.transform;
+ if (flutter_node.child_count > 0) {
result.children_in_traversal_order = std::vector<int32_t>(
- flutter_node->children_in_traversal_order,
- flutter_node->children_in_traversal_order + flutter_node->child_count);
+ flutter_node.children_in_traversal_order,
+ flutter_node.children_in_traversal_order + flutter_node.child_count);
}
- if (flutter_node->custom_accessibility_actions_count > 0) {
+ if (flutter_node.custom_accessibility_actions_count > 0) {
result.custom_accessibility_actions = std::vector<int32_t>(
- flutter_node->custom_accessibility_actions,
- flutter_node->custom_accessibility_actions +
- flutter_node->custom_accessibility_actions_count);
+ flutter_node.custom_accessibility_actions,
+ flutter_node.custom_accessibility_actions +
+ flutter_node.custom_accessibility_actions_count);
}
return result;
}
AccessibilityBridge::SemanticsCustomAction
AccessibilityBridge::FromFlutterSemanticsCustomAction(
- const FlutterSemanticsCustomAction* flutter_custom_action) {
+ const FlutterSemanticsCustomAction& flutter_custom_action) {
SemanticsCustomAction result;
- result.id = flutter_custom_action->id;
- result.override_action = flutter_custom_action->override_action;
- if (flutter_custom_action->label) {
- result.label = std::string(flutter_custom_action->label);
+ result.id = flutter_custom_action.id;
+ result.override_action = flutter_custom_action.override_action;
+ if (flutter_custom_action.label) {
+ result.label = std::string(flutter_custom_action.label);
}
- if (flutter_custom_action->hint) {
- result.hint = std::string(flutter_custom_action->hint);
+ if (flutter_custom_action.hint) {
+ result.hint = std::string(flutter_custom_action.hint);
}
return result;
}
diff --git a/shell/platform/common/accessibility_bridge.h b/shell/platform/common/accessibility_bridge.h
index 81a6a1a..b654dad 100644
--- a/shell/platform/common/accessibility_bridge.h
+++ b/shell/platform/common/accessibility_bridge.h
@@ -60,8 +60,8 @@
/// Calling this method alone will NOT update the semantics tree.
/// To flush the pending updates, call the CommitUpdates().
///
- /// @param[in] node A pointer to the semantics node update.
- void AddFlutterSemanticsNodeUpdate(const FlutterSemanticsNode* node);
+ /// @param[in] node A reference to the semantics node update.
+ void AddFlutterSemanticsNodeUpdate(const FlutterSemanticsNode& node);
//------------------------------------------------------------------------------
/// @brief Adds a custom semantics action update to the pending semantics
@@ -69,10 +69,10 @@
/// semantics tree. To flush the pending updates, call the
/// CommitUpdates().
///
- /// @param[in] action A pointer to the custom semantics action
+ /// @param[in] action A reference to the custom semantics action
/// update.
void AddFlutterSemanticsCustomActionUpdate(
- const FlutterSemanticsCustomAction* action);
+ const FlutterSemanticsCustomAction& action);
//------------------------------------------------------------------------------
/// @brief Flushes the pending updates and applies them to this
@@ -252,9 +252,9 @@
const SemanticsNode& node);
void SetTreeData(const SemanticsNode& node, ui::AXTreeUpdate& tree_update);
SemanticsNode FromFlutterSemanticsNode(
- const FlutterSemanticsNode* flutter_node);
+ const FlutterSemanticsNode& flutter_node);
SemanticsCustomAction FromFlutterSemanticsCustomAction(
- const FlutterSemanticsCustomAction* flutter_custom_action);
+ const FlutterSemanticsCustomAction& flutter_custom_action);
// |AXTreeObserver|
void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
diff --git a/shell/platform/common/accessibility_bridge_unittests.cc b/shell/platform/common/accessibility_bridge_unittests.cc
index 3b5f197..d243afc 100644
--- a/shell/platform/common/accessibility_bridge_unittests.cc
+++ b/shell/platform/common/accessibility_bridge_unittests.cc
@@ -46,9 +46,9 @@
FlutterSemanticsNode child1 = CreateSemanticsNode(1, "child 1");
FlutterSemanticsNode child2 = CreateSemanticsNode(2, "child 2");
- bridge->AddFlutterSemanticsNodeUpdate(&root);
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
- bridge->AddFlutterSemanticsNodeUpdate(&child2);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
+ bridge->AddFlutterSemanticsNodeUpdate(child2);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
@@ -78,9 +78,9 @@
FlutterSemanticsNode child1 = CreateSemanticsNode(456, "child 1");
FlutterSemanticsNode child2 = CreateSemanticsNode(789, "child 2");
- bridge->AddFlutterSemanticsNodeUpdate(&root);
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
- bridge->AddFlutterSemanticsNodeUpdate(&child2);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
+ bridge->AddFlutterSemanticsNodeUpdate(child2);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(123).lock();
@@ -121,11 +121,11 @@
CreateSemanticsNode(78, "child 3", &child3_children);
FlutterSemanticsNode child4 = CreateSemanticsNode(90, "child 4");
- bridge->AddFlutterSemanticsNodeUpdate(&child3);
- bridge->AddFlutterSemanticsNodeUpdate(&child2);
- bridge->AddFlutterSemanticsNodeUpdate(&root);
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
- bridge->AddFlutterSemanticsNodeUpdate(&child4);
+ bridge->AddFlutterSemanticsNodeUpdate(child3);
+ bridge->AddFlutterSemanticsNodeUpdate(child2);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
+ bridge->AddFlutterSemanticsNodeUpdate(child4);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(12).lock();
@@ -165,8 +165,8 @@
FlutterSemanticsNode root = CreateSemanticsNode(0, "root", &children);
FlutterSemanticsNode child1 = CreateSemanticsNode(1, "child 1");
- bridge->AddFlutterSemanticsNodeUpdate(&root);
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
bridge->CommitUpdates();
@@ -187,8 +187,8 @@
FlutterSemanticsNode child2 = CreateSemanticsNode(2, "child 2");
- bridge->AddFlutterSemanticsNodeUpdate(&root);
- bridge->AddFlutterSemanticsNodeUpdate(&child2);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
+ bridge->AddFlutterSemanticsNodeUpdate(child2);
bridge->CommitUpdates();
root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
@@ -213,8 +213,8 @@
FlutterSemanticsNode root = CreateSemanticsNode(0, "root", &children);
FlutterSemanticsNode child1 = CreateSemanticsNode(1, "child 1");
- bridge->AddFlutterSemanticsNodeUpdate(&root);
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0);
@@ -246,7 +246,7 @@
root.flags = static_cast<FlutterSemanticsFlag>(
FlutterSemanticsFlag::kFlutterSemanticsFlagIsTextField |
FlutterSemanticsFlag::kFlutterSemanticsFlagIsFocused);
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
const ui::AXTreeData& tree = bridge->GetAXTreeData();
@@ -256,7 +256,7 @@
// Update the selection.
root.text_selection_base = 0;
root.text_selection_extent = 5;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
@@ -278,7 +278,7 @@
root.flags = static_cast<FlutterSemanticsFlag>(
FlutterSemanticsFlag::kFlutterSemanticsFlagIsTextField |
FlutterSemanticsFlag::kFlutterSemanticsFlagIsReadOnly);
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
@@ -295,7 +295,7 @@
FlutterSemanticsFlag::kFlutterSemanticsFlagHasToggledState |
FlutterSemanticsFlag::kFlutterSemanticsFlagHasEnabledState |
FlutterSemanticsFlag::kFlutterSemanticsFlagIsEnabled);
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
@@ -311,7 +311,7 @@
FlutterSemanticsFlag::kFlutterSemanticsFlagHasEnabledState |
FlutterSemanticsFlag::kFlutterSemanticsFlagIsEnabled |
FlutterSemanticsFlag::kFlutterSemanticsFlagIsFocusable);
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
@@ -330,7 +330,7 @@
root.flags = static_cast<FlutterSemanticsFlag>(
FlutterSemanticsFlag::kFlutterSemanticsFlagHasCheckedState |
FlutterSemanticsFlag::kFlutterSemanticsFlagIsChecked);
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
@@ -351,9 +351,9 @@
CreateSemanticsNode(1, "child 1", &child1_children);
FlutterSemanticsNode child2 = CreateSemanticsNode(2, "child 2");
- bridge->AddFlutterSemanticsNodeUpdate(&root);
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
- bridge->AddFlutterSemanticsNodeUpdate(&child2);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
+ bridge->AddFlutterSemanticsNodeUpdate(child2);
bridge->CommitUpdates();
bridge->accessibility_events.clear();
@@ -365,9 +365,9 @@
root.child_count = 2;
root.children_in_traversal_order = new_root_children;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
- bridge->AddFlutterSemanticsNodeUpdate(&child2);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
+ bridge->AddFlutterSemanticsNodeUpdate(child2);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
@@ -427,12 +427,12 @@
FlutterSemanticsNode leaf2 = CreateSemanticsNode(leaf2_id, "leaf 2");
FlutterSemanticsNode leaf3 = CreateSemanticsNode(leaf3_id, "leaf 3");
- bridge->AddFlutterSemanticsNodeUpdate(&root);
- bridge->AddFlutterSemanticsNodeUpdate(&intermediary1);
- bridge->AddFlutterSemanticsNodeUpdate(&intermediary2);
- bridge->AddFlutterSemanticsNodeUpdate(&leaf1);
- bridge->AddFlutterSemanticsNodeUpdate(&leaf2);
- bridge->AddFlutterSemanticsNodeUpdate(&leaf3);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
+ bridge->AddFlutterSemanticsNodeUpdate(intermediary1);
+ bridge->AddFlutterSemanticsNodeUpdate(intermediary2);
+ bridge->AddFlutterSemanticsNodeUpdate(leaf1);
+ bridge->AddFlutterSemanticsNodeUpdate(leaf2);
+ bridge->AddFlutterSemanticsNodeUpdate(leaf3);
bridge->CommitUpdates();
bridge->accessibility_events.clear();
@@ -445,11 +445,11 @@
intermediary2.child_count = 1;
intermediary2.children_in_traversal_order = new_intermediary2_children;
- bridge->AddFlutterSemanticsNodeUpdate(&intermediary1);
- bridge->AddFlutterSemanticsNodeUpdate(&intermediary2);
- bridge->AddFlutterSemanticsNodeUpdate(&leaf1);
- bridge->AddFlutterSemanticsNodeUpdate(&leaf2);
- bridge->AddFlutterSemanticsNodeUpdate(&leaf3);
+ bridge->AddFlutterSemanticsNodeUpdate(intermediary1);
+ bridge->AddFlutterSemanticsNodeUpdate(intermediary2);
+ bridge->AddFlutterSemanticsNodeUpdate(leaf1);
+ bridge->AddFlutterSemanticsNodeUpdate(leaf2);
+ bridge->AddFlutterSemanticsNodeUpdate(leaf3);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(root_id).lock();
@@ -516,10 +516,10 @@
CreateSemanticsNode(intermediary2_id, "intermediary 2");
FlutterSemanticsNode leaf1 = CreateSemanticsNode(leaf1_id, "leaf 1");
- bridge->AddFlutterSemanticsNodeUpdate(&root);
- bridge->AddFlutterSemanticsNodeUpdate(&intermediary1);
- bridge->AddFlutterSemanticsNodeUpdate(&intermediary2);
- bridge->AddFlutterSemanticsNodeUpdate(&leaf1);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
+ bridge->AddFlutterSemanticsNodeUpdate(intermediary1);
+ bridge->AddFlutterSemanticsNodeUpdate(intermediary2);
+ bridge->AddFlutterSemanticsNodeUpdate(leaf1);
bridge->CommitUpdates();
bridge->accessibility_events.clear();
@@ -532,10 +532,10 @@
intermediary2.child_count = 1;
intermediary2.children_in_traversal_order = new_intermediary2_children;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
- bridge->AddFlutterSemanticsNodeUpdate(&intermediary1);
- bridge->AddFlutterSemanticsNodeUpdate(&intermediary2);
- bridge->AddFlutterSemanticsNodeUpdate(&leaf1);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
+ bridge->AddFlutterSemanticsNodeUpdate(intermediary1);
+ bridge->AddFlutterSemanticsNodeUpdate(intermediary2);
+ bridge->AddFlutterSemanticsNodeUpdate(leaf1);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(root_id).lock();
@@ -595,7 +595,7 @@
FlutterSemanticsNode root = CreateSemanticsNode(root_id, "root", {});
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(root_id).lock();
diff --git a/shell/platform/common/flutter_platform_node_delegate_unittests.cc b/shell/platform/common/flutter_platform_node_delegate_unittests.cc
index d9fe80c..efe9e8d 100644
--- a/shell/platform/common/flutter_platform_node_delegate_unittests.cc
+++ b/shell/platform/common/flutter_platform_node_delegate_unittests.cc
@@ -28,8 +28,8 @@
node1.label = "prefecture";
node1.value = "Kyoto";
- bridge->AddFlutterSemanticsNodeUpdate(&node0);
- bridge->AddFlutterSemanticsNodeUpdate(&node1);
+ bridge->AddFlutterSemanticsNodeUpdate(node0);
+ bridge->AddFlutterSemanticsNodeUpdate(node1);
bridge->CommitUpdates();
auto node0_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
@@ -54,7 +54,7 @@
root.tooltip = "";
root.child_count = 0;
root.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
@@ -99,7 +99,7 @@
root.tooltip = "";
root.child_count = 0;
root.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
@@ -124,7 +124,7 @@
root.custom_accessibility_actions_count = 0;
root.rect = {0, 0, 100, 100}; // LTRB
root.transform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
FlutterSemanticsNode child1;
child1.id = 1;
@@ -138,7 +138,7 @@
child1.custom_accessibility_actions_count = 0;
child1.rect = {0, 0, 50, 50}; // LTRB
child1.transform = {0.5, 0, 0, 0, 0.5, 0, 0, 0, 1};
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
bridge->CommitUpdates();
auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
@@ -170,7 +170,7 @@
root.custom_accessibility_actions_count = 0;
root.rect = {0, 0, 100, 100}; // LTRB
root.transform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
FlutterSemanticsNode child1;
child1.id = 1;
@@ -184,7 +184,7 @@
child1.custom_accessibility_actions_count = 0;
child1.rect = {90, 90, 100, 100}; // LTRB
child1.transform = {2, 0, 0, 0, 2, 0, 0, 0, 1};
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
bridge->CommitUpdates();
auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
@@ -216,7 +216,7 @@
root.custom_accessibility_actions_count = 0;
root.rect = {0, 0, 100, 100}; // LTRB
root.transform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
FlutterSemanticsNode child1;
child1.id = 1;
@@ -230,7 +230,7 @@
child1.custom_accessibility_actions_count = 0;
child1.rect = {0, 0, 50, 50}; // LTRB
child1.transform = {0.5, 0, 0, 0, 0.5, 0, 0, 0, 1};
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
bridge->CommitUpdates();
auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
@@ -260,7 +260,7 @@
root.child_count = 0;
root.children_in_traversal_order = nullptr;
root.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
@@ -283,7 +283,7 @@
int32_t children[] = {1};
root.children_in_traversal_order = children;
root.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
FlutterSemanticsNode child1;
child1.id = 1;
@@ -295,7 +295,7 @@
child1.tooltip = "";
child1.child_count = 0;
child1.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
diff --git a/shell/platform/darwin/ios/platform_message_handler_ios.h b/shell/platform/darwin/ios/platform_message_handler_ios.h
index 09ef281..3b176a1 100644
--- a/shell/platform/darwin/ios/platform_message_handler_ios.h
+++ b/shell/platform/darwin/ios/platform_message_handler_ios.h
@@ -13,7 +13,9 @@
#include "flutter/shell/common/platform_message_handler.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
-@protocol FlutterTaskQueue;
+@protocol FlutterTaskQueue
+- (void)dispatch:(dispatch_block_t)block;
+@end
namespace flutter {
@@ -21,11 +23,11 @@
public:
static NSObject<FlutterTaskQueue>* MakeBackgroundTaskQueue();
- PlatformMessageHandlerIos(const TaskRunners& task_runners);
+ PlatformMessageHandlerIos(fml::RefPtr<fml::TaskRunner> platform_task_runner);
void HandlePlatformMessage(std::unique_ptr<PlatformMessage> message) override;
- bool DoesHandlePlatformMessageOnPlatformThread() const override { return false; }
+ bool DoesHandlePlatformMessageOnPlatformThread() const override;
void InvokePlatformMessageResponseCallback(int response_id,
std::unique_ptr<fml::Mapping> mapping) override;
@@ -43,7 +45,7 @@
private:
std::unordered_map<std::string, HandlerInfo> message_handlers_;
- TaskRunners task_runners_;
+ const fml::RefPtr<fml::TaskRunner> platform_task_runner_;
std::mutex message_handlers_mutex_;
FML_DISALLOW_COPY_AND_ASSIGN(PlatformMessageHandlerIos);
};
diff --git a/shell/platform/darwin/ios/platform_message_handler_ios.mm b/shell/platform/darwin/ios/platform_message_handler_ios.mm
index cf510bc..df65828 100644
--- a/shell/platform/darwin/ios/platform_message_handler_ios.mm
+++ b/shell/platform/darwin/ios/platform_message_handler_ios.mm
@@ -11,10 +11,6 @@
static uint64_t platform_message_counter = 1;
-@protocol FlutterTaskQueue
-- (void)dispatch:(dispatch_block_t)block;
-@end
-
@interface FLTSerialTaskQueue : NSObject <FlutterTaskQueue>
@property(nonatomic, strong) dispatch_queue_t queue;
@end
@@ -44,8 +40,9 @@
return [[[FLTSerialTaskQueue alloc] init] autorelease];
}
-PlatformMessageHandlerIos::PlatformMessageHandlerIos(const TaskRunners& task_runners)
- : task_runners_(task_runners) {}
+PlatformMessageHandlerIos::PlatformMessageHandlerIos(
+ fml::RefPtr<fml::TaskRunner> platform_task_runner)
+ : platform_task_runner_(std::move(platform_task_runner)) {}
void PlatformMessageHandlerIos::HandlePlatformMessage(std::unique_ptr<PlatformMessage> message) {
// This can be called from any isolate's thread.
@@ -97,6 +94,10 @@
}
}
+bool PlatformMessageHandlerIos::DoesHandlePlatformMessageOnPlatformThread() const {
+ return false;
+}
+
void PlatformMessageHandlerIos::InvokePlatformMessageResponseCallback(
int response_id,
std::unique_ptr<fml::Mapping> mapping) {
@@ -114,7 +115,7 @@
void PlatformMessageHandlerIos::SetMessageHandler(const std::string& channel,
FlutterBinaryMessageHandler handler,
NSObject<FlutterTaskQueue>* task_queue) {
- FML_CHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
+ FML_CHECK(platform_task_runner_->RunsTasksOnCurrentThread());
/// TODO(gaaclarke): This should be migrated to a lockfree datastructure.
std::lock_guard lock(message_handlers_mutex_);
message_handlers_.erase(channel);
diff --git a/shell/platform/darwin/ios/platform_message_handler_ios_test.mm b/shell/platform/darwin/ios/platform_message_handler_ios_test.mm
index 7249722..f1af3be 100644
--- a/shell/platform/darwin/ios/platform_message_handler_ios_test.mm
+++ b/shell/platform/darwin/ios/platform_message_handler_ios_test.mm
@@ -46,7 +46,7 @@
- (void)testCreate {
flutter::TaskRunners task_runners("test", GetCurrentTaskRunner(), CreateNewThread("raster"),
CreateNewThread("ui"), CreateNewThread("io"));
- auto handler = std::make_unique<PlatformMessageHandlerIos>(task_runners);
+ auto handler = std::make_unique<PlatformMessageHandlerIos>(task_runners.GetPlatformTaskRunner());
XCTAssertTrue(handler);
}
@@ -57,7 +57,7 @@
"test", GetCurrentTaskRunner(), thread_host.raster_thread->GetTaskRunner(),
thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner());
- auto handler = std::make_unique<PlatformMessageHandlerIos>(task_runners);
+ auto handler = std::make_unique<PlatformMessageHandlerIos>(task_runners.GetPlatformTaskRunner());
std::string channel = "foo";
XCTestExpectation* didCallReply = [self expectationWithDescription:@"didCallReply"];
handler->SetMessageHandler(
@@ -83,7 +83,7 @@
"test", GetCurrentTaskRunner(), thread_host.raster_thread->GetTaskRunner(),
thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner());
- auto handler = std::make_unique<PlatformMessageHandlerIos>(task_runners);
+ auto handler = std::make_unique<PlatformMessageHandlerIos>(task_runners.GetPlatformTaskRunner());
std::string channel = "foo";
XCTestExpectation* didCallMessage = [self expectationWithDescription:@"didCallMessage"];
handler->SetMessageHandler(
@@ -111,7 +111,7 @@
"test", GetCurrentTaskRunner(), thread_host.raster_thread->GetTaskRunner(),
thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner());
- auto handler = std::make_unique<PlatformMessageHandlerIos>(task_runners);
+ auto handler = std::make_unique<PlatformMessageHandlerIos>(task_runners.GetPlatformTaskRunner());
std::string channel = "foo";
XCTestExpectation* didCallReply = [self expectationWithDescription:@"didCallReply"];
NSObject<FlutterTaskQueue>* taskQueue = PlatformMessageHandlerIos::MakeBackgroundTaskQueue();
diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm
index 7e054fc..219dab4 100644
--- a/shell/platform/darwin/ios/platform_view_ios.mm
+++ b/shell/platform/darwin/ios/platform_view_ios.mm
@@ -48,7 +48,8 @@
ios_context_(context),
platform_views_controller_(platform_views_controller),
accessibility_bridge_([this](bool enabled) { PlatformView::SetSemanticsEnabled(enabled); }),
- platform_message_handler_(new PlatformMessageHandlerIos(task_runners)) {}
+ platform_message_handler_(
+ new PlatformMessageHandlerIos(task_runners.GetPlatformTaskRunner())) {}
PlatformViewIOS::PlatformViewIOS(
PlatformView::Delegate& delegate,
diff --git a/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacTest.mm b/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacTest.mm
index 0100e0b..9ba8d25 100644
--- a/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacTest.mm
+++ b/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacTest.mm
@@ -87,7 +87,7 @@
root.tooltip = "";
root.child_count = 0;
root.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
auto platform_node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
@@ -135,7 +135,7 @@
root.tooltip = "";
root.child_count = 0;
root.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
auto platform_node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
@@ -182,7 +182,7 @@
root.tooltip = "";
root.child_count = 0;
root.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
auto platform_node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
diff --git a/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMacTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMacTest.mm
index 276d620..8dbc02f 100644
--- a/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMacTest.mm
+++ b/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMacTest.mm
@@ -50,7 +50,7 @@
root.tooltip = "";
root.child_count = 0;
root.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
@@ -88,7 +88,7 @@
root.tooltip = "";
root.child_count = 0;
root.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
@@ -130,7 +130,7 @@
root.tooltip = "";
root.child_count = 0;
root.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
@@ -172,7 +172,7 @@
int32_t children[] = {1};
root.children_in_traversal_order = children;
root.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
FlutterSemanticsNode child1;
child1.id = 1;
@@ -184,7 +184,7 @@
child1.tooltip = "";
child1.child_count = 0;
child1.custom_accessibility_actions_count = 0;
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
bridge->CommitUpdates();
@@ -251,7 +251,7 @@
root.custom_accessibility_actions_count = 0;
root.rect = {0, 0, 100, 100}; // LTRB
root.transform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
double rectSize = 50;
double transformFactor = 0.5;
@@ -272,7 +272,7 @@
child1.custom_accessibility_actions_count = 0;
child1.rect = {0, 0, rectSize, rectSize}; // LTRB
child1.transform = {transformFactor, 0, 0, 0, transformFactor, 0, 0, 0, 1};
- bridge->AddFlutterSemanticsNodeUpdate(&child1);
+ bridge->AddFlutterSemanticsNodeUpdate(child1);
bridge->CommitUpdates();
diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm
index a921738..ace1e14 100644
--- a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm
+++ b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm
@@ -479,13 +479,11 @@
return;
}
for (size_t i = 0; i < update->nodes_count; i++) {
- const FlutterSemanticsNode* node = &update->nodes[i];
- _bridge->AddFlutterSemanticsNodeUpdate(node);
+ _bridge->AddFlutterSemanticsNodeUpdate(update->nodes[i]);
}
for (size_t i = 0; i < update->custom_actions_count; i++) {
- const FlutterSemanticsCustomAction* action = &update->custom_actions[i];
- _bridge->AddFlutterSemanticsCustomActionUpdate(action);
+ _bridge->AddFlutterSemanticsCustomActionUpdate(update->custom_actions[i]);
}
_bridge->CommitUpdates();
diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h
index 60a90f4..989b9cc 100644
--- a/shell/platform/embedder/embedder.h
+++ b/shell/platform/embedder/embedder.h
@@ -25,12 +25,16 @@
// - Function signatures (names, argument counts, argument order, and argument
// type) cannot change.
// - The core behavior of existing functions cannot change.
+// - Instead of nesting structures by value within another structure, prefer
+// nesting by pointer. This ensures that adding members to the nested struct
+// does not break the ABI of the parent struct.
// - Instead of array of structures, prefer array of pointers to structures.
// This ensures that array indexing does not break if members are added
// to the structure.
//
// These changes are allowed:
-// - Adding new struct members at the end of a structure.
+// - Adding new struct members at the end of a structure as long as the struct
+// is not nested within another struct by value.
// - Adding new enum members with a new value.
// - Renaming a struct member as long as its type, size, and intent remain the
// same.
diff --git a/shell/platform/embedder/tests/embedder_frozen.h b/shell/platform/embedder/tests/embedder_frozen.h
index 46e00f0..60c995f 100644
--- a/shell/platform/embedder/tests/embedder_frozen.h
+++ b/shell/platform/embedder/tests/embedder_frozen.h
@@ -22,6 +22,47 @@
namespace flutter {
namespace testing {
+// New members must not be added to `FlutterTransformation`
+// as it would break the ABI of `FlutterSemanticsNode`.
+// See: https://github.com/flutter/flutter/issues/121176
+typedef struct {
+ double scaleX;
+ double skewX;
+ double transX;
+ double skewY;
+ double scaleY;
+ double transY;
+ double pers0;
+ double pers1;
+ double pers2;
+} FrozenFlutterTransformation;
+
+// New members must not be added to `FlutterRect` as it would
+// break the ABI of `FlutterSemanticsNode` and `FlutterDamage`.
+// See: https://github.com/flutter/flutter/issues/121176
+// See: https://github.com/flutter/flutter/issues/121347
+typedef struct {
+ double left;
+ double top;
+ double right;
+ double bottom;
+} FrozenFlutterRect;
+
+// New members must not be added to `FlutterPoint` as it would
+// break the ABI of `FlutterLayer`.
+typedef struct {
+ double x;
+ double y;
+} FrozenFlutterPoint;
+
+// New members must not be added to `FlutterDamage` as it would
+// break the ABI of `FlutterPresentInfo`.
+typedef struct {
+ size_t struct_size;
+ size_t num_rects;
+ FrozenFlutterRect* damage;
+} FrozenFlutterDamage;
+
// New members must not be added to `FlutterSemanticsNode`
// as it would break the ABI of `FlutterSemanticsUpdate`.
// See: https://github.com/flutter/flutter/issues/121176
@@ -45,8 +86,8 @@
const char* increased_value;
const char* decreased_value;
FlutterTextDirection text_direction;
- FlutterRect rect;
- FlutterTransformation transform;
+ FrozenFlutterRect rect;
+ FrozenFlutterTransformation transform;
size_t child_count;
const int32_t* children_in_traversal_order;
const int32_t* children_in_hit_test_order;
diff --git a/shell/platform/embedder/tests/embedder_frozen_unittests.cc b/shell/platform/embedder/tests/embedder_frozen_unittests.cc
index eb173fe..4235547 100644
--- a/shell/platform/embedder/tests/embedder_frozen_unittests.cc
+++ b/shell/platform/embedder/tests/embedder_frozen_unittests.cc
@@ -14,6 +14,47 @@
#define ASSERT_EQ_OFFSET(type1, type2, member) \
ASSERT_EQ(offsetof(type1, member), offsetof(type2, member))
+// New members must not be added to `FlutterTransformation`
+// as it would break the ABI of `FlutterSemanticsNode`.
+// See: https://github.com/flutter/flutter/issues/121176
+TEST(EmbedderFrozen, FlutterTransformationIsFrozen) {
+ ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, scaleX);
+ ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, skewX);
+ ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, transX);
+ ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, skewY);
+ ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, scaleY);
+ ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, transY);
+ ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, pers0);
+ ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, pers1);
+ ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, pers2);
+}
+
+// New members must not be added to `FlutterRect` as it would
+// break the ABI of `FlutterSemanticsNode` and `FlutterDamage`.
+// See: https://github.com/flutter/flutter/issues/121176
+// See: https://github.com/flutter/flutter/issues/121347
+TEST(EmbedderFrozen, FlutterRectIsFrozen) {
+ ASSERT_EQ_OFFSET(FlutterRect, FrozenFlutterRect, left);
+ ASSERT_EQ_OFFSET(FlutterRect, FrozenFlutterRect, top);
+ ASSERT_EQ_OFFSET(FlutterRect, FrozenFlutterRect, right);
+ ASSERT_EQ_OFFSET(FlutterRect, FrozenFlutterRect, bottom);
+}
+
+// New members must not be added to `FlutterPoint` as it would
+// break the ABI of `FlutterLayer`.
+TEST(EmbedderFrozen, FlutterPointIsFrozen) {
+ ASSERT_EQ_OFFSET(FlutterPoint, FrozenFlutterPoint, x);
+ ASSERT_EQ_OFFSET(FlutterPoint, FrozenFlutterPoint, y);
+}
+
+// New members must not be added to `FlutterDamage` as it would
+// break the ABI of `FlutterPresentInfo`.
+TEST(EmbedderFrozen, FlutterDamageIsFrozen) {
+ ASSERT_EQ_OFFSET(FlutterDamage, FrozenFlutterDamage, struct_size);
+ ASSERT_EQ_OFFSET(FlutterDamage, FrozenFlutterDamage, num_rects);
+ ASSERT_EQ_OFFSET(FlutterDamage, FrozenFlutterDamage, damage);
+}
+
// New members must not be added to `FlutterSemanticsNode`
// as it would break the ABI of `FlutterSemanticsUpdate`.
// See: https://github.com/flutter/flutter/issues/121176
diff --git a/shell/platform/fuchsia/flutter/BUILD.gn b/shell/platform/fuchsia/flutter/BUILD.gn
index 13e5526..cc1407f 100644
--- a/shell/platform/fuchsia/flutter/BUILD.gn
+++ b/shell/platform/fuchsia/flutter/BUILD.gn
@@ -57,8 +57,6 @@
sources = [
"accessibility_bridge.cc",
"accessibility_bridge.h",
- "component_v1.cc",
- "component_v1.h",
"component_v2.cc",
"component_v2.h",
"engine.cc",
@@ -322,7 +320,6 @@
binary = "flutter_jit${product_suffix}_runner"
- cmx_file = rebase_path("meta/flutter_jit${product_suffix}_runner.cmx")
cml_file = rebase_path("meta/flutter_jit${product_suffix}_runner.cml")
resources = [
@@ -402,7 +399,6 @@
]
}
- cmx_file = rebase_path("meta/flutter_aot${product_suffix}_runner.cmx")
cml_file = rebase_path("meta/flutter_aot${product_suffix}_runner.cml")
binary = "flutter_aot${product_suffix}_runner"
@@ -500,7 +496,6 @@
sources = [
"accessibility_bridge_unittest.cc",
- "component_v1_unittest.cc",
"component_v2_unittest.cc",
"flutter_runner_fakes.h",
"focus_delegate_unittests.cc",
diff --git a/shell/platform/fuchsia/flutter/component_v1.cc b/shell/platform/fuchsia/flutter/component_v1.cc
deleted file mode 100644
index b869edb..0000000
--- a/shell/platform/fuchsia/flutter/component_v1.cc
+++ /dev/null
@@ -1,609 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "component_v1.h"
-
-#include <dlfcn.h>
-#include <fuchsia/mem/cpp/fidl.h>
-#include <lib/async-loop/cpp/loop.h>
-#include <lib/async/cpp/task.h>
-#include <lib/async/default.h>
-#include <lib/fdio/directory.h>
-#include <lib/fdio/io.h>
-#include <lib/fdio/namespace.h>
-#include <lib/ui/scenic/cpp/view_ref_pair.h>
-#include <lib/ui/scenic/cpp/view_token_pair.h>
-#include <lib/vfs/cpp/composed_service_dir.h>
-#include <lib/vfs/cpp/remote_dir.h>
-#include <lib/vfs/cpp/service.h>
-#include <sys/stat.h>
-#include <zircon/dlfcn.h>
-#include <zircon/status.h>
-#include <zircon/types.h>
-
-#include <memory>
-#include <regex>
-#include <sstream>
-
-#include "file_in_namespace_buffer.h"
-#include "flutter/fml/mapping.h"
-#include "flutter/fml/platform/fuchsia/task_observers.h"
-#include "flutter/fml/synchronization/waitable_event.h"
-#include "flutter/fml/unique_fd.h"
-#include "flutter/runtime/dart_vm_lifecycle.h"
-#include "flutter/shell/common/switches.h"
-#include "runtime/dart/utils/files.h"
-#include "runtime/dart/utils/handle_exception.h"
-#include "runtime/dart/utils/mapped_resource.h"
-#include "runtime/dart/utils/tempfs.h"
-#include "runtime/dart/utils/vmo.h"
-
-namespace flutter_runner {
-namespace {
-
-constexpr char kDataKey[] = "data";
-constexpr char kAssetsKey[] = "assets";
-constexpr char kOldGenHeapSizeKey[] = "old_gen_heap_size";
-
-constexpr char kTmpPath[] = "/tmp";
-constexpr char kServiceRootPath[] = "/svc";
-constexpr char kRunnerConfigPath[] = "/config/data/flutter_runner_config";
-
-std::string DebugLabelForUrl(const std::string& url) {
- auto found = url.rfind("/");
- if (found == std::string::npos) {
- return url;
- } else {
- return {url, found + 1};
- }
-}
-
-} // namespace
-
-ProgramMetadata ComponentV1::ParseProgramMetadata(
- const fidl::VectorPtr<fuchsia::sys::ProgramMetadata>& program_metadata) {
- ProgramMetadata result;
- if (!program_metadata.has_value()) {
- return result;
- }
-
- for (const auto& pg : *program_metadata) {
- if (pg.key.compare(kDataKey) == 0) {
- result.data_path = "pkg/" + pg.value;
- } else if (pg.key.compare(kAssetsKey) == 0) {
- result.assets_path = "pkg/" + pg.value;
- } else if (pg.key.compare(kOldGenHeapSizeKey) == 0) {
- int64_t specified_old_gen_heap_size =
- strtol(pg.value.c_str(), nullptr /* endptr */, 10 /* base */);
- if (specified_old_gen_heap_size != 0) {
- result.old_gen_heap_size = specified_old_gen_heap_size;
- } else {
- FML_LOG(ERROR) << "Invalid old_gen_heap_size: " << pg.value;
- }
- }
- }
-
- // assets_path defaults to the same as data_path if omitted.
- if (result.assets_path.empty()) {
- result.assets_path = result.data_path;
- }
-
- return result;
-}
-
-ActiveComponentV1 ComponentV1::Create(
- TerminationCallback termination_callback,
- fuchsia::sys::Package package,
- fuchsia::sys::StartupInfo startup_info,
- std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
- fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
- auto thread = std::make_unique<fml::Thread>();
- std::unique_ptr<ComponentV1> component;
-
- fml::AutoResetWaitableEvent latch;
- thread->GetTaskRunner()->PostTask([&]() mutable {
- component.reset(new ComponentV1(std::move(termination_callback),
- std::move(package), std::move(startup_info),
- runner_incoming_services,
- std::move(controller)));
- latch.Signal();
- });
-
- latch.Wait();
- return {.platform_thread = std::move(thread),
- .component = std::move(component)};
-}
-
-ComponentV1::ComponentV1(
- TerminationCallback termination_callback,
- fuchsia::sys::Package package,
- fuchsia::sys::StartupInfo startup_info,
- std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
- fidl::InterfaceRequest<fuchsia::sys::ComponentController>
- component_controller_request)
- : termination_callback_(std::move(termination_callback)),
- debug_label_(DebugLabelForUrl(startup_info.launch_info.url)),
- component_controller_(this),
- outgoing_dir_(new vfs::PseudoDir()),
- runner_incoming_services_(runner_incoming_services),
- weak_factory_(this) {
- component_controller_.set_error_handler(
- [this](zx_status_t status) { Kill(); });
-
- FML_DCHECK(fdio_ns_.is_valid());
- // LaunchInfo::url non-optional.
- auto& launch_info = startup_info.launch_info;
-
- // LaunchInfo::arguments optional.
- if (auto& arguments = launch_info.arguments) {
- dart_entrypoint_args_ = arguments.value();
- }
-
- const ProgramMetadata metadata =
- ParseProgramMetadata(startup_info.program_metadata);
-
- if (metadata.data_path.empty()) {
- FML_LOG(ERROR) << "Could not find a /pkg/data directory for "
- << package.resolved_url;
- return;
- }
-
- // Setup /tmp to be mapped to the process-local memfs.
- dart_utils::RunnerTemp::SetupComponent(fdio_ns_.get());
-
- // LaunchInfo::flat_namespace optional.
- for (size_t i = 0; i < startup_info.flat_namespace.paths.size(); ++i) {
- const auto& path = startup_info.flat_namespace.paths.at(i);
- if (path == kTmpPath) {
- continue;
- }
-
- fidl::InterfaceHandle<fuchsia::io::Directory> dir;
- if (path == kServiceRootPath) {
- svc_ = std::make_unique<sys::ServiceDirectory>(
- std::move(startup_info.flat_namespace.directories.at(i)));
- dir = svc_->CloneChannel();
- } else {
- dir = std::move(startup_info.flat_namespace.directories.at(i));
- }
-
- zx_handle_t dir_handle = dir.TakeChannel().release();
- if (fdio_ns_bind(fdio_ns_.get(), path.data(), dir_handle) != ZX_OK) {
- FML_LOG(ERROR) << "Could not bind path to namespace: " << path;
- zx_handle_close(dir_handle);
- }
- }
-
- {
- fml::UniqueFD ns_fd(fdio_ns_opendir(fdio_ns_.get()));
- FML_DCHECK(ns_fd.is_valid());
-
- constexpr mode_t mode = O_RDONLY | O_DIRECTORY;
-
- component_assets_directory_.reset(
- openat(ns_fd.get(), metadata.assets_path.c_str(), mode));
- FML_DCHECK(component_assets_directory_.is_valid());
-
- component_data_directory_.reset(
- openat(ns_fd.get(), metadata.data_path.c_str(), mode));
- FML_DCHECK(component_data_directory_.is_valid());
- }
-
- // TODO: LaunchInfo::out.
-
- // TODO: LaunchInfo::err.
-
- // LaunchInfo::service_request optional.
- if (launch_info.directory_request) {
- outgoing_dir_->Serve(fuchsia::io::OpenFlags::RIGHT_READABLE |
- fuchsia::io::OpenFlags::RIGHT_WRITABLE |
- fuchsia::io::OpenFlags::DIRECTORY,
- launch_info.directory_request.TakeChannel());
- }
-
- directory_request_ = directory_ptr_.NewRequest();
-
- fuchsia::io::DirectoryHandle flutter_public_dir;
- // TODO(anmittal): when fixing enumeration using new c++ vfs, make sure that
- // flutter_public_dir is only accessed once we receive OnOpen Event.
- // That will prevent FL-175 for public directory
- auto request = flutter_public_dir.NewRequest().TakeChannel();
- fdio_service_connect_at(directory_ptr_.channel().get(), "svc",
- request.release());
-
- auto composed_service_dir = std::make_unique<vfs::ComposedServiceDir>();
- composed_service_dir->set_fallback(std::move(flutter_public_dir));
-
- // Clone and check if client is servicing the directory.
- directory_ptr_->Clone(fuchsia::io::OpenFlags::DESCRIBE |
- fuchsia::io::OpenFlags::CLONE_SAME_RIGHTS,
- cloned_directory_ptr_.NewRequest());
-
- cloned_directory_ptr_.events().OnOpen = [this](zx_status_t status,
- auto unused) {
- cloned_directory_ptr_.Unbind();
- if (status != ZX_OK) {
- FML_LOG(ERROR) << "could not bind out directory for flutter component("
- << debug_label_ << "): " << zx_status_get_string(status);
- return;
- }
- const char* other_dirs[] = {"debug", "ctrl", "diagnostics"};
- // add other directories as RemoteDirs.
- for (auto& dir_str : other_dirs) {
- fuchsia::io::DirectoryHandle dir;
- auto request = dir.NewRequest().TakeChannel();
- auto status = fdio_open_at(
- directory_ptr_.channel().get(), dir_str,
- static_cast<uint32_t>(fuchsia::io::OpenFlags::DIRECTORY |
- fuchsia::io::OpenFlags::RIGHT_READABLE),
- request.release());
- if (status == ZX_OK) {
- outgoing_dir_->AddEntry(
- dir_str, std::make_unique<vfs::RemoteDir>(dir.TakeChannel()));
- } else {
- FML_LOG(ERROR) << "could not add out directory entry(" << dir_str
- << ") for flutter component(" << debug_label_
- << "): " << zx_status_get_string(status);
- }
- }
- };
-
- cloned_directory_ptr_.set_error_handler(
- [this](zx_status_t status) { cloned_directory_ptr_.Unbind(); });
-
- // TODO: LaunchInfo::additional_services optional.
-
- // All launch arguments have been read. Perform service binding and
- // final settings configuration. The next call will be to create a view
- // for this component.
- composed_service_dir->AddService(
- fuchsia::ui::app::ViewProvider::Name_,
- std::make_unique<vfs::Service>(
- [this](zx::channel channel, async_dispatcher_t* dispatcher) {
- shells_bindings_.AddBinding(
- this, fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider>(
- std::move(channel)));
- }));
-
- outgoing_dir_->AddEntry("svc", std::move(composed_service_dir));
-
- // Setup the component controller binding.
- if (component_controller_request) {
- component_controller_.Bind(std::move(component_controller_request));
- }
-
- // Load and use runner-specific configuration, if it exists.
- std::string json_string;
- if (dart_utils::ReadFileToString(kRunnerConfigPath, &json_string)) {
- product_config_ = FlutterRunnerProductConfiguration(json_string);
- FML_LOG(INFO) << "Successfully loaded runner configuration: "
- << json_string;
- } else {
- FML_LOG(WARNING) << "Failed to load runner configuration from "
- << kRunnerConfigPath << "; using default config values.";
- }
-
- // Load VM and component bytecode.
- // For AOT, compare with flutter_aot_app in flutter_app.gni.
- // For JIT, compare flutter_jit_runner in BUILD.gn.
- if (flutter::DartVM::IsRunningPrecompiledCode()) {
- std::shared_ptr<dart_utils::ElfSnapshot> snapshot =
- std::make_shared<dart_utils::ElfSnapshot>();
- if (snapshot->Load(component_data_directory_.get(),
- "app_aot_snapshot.so")) {
- const uint8_t* isolate_data = snapshot->IsolateData();
- const uint8_t* isolate_instructions = snapshot->IsolateInstrs();
- const uint8_t* vm_data = snapshot->VmData();
- const uint8_t* vm_instructions = snapshot->VmInstrs();
- if (isolate_data == nullptr || isolate_instructions == nullptr ||
- vm_data == nullptr || vm_instructions == nullptr) {
- FML_LOG(FATAL) << "ELF snapshot missing AOT symbols.";
- return;
- }
- auto hold_snapshot = [snapshot](const uint8_t* _, size_t __) {};
- settings_.vm_snapshot_data = [hold_snapshot, vm_data]() {
- return std::make_unique<fml::NonOwnedMapping>(vm_data, 0, hold_snapshot,
- true /* dontneed_safe */);
- };
- settings_.vm_snapshot_instr = [hold_snapshot, vm_instructions]() {
- return std::make_unique<fml::NonOwnedMapping>(
- vm_instructions, 0, hold_snapshot, true /* dontneed_safe */);
- };
- settings_.isolate_snapshot_data = [hold_snapshot, isolate_data]() {
- return std::make_unique<fml::NonOwnedMapping>(
- isolate_data, 0, hold_snapshot, true /* dontneed_safe */);
- };
- settings_.isolate_snapshot_instr = [hold_snapshot,
- isolate_instructions]() {
- return std::make_unique<fml::NonOwnedMapping>(
- isolate_instructions, 0, hold_snapshot, true /* dontneed_safe */);
- };
- isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
- std::make_shared<fml::NonOwnedMapping>(isolate_data, 0, hold_snapshot,
- true /* dontneed_safe */),
- std::make_shared<fml::NonOwnedMapping>(isolate_instructions, 0,
- hold_snapshot,
- true /* dontneed_safe */));
- } else {
- const int namespace_fd = component_data_directory_.get();
- settings_.vm_snapshot_data = [namespace_fd]() {
- return LoadFile(namespace_fd, "vm_snapshot_data.bin",
- false /* executable */);
- };
- settings_.vm_snapshot_instr = [namespace_fd]() {
- return LoadFile(namespace_fd, "vm_snapshot_instructions.bin",
- true /* executable */);
- };
- settings_.isolate_snapshot_data = [namespace_fd]() {
- return LoadFile(namespace_fd, "isolate_snapshot_data.bin",
- false /* executable */);
- };
- settings_.isolate_snapshot_instr = [namespace_fd]() {
- return LoadFile(namespace_fd, "isolate_snapshot_instructions.bin",
- true /* executable */);
- };
- }
- } else {
- settings_.vm_snapshot_data = []() {
- return MakeFileMapping("/pkg/data/vm_snapshot_data.bin",
- false /* executable */);
- };
- settings_.vm_snapshot_instr = []() {
- return MakeFileMapping("/pkg/data/vm_snapshot_instructions.bin",
- true /* executable */);
- };
-
- settings_.isolate_snapshot_data = []() {
- return MakeFileMapping("/pkg/data/isolate_core_snapshot_data.bin",
- false /* executable */);
- };
- settings_.isolate_snapshot_instr = [] {
- return MakeFileMapping("/pkg/data/isolate_core_snapshot_instructions.bin",
- true /* executable */);
- };
- }
-
-#if defined(DART_PRODUCT)
- settings_.enable_vm_service = false;
-#else
- settings_.enable_vm_service = true;
-
- // TODO(cbracken): pass this in as a param to allow 0.0.0.0, ::1, etc.
- settings_.vm_service_host = "127.0.0.1";
-#endif
-
- // Controls whether category "skia" trace events are enabled.
- settings_.trace_skia = true;
-
- settings_.verbose_logging = true;
-
- settings_.advisory_script_uri = debug_label_;
-
- settings_.advisory_script_entrypoint = debug_label_;
-
- settings_.icu_data_path = "";
-
- settings_.assets_dir = component_assets_directory_.get();
-
- // Compare flutter_jit_app in flutter_app.gni.
- settings_.application_kernel_list_asset = "app.dilplist";
-
- settings_.log_tag = debug_label_ + std::string{"(flutter)"};
-
- if (metadata.old_gen_heap_size.has_value()) {
- settings_.old_gen_heap_size = *metadata.old_gen_heap_size;
- }
-
- // No asserts in debug or release product.
- // No asserts in release with flutter_profile=true (non-product)
- // Yes asserts in non-product debug.
-#if !defined(DART_PRODUCT) && (!defined(FLUTTER_PROFILE) || !defined(NDEBUG))
- // Debug mode
- settings_.disable_dart_asserts = false;
-#else
- // Release mode
- settings_.disable_dart_asserts = true;
-#endif
-
- // Do not leak the VM; allow it to shut down normally when the last shell
- // terminates.
- settings_.leak_vm = false;
-
- settings_.task_observer_add =
- std::bind(&fml::CurrentMessageLoopAddAfterTaskObserver,
- std::placeholders::_1, std::placeholders::_2);
-
- settings_.task_observer_remove = std::bind(
- &fml::CurrentMessageLoopRemoveAfterTaskObserver, std::placeholders::_1);
-
- settings_.log_message_callback = [](const std::string& tag,
- const std::string& message) {
- if (!tag.empty()) {
- std::cout << tag << ": ";
- }
- std::cout << message << std::endl;
- };
-
- settings_.dart_flags = {};
-
- // Run in unsound null safety mode as some packages used in Integration
- // testing have not been migrated yet.
- settings_.dart_flags.push_back("--no-sound-null-safety");
-
- // Don't collect CPU samples from Dart VM C++ code.
- settings_.dart_flags.push_back("--no_profile_vm");
-
- // Scale back CPU profiler sampling period on ARM64 to avoid overloading
- // the tracing engine.
-#if defined(__aarch64__)
- settings_.dart_flags.push_back("--profile_period=10000");
-#endif // defined(__aarch64__)
-
- auto platform_task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner();
- const std::string component_url = package.resolved_url;
- settings_.unhandled_exception_callback = [weak = weak_factory_.GetWeakPtr(),
- platform_task_runner,
- runner_incoming_services,
- component_url](
- const std::string& error,
- const std::string& stack_trace) {
- if (weak) {
- // TODO(cbracken): unsafe. The above check and the PostTask below are
- // happening on the UI thread. If the Component dtor and thread
- // termination happen (on the platform thread) between the previous
- // line and the next line, a crash will occur since we'll be posting
- // to a dead thread. See Runner::OnComponentV1Terminate() in
- // runner.cc.
- platform_task_runner->PostTask([weak, runner_incoming_services,
- component_url, error, stack_trace]() {
- if (weak) {
- dart_utils::HandleException(runner_incoming_services, component_url,
- error, stack_trace);
- } else {
- FML_LOG(WARNING)
- << "Exception was thrown which was not caught in Flutter app: "
- << error;
- }
- });
- } else {
- FML_LOG(WARNING)
- << "Exception was thrown which was not caught in Flutter app: "
- << error;
- }
- // Ideally we would return whether HandleException returned ZX_OK, but
- // short of knowing if the exception was correctly handled, we return
- // false to have the error and stack trace printed in the logs.
- return false;
- };
-}
-
-ComponentV1::~ComponentV1() = default;
-
-const std::string& ComponentV1::GetDebugLabel() const {
- return debug_label_;
-}
-
-void ComponentV1::Kill() {
- component_controller_.events().OnTerminated(
- last_return_code_.second, fuchsia::sys::TerminationReason::EXITED);
-
- termination_callback_(this);
- // WARNING: Don't do anything past this point as this instance may have been
- // collected.
-}
-
-void ComponentV1::Detach() {
- component_controller_.set_error_handler(nullptr);
-}
-
-void ComponentV1::OnEngineTerminate(const Engine* shell_holder) {
- auto found = std::find_if(shell_holders_.begin(), shell_holders_.end(),
- [shell_holder](const auto& holder) {
- return holder.get() == shell_holder;
- });
-
- if (found == shell_holders_.end()) {
- // This indicates a deeper issue with memory management and should never
- // happen.
- FML_LOG(ERROR) << "Tried to terminate an unregistered shell holder.";
- FML_DCHECK(false);
-
- return;
- }
-
- // We may launch multiple shell in this component. However, we will
- // terminate when the last shell goes away. The error code return to the
- // component controller will be the last isolate that had an error.
- auto return_code = shell_holder->GetEngineReturnCode();
- if (return_code.has_value()) {
- last_return_code_ = {true, return_code.value()};
- } else {
- FML_LOG(ERROR) << "Failed to get return code from terminated shell holder.";
- }
-
- shell_holders_.erase(found);
-
- if (shell_holders_.empty()) {
- FML_VLOG(-1) << "Killing component because all shell holders have been "
- "terminated.";
- Kill();
- // WARNING: Don't do anything past this point because the delegate may have
- // collected this instance via the termination callback.
- }
-}
-
-void ComponentV1::CreateView(
- zx::eventpair token,
- fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> /*incoming_services*/,
- fidl::InterfaceHandle<
- fuchsia::sys::ServiceProvider> /*outgoing_services*/) {
- auto view_ref_pair = scenic::ViewRefPair::New();
- CreateViewWithViewRef(std::move(token), std::move(view_ref_pair.control_ref),
- std::move(view_ref_pair.view_ref));
-}
-
-void ComponentV1::CreateViewWithViewRef(
- zx::eventpair view_token,
- fuchsia::ui::views::ViewRefControl control_ref,
- fuchsia::ui::views::ViewRef view_ref) {
- if (!svc_) {
- FML_LOG(ERROR)
- << "Component incoming services was invalid when attempting to "
- "create a shell for a view provider request.";
- return;
- }
-
- shell_holders_.emplace(std::make_unique<Engine>(
- *this, // delegate
- debug_label_, // thread label
- svc_, // Component incoming services
- runner_incoming_services_, // Runner incoming services
- settings_, // settings
- scenic::ToViewToken(std::move(view_token)), // view token
- scenic::ViewRefPair{
- .control_ref = std::move(control_ref),
- .view_ref = std::move(view_ref),
- },
- std::move(fdio_ns_), // FDIO namespace
- std::move(directory_request_), // outgoing request
- product_config_, // product configuration
- dart_entrypoint_args_, // dart entrypoint args
- true // v1 component
- ));
-}
-
-void ComponentV1::CreateView2(fuchsia::ui::app::CreateView2Args view_args) {
- if (!svc_) {
- FML_LOG(ERROR)
- << "Component incoming services was invalid when attempting to "
- "create a shell for a view provider request.";
- return;
- }
-
- shell_holders_.emplace(std::make_unique<Engine>(
- *this, // delegate
- debug_label_, // thread label
- svc_, // Component incoming services
- runner_incoming_services_, // Runner incoming services
- settings_, // settings
- std::move(
- *view_args.mutable_view_creation_token()), // view creation token
- scenic::ViewRefPair::New(), // view ref pair
- std::move(fdio_ns_), // FDIO namespace
- std::move(directory_request_), // outgoing request
- product_config_, // product configuration
- dart_entrypoint_args_, // dart entrypoint args
- true // v1 component
- ));
-}
-
-#if !defined(DART_PRODUCT)
-void ComponentV1::WriteProfileToTrace() const {
- for (const auto& engine : shell_holders_) {
- engine->WriteProfileToTrace();
- }
-}
-#endif // !defined(DART_PRODUCT)
-
-} // namespace flutter_runner
diff --git a/shell/platform/fuchsia/flutter/component_v1.h b/shell/platform/fuchsia/flutter/component_v1.h
deleted file mode 100644
index efdc2a3..0000000
--- a/shell/platform/fuchsia/flutter/component_v1.h
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_COMPONENT_V1_H_
-#define FLUTTER_SHELL_PLATFORM_FUCHSIA_COMPONENT_V1_H_
-
-#include <array>
-#include <memory>
-#include <set>
-
-#include <fuchsia/io/cpp/fidl.h>
-#include <fuchsia/sys/cpp/fidl.h>
-#include <fuchsia/ui/app/cpp/fidl.h>
-#include <lib/async-loop/cpp/loop.h>
-#include <lib/async/default.h>
-#include <lib/fidl/cpp/binding_set.h>
-#include <lib/fidl/cpp/interface_request.h>
-#include <lib/fit/function.h>
-#include <lib/sys/cpp/service_directory.h>
-#include <lib/vfs/cpp/pseudo_dir.h>
-#include <lib/zx/eventpair.h>
-
-#include "flutter/common/settings.h"
-#include "flutter/fml/macros.h"
-
-#include "engine.h"
-#include "flutter_runner_product_configuration.h"
-#include "program_metadata.h"
-#include "unique_fdio_ns.h"
-
-namespace flutter_runner {
-
-class ComponentV1;
-
-struct ActiveComponentV1 {
- std::unique_ptr<fml::Thread> platform_thread;
- std::unique_ptr<ComponentV1> component;
-
- ActiveComponentV1& operator=(ActiveComponentV1&& other) noexcept {
- if (this != &other) {
- this->platform_thread.reset(other.platform_thread.release());
- this->component.reset(other.component.release());
- }
- return *this;
- }
-
- ~ActiveComponentV1() = default;
-};
-
-// Represents an instance of a CF v1 Flutter component that contains one or more
-// Flutter engine instances.
-class ComponentV1 final : public Engine::Delegate,
- public fuchsia::sys::ComponentController,
- public fuchsia::ui::app::ViewProvider {
- public:
- using TerminationCallback = fit::function<void(const ComponentV1*)>;
-
- // Creates a dedicated thread to run the component and creates the
- // component on it. The component can be accessed only on this thread.
- // This is a synchronous operation.
- static ActiveComponentV1 Create(
- TerminationCallback termination_callback,
- fuchsia::sys::Package package,
- fuchsia::sys::StartupInfo startup_info,
- std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
- fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller);
-
- // Must be called on the same thread returned from the create call. The thread
- // may be collected after.
- ~ComponentV1();
-
- static ProgramMetadata ParseProgramMetadata(
- const fidl::VectorPtr<fuchsia::sys::ProgramMetadata>& program_metadata);
-
- const std::string& GetDebugLabel() const;
-
-#if !defined(DART_PRODUCT)
- void WriteProfileToTrace() const;
-#endif // !defined(DART_PRODUCT)
-
- private:
- ComponentV1(
- TerminationCallback termination_callback,
- fuchsia::sys::Package package,
- fuchsia::sys::StartupInfo startup_info,
- std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
- fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller);
-
- // |fuchsia::sys::ComponentController|
- void Kill() override;
-
- // |fuchsia::sys::ComponentController|
- void Detach() override;
-
- // |fuchsia::ui::app::ViewProvider|
- void CreateView(
- zx::eventpair token,
- fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> incoming_services,
- fuchsia::sys::ServiceProviderHandle outgoing_services) override;
-
- // |fuchsia::ui::app::ViewProvider|
- void CreateViewWithViewRef(zx::eventpair view_token,
- fuchsia::ui::views::ViewRefControl control_ref,
- fuchsia::ui::views::ViewRef view_ref) override;
-
- // |fuchsia::ui::app::ViewProvider|
- void CreateView2(fuchsia::ui::app::CreateView2Args view_args) override;
-
- // |flutter::Engine::Delegate|
- void OnEngineTerminate(const Engine* holder) override;
-
- flutter::Settings settings_;
- FlutterRunnerProductConfiguration product_config_;
- TerminationCallback termination_callback_;
- const std::string debug_label_;
- UniqueFDIONS fdio_ns_ = UniqueFDIONSCreate();
- fml::UniqueFD component_data_directory_;
- fml::UniqueFD component_assets_directory_;
-
- fidl::Binding<fuchsia::sys::ComponentController> component_controller_;
- fuchsia::io::DirectoryPtr directory_ptr_;
- fuchsia::io::NodePtr cloned_directory_ptr_;
- fidl::InterfaceRequest<fuchsia::io::Directory> directory_request_;
- std::unique_ptr<vfs::PseudoDir> outgoing_dir_;
- std::shared_ptr<sys::ServiceDirectory> svc_;
- std::shared_ptr<sys::ServiceDirectory> runner_incoming_services_;
- fidl::BindingSet<fuchsia::ui::app::ViewProvider> shells_bindings_;
-
- fml::RefPtr<flutter::DartSnapshot> isolate_snapshot_;
- std::set<std::unique_ptr<Engine>> shell_holders_;
- std::pair<bool, uint32_t> last_return_code_;
- std::vector<std::string> dart_entrypoint_args_;
- fml::WeakPtrFactory<ComponentV1> weak_factory_; // Must be the last member.
- FML_DISALLOW_COPY_AND_ASSIGN(ComponentV1);
-};
-
-} // namespace flutter_runner
-
-#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_COMPONENT_V1_H_
diff --git a/shell/platform/fuchsia/flutter/component_v1_unittest.cc b/shell/platform/fuchsia/flutter/component_v1_unittest.cc
deleted file mode 100644
index c9abacc..0000000
--- a/shell/platform/fuchsia/flutter/component_v1_unittest.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "component_v1.h"
-
-#include <gtest/gtest.h>
-#include <optional>
-
-namespace flutter_runner {
-namespace {
-
-TEST(ComponentV1, ParseProgramMetadata) {
- // The ProgramMetadata field may be null. We should parse this as if no
- // fields were specified.
- ProgramMetadata result = ComponentV1::ParseProgramMetadata(nullptr);
-
- EXPECT_EQ(result.data_path, "");
- EXPECT_EQ(result.assets_path, "");
- EXPECT_EQ(result.old_gen_heap_size, std::nullopt);
-
- // The ProgramMetadata field may be empty. Treat this the same as null.
- fidl::VectorPtr<fuchsia::sys::ProgramMetadata> program_metadata(size_t{0});
- result = ComponentV1::ParseProgramMetadata(program_metadata);
-
- EXPECT_EQ(result.data_path, "");
- EXPECT_EQ(result.assets_path, "");
- EXPECT_EQ(result.old_gen_heap_size, std::nullopt);
-
- // The assets_path defaults to the "data" value if unspecified.
- program_metadata = {{"data", "foobar"}};
- result = ComponentV1::ParseProgramMetadata(program_metadata);
-
- EXPECT_EQ(result.data_path, "pkg/foobar");
- EXPECT_EQ(result.assets_path, "pkg/foobar");
- EXPECT_EQ(result.old_gen_heap_size, std::nullopt);
-
- // Invalid keys are ignored.
- program_metadata = {{"not_data", "foo"}, {"data", "bar"}, {"assets", "baz"}};
- result = ComponentV1::ParseProgramMetadata(program_metadata);
-
- EXPECT_EQ(result.data_path, "pkg/bar");
- EXPECT_EQ(result.assets_path, "pkg/baz");
- EXPECT_EQ(result.old_gen_heap_size, std::nullopt);
-
- // The old_gen_heap_size can be specified.
- program_metadata = {{"old_gen_heap_size", "100"}};
- result = ComponentV1::ParseProgramMetadata(program_metadata);
-
- EXPECT_EQ(result.data_path, "");
- EXPECT_EQ(result.assets_path, "");
- EXPECT_EQ(result.old_gen_heap_size, 100);
-
- // Invalid old_gen_heap_sizes should be ignored.
- program_metadata = {{"old_gen_heap_size", "asdf100"}};
- result = ComponentV1::ParseProgramMetadata(program_metadata);
-
- EXPECT_EQ(result.data_path, "");
- EXPECT_EQ(result.assets_path, "");
- EXPECT_EQ(result.old_gen_heap_size, std::nullopt);
-}
-
-} // anonymous namespace
-} // namespace flutter_runner
diff --git a/shell/platform/fuchsia/flutter/meta/aot_product_runtime b/shell/platform/fuchsia/flutter/meta/aot_product_runtime
deleted file mode 100644
index 244bbc8..0000000
--- a/shell/platform/fuchsia/flutter/meta/aot_product_runtime
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "runner": "fuchsia-pkg://fuchsia.com/flutter_aot_product_runner#meta/flutter_aot_product_runner.cmx"
-}
diff --git a/shell/platform/fuchsia/flutter/meta/aot_runtime b/shell/platform/fuchsia/flutter/meta/aot_runtime
deleted file mode 100644
index 8e1b724..0000000
--- a/shell/platform/fuchsia/flutter/meta/aot_runtime
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "runner": "fuchsia-pkg://fuchsia.com/flutter_aot_runner#meta/flutter_aot_runner.cmx"
-}
\ No newline at end of file
diff --git a/shell/platform/fuchsia/flutter/meta/flutter_aot_product_runner.cmx b/shell/platform/fuchsia/flutter/meta/flutter_aot_product_runner.cmx
deleted file mode 100644
index ec1e197..0000000
--- a/shell/platform/fuchsia/flutter/meta/flutter_aot_product_runner.cmx
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "program": {
- "data": "data"
- },
- "sandbox": {
- "features": [
- "config-data",
- "isolated-cache-storage",
- "root-ssl-certificates",
- "vulkan"
- ],
- "services": [
- "fuchsia.accessibility.semantics.SemanticsManager",
- "fuchsia.device.NameProvider",
- "fuchsia.feedback.CrashReporter",
- "fuchsia.fonts.Provider",
- "fuchsia.intl.PropertyProvider",
- "fuchsia.logger.LogSink",
- "fuchsia.memorypressure.Provider",
- "fuchsia.net.name.Lookup",
- "fuchsia.posix.socket.Provider",
- "fuchsia.sysmem.Allocator",
- "fuchsia.tracing.provider.Registry",
- "fuchsia.ui.composition.Allocator",
- "fuchsia.ui.composition.Flatland",
- "fuchsia.ui.input.ImeService",
- "fuchsia.ui.input3.Keyboard",
- "fuchsia.ui.scenic.Scenic",
- "fuchsia.ui.pointerinjector.Registry",
- "fuchsia.vulkan.loader.Loader"
- ]
- }
-}
diff --git a/shell/platform/fuchsia/flutter/meta/flutter_aot_runner.cmx b/shell/platform/fuchsia/flutter/meta/flutter_aot_runner.cmx
deleted file mode 100644
index ec1e197..0000000
--- a/shell/platform/fuchsia/flutter/meta/flutter_aot_runner.cmx
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "program": {
- "data": "data"
- },
- "sandbox": {
- "features": [
- "config-data",
- "isolated-cache-storage",
- "root-ssl-certificates",
- "vulkan"
- ],
- "services": [
- "fuchsia.accessibility.semantics.SemanticsManager",
- "fuchsia.device.NameProvider",
- "fuchsia.feedback.CrashReporter",
- "fuchsia.fonts.Provider",
- "fuchsia.intl.PropertyProvider",
- "fuchsia.logger.LogSink",
- "fuchsia.memorypressure.Provider",
- "fuchsia.net.name.Lookup",
- "fuchsia.posix.socket.Provider",
- "fuchsia.sysmem.Allocator",
- "fuchsia.tracing.provider.Registry",
- "fuchsia.ui.composition.Allocator",
- "fuchsia.ui.composition.Flatland",
- "fuchsia.ui.input.ImeService",
- "fuchsia.ui.input3.Keyboard",
- "fuchsia.ui.scenic.Scenic",
- "fuchsia.ui.pointerinjector.Registry",
- "fuchsia.vulkan.loader.Loader"
- ]
- }
-}
diff --git a/shell/platform/fuchsia/flutter/meta/flutter_jit_product_runner.cmx b/shell/platform/fuchsia/flutter/meta/flutter_jit_product_runner.cmx
deleted file mode 100644
index b0a626c..0000000
--- a/shell/platform/fuchsia/flutter/meta/flutter_jit_product_runner.cmx
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "program": {
- "data": "data"
- },
- "sandbox": {
- "features": [
- "config-data",
- "deprecated-ambient-replace-as-executable",
- "isolated-cache-storage",
- "root-ssl-certificates",
- "vulkan"
- ],
- "services": [
- "fuchsia.accessibility.semantics.SemanticsManager",
- "fuchsia.device.NameProvider",
- "fuchsia.feedback.CrashReporter",
- "fuchsia.fonts.Provider",
- "fuchsia.intl.PropertyProvider",
- "fuchsia.logger.LogSink",
- "fuchsia.memorypressure.Provider",
- "fuchsia.net.name.Lookup",
- "fuchsia.posix.socket.Provider",
- "fuchsia.sysmem.Allocator",
- "fuchsia.tracing.provider.Registry",
- "fuchsia.ui.composition.Allocator",
- "fuchsia.ui.composition.Flatland",
- "fuchsia.ui.input.ImeService",
- "fuchsia.ui.input3.Keyboard",
- "fuchsia.ui.scenic.Scenic",
- "fuchsia.ui.pointerinjector.Registry",
- "fuchsia.vulkan.loader.Loader"
- ]
- }
-}
diff --git a/shell/platform/fuchsia/flutter/meta/flutter_jit_runner.cmx b/shell/platform/fuchsia/flutter/meta/flutter_jit_runner.cmx
deleted file mode 100644
index b0a626c..0000000
--- a/shell/platform/fuchsia/flutter/meta/flutter_jit_runner.cmx
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "program": {
- "data": "data"
- },
- "sandbox": {
- "features": [
- "config-data",
- "deprecated-ambient-replace-as-executable",
- "isolated-cache-storage",
- "root-ssl-certificates",
- "vulkan"
- ],
- "services": [
- "fuchsia.accessibility.semantics.SemanticsManager",
- "fuchsia.device.NameProvider",
- "fuchsia.feedback.CrashReporter",
- "fuchsia.fonts.Provider",
- "fuchsia.intl.PropertyProvider",
- "fuchsia.logger.LogSink",
- "fuchsia.memorypressure.Provider",
- "fuchsia.net.name.Lookup",
- "fuchsia.posix.socket.Provider",
- "fuchsia.sysmem.Allocator",
- "fuchsia.tracing.provider.Registry",
- "fuchsia.ui.composition.Allocator",
- "fuchsia.ui.composition.Flatland",
- "fuchsia.ui.input.ImeService",
- "fuchsia.ui.input3.Keyboard",
- "fuchsia.ui.scenic.Scenic",
- "fuchsia.ui.pointerinjector.Registry",
- "fuchsia.vulkan.loader.Loader"
- ]
- }
-}
diff --git a/shell/platform/fuchsia/flutter/meta/jit_product_runtime b/shell/platform/fuchsia/flutter/meta/jit_product_runtime
deleted file mode 100644
index 03707e7..0000000
--- a/shell/platform/fuchsia/flutter/meta/jit_product_runtime
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "runner": "fuchsia-pkg://fuchsia.com/flutter_jit_product_runner#meta/flutter_jit_product_runner.cmx"
-}
diff --git a/shell/platform/fuchsia/flutter/meta/jit_runtime b/shell/platform/fuchsia/flutter/meta/jit_runtime
deleted file mode 100644
index d23fb95..0000000
--- a/shell/platform/fuchsia/flutter/meta/jit_runtime
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "runner": "fuchsia-pkg://fuchsia.com/flutter_jit_runner#meta/flutter_jit_runner.cmx"
-}
\ No newline at end of file
diff --git a/shell/platform/fuchsia/flutter/runner.cc b/shell/platform/fuchsia/flutter/runner.cc
index 97cb8dd..e49c689 100644
--- a/shell/platform/fuchsia/flutter/runner.cc
+++ b/shell/platform/fuchsia/flutter/runner.cc
@@ -187,8 +187,6 @@
SetThreadName("io.flutter.runner.main");
- context_->outgoing()->AddPublicService<fuchsia::sys::Runner>(
- std::bind(&Runner::RegisterComponentV1, this, std::placeholders::_1));
context_->outgoing()
->AddPublicService<fuchsia::component::runner::ComponentRunner>(
std::bind(&Runner::RegisterComponentV2, this, std::placeholders::_1));
@@ -214,82 +212,6 @@
#endif // !defined(DART_PRODUCT)
}
-// CF v1 lifecycle methods.
-
-void Runner::RegisterComponentV1(
- fidl::InterfaceRequest<fuchsia::sys::Runner> request) {
- active_components_v1_bindings_.AddBinding(this, std::move(request));
-}
-
-void Runner::StartComponent(
- fuchsia::sys::Package package,
- fuchsia::sys::StartupInfo startup_info,
- fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
- // TRACE_DURATION currently requires that the string data does not change
- // in the traced scope. Since |package| gets moved in the Component::Create
- // call below, we cannot ensure that |package.resolved_url| does not move or
- // change, so we make a copy to pass to TRACE_DURATION.
- // TODO(PT-169): Remove this copy when TRACE_DURATION reads string arguments
- // eagerly.
- std::string url_copy = package.resolved_url;
- TRACE_EVENT1("flutter", "StartComponent", "url", url_copy.c_str());
- // Notes on component termination: Components typically terminate on the
- // thread on which they were created. This usually means the thread was
- // specifically created to host the component. But we want to ensure that
- // access to the active components collection is made on the same thread. So
- // we capture the runner in the termination callback. There is no risk of
- // there being multiple component runner instances in the process at the same
- // time. So it is safe to use the raw pointer.
- ComponentV1::TerminationCallback termination_callback =
- [component_runner = this](const ComponentV1* component) {
- component_runner->task_runner_->PostTask(
- [component_runner, component]() {
- component_runner->OnComponentV1Terminate(component);
- });
- };
-
- ActiveComponentV1 active_component = ComponentV1::Create(
- std::move(termination_callback), // termination callback
- std::move(package), // component package
- std::move(startup_info), // startup info
- context_->svc(), // runner incoming services
- std::move(controller) // controller request
- );
-
- auto key = active_component.component.get();
- active_components_v1_[key] = std::move(active_component);
-}
-
-void Runner::OnComponentV1Terminate(const ComponentV1* component) {
- auto app = active_components_v1_.find(component);
- if (app == active_components_v1_.end()) {
- FML_LOG(INFO)
- << "The remote end of the component runner tried to terminate an "
- "component that has already been terminated, possibly because we "
- "initiated the termination";
- return;
- }
- ActiveComponentV1& active_component = app->second;
-
- // Grab the items out of the entry because we will have to rethread the
- // destruction.
- std::unique_ptr<ComponentV1> component_to_destroy =
- std::move(active_component.component);
- std::unique_ptr<fml::Thread> component_thread =
- std::move(active_component.platform_thread);
-
- // Delete the entry.
- active_components_v1_.erase(component);
-
- // Post the task to destroy the component and quit its message loop.
- component_thread->GetTaskRunner()->PostTask(fml::MakeCopyable(
- [instance = std::move(component_to_destroy),
- thread = component_thread.get()]() mutable { instance.reset(); }));
-
- // Terminate and join the thread's message loop.
- component_thread->Join();
-}
-
// CF v2 lifecycle methods.
void Runner::RegisterComponentV2(
@@ -409,7 +331,6 @@
latch.Wait();
}
};
- write_profile_trace_for_components(runner->active_components_v1_);
write_profile_trace_for_components(runner->active_components_v2_);
Dart_StopProfiling();
diff --git a/shell/platform/fuchsia/flutter/runner.h b/shell/platform/fuchsia/flutter/runner.h
index 2d5c711..4c077b6 100644
--- a/shell/platform/fuchsia/flutter/runner.h
+++ b/shell/platform/fuchsia/flutter/runner.h
@@ -15,7 +15,6 @@
#include <lib/trace-engine/instrumentation.h>
#include <lib/trace/observer.h>
-#include "component_v1.h"
#include "component_v2.h"
#include "flutter/fml/macros.h"
#include "fml/memory/ref_ptr.h"
@@ -25,14 +24,13 @@
namespace flutter_runner {
-/// Publishes the CF v1 and CF v2 runner services.
+/// Publishes the CF v2 runner service.
///
/// Each component will be run on a separate thread dedicated to that component.
///
/// TODO(fxb/50694): Add unit tests for CF v2.
class Runner final
- : public fuchsia::sys::Runner /* CF v1 */,
- public fuchsia::component::runner::ComponentRunner /* CF v2 */ {
+ : public fuchsia::component::runner::ComponentRunner /* CF v2 */ {
public:
// Does not take ownership of context.
Runner(fml::RefPtr<fml::TaskRunner> task_runner,
@@ -41,25 +39,6 @@
~Runner();
private:
- // CF v1 lifecycle methods.
- // TODO(fxb/50694) Deprecate these once all Flutter components have been
- // ported to CF v2.
-
- // |fuchsia::sys::Runner|
- void StartComponent(fuchsia::sys::Package package,
- fuchsia::sys::StartupInfo startup_info,
- fidl::InterfaceRequest<fuchsia::sys::ComponentController>
- controller) override;
-
- /// Registers a new CF v1 component with this runner, binding the component
- /// to this runner.
- void RegisterComponentV1(
- fidl::InterfaceRequest<fuchsia::sys::Runner> request);
-
- /// Callback that should be fired when a registered CF v2 component is
- /// terminated.
- void OnComponentV1Terminate(const ComponentV1* component);
-
// CF v2 lifecycle methods.
// |fuchsia::component::runner::ComponentRunner|
@@ -97,11 +76,6 @@
sys::ComponentContext* context_;
- // CF v1 component state.
- fidl::BindingSet<fuchsia::sys::Runner> active_components_v1_bindings_;
- std::unordered_map<const ComponentV1*, ActiveComponentV1>
- active_components_v1_;
-
// CF v2 component state.
/// The components that are currently bound to this runner.
diff --git a/shell/platform/linux/fl_platform_plugin.cc b/shell/platform/linux/fl_platform_plugin.cc
index 1507626..2a2065b 100644
--- a/shell/platform/linux/fl_platform_plugin.cc
+++ b/shell/platform/linux/fl_platform_plugin.cc
@@ -14,15 +14,25 @@
static constexpr char kBadArgumentsError[] = "Bad Arguments";
static constexpr char kUnknownClipboardFormatError[] =
"Unknown Clipboard Format";
-static constexpr char kFailedError[] = "Failed";
+static constexpr char kInProgressError[] = "In Progress";
static constexpr char kGetClipboardDataMethod[] = "Clipboard.getData";
static constexpr char kSetClipboardDataMethod[] = "Clipboard.setData";
static constexpr char kClipboardHasStringsMethod[] = "Clipboard.hasStrings";
+static constexpr char kExitApplicationMethod[] = "System.exitApplication";
+static constexpr char kRequestAppExitMethod[] = "System.requestAppExit";
static constexpr char kPlaySoundMethod[] = "SystemSound.play";
static constexpr char kSystemNavigatorPopMethod[] = "SystemNavigator.pop";
static constexpr char kTextKey[] = "text";
static constexpr char kValueKey[] = "value";
+static constexpr char kExitTypeKey[] = "type";
+static constexpr char kExitTypeCancelable[] = "cancelable";
+static constexpr char kExitTypeRequired[] = "required";
+
+static constexpr char kExitResponseKey[] = "response";
+static constexpr char kExitResponseCancel[] = "cancel";
+static constexpr char kExitResponseExit[] = "exit";
+
static constexpr char kTextPlainFormat[] = "text/plain";
static constexpr char kSoundTypeAlert[] = "SystemSoundType.alert";
@@ -32,6 +42,8 @@
GObject parent_instance;
FlMethodChannel* channel;
+ FlMethodCall* exit_application_method_call;
+ GCancellable* cancellable;
};
G_DEFINE_TYPE(FlPlatformPlugin, fl_platform_plugin, G_TYPE_OBJECT)
@@ -140,6 +152,138 @@
return nullptr;
}
+// Get the exit response from a System.requestAppExit method call.
+static gchar* get_exit_response(FlMethodResponse* response) {
+ if (response == nullptr) {
+ return nullptr;
+ }
+
+ g_autoptr(GError) error = nullptr;
+ FlValue* result = fl_method_response_get_result(response, &error);
+ if (result == nullptr) {
+ g_warning("Error returned from System.requestAppExit: %s", error->message);
+ return nullptr;
+ }
+ if (fl_value_get_type(result) != FL_VALUE_TYPE_MAP) {
+ g_warning("System.requestAppExit result argument map missing or malformed");
+ return nullptr;
+ }
+
+ FlValue* response_value = fl_value_lookup_string(result, kExitResponseKey);
+ if (fl_value_get_type(response_value) != FL_VALUE_TYPE_STRING) {
+ g_warning("Invalid response from System.requestAppExit");
+ return nullptr;
+ }
+ return g_strdup(fl_value_get_string(response_value));
+}
+
+// Quit this application
+static void quit_application() {
+ GApplication* app = g_application_get_default();
+ if (app == nullptr) {
+ // Unable to gracefully quit, so just exit the process.
+ exit(0);
+ } else {
+ g_application_quit(app);
+ }
+}
+
+// Handle response of System.requestAppExit.
+static void request_app_exit_response_cb(GObject* object,
+ GAsyncResult* result,
+ gpointer user_data) {
+ FlPlatformPlugin* self = FL_PLATFORM_PLUGIN(user_data);
+
+ g_autoptr(GError) error = nullptr;
+ g_autoptr(FlMethodResponse) method_response =
+ fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object), result,
+ &error);
+ g_autofree gchar* exit_response = nullptr;
+ if (method_response == nullptr) {
+ if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ return;
+ }
+ g_warning("Failed to complete System.requestAppExit: %s", error->message);
+ } else {
+ exit_response = get_exit_response(method_response);
+ }
+ // If something went wrong, then just exit.
+ if (exit_response == nullptr) {
+ exit_response = g_strdup(kExitResponseExit);
+ }
+
+ if (g_str_equal(exit_response, kExitResponseExit)) {
+ quit_application();
+ } else if (g_str_equal(exit_response, kExitResponseCancel)) {
+ // Canceled - no action to take.
+ }
+
+ // If request was due to a request from Flutter, pass result back.
+ if (self->exit_application_method_call != nullptr) {
+ g_autoptr(FlValue) exit_result = fl_value_new_map();
+ fl_value_set_string_take(exit_result, kExitResponseKey,
+ fl_value_new_string(exit_response));
+ g_autoptr(FlMethodResponse) exit_response =
+ FL_METHOD_RESPONSE(fl_method_success_response_new(exit_result));
+ if (!fl_method_call_respond(self->exit_application_method_call,
+ exit_response, &error)) {
+ g_warning("Failed to send response to System.exitApplication: %s",
+ error->message);
+ }
+ g_clear_object(&self->exit_application_method_call);
+ }
+}
+
+// Send a request to Flutter to exit the application.
+static void request_app_exit(FlPlatformPlugin* self, const char* type) {
+ g_autoptr(FlValue) args = fl_value_new_map();
+ fl_value_set_string_take(args, kExitTypeKey, fl_value_new_string(type));
+ fl_method_channel_invoke_method(self->channel, kRequestAppExitMethod, args,
+ self->cancellable,
+ request_app_exit_response_cb, self);
+}
+
+// Called when Flutter wants to exit the application.
+static FlMethodResponse* system_exit_application(FlPlatformPlugin* self,
+ FlMethodCall* method_call) {
+ FlValue* args = fl_method_call_get_args(method_call);
+ if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
+ return FL_METHOD_RESPONSE(fl_method_error_response_new(
+ kBadArgumentsError, "Argument map missing or malformed", nullptr));
+ }
+
+ FlValue* type_value = fl_value_lookup_string(args, kExitTypeKey);
+ if (type_value == nullptr ||
+ fl_value_get_type(type_value) != FL_VALUE_TYPE_STRING) {
+ return FL_METHOD_RESPONSE(fl_method_error_response_new(
+ kBadArgumentsError, "Missing type argument", nullptr));
+ }
+ const char* type = fl_value_get_string(type_value);
+
+ // Save method call to respond to when our request to Flutter completes.
+ if (self->exit_application_method_call != nullptr) {
+ return FL_METHOD_RESPONSE(fl_method_error_response_new(
+ kInProgressError, "Request already in progress", nullptr));
+ }
+ self->exit_application_method_call =
+ FL_METHOD_CALL(g_object_ref(method_call));
+
+ // Requested to immediately quit.
+ if (g_str_equal(type, kExitTypeRequired)) {
+ quit_application();
+ g_autoptr(FlValue) exit_result = fl_value_new_map();
+ fl_value_set_string_take(exit_result, kExitResponseKey,
+ fl_value_new_string(kExitResponseExit));
+ return FL_METHOD_RESPONSE(fl_method_success_response_new(exit_result));
+ }
+
+ // Send the request back to Flutter to follow the standard process.
+ request_app_exit(self, type);
+
+ // Will respond later.
+ return nullptr;
+}
+
// Called when Flutter wants to play a sound.
static FlMethodResponse* system_sound_play(FlPlatformPlugin* self,
FlValue* args) {
@@ -165,14 +309,7 @@
// Called when Flutter wants to quit the application.
static FlMethodResponse* system_navigator_pop(FlPlatformPlugin* self) {
- GApplication* app = g_application_get_default();
- if (app == nullptr) {
- return FL_METHOD_RESPONSE(fl_method_error_response_new(
- kFailedError, "Unable to get GApplication", nullptr));
- }
-
- g_application_quit(app);
-
+ quit_application();
return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
}
@@ -192,6 +329,8 @@
response = clipboard_get_data_async(self, method_call);
} else if (strcmp(method, kClipboardHasStringsMethod) == 0) {
response = clipboard_has_strings_async(self, method_call);
+ } else if (strcmp(method, kExitApplicationMethod) == 0) {
+ response = system_exit_application(self, method_call);
} else if (strcmp(method, kPlaySoundMethod) == 0) {
response = system_sound_play(self, args);
} else if (strcmp(method, kSystemNavigatorPopMethod) == 0) {
@@ -208,7 +347,11 @@
static void fl_platform_plugin_dispose(GObject* object) {
FlPlatformPlugin* self = FL_PLATFORM_PLUGIN(object);
+ g_cancellable_cancel(self->cancellable);
+
g_clear_object(&self->channel);
+ g_clear_object(&self->exit_application_method_call);
+ g_clear_object(&self->cancellable);
G_OBJECT_CLASS(fl_platform_plugin_parent_class)->dispose(object);
}
@@ -217,7 +360,9 @@
G_OBJECT_CLASS(klass)->dispose = fl_platform_plugin_dispose;
}
-static void fl_platform_plugin_init(FlPlatformPlugin* self) {}
+static void fl_platform_plugin_init(FlPlatformPlugin* self) {
+ self->cancellable = g_cancellable_new();
+}
FlPlatformPlugin* fl_platform_plugin_new(FlBinaryMessenger* messenger) {
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
@@ -233,3 +378,9 @@
return self;
}
+
+void fl_platform_plugin_request_app_exit(FlPlatformPlugin* self) {
+ g_return_if_fail(FL_IS_PLATFORM_PLUGIN(self));
+ // Request a cancellable exit.
+ request_app_exit(self, kExitTypeCancelable);
+}
diff --git a/shell/platform/linux/fl_platform_plugin.h b/shell/platform/linux/fl_platform_plugin.h
index 72f91ea..c25874d 100644
--- a/shell/platform/linux/fl_platform_plugin.h
+++ b/shell/platform/linux/fl_platform_plugin.h
@@ -33,6 +33,15 @@
*/
FlPlatformPlugin* fl_platform_plugin_new(FlBinaryMessenger* messenger);
+/**
+ * fl_platform_plugin_request_app_exit:
+ * @plugin: an #FlPlatformPlugin
+ *
+ * Request the application exits (i.e. due to the window being requested to be
+ * closed).
+ */
+void fl_platform_plugin_request_app_exit(FlPlatformPlugin* plugin);
+
G_END_DECLS
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_PLATFORM_PLUGIN_H_
diff --git a/shell/platform/linux/fl_platform_plugin_test.cc b/shell/platform/linux/fl_platform_plugin_test.cc
index 88051e8..0bf5b80 100644
--- a/shell/platform/linux/fl_platform_plugin_test.cc
+++ b/shell/platform/linux/fl_platform_plugin_test.cc
@@ -26,6 +26,67 @@
return false;
}
+class MethodCallMatcher {
+ public:
+ using is_gtest_matcher = void;
+
+ explicit MethodCallMatcher(::testing::Matcher<std::string> name,
+ ::testing::Matcher<FlValue*> args)
+ : name_(std::move(name)), args_(std::move(args)) {}
+
+ bool MatchAndExplain(GBytes* method_call,
+ ::testing::MatchResultListener* result_listener) const {
+ g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
+ g_autoptr(GError) error = nullptr;
+ g_autofree gchar* name = nullptr;
+ g_autoptr(FlValue) args = nullptr;
+ gboolean result = fl_method_codec_decode_method_call(
+ FL_METHOD_CODEC(codec), method_call, &name, &args, &error);
+ if (!result) {
+ *result_listener << ::testing::PrintToString(error->message);
+ return false;
+ }
+ if (!name_.MatchAndExplain(name, result_listener)) {
+ *result_listener << " where the name doesn't match: \"" << name << "\"";
+ return false;
+ }
+ if (!args_.MatchAndExplain(args, result_listener)) {
+ *result_listener << " where the args don't match: "
+ << ::testing::PrintToString(args);
+ return false;
+ }
+ return true;
+ }
+
+ void DescribeTo(std::ostream* os) const {
+ *os << "method name ";
+ name_.DescribeTo(os);
+ *os << " and args ";
+ args_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const {
+ *os << "method name ";
+ name_.DescribeNegationTo(os);
+ *os << " or args ";
+ args_.DescribeNegationTo(os);
+ }
+
+ private:
+ ::testing::Matcher<std::string> name_;
+ ::testing::Matcher<FlValue*> args_;
+};
+
+static ::testing::Matcher<GBytes*> MethodCall(
+ const std::string& name,
+ ::testing::Matcher<FlValue*> args) {
+ return MethodCallMatcher(::testing::StrEq(name), std::move(args));
+}
+
+MATCHER_P(FlValueEq, value, "equal to " + ::testing::PrintToString(value)) {
+ return fl_value_equal(arg, value);
+}
+
TEST(FlPlatformPluginTest, PlaySound) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
@@ -45,3 +106,28 @@
messenger.ReceiveMessage("flutter/platform", message);
}
+
+TEST(FlPlatformPluginTest, ExitApplication) {
+ ::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
+
+ g_autoptr(FlPlatformPlugin) plugin = fl_platform_plugin_new(messenger);
+ EXPECT_NE(plugin, nullptr);
+
+ g_autoptr(FlValue) args = fl_value_new_map();
+ fl_value_set_string_take(args, "type", fl_value_new_string("cancelable"));
+ g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
+ g_autoptr(GBytes) message = fl_method_codec_encode_method_call(
+ FL_METHOD_CODEC(codec), "System.exitApplication", args, nullptr);
+
+ g_autoptr(FlValue) requestArgs = fl_value_new_map();
+ fl_value_set_string_take(requestArgs, "type",
+ fl_value_new_string("cancelable"));
+ EXPECT_CALL(messenger,
+ fl_binary_messenger_send_on_channel(
+ ::testing::Eq<FlBinaryMessenger*>(messenger),
+ ::testing::StrEq("flutter/platform"),
+ MethodCall("System.requestAppExit", FlValueEq(requestArgs)),
+ ::testing::_, ::testing::_, ::testing::_));
+
+ messenger.ReceiveMessage("flutter/platform", message);
+}
diff --git a/shell/platform/linux/fl_view.cc b/shell/platform/linux/fl_view.cc
index cb77e0c..58f11eb 100644
--- a/shell/platform/linux/fl_view.cc
+++ b/shell/platform/linux/fl_view.cc
@@ -89,6 +89,15 @@
G_IMPLEMENT_INTERFACE(fl_text_input_view_delegate_get_type(),
fl_view_text_input_delegate_iface_init))
+// Signal handler for GtkWidget::delete-event
+static gboolean window_delete_event_cb(GtkWidget* widget,
+ GdkEvent* event,
+ FlView* self) {
+ fl_platform_plugin_request_app_exit(self->platform_plugin);
+ // Stop the event from propagating.
+ return TRUE;
+}
+
// Initialize keyboard manager.
static void init_keyboard(FlView* self) {
FlBinaryMessenger* messenger = fl_engine_get_binary_messenger(self->engine);
@@ -475,6 +484,11 @@
FlView* self = FL_VIEW(widget);
g_autoptr(GError) error = nullptr;
+ // Handle requests by the user to close the application.
+ GtkWidget* toplevel_window = gtk_widget_get_toplevel(GTK_WIDGET(self));
+ g_signal_connect(toplevel_window, "delete-event",
+ G_CALLBACK(window_delete_event_cb), self);
+
init_keyboard(self);
if (!fl_renderer_start(self->renderer, self, &error)) {
diff --git a/shell/platform/windows/accessibility_bridge_windows_unittests.cc b/shell/platform/windows/accessibility_bridge_windows_unittests.cc
index d2d4d79..089e3aa 100644
--- a/shell/platform/windows/accessibility_bridge_windows_unittests.cc
+++ b/shell/platform/windows/accessibility_bridge_windows_unittests.cc
@@ -151,11 +151,11 @@
// Add node 4: text child (with no text) of node 2.
FlutterSemanticsNode node4{sizeof(FlutterSemanticsNode), 4};
- bridge->AddFlutterSemanticsNodeUpdate(&node0);
- bridge->AddFlutterSemanticsNodeUpdate(&node1);
- bridge->AddFlutterSemanticsNodeUpdate(&node2);
- bridge->AddFlutterSemanticsNodeUpdate(&node3);
- bridge->AddFlutterSemanticsNodeUpdate(&node4);
+ bridge->AddFlutterSemanticsNodeUpdate(node0);
+ bridge->AddFlutterSemanticsNodeUpdate(node1);
+ bridge->AddFlutterSemanticsNodeUpdate(node2);
+ bridge->AddFlutterSemanticsNodeUpdate(node3);
+ bridge->AddFlutterSemanticsNodeUpdate(node4);
bridge->CommitUpdates();
}
diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc
index 8eddb3f..b49e6ec 100644
--- a/shell/platform/windows/flutter_windows_engine.cc
+++ b/shell/platform/windows/flutter_windows_engine.cc
@@ -332,14 +332,13 @@
auto host = static_cast<FlutterWindowsEngine*>(user_data);
for (size_t i = 0; i < update->nodes_count; i++) {
- const FlutterSemanticsNode* node = &update->nodes[i];
- host->accessibility_bridge_->AddFlutterSemanticsNodeUpdate(node);
+ host->accessibility_bridge_->AddFlutterSemanticsNodeUpdate(
+ update->nodes[i]);
}
for (size_t i = 0; i < update->custom_actions_count; i++) {
- const FlutterSemanticsCustomAction* action = &update->custom_actions[i];
host->accessibility_bridge_->AddFlutterSemanticsCustomActionUpdate(
- action);
+ update->custom_actions[i]);
}
host->accessibility_bridge_->CommitUpdates();
diff --git a/shell/platform/windows/flutter_windows_view_unittests.cc b/shell/platform/windows/flutter_windows_view_unittests.cc
index c057f79..bff5080 100644
--- a/shell/platform/windows/flutter_windows_view_unittests.cc
+++ b/shell/platform/windows/flutter_windows_view_unittests.cc
@@ -162,7 +162,7 @@
node.label = "name";
node.value = "value";
node.platform_view_id = -1;
- bridge->AddFlutterSemanticsNodeUpdate(&node);
+ bridge->AddFlutterSemanticsNodeUpdate(node);
bridge->CommitUpdates();
// Look up the root windows node delegate.
@@ -275,10 +275,10 @@
node3.label = "city";
node3.value = "Uji";
- bridge->AddFlutterSemanticsNodeUpdate(&node0);
- bridge->AddFlutterSemanticsNodeUpdate(&node1);
- bridge->AddFlutterSemanticsNodeUpdate(&node2);
- bridge->AddFlutterSemanticsNodeUpdate(&node3);
+ bridge->AddFlutterSemanticsNodeUpdate(node0);
+ bridge->AddFlutterSemanticsNodeUpdate(node1);
+ bridge->AddFlutterSemanticsNodeUpdate(node2);
+ bridge->AddFlutterSemanticsNodeUpdate(node3);
bridge->CommitUpdates();
// Look up the root windows node delegate.
@@ -465,8 +465,8 @@
node2.label = "prefecture";
node2.value = "Kyoto";
- bridge->AddFlutterSemanticsNodeUpdate(&node1);
- bridge->AddFlutterSemanticsNodeUpdate(&node2);
+ bridge->AddFlutterSemanticsNodeUpdate(node1);
+ bridge->AddFlutterSemanticsNodeUpdate(node2);
bridge->CommitUpdates();
// Look up the root windows node delegate.
@@ -618,10 +618,10 @@
node3.label = "city";
node3.value = "Uji";
- bridge->AddFlutterSemanticsNodeUpdate(&node0);
- bridge->AddFlutterSemanticsNodeUpdate(&node1);
- bridge->AddFlutterSemanticsNodeUpdate(&node2);
- bridge->AddFlutterSemanticsNodeUpdate(&node3);
+ bridge->AddFlutterSemanticsNodeUpdate(node0);
+ bridge->AddFlutterSemanticsNodeUpdate(node1);
+ bridge->AddFlutterSemanticsNodeUpdate(node2);
+ bridge->AddFlutterSemanticsNodeUpdate(node3);
bridge->CommitUpdates();
// Look up the root windows node delegate.
@@ -743,7 +743,7 @@
root.flags = static_cast<FlutterSemanticsFlag>(
FlutterSemanticsFlag::kFlutterSemanticsFlagHasCheckedState |
FlutterSemanticsFlag::kFlutterSemanticsFlagIsChecked);
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
@@ -782,7 +782,7 @@
// Test unchecked too.
root.flags = static_cast<FlutterSemanticsFlag>(
FlutterSemanticsFlag::kFlutterSemanticsFlagHasCheckedState);
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
{
@@ -821,7 +821,7 @@
root.flags = static_cast<FlutterSemanticsFlag>(
FlutterSemanticsFlag::kFlutterSemanticsFlagHasCheckedState |
FlutterSemanticsFlag::kFlutterSemanticsFlagIsCheckStateMixed);
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
{
@@ -889,7 +889,7 @@
root.flags = static_cast<FlutterSemanticsFlag>(
FlutterSemanticsFlag::kFlutterSemanticsFlagHasToggledState |
FlutterSemanticsFlag::kFlutterSemanticsFlagIsToggled);
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
@@ -938,7 +938,7 @@
// Test unpressed too.
root.flags = static_cast<FlutterSemanticsFlag>(
FlutterSemanticsFlag::kFlutterSemanticsFlagHasToggledState);
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
{
@@ -1006,7 +1006,7 @@
root.custom_accessibility_actions_count = 0;
root.flags = static_cast<FlutterSemanticsFlag>(
FlutterSemanticsFlag::kFlutterSemanticsFlagIsTextField);
- bridge->AddFlutterSemanticsNodeUpdate(&root);
+ bridge->AddFlutterSemanticsNodeUpdate(root);
bridge->CommitUpdates();
auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
diff --git a/sky/packages/sky_engine/LICENSE b/sky/packages/sky_engine/LICENSE
index f38346b..7cf2b9f 100644
--- a/sky/packages/sky_engine/LICENSE
+++ b/sky/packages/sky_engine/LICENSE
@@ -28049,6 +28049,38 @@
--------------------------------------------------------------------------------
skia
+Copyright 2023 Google LLC.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------------
+skia
+
Copyright 2023 The Android Open Source Project
Redistribution and use in source and binary forms, with or without
diff --git a/testing/dart/assets_test.dart b/testing/dart/assets_test.dart
index 198f952..21e0c76 100644
--- a/testing/dart/assets_test.dart
+++ b/testing/dart/assets_test.dart
@@ -70,7 +70,7 @@
/// Manually load font asset through dart.
final Uint8List encoded = utf8.encoder.convert(Uri(path: Uri.encodeFull('Roboto-Medium.ttf')).path);
final Completer<Uint8List> result = Completer<Uint8List>();
- window.sendPlatformMessage('flutter/assets', encoded.buffer.asByteData(), (ByteData? data) {
+ PlatformDispatcher.instance.sendPlatformMessage('flutter/assets', encoded.buffer.asByteData(), (ByteData? data) {
result.complete(data!.buffer.asUint8List());
});
diff --git a/testing/dart/color_test.dart b/testing/dart/color_test.dart
index 8876fa8..5d8f680 100644
--- a/testing/dart/color_test.dart
+++ b/testing/dart/color_test.dart
@@ -7,7 +7,7 @@
import 'package:litetest/litetest.dart';
class NotAColor extends Color {
- const NotAColor(int value) : super(value);
+ const NotAColor(super.value);
}
void main() {
diff --git a/testing/dart/observatory/skp_test.dart b/testing/dart/observatory/skp_test.dart
index 00c7235..239e3b5 100644
--- a/testing/dart/observatory/skp_test.dart
+++ b/testing/dart/observatory/skp_test.dart
@@ -25,7 +25,7 @@
);
final Completer<void> completer = Completer<void>();
- window.onBeginFrame = (Duration timeStamp) {
+ PlatformDispatcher.instance.onBeginFrame = (Duration timeStamp) {
final PictureRecorder recorder = PictureRecorder();
final Canvas canvas = Canvas(recorder);
canvas.drawRect(const Rect.fromLTRB(10, 10, 20, 20), Paint());
@@ -35,14 +35,11 @@
builder.addPicture(Offset.zero, picture);
final Scene scene = builder.build();
- window.render(scene);
+ PlatformDispatcher.instance.implicitView!.render(scene);
scene.dispose();
- // window.onBeginFrame = (Duration timeStamp) {
- completer.complete();
- // };
- // window.scheduleFrame();
+ completer.complete();
};
- window.scheduleFrame();
+ PlatformDispatcher.instance.scheduleFrame();
await completer.future;
final vms.Response response = await vmService.callServiceExtension('_flutter.screenshotSkp');
diff --git a/testing/dart/observatory/tracing_test.dart b/testing/dart/observatory/tracing_test.dart
index 6f709bf..9c9f961 100644
--- a/testing/dart/observatory/tracing_test.dart
+++ b/testing/dart/observatory/tracing_test.dart
@@ -23,7 +23,7 @@
);
final Completer<void> completer = Completer<void>();
- window.onBeginFrame = (Duration timeStamp) async {
+ PlatformDispatcher.instance.onBeginFrame = (Duration timeStamp) async {
final PictureRecorder recorder = PictureRecorder();
final Canvas canvas = Canvas(recorder);
canvas.drawColor(const Color(0xff0000ff), BlendMode.srcOut);
@@ -45,7 +45,7 @@
scene.dispose();
completer.complete();
};
- window.scheduleFrame();
+ PlatformDispatcher.instance.scheduleFrame();
await completer.future;
final vms.Timeline timeline = await vmService.getVMTimeline();
diff --git a/testing/dart/observatory/vmservice_methods_test.dart b/testing/dart/observatory/vmservice_methods_test.dart
index e74caac..7ba1565 100644
--- a/testing/dart/observatory/vmservice_methods_test.dart
+++ b/testing/dart/observatory/vmservice_methods_test.dart
@@ -75,7 +75,7 @@
}
final Completer<PlatformResponse> completer = Completer<PlatformResponse>();
- ui.window.onPlatformMessage = (String name, ByteData? data, ui.PlatformMessageResponseCallback? callback) {
+ ui.PlatformDispatcher.instance.onPlatformMessage = (String name, ByteData? data, ui.PlatformMessageResponseCallback? callback) {
final ByteBuffer buffer = data!.buffer;
final Uint8List list = buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
completer.complete(PlatformResponse(name: name, contents: utf8.decode(list)));
diff --git a/testing/dart/platform_view_test.dart b/testing/dart/platform_view_test.dart
index c234e63..146c865 100644
--- a/testing/dart/platform_view_test.dart
+++ b/testing/dart/platform_view_test.dart
@@ -12,7 +12,7 @@
builder.addPlatformView(1);
final Scene scene = builder.build();
- window.render(scene);
+ PlatformDispatcher.instance.implicitView!.render(scene);
scene.dispose();
// Test harness asserts that this does not emit an error from the shell logs.
});
diff --git a/testing/dart/pubspec.yaml b/testing/dart/pubspec.yaml
index 971314f..cebfd58 100644
--- a/testing/dart/pubspec.yaml
+++ b/testing/dart/pubspec.yaml
@@ -14,7 +14,7 @@
# relative to this directory into //third_party/dart
environment:
- sdk: '>=2.12.0 <3.0.0'
+ sdk: '>=2.17.0 <3.0.0'
dependencies:
litetest: any
diff --git a/testing/dart/text_test.dart b/testing/dart/text_test.dart
index e0f9c82..db23069 100644
--- a/testing/dart/text_test.dart
+++ b/testing/dart/text_test.dart
@@ -195,10 +195,10 @@
void testLoadFontFromList() {
test('loadFontFromList will send platform message after font is loaded', () async {
- final PlatformMessageCallback? oldHandler = window.onPlatformMessage;
+ final PlatformMessageCallback? oldHandler = PlatformDispatcher.instance.onPlatformMessage;
late String actualName;
late String message;
- window.onPlatformMessage = (String name, ByteData? data, PlatformMessageResponseCallback? callback) {
+ PlatformDispatcher.instance.onPlatformMessage = (String name, ByteData? data, PlatformMessageResponseCallback? callback) {
assert(data != null);
actualName = name;
final Uint8List list = data!.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
@@ -206,7 +206,7 @@
};
final Uint8List fontData = Uint8List(0);
await loadFontFromList(fontData, fontFamily: 'fake');
- window.onPlatformMessage = oldHandler;
+ PlatformDispatcher.instance.onPlatformMessage = oldHandler;
expect(actualName, 'flutter/system');
expect(message, '{"type":"fontsChange"}');
});
diff --git a/testing/dart/window_test.dart b/testing/dart/window_test.dart
index 66bcefa..018c72a 100644
--- a/testing/dart/window_test.dart
+++ b/testing/dart/window_test.dart
@@ -12,7 +12,7 @@
test('window.sendPlatformMessage preserves callback zone', () {
runZoned(() {
final Zone innerZone = Zone.current;
- window.sendPlatformMessage('test', ByteData.view(Uint8List(0).buffer), expectAsync1((ByteData? data) {
+ PlatformDispatcher.instance.sendPlatformMessage('test', ByteData.view(Uint8List(0).buffer), expectAsync1((ByteData? data) {
final Zone runZone = Zone.current;
expect(runZone, isNotNull);
expect(runZone, same(innerZone));
@@ -76,7 +76,7 @@
const Locale.fromSubtags(languageCode: 'en'),
];
// The default implementation returns null due to lack of a real platform.
- final Locale? result = window.computePlatformResolvedLocale(supportedLocales);
+ final Locale? result = PlatformDispatcher.instance.computePlatformResolvedLocale(supportedLocales);
expect(result, null);
});
}
diff --git a/tools/activate_emsdk.py b/tools/activate_emsdk.py
index 30fd1b0..9b4e3ae 100644
--- a/tools/activate_emsdk.py
+++ b/tools/activate_emsdk.py
@@ -9,7 +9,9 @@
import subprocess
import sys
-EMSDK_ROOT = os.path.join('src', 'buildtools', 'emsdk')
+EMSDK_ROOT = os.path.abspath(
+ os.path.join(__file__, '..', '..', '..', 'buildtools', 'emsdk')
+)
EMSDK_PATH = os.path.join(EMSDK_ROOT, 'emsdk.py')
diff --git a/tools/fuchsia/flutter/flutter_build_config.gni b/tools/fuchsia/flutter/flutter_build_config.gni
index b7c033a..a322a7e 100644
--- a/tools/fuchsia/flutter/flutter_build_config.gni
+++ b/tools/fuchsia/flutter/flutter_build_config.gni
@@ -12,7 +12,6 @@
# Builds the component in a non-product JIT build. This will
# launch the vm service in the runner.
flutter_debug_build_cfg = {
- runtime_meta = "//flutter/shell/platform/fuchsia/flutter/meta/jit_runtime"
runner_dep = "//flutter/shell/platform/fuchsia/flutter:flutter_jit_runner"
platform_name = "flutter_runner"
is_aot = false
@@ -25,7 +24,6 @@
# This configuration is not compatible with a --release build since the
# profile aot runner is built without asserts.
flutter_aot_debug_build_cfg = {
- runtime_meta = "//flutter/shell/platform/fuchsia/flutter/meta/aot_runtime"
runner_dep = "//flutter/shell/platform/fuchsia/flutter:flutter_aot_runner"
platform_name = "flutter_runner"
is_aot = true
@@ -36,9 +34,6 @@
# Builds the component in a non-product AOT build. This will
# launch the vm service in the runner.
flutter_profile_build_cfg = {
- runtime_meta =
- "//flutter/shell/platform/fuchsia/flutter/meta/aot_runtime" # profile
- # runner
runner_dep = "//flutter/shell/platform/fuchsia/flutter:flutter_aot_runner"
platform_name = "flutter_runner"
is_aot = true
@@ -49,8 +44,6 @@
# Builds the component in a product JIT build. This will
# not launch the vm service in the runner.
flutter_jit_release_build_cfg = {
- runtime_meta =
- "//flutter/shell/platform/fuchsia/flutter/meta/jit_product_runtime"
runner_dep =
"//flutter/shell/platform/fuchsia/flutter:flutter_jit_product_runner"
platform_name = "flutter_runner"
@@ -62,8 +55,6 @@
# Builds the component in a product AOT build. This will
# not launch the vm service in the runner.
flutter_release_build_cfg = {
- runtime_meta =
- "//flutter/shell/platform/fuchsia/flutter/meta/aot_product_runtime"
runner_dep =
"//flutter/shell/platform/fuchsia/flutter:flutter_aot_product_runner"
platform_name = "flutter_runner"
diff --git a/tools/gn b/tools/gn
index 4aa78f2..b893752 100755
--- a/tools/gn
+++ b/tools/gn
@@ -380,6 +380,10 @@
else:
gn_args['dart_runtime_mode'] = runtime_mode
+ # If we are building the dart sdk in-tree, exclude the wasm-opt target, as
+ # it doesn't build properly with our gn configuration.
+ gn_args['dart_include_wasm_opt'] = False
+
# Desktop embeddings can have more dependencies than the engine library,
# which can be problematic in some build environments (e.g., building on
# Linux will bring in pkg-config dependencies at generation time). These