plugin_registry.dart 7.36 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6 7 8 9 10
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:ui' as ui;

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

11
/// A registrar for Flutter plugins implemented in Dart.
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
/// Plugins for the web platform are implemented in Dart and are
/// registered with this class by code generated by the `flutter` tool
/// when compiling the application.
///
/// This class implements [BinaryMessenger] to route messages from the
/// framework to registered plugins.
///
/// 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, // the registrar is used as the BinaryMessenger
///     );
///     final MyPlugin instance = MyPlugin();
///     channel.setMethodCallHandler(instance.handleMethodCall);
///   }
///   // ...
/// }
/// ```
class Registrar extends BinaryMessenger {
  /// Creates a [Registrar].
39
  ///
40 41 42 43 44 45 46 47 48 49 50 51 52 53
  /// The argument is ignored. To create a test [Registrar] with custom behavior,
  /// subclass the [Registrar] class and override methods as appropriate.
  Registrar([
    @Deprecated(
      'This argument is ignored. '
      'This feature was deprecated after v1.24.0-7.0.pre.'
    )
    BinaryMessenger? binaryMessenger,
  ]);

  /// Registers the registrar's message handler
  /// ([handlePlatformMessage]) with the engine, so that plugin
  /// messages are correctly dispatched to the relevant registered
  /// plugin.
54
  ///
55 56 57 58
  /// Only one handler can be registered at a time. Calling this
  /// method a second time silently unregisters any
  /// previously-registered handler and replaces it with the handler
  /// from this object.
59 60 61 62
  ///
  /// This method uses a function called `webOnlySetPluginHandler` in
  /// the [dart:ui] library. That function is only available when
  /// compiling for the web.
63 64 65
  void registerMessageHandler() {
    // The function below is only defined in the Web dart:ui.
    // ignore: undefined_function
66
    ui.webOnlySetPluginHandler(handleFrameworkMessage);
67 68
  }

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
  /// Receives a platform message from the framework.
  ///
  /// This method has been replaced with the more clearly-named [handleFrameworkMessage].
  @Deprecated(
    'Use handleFrameworkMessage instead. '
    'This feature was deprecated after v1.24.0-7.0.pre.'
  )
  @override
  Future<void> handlePlatformMessage(
    String channel,
    ByteData? data,
    ui.PlatformMessageResponseCallback? callback,
  ) => handleFrameworkMessage(channel, data, callback);

  /// Message handler for web plugins.
  ///
  /// This method is called when handling messages from the framework.
86
  ///
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
  /// If a handler has been registered for the given `channel`, it is
  /// invoked, and the value it returns is passed to `callback` (if that
  /// is non-null). Then, the method's future is completed.
  ///
  /// If no handler has been registered for that channel, then the
  /// callback (if any) is invoked with null, then the method's future
  /// is completed.
  ///
  /// Messages are not buffered (unlike platform messages headed to
  /// the framework, which are managed by [ChannelBuffers]).
  ///
  /// This method is registered as the message handler by code
  /// autogenerated by the `flutter` tool when the application is
  /// compiled, if any web plugins are used. The code in question is
  /// the following:
102
  ///
103
  /// ```dart
104
  /// ui.webOnlySetPluginHandler(webPluginRegistrar.handleFrameworkMessage);
105
  /// ```
106
  Future<void> handleFrameworkMessage(
107
    String channel,
108 109
    ByteData? data,
    ui.PlatformMessageResponseCallback? callback,
110
  ) async {
111
    ByteData? response;
112
    try {
113
      final MessageHandler? handler = _handlers[channel];
114 115 116 117 118 119 120
      if (handler != null) {
        response = await handler(data);
      }
    } catch (exception, stack) {
      FlutterError.reportError(FlutterErrorDetails(
        exception: exception,
        stack: stack,
121 122
        library: 'flutter web plugins',
        context: ErrorDescription('during a framework-to-plugin message'),
123 124
      ));
    } finally {
125 126 127
      if (callback != null) {
        callback(response);
      }
128 129 130
    }
  }

131 132 133 134 135 136 137 138 139
  /// Returns `this`.
  @Deprecated(
    'This property is redundant. It returns the object on which it is called. '
    'This feature was deprecated after v1.24.0-7.0.pre.'
  )
  BinaryMessenger get messenger => this;

  final Map<String, MessageHandler> _handlers = <String, MessageHandler>{};

140 141
  /// Sends a platform message from the platform side back to the framework.
  @override
142 143
  Future<ByteData?> send(String channel, ByteData? message) {
    final Completer<ByteData?> completer = Completer<ByteData?>();
144
    ui.window.onPlatformMessage!(channel, message, (ByteData? reply) {
145 146 147 148 149 150
      try {
        completer.complete(reply);
      } catch (exception, stack) {
        FlutterError.reportError(FlutterErrorDetails(
          exception: exception,
          stack: stack,
151
          library: 'flutter web plugins',
152 153 154 155 156
          context: ErrorDescription('during a plugin-to-framework message'),
        ));
      }
    });
    return completer.future;
157 158 159
  }

  @override
160
  void setMessageHandler(String channel, MessageHandler? handler) {
161 162 163 164 165 166
    if (handler == null)
      _handlers.remove(channel);
    else
      _handlers[channel] = handler;
  }

167
  @override
168
  bool checkMessageHandler(String channel, MessageHandler? handler) => _handlers[channel] == handler;
169

170 171
  @override
  void setMockMessageHandler(
172
    String channel,
173
    MessageHandler? handler,
174
  ) {
175
    throw FlutterError(
176 177
      'Setting mock handlers is not supported on the platform side.',
    );
178
  }
179 180

  @override
181
  bool checkMockMessageHandler(String channel, MessageHandler? handler) {
182
    throw FlutterError(
183 184
      'Setting mock handlers is not supported on the platform side.',
    );
185
  }
186 187
}

188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
/// This class was previously separate from [Registrar] but was merged into it
/// as part of a simplification of the web plugins API.
@Deprecated(
  'Use Registrar instead. '
  'This feature was deprecated after v1.24.0-7.0.pre.'
)
class PluginRegistry extends Registrar {
  /// Creates a [Registrar].
  ///
  /// The argument is ignored.
  PluginRegistry([
    @Deprecated(
      'This argument is ignored. '
      'This feature was deprecated after v1.24.0-7.0.pre.'
    )
    BinaryMessenger? binaryMessenger,
  ]) : super(); // ignore: avoid_unused_constructor_parameters

  /// Returns `this`. The argument is ignored.
  @Deprecated(
    'This method is redundant. It returns the object on which it is called. '
    'This feature was deprecated after v1.24.0-7.0.pre.'
  )
  Registrar registrarFor(Type key) => this;
}

/// The default plugin registrar for the web.
final Registrar webPluginRegistrar = PluginRegistry();

/// A deprecated alias for [webPluginRegistrar].
@Deprecated(
  'Use webPluginRegistrar instead. '
  'This feature was deprecated after v1.24.0-7.0.pre.'
)
PluginRegistry get webPluginRegistry => webPluginRegistrar as PluginRegistry;

/// A deprecated alias for [webPluginRegistrar].
@Deprecated(
  'Use webPluginRegistrar instead. '
  'This feature was deprecated after v1.24.0-7.0.pre.'
)
BinaryMessenger get pluginBinaryMessenger => webPluginRegistrar;