Let iOS auto-signing tool handle Googler scenario (#16010)

* Let iOS auto-signing tool handle Googler scenario

* Forgot to update tests
diff --git a/packages/flutter_tools/lib/src/ios/code_signing.dart b/packages/flutter_tools/lib/src/ios/code_signing.dart
index 54f2289..2e1d5c2 100644
--- a/packages/flutter_tools/lib/src/ios/code_signing.dart
+++ b/packages/flutter_tools/lib/src/ios/code_signing.dart
@@ -83,9 +83,15 @@
 /// signing identities in the user's keychain prompting a choice if multiple
 /// are found.
 ///
+/// Returns a set of build configuration settings that uses the selected
+/// signing identities.
+///
 /// Will return null if none are found, if the user cancels or if the Xcode
 /// project has a development team set in the project's build settings.
-Future<String> getCodeSigningIdentityDevelopmentTeam({BuildableIOSApp iosApp, bool usesTerminalUi: true}) async{
+Future<Map<String, String>> getCodeSigningIdentityDevelopmentTeam({
+  BuildableIOSApp iosApp,
+  bool usesTerminalUi: true
+}) async{
   if (iosApp.buildSettings == null)
     return null;
 
@@ -154,9 +160,19 @@
   if (await opensslProcess.exitCode != 0)
     return null;
 
-  return _certificateOrganizationalUnitExtractionPattern
+  final Map<String, String> signingConfigs = <String, String> {
+    'DEVELOPMENT_TEAM': _certificateOrganizationalUnitExtractionPattern
       .firstMatch(opensslOutput)
-      ?.group(1);
+      ?.group(1),
+  };
+
+  if (opensslOutput.contains('iPhone Developer: Google Development')) {
+    signingConfigs['PROVISIONING_PROFILE_SPECIFIER'] = 'Google Development';
+    signingConfigs['CODE_SIGN_STYLE'] = 'Manual';
+    printStatus("Manually selecting Google's mobile provisioning profile (see go/google-flutter-signing).");
+  }
+
+  return signingConfigs;
 }
 
 Future<String> _chooseSigningIdentity(List<String> validCodeSigningIdentities, bool usesTerminalUi) async {
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index 7356716..ff3d9d1 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -225,9 +225,9 @@
     return new XcodeBuildResult(success: false);
   }
 
-  String developmentTeam;
+  Map<String, String> autoSigningConfigs;
   if (codesign && buildForDevice)
-    developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app, usesTerminalUi: usesTerminalUi);
+    autoSigningConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app, usesTerminalUi: usesTerminalUi);
 
   // Before the build, all service definitions must be updated and the dylibs
   // copied over to a location that is suitable for Xcodebuild to find them.
@@ -287,8 +287,10 @@
     buildCommands.add('-quiet');
   }
 
-  if (developmentTeam != null) {
-    buildCommands.add('DEVELOPMENT_TEAM=$developmentTeam');
+  if (autoSigningConfigs != null) {
+    for (MapEntry<String, String> signingConfig in autoSigningConfigs.entries) {
+      buildCommands.add('${signingConfig.key}=${signingConfig.value}');
+    }
     buildCommands.add('-allowProvisioningUpdates');
     buildCommands.add('-allowProvisioningDeviceRegistration');
   }
diff --git a/packages/flutter_tools/test/ios/code_signing_test.dart b/packages/flutter_tools/test/ios/code_signing_test.dart
index 5137b30..fcd5522 100644
--- a/packages/flutter_tools/test/ios/code_signing_test.dart
+++ b/packages/flutter_tools/test/ios/code_signing_test.dart
@@ -38,8 +38,8 @@
 
     testUsingContext('No auto-sign if Xcode project settings are not available', () async {
       app = new BuildableIOSApp(projectBundleId: 'test.app');
-      final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
-      expect(developmentTeam, isNull);
+      final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
+      expect(signingConfigs, isNull);
     });
 
     testUsingContext('No discovery if development team specified in Xcode project', () async {
@@ -49,8 +49,8 @@
           'DEVELOPMENT_TEAM': 'abc',
         },
       );
-      final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
-      expect(developmentTeam, isNull);
+      final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
+      expect(signingConfigs, isNull);
       expect(testLogger.statusText, equals(
         'Automatically signing iOS for device deployment using specified development team in Xcode project: abc\n'
       ));
@@ -59,8 +59,8 @@
     testUsingContext('No auto-sign if security or openssl not available', () async {
       when(mockProcessManager.runSync(<String>['which', 'security']))
           .thenReturn(exitsFail);
-      final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
-      expect(developmentTeam, isNull);
+      final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
+      expect(signingConfigs, isNull);
     },
     overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
@@ -75,12 +75,12 @@
         argThat(contains('find-identity')), environment: any, workingDirectory: any)
       ).thenReturn(exitsHappy);
 
-      String developmentTeam;
+      Map<String, String> signingConfigs;
       try {
-        developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
+        signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
         fail('No identity should throw tool error');
       } on ToolExit {
-        expect(developmentTeam, isNull);
+        expect(signingConfigs, isNull);
         expect(testLogger.errorText, contains('No valid code signing certificates were found'));
       }
     },
@@ -132,12 +132,71 @@
       when(mockProcess.stderr).thenAnswer((Invocation invocation) => mockStdErr);
       when(mockProcess.exitCode).thenReturn(0);
 
-      final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
+      final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
 
       expect(testLogger.statusText, contains('iPhone Developer: Profile 1 (1111AAAA11)'));
       expect(testLogger.errorText, isEmpty);
       verify(mockStdIn.write('This is a mock certificate'));
-      expect(developmentTeam, '3333CCCC33');
+      expect(signingConfigs, <String, String> {'DEVELOPMENT_TEAM': '3333CCCC33'});
+    },
+    overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext('Test Google cert also manually selects a provisioning profile', () async {
+      when(mockProcessManager.runSync(<String>['which', 'security']))
+          .thenReturn(exitsHappy);
+      when(mockProcessManager.runSync(<String>['which', 'openssl']))
+          .thenReturn(exitsHappy);
+      when(mockProcessManager.runSync(
+        argThat(contains('find-identity')), environment: any, workingDirectory: any,
+      )).thenReturn(new ProcessResult(
+        1, // pid
+        0, // exitCode
+        '''
+1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Google Development (1111AAAA11)"
+    1 valid identities found''',
+        ''
+      ));
+      when(mockProcessManager.runSync(
+        <String>['security', 'find-certificate', '-c', '1111AAAA11', '-p'],
+        environment: any,
+        workingDirectory: any,
+      )).thenReturn(new ProcessResult(
+        1, // pid
+        0, // exitCode
+        'This is a mock certificate',
+        '',
+      ));
+
+      final MockProcess mockProcess = new MockProcess();
+      final MockStdIn mockStdIn = new MockStdIn();
+      final MockStream mockStdErr = new MockStream();
+
+      when(mockProcessManager.start(
+        argThat(contains('openssl')), environment: any, workingDirectory: any,
+      )).thenAnswer((Invocation invocation) => new Future<Process>.value(mockProcess));
+
+      when(mockProcess.stdin).thenReturn(mockStdIn);
+      when(mockProcess.stdout)
+          .thenAnswer((Invocation invocation) => new Stream<List<int>>.fromFuture(
+            new Future<List<int>>.value(utf8.encode(
+              'subject= /CN=iPhone Developer: Google Development (1111AAAA11)/OU=3333CCCC33/O=My Team/C=US'
+            ))
+          ));
+      when(mockProcess.stderr).thenAnswer((Invocation invocation) => mockStdErr);
+      when(mockProcess.exitCode).thenReturn(0);
+
+      final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
+
+      expect(testLogger.statusText, contains('iPhone Developer: Google Development (1111AAAA11)'));
+      expect(testLogger.errorText, isEmpty);
+      verify(mockStdIn.write('This is a mock certificate'));
+      expect(signingConfigs, <String, String> {
+        'DEVELOPMENT_TEAM': '3333CCCC33',
+        'PROVISIONING_PROFILE_SPECIFIER': 'Google Development',
+        'CODE_SIGN_STYLE': 'Manual',
+      });
     },
     overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
@@ -191,7 +250,7 @@
       when(mockOpenSslProcess.stderr).thenAnswer((Invocation invocation) => mockOpenSslStdErr);
       when(mockOpenSslProcess.exitCode).thenAnswer((_) => new Future<int>.value(0));
 
-      final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
+      final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
 
       expect(
         testLogger.statusText,
@@ -203,7 +262,7 @@
       );
       expect(testLogger.errorText, isEmpty);
       verify(mockOpenSslStdIn.write('This is a mock certificate'));
-      expect(developmentTeam, '4444DDDD44');
+      expect(signingConfigs, <String, String> {'DEVELOPMENT_TEAM':'4444DDDD44'});
 
       verify(config.setValue('ios-signing-cert', 'iPhone Developer: Profile 3 (3333CCCC33)'));
     },
@@ -261,7 +320,7 @@
       when(mockOpenSslProcess.stderr).thenAnswer((Invocation invocation) => mockOpenSslStdErr);
       when(mockOpenSslProcess.exitCode).thenAnswer((_) => new Future<int>.value(0));
 
-      final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app, usesTerminalUi: false);
+      final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app, usesTerminalUi: false);
 
       expect(
         testLogger.statusText,
@@ -269,7 +328,7 @@
       );
       expect(testLogger.errorText, isEmpty);
       verify(mockOpenSslStdIn.write('This is a mock certificate'));
-      expect(developmentTeam, '5555EEEE55');
+      expect(signingConfigs, <String, String> {'DEVELOPMENT_TEAM':'5555EEEE55'});
     },
     overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
@@ -324,7 +383,7 @@
       when(mockOpenSslProcess.exitCode).thenAnswer((_) => new Future<int>.value(0));
       when<String>(mockConfig.getValue('ios-signing-cert')).thenReturn('iPhone Developer: Profile 3 (3333CCCC33)');
 
-      final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
+      final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
 
       expect(
         testLogger.statusText,
@@ -336,7 +395,7 @@
       );
       expect(testLogger.errorText, isEmpty);
       verify(mockOpenSslStdIn.write('This is a mock certificate'));
-      expect(developmentTeam, '4444DDDD44');
+      expect(signingConfigs, <String, String> {'DEVELOPMENT_TEAM':'4444DDDD44'});
     },
     overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
@@ -393,7 +452,7 @@
       when(mockOpenSslProcess.exitCode).thenAnswer((_) => new Future<int>.value(0));
       when<String>(mockConfig.getValue('ios-signing-cert')).thenReturn('iPhone Developer: Invalid Profile');
 
-      final String developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
+      final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
 
       expect(
         testLogger.errorText,
@@ -403,7 +462,7 @@
         testLogger.statusText,
         contains('Certificate choice "iPhone Developer: Profile 3 (3333CCCC33)"')
       );
-      expect(developmentTeam, '4444DDDD44');
+      expect(signingConfigs, <String, String> {'DEVELOPMENT_TEAM':'4444DDDD44'});
       verify(config.setValue('ios-signing-cert', 'iPhone Developer: Profile 3 (3333CCCC33)'));
     },
     overrides: <Type, Generator>{