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