Cherry pick of revert (#132174)

CP: 2728ba0f23aeed05ae752cdd60e940dadf942ddf
diff --git a/dev/integration_tests/flutter_gallery/lib/demo/cupertino/cupertino_navigation_demo.dart b/dev/integration_tests/flutter_gallery/lib/demo/cupertino/cupertino_navigation_demo.dart
index a68c2a1..f6626b8 100644
--- a/dev/integration_tests/flutter_gallery/lib/demo/cupertino/cupertino_navigation_demo.dart
+++ b/dev/integration_tests/flutter_gallery/lib/demo/cupertino/cupertino_navigation_demo.dart
@@ -48,9 +48,9 @@
 
   @override
   Widget build(BuildContext context) {
-    return PopScope(
+    return WillPopScope(
       // Prevent swipe popping of this page. Use explicit exit buttons only.
-      canPop: false,
+      onWillPop: () => Future<bool>.value(true),
       child: DefaultTextStyle(
         style: CupertinoTheme.of(context).textTheme.textStyle,
         child: CupertinoTabScaffold(
diff --git a/dev/integration_tests/flutter_gallery/lib/demo/material/full_screen_dialog_demo.dart b/dev/integration_tests/flutter_gallery/lib/demo/material/full_screen_dialog_demo.dart
index 81ee4da..b6f7bbe 100644
--- a/dev/integration_tests/flutter_gallery/lib/demo/material/full_screen_dialog_demo.dart
+++ b/dev/integration_tests/flutter_gallery/lib/demo/material/full_screen_dialog_demo.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
 import 'package:intl/intl.dart';
 
 // This demo is based on
@@ -110,15 +109,16 @@
   bool _hasName = false;
   late String _eventName;
 
-  Future<void> _handlePopInvoked(bool didPop) async {
-    if (didPop) {
-      return;
+  Future<bool> _onWillPop() async {
+    _saveNeeded = _hasLocation || _hasName || _saveNeeded;
+    if (!_saveNeeded) {
+      return true;
     }
 
     final ThemeData theme = Theme.of(context);
     final TextStyle dialogTextStyle = theme.textTheme.titleMedium!.copyWith(color: theme.textTheme.bodySmall!.color);
 
-    final bool? shouldDiscard = await showDialog<bool>(
+    return showDialog<bool>(
       context: context,
       builder: (BuildContext context) {
         return AlertDialog(
@@ -130,31 +130,19 @@
             TextButton(
               child: const Text('CANCEL'),
               onPressed: () {
-                // Pop the confirmation dialog and indicate that the page should
-                // not be popped.
-                Navigator.of(context).pop(false);
+                Navigator.of(context).pop(false); // Pops the confirmation dialog but not the page.
               },
             ),
             TextButton(
               child: const Text('DISCARD'),
               onPressed: () {
-                // Pop the confirmation dialog and indicate that the page should
-                // be popped, too.
-                Navigator.of(context).pop(true);
+                Navigator.of(context).pop(true); // Returning true to _onWillPop will pop again.
               },
             ),
           ],
         );
       },
-    );
-
-    if (shouldDiscard ?? false) {
-      // Since this is the root route, quit the app where possible by invoking
-      // the SystemNavigator. If this wasn't the root route, then
-      // Navigator.maybePop could be used instead.
-      // See https://github.com/flutter/flutter/issues/11490
-      SystemNavigator.pop();
-    }
+    ) as Future<bool>;
   }
 
   @override
@@ -174,8 +162,7 @@
         ],
       ),
       body: Form(
-        canPop: !_saveNeeded && !_hasLocation && !_hasName,
-        onPopInvoked: _handlePopInvoked,
+        onWillPop: _onWillPop,
         child: Scrollbar(
           child: ListView(
             primary: true,
diff --git a/dev/integration_tests/flutter_gallery/lib/demo/material/text_form_field_demo.dart b/dev/integration_tests/flutter_gallery/lib/demo/material/text_form_field_demo.dart
index c6f644e..5d3fee8 100644
--- a/dev/integration_tests/flutter_gallery/lib/demo/material/text_form_field_demo.dart
+++ b/dev/integration_tests/flutter_gallery/lib/demo/material/text_form_field_demo.dart
@@ -143,9 +143,10 @@
     return null;
   }
 
-  Future<void> _handlePopInvoked(bool didPop) async {
-    if (didPop) {
-      return;
+  Future<bool> _warnUserAboutInvalidData() async {
+    final FormState? form = _formKey.currentState;
+    if (form == null || !_formWasEdited || form.validate()) {
+      return true;
     }
 
     final bool? result = await showDialog<bool>(
@@ -167,14 +168,7 @@
         );
       },
     );
-
-    if (result ?? false) {
-      // Since this is the root route, quit the app where possible by invoking
-      // the SystemNavigator. If this wasn't the root route, then
-      // Navigator.maybePop could be used instead.
-      // See https://github.com/flutter/flutter/issues/11490
-      SystemNavigator.pop();
-    }
+    return result!;
   }
 
   @override
@@ -191,8 +185,7 @@
         child: Form(
           key: _formKey,
           autovalidateMode: _autovalidateMode,
-          canPop: _formKey.currentState == null || !_formWasEdited || _formKey.currentState!.validate(),
-          onPopInvoked: _handlePopInvoked,
+          onWillPop: _warnUserAboutInvalidData,
           child: Scrollbar(
             child: SingleChildScrollView(
               primary: true,
diff --git a/dev/integration_tests/flutter_gallery/lib/demo/shrine/expanding_bottom_sheet.dart b/dev/integration_tests/flutter_gallery/lib/demo/shrine/expanding_bottom_sheet.dart
index de2cfa4..0391ef9 100644
--- a/dev/integration_tests/flutter_gallery/lib/demo/shrine/expanding_bottom_sheet.dart
+++ b/dev/integration_tests/flutter_gallery/lib/demo/shrine/expanding_bottom_sheet.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
 import 'package:scoped_model/scoped_model.dart';
 
 import 'colors.dart';
@@ -360,12 +361,14 @@
 
   // Closes the cart if the cart is open, otherwise exits the app (this should
   // only be relevant for Android).
-  void _handlePopInvoked(bool didPop) {
-    if (didPop) {
-      return;
+  Future<bool> _onWillPop() async {
+    if (!_isOpen) {
+      await SystemNavigator.pop();
+      return true;
     }
 
     close();
+    return true;
   }
 
   @override
@@ -375,9 +378,8 @@
       duration: const Duration(milliseconds: 225),
       curve: Curves.easeInOut,
       alignment: FractionalOffset.topLeft,
-      child: PopScope(
-        canPop: !_isOpen,
-        onPopInvoked: _handlePopInvoked,
+      child: WillPopScope(
+        onWillPop: _onWillPop,
         child: AnimatedBuilder(
           animation: widget.hideController,
           builder: _buildSlideAnimation,
diff --git a/dev/integration_tests/flutter_gallery/lib/gallery/home.dart b/dev/integration_tests/flutter_gallery/lib/gallery/home.dart
index 4a5f01f..c661ce6 100644
--- a/dev/integration_tests/flutter_gallery/lib/gallery/home.dart
+++ b/dev/integration_tests/flutter_gallery/lib/gallery/home.dart
@@ -325,14 +325,14 @@
       backgroundColor: isDark ? _kFlutterBlue : theme.primaryColor,
       body: SafeArea(
         bottom: false,
-        child: PopScope(
-          canPop: _category == null,
-          onPopInvoked: (bool didPop) {
-            if (didPop) {
-              return;
-            }
+        child: WillPopScope(
+          onWillPop: () {
             // Pop the category page if Android back button is pressed.
-            setState(() => _category = null);
+            if (_category != null) {
+              setState(() => _category = null);
+              return Future<bool>.value(false);
+            }
+            return Future<bool>.value(true);
           },
           child: Backdrop(
             backTitle: const Text('Options'),
diff --git a/examples/api/lib/material/navigation_bar/navigation_bar.2.dart b/examples/api/lib/material/navigation_bar/navigation_bar.2.dart
index 981eb5d..7af02cf 100644
--- a/examples/api/lib/material/navigation_bar/navigation_bar.2.dart
+++ b/examples/api/lib/material/navigation_bar/navigation_bar.2.dart
@@ -71,10 +71,14 @@
 
   @override
   Widget build(BuildContext context) {
-    return NavigatorPopHandler(
-      onPop: () {
+    return WillPopScope(
+      onWillPop: () async {
         final NavigatorState navigator = navigatorKeys[selectedIndex].currentState!;
+        if (!navigator.canPop()) {
+          return true;
+        }
         navigator.pop();
+        return false;
       },
       child: Scaffold(
         body: SafeArea(
diff --git a/examples/api/lib/widgets/form/form.1.dart b/examples/api/lib/widgets/form/form.1.dart
deleted file mode 100644
index b5e8b6e..0000000
--- a/examples/api/lib/widgets/form/form.1.dart
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2014 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.
-
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-
-/// This sample demonstrates showing a confirmation dialog when the user
-/// attempts to navigate away from a page with unsaved [Form] data.
-
-void main() => runApp(const FormApp());
-
-class FormApp extends StatelessWidget {
-  const FormApp({
-    super.key,
-  });
-
-  @override
-  Widget build(BuildContext context) {
-    return MaterialApp(
-      home: Scaffold(
-        appBar: AppBar(
-          title: const Text('Confirmation Dialog Example'),
-        ),
-        body: Center(
-          child: _SaveableForm(),
-        ),
-      ),
-    );
-  }
-}
-
-class _SaveableForm extends StatefulWidget {
-  @override
-  State<_SaveableForm> createState() => _SaveableFormState();
-}
-
-class _SaveableFormState extends State<_SaveableForm> {
-  final TextEditingController _controller = TextEditingController();
-  String _savedValue = '';
-  bool _isDirty = false;
-
-  @override
-  void initState() {
-    super.initState();
-    _controller.addListener(_onChanged);
-  }
-
-  @override
-  void dispose() {
-    _controller.removeListener(_onChanged);
-    super.dispose();
-  }
-
-  void _onChanged() {
-    final bool nextIsDirty = _savedValue != _controller.text;
-    if (nextIsDirty == _isDirty) {
-      return;
-    }
-    setState(() {
-      _isDirty = nextIsDirty;
-    });
-  }
-
-  Future<void> _showDialog() async {
-    final bool? shouldDiscard = await showDialog<bool>(
-      context: context,
-      builder: (BuildContext context) {
-        return AlertDialog(
-          title: const Text('Are you sure?'),
-          content: const Text('Any unsaved changes will be lost!'),
-          actions: <Widget>[
-            TextButton(
-              child: const Text('Yes, discard my changes'),
-              onPressed: () {
-                Navigator.pop(context, true);
-              },
-            ),
-            TextButton(
-              child: const Text('No, continue editing'),
-              onPressed: () {
-                Navigator.pop(context, false);
-              },
-            ),
-          ],
-        );
-      },
-    );
-
-    if (shouldDiscard ?? false) {
-      // Since this is the root route, quit the app where possible by invoking
-      // the SystemNavigator. If this wasn't the root route, then
-      // Navigator.maybePop could be used instead.
-      // See https://github.com/flutter/flutter/issues/11490
-      SystemNavigator.pop();
-    }
-  }
-
-  void _save(String? value) {
-    setState(() {
-      _savedValue = value ?? '';
-    });
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Center(
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.center,
-        children: <Widget>[
-          const Text('If the field below is unsaved, a confirmation dialog will be shown on back.'),
-          const SizedBox(height: 20.0),
-          Form(
-            canPop: !_isDirty,
-            onPopInvoked: (bool didPop) {
-              if (didPop) {
-                return;
-              }
-              _showDialog();
-            },
-            autovalidateMode: AutovalidateMode.always,
-            child: Column(
-              mainAxisAlignment: MainAxisAlignment.center,
-              children: <Widget>[
-                TextFormField(
-                  controller: _controller,
-                  onFieldSubmitted: (String? value) {
-                    _save(value);
-                  },
-                ),
-                TextButton(
-                  onPressed: () {
-                    _save(_controller.text);
-                  },
-                  child: Row(
-                    children: <Widget>[
-                      const Text('Save'),
-                      if (_controller.text.isNotEmpty)
-                        Icon(
-                          _isDirty ? Icons.warning : Icons.check,
-                        ),
-                    ],
-                  ),
-                ),
-              ],
-            ),
-          ),
-          TextButton(
-            onPressed: () {
-              if (_isDirty) {
-                _showDialog();
-                return;
-              }
-              // Since this is the root route, quit the app where possible by
-              // invoking the SystemNavigator. If this wasn't the root route,
-              // then Navigator.maybePop could be used instead.
-              // See https://github.com/flutter/flutter/issues/11490
-              SystemNavigator.pop();
-            },
-            child: const Text('Go back'),
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/examples/api/lib/widgets/navigator_pop_handler/navigator_pop_handler.0.dart b/examples/api/lib/widgets/navigator_pop_handler/navigator_pop_handler.0.dart
deleted file mode 100644
index d81b74f..0000000
--- a/examples/api/lib/widgets/navigator_pop_handler/navigator_pop_handler.0.dart
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2014 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.
-
-import 'package:flutter/material.dart';
-
-/// This sample demonstrates using [NavigatorPopHandler] to handle system back
-/// gestures when there are nested [Navigator] widgets by delegating to the
-/// current [Navigator].
-
-void main() => runApp(const NavigatorPopHandlerApp());
-
-class NavigatorPopHandlerApp extends StatelessWidget {
-  const NavigatorPopHandlerApp({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return MaterialApp(
-      initialRoute: '/',
-      routes: <String, WidgetBuilder>{
-        '/': (BuildContext context) => _HomePage(),
-        '/nested_navigators': (BuildContext context) => const NestedNavigatorsPage(),
-      },
-    );
-  }
-}
-
-class _HomePage extends StatelessWidget {
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      appBar: AppBar(
-        title: const Text('Nested Navigators Example'),
-      ),
-      body: Center(
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: <Widget>[
-            const Text('Home Page'),
-            const Text('A system back gesture here will exit the app.'),
-            const SizedBox(height: 20.0),
-            ListTile(
-              title: const Text('Nested Navigator route'),
-              subtitle: const Text('This route has another Navigator widget in addition to the one inside MaterialApp above.'),
-              onTap: () {
-                Navigator.of(context).pushNamed('/nested_navigators');
-              },
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}
-
-class NestedNavigatorsPage extends StatefulWidget {
-  const NestedNavigatorsPage({super.key});
-
-  @override
-  State<NestedNavigatorsPage> createState() => _NestedNavigatorsPageState();
-}
-
-class _NestedNavigatorsPageState extends State<NestedNavigatorsPage> {
-  final GlobalKey<NavigatorState> _nestedNavigatorKey = GlobalKey<NavigatorState>();
-
-  @override
-  Widget build(BuildContext context) {
-    return NavigatorPopHandler(
-      onPop: () {
-        _nestedNavigatorKey.currentState!.maybePop();
-      },
-      child: Navigator(
-        key: _nestedNavigatorKey,
-        initialRoute: 'nested_navigators/one',
-        onGenerateRoute: (RouteSettings settings) {
-          switch (settings.name) {
-            case 'nested_navigators/one':
-              final BuildContext rootContext = context;
-              return MaterialPageRoute<void>(
-                builder: (BuildContext context) => NestedNavigatorsPageOne(
-                  onBack: () {
-                    Navigator.of(rootContext).pop();
-                  },
-                ),
-              );
-            case 'nested_navigators/one/another_one':
-              return MaterialPageRoute<void>(
-                builder: (BuildContext context) => const NestedNavigatorsPageTwo(
-                ),
-              );
-            default:
-              throw Exception('Invalid route: ${settings.name}');
-          }
-        },
-      ),
-    );
-  }
-}
-
-class NestedNavigatorsPageOne extends StatelessWidget {
-  const NestedNavigatorsPageOne({
-    required this.onBack,
-    super.key,
-  });
-
-  final VoidCallback onBack;
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      backgroundColor: Colors.grey,
-      body: Center(
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: <Widget>[
-            const Text('Nested Navigators Page One'),
-            const Text('A system back here returns to the home page.'),
-            TextButton(
-              onPressed: () {
-                Navigator.of(context).pushNamed('nested_navigators/one/another_one');
-              },
-              child: const Text('Go to another route in this nested Navigator'),
-            ),
-            TextButton(
-              // Can't use Navigator.of(context).pop() because this is the root
-              // route, so it can't be popped. The Navigator above this needs to
-              // be popped.
-              onPressed: onBack,
-              child: const Text('Go back'),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}
-
-class NestedNavigatorsPageTwo extends StatelessWidget {
-  const NestedNavigatorsPageTwo({
-    super.key,
-  });
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      backgroundColor: Colors.grey.withBlue(180),
-      body: Center(
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: <Widget>[
-            const Text('Nested Navigators Page Two'),
-            const Text('A system back here will go back to Nested Navigators Page One'),
-            TextButton(
-              onPressed: () {
-                Navigator.of(context).pop();
-              },
-              child: const Text('Go back'),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}
diff --git a/examples/api/lib/widgets/navigator_pop_handler/navigator_pop_handler.1.dart b/examples/api/lib/widgets/navigator_pop_handler/navigator_pop_handler.1.dart
deleted file mode 100644
index 04fbded..0000000
--- a/examples/api/lib/widgets/navigator_pop_handler/navigator_pop_handler.1.dart
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright 2014 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.
-
-// This sample demonstrates nested navigation in a bottom navigation bar.
-
-import 'package:flutter/material.dart';
-
-// There are three possible tabs.
-enum _Tab {
-  home,
-  one,
-  two,
-}
-
-// Each tab has two possible pages.
-enum _TabPage {
-  home,
-  one,
-}
-
-typedef _TabPageCallback = void Function(List<_TabPage> pages);
-
-void main() => runApp(const NavigatorPopHandlerApp());
-
-class NavigatorPopHandlerApp extends StatelessWidget {
-  const NavigatorPopHandlerApp({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return MaterialApp(
-      initialRoute: '/home',
-      routes: <String, WidgetBuilder>{
-        '/home': (BuildContext context) => const _BottomNavPage(
-        ),
-      },
-    );
-  }
-}
-
-class _BottomNavPage extends StatefulWidget {
-  const _BottomNavPage();
-
-  @override
-  State<_BottomNavPage> createState() => _BottomNavPageState();
-}
-
-class _BottomNavPageState extends State<_BottomNavPage> {
-  _Tab _tab = _Tab.home;
-
-  final GlobalKey _tabHomeKey = GlobalKey();
-  final GlobalKey _tabOneKey = GlobalKey();
-  final GlobalKey _tabTwoKey = GlobalKey();
-
-  List<_TabPage> _tabHomePages = <_TabPage>[_TabPage.home];
-  List<_TabPage> _tabOnePages = <_TabPage>[_TabPage.home];
-  List<_TabPage> _tabTwoPages = <_TabPage>[_TabPage.home];
-
-  BottomNavigationBarItem _itemForPage(_Tab page) {
-    switch (page) {
-      case _Tab.home:
-        return const BottomNavigationBarItem(
-          icon: Icon(Icons.home),
-          label: 'Go to Home',
-        );
-      case _Tab.one:
-        return const BottomNavigationBarItem(
-          icon: Icon(Icons.one_k),
-          label: 'Go to One',
-        );
-      case _Tab.two:
-        return const BottomNavigationBarItem(
-          icon: Icon(Icons.two_k),
-          label: 'Go to Two',
-        );
-    }
-  }
-
-  Widget _getPage(_Tab page) {
-    switch (page) {
-      case _Tab.home:
-        return _BottomNavTab(
-          key: _tabHomeKey,
-          title: 'Home Tab',
-          color: Colors.grey,
-          pages: _tabHomePages,
-          onChangedPages: (List<_TabPage> pages) {
-            setState(() {
-              _tabHomePages = pages;
-            });
-          },
-        );
-      case _Tab.one:
-        return _BottomNavTab(
-          key: _tabOneKey,
-          title: 'Tab One',
-          color: Colors.amber,
-          pages: _tabOnePages,
-          onChangedPages: (List<_TabPage> pages) {
-            setState(() {
-              _tabOnePages = pages;
-            });
-          },
-        );
-      case _Tab.two:
-        return _BottomNavTab(
-          key: _tabTwoKey,
-          title: 'Tab Two',
-          color: Colors.blueGrey,
-          pages: _tabTwoPages,
-          onChangedPages: (List<_TabPage> pages) {
-            setState(() {
-              _tabTwoPages = pages;
-            });
-          },
-        );
-    }
-  }
-
-  void _onItemTapped(int index) {
-    setState(() {
-      _tab = _Tab.values.elementAt(index);
-    });
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      body: Center(
-        child: _getPage(_tab),
-      ),
-      bottomNavigationBar: BottomNavigationBar(
-        items: _Tab.values.map(_itemForPage).toList(),
-        currentIndex: _Tab.values.indexOf(_tab),
-        selectedItemColor: Colors.amber[800],
-        onTap: _onItemTapped,
-      ),
-    );
-  }
-}
-
-class _BottomNavTab extends StatefulWidget {
-  const _BottomNavTab({
-    super.key,
-    required this.color,
-    required this.onChangedPages,
-    required this.pages,
-    required this.title,
-  });
-
-  final Color color;
-  final _TabPageCallback onChangedPages;
-  final List<_TabPage> pages;
-  final String title;
-
-  @override
-  State<_BottomNavTab> createState() => _BottomNavTabState();
-}
-
-class _BottomNavTabState extends State<_BottomNavTab> {
-  final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
-
-  @override
-  Widget build(BuildContext context) {
-    return NavigatorPopHandler(
-      onPop: () {
-        _navigatorKey.currentState?.maybePop();
-      },
-      child: Navigator(
-        key: _navigatorKey,
-        onPopPage: (Route<void> route, void result) {
-          if (!route.didPop(null)) {
-            return false;
-          }
-          widget.onChangedPages(<_TabPage>[
-            ...widget.pages,
-          ]..removeLast());
-          return true;
-        },
-        pages: widget.pages.map((_TabPage page) {
-          switch (page) {
-            case _TabPage.home:
-              return MaterialPage<void>(
-                child: _LinksPage(
-                  title: 'Bottom nav - tab ${widget.title} - route $page',
-                  backgroundColor: widget.color,
-                  buttons: <Widget>[
-                    TextButton(
-                      onPressed: () {
-                        widget.onChangedPages(<_TabPage>[
-                          ...widget.pages,
-                          _TabPage.one,
-                        ]);
-                      },
-                      child: const Text('Go to another route in this nested Navigator'),
-                    ),
-                  ],
-                ),
-              );
-            case _TabPage.one:
-              return MaterialPage<void>(
-                child: _LinksPage(
-                  backgroundColor: widget.color,
-                  title: 'Bottom nav - tab ${widget.title} - route $page',
-                  buttons: <Widget>[
-                    TextButton(
-                      onPressed: () {
-                        widget.onChangedPages(<_TabPage>[
-                          ...widget.pages,
-                        ]..removeLast());
-                      },
-                      child: const Text('Go back'),
-                    ),
-                  ],
-                ),
-              );
-          }
-        }).toList(),
-      ),
-    );
-  }
-}
-
-class _LinksPage extends StatelessWidget {
-  const _LinksPage ({
-    required this.backgroundColor,
-    this.buttons = const <Widget>[],
-    required this.title,
-  });
-
-  final Color backgroundColor;
-  final List<Widget> buttons;
-  final String title;
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      backgroundColor: backgroundColor,
-      body: Center(
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: <Widget>[
-            Text(title),
-            ...buttons,
-          ],
-        ),
-      ),
-    );
-  }
-}
diff --git a/examples/api/lib/widgets/pop_scope/pop_scope.0.dart b/examples/api/lib/widgets/pop_scope/pop_scope.0.dart
deleted file mode 100644
index 6d144bd..0000000
--- a/examples/api/lib/widgets/pop_scope/pop_scope.0.dart
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2014 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.
-
-// This sample demonstrates showing a confirmation dialog before navigating
-// away from a page.
-
-import 'package:flutter/material.dart';
-
-void main() => runApp(const NavigatorPopHandlerApp());
-
-class NavigatorPopHandlerApp extends StatelessWidget {
-  const NavigatorPopHandlerApp({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return MaterialApp(
-      initialRoute: '/home',
-      routes: <String, WidgetBuilder>{
-        '/home': (BuildContext context) => const _HomePage(),
-        '/two': (BuildContext context) => const _PageTwo(),
-      },
-    );
-  }
-}
-
-class _HomePage extends StatefulWidget {
-  const _HomePage();
-
-  @override
-  State<_HomePage> createState() => _HomePageState();
-}
-
-class _HomePageState extends State<_HomePage> {
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      body: Center(
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: <Widget>[
-            const Text('Page One'),
-            TextButton(
-              onPressed: () {
-                Navigator.of(context).pushNamed('/two');
-              },
-              child: const Text('Next page'),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}
-
-class _PageTwo extends StatefulWidget {
-  const _PageTwo();
-
-  @override
-  State<_PageTwo> createState() => _PageTwoState();
-}
-
-class _PageTwoState extends State<_PageTwo> {
-  void _showBackDialog() {
-    showDialog<void>(
-      context: context,
-      builder: (BuildContext context) {
-        return AlertDialog(
-          title: const Text('Are you sure?'),
-          content: const Text(
-            'Are you sure you want to leave this page?',
-          ),
-          actions: <Widget>[
-            TextButton(
-              style: TextButton.styleFrom(
-                textStyle: Theme.of(context).textTheme.labelLarge,
-              ),
-              child: const Text('Nevermind'),
-              onPressed: () {
-                Navigator.pop(context);
-              },
-            ),
-            TextButton(
-              style: TextButton.styleFrom(
-                textStyle: Theme.of(context).textTheme.labelLarge,
-              ),
-              child: const Text('Leave'),
-              onPressed: () {
-                Navigator.pop(context);
-                Navigator.pop(context);
-              },
-            ),
-          ],
-        );
-      },
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      body: Center(
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: <Widget>[
-            const Text('Page Two'),
-            PopScope(
-              canPop: false,
-              onPopInvoked: (bool didPop) {
-                if (didPop) {
-                  return;
-                }
-                _showBackDialog();
-              },
-              child: TextButton(
-                onPressed: () {
-                  _showBackDialog();
-                },
-                child: const Text('Go back'),
-              ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}
diff --git a/examples/api/lib/widgets/will_pop_scope/will_pop_scope.0.dart b/examples/api/lib/widgets/will_pop_scope/will_pop_scope.0.dart
new file mode 100644
index 0000000..46dafa5
--- /dev/null
+++ b/examples/api/lib/widgets/will_pop_scope/will_pop_scope.0.dart
@@ -0,0 +1,77 @@
+// Copyright 2014 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.
+
+import 'package:flutter/material.dart';
+
+/// Flutter code sample for [WillPopScope].
+
+void main() => runApp(const WillPopScopeExampleApp());
+
+class WillPopScopeExampleApp extends StatelessWidget {
+  const WillPopScopeExampleApp({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return const MaterialApp(
+      home: WillPopScopeExample(),
+    );
+  }
+}
+
+class WillPopScopeExample extends StatefulWidget {
+  const WillPopScopeExample({super.key});
+
+  @override
+  State<WillPopScopeExample> createState() => _WillPopScopeExampleState();
+}
+
+class _WillPopScopeExampleState extends State<WillPopScopeExample> {
+  bool shouldPop = true;
+  @override
+  Widget build(BuildContext context) {
+    return WillPopScope(
+      onWillPop: () async {
+        return shouldPop;
+      },
+      child: Scaffold(
+        appBar: AppBar(
+          title: const Text('Flutter WillPopScope demo'),
+        ),
+        body: Center(
+          child: Column(
+            mainAxisAlignment: MainAxisAlignment.center,
+            children: <Widget>[
+              OutlinedButton(
+                child: const Text('Push'),
+                onPressed: () {
+                  Navigator.of(context).push<void>(
+                    MaterialPageRoute<void>(
+                      builder: (BuildContext context) {
+                        return const WillPopScopeExample();
+                      },
+                    ),
+                  );
+                },
+              ),
+              OutlinedButton(
+                child: Text('shouldPop: $shouldPop'),
+                onPressed: () {
+                  setState(
+                    () {
+                      shouldPop = !shouldPop;
+                    },
+                  );
+                },
+              ),
+              const Text('Push to a new screen, then tap on shouldPop '
+                  'button to toggle its value. Press the back '
+                  'button in the appBar to check its behavior '
+                  'for different values of shouldPop'),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/examples/api/test/widgets/form/form.1_test.dart b/examples/api/test/widgets/form/form.1_test.dart
deleted file mode 100644
index f9ccd71..0000000
--- a/examples/api/test/widgets/form/form.1_test.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 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.
-
-import 'package:flutter/material.dart';
-import 'package:flutter_api_samples/widgets/form/form.1.dart' as example;
-import 'package:flutter_test/flutter_test.dart';
-
-void main() {
-  testWidgets('Can go back when form is clean', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      const example.FormApp(),
-    );
-
-    expect(find.text('Are you sure?'), findsNothing);
-
-    await tester.tap(find.text('Go back'));
-    await tester.pumpAndSettle();
-
-    expect(find.text('Are you sure?'), findsNothing);
-  });
-
-  testWidgets('Cannot go back when form is dirty', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      const example.FormApp(),
-    );
-
-    expect(find.text('Are you sure?'), findsNothing);
-
-    await tester.enterText(find.byType(TextFormField), 'some new text');
-
-    await tester.tap(find.text('Go back'));
-    await tester.pumpAndSettle();
-
-    expect(find.text('Are you sure?'), findsOneWidget);
-  });
-}
diff --git a/examples/api/test/widgets/navigator_pop_handler/navigator_pop_handler.0_test.dart b/examples/api/test/widgets/navigator_pop_handler/navigator_pop_handler.0_test.dart
deleted file mode 100644
index 88f2922..0000000
--- a/examples/api/test/widgets/navigator_pop_handler/navigator_pop_handler.0_test.dart
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2014 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.
-
-import 'package:flutter_api_samples/widgets/navigator_pop_handler/navigator_pop_handler.0.dart' as example;
-import 'package:flutter_test/flutter_test.dart';
-
-import '../navigator_utils.dart';
-
-void main() {
-  testWidgets('Can go back with system back gesture', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      const example.NavigatorPopHandlerApp(),
-    );
-
-    expect(find.text('Nested Navigators Example'), findsOneWidget);
-    expect(find.text('Nested Navigators Page One'), findsNothing);
-    expect(find.text('Nested Navigators Page Two'), findsNothing);
-
-    await tester.tap(find.text('Nested Navigator route'));
-    await tester.pumpAndSettle();
-
-    expect(find.text('Nested Navigators Example'), findsNothing);
-    expect(find.text('Nested Navigators Page One'), findsOneWidget);
-    expect(find.text('Nested Navigators Page Two'), findsNothing);
-
-    await tester.tap(find.text('Go to another route in this nested Navigator'));
-    await tester.pumpAndSettle();
-
-    expect(find.text('Nested Navigators Example'), findsNothing);
-    expect(find.text('Nested Navigators Page One'), findsNothing);
-    expect(find.text('Nested Navigators Page Two'), findsOneWidget);
-
-    await simulateSystemBack();
-    await tester.pumpAndSettle();
-
-    expect(find.text('Nested Navigators Example'), findsNothing);
-    expect(find.text('Nested Navigators Page One'), findsOneWidget);
-    expect(find.text('Nested Navigators Page Two'), findsNothing);
-
-    await simulateSystemBack();
-    await tester.pumpAndSettle();
-
-    expect(find.text('Nested Navigators Example'), findsOneWidget);
-    expect(find.text('Nested Navigators Page One'), findsNothing);
-    expect(find.text('Nested Navigators Page Two'), findsNothing);
-  });
-}
diff --git a/examples/api/test/widgets/navigator_pop_handler/navigator_pop_handler.1_test.dart b/examples/api/test/widgets/navigator_pop_handler/navigator_pop_handler.1_test.dart
deleted file mode 100644
index a6ea0ac..0000000
--- a/examples/api/test/widgets/navigator_pop_handler/navigator_pop_handler.1_test.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 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.
-
-import 'package:flutter_api_samples/widgets/navigator_pop_handler/navigator_pop_handler.1.dart' as example;
-import 'package:flutter_test/flutter_test.dart';
-
-import '../navigator_utils.dart';
-
-void main() {
-  testWidgets("System back gesture operates on current tab's nested Navigator", (WidgetTester tester) async {
-    await tester.pumpWidget(
-      const example.NavigatorPopHandlerApp(),
-    );
-
-    expect(find.text('Bottom nav - tab Home Tab - route _TabPage.home'), findsOneWidget);
-
-    // Go to the next route in this tab.
-    await tester.tap(find.text('Go to another route in this nested Navigator'));
-    await tester.pumpAndSettle();
-    expect(find.text('Bottom nav - tab Home Tab - route _TabPage.one'), findsOneWidget);
-
-    // Go to another tab.
-    await tester.tap(find.text('Go to One'));
-    await tester.pumpAndSettle();
-    expect(find.text('Bottom nav - tab Tab One - route _TabPage.home'), findsOneWidget);
-
-    // Return to the home tab. The navigation state is preserved.
-    await tester.tap(find.text('Go to Home'));
-    await tester.pumpAndSettle();
-    expect(find.text('Bottom nav - tab Home Tab - route _TabPage.one'), findsOneWidget);
-
-    // A back pops the navigation stack of the current tab's nested Navigator.
-    await simulateSystemBack();
-    await tester.pumpAndSettle();
-    expect(find.text('Bottom nav - tab Home Tab - route _TabPage.home'), findsOneWidget);
-  });
-}
diff --git a/examples/api/test/widgets/navigator_utils.dart b/examples/api/test/widgets/navigator_utils.dart
deleted file mode 100644
index 46f1f9b..0000000
--- a/examples/api/test/widgets/navigator_utils.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 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.
-
-import 'package:flutter/services.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-/// Simulates a system back, like a back gesture on Android.
-///
-/// Sends the same platform channel message that the engine sends when it
-/// receives a system back.
-Future<void> simulateSystemBack() {
-  return TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
-    'flutter/navigation',
-    const JSONMessageCodec().encodeMessage(<String, dynamic>{
-      'method': 'popRoute',
-    }),
-    (ByteData? _) {},
-  );
-}
diff --git a/examples/api/test/widgets/pop_scope/pop_scope.0_test.dart b/examples/api/test/widgets/pop_scope/pop_scope.0_test.dart
deleted file mode 100644
index ac334fc..0000000
--- a/examples/api/test/widgets/pop_scope/pop_scope.0_test.dart
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2014 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.
-
-import 'package:flutter_api_samples/widgets/pop_scope/pop_scope.0.dart' as example;
-import 'package:flutter_test/flutter_test.dart';
-
-import '../navigator_utils.dart';
-
-void main() {
-  testWidgets('Can choose to stay on page', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      const example.NavigatorPopHandlerApp(),
-    );
-
-    expect(find.text('Page One'), findsOneWidget);
-    expect(find.text('Page Two'), findsNothing);
-    expect(find.text('Are you sure?'), findsNothing);
-
-    await tester.tap(find.text('Next page'));
-    await tester.pumpAndSettle();
-    expect(find.text('Page One'), findsNothing);
-    expect(find.text('Page Two'), findsOneWidget);
-    expect(find.text('Are you sure?'), findsNothing);
-
-    await simulateSystemBack();
-    await tester.pumpAndSettle();
-    expect(find.text('Page One'), findsNothing);
-    expect(find.text('Page Two'), findsOneWidget);
-    expect(find.text('Are you sure?'), findsOneWidget);
-
-    await tester.tap(find.text('Nevermind'));
-    await tester.pumpAndSettle();
-    expect(find.text('Page One'), findsNothing);
-    expect(find.text('Page Two'), findsOneWidget);
-    expect(find.text('Are you sure?'), findsNothing);
-  });
-
-  testWidgets('Can choose to go back', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      const example.NavigatorPopHandlerApp(),
-    );
-
-    expect(find.text('Page One'), findsOneWidget);
-    expect(find.text('Page Two'), findsNothing);
-    expect(find.text('Are you sure?'), findsNothing);
-
-    await tester.tap(find.text('Next page'));
-    await tester.pumpAndSettle();
-    expect(find.text('Page One'), findsNothing);
-    expect(find.text('Page Two'), findsOneWidget);
-    expect(find.text('Are you sure?'), findsNothing);
-
-    await simulateSystemBack();
-    await tester.pumpAndSettle();
-    expect(find.text('Page One'), findsNothing);
-    expect(find.text('Page Two'), findsOneWidget);
-    expect(find.text('Are you sure?'), findsOneWidget);
-
-    await tester.tap(find.text('Leave'));
-    await tester.pumpAndSettle();
-    expect(find.text('Page One'), findsOneWidget);
-    expect(find.text('Page Two'), findsNothing);
-    expect(find.text('Are you sure?'), findsNothing);
-  });
-}
diff --git a/examples/api/test/widgets/will_pop_scope/will_pop_scope.0_test.dart b/examples/api/test/widgets/will_pop_scope/will_pop_scope.0_test.dart
new file mode 100644
index 0000000..ad05943
--- /dev/null
+++ b/examples/api/test/widgets/will_pop_scope/will_pop_scope.0_test.dart
@@ -0,0 +1,32 @@
+// Copyright 2014 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.
+
+import 'package:flutter_api_samples/widgets/will_pop_scope/will_pop_scope.0.dart' as example;
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+  testWidgets('pressing shouldPop button changes shouldPop', (WidgetTester tester) async {
+    await tester.pumpWidget(
+      const example.WillPopScopeExampleApp(),
+    );
+
+    final Finder buttonFinder = find.text('shouldPop: true');
+    expect(buttonFinder, findsOneWidget);
+    await tester.tap(buttonFinder);
+    await tester.pump();
+    expect(find.text('shouldPop: false'), findsOneWidget);
+  });
+  testWidgets('pressing Push button pushes route', (WidgetTester tester) async {
+    await tester.pumpWidget(
+      const example.WillPopScopeExampleApp(),
+    );
+
+    final Finder buttonFinder = find.text('Push');
+    expect(buttonFinder, findsOneWidget);
+    expect(find.byType(example.WillPopScopeExample), findsOneWidget);
+    await tester.tap(buttonFinder);
+    await tester.pumpAndSettle();
+    expect(find.byType(example.WillPopScopeExample, skipOffstage: false), findsNWidgets(2));
+  });
+}
diff --git a/packages/flutter/lib/src/cupertino/app.dart b/packages/flutter/lib/src/cupertino/app.dart
index 6501b9c..47e45b1 100644
--- a/packages/flutter/lib/src/cupertino/app.dart
+++ b/packages/flutter/lib/src/cupertino/app.dart
@@ -157,7 +157,6 @@
     this.onGenerateRoute,
     this.onGenerateInitialRoutes,
     this.onUnknownRoute,
-    this.onNavigationNotification = WidgetsApp.defaultOnNavigationNotification,
     List<NavigatorObserver> this.navigatorObservers = const <NavigatorObserver>[],
     this.builder,
     this.title = '',
@@ -203,7 +202,6 @@
     this.builder,
     this.title = '',
     this.onGenerateTitle,
-    this.onNavigationNotification = WidgetsApp.defaultOnNavigationNotification,
     this.color,
     this.locale,
     this.localizationsDelegates,
@@ -270,9 +268,6 @@
   /// {@macro flutter.widgets.widgetsApp.onUnknownRoute}
   final RouteFactory? onUnknownRoute;
 
-  /// {@macro flutter.widgets.widgetsApp.onNavigationNotification}
-  final NotificationListenerCallback<NavigationNotification>? onNavigationNotification;
-
   /// {@macro flutter.widgets.widgetsApp.navigatorObservers}
   final List<NavigatorObserver>? navigatorObservers;
 
@@ -578,7 +573,6 @@
       onGenerateRoute: widget.onGenerateRoute,
       onGenerateInitialRoutes: widget.onGenerateInitialRoutes,
       onUnknownRoute: widget.onUnknownRoute,
-      onNavigationNotification: widget.onNavigationNotification,
       builder: widget.builder,
       title: widget.title,
       onGenerateTitle: widget.onGenerateTitle,
diff --git a/packages/flutter/lib/src/cupertino/route.dart b/packages/flutter/lib/src/cupertino/route.dart
index 2115782..f922eaf 100644
--- a/packages/flutter/lib/src/cupertino/route.dart
+++ b/packages/flutter/lib/src/cupertino/route.dart
@@ -196,8 +196,7 @@
     }
     // If attempts to dismiss this route might be vetoed such as in a page
     // with forms, then do not allow the user to dismiss the route with a swipe.
-    if (route.hasScopedWillPopCallback
-        || route.popDisposition == RoutePopDisposition.doNotPop) {
+    if (route.hasScopedWillPopCallback) {
       return false;
     }
     // Fullscreen dialogs aren't dismissible by back swipe.
diff --git a/packages/flutter/lib/src/cupertino/tab_view.dart b/packages/flutter/lib/src/cupertino/tab_view.dart
index f41d0a4..8728196 100644
--- a/packages/flutter/lib/src/cupertino/tab_view.dart
+++ b/packages/flutter/lib/src/cupertino/tab_view.dart
@@ -162,39 +162,15 @@
           ..add(_heroController);
   }
 
-  GlobalKey<NavigatorState>? _ownedNavigatorKey;
-  GlobalKey<NavigatorState> get _navigatorKey {
-    if (widget.navigatorKey != null) {
-      return widget.navigatorKey!;
-    }
-    _ownedNavigatorKey ??= GlobalKey<NavigatorState>();
-    return _ownedNavigatorKey!;
-  }
-
-  // Whether this tab is currently the active tab.
-  bool get _isActive => TickerMode.of(context);
-
   @override
   Widget build(BuildContext context) {
-    final Widget child = Navigator(
-      key: _navigatorKey,
+    return Navigator(
+      key: widget.navigatorKey,
       onGenerateRoute: _onGenerateRoute,
       onUnknownRoute: _onUnknownRoute,
       observers: _navigatorObservers,
       restorationScopeId: widget.restorationScopeId,
     );
-
-    // Handle system back gestures only if the tab is currently active.
-    return NavigatorPopHandler(
-      enabled: _isActive,
-      onPop: () {
-        if (!_isActive) {
-          return;
-        }
-        _navigatorKey.currentState!.pop();
-      },
-      child: child,
-    );
   }
 
   Route<dynamic>? _onGenerateRoute(RouteSettings settings) {
diff --git a/packages/flutter/lib/src/material/about.dart b/packages/flutter/lib/src/material/about.dart
index 76462c8..44d4e7b 100644
--- a/packages/flutter/lib/src/material/about.dart
+++ b/packages/flutter/lib/src/material/about.dart
@@ -1179,10 +1179,9 @@
     _builtLayout = _LayoutMode.nested;
     final MaterialPageRoute<void> masterPageRoute = _masterPageRoute(context);
 
-    return NavigatorPopHandler(
-      onPop: () {
-        _navigatorKey.currentState!.maybePop();
-      },
+    return WillPopScope(
+      // Push pop check into nested navigator.
+      onWillPop: () async => !(await _navigatorKey.currentState!.maybePop()),
       child: Navigator(
         key: _navigatorKey,
         initialRoute: 'initial',
@@ -1235,10 +1234,12 @@
 
   MaterialPageRoute<void> _detailPageRoute(Object? arguments) {
     return MaterialPageRoute<dynamic>(builder: (BuildContext context) {
-      return PopScope(
-        onPopInvoked: (bool didPop) {
+      return WillPopScope(
+        onWillPop: () async {
           // No need for setState() as rebuild happens on navigation pop.
           focus = _Focus.master;
+          Navigator.of(context).pop();
+          return false;
         },
         child: BlockSemantics(child: widget.detailPageBuilder(context, arguments, null)),
       );
diff --git a/packages/flutter/lib/src/material/app.dart b/packages/flutter/lib/src/material/app.dart
index 62f0385..2438c45 100644
--- a/packages/flutter/lib/src/material/app.dart
+++ b/packages/flutter/lib/src/material/app.dart
@@ -214,7 +214,6 @@
     this.onGenerateRoute,
     this.onGenerateInitialRoutes,
     this.onUnknownRoute,
-    this.onNavigationNotification = WidgetsApp.defaultOnNavigationNotification,
     List<NavigatorObserver> this.navigatorObservers = const <NavigatorObserver>[],
     this.builder,
     this.title = '',
@@ -268,7 +267,6 @@
     this.builder,
     this.title = '',
     this.onGenerateTitle,
-    this.onNavigationNotification = WidgetsApp.defaultOnNavigationNotification,
     this.color,
     this.theme,
     this.darkTheme,
@@ -345,9 +343,6 @@
   /// {@macro flutter.widgets.widgetsApp.onUnknownRoute}
   final RouteFactory? onUnknownRoute;
 
-  /// {@macro flutter.widgets.widgetsApp.onNavigationNotification}
-  final NotificationListenerCallback<NavigationNotification>? onNavigationNotification;
-
   /// {@macro flutter.widgets.widgetsApp.navigatorObservers}
   final List<NavigatorObserver>? navigatorObservers;
 
@@ -1024,7 +1019,6 @@
       onGenerateRoute: widget.onGenerateRoute,
       onGenerateInitialRoutes: widget.onGenerateInitialRoutes,
       onUnknownRoute: widget.onUnknownRoute,
-      onNavigationNotification: widget.onNavigationNotification,
       builder: _materialBuilder,
       title: widget.title,
       onGenerateTitle: widget.onGenerateTitle,
diff --git a/packages/flutter/lib/src/services/system_navigator.dart b/packages/flutter/lib/src/services/system_navigator.dart
index 1ea16f9..9edff64 100644
--- a/packages/flutter/lib/src/services/system_navigator.dart
+++ b/packages/flutter/lib/src/services/system_navigator.dart
@@ -2,44 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter/foundation.dart';
-
 import 'system_channels.dart';
 
 /// Controls specific aspects of the system navigation stack.
 abstract final class SystemNavigator {
-  /// Informs the platform of whether or not the Flutter framework will handle
-  /// back events.
-  ///
-  /// Currently, this is used only on Android to inform its use of the
-  /// predictive back gesture when exiting the app. When true, predictive back
-  /// is disabled.
-  ///
-  /// See also:
-  ///
-  ///  * The
-  ///    [migration guide](https://developer.android.com/guide/navigation/predictive-back-gesture)
-  ///    for predictive back in native Android apps.
-  static Future<void> setFrameworkHandlesBack(bool frameworkHandlesBack) async {
-    // Currently, this method call is only relevant on Android.
-    if (kIsWeb) {
-      return;
-    }
-    switch (defaultTargetPlatform) {
-      case TargetPlatform.iOS:
-      case TargetPlatform.macOS:
-      case TargetPlatform.fuchsia:
-      case TargetPlatform.linux:
-      case TargetPlatform.windows:
-        return;
-      case TargetPlatform.android:
-        return SystemChannels.platform.invokeMethod<void>(
-          'SystemNavigator.setFrameworkHandlesBack',
-          frameworkHandlesBack,
-        );
-    }
-  }
-
   /// Removes the topmost Flutter instance, presenting what was before
   /// it.
   ///
diff --git a/packages/flutter/lib/src/widgets/app.dart b/packages/flutter/lib/src/widgets/app.dart
index 5d402c6..af5d404 100644
--- a/packages/flutter/lib/src/widgets/app.dart
+++ b/packages/flutter/lib/src/widgets/app.dart
@@ -19,7 +19,6 @@
 import 'localizations.dart';
 import 'media_query.dart';
 import 'navigator.dart';
-import 'notification_listener.dart';
 import 'pages.dart';
 import 'performance_overlay.dart';
 import 'restoration.dart';
@@ -314,7 +313,6 @@
     this.onGenerateRoute,
     this.onGenerateInitialRoutes,
     this.onUnknownRoute,
-    this.onNavigationNotification = defaultOnNavigationNotification,
     List<NavigatorObserver> this.navigatorObservers = const <NavigatorObserver>[],
     this.initialRoute,
     this.pageRouteBuilder,
@@ -422,7 +420,6 @@
     this.builder,
     this.title = '',
     this.onGenerateTitle,
-    this.onNavigationNotification = defaultOnNavigationNotification,
     this.textStyle,
     required this.color,
     this.locale,
@@ -704,17 +701,6 @@
   /// {@endtemplate}
   final RouteFactory? onUnknownRoute;
 
-  /// {@template flutter.widgets.widgetsApp.onNavigationNotification}
-  /// The callback to use when receiving a [NavigationNotification].
-  ///
-  /// By default set to [WidgetsApp.defaultOnNavigationNotification], which
-  /// updates the engine with the navigation status.
-  ///
-  /// If null, [NavigationNotification] is not listened for at all, and so will
-  /// continue to propagate.
-  /// {@endtemplate}
-  final NotificationListenerCallback<NavigationNotification>? onNavigationNotification;
-
   /// {@template flutter.widgets.widgetsApp.initialRoute}
   /// The name of the first route to show, if a [Navigator] is built.
   ///
@@ -1328,15 +1314,6 @@
     VoidCallbackIntent: VoidCallbackAction(),
   };
 
-  /// The default value for [onNavigationNotification].
-  ///
-  /// Updates the platform with [NavigationNotification.canHandlePop] and stops
-  /// bubbling.
-  static bool defaultOnNavigationNotification(NavigationNotification notification) {
-    SystemNavigator.setFrameworkHandlesBack(notification.canHandlePop);
-    return true;
-  }
-
   @override
   State<WidgetsApp> createState() => _WidgetsAppState();
 }
@@ -1771,25 +1748,30 @@
 
     assert(_debugCheckLocalizations(appLocale));
 
-    Widget child = Shortcuts(
-      debugLabel: '<Default WidgetsApp Shortcuts>',
-      shortcuts: widget.shortcuts ?? WidgetsApp.defaultShortcuts,
-      // DefaultTextEditingShortcuts is nested inside Shortcuts so that it can
-      // fall through to the defaultShortcuts.
-      child: DefaultTextEditingShortcuts(
-        child: Actions(
-          actions: widget.actions ?? <Type, Action<Intent>>{
-            ...WidgetsApp.defaultActions,
-            ScrollIntent: Action<ScrollIntent>.overridable(context: context, defaultAction: ScrollAction()),
-          },
-          child: FocusTraversalGroup(
-            policy: ReadingOrderTraversalPolicy(),
-            child: TapRegionSurface(
-              child: ShortcutRegistrar(
-                child: Localizations(
-                  locale: appLocale,
-                  delegates: _localizationsDelegates.toList(),
-                  child: title,
+    return RootRestorationScope(
+      restorationId: widget.restorationScopeId,
+      child: SharedAppData(
+        child: Shortcuts(
+          debugLabel: '<Default WidgetsApp Shortcuts>',
+          shortcuts: widget.shortcuts ?? WidgetsApp.defaultShortcuts,
+          // DefaultTextEditingShortcuts is nested inside Shortcuts so that it can
+          // fall through to the defaultShortcuts.
+          child: DefaultTextEditingShortcuts(
+            child: Actions(
+              actions: widget.actions ?? <Type, Action<Intent>>{
+                ...WidgetsApp.defaultActions,
+                ScrollIntent: Action<ScrollIntent>.overridable(context: context, defaultAction: ScrollAction()),
+              },
+              child: FocusTraversalGroup(
+                policy: ReadingOrderTraversalPolicy(),
+                child: TapRegionSurface(
+                  child: ShortcutRegistrar(
+                    child: Localizations(
+                      locale: appLocale,
+                      delegates: _localizationsDelegates.toList(),
+                      child: title,
+                    ),
+                  ),
                 ),
               ),
             ),
@@ -1797,19 +1779,5 @@
         ),
       ),
     );
-
-    if (widget.onNavigationNotification != null) {
-      child = NotificationListener<NavigationNotification>(
-        onNotification: widget.onNavigationNotification,
-        child: child,
-      );
-    }
-
-    return RootRestorationScope(
-      restorationId: widget.restorationScopeId,
-      child: SharedAppData(
-        child: child,
-      ),
-    );
   }
 }
diff --git a/packages/flutter/lib/src/widgets/binding.dart b/packages/flutter/lib/src/widgets/binding.dart
index 13efd54..900d34f 100644
--- a/packages/flutter/lib/src/widgets/binding.dart
+++ b/packages/flutter/lib/src/widgets/binding.dart
@@ -54,8 +54,9 @@
 /// ** See code in examples/api/lib/widgets/binding/widget_binding_observer.0.dart **
 /// {@end-tool}
 abstract mixin class WidgetsBindingObserver {
-  /// Called when the system tells the app to pop the current route, such as
-  /// after a system back button press or back gesture.
+  /// Called when the system tells the app to pop the current route.
+  /// For example, on Android, this is called when the user presses
+  /// the back button.
   ///
   /// Observers are notified in registration order until one returns
   /// true. If none return true, the application quits.
@@ -68,8 +69,6 @@
   ///
   /// This method exposes the `popRoute` notification from
   /// [SystemChannels.navigation].
-  ///
-  /// {@macro flutter.widgets.AndroidPredictiveBack}
   Future<bool> didPopRoute() => Future<bool>.value(false);
 
   /// Called when the host tells the application to push a new route onto the
@@ -721,27 +720,6 @@
   ///
   /// This method exposes the `popRoute` notification from
   /// [SystemChannels.navigation].
-  ///
-  /// {@template flutter.widgets.AndroidPredictiveBack}
-  /// ## Handling backs ahead of time
-  ///
-  /// Not all system backs will result in a call to this method. Some are
-  /// handled entirely by the system without informing the Flutter framework.
-  ///
-  /// Android API 33+ introduced a feature called predictive back, which allows
-  /// the user to peek behind the current app or route during a back gesture and
-  /// then decide to cancel or commit the back. Flutter enables or disables this
-  /// feature ahead of time, before a back gesture occurs, and back gestures
-  /// that trigger predictive back are handled entirely by the system and do not
-  /// trigger this method here in the framework.
-  ///
-  /// By default, the framework communicates when it would like to handle system
-  /// back gestures using [SystemNavigator.setFrameworkHandlesBack] in
-  /// [WidgetsApp.defaultOnNavigationNotification]. This is done automatically
-  /// based on the status of the [Navigator] stack and the state of any
-  /// [PopScope] widgets present. Developers can manually set this by calling
-  /// the method directly or by using [NavigationNotification].
-  /// {@endtemplate}
   @protected
   @visibleForTesting
   Future<void> handlePopRoute() async {
diff --git a/packages/flutter/lib/src/widgets/form.dart b/packages/flutter/lib/src/widgets/form.dart
index 05ad855..76e8521 100644
--- a/packages/flutter/lib/src/widgets/form.dart
+++ b/packages/flutter/lib/src/widgets/form.dart
@@ -10,10 +10,8 @@
 import 'basic.dart';
 import 'framework.dart';
 import 'navigator.dart';
-import 'pop_scope.dart';
 import 'restoration.dart';
 import 'restoration_properties.dart';
-import 'routes.dart';
 import 'will_pop_scope.dart';
 
 // Duration for delay before announcement in IOS so that the announcement won't be interrupted.
@@ -54,17 +52,10 @@
   const Form({
     super.key,
     required this.child,
-    this.canPop,
-    this.onPopInvoked,
-    @Deprecated(
-      'Use canPop and/or onPopInvoked instead. '
-      'This feature was deprecated after v3.12.0-1.0.pre.',
-    )
     this.onWillPop,
     this.onChanged,
     AutovalidateMode? autovalidateMode,
-  }) : autovalidateMode = autovalidateMode ?? AutovalidateMode.disabled,
-       assert((onPopInvoked == null && canPop == null) || onWillPop == null, 'onWillPop is deprecated; use canPop and/or onPopInvoked.');
+  }) : autovalidateMode = autovalidateMode ?? AutovalidateMode.disabled;
 
   /// Returns the [FormState] of the closest [Form] widget which encloses the
   /// given context, or null if none is found.
@@ -143,44 +134,8 @@
   ///
   ///  * [WillPopScope], another widget that provides a way to intercept the
   ///    back button.
-  @Deprecated(
-    'Use canPop and/or onPopInvoked instead. '
-    'This feature was deprecated after v3.12.0-1.0.pre.',
-  )
   final WillPopCallback? onWillPop;
 
-  /// {@macro flutter.widgets.PopScope.canPop}
-  ///
-  /// {@tool dartpad}
-  /// This sample demonstrates how to use this parameter to show a confirmation
-  /// dialog when a navigation pop would cause form data to be lost.
-  ///
-  /// ** See code in examples/api/lib/widgets/form/form.1.dart **
-  /// {@end-tool}
-  ///
-  /// See also:
-  ///
-  ///  * [onPopInvoked], which also comes from [PopScope] and is often used in
-  ///    conjunction with this parameter.
-  ///  * [PopScope.canPop], which is what [Form] delegates to internally.
-  final bool? canPop;
-
-  /// {@macro flutter.widgets.navigator.onPopInvoked}
-  ///
-  /// {@tool dartpad}
-  /// This sample demonstrates how to use this parameter to show a confirmation
-  /// dialog when a navigation pop would cause form data to be lost.
-  ///
-  /// ** See code in examples/api/lib/widgets/form/form.1.dart **
-  /// {@end-tool}
-  ///
-  /// See also:
-  ///
-  ///  * [canPop], which also comes from [PopScope] and is often used in
-  ///    conjunction with this parameter.
-  ///  * [PopScope.onPopInvoked], which is what [Form] delegates to internally.
-  final PopInvokedCallback? onPopInvoked;
-
   /// Called when one of the form fields changes.
   ///
   /// In addition to this callback being invoked, all the form fields themselves
@@ -245,18 +200,6 @@
         break;
     }
 
-    if (widget.canPop != null || widget.onPopInvoked != null) {
-      return PopScope(
-        canPop: widget.canPop ?? true,
-        onPopInvoked: widget.onPopInvoked,
-        child: _FormScope(
-          formState: this,
-          generation: _generation,
-          child: widget.child,
-        ),
-      );
-    }
-
     return WillPopScope(
       onWillPop: widget.onWillPop,
       child: _FormScope(
diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart
index f366dfb..43156aa 100644
--- a/packages/flutter/lib/src/widgets/navigator.dart
+++ b/packages/flutter/lib/src/widgets/navigator.dart
@@ -20,7 +20,6 @@
 import 'focus_traversal.dart';
 import 'framework.dart';
 import 'heroes.dart';
-import 'notification_listener.dart';
 import 'overlay.dart';
 import 'restoration.dart';
 import 'restoration_properties.dart';
@@ -68,10 +67,6 @@
 ///
 /// Used by [Form.onWillPop], [ModalRoute.addScopedWillPopCallback],
 /// [ModalRoute.removeScopedWillPopCallback], and [WillPopScope].
-@Deprecated(
-  'Use PopInvokedCallback instead. '
-  'This feature was deprecated after v3.12.0-1.0.pre.',
-)
 typedef WillPopCallback = Future<bool> Function();
 
 /// Signature for the [Navigator.onPopPage] callback.
@@ -94,21 +89,19 @@
 enum RoutePopDisposition {
   /// Pop the route.
   ///
-  /// If [Route.willPop] or [Route.popDisposition] return [pop] then the back
-  /// button will actually pop the current route.
+  /// If [Route.willPop] returns [pop] then the back button will actually pop
+  /// the current route.
   pop,
 
   /// Do not pop the route.
   ///
-  /// If [Route.willPop] or [Route.popDisposition] return [doNotPop] then the
-  /// back button will be ignored.
+  /// If [Route.willPop] returns [doNotPop] then the back button will be ignored.
   doNotPop,
 
   /// Delegate this to the next level of navigation.
   ///
-  /// If [Route.willPop] or [Route.popDisposition] return [bubble] then the back
-  /// button will be handled by the [SystemNavigator], which will usually close
-  /// the application.
+  /// If [Route.willPop] returns [bubble] then the back button will be handled
+  /// by the [SystemNavigator], which will usually close the application.
   bubble,
 }
 
@@ -301,51 +294,10 @@
   ///    mechanism.
   ///  * [WillPopScope], another widget that provides a way to intercept the
   ///    back button.
-  @Deprecated(
-    'Use popDisposition instead. '
-    'This feature was deprecated after v3.12.0-1.0.pre.',
-  )
   Future<RoutePopDisposition> willPop() async {
     return isFirst ? RoutePopDisposition.bubble : RoutePopDisposition.pop;
   }
 
-  /// Returns whether calling [Navigator.maybePop] when this [Route] is current
-  /// ([isCurrent]) should do anything.
-  ///
-  /// [Navigator.maybePop] is usually used instead of [Navigator.pop] to handle
-  /// the system back button, when it hasn't been disabled via
-  /// [SystemNavigator.setFrameworkHandlesBack].
-  ///
-  /// By default, if a [Route] is the first route in the history (i.e., if
-  /// [isFirst]), it reports that pops should be bubbled
-  /// ([RoutePopDisposition.bubble]). This behavior prevents the user from
-  /// popping the first route off the history and being stranded at a blank
-  /// screen; instead, the larger scope is popped (e.g. the application quits,
-  /// so that the user returns to the previous application).
-  ///
-  /// In other cases, the default behavior is to accept the pop
-  /// ([RoutePopDisposition.pop]).
-  ///
-  /// The third possible value is [RoutePopDisposition.doNotPop], which causes
-  /// the pop request to be ignored entirely.
-  ///
-  /// See also:
-  ///
-  ///  * [Form], which provides a [Form.canPop] boolean that is similar.
-  ///  * [PopScope], a widget that provides a way to intercept the back button.
-  RoutePopDisposition get popDisposition {
-    return isFirst ? RoutePopDisposition.bubble : RoutePopDisposition.pop;
-  }
-
-  /// {@template flutter.widgets.navigator.onPopInvoked}
-  /// Called after a route pop was handled.
-  ///
-  /// Even when the pop is canceled, for example by a [PopScope] widget, this
-  /// will still be called. The `didPop` parameter indicates whether or not the
-  /// back navigation actually happened successfully.
-  /// {@endtemplate}
-  void onPopInvoked(bool didPop) {}
-
   /// Whether calling [didPop] would return false.
   bool get willHandlePopInternally => false;
 
@@ -2463,9 +2415,6 @@
   /// the initial route.
   ///
   /// If there is no [Navigator] in scope, returns false.
-  ///
-  /// Does not consider anything that might externally prevent popping, such as
-  /// [PopEntry].
   /// {@endtemplate}
   ///
   /// See also:
@@ -2477,22 +2426,21 @@
     return navigator != null && navigator.canPop();
   }
 
-  /// Consults the current route's [Route.popDisposition] getter or
-  /// [Route.willPop] method, and acts accordingly, potentially popping the
-  /// route as a result; returns whether the pop request should be considered
-  /// handled.
+  /// Consults the current route's [Route.willPop] method, and acts accordingly,
+  /// potentially popping the route as a result; returns whether the pop request
+  /// should be considered handled.
   ///
   /// {@template flutter.widgets.navigator.maybePop}
-  /// If the [RoutePopDisposition] is [RoutePopDisposition.pop], then the [pop]
+  /// If [Route.willPop] returns [RoutePopDisposition.pop], then the [pop]
   /// method is called, and this method returns true, indicating that it handled
   /// the pop request.
   ///
-  /// If the [RoutePopDisposition] is [RoutePopDisposition.doNotPop], then this
+  /// If [Route.willPop] returns [RoutePopDisposition.doNotPop], then this
   /// method returns true, but does not do anything beyond that.
   ///
-  /// If the [RoutePopDisposition] is [RoutePopDisposition.bubble], then this
-  /// method returns false, and the caller is responsible for sending the
-  /// request to the containing scope (e.g. by closing the application).
+  /// If [Route.willPop] returns [RoutePopDisposition.bubble], then this method
+  /// returns false, and the caller is responsible for sending the request to
+  /// the containing scope (e.g. by closing the application).
   ///
   /// This method is typically called for a user-initiated [pop]. For example on
   /// Android it's called by the binding for the system's back button.
@@ -3067,7 +3015,6 @@
     assert(isPresent);
     pendingResult = result;
     currentState = _RouteLifecycle.pop;
-    route.onPopInvoked(true);
   }
 
   bool _reportRemovalToObserver = true;
@@ -3348,93 +3295,12 @@
   }
 }
 
-typedef _IndexWhereCallback = bool Function(_RouteEntry element);
-
-/// A collection of _RouteEntries representing a navigation history.
-///
-/// Acts as a ChangeNotifier and notifies after its List of _RouteEntries is
-/// mutated.
-class _History extends Iterable<_RouteEntry> with ChangeNotifier implements Iterator<_RouteEntry> {
-  final List<_RouteEntry> _value = <_RouteEntry>[];
-
-  int indexWhere(_IndexWhereCallback test, [int start = 0]) {
-    return _value.indexWhere(test, start);
-  }
-
-  void add(_RouteEntry element) {
-    _value.add(element);
-    notifyListeners();
-  }
-
-  void addAll(Iterable<_RouteEntry> elements) {
-    _value.addAll(elements);
-    if (elements.isNotEmpty) {
-      notifyListeners();
-    }
-  }
-
-  void clear() {
-    final bool valueWasEmpty = _value.isEmpty;
-    _value.clear();
-    if (!valueWasEmpty) {
-      notifyListeners();
-    }
-  }
-
-  void insert(int index, _RouteEntry element) {
-    _value.insert(index, element);
-    notifyListeners();
-  }
-
-  _RouteEntry removeAt(int index) {
-    final _RouteEntry entry = _value.removeAt(index);
-    notifyListeners();
-    return entry;
-  }
-
-  _RouteEntry removeLast() {
-    final _RouteEntry entry = _value.removeLast();
-    notifyListeners();
-    return entry;
-  }
-
-  // Begin Iterator.
-
-  int _i = 0;
-
-  _RouteEntry operator [](int index) {
-    return _value[index];
-  }
-
-  @override
-  Iterator<_RouteEntry> get iterator {
-    return _value.iterator;
-  }
-
-  @override
-  _RouteEntry get current => _value[_i];
-
-  @override
-  bool moveNext() {
-    _i++;
-    return _i <= _value.length - 1;
-  }
-
-  // End Iterator.
-
-  @override
-  String toString() {
-    return _value.toString();
-  }
-}
-
 /// The state for a [Navigator] widget.
 ///
 /// A reference to this class can be obtained by calling [Navigator.of].
 class NavigatorState extends State<Navigator> with TickerProviderStateMixin, RestorationMixin {
   late GlobalKey<OverlayState> _overlayKey;
-  final _History _history = _History();
-
+  List<_RouteEntry> _history = <_RouteEntry>[];
   /// A set for entries that are waiting to dispose until their subtrees are
   /// disposed.
   ///
@@ -3464,43 +3330,12 @@
 
   late List<NavigatorObserver> _effectiveObservers;
 
-  bool get _usingPagesAPI => widget.pages != const <Page<dynamic>>[];
-
-  void _handleHistoryChanged() {
-    final bool navigatorCanPop = canPop();
-    late final bool routeBlocksPop;
-    if (!navigatorCanPop) {
-      final _RouteEntry? lastEntry = _lastRouteEntryWhereOrNull(_RouteEntry.isPresentPredicate);
-      routeBlocksPop = lastEntry != null
-          && lastEntry.route.popDisposition == RoutePopDisposition.doNotPop;
-    } else {
-      routeBlocksPop = false;
-    }
-    final NavigationNotification notification = NavigationNotification(
-      canHandlePop: navigatorCanPop || routeBlocksPop,
-    );
-    // Avoid dispatching a notification in the middle of a build.
-    switch (SchedulerBinding.instance.schedulerPhase) {
-      case SchedulerPhase.postFrameCallbacks:
-        notification.dispatch(context);
-      case SchedulerPhase.idle:
-      case SchedulerPhase.midFrameMicrotasks:
-      case SchedulerPhase.persistentCallbacks:
-      case SchedulerPhase.transientCallbacks:
-        SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
-          if (!mounted) {
-            return;
-          }
-          notification.dispatch(context);
-        });
-    }
-  }
-
   @override
   void initState() {
     super.initState();
     assert(() {
-      if (_usingPagesAPI) {
+      if (widget.pages != const <Page<dynamic>>[]) {
+        // This navigator uses page API.
         if (widget.pages.isEmpty) {
           FlutterError.reportError(
             FlutterErrorDetails(
@@ -3543,8 +3378,6 @@
     if (widget.reportsRouteUpdateToEngine) {
       SystemNavigator.selectSingleEntryHistory();
     }
-
-    _history.addListener(_handleHistoryChanged);
   }
 
   // Use [_nextPagelessRestorationScopeId] to get the next id.
@@ -3727,7 +3560,7 @@
   void didUpdateWidget(Navigator oldWidget) {
     super.didUpdateWidget(oldWidget);
     assert(() {
-      if (_usingPagesAPI) {
+      if (widget.pages != const <Page<dynamic>>[]) {
         // This navigator uses page API.
         if (widget.pages.isEmpty) {
           FlutterError.reportError(
@@ -3839,8 +3672,6 @@
     _rawNextPagelessRestorationScopeId.dispose();
     _serializableHistory.dispose();
     userGestureInProgressNotifier.dispose();
-    _history.removeListener(_handleHistoryChanged);
-    _history.dispose();
     super.dispose();
     // don't unlock, so that the object becomes unusable
     assert(_debugLocked);
@@ -4126,7 +3957,7 @@
         pageRouteToPagelessRoutes: pageRouteToPagelessRoutes,
       ).cast<_RouteEntry>();
     }
-    _history.clear();
+    _history = <_RouteEntry>[];
     // Adds the leading pageless routes if there is any.
     if (pageRouteToPagelessRoutes.containsKey(null)) {
       _history.addAll(pageRouteToPagelessRoutes[null]!);
@@ -5142,17 +4973,17 @@
     return true; // there's at least two routes, so we can pop
   }
 
-  /// Consults the current route's [Route.popDisposition] method, and acts
-  /// accordingly, potentially popping the route as a result; returns whether
-  /// the pop request should be considered handled.
+  /// Consults the current route's [Route.willPop] method, and acts accordingly,
+  /// potentially popping the route as a result; returns whether the pop request
+  /// should be considered handled.
   ///
   /// {@macro flutter.widgets.navigator.maybePop}
   ///
   /// See also:
   ///
-  ///  * [Form], which provides a [Form.canPop] boolean that enables the
-  ///    form to prevent any [pop]s initiated by the app's back button.
-  ///  * [ModalRoute], which provides a `scopedOnPopCallback` that can be used
+  ///  * [Form], which provides an `onWillPop` callback that enables the form
+  ///    to veto a [pop] initiated by the app's back button.
+  ///  * [ModalRoute], which provides a `scopedWillPopCallback` that can be used
   ///    to define the route's `willPop` method.
   @optionalTypeArgs
   Future<bool> maybePop<T extends Object?>([ T? result ]) async {
@@ -5161,31 +4992,23 @@
       return false;
     }
     assert(lastEntry.route._navigator == this);
-
-    // TODO(justinmc): When the deprecated willPop method is removed, delete
-    // this code and use only popDisposition, below.
-    final RoutePopDisposition willPopDisposition = await lastEntry.route.willPop();
+    final RoutePopDisposition disposition = await lastEntry.route.willPop(); // this is asynchronous
     if (!mounted) {
       // Forget about this pop, we were disposed in the meantime.
       return true;
     }
-    if (willPopDisposition == RoutePopDisposition.doNotPop) {
-      return true;
-    }
     final _RouteEntry? newLastEntry = _lastRouteEntryWhereOrNull(_RouteEntry.isPresentPredicate);
     if (lastEntry != newLastEntry) {
       // Forget about this pop, something happened to our history in the meantime.
       return true;
     }
-
-    switch (lastEntry.route.popDisposition) {
+    switch (disposition) {
       case RoutePopDisposition.bubble:
         return false;
       case RoutePopDisposition.pop:
         pop(result);
         return true;
       case RoutePopDisposition.doNotPop:
-        lastEntry.route.onPopInvoked(false);
         return true;
     }
   }
@@ -5475,46 +5298,29 @@
   Widget build(BuildContext context) {
     assert(!_debugLocked);
     assert(_history.isNotEmpty);
-
     // Hides the HeroControllerScope for the widget subtree so that the other
     // nested navigator underneath will not pick up the hero controller above
     // this level.
     return HeroControllerScope.none(
-      child: NotificationListener<NavigationNotification>(
-        onNotification: (NavigationNotification notification) {
-          // If the state of this Navigator does not change whether or not the
-          // whole framework can pop, propagate the Notification as-is.
-          if (notification.canHandlePop || !canPop()) {
-            return false;
-          }
-          // Otherwise, dispatch a new Notification with the correct canPop and
-          // stop the propagation of the old Notification.
-          const NavigationNotification nextNotification = NavigationNotification(
-            canHandlePop: true,
-          );
-          nextNotification.dispatch(context);
-          return true;
-        },
-        child: Listener(
-          onPointerDown: _handlePointerDown,
-          onPointerUp: _handlePointerUpOrCancel,
-          onPointerCancel: _handlePointerUpOrCancel,
-          child: AbsorbPointer(
-            absorbing: false, // it's mutated directly by _cancelActivePointers above
-            child: FocusTraversalGroup(
-              policy: FocusTraversalGroup.maybeOf(context),
-              child: Focus(
-                focusNode: focusNode,
-                autofocus: true,
-                skipTraversal: true,
-                includeSemantics: false,
-                child: UnmanagedRestorationScope(
-                  bucket: bucket,
-                  child: Overlay(
-                    key: _overlayKey,
-                    clipBehavior: widget.clipBehavior,
-                    initialEntries: overlay == null ?  _allRouteOverlayEntries.toList(growable: false) : const <OverlayEntry>[],
-                  ),
+      child: Listener(
+        onPointerDown: _handlePointerDown,
+        onPointerUp: _handlePointerUpOrCancel,
+        onPointerCancel: _handlePointerUpOrCancel,
+        child: AbsorbPointer(
+          absorbing: false, // it's mutated directly by _cancelActivePointers above
+          child: FocusTraversalGroup(
+            policy: FocusTraversalGroup.maybeOf(context),
+            child: Focus(
+              focusNode: focusNode,
+              autofocus: true,
+              skipTraversal: true,
+              includeSemantics: false,
+              child: UnmanagedRestorationScope(
+                bucket: bucket,
+                child: Overlay(
+                  key: _overlayKey,
+                  clipBehavior: widget.clipBehavior,
+                  initialEntries: overlay == null ?  _allRouteOverlayEntries.toList(growable: false) : const <OverlayEntry>[],
                 ),
               ),
             ),
@@ -5675,7 +5481,7 @@
 
   // Updating.
 
-  void update(_History history) {
+  void update(List<_RouteEntry> history) {
     assert(isRegistered);
     final bool wasUninitialized = _pageToPagelessRoutes == null;
     bool needsSerialization = wasUninitialized;
@@ -5998,26 +5804,3 @@
 
   static NavigatorState _defaultNavigatorFinder(BuildContext context) => Navigator.of(context);
 }
-
-/// A notification that a change in navigation has taken place.
-///
-/// Specifically, this notification indicates that at least one of the following
-/// has occurred:
-///
-///  * That route stack of a [Navigator] has changed in any way.
-///  * The ability to pop has changed, such as controlled by [PopScope].
-class NavigationNotification extends Notification {
-  /// Creates a notification that some change in navigation has happened.
-  const NavigationNotification({
-    required this.canHandlePop,
-  });
-
-  /// Indicates that the originator of this [Notification] is capable of
-  /// handling a navigation pop.
-  final bool canHandlePop;
-
-  @override
-  String toString() {
-    return 'NavigationNotification canHandlePop: $canHandlePop';
-  }
-}
diff --git a/packages/flutter/lib/src/widgets/navigator_pop_handler.dart b/packages/flutter/lib/src/widgets/navigator_pop_handler.dart
deleted file mode 100644
index 203a85b..0000000
--- a/packages/flutter/lib/src/widgets/navigator_pop_handler.dart
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2014 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.
-
-import 'framework.dart';
-import 'navigator.dart';
-import 'notification_listener.dart';
-import 'pop_scope.dart';
-
-/// Enables the handling of system back gestures.
-///
-/// Typically wraps a nested [Navigator] widget and allows it to handle system
-/// back gestures in the [onPop] callback.
-///
-/// {@tool dartpad}
-/// This sample demonstrates how to use this widget to properly handle system
-/// back gestures when using nested [Navigator]s.
-///
-/// ** See code in examples/api/lib/widgets/navigator_pop_handler/navigator_pop_handler.0.dart **
-/// {@end-tool}
-///
-/// {@tool dartpad}
-/// This sample demonstrates how to use this widget to properly handle system
-/// back gestures with a bottom navigation bar whose tabs each have their own
-/// nested [Navigator]s.
-///
-/// ** See code in examples/api/lib/widgets/navigator_pop_handler/navigator_pop_handler.1.dart **
-/// {@end-tool}
-///
-/// See also:
-///
-///  * [PopScope], which allows toggling the ability of a [Navigator] to
-///    handle pops.
-///  * [NavigationNotification], which indicates whether a [Navigator] in a
-///    subtree can handle pops.
-class NavigatorPopHandler extends StatefulWidget {
-  /// Creates an instance of [NavigatorPopHandler].
-  const NavigatorPopHandler({
-    super.key,
-    this.onPop,
-    this.enabled = true,
-    required this.child,
-  });
-
-  /// The widget to place below this in the widget tree.
-  ///
-  /// Typically this is a [Navigator] that will handle the pop when [onPop] is
-  /// called.
-  final Widget child;
-
-  /// Whether this widget's ability to handle system back gestures is enabled or
-  /// disabled.
-  ///
-  /// When false, there will be no effect on system back gestures. If provided,
-  /// [onPop] will still be called.
-  ///
-  /// This can be used, for example, when the nested [Navigator] is no longer
-  /// active but remains in the widget tree, such as in an inactive tab.
-  ///
-  /// Defaults to true.
-  final bool enabled;
-
-  /// Called when a handleable pop event happens.
-  ///
-  /// For example, a pop is handleable when a [Navigator] in [child] has
-  /// multiple routes on its stack. It's not handleable when it has only a
-  /// single route, and so [onPop] will not be called.
-  ///
-  /// Typically this is used to pop the [Navigator] in [child]. See the sample
-  /// code on [NavigatorPopHandler] for a full example of this.
-  final VoidCallback? onPop;
-
-  @override
-  State<NavigatorPopHandler> createState() => _NavigatorPopHandlerState();
-}
-
-class _NavigatorPopHandlerState extends State<NavigatorPopHandler> {
-  bool _canPop = true;
-
-  @override
-  Widget build(BuildContext context) {
-    // When the widget subtree indicates it can handle a pop, disable popping
-    // here, so that it can be manually handled in canPop.
-    return PopScope(
-      canPop: !widget.enabled || _canPop,
-      onPopInvoked: (bool didPop) {
-        if (didPop) {
-          return;
-        }
-        widget.onPop?.call();
-      },
-      // Listen to changes in the navigation stack in the widget subtree.
-      child: NotificationListener<NavigationNotification>(
-        onNotification: (NavigationNotification notification) {
-          // If this subtree cannot handle pop, then set canPop to true so
-          // that our PopScope will allow the Navigator higher in the tree to
-          // handle the pop instead.
-          final bool nextCanPop = !notification.canHandlePop;
-          if (nextCanPop != _canPop) {
-            setState(() {
-              _canPop = nextCanPop;
-            });
-          }
-          return false;
-        },
-        child: widget.child,
-      ),
-    );
-  }
-}
diff --git a/packages/flutter/lib/src/widgets/pop_scope.dart b/packages/flutter/lib/src/widgets/pop_scope.dart
deleted file mode 100644
index b47d83f..0000000
--- a/packages/flutter/lib/src/widgets/pop_scope.dart
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2014 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.
-
-import 'package:flutter/foundation.dart';
-
-import 'framework.dart';
-import 'navigator.dart';
-import 'routes.dart';
-
-/// Manages system back gestures.
-///
-/// The [canPop] parameter can be used to disable system back gestures. Defaults
-/// to true, meaning that back gestures happen as usual.
-///
-/// The [onPopInvoked] parameter reports when system back gestures occur,
-/// regardless of whether or not they were successful.
-///
-/// If [canPop] is false, then a system back gesture will not pop the route off
-/// of the enclosing [Navigator]. [onPopInvoked] will still be called, and
-/// `didPop` will be `false`.
-///
-/// If [canPop] is true, then a system back gesture will cause the enclosing
-/// [Navigator] to receive a pop as usual. [onPopInvoked] will be called with
-/// `didPop` as `true`, unless the pop failed for reasons unrelated to
-/// [PopScope], in which case it will be `false`.
-///
-/// {@tool dartpad}
-/// This sample demonstrates how to use this widget to handle nested navigation
-/// in a bottom navigation bar.
-///
-/// ** See code in examples/api/lib/widgets/pop_scope/pop_scope.0.dart **
-/// {@end-tool}
-///
-/// See also:
-///
-///  * [NavigatorPopHandler], which is a less verbose way to handle system back
-///    gestures in simple cases of nested [Navigator]s.
-///  * [Form.canPop] and [Form.onPopInvoked], which can be used to handle system
-///    back gestures in the case of a form with unsaved data.
-///  * [ModalRoute.registerPopEntry] and [ModalRoute.unregisterPopEntry],
-///    which this widget uses to integrate with Flutter's navigation system.
-class PopScope extends StatefulWidget {
-  /// Creates a widget that registers a callback to veto attempts by the user to
-  /// dismiss the enclosing [ModalRoute].
-  const PopScope({
-    super.key,
-    required this.child,
-    this.canPop = true,
-    this.onPopInvoked,
-  });
-
-  /// The widget below this widget in the tree.
-  ///
-  /// {@macro flutter.widgets.ProxyWidget.child}
-  final Widget child;
-
-  /// {@template flutter.widgets.PopScope.onPopInvoked}
-  /// Called after a route pop was handled.
-  /// {@endtemplate}
-  ///
-  /// It's not possible to prevent the pop from happening at the time that this
-  /// method is called; the pop has already happened. Use [canPop] to
-  /// disable pops in advance.
-  ///
-  /// This will still be called even when the pop is canceled. A pop is canceled
-  /// when the relevant [Route.popDisposition] returns false, such as when
-  /// [canPop] is set to false on a [PopScope]. The `didPop` parameter
-  /// indicates whether or not the back navigation actually happened
-  /// successfully.
-  ///
-  /// See also:
-  ///
-  ///  * [Route.onPopInvoked], which is similar.
-  final PopInvokedCallback? onPopInvoked;
-
-  /// {@template flutter.widgets.PopScope.canPop}
-  /// When false, blocks the current route from being popped.
-  ///
-  /// This includes the root route, where upon popping, the Flutter app would
-  /// exit.
-  ///
-  /// If multiple [PopScope] widgets appear in a route's widget subtree, then
-  /// each and every `canPop` must be `true` in order for the route to be
-  /// able to pop.
-  ///
-  /// [Android's predictive back](https://developer.android.com/guide/navigation/predictive-back-gesture)
-  /// feature will not animate when this boolean is false.
-  /// {@endtemplate}
-  final bool canPop;
-
-  @override
-  State<PopScope> createState() => _PopScopeState();
-}
-
-class _PopScopeState extends State<PopScope> implements PopEntry {
-  ModalRoute<dynamic>? _route;
-
-  @override
-  PopInvokedCallback? get onPopInvoked => widget.onPopInvoked;
-
-  @override
-  late final ValueNotifier<bool> canPopNotifier;
-
-  @override
-  void initState() {
-    super.initState();
-    canPopNotifier = ValueNotifier<bool>(widget.canPop);
-  }
-
-  @override
-  void didChangeDependencies() {
-    super.didChangeDependencies();
-    final ModalRoute<dynamic>? nextRoute = ModalRoute.of(context);
-    if (nextRoute != _route) {
-      _route?.unregisterPopEntry(this);
-      _route = nextRoute;
-      _route?.registerPopEntry(this);
-    }
-  }
-
-  @override
-  void didUpdateWidget(PopScope oldWidget) {
-    super.didUpdateWidget(oldWidget);
-    canPopNotifier.value = widget.canPop;
-  }
-
-  @override
-  void dispose() {
-    _route?.unregisterPopEntry(this);
-    canPopNotifier.dispose();
-    super.dispose();
-  }
-
-  @override
-  Widget build(BuildContext context) => widget.child;
-}
diff --git a/packages/flutter/lib/src/widgets/routes.dart b/packages/flutter/lib/src/widgets/routes.dart
index e54e46a..441486e 100644
--- a/packages/flutter/lib/src/widgets/routes.dart
+++ b/packages/flutter/lib/src/widgets/routes.dart
@@ -717,10 +717,6 @@
     }
   }
 
-  @Deprecated(
-    'Use popDisposition instead. '
-    'This feature was deprecated after v3.12.0-1.0.pre.',
-  )
   @override
   Future<RoutePopDisposition> willPop() async {
     if (willHandlePopInternally) {
@@ -730,14 +726,6 @@
   }
 
   @override
-  RoutePopDisposition get popDisposition {
-    if (willHandlePopInternally) {
-      return RoutePopDisposition.pop;
-    }
-    return super.popDisposition;
-  }
-
-  @override
   bool didPop(T? result) {
     if (_localHistory != null && _localHistory!.isNotEmpty) {
       final LocalHistoryEntry entry = _localHistory!.removeLast();
@@ -1502,8 +1490,6 @@
 
   final List<WillPopCallback> _willPopCallbacks = <WillPopCallback>[];
 
-  final Set<PopEntry> _popEntries = <PopEntry>{};
-
   /// Returns [RoutePopDisposition.doNotPop] if any of callbacks added with
   /// [addScopedWillPopCallback] returns either false or null. If they all
   /// return true, the base [Route.willPop]'s result will be returned. The
@@ -1522,10 +1508,6 @@
   ///    method checks.
   ///  * [removeScopedWillPopCallback], which removes a callback from the list
   ///    this method checks.
-  @Deprecated(
-    'Use popDisposition instead. '
-    'This feature was deprecated after v3.12.0-1.0.pre.',
-  )
   @override
   Future<RoutePopDisposition> willPop() async {
     final _ModalScopeState<T>? scope = _scopeKey.currentState;
@@ -1538,44 +1520,26 @@
     return super.willPop();
   }
 
-  /// Returns [RoutePopDisposition.doNotPop] if any of the [PopEntry] instances
-  /// registered with [registerPopEntry] have [PopEntry.canPopNotifier] set to
-  /// false.
-  ///
-  /// Typically this method is not overridden because applications usually
-  /// don't create modal routes directly, they use higher level primitives
-  /// like [showDialog]. The scoped [PopEntry] list makes it possible for
-  /// ModalRoute descendants to collectively define the value of
-  /// [popDisposition].
-  ///
-  /// See also:
-  ///
-  ///  * [Form], which provides an `onPopInvoked` callback that is similar.
-  ///  * [registerPopEntry], which adds a [PopEntry] to the list this method
-  ///    checks.
-  ///  * [unregisterPopEntry], which removes a [PopEntry] from the list this
-  ///    method checks.
-  @override
-  RoutePopDisposition get popDisposition {
-    final bool canPop = _popEntries.every((PopEntry popEntry) {
-      return popEntry.canPopNotifier.value;
-    });
-
-    if (!canPop) {
-      return RoutePopDisposition.doNotPop;
-    }
-    return super.popDisposition;
-  }
-
-  @override
-  void onPopInvoked(bool didPop) {
-    for (final PopEntry popEntry in _popEntries) {
-      popEntry.onPopInvoked?.call(didPop);
-    }
-  }
-
   /// Enables this route to veto attempts by the user to dismiss it.
   ///
+  /// {@tool snippet}
+  /// This callback is typically added using a [WillPopScope] widget. That
+  /// widget finds the enclosing [ModalRoute] and uses this function to register
+  /// this callback:
+  ///
+  /// ```dart
+  /// Widget build(BuildContext context) {
+  ///   return WillPopScope(
+  ///     onWillPop: () async {
+  ///       // ask the user if they are sure
+  ///       return true;
+  ///     },
+  ///     child: Container(),
+  ///   );
+  /// }
+  /// ```
+  /// {@end-tool}
+  ///
   /// This callback runs asynchronously and it's possible that it will be called
   /// after its route has been disposed. The callback should check [State.mounted]
   /// before doing anything.
@@ -1584,6 +1548,49 @@
   /// unsaved [Form] data if the user attempts to back out of the form. In that
   /// case, use the [Form.onWillPop] property to register the callback.
   ///
+  /// {@tool snippet}
+  /// To register a callback manually, look up the enclosing [ModalRoute] in a
+  /// [State.didChangeDependencies] callback:
+  ///
+  /// ```dart
+  /// abstract class _MyWidgetState extends State<MyWidget> {
+  ///   ModalRoute<dynamic>? _route;
+  ///
+  ///   // ...
+  ///
+  ///   @override
+  ///   void didChangeDependencies() {
+  ///    super.didChangeDependencies();
+  ///    _route?.removeScopedWillPopCallback(askTheUserIfTheyAreSure);
+  ///    _route = ModalRoute.of(context);
+  ///    _route?.addScopedWillPopCallback(askTheUserIfTheyAreSure);
+  ///   }
+  /// }
+  /// ```
+  /// {@end-tool}
+  ///
+  /// {@tool snippet}
+  /// If you register a callback manually, be sure to remove the callback with
+  /// [removeScopedWillPopCallback] by the time the widget has been disposed. A
+  /// stateful widget can do this in its dispose method (continuing the previous
+  /// example):
+  ///
+  /// ```dart
+  /// abstract class _MyWidgetState2 extends State<MyWidget> {
+  ///   ModalRoute<dynamic>? _route;
+  ///
+  ///   // ...
+  ///
+  ///   @override
+  ///   void dispose() {
+  ///     _route?.removeScopedWillPopCallback(askTheUserIfTheyAreSure);
+  ///     _route = null;
+  ///     super.dispose();
+  ///   }
+  /// }
+  /// ```
+  /// {@end-tool}
+  ///
   /// See also:
   ///
   ///  * [WillPopScope], which manages the registration and unregistration
@@ -1592,10 +1599,6 @@
   ///  * [willPop], which runs the callbacks added with this method.
   ///  * [removeScopedWillPopCallback], which removes a callback from the list
   ///    that [willPop] checks.
-  @Deprecated(
-    'Use registerPopEntry or PopScope instead. '
-    'This feature was deprecated after v3.12.0-1.0.pre.',
-  )
   void addScopedWillPopCallback(WillPopCallback callback) {
     assert(_scopeKey.currentState != null, 'Tried to add a willPop callback to a route that is not currently in the tree.');
     _willPopCallbacks.add(callback);
@@ -1608,69 +1611,11 @@
   ///  * [Form], which provides an `onWillPop` callback that uses this mechanism.
   ///  * [addScopedWillPopCallback], which adds callback to the list
   ///    checked by [willPop].
-  @Deprecated(
-    'Use unregisterPopEntry or PopScope instead. '
-    'This feature was deprecated after v3.12.0-1.0.pre.',
-  )
   void removeScopedWillPopCallback(WillPopCallback callback) {
     assert(_scopeKey.currentState != null, 'Tried to remove a willPop callback from a route that is not currently in the tree.');
     _willPopCallbacks.remove(callback);
   }
 
-  /// Registers the existence of a [PopEntry] in the route.
-  ///
-  /// [PopEntry] instances registered in this way will have their
-  /// [PopEntry.onPopInvoked] callbacks called when a route is popped or a pop
-  /// is attempted. They will also be able to block pop operations with
-  /// [PopEntry.canPopNotifier] through this route's [popDisposition] method.
-  ///
-  /// See also:
-  ///
-  ///  * [unregisterPopEntry], which performs the opposite operation.
-  void registerPopEntry(PopEntry popEntry) {
-    _popEntries.add(popEntry);
-    popEntry.canPopNotifier.addListener(_handlePopEntryChange);
-    _handlePopEntryChange();
-  }
-
-  /// Unregisters a [PopEntry] in the route's widget subtree.
-  ///
-  /// See also:
-  ///
-  ///  * [registerPopEntry], which performs the opposite operation.
-  void unregisterPopEntry(PopEntry popEntry) {
-    _popEntries.remove(popEntry);
-    popEntry.canPopNotifier.removeListener(_handlePopEntryChange);
-    _handlePopEntryChange();
-  }
-
-  void _handlePopEntryChange() {
-    if (!isCurrent) {
-      return;
-    }
-    final NavigationNotification notification = NavigationNotification(
-      // canPop indicates that the originator of the Notification can handle a
-      // pop. In the case of PopScope, it handles pops when canPop is
-      // false. Hence the seemingly backward logic here.
-      canHandlePop: popDisposition == RoutePopDisposition.doNotPop,
-    );
-    // Avoid dispatching a notification in the middle of a build.
-    switch (SchedulerBinding.instance.schedulerPhase) {
-      case SchedulerPhase.postFrameCallbacks:
-        notification.dispatch(subtreeContext);
-      case SchedulerPhase.idle:
-      case SchedulerPhase.midFrameMicrotasks:
-      case SchedulerPhase.persistentCallbacks:
-      case SchedulerPhase.transientCallbacks:
-        SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
-          if (!(subtreeContext?.mounted ?? false)) {
-            return;
-          }
-          notification.dispatch(subtreeContext);
-        });
-    }
-  }
-
   /// True if one or more [WillPopCallback] callbacks exist.
   ///
   /// This method is used to disable the horizontal swipe pop gesture supported
@@ -1688,10 +1633,6 @@
   ///  * [removeScopedWillPopCallback], which removes a callback.
   ///  * [willHandlePopInternally], which reports on another reason why
   ///    a pop might be vetoed.
-  @Deprecated(
-    'Use popDisposition instead. '
-    'This feature was deprecated after v3.12.0-1.0.pre.',
-  )
   @protected
   bool get hasScopedWillPopCallback {
     return _willPopCallbacks.isNotEmpty;
@@ -1832,14 +1773,6 @@
   }
 
   @override
-  bool get willHandlePopInternally {
-    final bool popEntriesCanPop = _popEntries.every((PopEntry popEntry) {
-      return popEntry.canPopNotifier.value;
-    });
-    return !popEntriesCanPop || super.willHandlePopInternally;
-  }
-
-  @override
   String toString() => '${objectRuntimeType(this, 'ModalRoute')}($settings, animation: $_animation)';
 }
 
@@ -2279,33 +2212,3 @@
 ///
 /// See [ModalRoute.buildTransitions] for complete definition of the parameters.
 typedef RouteTransitionsBuilder = Widget Function(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child);
-
-/// A callback type for informing that a navigation pop has been invoked,
-/// whether or not it was handled successfully.
-///
-/// Accepts a didPop boolean indicating whether or not back navigation
-/// succeeded.
-typedef PopInvokedCallback = void Function(bool didPop);
-
-/// Allows listening to and preventing pops.
-///
-/// Can be registered in [ModalRoute] to listen to pops with [onPopInvoked] or
-/// to enable/disable them with [canPopNotifier].
-///
-/// See also:
-///
-///  * [PopScope], which provides similar functionality in a widget.
-///  * [ModalRoute.registerPopEntry], which unregisters instances of this.
-///  * [ModalRoute.unregisterPopEntry], which unregisters instances of this.
-abstract class PopEntry {
-  /// {@macro flutter.widgets.PopScope.onPopInvoked}
-  PopInvokedCallback? get onPopInvoked;
-
-  /// {@macro flutter.widgets.PopScope.canPop}
-  ValueListenable<bool> get canPopNotifier;
-
-  @override
-  String toString() {
-    return 'PopEntry canPop: ${canPopNotifier.value}, onPopInvoked: $onPopInvoked';
-  }
-}
diff --git a/packages/flutter/lib/src/widgets/will_pop_scope.dart b/packages/flutter/lib/src/widgets/will_pop_scope.dart
index eefe437..ab90c7f 100644
--- a/packages/flutter/lib/src/widgets/will_pop_scope.dart
+++ b/packages/flutter/lib/src/widgets/will_pop_scope.dart
@@ -9,25 +9,26 @@
 /// Registers a callback to veto attempts by the user to dismiss the enclosing
 /// [ModalRoute].
 ///
+/// {@tool dartpad}
+/// Whenever the back button is pressed, you will get a callback at [onWillPop],
+/// which returns a [Future]. If the [Future] returns true, the screen is
+/// popped.
+///
+/// ** See code in examples/api/lib/widgets/will_pop_scope/will_pop_scope.0.dart **
+/// {@end-tool}
+///
 /// See also:
 ///
 ///  * [ModalRoute.addScopedWillPopCallback] and [ModalRoute.removeScopedWillPopCallback],
 ///    which this widget uses to register and unregister [onWillPop].
 ///  * [Form], which provides an `onWillPop` callback that enables the form
 ///    to veto a `pop` initiated by the app's back button.
-@Deprecated(
-  'Use PopScope instead. '
-  'This feature was deprecated after v3.12.0-1.0.pre.',
-)
+///
 class WillPopScope extends StatefulWidget {
   /// Creates a widget that registers a callback to veto attempts by the user to
   /// dismiss the enclosing [ModalRoute].
   ///
   /// The [child] argument must not be null.
-  @Deprecated(
-    'Use PopScope instead. '
-    'This feature was deprecated after v3.12.0-1.0.pre.',
-  )
   const WillPopScope({
     super.key,
     required this.child,
diff --git a/packages/flutter/lib/widgets.dart b/packages/flutter/lib/widgets.dart
index 3ca0999..539d6aa 100644
--- a/packages/flutter/lib/widgets.dart
+++ b/packages/flutter/lib/widgets.dart
@@ -81,7 +81,6 @@
 export 'src/widgets/modal_barrier.dart';
 export 'src/widgets/navigation_toolbar.dart';
 export 'src/widgets/navigator.dart';
-export 'src/widgets/navigator_pop_handler.dart';
 export 'src/widgets/nested_scroll_view.dart';
 export 'src/widgets/notification_listener.dart';
 export 'src/widgets/orientation_builder.dart';
@@ -96,7 +95,6 @@
 export 'src/widgets/platform_menu_bar.dart';
 export 'src/widgets/platform_selectable_region_context_menu.dart';
 export 'src/widgets/platform_view.dart';
-export 'src/widgets/pop_scope.dart';
 export 'src/widgets/preferred_size.dart';
 export 'src/widgets/primary_scroll_controller.dart';
 export 'src/widgets/raw_keyboard_listener.dart';
diff --git a/packages/flutter/test/cupertino/tab_scaffold_test.dart b/packages/flutter/test/cupertino/tab_scaffold_test.dart
index b376a92..a8a43b5 100644
--- a/packages/flutter/test/cupertino/tab_scaffold_test.dart
+++ b/packages/flutter/test/cupertino/tab_scaffold_test.dart
@@ -2,14 +2,13 @@
 // 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:flutter/cupertino.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
 
 import '../image_data.dart';
 import '../rendering/rendering_tester.dart' show TestCallbackPainter;
-import '../widgets/navigator_utils.dart';
 
 late List<int> selectedTabs;
 
@@ -1216,132 +1215,6 @@
     expect(find.text('Content 2'), findsNothing);
     expect(find.text('Content 3'), findsNothing);
   });
-
-  group('Android Predictive Back', () {
-    bool? lastFrameworkHandlesBack;
-    setUp(() {
-      // Initialize to false. Because this uses a static boolean internally, it
-      // is not reset between tests or calls to pumpWidget. Explicitly setting
-      // it to false before each test makes them behave deterministically.
-      SystemNavigator.setFrameworkHandlesBack(false);
-      lastFrameworkHandlesBack = null;
-      TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
-        .setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
-          if (methodCall.method == 'SystemNavigator.setFrameworkHandlesBack') {
-            expect(methodCall.arguments, isA<bool>());
-            lastFrameworkHandlesBack = methodCall.arguments as bool;
-          }
-          return;
-        });
-    });
-
-    tearDown(() {
-      TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
-          .setMockMethodCallHandler(SystemChannels.platform, null);
-      SystemNavigator.setFrameworkHandlesBack(true);
-    });
-
-    testWidgets('System back navigation inside of tabs', (WidgetTester tester) async {
-      await tester.pumpWidget(
-        CupertinoApp(
-          home: MediaQuery(
-            data: const MediaQueryData(
-              viewInsets: EdgeInsets.only(bottom: 200),
-            ),
-            child: CupertinoTabScaffold(
-              tabBar: _buildTabBar(),
-              tabBuilder: (BuildContext context, int index) {
-                return CupertinoTabView(
-                  builder: (BuildContext context) {
-                    return CupertinoPageScaffold(
-                      navigationBar: CupertinoNavigationBar(
-                        middle: Text('Page 1 of tab ${index + 1}'),
-                      ),
-                      child: Center(
-                        child: CupertinoButton(
-                          child: const Text('Next page'),
-                          onPressed: () {
-                            Navigator.of(context).push(
-                              CupertinoPageRoute<void>(
-                                builder: (BuildContext context) {
-                                  return CupertinoPageScaffold(
-                                    navigationBar: CupertinoNavigationBar(
-                                      middle: Text('Page 2 of tab ${index + 1}'),
-                                    ),
-                                    child: Center(
-                                      child: CupertinoButton(
-                                        child: const Text('Back'),
-                                        onPressed: () {
-                                          Navigator.of(context).pop();
-                                        },
-                                      ),
-                                    ),
-                                  );
-                                },
-                              ),
-                            );
-                          },
-                        ),
-                      ),
-                    );
-                  },
-                );
-              },
-            ),
-          ),
-        ),
-      );
-
-      expect(find.text('Page 1 of tab 1'), findsOneWidget);
-      expect(find.text('Page 2 of tab 1'), findsNothing);
-      expect(lastFrameworkHandlesBack, isFalse);
-
-      await tester.tap(find.text('Next page'));
-      await tester.pumpAndSettle();
-      expect(find.text('Page 1 of tab 1'), findsNothing);
-      expect(find.text('Page 2 of tab 1'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await simulateSystemBack();
-      await tester.pumpAndSettle();
-      expect(find.text('Page 1 of tab 1'), findsOneWidget);
-      expect(find.text('Page 2 of tab 1'), findsNothing);
-      expect(lastFrameworkHandlesBack, isFalse);
-
-      await tester.tap(find.text('Next page'));
-      await tester.pumpAndSettle();
-      expect(find.text('Page 1 of tab 1'), findsNothing);
-      expect(find.text('Page 2 of tab 1'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await tester.tap(find.text('Tab 2'));
-      await tester.pumpAndSettle();
-      expect(find.text('Page 1 of tab 2'), findsOneWidget);
-      expect(find.text('Page 2 of tab 2'), findsNothing);
-      expect(lastFrameworkHandlesBack, isFalse);
-
-      await tester.tap(find.text('Tab 1'));
-      await tester.pumpAndSettle();
-      expect(find.text('Page 1 of tab 1'), findsNothing);
-      expect(find.text('Page 2 of tab 1'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await simulateSystemBack();
-      await tester.pumpAndSettle();
-      expect(find.text('Page 1 of tab 1'), findsOneWidget);
-      expect(find.text('Page 2 of tab 1'), findsNothing);
-      expect(lastFrameworkHandlesBack, isFalse);
-
-      await tester.tap(find.text('Tab 2'));
-      await tester.pumpAndSettle();
-      expect(find.text('Page 1 of tab 2'), findsOneWidget);
-      expect(find.text('Page 2 of tab 2'), findsNothing);
-      expect(lastFrameworkHandlesBack, isFalse);
-    },
-      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
-      skip: kIsWeb, // [intended] frameworkHandlesBack not used on web.
-    );
-  });
 }
 
 CupertinoTabBar _buildTabBar({ int selectedTab = 0 }) {
diff --git a/packages/flutter/test/widgets/navigator_test.dart b/packages/flutter/test/widgets/navigator_test.dart
index d403ceb..26d1463 100644
--- a/packages/flutter/test/widgets/navigator_test.dart
+++ b/packages/flutter/test/widgets/navigator_test.dart
@@ -6,12 +6,9 @@
 
 import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter/rendering.dart';
 import 'package:flutter/scheduler.dart';
-import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
 
-import 'navigator_utils.dart';
 import 'observer_tester.dart';
 import 'semantics_tester.dart';
 
@@ -4156,719 +4153,6 @@
       expect(const RouteSettings().toString(), 'RouteSettings(none, null)');
     });
   });
-
-  group('Android Predictive Back', () {
-    bool? lastFrameworkHandlesBack;
-    setUp(() {
-      // Initialize to false. Because this uses a static boolean internally, it
-      // is not reset between tests or calls to pumpWidget. Explicitly setting
-      // it to false before each test makes them behave deterministically.
-      SystemNavigator.setFrameworkHandlesBack(false);
-      lastFrameworkHandlesBack = null;
-      TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
-        .setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
-          if (methodCall.method == 'SystemNavigator.setFrameworkHandlesBack') {
-            expect(methodCall.arguments, isA<bool>());
-            lastFrameworkHandlesBack = methodCall.arguments as bool;
-          }
-          return;
-        });
-    });
-
-    tearDown(() {
-      TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
-          .setMockMethodCallHandler(SystemChannels.platform, null);
-      SystemNavigator.setFrameworkHandlesBack(true);
-    });
-
-    testWidgets('a single route is already defaulted to false', (WidgetTester tester) async {
-      await tester.pumpWidget(
-        const MaterialApp(
-          home: Scaffold(
-            body: Text('home'),
-          )
-        )
-      );
-
-      expect(lastFrameworkHandlesBack, isFalse);
-    },
-      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
-      skip: isBrowser, // [intended] only non-web Android supports predictive back.
-    );
-
-    testWidgets('navigating around a single Navigator with .pop', (WidgetTester tester) async {
-      await tester.pumpWidget(
-        MaterialApp(
-          initialRoute: '/',
-          routes: <String, WidgetBuilder>{
-            '/': (BuildContext context) => _LinksPage(
-              title: 'Home page',
-              buttons: <Widget>[
-                TextButton(
-                  onPressed: () {
-                    Navigator.of(context).pushNamed('/one');
-                  },
-                  child: const Text('Go to one'),
-                ),
-              ],
-            ),
-            '/one': (BuildContext context) => _LinksPage(
-              title: 'Page one',
-              buttons: <Widget>[
-                TextButton(
-                  onPressed: () {
-                    Navigator.of(context).pushNamed('/one/one');
-                  },
-                  child: const Text('Go to one/one'),
-                ),
-              ],
-            ),
-            '/one/one': (BuildContext context) => const _LinksPage(
-              title: 'Page one - one',
-            ),
-          },
-        ),
-      );
-
-      expect(find.text('Home page'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isFalse);
-
-      await tester.tap(find.text('Go to one'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Page one'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await tester.tap(find.text('Go back'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Home page'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isFalse);
-
-      await tester.tap(find.text('Go to one'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Page one'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await tester.tap(find.text('Go to one/one'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Page one - one'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await tester.tap(find.text('Go back'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Page one'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await tester.tap(find.text('Go back'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Home page'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isFalse);
-    },
-      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
-      skip: isBrowser, // [intended] only non-web Android supports predictive back.
-    );
-
-    testWidgets('navigating around a single Navigator with system back', (WidgetTester tester) async {
-      await tester.pumpWidget(
-        MaterialApp(
-          initialRoute: '/',
-          routes: <String, WidgetBuilder>{
-            '/': (BuildContext context) => _LinksPage(
-              title: 'Home page',
-              buttons: <Widget>[
-                TextButton(
-                  onPressed: () {
-                    Navigator.of(context).pushNamed('/one');
-                  },
-                  child: const Text('Go to one'),
-                ),
-              ],
-            ),
-            '/one': (BuildContext context) => _LinksPage(
-              title: 'Page one',
-              buttons: <Widget>[
-                TextButton(
-                  onPressed: () {
-                    Navigator.of(context).pushNamed('/one/one');
-                  },
-                  child: const Text('Go to one/one'),
-                ),
-              ],
-            ),
-            '/one/one': (BuildContext context) => const _LinksPage(
-              title: 'Page one - one',
-            ),
-          },
-        ),
-      );
-
-      expect(find.text('Home page'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isFalse);
-
-      await tester.tap(find.text('Go to one'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Page one'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await simulateSystemBack();
-      await tester.pumpAndSettle();
-
-      expect(find.text('Home page'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isFalse);
-
-      await tester.tap(find.text('Go to one'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Page one'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await tester.tap(find.text('Go to one/one'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Page one - one'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await simulateSystemBack();
-      await tester.pumpAndSettle();
-
-      expect(find.text('Page one'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await simulateSystemBack();
-      await tester.pumpAndSettle();
-
-      expect(find.text('Home page'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isFalse);
-    },
-      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
-      skip: isBrowser, // [intended] only non-web Android supports predictive back.
-    );
-
-    testWidgets('a single Navigator with a PopScope that defaults to enabled', (WidgetTester tester) async {
-      bool canPop = true;
-      late StateSetter setState;
-      await tester.pumpWidget(
-        StatefulBuilder(
-          builder: (BuildContext context, StateSetter setter) {
-            setState = setter;
-            return MaterialApp(
-              initialRoute: '/',
-              routes: <String, WidgetBuilder>{
-                '/': (BuildContext context) => _LinksPage(
-                  title: 'Home page',
-                  canPop: canPop,
-                ),
-              },
-            );
-          },
-        ),
-      );
-
-      expect(lastFrameworkHandlesBack, isFalse);
-
-      setState(() {
-        canPop = false;
-      });
-      await tester.pump();
-
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      setState(() {
-        canPop = true;
-      });
-      await tester.pump();
-
-      expect(lastFrameworkHandlesBack, isFalse);
-    },
-      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
-      skip: isBrowser, // [intended] only non-web Android supports predictive back.
-    );
-
-    testWidgets('a single Navigator with a PopScope that defaults to disabled', (WidgetTester tester) async {
-      bool canPop = false;
-      late StateSetter setState;
-      await tester.pumpWidget(
-        StatefulBuilder(
-          builder: (BuildContext context, StateSetter setter) {
-            setState = setter;
-            return MaterialApp(
-              initialRoute: '/',
-              routes: <String, WidgetBuilder>{
-                '/': (BuildContext context) => _LinksPage(
-                  title: 'Home page',
-                  canPop: canPop,
-                ),
-              },
-            );
-          },
-        ),
-      );
-
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      setState(() {
-        canPop = true;
-      });
-      await tester.pump();
-
-      expect(lastFrameworkHandlesBack, isFalse);
-
-      setState(() {
-        canPop = false;
-      });
-      await tester.pump();
-
-      expect(lastFrameworkHandlesBack, isTrue);
-    },
-      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
-      skip: isBrowser, // [intended] only non-web Android supports predictive back.
-    );
-
-    // Test both system back gestures and Navigator.pop.
-    for (final _BackType backType in _BackType.values) {
-      testWidgets('navigating around nested Navigators', (WidgetTester tester) async {
-        final GlobalKey<NavigatorState> nav = GlobalKey<NavigatorState>();
-        final GlobalKey<NavigatorState> nestedNav = GlobalKey<NavigatorState>();
-        Future<void> goBack() async {
-          switch (backType) {
-            case _BackType.systemBack:
-              return simulateSystemBack();
-            case _BackType.navigatorPop:
-              if (nestedNav.currentState != null) {
-                if (nestedNav.currentState!.mounted && nestedNav.currentState!.canPop()) {
-                  return nestedNav.currentState?.pop();
-                }
-              }
-              return nav.currentState?.pop();
-          }
-        }
-        await tester.pumpWidget(
-          MaterialApp(
-            navigatorKey: nav,
-            initialRoute: '/',
-            routes: <String, WidgetBuilder>{
-              '/': (BuildContext context) => _LinksPage(
-                title: 'Home page',
-                buttons: <Widget>[
-                  TextButton(
-                    onPressed: () {
-                      Navigator.of(context).pushNamed('/one');
-                    },
-                    child: const Text('Go to one'),
-                  ),
-                  TextButton(
-                    onPressed: () {
-                      Navigator.of(context).pushNamed('/nested');
-                    },
-                    child: const Text('Go to nested'),
-                  ),
-                ],
-              ),
-              '/one': (BuildContext context) => _LinksPage(
-                title: 'Page one',
-                buttons: <Widget>[
-                  TextButton(
-                    onPressed: () {
-                      Navigator.of(context).pushNamed('/one/one');
-                    },
-                    child: const Text('Go to one/one'),
-                  ),
-                ],
-              ),
-              '/nested': (BuildContext context) => _NestedNavigatorsPage(
-                navigatorKey: nestedNav,
-              ),
-            },
-          ),
-        );
-
-        expect(find.text('Home page'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isFalse);
-
-        await tester.tap(find.text('Go to one'));
-        await tester.pumpAndSettle();
-
-        expect(find.text('Page one'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isTrue);
-
-        await goBack();
-        await tester.pumpAndSettle();
-
-        expect(find.text('Home page'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isFalse);
-
-        await tester.tap(find.text('Go to nested'));
-        await tester.pumpAndSettle();
-
-        expect(find.text('Nested - home'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isTrue);
-
-        await tester.tap(find.text('Go to nested/one'));
-        await tester.pumpAndSettle();
-
-        expect(find.text('Nested - page one'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isTrue);
-
-        await goBack();
-        await tester.pumpAndSettle();
-
-        expect(find.text('Nested - home'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isTrue);
-
-        await goBack();
-        await tester.pumpAndSettle();
-
-        expect(find.text('Home page'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isFalse);
-      },
-        variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
-        skip: isBrowser, // [intended] only non-web Android supports predictive back.
-      );
-    }
-
-    testWidgets('nested Navigators with a nested PopScope', (WidgetTester tester) async {
-      bool canPop = true;
-      late StateSetter setState;
-      await tester.pumpWidget(
-        StatefulBuilder(
-          builder: (BuildContext context, StateSetter setter) {
-            setState = setter;
-            return MaterialApp(
-              initialRoute: '/',
-              routes: <String, WidgetBuilder>{
-                '/': (BuildContext context) => _LinksPage(
-                  title: 'Home page',
-                  buttons: <Widget>[
-                    TextButton(
-                      onPressed: () {
-                        Navigator.of(context).pushNamed('/one');
-                      },
-                      child: const Text('Go to one'),
-                    ),
-                    TextButton(
-                      onPressed: () {
-                        Navigator.of(context).pushNamed('/nested');
-                      },
-                      child: const Text('Go to nested'),
-                    ),
-                  ],
-                ),
-                '/one': (BuildContext context) => _LinksPage(
-                  title: 'Page one',
-                  buttons: <Widget>[
-                    TextButton(
-                      onPressed: () {
-                        Navigator.of(context).pushNamed('/one/one');
-                      },
-                      child: const Text('Go to one/one'),
-                    ),
-                  ],
-                ),
-                '/nested': (BuildContext context) => _NestedNavigatorsPage(
-                  popScopePageEnabled: canPop,
-                ),
-              },
-            );
-          },
-        ),
-      );
-
-      expect(find.text('Home page'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isFalse);
-
-      await tester.tap(find.text('Go to one'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Page one'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await simulateSystemBack();
-      await tester.pumpAndSettle();
-
-      expect(find.text('Home page'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isFalse);
-
-      await tester.tap(find.text('Go to nested'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Nested - home'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await tester.tap(find.text('Go to nested/popscope'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Nested - PopScope'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      // Going back works because canPop is true.
-      await simulateSystemBack();
-      await tester.pumpAndSettle();
-
-      expect(find.text('Nested - home'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await tester.tap(find.text('Go to nested/popscope'));
-      await tester.pumpAndSettle();
-
-      expect(find.text('Nested - PopScope'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      setState(() {
-        canPop = false;
-      });
-      await tester.pumpAndSettle();
-
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      // Now going back doesn't work because canPop is false, but it still
-      // has no effect on the system navigator due to all of the other routes.
-      await simulateSystemBack();
-      await tester.pumpAndSettle();
-
-      expect(find.text('Nested - PopScope'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      setState(() {
-        canPop = true;
-      });
-      await tester.pump();
-
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      // And going back works again after switching canPop back to true.
-      await simulateSystemBack();
-      await tester.pumpAndSettle();
-
-      expect(find.text('Nested - home'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isTrue);
-
-      await simulateSystemBack();
-      await tester.pumpAndSettle();
-
-      expect(find.text('Home page'), findsOneWidget);
-      expect(lastFrameworkHandlesBack, isFalse);
-    },
-      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
-      skip: isBrowser, // [intended] only non-web Android supports predictive back.
-    );
-
-    group('Navigator page API', () {
-      testWidgets('starting with one route as usual', (WidgetTester tester) async {
-        late StateSetter builderSetState;
-        final List<_Page> pages = <_Page>[_Page.home];
-        bool canPop() => pages.length <= 1;
-
-        await tester.pumpWidget(
-          MaterialApp(
-            home: StatefulBuilder(
-              builder: (BuildContext context, StateSetter setState) {
-                builderSetState = setState;
-                return PopScope(
-                  canPop: canPop(),
-                  onPopInvoked: (bool success) {
-                    if (success || pages.last == _Page.noPop) {
-                      return;
-                    }
-                    setState(() {
-                      pages.removeLast();
-                    });
-                  },
-                  child: Navigator(
-                    onPopPage: (Route<void> route, void result) {
-                      if (!route.didPop(null)) {
-                        return false;
-                      }
-                      setState(() {
-                        pages.removeLast();
-                      });
-                      return true;
-                    },
-                    pages: pages.map((_Page page) {
-                      switch (page) {
-                        case _Page.home:
-                          return MaterialPage<void>(
-                            child: _LinksPage(
-                              title: 'Home page',
-                              buttons: <Widget>[
-                                TextButton(
-                                  onPressed: () {
-                                    setState(() {
-                                      pages.add(_Page.one);
-                                    });
-                                  },
-                                  child: const Text('Go to _Page.one'),
-                                ),
-                                TextButton(
-                                  onPressed: () {
-                                    setState(() {
-                                      pages.add(_Page.noPop);
-                                    });
-                                  },
-                                  child: const Text('Go to _Page.noPop'),
-                                ),
-                              ],
-                            ),
-                          );
-                        case _Page.one:
-                          return const MaterialPage<void>(
-                            child: _LinksPage(
-                              title: 'Page one',
-                            ),
-                          );
-                        case _Page.noPop:
-                          return const MaterialPage<void>(
-                            child: _LinksPage(
-                              title: 'Cannot pop page',
-                              canPop: false,
-                            ),
-                          );
-                      }
-                    }).toList(),
-                  ),
-                );
-              },
-            ),
-          ),
-        );
-
-        expect(find.text('Home page'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isFalse);
-
-        await tester.tap(find.text('Go to _Page.one'));
-        await tester.pumpAndSettle();
-
-        expect(find.text('Page one'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isTrue);
-
-        await simulateSystemBack();
-        await tester.pumpAndSettle();
-
-        expect(find.text('Home page'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isFalse);
-
-        await tester.tap(find.text('Go to _Page.noPop'));
-        await tester.pumpAndSettle();
-
-        expect(find.text('Cannot pop page'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isTrue);
-
-        await simulateSystemBack();
-        await tester.pumpAndSettle();
-
-        expect(find.text('Cannot pop page'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isTrue);
-
-        // Circumvent "Cannot pop page" by directly modifying pages.
-        builderSetState(() {
-          pages.removeLast();
-        });
-        await tester.pumpAndSettle();
-
-        expect(find.text('Home page'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isFalse);
-      },
-        variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
-        skip: isBrowser, // [intended] only non-web Android supports predictive back.
-      );
-
-      testWidgets('starting with existing route history', (WidgetTester tester) async {
-        final List<_Page> pages = <_Page>[_Page.home, _Page.one];
-        bool canPop() => pages.length <= 1;
-
-        await tester.pumpWidget(
-          MaterialApp(
-            home: StatefulBuilder(
-              builder: (BuildContext context, StateSetter setState) {
-                return PopScope(
-                  canPop: canPop(),
-                  onPopInvoked: (bool success) {
-                    if (success || pages.last == _Page.noPop) {
-                      return;
-                    }
-                    setState(() {
-                      pages.removeLast();
-                    });
-                  },
-                  child: Navigator(
-                    onPopPage: (Route<void> route, void result) {
-                      if (!route.didPop(null)) {
-                        return false;
-                      }
-                      setState(() {
-                        pages.removeLast();
-                      });
-                      return true;
-                    },
-                    pages: pages.map((_Page page) {
-                      switch (page) {
-                        case _Page.home:
-                          return MaterialPage<void>(
-                            child: _LinksPage(
-                              title: 'Home page',
-                              buttons: <Widget>[
-                                TextButton(
-                                  onPressed: () {
-                                    setState(() {
-                                      pages.add(_Page.one);
-                                    });
-                                  },
-                                  child: const Text('Go to _Page.one'),
-                                ),
-                                TextButton(
-                                  onPressed: () {
-                                    setState(() {
-                                      pages.add(_Page.noPop);
-                                    });
-                                  },
-                                  child: const Text('Go to _Page.noPop'),
-                                ),
-                              ],
-                            ),
-                          );
-                        case _Page.one:
-                          return const MaterialPage<void>(
-                            child: _LinksPage(
-                              title: 'Page one',
-                            ),
-                          );
-                        case _Page.noPop:
-                          return const MaterialPage<void>(
-                            child: _LinksPage(
-                              title: 'Cannot pop page',
-                              canPop: false,
-                            ),
-                          );
-                      }
-                    }).toList(),
-                  ),
-                );
-              },
-            ),
-          ),
-        );
-
-        expect(find.text('Home page'), findsNothing);
-        expect(find.text('Page one'), findsOneWidget);
-        expect(lastFrameworkHandlesBack, isTrue);
-
-        await simulateSystemBack();
-        await tester.pumpAndSettle();
-
-        expect(find.text('Home page'), findsOneWidget);
-        expect(find.text('Page one'), findsNothing);
-        expect(lastFrameworkHandlesBack, isFalse);
-      },
-        variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
-        skip: isBrowser, // [intended] only non-web Android supports predictive back.
-      );
-    });
-  });
 }
 
 typedef AnnouncementCallBack = void Function(Route<dynamic>?);
@@ -5151,153 +4435,3 @@
     );
   }
 }
-
-enum _BackType {
-  systemBack,
-  navigatorPop,
-}
-
-enum _Page {
-  home,
-  one,
-  noPop,
-}
-
-class _LinksPage extends StatelessWidget {
-  const _LinksPage ({
-    this.buttons = const <Widget>[],
-    this.canPop,
-    required this.title,
-    this.onBack,
-  });
-
-  final List<Widget> buttons;
-  final bool? canPop;
-  final VoidCallback? onBack;
-  final String title;
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      body: Center(
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: <Widget>[
-            Text(title),
-            ...buttons,
-            if (Navigator.of(context).canPop())
-              TextButton(
-                onPressed: onBack ?? () {
-                  Navigator.of(context).pop();
-                },
-                child: const Text('Go back'),
-              ),
-            if (canPop != null)
-              PopScope(
-                canPop: canPop!,
-                child: const SizedBox.shrink(),
-              ),
-          ],
-        ),
-      ),
-    );
-  }
-}
-
-class _NestedNavigatorsPage extends StatefulWidget {
-  const _NestedNavigatorsPage({
-    this.popScopePageEnabled,
-    this.navigatorKey,
-  });
-
-  /// Whether the PopScope on the /popscope page is enabled.
-  ///
-  /// If null, then no PopScope is built at all.
-  final bool? popScopePageEnabled;
-
-  final GlobalKey<NavigatorState>? navigatorKey;
-
-  @override
-  State<_NestedNavigatorsPage> createState() => _NestedNavigatorsPageState();
-}
-
-class _NestedNavigatorsPageState extends State<_NestedNavigatorsPage> {
-  late final GlobalKey<NavigatorState> _navigatorKey;
-
-  @override
-  void initState() {
-    super.initState();
-    _navigatorKey = widget.navigatorKey ?? GlobalKey<NavigatorState>();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final BuildContext rootContext = context;
-    return NavigatorPopHandler(
-      onPop: () {
-        if (widget.popScopePageEnabled == false) {
-          return;
-        }
-        _navigatorKey.currentState!.pop();
-      },
-      child: Navigator(
-        key: _navigatorKey,
-        initialRoute: '/',
-        onGenerateRoute: (RouteSettings settings) {
-          switch (settings.name) {
-            case '/':
-              return MaterialPageRoute<void>(
-                builder: (BuildContext context) {
-                  return _LinksPage(
-                    title: 'Nested - home',
-                    onBack: () {
-                      Navigator.of(rootContext).pop();
-                    },
-                    buttons: <Widget>[
-                      TextButton(
-                        onPressed: () {
-                          Navigator.of(context).pushNamed('/one');
-                        },
-                        child: const Text('Go to nested/one'),
-                      ),
-                      TextButton(
-                        onPressed: () {
-                          Navigator.of(context).pushNamed('/popscope');
-                        },
-                        child: const Text('Go to nested/popscope'),
-                      ),
-                      TextButton(
-                        onPressed: () {
-                          Navigator.of(rootContext).pop();
-                        },
-                        child: const Text('Go back out of nested nav'),
-                      ),
-                    ],
-                  );
-                },
-              );
-            case '/one':
-              return MaterialPageRoute<void>(
-                builder: (BuildContext context) {
-                  return const _LinksPage(
-                    title: 'Nested - page one',
-                  );
-                },
-              );
-            case '/popscope':
-              return MaterialPageRoute<void>(
-                builder: (BuildContext context) {
-                  return _LinksPage(
-                    canPop: widget.popScopePageEnabled,
-                    title: 'Nested - PopScope',
-                  );
-                },
-              );
-            default:
-              throw Exception('Invalid route: ${settings.name}');
-          }
-        },
-      ),
-    );
-  }
-}
diff --git a/packages/flutter/test/widgets/navigator_utils.dart b/packages/flutter/test/widgets/navigator_utils.dart
deleted file mode 100644
index 46f1f9b..0000000
--- a/packages/flutter/test/widgets/navigator_utils.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 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.
-
-import 'package:flutter/services.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-/// Simulates a system back, like a back gesture on Android.
-///
-/// Sends the same platform channel message that the engine sends when it
-/// receives a system back.
-Future<void> simulateSystemBack() {
-  return TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
-    'flutter/navigation',
-    const JSONMessageCodec().encodeMessage(<String, dynamic>{
-      'method': 'popRoute',
-    }),
-    (ByteData? _) {},
-  );
-}
diff --git a/packages/flutter/test/widgets/pop_scope_test.dart b/packages/flutter/test/widgets/pop_scope_test.dart
deleted file mode 100644
index c5d0e88..0000000
--- a/packages/flutter/test/widgets/pop_scope_test.dart
+++ /dev/null
@@ -1,361 +0,0 @@
-// Copyright 2014 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.
-
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-import 'navigator_utils.dart';
-
-void main() {
-  bool? lastFrameworkHandlesBack;
-  setUp(() {
-    // Initialize to false. Because this uses a static boolean internally, it
-    // is not reset between tests or calls to pumpWidget. Explicitly setting
-    // it to false before each test makes them behave deterministically.
-    SystemNavigator.setFrameworkHandlesBack(false);
-    lastFrameworkHandlesBack = null;
-    TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
-      .setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
-        if (methodCall.method == 'SystemNavigator.setFrameworkHandlesBack') {
-          expect(methodCall.arguments, isA<bool>());
-          lastFrameworkHandlesBack = methodCall.arguments as bool;
-        }
-        return;
-      });
-  });
-
-  tearDown(() {
-    TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
-        .setMockMethodCallHandler(SystemChannels.platform, null);
-    SystemNavigator.setFrameworkHandlesBack(true);
-  });
-
-  testWidgets('toggling canPop on root route allows/prevents backs', (WidgetTester tester) async {
-    bool canPop = false;
-    late StateSetter setState;
-    late BuildContext context;
-    await tester.pumpWidget(
-      MaterialApp(
-        initialRoute: '/',
-        routes: <String, WidgetBuilder>{
-          '/': (BuildContext buildContext) => Scaffold(
-            body: StatefulBuilder(
-              builder: (BuildContext buildContext, StateSetter stateSetter) {
-                context = buildContext;
-                setState = stateSetter;
-                return PopScope(
-                  canPop: canPop,
-                  child: const Center(
-                    child: Column(
-                      mainAxisAlignment: MainAxisAlignment.center,
-                      children: <Widget>[
-                        Text('Home/PopScope Page'),
-                      ],
-                    ),
-                  ),
-                );
-              },
-            ),
-          ),
-        },
-      ),
-    );
-
-    expect(ModalRoute.of(context)!.popDisposition, RoutePopDisposition.doNotPop);
-
-    setState(() {
-      canPop = true;
-    });
-    await tester.pump();
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isFalse);
-    }
-    expect(ModalRoute.of(context)!.popDisposition, RoutePopDisposition.bubble);
-  },
-    variant: TargetPlatformVariant.all(),
-  );
-
-  testWidgets('toggling canPop on secondary route allows/prevents backs', (WidgetTester tester) async {
-    final GlobalKey<NavigatorState> nav = GlobalKey<NavigatorState>();
-    bool canPop = true;
-    late StateSetter setState;
-    late BuildContext homeContext;
-    late BuildContext oneContext;
-    late bool lastPopSuccess;
-    await tester.pumpWidget(
-      MaterialApp(
-        navigatorKey: nav,
-        initialRoute: '/',
-        routes: <String, WidgetBuilder>{
-          '/': (BuildContext context) {
-            homeContext = context;
-            return Scaffold(
-              body: Center(
-                child: Column(
-                  mainAxisAlignment: MainAxisAlignment.center,
-                  children: <Widget>[
-                    const Text('Home Page'),
-                    TextButton(
-                      onPressed: () {
-                        Navigator.of(context).pushNamed('/one');
-                      },
-                      child: const Text('Next'),
-                    ),
-                  ],
-                ),
-              ),
-            );
-          },
-          '/one': (BuildContext context) => Scaffold(
-            body: StatefulBuilder(
-              builder: (BuildContext context, StateSetter stateSetter) {
-                oneContext = context;
-                setState = stateSetter;
-                return PopScope(
-                  canPop: canPop,
-                  onPopInvoked: (bool didPop) {
-                    lastPopSuccess = didPop;
-                  },
-                  child: const Center(
-                    child: Column(
-                      mainAxisAlignment: MainAxisAlignment.center,
-                      children: <Widget>[
-                        Text('PopScope Page'),
-                      ],
-                    ),
-                  ),
-                );
-              },
-            ),
-          ),
-        },
-      ),
-    );
-
-    expect(find.text('Home Page'), findsOneWidget);
-    expect(ModalRoute.of(homeContext)!.popDisposition, RoutePopDisposition.bubble);
-
-    await tester.tap(find.text('Next'));
-    await tester.pumpAndSettle();
-    expect(find.text('PopScope Page'), findsOneWidget);
-    expect(find.text('Home Page'), findsNothing);
-    expect(ModalRoute.of(oneContext)!.popDisposition, RoutePopDisposition.pop);
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isTrue);
-    }
-
-    // When canPop is true, can use pop to go back.
-    nav.currentState!.maybePop();
-    await tester.pumpAndSettle();
-    expect(lastPopSuccess, true);
-    expect(find.text('Home Page'), findsOneWidget);
-    expect(find.text('PopScope Page'), findsNothing);
-    expect(ModalRoute.of(homeContext)!.popDisposition, RoutePopDisposition.bubble);
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isFalse);
-    }
-
-    await tester.tap(find.text('Next'));
-    await tester.pumpAndSettle();
-    expect(find.text('PopScope Page'), findsOneWidget);
-    expect(find.text('Home Page'), findsNothing);
-    expect(ModalRoute.of(oneContext)!.popDisposition, RoutePopDisposition.pop);
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isTrue);
-    }
-
-    // When canPop is true, can use system back to go back.
-    await simulateSystemBack();
-    await tester.pumpAndSettle();
-    expect(lastPopSuccess, true);
-    expect(find.text('Home Page'), findsOneWidget);
-    expect(find.text('PopScope Page'), findsNothing);
-    expect(ModalRoute.of(homeContext)!.popDisposition, RoutePopDisposition.bubble);
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isFalse);
-    }
-
-    await tester.tap(find.text('Next'));
-    await tester.pumpAndSettle();
-    expect(find.text('PopScope Page'), findsOneWidget);
-    expect(find.text('Home Page'), findsNothing);
-    expect(ModalRoute.of(oneContext)!.popDisposition, RoutePopDisposition.pop);
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isTrue);
-    }
-
-    setState(() {
-      canPop = false;
-    });
-    await tester.pump();
-
-    // When canPop is false, can't use pop to go back.
-    nav.currentState!.maybePop();
-    await tester.pumpAndSettle();
-    expect(lastPopSuccess, false);
-    expect(find.text('PopScope Page'), findsOneWidget);
-    expect(find.text('Home Page'), findsNothing);
-    expect(ModalRoute.of(oneContext)!.popDisposition, RoutePopDisposition.doNotPop);
-
-    // When canPop is false, can't use system back to go back.
-    await simulateSystemBack();
-    await tester.pumpAndSettle();
-    expect(lastPopSuccess, false);
-    expect(find.text('PopScope Page'), findsOneWidget);
-    expect(find.text('Home Page'), findsNothing);
-    expect(ModalRoute.of(oneContext)!.popDisposition, RoutePopDisposition.doNotPop);
-
-    // Toggle canPop back to true and back works again.
-    setState(() {
-      canPop = true;
-    });
-    await tester.pump();
-
-    nav.currentState!.maybePop();
-    await tester.pumpAndSettle();
-    expect(lastPopSuccess, true);
-    expect(find.text('Home Page'), findsOneWidget);
-    expect(find.text('PopScope Page'), findsNothing);
-    expect(ModalRoute.of(homeContext)!.popDisposition, RoutePopDisposition.bubble);
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isFalse);
-    }
-
-    await tester.tap(find.text('Next'));
-    await tester.pumpAndSettle();
-    expect(find.text('PopScope Page'), findsOneWidget);
-    expect(find.text('Home Page'), findsNothing);
-    expect(ModalRoute.of(oneContext)!.popDisposition, RoutePopDisposition.pop);
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isTrue);
-    }
-
-    await simulateSystemBack();
-    await tester.pumpAndSettle();
-    expect(lastPopSuccess, true);
-    expect(find.text('Home Page'), findsOneWidget);
-    expect(find.text('PopScope Page'), findsNothing);
-    expect(ModalRoute.of(homeContext)!.popDisposition, RoutePopDisposition.bubble);
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isFalse);
-    }
-  },
-    variant: TargetPlatformVariant.all(),
-  );
-
-  testWidgets('removing PopScope from the tree removes its effect on navigation', (WidgetTester tester) async {
-    bool usePopScope = true;
-    late StateSetter setState;
-    late BuildContext context;
-    await tester.pumpWidget(
-      MaterialApp(
-        initialRoute: '/',
-        routes: <String, WidgetBuilder>{
-          '/': (BuildContext buildContext) => Scaffold(
-            body: StatefulBuilder(
-              builder: (BuildContext buildContext, StateSetter stateSetter) {
-                context = buildContext;
-                setState = stateSetter;
-                const Widget child = Center(
-                  child: Column(
-                    mainAxisAlignment: MainAxisAlignment.center,
-                    children: <Widget>[
-                      Text('Home/PopScope Page'),
-                    ],
-                  ),
-                );
-                if (!usePopScope) {
-                  return child;
-                }
-                return const PopScope(
-                  canPop: false,
-                  child: child,
-                );
-              },
-            ),
-          ),
-        },
-      ),
-    );
-
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isTrue);
-    }
-    expect(ModalRoute.of(context)!.popDisposition, RoutePopDisposition.doNotPop);
-
-    setState(() {
-      usePopScope = false;
-    });
-    await tester.pump();
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isFalse);
-    }
-    expect(ModalRoute.of(context)!.popDisposition, RoutePopDisposition.bubble);
-  },
-    variant: TargetPlatformVariant.all(),
-  );
-
-  testWidgets('identical PopScopes', (WidgetTester tester) async {
-    bool usePopScope1 = true;
-    bool usePopScope2 = true;
-    late StateSetter setState;
-    late BuildContext context;
-    await tester.pumpWidget(
-      MaterialApp(
-        home: Scaffold(
-          body: StatefulBuilder(
-            builder: (BuildContext buildContext, StateSetter stateSetter) {
-              context = buildContext;
-              setState = stateSetter;
-              return Column(
-                children: <Widget>[
-                  if (usePopScope1)
-                    const PopScope(
-                      canPop: false,
-                      child: Text('hello'),
-                    ),
-                  if (usePopScope2)
-                    const PopScope(
-                      canPop: false,
-                      child: Text('hello'),
-                    ),
-                ],
-              );
-            },
-          ),
-        ),
-      ),
-    );
-
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isTrue);
-    }
-    expect(ModalRoute.of(context)!.popDisposition, RoutePopDisposition.doNotPop);
-
-    // Despite being in the widget tree twice, the ModalRoute has only ever
-    // registered one PopScopeInterface for it. Removing one makes it think that
-    // both have been removed.
-    setState(() {
-      usePopScope1 = false;
-    });
-    await tester.pump();
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isTrue);
-    }
-    expect(ModalRoute.of(context)!.popDisposition, RoutePopDisposition.doNotPop);
-
-    setState(() {
-      usePopScope2 = false;
-    });
-    await tester.pump();
-    if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
-      expect(lastFrameworkHandlesBack, isFalse);
-    }
-    expect(ModalRoute.of(context)!.popDisposition, RoutePopDisposition.bubble);
-  },
-    variant: TargetPlatformVariant.all(),
-  );
-}