Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
e0127526
Unverified
Commit
e0127526
authored
Apr 03, 2020
by
Francisco Magdaleno
Committed by
GitHub
Apr 03, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tools] Don't generate native registrant classes if no pluginClass is defined (#53785)
parent
63f8b9a4
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
203 additions
and
33 deletions
+203
-33
platform_plugins.dart
packages/flutter_tools/lib/src/platform_plugins.dart
+58
-25
plugins.dart
packages/flutter_tools/lib/src/plugins.dart
+25
-4
pubspec_yaml.json
packages/flutter_tools/schema/pubspec_yaml.json
+6
-3
plugin_parsing_test.dart
...flutter_tools/test/general.shard/plugin_parsing_test.dart
+27
-0
plugins_test.dart
packages/flutter_tools/test/general.shard/plugins_test.dart
+87
-1
No files found.
packages/flutter_tools/lib/src/platform_plugins.dart
View file @
e0127526
...
...
@@ -9,6 +9,12 @@ import 'base/common.dart';
import
'base/file_system.dart'
;
import
'globals.dart'
as
globals
;
/// Constant for 'pluginClass' key in plugin maps.
const
String
kPluginClass
=
'pluginClass'
;
/// Constant for 'pluginClass' key in plugin maps.
const
String
kDartPluginClass
=
'dartPluginClass'
;
/// Marker interface for all platform specific plugin config impls.
abstract
class
PluginPlatform
{
const
PluginPlatform
();
...
...
@@ -16,6 +22,12 @@ abstract class PluginPlatform {
Map
<
String
,
dynamic
>
toMap
();
}
abstract
class
NativeOrDartPlugin
{
/// Determines whether the plugin has a native implementation or if it's a
/// Dart-only plugin.
bool
isNative
();
}
/// Contains parameters to template an Android plugin.
///
/// The required fields include: [name] of the plugin, [package] of the plugin and
...
...
@@ -191,19 +203,21 @@ class IOSPlugin extends PluginPlatform {
/// Contains the parameters to template a macOS plugin.
///
/// The
required fields include: [name] of the plugin, and [pluginClass] that will
/// be the entry point to the plugin's native code.
class
MacOSPlugin
extends
PluginPlatform
{
/// The
[name] of the plugin is required. Either [dartPluginClass] or [pluginClass] are required.
///
[pluginClass] will
be the entry point to the plugin's native code.
class
MacOSPlugin
extends
PluginPlatform
implements
NativeOrDartPlugin
{
const
MacOSPlugin
({
@required
this
.
name
,
@required
this
.
pluginClass
,
this
.
pluginClass
,
this
.
dartPluginClass
,
});
factory
MacOSPlugin
.
fromYaml
(
String
name
,
YamlMap
yaml
)
{
assert
(
validate
(
yaml
));
return
MacOSPlugin
(
name:
name
,
pluginClass:
yaml
[
'pluginClass'
]
as
String
,
pluginClass:
yaml
[
kPluginClass
]
as
String
,
dartPluginClass:
yaml
[
kDartPluginClass
]
as
String
,
);
}
...
...
@@ -211,38 +225,45 @@ class MacOSPlugin extends PluginPlatform {
if
(
yaml
==
null
)
{
return
false
;
}
return
yaml
[
'pluginClass'
]
is
String
;
return
yaml
[
kPluginClass
]
is
String
||
yaml
[
kDartPluginClass
]
is
String
;
}
static
const
String
kConfigKey
=
'macos'
;
final
String
name
;
final
String
pluginClass
;
final
String
dartPluginClass
;
@override
bool
isNative
()
=>
pluginClass
!=
null
;
@override
Map
<
String
,
dynamic
>
toMap
()
{
return
<
String
,
dynamic
>{
'name'
:
name
,
'class'
:
pluginClass
,
if
(
pluginClass
!=
null
)
'class'
:
pluginClass
,
if
(
dartPluginClass
!=
null
)
'dartPluginClass'
:
dartPluginClass
,
};
}
}
/// Contains the parameters to template a Windows plugin.
///
/// The
required fields include: [name] of the plugin, and [pluginClass] that will
/// be the entry point to the plugin's native code.
class
WindowsPlugin
extends
PluginPlatform
{
/// The
[name] of the plugin is required. Either [dartPluginClass] or [pluginClass] are required.
///
[pluginClass] will
be the entry point to the plugin's native code.
class
WindowsPlugin
extends
PluginPlatform
implements
NativeOrDartPlugin
{
const
WindowsPlugin
({
@required
this
.
name
,
@required
this
.
pluginClass
,
});
this
.
pluginClass
,
this
.
dartPluginClass
,
})
:
assert
(
pluginClass
!=
null
||
dartPluginClass
!=
null
);
factory
WindowsPlugin
.
fromYaml
(
String
name
,
YamlMap
yaml
)
{
assert
(
validate
(
yaml
));
return
WindowsPlugin
(
name:
name
,
pluginClass:
yaml
[
'pluginClass'
]
as
String
,
pluginClass:
yaml
[
kPluginClass
]
as
String
,
dartPluginClass:
yaml
[
kDartPluginClass
]
as
String
,
);
}
...
...
@@ -250,39 +271,46 @@ class WindowsPlugin extends PluginPlatform {
if
(
yaml
==
null
)
{
return
false
;
}
return
yaml
[
'pluginClass'
]
is
String
;
return
yaml
[
kDartPluginClass
]
is
String
||
yaml
[
kPluginClass
]
is
String
;
}
static
const
String
kConfigKey
=
'windows'
;
final
String
name
;
final
String
pluginClass
;
final
String
dartPluginClass
;
@override
bool
isNative
()
=>
pluginClass
!=
null
;
@override
Map
<
String
,
dynamic
>
toMap
()
{
return
<
String
,
dynamic
>{
'name'
:
name
,
'class'
:
pluginClass
,
'filename'
:
_filenameForCppClass
(
pluginClass
),
if
(
pluginClass
!=
null
)
'class'
:
pluginClass
,
if
(
pluginClass
!=
null
)
'filename'
:
_filenameForCppClass
(
pluginClass
),
if
(
dartPluginClass
!=
null
)
'dartPluginClass'
:
dartPluginClass
,
};
}
}
/// Contains the parameters to template a Linux plugin.
///
/// The
required fields include: [name] of the plugin, and [pluginClass] that will
/// be the entry point to the plugin's native code.
class
LinuxPlugin
extends
PluginPlatform
{
/// The
[name] of the plugin is required. Either [dartPluginClass] or [pluginClass] are required.
///
[pluginClass] will
be the entry point to the plugin's native code.
class
LinuxPlugin
extends
PluginPlatform
implements
NativeOrDartPlugin
{
const
LinuxPlugin
({
@required
this
.
name
,
@required
this
.
pluginClass
,
});
this
.
pluginClass
,
this
.
dartPluginClass
,
})
:
assert
(
pluginClass
!=
null
||
dartPluginClass
!=
null
);
factory
LinuxPlugin
.
fromYaml
(
String
name
,
YamlMap
yaml
)
{
assert
(
validate
(
yaml
));
return
LinuxPlugin
(
name:
name
,
pluginClass:
yaml
[
'pluginClass'
]
as
String
,
pluginClass:
yaml
[
kPluginClass
]
as
String
,
dartPluginClass:
yaml
[
kDartPluginClass
]
as
String
,
);
}
...
...
@@ -290,20 +318,25 @@ class LinuxPlugin extends PluginPlatform {
if
(
yaml
==
null
)
{
return
false
;
}
return
yaml
[
'pluginClass'
]
is
String
;
return
yaml
[
kPluginClass
]
is
String
||
yaml
[
kDartPluginClass
]
is
String
;
}
static
const
String
kConfigKey
=
'linux'
;
final
String
name
;
final
String
pluginClass
;
final
String
dartPluginClass
;
@override
bool
isNative
()
=>
pluginClass
!=
null
;
@override
Map
<
String
,
dynamic
>
toMap
()
{
return
<
String
,
dynamic
>{
'name'
:
name
,
'class'
:
pluginClass
,
'filename'
:
_filenameForCppClass
(
pluginClass
),
if
(
pluginClass
!=
null
)
'class'
:
pluginClass
,
if
(
pluginClass
!=
null
)
'filename'
:
_filenameForCppClass
(
pluginClass
),
if
(
dartPluginClass
!=
null
)
'dartPluginClass'
:
dartPluginClass
,
};
}
}
...
...
packages/flutter_tools/lib/src/plugins.dart
View file @
e0127526
...
...
@@ -871,7 +871,8 @@ Future<void> _writeIOSPluginRegistrant(FlutterProject project, List<Plugin> plug
}
Future
<
void
>
_writeLinuxPluginFiles
(
FlutterProject
project
,
List
<
Plugin
>
plugins
)
async
{
final
List
<
Map
<
String
,
dynamic
>>
linuxPlugins
=
_extractPlatformMaps
(
plugins
,
LinuxPlugin
.
kConfigKey
);
final
List
<
Plugin
>
nativePlugins
=
_filterNativePlugins
(
plugins
,
LinuxPlugin
.
kConfigKey
);
final
List
<
Map
<
String
,
dynamic
>>
linuxPlugins
=
_extractPlatformMaps
(
nativePlugins
,
LinuxPlugin
.
kConfigKey
);
// The generated makefile is checked in, so can't use absolute paths. It is
// included by the main makefile, so relative paths must be relative to that
// file's directory.
...
...
@@ -901,7 +902,8 @@ Future<void> _writeLinuxPluginMakefile(Directory destination, Map<String, dynami
}
Future
<
void
>
_writeMacOSPluginRegistrant
(
FlutterProject
project
,
List
<
Plugin
>
plugins
)
async
{
final
List
<
Map
<
String
,
dynamic
>>
macosPlugins
=
_extractPlatformMaps
(
plugins
,
MacOSPlugin
.
kConfigKey
);
final
List
<
Plugin
>
nativePlugins
=
_filterNativePlugins
(
plugins
,
MacOSPlugin
.
kConfigKey
);
final
List
<
Map
<
String
,
dynamic
>>
macosPlugins
=
_extractPlatformMaps
(
nativePlugins
,
MacOSPlugin
.
kConfigKey
);
final
Map
<
String
,
dynamic
>
context
=
<
String
,
dynamic
>{
'os'
:
'macos'
,
'framework'
:
'FlutterMacOS'
,
...
...
@@ -915,8 +917,25 @@ Future<void> _writeMacOSPluginRegistrant(FlutterProject project, List<Plugin> pl
);
}
/// Filters out Dart-only plugins, which shouldn't be added to the native generated registrants.
List
<
Plugin
>
_filterNativePlugins
(
List
<
Plugin
>
plugins
,
String
platformKey
)
{
return
plugins
.
where
((
Plugin
element
)
{
final
PluginPlatform
plugin
=
element
.
platforms
[
platformKey
];
if
(
plugin
==
null
)
{
return
false
;
}
if
(
plugin
is
NativeOrDartPlugin
)
{
return
(
plugin
as
NativeOrDartPlugin
).
isNative
();
}
// Not all platforms have the ability to create Dart-only plugins. Therefore, any plugin that doesn't
// implement NativeOrDartPlugin is always native.
return
true
;
}).
toList
();
}
Future
<
void
>
_writeWindowsPluginFiles
(
FlutterProject
project
,
List
<
Plugin
>
plugins
)
async
{
final
List
<
Map
<
String
,
dynamic
>>
windowsPlugins
=
_extractPlatformMaps
(
plugins
,
WindowsPlugin
.
kConfigKey
);
final
List
<
Plugin
>
nativePlugins
=
_filterNativePlugins
(
plugins
,
WindowsPlugin
.
kConfigKey
);
final
List
<
Map
<
String
,
dynamic
>>
windowsPlugins
=
_extractPlatformMaps
(
nativePlugins
,
WindowsPlugin
.
kConfigKey
);
final
Map
<
String
,
dynamic
>
context
=
<
String
,
dynamic
>{
'plugins'
:
windowsPlugins
,
};
...
...
@@ -1092,7 +1111,9 @@ Future<void> injectPlugins(FlutterProject project, {bool checkProjects = false})
}
if
(
featureFlags
.
isWindowsEnabled
&&
project
.
windows
.
existsSync
())
{
await
_writeWindowsPluginFiles
(
project
,
plugins
);
await
VisualStudioSolutionUtils
(
project:
project
.
windows
,
fileSystem:
globals
.
fs
).
updatePlugins
(
plugins
);
final
List
<
Plugin
>
nativePlugins
=
_filterNativePlugins
(
plugins
,
WindowsPlugin
.
kConfigKey
);
await
VisualStudioSolutionUtils
(
project:
project
.
windows
,
fileSystem:
globals
.
fs
).
updatePlugins
(
nativePlugins
);
}
for
(
final
XcodeBasedProject
subproject
in
<
XcodeBasedProject
>[
project
.
ios
,
project
.
macos
])
{
if
(!
project
.
isModule
&&
(!
checkProjects
||
subproject
.
existsSync
()))
{
...
...
packages/flutter_tools/schema/pubspec_yaml.json
View file @
e0127526
...
...
@@ -80,21 +80,24 @@
"type"
:
"object"
,
"additionalProperties"
:
false
,
"properties"
:
{
"pluginClass"
:
{
"type"
:
"string"
}
"pluginClass"
:
{
"type"
:
"string"
},
"dartPluginClass"
:
{
"type"
:
"string"
}
}
},
"macos"
:
{
"type"
:
"object"
,
"additionalProperties"
:
false
,
"properties"
:
{
"pluginClass"
:
{
"type"
:
"string"
}
"pluginClass"
:
{
"type"
:
"string"
},
"dartPluginClass"
:
{
"type"
:
"string"
}
}
},
"windows"
:
{
"type"
:
"object"
,
"additionalProperties"
:
false
,
"properties"
:
{
"pluginClass"
:
{
"type"
:
"string"
}
"pluginClass"
:
{
"type"
:
"string"
},
"dartPluginClass"
:
{
"type"
:
"string"
}
}
}
}
...
...
packages/flutter_tools/test/general.shard/plugin_parsing_test.dart
View file @
e0127526
...
...
@@ -122,6 +122,33 @@ void main() {
expect
(
windowsPlugin
.
pluginClass
,
'WinSamplePlugin'
);
});
test
(
'Allow for Dart-only plugins without a pluginClass'
,
()
{
/// This is currently supported only on macOS, linux, Windows.
const
String
pluginYamlRaw
=
'implements: same_plugin
\n
'
// this should be ignored by the tool
'platforms:
\n
'
' linux:
\n
'
' dartPluginClass: LSamplePlugin
\n
'
' macos:
\n
'
' dartPluginClass: MSamplePlugin
\n
'
' windows:
\n
'
' dartPluginClass: WinSamplePlugin
\n
'
;
final
dynamic
pluginYaml
=
loadYaml
(
pluginYamlRaw
);
final
Plugin
plugin
=
Plugin
.
fromYaml
(
_kTestPluginName
,
_kTestPluginPath
,
pluginYaml
as
YamlMap
,
const
<
String
>[]);
final
LinuxPlugin
linuxPlugin
=
plugin
.
platforms
[
LinuxPlugin
.
kConfigKey
]
as
LinuxPlugin
;
final
MacOSPlugin
macOSPlugin
=
plugin
.
platforms
[
MacOSPlugin
.
kConfigKey
]
as
MacOSPlugin
;
final
WindowsPlugin
windowsPlugin
=
plugin
.
platforms
[
WindowsPlugin
.
kConfigKey
]
as
WindowsPlugin
;
expect
(
linuxPlugin
.
pluginClass
,
isNull
);
expect
(
macOSPlugin
.
pluginClass
,
isNull
);
expect
(
windowsPlugin
.
pluginClass
,
isNull
);
expect
(
linuxPlugin
.
dartPluginClass
,
'LSamplePlugin'
);
expect
(
macOSPlugin
.
dartPluginClass
,
'MSamplePlugin'
);
expect
(
windowsPlugin
.
dartPluginClass
,
'WinSamplePlugin'
);
});
test
(
'Legacy Format and Multi-Platform Format together is not allowed and error message contains plugin name'
,
()
{
const
String
pluginYamlRaw
=
'androidPackage: com.flutter.dev
\n
'
'platforms:
\n
'
...
...
packages/flutter_tools/test/general.shard/plugins_test.dart
View file @
e0127526
...
...
@@ -6,6 +6,7 @@ import 'dart:convert';
import
'package:file/file.dart'
;
import
'package:file/memory.dart'
;
import
'package:file_testing/file_testing.dart'
;
import
'package:flutter_tools/src/base/time.dart'
;
import
'package:flutter_tools/src/dart/package_map.dart'
;
import
'package:flutter_tools/src/features.dart'
;
...
...
@@ -56,6 +57,8 @@ void main() {
when
(
flutterProject
.
macos
).
thenReturn
(
macosProject
);
when
(
macosProject
.
podfile
).
thenReturn
(
flutterProject
.
directory
.
childDirectory
(
'macos'
).
childFile
(
'Podfile'
));
when
(
macosProject
.
podManifestLock
).
thenReturn
(
flutterProject
.
directory
.
childDirectory
(
'macos'
).
childFile
(
'Podfile.lock'
));
final
Directory
macosManagedDirectory
=
flutterProject
.
directory
.
childDirectory
(
'macos'
).
childDirectory
(
'Flutter'
);
when
(
macosProject
.
managedDirectory
).
thenReturn
(
macosManagedDirectory
);
when
(
macosProject
.
pluginConfigKey
).
thenReturn
(
'macos'
);
when
(
macosProject
.
existsSync
()).
thenReturn
(
false
);
androidProject
=
MockAndroidProject
();
...
...
@@ -129,7 +132,6 @@ void main() {
'''
);
}
void
createNewJavaPlugin1
()
{
final
Directory
pluginUsingJavaAndNewEmbeddingDir
=
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_plugin_using_java_and_new_embedding_dir.'
);
...
...
@@ -879,6 +881,33 @@ web_plugin_with_nested:${webPluginWithNestedFile.childDirectory('lib').uri.toStr
FeatureFlags:
()
=>
featureFlags
,
});
testUsingContext
(
'Injecting creates generated macos registrant, but does not include Dart-only plugins'
,
()
async
{
when
(
macosProject
.
existsSync
()).
thenReturn
(
true
);
when
(
featureFlags
.
isMacOSEnabled
).
thenReturn
(
true
);
when
(
flutterProject
.
isModule
).
thenReturn
(
true
);
// Create a plugin without a pluginClass.
dummyPackageDirectory
.
parent
.
childFile
(
'pubspec.yaml'
)
..
createSync
(
recursive:
true
)
..
writeAsStringSync
(
'''
flutter:
plugin:
platforms:
macos:
dartPluginClass: SomePlugin
'''
);
await
injectPlugins
(
flutterProject
,
checkProjects:
true
);
final
File
registrantFile
=
macosProject
.
managedDirectory
.
childFile
(
'GeneratedPluginRegistrant.swift'
);
expect
(
registrantFile
,
exists
);
expect
(
registrantFile
,
isNot
(
contains
(
'SomePlugin'
)));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fs
,
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
FeatureFlags:
()
=>
featureFlags
,
});
testUsingContext
(
'Injecting creates generated Linux registrant'
,
()
async
{
when
(
linuxProject
.
existsSync
()).
thenReturn
(
true
);
when
(
featureFlags
.
isLinuxEnabled
).
thenReturn
(
true
);
...
...
@@ -899,6 +928,33 @@ web_plugin_with_nested:${webPluginWithNestedFile.childDirectory('lib').uri.toStr
FeatureFlags:
()
=>
featureFlags
,
});
testUsingContext
(
'Injecting creates generated Linux registrant, but does not include Dart-only plugins'
,
()
async
{
when
(
linuxProject
.
existsSync
()).
thenReturn
(
true
);
when
(
featureFlags
.
isLinuxEnabled
).
thenReturn
(
true
);
when
(
flutterProject
.
isModule
).
thenReturn
(
false
);
// Create a plugin without a pluginClass.
dummyPackageDirectory
.
parent
.
childFile
(
'pubspec.yaml'
)
..
createSync
(
recursive:
true
)
..
writeAsStringSync
(
'''
flutter:
plugin:
platforms:
linux:
dartPluginClass: SomePlugin
'''
);
await
injectPlugins
(
flutterProject
,
checkProjects:
true
);
final
File
registrantImpl
=
linuxProject
.
managedDirectory
.
childFile
(
'generated_plugin_registrant.cc'
);
expect
(
registrantImpl
,
exists
);
expect
(
registrantImpl
,
isNot
(
contains
(
'SomePlugin'
)));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fs
,
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
FeatureFlags:
()
=>
featureFlags
,
});
testUsingContext
(
'Injecting creates generated Linux plugin makefile'
,
()
async
{
when
(
linuxProject
.
existsSync
()).
thenReturn
(
true
);
when
(
featureFlags
.
isLinuxEnabled
).
thenReturn
(
true
);
...
...
@@ -946,6 +1002,36 @@ web_plugin_with_nested:${webPluginWithNestedFile.childDirectory('lib').uri.toStr
FeatureFlags:
()
=>
featureFlags
,
});
testUsingContext
(
'Injecting creates generated Windows registrant, but does not include Dart-only plugins'
,
()
async
{
when
(
windowsProject
.
existsSync
()).
thenReturn
(
true
);
when
(
featureFlags
.
isWindowsEnabled
).
thenReturn
(
true
);
when
(
flutterProject
.
isModule
).
thenReturn
(
false
);
// Create a plugin without a pluginClass.
dummyPackageDirectory
.
parent
.
childFile
(
'pubspec.yaml'
)
..
createSync
(
recursive:
true
)
..
writeAsStringSync
(
'''
flutter:
plugin:
platforms:
windows:
dartPluginClass: SomePlugin
'''
);
createDummyWindowsSolutionFile
();
createDummyPluginWindowsProjectFile
();
await
injectPlugins
(
flutterProject
,
checkProjects:
true
);
final
File
registrantImpl
=
windowsProject
.
managedDirectory
.
childFile
(
'generated_plugin_registrant.cc'
);
expect
(
registrantImpl
,
exists
);
expect
(
registrantImpl
,
isNot
(
contains
(
'SomePlugin'
)));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fs
,
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
FeatureFlags:
()
=>
featureFlags
,
});
testUsingContext
(
'Injecting creates generated Windows plugin properties'
,
()
async
{
when
(
windowsProject
.
existsSync
()).
thenReturn
(
true
);
when
(
featureFlags
.
isWindowsEnabled
).
thenReturn
(
true
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment