forked from flutter/flutter
-
Notifications
You must be signed in to change notification settings - Fork 2
/
plugin_registry.dart
175 lines (156 loc) · 5.59 KB
/
plugin_registry.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
typedef _MessageHandler = Future<ByteData> Function(ByteData);
/// This class registers web platform plugins.
///
/// An instance of this class is available as [webPluginRegistry].
class PluginRegistry {
/// Creates a plugin registry.
///
/// The argument selects the [BinaryMessenger] to use. An
/// appropriate value would be [pluginBinaryMessenger].
PluginRegistry(this._binaryMessenger);
final BinaryMessenger _binaryMessenger;
/// Creates a registrar for the given plugin implementation class.
Registrar registrarFor(Type key) => Registrar(_binaryMessenger);
/// Registers this plugin handler with the engine, so that unrecognized
/// platform messages are forwarded to the registry, where they can be
/// correctly dispatched to one of the registered plugins.
///
/// Code generated by the `flutter` tool automatically calls this method
/// for the global [webPluginRegistry] at startup.
///
/// Only one [PluginRegistry] can be registered at a time. Calling this
/// method a second time silently unregisters the first [PluginRegistry]
/// and replaces it with the new one.
///
/// This method uses a function called `webOnlySetPluginHandler` in
/// the [dart:ui] library. That function is only available when
/// compiling for the web.
void registerMessageHandler() {
// The function below is only defined in the Web dart:ui.
// ignore: undefined_function
ui.webOnlySetPluginHandler(_binaryMessenger.handlePlatformMessage);
}
}
/// A registrar for a particular plugin.
///
/// Gives access to a [BinaryMessenger] which has been configured to receive
/// platform messages from the framework side.
class Registrar {
/// Creates a registrar with the given [BinaryMessenger].
Registrar(this.messenger);
/// A [BinaryMessenger] configured to receive platform messages from the
/// framework side.
///
/// Use this [BinaryMessenger] when creating platform channels in order for
/// them to receive messages from the platform side. For example:
///
/// ```dart
/// class MyPlugin {
/// static void registerWith(Registrar registrar) {
/// final MethodChannel channel = MethodChannel(
/// 'com.my_plugin/my_plugin',
/// const StandardMethodCodec(),
/// registrar.messenger,
/// );
/// final MyPlugin instance = MyPlugin();
/// channel.setMethodCallHandler(instance.handleMethodCall);
/// }
/// // ...
/// }
/// ```
final BinaryMessenger messenger;
}
/// The default plugin registry for the web.
///
/// Uses [pluginBinaryMessenger] as the [BinaryMessenger].
final PluginRegistry webPluginRegistry = PluginRegistry(pluginBinaryMessenger);
/// A [BinaryMessenger] which does the inverse of the default framework
/// messenger.
///
/// Instead of sending messages from the framework to the engine, this
/// receives messages from the framework and dispatches them to registered
/// plugins.
class _PlatformBinaryMessenger extends BinaryMessenger {
final Map<String, _MessageHandler> _handlers = <String, _MessageHandler>{};
/// Receives a platform message from the framework.
@override
Future<void> handlePlatformMessage(
String channel,
ByteData data,
ui.PlatformMessageResponseCallback callback,
) async {
ByteData response;
try {
final MessageHandler handler = _handlers[channel];
if (handler != null) {
response = await handler(data);
}
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'flutter web plugins',
context: ErrorDescription('during a framework-to-plugin message'),
));
} finally {
if (callback != null) {
callback(response);
}
}
}
/// Sends a platform message from the platform side back to the framework.
@override
Future<ByteData> send(String channel, ByteData message) {
final Completer<ByteData> completer = Completer<ByteData>();
ui.window.onPlatformMessage(channel, message, (ByteData reply) {
try {
completer.complete(reply);
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'flutter web plugins',
context: ErrorDescription('during a plugin-to-framework message'),
));
}
});
return completer.future;
}
@override
void setMessageHandler(String channel, MessageHandler handler) {
if (handler == null)
_handlers.remove(channel);
else
_handlers[channel] = handler;
}
@override
bool checkMessageHandler(String channel, MessageHandler handler) => _handlers[channel] == handler;
@override
void setMockMessageHandler(
String channel,
Future<ByteData> Function(ByteData message) handler,
) {
throw FlutterError(
'Setting mock handlers is not supported on the platform side.',
);
}
@override
bool checkMockMessageHandler(String channel, MessageHandler handler) {
throw FlutterError(
'Setting mock handlers is not supported on the platform side.',
);
}
}
/// The default [BinaryMessenger] for Flutter web plugins.
///
/// This is the value used for [webPluginRegistry]'s [PluginRegistry]
/// constructor argument.
final BinaryMessenger pluginBinaryMessenger = _PlatformBinaryMessenger();