Commit ef43d000 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Ignore some missing plugins. (#8852)

Fixes #8850
parent 9f770ec8
...@@ -42,7 +42,7 @@ class MethodCall { ...@@ -42,7 +42,7 @@ class MethodCall {
/// ///
/// Must be a valid value for the [MethodCodec] used. /// Must be a valid value for the [MethodCodec] used.
final dynamic arguments; final dynamic arguments;
@override @override
bool operator== (dynamic other) { bool operator== (dynamic other) {
if (identical(this, other)) if (identical(this, other))
...@@ -64,7 +64,7 @@ class MethodCall { ...@@ -64,7 +64,7 @@ class MethodCall {
return b is Map && _deepEqualsMap(a, b); return b is Map && _deepEqualsMap(a, b);
return false; return false;
} }
bool _deepEqualsList(List<dynamic> a, List<dynamic> b) { bool _deepEqualsList(List<dynamic> a, List<dynamic> b) {
if (a.length != b.length) if (a.length != b.length)
return false; return false;
...@@ -84,7 +84,7 @@ class MethodCall { ...@@ -84,7 +84,7 @@ class MethodCall {
} }
return true; return true;
} }
@override @override
String toString() => '$runtimeType($method, $arguments)'; String toString() => '$runtimeType($method, $arguments)';
} }
...@@ -120,7 +120,7 @@ abstract class MethodCodec { ...@@ -120,7 +120,7 @@ abstract class MethodCodec {
/// Encodes a successful [result] into a binary envelope. /// Encodes a successful [result] into a binary envelope.
ByteData encodeSuccessEnvelope(dynamic result); ByteData encodeSuccessEnvelope(dynamic result);
/// Encodes an error result into a binary envelope. /// Encodes an error result into a binary envelope.
/// ///
/// The specified error [code], human-readable error [message], and error /// The specified error [code], human-readable error [message], and error
...@@ -166,3 +166,9 @@ class PlatformException implements Exception { ...@@ -166,3 +166,9 @@ class PlatformException implements Exception {
@override @override
String toString() => 'PlatformException($code, $message, $details)'; String toString() => 'PlatformException($code, $message, $details)';
} }
/// Thrown to indicate that a platform interaction failed to find the plugin.
class MissingPluginException implements Exception {
@override
String toString() => 'MissingPluginException';
}
...@@ -121,6 +121,8 @@ class JSONMethodCodec implements MethodCodec { ...@@ -121,6 +121,8 @@ class JSONMethodCodec implements MethodCodec {
@override @override
dynamic decodeEnvelope(ByteData envelope) { dynamic decodeEnvelope(ByteData envelope) {
if (envelope == null)
throw new MissingPluginException();
final dynamic decoded = const JSONMessageCodec().decodeMessage(envelope); final dynamic decoded = const JSONMessageCodec().decodeMessage(envelope);
if (decoded is! List) if (decoded is! List)
throw new FormatException('Expected envelope List, got $decoded'); throw new FormatException('Expected envelope List, got $decoded');
...@@ -460,8 +462,10 @@ class StandardMethodCodec implements MethodCodec { ...@@ -460,8 +462,10 @@ class StandardMethodCodec implements MethodCodec {
@override @override
dynamic decodeEnvelope(ByteData envelope) { dynamic decodeEnvelope(ByteData envelope) {
if (envelope == null)
throw new MissingPluginException();
// First byte is zero in success case, and non-zero otherwise. // First byte is zero in success case, and non-zero otherwise.
if (envelope == null || envelope.lengthInBytes == 0) if (envelope.lengthInBytes == 0)
throw const FormatException('Expected envelope, got nothing'); throw const FormatException('Expected envelope, got nothing');
final ReadBuffer buffer = new ReadBuffer(envelope); final ReadBuffer buffer = new ReadBuffer(envelope);
if (buffer.getUint8() == 0) if (buffer.getUint8() == 0)
......
...@@ -261,3 +261,22 @@ class PlatformMethodChannel { ...@@ -261,3 +261,22 @@ class PlatformMethodChannel {
return controller.stream; return controller.stream;
} }
} }
/// A [PlatformMethodChannel] that ignores missing platform plugins.
///
/// When [invokeMethod] fails to find the platform plugin, it returns null
/// instead of throwing an exception.
class OptionalPlatformMethodChannel extends PlatformMethodChannel {
/// Creates a [PlatformMethodChannel] that ignores missing platform plugins.
const OptionalPlatformMethodChannel(String name, [MethodCodec codec = const StandardMethodCodec()])
: super(name, codec);
@override
Future<dynamic> invokeMethod(String method, [dynamic arguments]) async {
try {
return await super.invokeMethod(method, arguments);
} on MissingPluginException {
return null;
}
}
}
...@@ -16,13 +16,17 @@ class SystemChannels { ...@@ -16,13 +16,17 @@ class SystemChannels {
); );
/// A JSON [PlatformMethodChannel] for invoking miscellaneous platform methods. /// A JSON [PlatformMethodChannel] for invoking miscellaneous platform methods.
static const PlatformMethodChannel platform = const PlatformMethodChannel( ///
/// Ignores missing plugins.
static const PlatformMethodChannel platform = const OptionalPlatformMethodChannel(
'flutter/platform', 'flutter/platform',
const JSONMethodCodec(), const JSONMethodCodec(),
); );
/// A JSON [PlatformMethodChannel] for handling text input. /// A JSON [PlatformMethodChannel] for handling text input.
static const PlatformMethodChannel textInput = const PlatformMethodChannel( ///
/// Ignores missing plugins.
static const PlatformMethodChannel textInput = const OptionalPlatformMethodChannel(
'flutter/textinput', 'flutter/textinput',
const JSONMethodCodec(), const JSONMethodCodec(),
); );
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:typed_data';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -54,6 +56,21 @@ void main() { ...@@ -54,6 +56,21 @@ void main() {
)])); )]));
}); });
test('setApplicationSwitcherDescription missing plugin', () async {
final List<ByteData> log = <ByteData>[];
PlatformMessages.setMockBinaryMessageHandler('flutter/platform', (ByteData message) {
log.add(message);
return null;
});
await SystemChrome.setApplicationSwitcherDescription(
const ApplicationSwitcherDescription(label: 'Example label', primaryColor: 0xFF00FF00)
);
expect(log, isNotEmpty);
});
test('setEnabledSystemUIOverlays control test', () async { test('setEnabledSystemUIOverlays control test', () async {
final List<MethodCall> log = <MethodCall>[]; final List<MethodCall> log = <MethodCall>[];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment