diff --git a/dev/benchmarks/complex_layout/macos/Runner/Info.plist b/dev/benchmarks/complex_layout/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/dev/benchmarks/complex_layout/macos/Runner/Info.plist +++ b/dev/benchmarks/complex_layout/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/dev/benchmarks/macrobenchmarks/macos/Runner/Info.plist b/dev/benchmarks/macrobenchmarks/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/dev/benchmarks/macrobenchmarks/macos/Runner/Info.plist +++ b/dev/benchmarks/macrobenchmarks/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/dev/integration_tests/channels/macos/Runner/Info.plist b/dev/integration_tests/channels/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/dev/integration_tests/channels/macos/Runner/Info.plist +++ b/dev/integration_tests/channels/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/dev/integration_tests/flavors/macos/Runner/Info.plist b/dev/integration_tests/flavors/macos/Runner/Info.plist index eba8f244a53..e6e728b5521 100644 --- a/dev/integration_tests/flavors/macos/Runner/Info.plist +++ b/dev/integration_tests/flavors/macos/Runner/Info.plist @@ -29,6 +29,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/dev/integration_tests/flutter_gallery/macos/Runner/Info.plist b/dev/integration_tests/flutter_gallery/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/dev/integration_tests/flutter_gallery/macos/Runner/Info.plist +++ b/dev/integration_tests/flutter_gallery/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/dev/integration_tests/ui/macos/Runner/Info.plist b/dev/integration_tests/ui/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/dev/integration_tests/ui/macos/Runner/Info.plist +++ b/dev/integration_tests/ui/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/dev/manual_tests/macos/Runner/Info.plist b/dev/manual_tests/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/dev/manual_tests/macos/Runner/Info.plist +++ b/dev/manual_tests/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/examples/api/macos/Runner/Info.plist b/examples/api/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/examples/api/macos/Runner/Info.plist +++ b/examples/api/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/examples/flutter_view/macos/Runner/Info.plist b/examples/flutter_view/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/examples/flutter_view/macos/Runner/Info.plist +++ b/examples/flutter_view/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/examples/hello_world/macos/Runner/Info.plist b/examples/hello_world/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/examples/hello_world/macos/Runner/Info.plist +++ b/examples/hello_world/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/examples/image_list/macos/Runner/Info.plist b/examples/image_list/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/examples/image_list/macos/Runner/Info.plist +++ b/examples/image_list/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/examples/layers/macos/Runner/Info.plist b/examples/layers/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/examples/layers/macos/Runner/Info.plist +++ b/examples/layers/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/examples/platform_channel/macos/Runner/Info.plist b/examples/platform_channel/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/examples/platform_channel/macos/Runner/Info.plist +++ b/examples/platform_channel/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/examples/platform_view/macos/Runner/Info.plist b/examples/platform_view/macos/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/examples/platform_view/macos/Runner/Info.plist +++ b/examples/platform_view/macos/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/packages/flutter_tools/lib/src/macos/migrations/flutter_application_migration.dart b/packages/flutter_tools/lib/src/macos/migrations/flutter_application_migration.dart index 14ea4d64ffe..ac0bef66518 100644 --- a/packages/flutter_tools/lib/src/macos/migrations/flutter_application_migration.dart +++ b/packages/flutter_tools/lib/src/macos/migrations/flutter_application_migration.dart @@ -8,7 +8,13 @@ import '../../globals.dart' as globals; import '../../ios/plist_parser.dart'; import '../../xcode_project.dart'; -/// Update the minimum macOS deployment version to the minimum allowed by Xcode without causing a warning. +/// Migrate principle class from FlutterApplication to NSApplication. +/// +/// For several weeks, we required macOS apps to use FlutterApplication as the +/// app's NSPrincipalClass rather than NSApplication. During that time an +/// automated migration migrated the NSPrincipalClass in the Info.plist from +/// NSApplication to FlutterApplication. Now that this is no longer necessary, +/// we apply the reverse migration for anyone who was previously migrated. class FlutterApplicationMigration extends ProjectMigrator { FlutterApplicationMigration( MacOSProject project, @@ -20,29 +26,23 @@ class FlutterApplicationMigration extends ProjectMigrator { @override void migrate() { if (_infoPlistFile.existsSync()) { - final String? principleClass = + final String? principalClass = globals.plistParser.getStringValueFromFile(_infoPlistFile.path, PlistParser.kNSPrincipalClassKey); - if (principleClass == null || principleClass == 'FlutterApplication') { - // No NSPrincipalClass defined, or already converted, so no migration + if (principalClass == null || principalClass == 'NSApplication') { + // No NSPrincipalClass defined, or already converted. No migration // needed. return; } - if (principleClass != 'NSApplication') { - // Only replace NSApplication values, since we don't know why they might - // have substituted something else. - logger.printTrace('${_infoPlistFile.basename} has an ' - '${PlistParser.kNSPrincipalClassKey} of $principleClass, not ' - 'NSApplication, skipping FlutterApplication migration.\nYou will need ' - 'to modify your application class to derive from FlutterApplication.'); + if (principalClass != 'FlutterApplication') { + // If the principal class wasn't already migrated to + // FlutterApplication, there's no need to revert the migration. return; } - logger.printStatus('Updating ${_infoPlistFile.basename} to use FlutterApplication instead of NSApplication.'); - final bool success = globals.plistParser.replaceKey(_infoPlistFile.path, key: PlistParser.kNSPrincipalClassKey, value: 'FlutterApplication'); + logger.printStatus('Updating ${_infoPlistFile.basename} to use NSApplication instead of FlutterApplication.'); + final bool success = globals.plistParser.replaceKey(_infoPlistFile.path, key: PlistParser.kNSPrincipalClassKey, value: 'NSApplication'); if (!success) { logger.printError('Updating ${_infoPlistFile.basename} failed.'); } - } else { - logger.printTrace('${_infoPlistFile.basename} not found, skipping FlutterApplication migration.'); } } } diff --git a/packages/flutter_tools/templates/app_shared/macos.tmpl/Runner/Info.plist b/packages/flutter_tools/templates/app_shared/macos.tmpl/Runner/Info.plist index 55c6534ef34..4789daa6a44 100644 --- a/packages/flutter_tools/templates/app_shared/macos.tmpl/Runner/Info.plist +++ b/packages/flutter_tools/templates/app_shared/macos.tmpl/Runner/Info.plist @@ -27,6 +27,6 @@ NSMainNibFile MainMenu NSPrincipalClass - FlutterApplication + NSApplication diff --git a/packages/flutter_tools/test/general.shard/macos/macos_project_migration_test.dart b/packages/flutter_tools/test/general.shard/macos/macos_project_migration_test.dart index cfcd32e623c..5abb987b76e 100644 --- a/packages/flutter_tools/test/general.shard/macos/macos_project_migration_test.dart +++ b/packages/flutter_tools/test/general.shard/macos/macos_project_migration_test.dart @@ -280,7 +280,7 @@ platform :osx, '10.14' }); }); - group('update NSPrincipalClass to FlutterApplication', () { + group('update NSPrincipalClass from FlutterApplication to NSApplication', () { late MemoryFileSystem memoryFileSystem; late BufferLogger testLogger; late FakeMacOSProject project; @@ -318,7 +318,7 @@ platform :osx, '10.14' macOSProjectMigration.migrate(); expect(infoPlistFile.existsSync(), isFalse); - expect(testLogger.traceText, contains('${infoPlistFile.basename} not found, skipping FlutterApplication migration.')); + expect(testLogger.traceText, isEmpty); expect(testLogger.statusText, isEmpty); }); @@ -333,19 +333,7 @@ platform :osx, '10.14' expect(testLogger.statusText, isEmpty); }); - testWithMocks('skipped if already upgraded', () async { - fakePlistParser.setProperty(PlistParser.kNSPrincipalClassKey, 'FlutterApplication'); - final FlutterApplicationMigration macOSProjectMigration = FlutterApplicationMigration( - project, - testLogger, - ); - infoPlistFile.writeAsStringSync('contents'); // Just so it exists: parser is a fake. - macOSProjectMigration.migrate(); - expect(fakePlistParser.getStringValueFromFile(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), 'FlutterApplication'); - expect(testLogger.statusText, isEmpty); - }); - - testWithMocks('Info.plist migrated to use FlutterApplication', () async { + testWithMocks('skipped if already de-upgraded (or never migrated)', () async { fakePlistParser.setProperty(PlistParser.kNSPrincipalClassKey, 'NSApplication'); final FlutterApplicationMigration macOSProjectMigration = FlutterApplicationMigration( project, @@ -353,9 +341,21 @@ platform :osx, '10.14' ); infoPlistFile.writeAsStringSync('contents'); // Just so it exists: parser is a fake. macOSProjectMigration.migrate(); - expect(fakePlistParser.getStringValueFromFile(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), 'FlutterApplication'); + expect(fakePlistParser.getStringValueFromFile(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), 'NSApplication'); + expect(testLogger.statusText, isEmpty); + }); + + testWithMocks('Info.plist migrated to use NSApplication', () async { + fakePlistParser.setProperty(PlistParser.kNSPrincipalClassKey, 'FlutterApplication'); + final FlutterApplicationMigration macOSProjectMigration = FlutterApplicationMigration( + project, + testLogger, + ); + infoPlistFile.writeAsStringSync('contents'); // Just so it exists: parser is a fake. + macOSProjectMigration.migrate(); + expect(fakePlistParser.getStringValueFromFile(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), 'NSApplication'); // Only print once. - expect('Updating ${infoPlistFile.basename} to use FlutterApplication instead of NSApplication.'.allMatches(testLogger.statusText).length, 1); + expect('Updating ${infoPlistFile.basename} to use NSApplication instead of FlutterApplication.'.allMatches(testLogger.statusText).length, 1); }); testWithMocks('Skip if NSPrincipalClass is not NSApplication', () async { @@ -368,7 +368,7 @@ platform :osx, '10.14' infoPlistFile.writeAsStringSync('contents'); // Just so it exists: parser is a fake. macOSProjectMigration.migrate(); expect(fakePlistParser.getStringValueFromFile(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), differentApp); - expect(testLogger.traceText, contains('${infoPlistFile.basename} has an ${PlistParser.kNSPrincipalClassKey} of $differentApp, not NSApplication, skipping FlutterApplication migration')); + expect(testLogger.traceText, isEmpty); }); }); }