Make plugins work in Swift projects (#15437)

diff --git a/dev/devicelab/bin/tasks/plugin_test.dart b/dev/devicelab/bin/tasks/plugin_test.dart
index 3217961..7dadc8d 100644
--- a/dev/devicelab/bin/tasks/plugin_test.dart
+++ b/dev/devicelab/bin/tasks/plugin_test.dart
@@ -8,5 +8,8 @@
 import 'package:flutter_devicelab/framework/framework.dart';
 
 Future<Null> main() async {
-  await task(new PluginTest('apk'));
+  await task(combine(<TaskFunction>[
+    new PluginTest('apk', <String>['-a', 'java']),
+    new PluginTest('apk', <String>['-a', 'kotlin']),
+  ]));
 }
diff --git a/dev/devicelab/bin/tasks/plugin_test_ios.dart b/dev/devicelab/bin/tasks/plugin_test_ios.dart
index 492e7d6..5992dd3 100644
--- a/dev/devicelab/bin/tasks/plugin_test_ios.dart
+++ b/dev/devicelab/bin/tasks/plugin_test_ios.dart
@@ -8,5 +8,8 @@
 import 'package:flutter_devicelab/framework/framework.dart';
 
 Future<Null> main() async {
-  await task(new PluginTest('ios'));
+  await task(combine(<TaskFunction>[
+    new PluginTest('ios', <String>['-i', 'objc']),
+    new PluginTest('ios', <String>['-i', 'swift']),
+  ]));
 }
diff --git a/dev/devicelab/bin/tasks/plugin_test_win.dart b/dev/devicelab/bin/tasks/plugin_test_win.dart
index 3217961..7dadc8d 100644
--- a/dev/devicelab/bin/tasks/plugin_test_win.dart
+++ b/dev/devicelab/bin/tasks/plugin_test_win.dart
@@ -8,5 +8,8 @@
 import 'package:flutter_devicelab/framework/framework.dart';
 
 Future<Null> main() async {
-  await task(new PluginTest('apk'));
+  await task(combine(<TaskFunction>[
+    new PluginTest('apk', <String>['-a', 'java']),
+    new PluginTest('apk', <String>['-a', 'kotlin']),
+  ]));
 }
diff --git a/dev/devicelab/lib/tasks/plugin_tests.dart b/dev/devicelab/lib/tasks/plugin_tests.dart
index d7baac5..cc736f8 100644
--- a/dev/devicelab/lib/tasks/plugin_tests.dart
+++ b/dev/devicelab/lib/tasks/plugin_tests.dart
@@ -10,17 +10,31 @@
 import 'package:flutter_devicelab/framework/ios.dart';
 import 'package:flutter_devicelab/framework/utils.dart';
 
+/// Combines several TaskFunctions with trivial success value into one.
+TaskFunction combine(List<TaskFunction> tasks) {
+  return () async {
+    for (TaskFunction task in tasks) {
+      final TaskResult result = await task();
+      if (result.failed) {
+        return result;
+      }
+    }
+    return new TaskResult.success(null);
+  };
+}
+
 /// Defines task that creates new Flutter project, adds a plugin, and then
 /// builds the specified [buildTarget].
 class PluginTest {
   final String buildTarget;
+  final List<String> options;
 
-  PluginTest(this.buildTarget);
+  PluginTest(this.buildTarget, this.options);
 
   Future<TaskResult> call() async {
     section('Create Flutter project');
     final Directory tmp = await Directory.systemTemp.createTemp('plugin');
-    final FlutterProject project = await FlutterProject.create(tmp);
+    final FlutterProject project = await FlutterProject.create(tmp, options);
     if (buildTarget == 'ios') {
       await prepareProvisioningCertificates(project.rootPath);
     }
@@ -46,9 +60,12 @@
   final Directory parent;
   final String name;
 
-  static Future<FlutterProject> create(Directory directory) async {
+  static Future<FlutterProject> create(Directory directory, List<String> options) async {
     await inDirectory(directory, () async {
-      await flutter('create', options: <String>['--org', 'io.flutter.devicelab', 'plugintest']);
+      await flutter(
+        'create',
+        options: <String>['--org', 'io.flutter.devicelab']..addAll(options)..add('plugintest')
+      );
     });
     return new FlutterProject(directory, 'plugintest');
   }
diff --git a/packages/flutter_tools/templates/cocoapods/Podfile-swift b/packages/flutter_tools/templates/cocoapods/Podfile-swift
index 6b17e82..aeee647 100644
--- a/packages/flutter_tools/templates/cocoapods/Podfile-swift
+++ b/packages/flutter_tools/templates/cocoapods/Podfile-swift
@@ -67,5 +67,9 @@
     target.build_configurations.each do |config|
       config.build_settings['ENABLE_BITCODE'] = 'NO'
     end
+    # workaround for https://github.com/CocoaPods/CocoaPods/issues/7463
+    target.headers_build_phase.files.each do |file|
+      file.settings = { 'ATTRIBUTES' => ['Public'] }
+    end
   end
 end