| // Copyright 2017 The Chromium 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:mustache/mustache.dart' as mustache; |
| import 'package:yaml/yaml.dart'; |
| |
| import 'base/file_system.dart'; |
| import 'dart/package_map.dart'; |
| import 'globals.dart'; |
| |
| class Plugin { |
| final String name; |
| final String path; |
| final String pluginClass; |
| final String androidPackage; |
| |
| Plugin(this.name, this.path, this.pluginClass, this.androidPackage); |
| |
| factory Plugin.fromYaml(String name, String path, dynamic pluginYaml) { |
| String androidPackage; |
| String pluginClass; |
| if (pluginYaml != null) { |
| androidPackage = pluginYaml['androidPackage']; |
| pluginClass = pluginYaml['pluginClass']; |
| } |
| return new Plugin(name, path, pluginClass, androidPackage); |
| } |
| } |
| |
| Plugin _pluginFromPubspec(String name, Uri packageRoot) { |
| final String pubspecPath = packageRoot.resolve('pubspec.yaml').path; |
| if (!fs.isFileSync(pubspecPath)) |
| return null; |
| final dynamic pubspec = loadYaml(fs.file(pubspecPath).readAsStringSync()); |
| if (pubspec == null) |
| return null; |
| final dynamic flutterConfig = pubspec['flutter']; |
| if (flutterConfig == null || !flutterConfig.containsKey('plugin')) |
| return null; |
| printTrace('Found plugin $name at ${packageRoot.path}'); |
| return new Plugin.fromYaml(name, packageRoot.path, flutterConfig['plugin']); |
| } |
| |
| List<Plugin> _findPlugins(String directory) { |
| final List<Plugin> plugins = <Plugin>[]; |
| Map<String, Uri> packages; |
| try { |
| final String packagesFile = fs.path.join(directory, PackageMap.globalPackagesPath); |
| packages = new PackageMap(packagesFile).map; |
| } on FormatException catch(e) { |
| printTrace('Invalid .packages file: $e'); |
| return plugins; |
| } |
| packages.forEach((String name, Uri uri) { |
| final Uri packageRoot = uri.resolve('..'); |
| final Plugin plugin = _pluginFromPubspec(name, packageRoot); |
| if (plugin != null) |
| plugins.add(plugin); |
| }); |
| return plugins; |
| } |
| |
| void _writeFlutterPluginsList(String directory, List<Plugin> plugins) { |
| final File pluginsProperties = fs.file(fs.path.join(directory, '.flutter-plugins')); |
| final String pluginManifest = |
| plugins.map((Plugin p) => '${p.name}=${p.path}').join('\n'); |
| if (pluginManifest.isNotEmpty) { |
| pluginsProperties.writeAsStringSync('$pluginManifest\n'); |
| } else { |
| if (pluginsProperties.existsSync()) { |
| pluginsProperties.deleteSync(); |
| } |
| } |
| } |
| |
| const String _androidPluginRegistryTemplate = '''package io.flutter.plugins; |
| |
| import io.flutter.app.FlutterActivity; |
| |
| {{#plugins}} |
| import {{package}}.{{class}}; |
| {{/plugins}} |
| |
| /** |
| * Generated file. Do not edit. |
| */ |
| |
| public class PluginRegistry { |
| {{#plugins}} |
| public {{class}} {{name}}; |
| {{/plugins}} |
| |
| public void registerAll(FlutterActivity activity) { |
| {{#plugins}} |
| {{name}} = {{class}}.register(activity); |
| {{/plugins}} |
| } |
| } |
| '''; |
| |
| void _writeAndroidPluginRegistry(String directory, List<Plugin> plugins) { |
| final List<Map<String, dynamic>> androidPlugins = plugins |
| .where((Plugin p) => p.androidPackage != null && p.pluginClass != null) |
| .map((Plugin p) => <String, dynamic>{ |
| 'name': p.name, |
| 'package': p.androidPackage, |
| 'class': p.pluginClass, |
| }) |
| .toList(); |
| final Map<String, dynamic> context = <String, dynamic>{ |
| 'plugins': androidPlugins, |
| }; |
| |
| final String pluginRegistry = |
| new mustache.Template(_androidPluginRegistryTemplate).renderString(context); |
| final String javaSourcePath = fs.path.join(directory, 'android', 'app', 'src', 'main', 'java'); |
| final Directory registryDirectory = |
| fs.directory(fs.path.join(javaSourcePath, 'io', 'flutter', 'plugins')); |
| registryDirectory.createSync(recursive: true); |
| final File registryFile = registryDirectory.childFile('PluginRegistry.java'); |
| registryFile.writeAsStringSync(pluginRegistry); |
| } |
| |
| const String _iosPluginRegistryHeaderTemplate = '''// |
| // Generated file. Do not edit. |
| // |
| |
| #ifndef PluginRegistry_h |
| #define PluginRegistry_h |
| |
| #import <Flutter/Flutter.h> |
| |
| {{#plugins}} |
| #import "{{class}}.h" |
| {{/plugins}} |
| |
| @interface PluginRegistry : NSObject |
| |
| {{#plugins}} |
| @property (readonly, nonatomic) {{class}} *{{name}}; |
| {{/plugins}} |
| |
| - (instancetype)initWithController:(FlutterViewController *)controller; |
| |
| @end |
| |
| #endif /* PluginRegistry_h */ |
| '''; |
| |
| const String _iosPluginRegistryImplementationTemplate = '''// |
| // Generated file. Do not edit. |
| // |
| |
| #import "PluginRegistry.h" |
| |
| @implementation PluginRegistry |
| |
| - (instancetype)initWithController:(FlutterViewController *)controller { |
| if (self = [super init]) { |
| {{#plugins}} |
| _{{name}} = [[{{class}} alloc] initWithController:controller]; |
| {{/plugins}} |
| } |
| return self; |
| } |
| |
| @end |
| '''; |
| |
| void _writeIOSPluginRegistry(String directory, List<Plugin> plugins) { |
| final List<Map<String, dynamic>> iosPlugins = plugins |
| .where((Plugin p) => p.pluginClass != null) |
| .map((Plugin p) => <String, dynamic>{ |
| 'name': p.name, |
| 'class': p.pluginClass, |
| }). |
| toList(); |
| final Map<String, dynamic> context = <String, dynamic>{ |
| 'plugins': iosPlugins, |
| }; |
| |
| final String pluginRegistryHeader = |
| new mustache.Template(_iosPluginRegistryHeaderTemplate).renderString(context); |
| final String pluginRegistryImplementation = |
| new mustache.Template(_iosPluginRegistryImplementationTemplate).renderString(context); |
| final Directory registryDirectory = fs.directory(fs.path.join(directory, 'ios', 'Runner')); |
| registryDirectory.createSync(recursive: true); |
| final File registryHeaderFile = registryDirectory.childFile('PluginRegistry.h'); |
| registryHeaderFile.writeAsStringSync(pluginRegistryHeader); |
| final File registryImplementationFile = registryDirectory.childFile('PluginRegistry.m'); |
| registryImplementationFile.writeAsStringSync(pluginRegistryImplementation); |
| |
| } |
| |
| void injectPlugins({String directory}) { |
| directory ??= fs.currentDirectory.path; |
| final List<Plugin> plugins = _findPlugins(directory); |
| _writeFlutterPluginsList(directory, plugins); |
| if (fs.isDirectorySync(fs.path.join(directory, 'android'))) |
| _writeAndroidPluginRegistry(directory, plugins); |
| if (fs.isDirectorySync(fs.path.join(directory, 'ios'))) |
| _writeIOSPluginRegistry(directory, plugins); |
| } |