diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 217ad698cafe..3c40ce365f34 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -118,13 +118,11 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterBinary FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterCodecs.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterNavigationController.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterChannels.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCodecs.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterNavigationController.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterStandardCodec.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterStandardCodec_Internal.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUmbrellaImport.m @@ -203,7 +201,6 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/common/JSONUtil. FILE: ../../../flutter/shell/platform/darwin/ios/framework/Flutter.podspec FILE: ../../../flutter/shell/platform/darwin/ios/framework/Info.plist FILE: ../../../flutter/shell/platform/darwin/ios/framework/module.modulemap -FILE: ../../../flutter/shell/platform/darwin/ios/headless_platform_view_ios.mm FILE: ../../../flutter/shell/platform/embedder/assets/EmbedderInfo.plist FILE: ../../../flutter/shell/platform/embedder/assets/embedder.modulemap FILE: ../../../flutter/shell/platform/embedder/fixtures/simple_main.dart @@ -518,7 +515,10 @@ FILE: ../../../flutter/shell/platform/android/android_shell_holder.cc FILE: ../../../flutter/shell/platform/android/android_shell_holder.h FILE: ../../../flutter/shell/platform/android/platform_message_response_android.cc FILE: ../../../flutter/shell/platform/android/platform_message_response_android.h +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Internal.h +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -599,7 +599,6 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbac FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegate.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.mm -FILE: ../../../flutter/shell/platform/darwin/ios/headless_platform_view_ios.h ---------------------------------------------------------------------------------------------------- Copyright 2018 The Chromium Authors. All rights reserved. diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index d33519ce0b71..15a14ad82bea 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -26,9 +26,9 @@ _flutter_framework_headers = [ "framework/Headers/FlutterChannels.h", "framework/Headers/FlutterCodecs.h", "framework/Headers/FlutterDartProject.h", + "framework/Headers/FlutterEngine.h", "framework/Headers/FlutterHeadlessDartRunner.h", "framework/Headers/FlutterMacros.h", - "framework/Headers/FlutterNavigationController.h", "framework/Headers/FlutterPlatformViews.h", "framework/Headers/FlutterPlugin.h", "framework/Headers/FlutterPluginAppLifeCycleDelegate.h", @@ -52,8 +52,9 @@ shared_library("create_flutter_framework_dylib") { "framework/Source/FlutterCodecs.mm", "framework/Source/FlutterDartProject.mm", "framework/Source/FlutterDartProject_Internal.h", + "framework/Source/FlutterEngine.mm", + "framework/Source/FlutterEngine_Internal.h", "framework/Source/FlutterHeadlessDartRunner.mm", - "framework/Source/FlutterNavigationController.mm", "framework/Source/FlutterObservatoryPublisher.h", "framework/Source/FlutterObservatoryPublisher.mm", "framework/Source/FlutterPlatformPlugin.h", @@ -80,8 +81,6 @@ shared_library("create_flutter_framework_dylib") { "framework/Source/platform_message_router.mm", "framework/Source/vsync_waiter_ios.h", "framework/Source/vsync_waiter_ios.mm", - "headless_platform_view_ios.h", - "headless_platform_view_ios.mm", "ios_external_texture_gl.h", "ios_external_texture_gl.mm", "ios_gl_context.h", diff --git a/shell/platform/darwin/ios/framework/Headers/Flutter.h b/shell/platform/darwin/ios/framework/Headers/Flutter.h index 458db5ed3637..0d2f831d8a1f 100644 --- a/shell/platform/darwin/ios/framework/Headers/Flutter.h +++ b/shell/platform/darwin/ios/framework/Headers/Flutter.h @@ -8,6 +8,13 @@ /** BREAKING CHANGES: + October 5, 2018: + - Removed FlutterNavigationController.h/.mm + - Changed return signature of `FlutterDartHeadlessCodeRunner.run*` from void + to bool + - Removed HeadlessPlatformViewIOS + - Marked FlutterDartHeadlessCodeRunner deprecated + August 31, 2018: Marked -[FlutterDartProject initFromDefaultSourceForConfiguration] and FlutterStandardBigInteger as unavailable. @@ -47,9 +54,9 @@ #include "FlutterChannels.h" #include "FlutterCodecs.h" #include "FlutterDartProject.h" +#include "FlutterEngine.h" #include "FlutterHeadlessDartRunner.h" #include "FlutterMacros.h" -#include "FlutterNavigationController.h" #include "FlutterPlatformViews.h" #include "FlutterPlugin.h" #include "FlutterPluginAppLifeCycleDelegate.h" diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h b/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h index f175ea292582..05c934b072c7 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h @@ -11,11 +11,11 @@ #include "FlutterPlugin.h" /** - * UIApplicationDelegate subclass for simple apps that want default behavior. + * `UIApplicationDelegate` subclass for simple apps that want default behavior. * - * This class provides the following behaviors: + * This class implements the following behaviors: * * Status bar touches are forwarded to the key window's root view - * FlutterViewController, in order to trigger scroll to top. + * `FlutterViewController`, in order to trigger scroll to top. * * Keeps the Flutter connection open in debug mode when the phone screen * locks. * @@ -24,7 +24,8 @@ * code as necessary from FlutterAppDelegate.mm. */ FLUTTER_EXPORT -@interface FlutterAppDelegate : UIResponder +@interface FlutterAppDelegate + : UIResponder @property(strong, nonatomic) UIWindow* window; diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterBinaryMessenger.h b/shell/platform/darwin/ios/framework/Headers/FlutterBinaryMessenger.h index 606c131349cc..341aae91cdc5 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterBinaryMessenger.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterBinaryMessenger.h @@ -11,72 +11,67 @@ NS_ASSUME_NONNULL_BEGIN /** - A message reply callback. - - Used for submitting a binary reply back to a Flutter message sender. Also used - in the dual capacity for handling a binary message reply received from Flutter. - - - Parameters: - - reply: The reply. + * A message reply callback. + * + * Used for submitting a binary reply back to a Flutter message sender. Also used + * in for handling a binary message reply received from Flutter. + * + * @param reply The reply. */ typedef void (^FlutterBinaryReply)(NSData* _Nullable reply); /** - A strategy for handling incoming binary messages from Flutter and to send - asynchronous replies back to Flutter. - - - Parameters: - - message: The message. - - reply: A callback for submitting a reply to the sender. + * A strategy for handling incoming binary messages from Flutter and to send + * asynchronous replies back to Flutter. + * + * @param message The message. + * @param reply A callback for submitting an asynchronous reply to the sender. */ typedef void (^FlutterBinaryMessageHandler)(NSData* _Nullable message, FlutterBinaryReply reply); /** - A facility for communicating with the Flutter side using asynchronous message - passing with binary messages. - - - SeeAlso: - - `FlutterBasicMessageChannel`, which supports communication using structured - messages. - - `FlutterMethodChannel`, which supports communication using asynchronous - method calls. - - `FlutterEventChannel`, which supports commuication using event streams. + * A facility for communicating with the Flutter side using asynchronous message + * passing with binary messages. + * + * Implementated by: + * - `FlutterBasicMessageChannel`, which supports communication using structured + * messages. + * - `FlutterMethodChannel`, which supports communication using asynchronous + * method calls. + * - `FlutterEventChannel`, which supports commuication using event streams. */ FLUTTER_EXPORT -@protocol FlutterBinaryMessenger +@protocol FlutterBinaryMessenger /** - Sends a binary message to the Flutter side on the specified channel, expecting - no reply. - - - Parameters: - - channel: The channel name. - - message: The message. + * Sends a binary message to the Flutter side on the specified channel, expecting + * no reply. + * + * @param channel The channel name. + * @param message The message. */ - (void)sendOnChannel:(NSString*)channel message:(NSData* _Nullable)message; /** - Sends a binary message to the Flutter side on the specified channel, expecting - an asynchronous reply. - - - Parameters: - - channel: The channel name. - - message: The message. - - callback: A callback for receiving a reply. + * Sends a binary message to the Flutter side on the specified channel, expecting + * an asynchronous reply. + * + * @param channel The channel name. + * @param message The message. + * @param callback A callback for receiving a reply. */ - (void)sendOnChannel:(NSString*)channel message:(NSData* _Nullable)message binaryReply:(FlutterBinaryReply _Nullable)callback; /** - Registers a message handler for incoming binary messages from the Flutter side - on the specified channel. - - Replaces any existing handler. Use a `nil` handler for unregistering the - existing handler. - - - Parameters: - - channel: The channel name. - - handler: The message handler. + * Registers a message handler for incoming binary messages from the Flutter side + * on the specified channel. + * + * Replaces any existing handler. Use a `nil` handler for unregistering the + * existing handler. + * + * @param channel The channel name. + * @param handler The message handler. */ - (void)setMessageHandlerOnChannel:(NSString*)channel binaryMessageHandler:(FlutterBinaryMessageHandler _Nullable)handler; diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterCallbackCache.h b/shell/platform/darwin/ios/framework/Headers/FlutterCallbackCache.h index 7150838fafbb..8931d7e7b19f 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterCallbackCache.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterCallbackCache.h @@ -9,26 +9,43 @@ #include "FlutterMacros.h" +/** + * An object containing the result of `FlutterCallbackCache`'s `lookupCallbackInformation` + * method. + */ FLUTTER_EXPORT @interface FlutterCallbackInformation : NSObject +/** + * The name of the callback. + */ @property(retain) NSString* callbackName; +/** + * The class name of the callback. + */ @property(retain) NSString* callbackClassName; +/** + * The library path of the callback. + */ @property(retain) NSString* callbackLibraryPath; @end +/** + * The cache containing callback information for spawning a + * `FlutterHeadlessDartRunner`. + */ FLUTTER_EXPORT @interface FlutterCallbackCache : NSObject /** - Returns the callback information for the given callback handle. - This callback information can be used when spawning a - FlutterHeadlessDartRunner. - - - Parameter handle: The handle for a callback, provided by the - Dart method `PluginUtilities.getCallbackHandle`. - - Returns: A FlutterCallbackInformation object which contains the name of the - callback, the name of the class in which the callback is defined, and the - path of the library which contains the callback. If the provided handle is - invalid, nil is returned. + * Returns the callback information for the given callback handle. + * This callback information can be used when spawning a + * `FlutterHeadlessDartRunner`. + * + * @param handle The handle for a callback, provided by the + * Dart method `PluginUtilities.getCallbackHandle`. + * @return A `FlutterCallbackInformation` object which contains the name of the + * callback, the name of the class in which the callback is defined, and the + * path of the library which contains the callback. If the provided handle is + * invalid, nil is returned. */ + (FlutterCallbackInformation*)lookupCallbackInformation:(int64_t)handle; diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h b/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h index 2e6cf4a4fd82..373f32293d60 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h @@ -10,373 +10,359 @@ NS_ASSUME_NONNULL_BEGIN /** - A message reply callback. - - Used for submitting a reply back to a Flutter message sender. Also used in - the dual capacity for handling a message reply received from Flutter. - - - Parameter reply: The reply. + * A message reply callback. + * + * Used for submitting a reply back to a Flutter message sender. Also used in + * the dual capacity for handling a message reply received from Flutter. + * + * @param reply The reply. */ typedef void (^FlutterReply)(id _Nullable reply); /** - A strategy for handling incoming messages from Flutter and to send - asynchronous replies back to Flutter. - - - Parameters: - - message: The message. - - reply: A callback for submitting a reply to the sender. + * A strategy for handling incoming messages from Flutter and to send + * asynchronous replies back to Flutter. + * + * @param message The message. + * @param callback A callback for submitting a reply to the sender. */ typedef void (^FlutterMessageHandler)(id _Nullable message, FlutterReply callback); /** - A channel for communicating with the Flutter side using basic, asynchronous - message passing. + * A channel for communicating with the Flutter side using basic, asynchronous + * message passing. */ FLUTTER_EXPORT @interface FlutterBasicMessageChannel : NSObject /** - Creates a `FlutterBasicMessageChannel` with the specified name and binary - messenger. - - The channel name logically identifies the channel; identically named channels - interfere with each other's communication. - - The binary messenger is a facility for sending raw, binary messages to the - Flutter side. This protocol is implemented by `FlutterViewController`. - - The channel uses `FlutterStandardMessageCodec` to encode and decode messages. - - - Parameters: - - name: The channel name. - - messenger: The binary messenger. + * Creates a `FlutterBasicMessageChannel` with the specified name and binary + * messenger. + * + * The channel name logically identifies the channel; identically named channels + * interfere with each other's communication. + * + * The binary messenger is a facility for sending raw, binary messages to the + * Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`. + * + * The channel uses `FlutterStandardMessageCodec` to encode and decode messages. + * + * @param name The channel name. + * @param messenger The binary messenger. */ + (instancetype)messageChannelWithName:(NSString*)name binaryMessenger:(NSObject*)messenger; /** - Creates a `FlutterBasicMessageChannel` with the specified name, binary - messenger, - and message codec. - - The channel name logically identifies the channel; identically named channels - interfere with each other's communication. - - The binary messenger is a facility for sending raw, binary messages to the - Flutter side. This protocol is implemented by `FlutterViewController`. - - - Parameters: - - name: The channel name. - - messenger: The binary messenger. - - codec: The message codec. + * Creates a `FlutterBasicMessageChannel` with the specified name, binary + * messenger, and message codec. + * + * The channel name logically identifies the channel; identically named channels + * interfere with each other's communication. + * + * The binary messenger is a facility for sending raw, binary messages to the + * Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`. + * + * @param name The channel name. + * @param messenger The binary messenger. + * @param codec The message codec. */ + (instancetype)messageChannelWithName:(NSString*)name binaryMessenger:(NSObject*)messenger codec:(NSObject*)codec; /** - Initializes a `FlutterBasicMessageChannel` with the specified name, binary - messenger, and message codec. - - The channel name logically identifies the channel; identically named channels - interfere with each other's communication. - - The binary messenger is a facility for sending raw, binary messages to the - Flutter side. This protocol is implemented by `FlutterViewController`. - - - Parameters: - - name: The channel name. - - messenger: The binary messenger. - - codec: The message codec. + * Initializes a `FlutterBasicMessageChannel` with the specified name, binary + * messenger, and message codec. + * + * The channel name logically identifies the channel; identically named channels + * interfere with each other's communication. + * + * The binary messenger is a facility for sending raw, binary messages to the + * Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`. + * + * @param name The channel name. + * @param messenger The binary messenger. + * @param codec The message codec. */ - (instancetype)initWithName:(NSString*)name binaryMessenger:(NSObject*)messenger codec:(NSObject*)codec; /** - Sends the specified message to the Flutter side, ignoring any reply. - - - Parameter message: The message. Must be supported by the codec of this - channel. + * Sends the specified message to the Flutter side, ignoring any reply. + * + * @param message The message. Must be supported by the codec of this + * channel. */ - (void)sendMessage:(id _Nullable)message; /** - Sends the specified message to the Flutter side, expecting an asynchronous - reply. - - - Parameters: - - message: The message. Must be supported by the codec of this channel. - - callback: A callback to be invoked with the message reply from Flutter. + * Sends the specified message to the Flutter side, expecting an asynchronous + * reply. + * + * @param message The message. Must be supported by the codec of this channel. + * @param callback A callback to be invoked with the message reply from Flutter. */ - (void)sendMessage:(id _Nullable)message reply:(FlutterReply _Nullable)callback; /** - Registers a message handler with this channel. - - Replaces any existing handler. Use a `nil` handler for unregistering the - existing handler. - - - Parameter handler: The message handler. + * Registers a message handler with this channel. + * + * Replaces any existing handler. Use a `nil` handler for unregistering the + * existing handler. + * + * @param handler The message handler. */ - (void)setMessageHandler:(FlutterMessageHandler _Nullable)handler; @end /** - A method call result callback. - - Used for submitting a method call result back to a Flutter caller. Also used in - the dual capacity for handling a method call result received from Flutter. - - - Parameter result: The result. + * A method call result callback. + * + * Used for submitting a method call result back to a Flutter caller. Also used in + * the dual capacity for handling a method call result received from Flutter. + * + * @param result The result. */ typedef void (^FlutterResult)(id _Nullable result); /** - A strategy for handling method calls. - - - Parameters: - - call: The incoming method call. - - result: A callback to asynchronously submit the result of the call. - Invoke the callback with a `FlutterError` to indicate that the call failed. - Invoke the callback with `FlutterMethodNotImplemented` to indicate that the - method was unknown. Any other values, including `nil`, are interpreted as - successful results. + * A strategy for handling method calls. + * + * @param call The incoming method call. + * @param result A callback to asynchronously submit the result of the call. + * Invoke the callback with a `FlutterError` to indicate that the call failed. + * Invoke the callback with `FlutterMethodNotImplemented` to indicate that the + * method was unknown. Any other values, including `nil`, are interpreted as + * successful results. */ typedef void (^FlutterMethodCallHandler)(FlutterMethodCall* call, FlutterResult result); /** - A constant used with `FlutterMethodCallHandler` to respond to the call of an - unknown method. + * A constant used with `FlutterMethodCallHandler` to respond to the call of an + * unknown method. */ FLUTTER_EXPORT extern NSObject const* FlutterMethodNotImplemented; /** - A channel for communicating with the Flutter side using invocation of - asynchronous methods. + * A channel for communicating with the Flutter side using invocation of + * asynchronous methods. */ FLUTTER_EXPORT @interface FlutterMethodChannel : NSObject /** - Creates a `FlutterMethodChannel` with the specified name and binary messenger. - - The channel name logically identifies the channel; identically named channels - interfere with each other's communication. - - The binary messenger is a facility for sending raw, binary messages to the - Flutter side. This protocol is implemented by `FlutterViewController`. - - The channel uses `FlutterStandardMethodCodec` to encode and decode method calls - and result envelopes. - - - Parameters: - - name: The channel name. - - messenger: The binary messenger. + * Creates a `FlutterMethodChannel` with the specified name and binary messenger. + * + * The channel name logically identifies the channel; identically named channels + * interfere with each other's communication. + * + * The binary messenger is a facility for sending raw, binary messages to the + * Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`. + * + * The channel uses `FlutterStandardMethodCodec` to encode and decode method calls + * and result envelopes. + * + * @param name The channel name. + * @param messenger The binary messenger. */ + (instancetype)methodChannelWithName:(NSString*)name binaryMessenger:(NSObject*)messenger; /** - Creates a `FlutterMethodChannel` with the specified name, binary messenger, and - method codec. - - The channel name logically identifies the channel; identically named channels - interfere with each other's communication. - - The binary messenger is a facility for sending raw, binary messages to the - Flutter side. This protocol is implemented by `FlutterViewController`. - - - Parameters: - - name: The channel name. - - messenger: The binary messenger. - - codec: The method codec. + * Creates a `FlutterMethodChannel` with the specified name, binary messenger, and + * method codec. + * + * The channel name logically identifies the channel; identically named channels + * interfere with each other's communication. + * + * The binary messenger is a facility for sending raw, binary messages to the + * Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`. + * + * @param name The channel name. + * @param messenger The binary messenger. + * @param codec The method codec. */ + (instancetype)methodChannelWithName:(NSString*)name binaryMessenger:(NSObject*)messenger codec:(NSObject*)codec; /** - Initializes a `FlutterMethodChannel` with the specified name, binary messenger, - and method codec. - - The channel name logically identifies the channel; identically named channels - interfere with each other's communication. - - The binary messenger is a facility for sending raw, binary messages to the - Flutter side. This protocol is implemented by `FlutterViewController`. - - - Parameters: - - name: The channel name. - - messenger: The binary messenger. - - codec: The method codec. + * Initializes a `FlutterMethodChannel` with the specified name, binary messenger, + * and method codec. + * + * The channel name logically identifies the channel; identically named channels + * interfere with each other's communication. + * + * The binary messenger is a facility for sending raw, binary messages to the + * Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`. + * + * @param name The channel name. + * @param messenger The binary messenger. + * @param codec The method codec. */ - (instancetype)initWithName:(NSString*)name binaryMessenger:(NSObject*)messenger codec:(NSObject*)codec; +// clang-format off /** - Invokes the specified Flutter method with the specified arguments, expecting - no results. See - [MethodChannel.setMethodCallHandler](https://docs.flutter.io/flutter/services/MethodChannel/setMethodCallHandler.html). - - - Parameters: - - method: The name of the method to invoke. - - arguments: The arguments. Must be a value supported by the codec of this - channel. + * Invokes the specified Flutter method with the specified arguments, expecting + * no results. + * + * @see [MethodChannel.setMethodCallHandler](https://docs.flutter.io/flutter/services/MethodChannel/setMethodCallHandler.html) + * + * @param method The name of the method to invoke. + * @param arguments The arguments. Must be a value supported by the codec of this + * channel. */ +// clang-format on - (void)invokeMethod:(NSString*)method arguments:(id _Nullable)arguments; /** - Invokes the specified Flutter method with the specified arguments, expecting - an asynchronous result. - - - Parameters: - - method: The name of the method to invoke. - - arguments: The arguments. Must be a value supported by the codec of this - channel. - - result: A callback that will be invoked with the asynchronous result. - The result will be a `FlutterError` instance, if the method call resulted - in an error on the Flutter side. Will be `FlutterMethodNotImplemented`, if - the method called was not implemented on the Flutter side. Any other value, - including `nil`, should be interpreted as successful results. + * Invokes the specified Flutter method with the specified arguments, expecting + * an asynchronous result. + * + * @param method The name of the method to invoke. + * @param arguments The arguments. Must be a value supported by the codec of this + * channel. + * @param callback A callback that will be invoked with the asynchronous result. + * The result will be a `FlutterError` instance, if the method call resulted + * in an error on the Flutter side. Will be `FlutterMethodNotImplemented`, if + * the method called was not implemented on the Flutter side. Any other value, + * including `nil`, should be interpreted as successful results. */ - (void)invokeMethod:(NSString*)method arguments:(id _Nullable)arguments result:(FlutterResult _Nullable)callback; /** - Registers a handler for method calls from the Flutter side. - - Replaces any existing handler. Use a `nil` handler for unregistering the - existing handler. - - - Parameter handler: The method call handler. + * Registers a handler for method calls from the Flutter side. + * + * Replaces any existing handler. Use a `nil` handler for unregistering the + * existing handler. + * + * @param handler The method call handler. */ - (void)setMethodCallHandler:(FlutterMethodCallHandler _Nullable)handler; @end /** - An event sink callback. - - - Parameter event: The event. + * An event sink callback. + * + * @param event The event. */ typedef void (^FlutterEventSink)(id _Nullable event); /** - A strategy for exposing an event stream to the Flutter side. + * A strategy for exposing an event stream to the Flutter side. */ FLUTTER_EXPORT @protocol FlutterStreamHandler /** - Sets up an event stream and begin emitting events. - - Invoked when the first listener is registered with the Stream associated to - this channel on the Flutter side. - - - Parameters: - - arguments: Arguments for the stream. - - events: A callback to asynchronously emit events. Invoke the - callback with a `FlutterError` to emit an error event. Invoke the - callback with `FlutterEndOfEventStream` to indicate that no more - events will be emitted. Any other value, including `nil` are emitted as - successful events. - - Returns: A FlutterError instance, if setup fails. + * Sets up an event stream and begin emitting events. + * + * Invoked when the first listener is registered with the Stream associated to + * this channel on the Flutter side. + * + * @param arguments Arguments for the stream. + * @param events A callback to asynchronously emit events. Invoke the + * callback with a `FlutterError` to emit an error event. Invoke the + * callback with `FlutterEndOfEventStream` to indicate that no more + * events will be emitted. Any other value, including `nil` are emitted as + * successful events. + * @return A FlutterError instance, if setup fails. */ - (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(FlutterEventSink)events; /** - Tears down an event stream. - - Invoked when the last listener is deregistered from the Stream associated to - this channel on the Flutter side. - - The channel implementation may call this method with `nil` arguments - to separate a pair of two consecutive set up requests. Such request pairs - may occur during Flutter hot restart. - - - Parameter arguments: Arguments for the stream. - - Returns: A FlutterError instance, if teardown fails. + * Tears down an event stream. + * + * Invoked when the last listener is deregistered from the Stream associated to + * this channel on the Flutter side. + * + * The channel implementation may call this method with `nil` arguments + * to separate a pair of two consecutive set up requests. Such request pairs + * may occur during Flutter hot restart. + * + * @param arguments Arguments for the stream. + * @return A FlutterError instance, if teardown fails. */ - (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments; @end /** - A constant used with `FlutterEventChannel` to indicate end of stream. + * A constant used with `FlutterEventChannel` to indicate end of stream. */ FLUTTER_EXPORT extern NSObject const* FlutterEndOfEventStream; /** - A channel for communicating with the Flutter side using event streams. + * A channel for communicating with the Flutter side using event streams. */ FLUTTER_EXPORT @interface FlutterEventChannel : NSObject /** - Creates a `FlutterEventChannel` with the specified name and binary messenger. - - The channel name logically identifies the channel; identically named channels - interfere with each other's communication. - - The binary messenger is a facility for sending raw, binary messages to the - Flutter side. This protocol is implemented by `FlutterViewController`. - - The channel uses `FlutterStandardMethodCodec` to decode stream setup and - teardown requests, and to encode event envelopes. - - - Parameters: - - name: The channel name. - - messenger: The binary messenger. - - codec: The method codec. + * Creates a `FlutterEventChannel` with the specified name and binary messenger. + * + * The channel name logically identifies the channel; identically named channels + * interfere with each other's communication. + * + * The binary messenger is a facility for sending raw, binary messages to the + * Flutter side. This protocol is implemented by `FlutterViewController`. + * + * The channel uses `FlutterStandardMethodCodec` to decode stream setup and + * teardown requests, and to encode event envelopes. + * + * @param name The channel name. + * @param messenger The binary messenger. */ + (instancetype)eventChannelWithName:(NSString*)name binaryMessenger:(NSObject*)messenger; /** - Creates a `FlutterEventChannel` with the specified name, binary messenger, - and method codec. - - The channel name logically identifies the channel; identically named channels - interfere with each other's communication. - - The binary messenger is a facility for sending raw, binary messages to the - Flutter side. This protocol is implemented by `FlutterViewController`. - - - Parameters: - - name: The channel name. - - messenger: The binary messenger. - - codec: The method codec. + * Creates a `FlutterEventChannel` with the specified name, binary messenger, + * and method codec. + * + * The channel name logically identifies the channel; identically named channels + * interfere with each other's communication. + * + * The binary messenger is a facility for sending raw, binary messages to the + * Flutter side. This protocol is implemented by `FlutterViewController`. + * + * @param name The channel name. + * @param messenger The binary messenger. + * @param codec The method codec. */ + (instancetype)eventChannelWithName:(NSString*)name binaryMessenger:(NSObject*)messenger codec:(NSObject*)codec; /** - Initializes a `FlutterEventChannel` with the specified name, binary messenger, - and method codec. - - The channel name logically identifies the channel; identically named channels - interfere with each other's communication. - - The binary messenger is a facility for sending raw, binary messages to the - Flutter side. This protocol is implemented by `FlutterViewController`. - - - Parameters: - - name: The channel name. - - messenger: The binary messenger. - - codec: The method codec. + * Initializes a `FlutterEventChannel` with the specified name, binary messenger, + * and method codec. + * + * The channel name logically identifies the channel; identically named channels + * interfere with each other's communication. + * + * The binary messenger is a facility for sending raw, binary messages to the + * Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`. + * + * @param name The channel name. + * @param messenger The binary messenger. + * @param codec The method codec. */ - (instancetype)initWithName:(NSString*)name binaryMessenger:(NSObject*)messenger codec:(NSObject*)codec; /** - Registers a handler for stream setup requests from the Flutter side. - - Replaces any existing handler. Use a `nil` handler for unregistering the - existing handler. - - - Parameter handler: The stream handler. + * Registers a handler for stream setup requests from the Flutter side. + * + * Replaces any existing handler. Use a `nil` handler for unregistering the + * existing handler. + * + * @param handler The stream handler. */ - (void)setStreamHandler:(NSObject* _Nullable)handler; @end diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterCodecs.h b/shell/platform/darwin/ios/framework/Headers/FlutterCodecs.h index 54d7eeca54fd..4a8e0775ac0a 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterCodecs.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterCodecs.h @@ -16,76 +16,76 @@ NS_ASSUME_NONNULL_BEGIN FLUTTER_EXPORT @protocol FlutterMessageCodec /** - Returns a shared instance of this `FlutterMessageCodec`. + * Returns a shared instance of this `FlutterMessageCodec`. */ + (instancetype)sharedInstance; /** - Encodes the specified message into binary. - - - Parameter message: The message. - - Returns: The binary encoding, or `nil`, if `message` was `nil`. + * Encodes the specified message into binary. + * + * @param message The message. + * @return The binary encoding, or `nil`, if `message` was `nil`. */ - (NSData* _Nullable)encode:(id _Nullable)message; /** - Decodes the specified message from binary. - - - Parameter message: The message. - - Returns: The decoded message, or `nil`, if `message` was `nil`. + * Decodes the specified message from binary. + * + * @param message The message. + * @return The decoded message, or `nil`, if `message` was `nil`. */ - (id _Nullable)decode:(NSData* _Nullable)message; @end /** - A `FlutterMessageCodec` using unencoded binary messages, represented as - `NSData` instances. - - This codec is guaranteed to be compatible with the corresponding - [BinaryCodec](https://docs.flutter.io/flutter/services/BinaryCodec-class.html) - on the Dart side. These parts of the Flutter SDK are evolved synchronously. - - On the Dart side, messages are represented using `ByteData`. + * A `FlutterMessageCodec` using unencoded binary messages, represented as + * `NSData` instances. + * + * This codec is guaranteed to be compatible with the corresponding + * [BinaryCodec](https://docs.flutter.io/flutter/services/BinaryCodec-class.html) + * on the Dart side. These parts of the Flutter SDK are evolved synchronously. + * + * On the Dart side, messages are represented using `ByteData`. */ FLUTTER_EXPORT @interface FlutterBinaryCodec : NSObject @end /** - A `FlutterMessageCodec` using UTF-8 encoded `NSString` messages. - - This codec is guaranteed to be compatible with the corresponding - [StringCodec](https://docs.flutter.io/flutter/services/StringCodec-class.html) - on the Dart side. These parts of the Flutter SDK are evolved synchronously. + * A `FlutterMessageCodec` using UTF-8 encoded `NSString` messages. + * + * This codec is guaranteed to be compatible with the corresponding + * [StringCodec](https://docs.flutter.io/flutter/services/StringCodec-class.html) + * on the Dart side. These parts of the Flutter SDK are evolved synchronously. */ FLUTTER_EXPORT @interface FlutterStringCodec : NSObject @end /** - A `FlutterMessageCodec` using UTF-8 encoded JSON messages. - - This codec is guaranteed to be compatible with the corresponding - [JSONMessageCodec](https://docs.flutter.io/flutter/services/JSONMessageCodec-class.html) - on the Dart side. These parts of the Flutter SDK are evolved synchronously. - - Supports values accepted by `NSJSONSerialization` plus top-level - `nil`, `NSNumber`, and `NSString`. - - On the Dart side, JSON messages are handled by the JSON facilities of the - [`dart:convert`](https://api.dartlang.org/stable/dart-convert/JSON-constant.html) - package. + * A `FlutterMessageCodec` using UTF-8 encoded JSON messages. + * + * This codec is guaranteed to be compatible with the corresponding + * [JSONMessageCodec](https://docs.flutter.io/flutter/services/JSONMessageCodec-class.html) + * on the Dart side. These parts of the Flutter SDK are evolved synchronously. + * + * Supports values accepted by `NSJSONSerialization` plus top-level + * `nil`, `NSNumber`, and `NSString`. + * + * On the Dart side, JSON messages are handled by the JSON facilities of the + * [`dart:convert`](https://api.dartlang.org/stable/dart-convert/JSON-constant.html) + * package. */ FLUTTER_EXPORT @interface FlutterJSONMessageCodec : NSObject @end /** - A writer of the Flutter standard binary encoding. - - See `FlutterStandardMessageCodec` for details on the encoding. - - The encoding is extensible via subclasses overriding `writeValue`. + * A writer of the Flutter standard binary encoding. + * + * See `FlutterStandardMessageCodec` for details on the encoding. + * + * The encoding is extensible via subclasses overriding `writeValue`. */ FLUTTER_EXPORT @interface FlutterStandardWriter : NSObject @@ -100,11 +100,11 @@ FLUTTER_EXPORT @end /** - A reader of the Flutter standard binary encoding. - - See `FlutterStandardMessageCodec` for details on the encoding. - - The encoding is extensible via subclasses overriding `readValueOfType`. + * A reader of the Flutter standard binary encoding. + * + * See `FlutterStandardMessageCodec` for details on the encoding. + * + * The encoding is extensible via subclasses overriding `readValueOfType`. */ FLUTTER_EXPORT @interface FlutterStandardReader : NSObject @@ -121,8 +121,8 @@ FLUTTER_EXPORT @end /** - A factory of compatible reader/writer instances using the Flutter standard - binary encoding or extensions thereof. + * A factory of compatible reader/writer instances using the Flutter standard + * binary encoding or extensions thereof. */ FLUTTER_EXPORT @interface FlutterStandardReaderWriter : NSObject @@ -131,29 +131,29 @@ FLUTTER_EXPORT @end /** - A `FlutterMessageCodec` using the Flutter standard binary encoding. - - This codec is guaranteed to be compatible with the corresponding - [StandardMessageCodec](https://docs.flutter.io/flutter/services/StandardMessageCodec-class.html) - on the Dart side. These parts of the Flutter SDK are evolved synchronously. - - Supported messages are acyclic values of these forms: - - - `nil` or `NSNull` - - `NSNumber` (including their representation of Boolean values) - - `NSString` - - `FlutterStandardTypedData` - - `NSArray` of supported values - - `NSDictionary` with supported keys and values - - On the Dart side, these values are represented as follows: - - - `nil` or `NSNull`: null - - `NSNumber`: `bool`, `int`, or `double`, depending on the contained value. - - `NSString`: `String` - - `FlutterStandardTypedData`: `Uint8List`, `Int32List`, `Int64List`, or `Float64List` - - `NSArray`: `List` - - `NSDictionary`: `Map` + * A `FlutterMessageCodec` using the Flutter standard binary encoding. + * + * This codec is guaranteed to be compatible with the corresponding + * [StandardMessageCodec](https://docs.flutter.io/flutter/services/StandardMessageCodec-class.html) + * on the Dart side. These parts of the Flutter SDK are evolved synchronously. + * + * Supported messages are acyclic values of these forms: + * + * - `nil` or `NSNull` + * - `NSNumber` (including their representation of Boolean values) + * - `NSString` + * - `FlutterStandardTypedData` + * - `NSArray` of supported values + * - `NSDictionary` with supported keys and values + * + * On the Dart side, these values are represented as follows: + * + * - `nil` or `NSNull`: null + * - `NSNumber`: `bool`, `int`, or `double`, depending on the contained value. + * - `NSString`: `String` + * - `FlutterStandardTypedData`: `Uint8List`, `Int32List`, `Int64List`, or `Float64List` + * - `NSArray`: `List` + * - `NSDictionary`: `Map` */ FLUTTER_EXPORT @interface FlutterStandardMessageCodec : NSObject @@ -166,39 +166,37 @@ FLUTTER_EXPORT FLUTTER_EXPORT @interface FlutterMethodCall : NSObject /** - Creates a method call for invoking the specified named method with the - specified arguments. - - - Parameters: - - method: the name of the method to call. - - arguments: the arguments value. + * Creates a method call for invoking the specified named method with the + * specified arguments. + * + * @param method the name of the method to call. + * @param arguments the arguments value. */ + (instancetype)methodCallWithMethodName:(NSString*)method arguments:(id _Nullable)arguments; /** - The method name. + * The method name. */ @property(readonly, nonatomic) NSString* method; /** - The arguments. + * The arguments. */ @property(readonly, nonatomic, nullable) id arguments; @end /** - Error object representing an unsuccessful outcome of invoking a method - on a `FlutterMethodChannel`, or an error event on a `FlutterEventChannel`. + * Error object representing an unsuccessful outcome of invoking a method + * on a `FlutterMethodChannel`, or an error event on a `FlutterEventChannel`. */ FLUTTER_EXPORT @interface FlutterError : NSObject /** - Creates a `FlutterError` with the specified error code, message, and details. - - - Parameters: - - code: An error code string for programmatic use. - - message: A human-readable error message. - - details: Custom error details. + * Creates a `FlutterError` with the specified error code, message, and details. + * + * @param code An error code string for programmatic use. + * @param message A human-readable error message. + * @param details Custom error details. */ + (instancetype)errorWithCode:(NSString*)code message:(NSString* _Nullable)message @@ -220,12 +218,12 @@ FLUTTER_EXPORT @end /** - Type of numeric data items encoded in a `FlutterStandardDataType`. - - - FlutterStandardDataTypeUInt8: plain bytes - - FlutterStandardDataTypeInt32: 32-bit signed integers - - FlutterStandardDataTypeInt64: 64-bit signed integers - - FlutterStandardDataTypeFloat64: 64-bit floats + * Type of numeric data items encoded in a `FlutterStandardDataType`. + * + * - FlutterStandardDataTypeUInt8: plain bytes + * - FlutterStandardDataTypeInt32: 32-bit signed integers + * - FlutterStandardDataTypeInt64: 64-bit signed integers + * - FlutterStandardDataTypeFloat64: 64-bit floats */ typedef NS_ENUM(NSInteger, FlutterStandardDataType) { FlutterStandardDataTypeUInt8, @@ -235,174 +233,173 @@ typedef NS_ENUM(NSInteger, FlutterStandardDataType) { }; /** - A byte buffer holding `UInt8`, `SInt32`, `SInt64`, or `Float64` values, used - with `FlutterStandardMessageCodec` and `FlutterStandardMethodCodec`. - - Two's complement encoding is used for signed integers. IEEE754 - double-precision representation is used for floats. The platform's native - endianness is assumed. + * A byte buffer holding `UInt8`, `SInt32`, `SInt64`, or `Float64` values, used + * with `FlutterStandardMessageCodec` and `FlutterStandardMethodCodec`. + * + * Two's complement encoding is used for signed integers. IEEE754 + * double-precision representation is used for floats. The platform's native + * endianness is assumed. */ FLUTTER_EXPORT @interface FlutterStandardTypedData : NSObject /** - Creates a `FlutterStandardTypedData` which interprets the specified data - as plain bytes. - - - Parameter data: the byte data. + * Creates a `FlutterStandardTypedData` which interprets the specified data + * as plain bytes. + * + * @param data the byte data. */ + (instancetype)typedDataWithBytes:(NSData*)data; /** - Creates a `FlutterStandardTypedData` which interprets the specified data - as 32-bit signed integers. - - - Parameter data: the byte data. The length must be divisible by 4. + * Creates a `FlutterStandardTypedData` which interprets the specified data + * as 32-bit signed integers. + * + * @param data the byte data. The length must be divisible by 4. */ + (instancetype)typedDataWithInt32:(NSData*)data; /** - Creates a `FlutterStandardTypedData` which interprets the specified data - as 64-bit signed integers. - - - Parameter data: the byte data. The length must be divisible by 8. + * Creates a `FlutterStandardTypedData` which interprets the specified data + * as 64-bit signed integers. + * + * @param data the byte data. The length must be divisible by 8. */ + (instancetype)typedDataWithInt64:(NSData*)data; /** - Creates a `FlutterStandardTypedData` which interprets the specified data - as 64-bit floats. - - - Parameter data: the byte data. The length must be divisible by 8. + * Creates a `FlutterStandardTypedData` which interprets the specified data + * as 64-bit floats. + * + * @param data the byte data. The length must be divisible by 8. */ + (instancetype)typedDataWithFloat64:(NSData*)data; /** - The raw underlying data buffer. + * The raw underlying data buffer. */ @property(readonly, nonatomic) NSData* data; /** - The type of the encoded values. + * The type of the encoded values. */ @property(readonly, nonatomic) FlutterStandardDataType type; /** - The number of value items encoded. + * The number of value items encoded. */ @property(readonly, nonatomic) UInt32 elementCount; /** - The number of bytes used by the encoding of a single value item. + * The number of bytes used by the encoding of a single value item. */ @property(readonly, nonatomic) UInt8 elementSize; @end /** - An arbitrarily large integer value, used with `FlutterStandardMessageCodec` - and `FlutterStandardMethodCodec`. + * An arbitrarily large integer value, used with `FlutterStandardMessageCodec` + * and `FlutterStandardMethodCodec`. */ FLUTTER_EXPORT -FLUTTER_UNAVAILABLE( - "Unavailable on 2018-08-31. Deprecated on 2018-01-09. " - "FlutterStandardBigInteger was needed because the Dart 1.0 int type had no " - "size limit. With Dart 2.0, the int type is a fixed-size, 64-bit signed " - "integer. If you need to communicate larger integers, use NSString encoding " - "instead.") +FLUTTER_UNAVAILABLE("Unavailable on 2018-08-31. Deprecated on 2018-01-09. " + "FlutterStandardBigInteger was needed because the Dart 1.0 int type had no " + "size limit. With Dart 2.0, the int type is a fixed-size, 64-bit signed " + "integer. If you need to communicate larger integers, use NSString encoding " + "instead.") @interface FlutterStandardBigInteger : NSObject @end /** - A codec for method calls and enveloped results. - - Method calls are encoded as binary messages with enough structure that the - codec can extract a method name `NSString` and an arguments `NSObject`, - possibly `nil`. These data items are used to populate a `FlutterMethodCall`. - - Result envelopes are encoded as binary messages with enough structure that - the codec can determine whether the result was successful or an error. In - the former case, the codec can extract the result `NSObject`, possibly `nil`. - In the latter case, the codec can extract an error code `NSString`, a - human-readable `NSString` error message (possibly `nil`), and a custom - error details `NSObject`, possibly `nil`. These data items are used to - populate a `FlutterError`. + * A codec for method calls and enveloped results. + * + * Method calls are encoded as binary messages with enough structure that the + * codec can extract a method name `NSString` and an arguments `NSObject`, + * possibly `nil`. These data items are used to populate a `FlutterMethodCall`. + * + * Result envelopes are encoded as binary messages with enough structure that + * the codec can determine whether the result was successful or an error. In + * the former case, the codec can extract the result `NSObject`, possibly `nil`. + * In the latter case, the codec can extract an error code `NSString`, a + * human-readable `NSString` error message (possibly `nil`), and a custom + * error details `NSObject`, possibly `nil`. These data items are used to + * populate a `FlutterError`. */ FLUTTER_EXPORT @protocol FlutterMethodCodec /** - Provides access to a shared instance this codec. - - - Returns: The shared instance. + * Provides access to a shared instance this codec. + * + * @return The shared instance. */ + (instancetype)sharedInstance; /** - Encodes the specified method call into binary. - - - Parameter methodCall: The method call. The arguments value - must be supported by this codec. - - Returns: The binary encoding. + * Encodes the specified method call into binary. + * + * @param methodCall The method call. The arguments value + * must be supported by this codec. + * @return The binary encoding. */ - (NSData*)encodeMethodCall:(FlutterMethodCall*)methodCall; /** - Decodes the specified method call from binary. - - - Parameter methodCall: The method call to decode. - - Returns: The decoded method call. + * Decodes the specified method call from binary. + * + * @param methodCall The method call to decode. + * @return The decoded method call. */ - (FlutterMethodCall*)decodeMethodCall:(NSData*)methodCall; /** - Encodes the specified successful result into binary. - - - Parameter result: The result. Must be a value supported by this codec. - - Returns: The binary encoding. + * Encodes the specified successful result into binary. + * + * @param result The result. Must be a value supported by this codec. + * @return The binary encoding. */ - (NSData*)encodeSuccessEnvelope:(id _Nullable)result; /** - Encodes the specified error result into binary. - - - Parameter error: The error object. The error details value must be supported - by this codec. - - Returns: The binary encoding. + * Encodes the specified error result into binary. + * + * @param error The error object. The error details value must be supported + * by this codec. + * @return The binary encoding. */ - (NSData*)encodeErrorEnvelope:(FlutterError*)error; /** - Deccodes the specified result envelope from binary. - - - Parameter error: The error object. - - Returns: The result value, if the envelope represented a successful result, - or a `FlutterError` instance, if not. + * Deccodes the specified result envelope from binary. + * + * @param envelope The error object. + * @return The result value, if the envelope represented a successful result, + * or a `FlutterError` instance, if not. */ - (id _Nullable)decodeEnvelope:(NSData*)envelope; @end /** - A `FlutterMethodCodec` using UTF-8 encoded JSON method calls and result - envelopes. - - This codec is guaranteed to be compatible with the corresponding - [JSONMethodCodec](https://docs.flutter.io/flutter/services/JSONMethodCodec-class.html) - on the Dart side. These parts of the Flutter SDK are evolved synchronously. - - Values supported as methods arguments and result payloads are - those supported as top-level or leaf values by `FlutterJSONMessageCodec`. + * A `FlutterMethodCodec` using UTF-8 encoded JSON method calls and result + * envelopes. + * + * This codec is guaranteed to be compatible with the corresponding + * [JSONMethodCodec](https://docs.flutter.io/flutter/services/JSONMethodCodec-class.html) + * on the Dart side. These parts of the Flutter SDK are evolved synchronously. + * + * Values supported as methods arguments and result payloads are + * those supported as top-level or leaf values by `FlutterJSONMessageCodec`. */ FLUTTER_EXPORT @interface FlutterJSONMethodCodec : NSObject @end /** - A `FlutterMethodCodec` using the Flutter standard binary encoding. - - This codec is guaranteed to be compatible with the corresponding - [StandardMethodCodec](https://docs.flutter.io/flutter/services/StandardMethodCodec-class.html) - on the Dart side. These parts of the Flutter SDK are evolved synchronously. - - Values supported as method arguments and result payloads are those supported by - `FlutterStandardMessageCodec`. + * A `FlutterMethodCodec` using the Flutter standard binary encoding. + * + * This codec is guaranteed to be compatible with the corresponding + * [StandardMethodCodec](https://docs.flutter.io/flutter/services/StandardMethodCodec-class.html) + * on the Dart side. These parts of the Flutter SDK are evolved synchronously. + * + * Values supported as method arguments and result payloads are those supported by + * `FlutterStandardMessageCodec`. */ FLUTTER_EXPORT @interface FlutterStandardMethodCodec : NSObject diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h b/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h index bef67aa04a93..de491405fe60 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h @@ -9,43 +9,58 @@ #include "FlutterMacros.h" +/** + * A set of Flutter and Dart assets used by a `FlutterEngine` to initialize execution. + */ FLUTTER_EXPORT @interface FlutterDartProject : NSObject +/** + * Initializes with a specific + */ - (instancetype)initWithPrecompiledDartBundle:(NSBundle*)bundle NS_DESIGNATED_INITIALIZER; +/** + * Initializes with a specific set of Flutter Assets, with a specified location of + * main() and Dart packages. + */ - (instancetype)initWithFlutterAssets:(NSURL*)flutterAssetsURL dartMain:(NSURL*)dartMainURL packages:(NSURL*)dartPackages NS_DESIGNATED_INITIALIZER; +/** + * Initializes from a specific set of Flutter Assets. + */ - (instancetype)initWithFlutterAssetsWithScriptSnapshot:(NSURL*)flutterAssetsURL NS_DESIGNATED_INITIALIZER; +/** + * Unavailable - use `init` instead. + */ - (instancetype)initFromDefaultSourceForConfiguration FLUTTER_UNAVAILABLE("Use -init instead."); /** - Returns the file name for the given asset. - The returned file name can be used to access the asset in the application's main bundle. - - - Parameter asset: The name of the asset. The name can be hierarchical. - - Returns: the file name to be used for lookup in the main bundle. + * Returns the file name for the given asset. + * The returned file name can be used to access the asset in the application's main bundle. + * + * @param asset The name of the asset. The name can be hierarchical. + * @return the file name to be used for lookup in the main bundle. */ + (NSString*)lookupKeyForAsset:(NSString*)asset; /** - Returns the file name for the given asset which originates from the specified package. - The returned file name can be used to access the asset in the application's main bundle. - - - Parameters: - - asset: The name of the asset. The name can be hierarchical. - - package: The name of the package from which the asset originates. - - Returns: the file name to be used for lookup in the main bundle. + * Returns the file name for the given asset which originates from the specified package. + * The returned file name can be used to access the asset in the application's main bundle. + * + * @param asset The name of the asset. The name can be hierarchical. + * @param package The name of the package from which the asset originates. + * @return the file name to be used for lookup in the main bundle. */ + (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package; /** - Returns the default identifier for the bundle where we expect to find the Flutter Dart - application. + * Returns the default identifier for the bundle where we expect to find the Flutter Dart + * application. */ + (NSString*)defaultBundleIdentifier; diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h b/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h new file mode 100644 index 000000000000..52e8017a299a --- /dev/null +++ b/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h @@ -0,0 +1,171 @@ +// Copyright 2018 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. + +#ifndef FLUTTER_FLUTTERENGINE_H_ +#define FLUTTER_FLUTTERENGINE_H_ + +#import +#import + +#include "FlutterBinaryMessenger.h" +#include "FlutterDartProject.h" +#include "FlutterMacros.h" +#include "FlutterPlugin.h" +#include "FlutterTexture.h" + +@class FlutterViewController; + +/** + * The FlutterEngine class coordinates a single instance of execution for a + * `FlutterDartProject`. It may have zero or one `FlutterViewController` at a + * time, which can be specified via `-setViewController:`. + * `FlutterViewController`'s `initWithEngine` initializer will automatically call + * `-setViewController:` for itself. + * + * A FlutterEngine can be created independently of a `FlutterViewController` for + * headless execution. It can also persist across the lifespan of multiple + * `FlutterViewController` instances to maintain state and/or asynchronous tasks + * (such as downloading a large file). + * + * Alternatively, you can simply create a new `FlutterViewController` with only a + * `FlutterDartProject`. That `FlutterViewController` will internally manage its + * own instance of a FlutterEngine, but will not guarantee survival of the engine + * beyond the life of the ViewController. + * + * A newly initialized FlutterEngine will not actually run a Dart Isolate until + * either `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI` is invoked. + * One of these methods must be invoked before calling `-setViewController:`. + */ +FLUTTER_EXPORT +@interface FlutterEngine + : NSObject +/** + * Initialize this FlutterEngine with a `FlutterDartProject`. + * + * If the FlutterDartProject is not specified, the FlutterEngine will attempt to locate + * the project in a default location (the flutter_assets folder in the iOS application + * bundle). + * + * A newly initialized engine will not run the `FlutterDartProject` until either + * `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI:` is called. + * + * @param labelPrefix The label prefix used to identify threads for this instance. Should + * be unique across FlutterEngine instances, and is used in instrumentation to label + * the threads used by this FlutterEngine. + * @param projectOrNil The `FlutterDartProject` to run. + */ +- (instancetype)initWithName:(NSString*)labelPrefix + project:(FlutterDartProject*)projectOrNil NS_DESIGNATED_INITIALIZER; + +/** + * The default initializer is not available for this object. + * Callers must use `-[FlutterEngine initWithName:project:]`. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** + * Runs a Dart program on an Isolate from the main Dart library (i.e. the library that + * contains `main()`). + * + * The first call to this method will create a new Isolate. Subsequent calls will return + * immediately. + * + * @param entrypoint The name of a top-level function from the same Dart + * library that contains the app's main() function. If this is nil, it will + * default to `main()`. If it is not the app's main() function, that function + * must be decorated with `@pragma(vm:entry-point)` to ensure the method is not + * tree-shaken by the Dart compiler. + * @return YES if the call succeeds in creating and running a Flutter Engine instance; NO otherwise. + */ +- (bool)runWithEntrypoint:(NSString*)entrypoint; + +/** + * Runs a Dart program on an Isolate using the specified entrypoint and Dart library, + * which may not be the same as the library containing the Dart program's `main()` function. + * + * The first call to this method will create a new Isolate. Subsequent calls will return + * immediately. + * + * @param entrypoint The name of a top-level function from a Dart library. If nil, this will + * default to `main()`. If it is not the app's main() function, that function + * must be decorated with `@pragma(vm:entry-point)` to ensure the method is not + * tree-shaken by the Dart compiler. + * @param uri The URI of the Dart library which contains the entrypoint method. IF nil, + * this will default to the same library as the `main()` function in the Dart program. + * @return YES if the call succeeds in creating and running a Flutter Engine instance; NO otherwise. + */ +- (bool)runWithEntrypoint:(NSString*)entrypoint libraryURI:(NSString*)uri; + +/** + * Sets the `FlutterViewController` for this instance. The FlutterEngine must be + * running (e.g. a successful call to `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI`) + * before calling this method. Callers may pass nil to remove the viewController + * and have the engine run headless in the current process. + * + * A FlutterEngine can only have one `FlutterViewController` at a time. If there is + * already a `FlutterViewController` associated with this instance, this method will replace + * the engine's current viewController with the newly specified one. + * + * Setting the viewController will signal the engine to start animations and drawing, and unsetting + * it will signal the engine to stop animations and drawing. However, neither will impact the state + * of the Dart program's execution. + */ +@property(nonatomic, weak) FlutterViewController* viewController; + +/** + * The `FlutterMethodChannel` used for localization related platform messages, such as + * setting the locale. + */ +@property(nonatomic, readonly) FlutterMethodChannel* localizationChannel; +/** + * The `FlutterMethodChannel` used for navigation related platform messages. + * + * @see [Navigation + * Channel](https://docs.flutter.io/flutter/services/SystemChannels/navigation-constant.html) + * @see [Navigator Widget](https://docs.flutter.io/flutter/widgets/Navigator-class.html) + */ +@property(nonatomic, readonly) FlutterMethodChannel* navigationChannel; + +/** + * The `FlutterMethodChannel` used for core platform messages, such as + * information about the screen orientation. + */ +@property(nonatomic, readonly) FlutterMethodChannel* platformChannel; + +/** + * The `FlutterMethodChannel` used to communicate text input events to the + * Dart Isolate. + * + * @see [Text Input + * Channel](https://docs.flutter.io/flutter/services/SystemChannels/textInput-constant.html) + */ +@property(nonatomic, readonly) FlutterMethodChannel* textInputChannel; + +/** + * The `FlutterBasicMessageChannel` used to communicate app lifecycle events + * to the Dart Isolate. + * + * @see [Lifecycle + * Channel](https://docs.flutter.io/flutter/services/SystemChannels/lifecycle-constant.html) + */ +@property(nonatomic, readonly) FlutterBasicMessageChannel* lifecycleChannel; + +/** + * The `FlutterBasicMessageChannel` used for communicating system events, such as + * memory pressure events. + * + * @see [System + * Channel](https://docs.flutter.io/flutter/services/SystemChannels/system-constant.html) + */ +@property(nonatomic, readonly) FlutterBasicMessageChannel* systemChannel; + +/** + * The `FlutterBasicMessageChannel` used for communicating user settings such as + * clock format and text scale. + */ +@property(nonatomic, readonly) FlutterBasicMessageChannel* settingsChannel; + +@end + +#endif // FLUTTER_FLUTTERENGINE_H_ diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h b/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h index f6f37248364e..eed2219fd821 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h @@ -9,44 +9,51 @@ #include "FlutterBinaryMessenger.h" #include "FlutterDartProject.h" +#include "FlutterEngine.h" #include "FlutterMacros.h" /** -A callback for when FlutterHeadlessDartRunner has attempted to start a Dart -Isolate in the background. - -- Parameter success: YES if the Isolate was started and run successfully, NO - otherwise. -*/ + * A callback for when FlutterHeadlessDartRunner has attempted to start a Dart + * Isolate in the background. + * + * @param success YES if the Isolate was started and run successfully, NO + * otherwise. + */ typedef void (^FlutterHeadlessDartRunnerCallback)(BOOL success); /** - The FlutterHeadlessDartRunner runs Flutter Dart code with a null rasterizer, - and no native drawing surface. It is appropriate for use in running Dart - code e.g. in the background from a plugin. -*/ + * The FlutterHeadlessDartRunner runs Flutter Dart code with a null rasterizer, + * and no native drawing surface. It is appropriate for use in running Dart + * code e.g. in the background from a plugin. + * + * Most callers should prefer using `FlutterEngine` directly; this interface exists + * for legacy support. + */ FLUTTER_EXPORT -@interface FlutterHeadlessDartRunner : NSObject +FLUTTER_DEPRECATED("FlutterEngine should be used rather than FlutterHeadlessDartRunner") +@interface FlutterHeadlessDartRunner : FlutterEngine /** - Runs a Dart function on an Isolate that is not the main application's Isolate. - The first call will create a new Isolate. Subsequent calls will return - immediately. - - - Parameter entrypoint: The name of a top-level function from the same Dart - library that contains the app's main() function. -*/ -- (void)runWithEntrypoint:(NSString*)entrypoint; + * Iniitalize this FlutterHeadlessDartRunner with a `FlutterDartProject`. + * + * If the FlutterDartProject is not specified, the FlutterHeadlessDartRunner will attempt to locate + * the project in a default location. + * + * A newly initialized engine will not run the `FlutterDartProject` until either + * `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI` is called. + * + * @param labelPrefix The label prefix used to identify threads for this instance. Should + * be unique across FlutterEngine instances + * @param projectOrNil The `FlutterDartProject` to run. + */ +- (instancetype)initWithName:(NSString*)labelPrefix + project:(FlutterDartProject*)projectOrNil NS_DESIGNATED_INITIALIZER; /** - Runs a Dart function on an Isolate that is not the main application's Isolate. - The first call will create a new Isolate. Subsequent calls will return - immediately. - - - Parameter entrypoint: The name of a top-level function from a Dart library. - - Parameter uri: The URI of the Dart library which contains entrypoint. -*/ -- (void)runWithEntrypointAndLibraryUri:(NSString*)entrypoint libraryUri:(NSString*)uri; + * Not recommended for use - will initialize with a default label ("io.flutter.headless") + * and the default FlutterDartProject. + */ +- (instancetype)init; @end diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterMacros.h b/shell/platform/darwin/ios/framework/Headers/FlutterMacros.h index e3050963192e..d950856c73c5 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterMacros.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterMacros.h @@ -21,19 +21,19 @@ #endif // defined(NS_ASSUME_NONNULL_BEGIN) /** - Indicates that the API has been deprecated for the specified reason. Code that - uses the deprecated API will continue to work as before. However, the API will - soon become unavailable and users are encouraged to immediately take the - appropriate action mentioned in the deprecation message and the BREAKING - CHANGES section present in the Flutter.h umbrella header. + * Indicates that the API has been deprecated for the specified reason. Code + * that uses the deprecated API will continue to work as before. However, the + * API will soon become unavailable and users are encouraged to immediately take + * the appropriate action mentioned in the deprecation message and the BREAKING + * CHANGES section present in the Flutter.h umbrella header. */ #define FLUTTER_DEPRECATED(msg) __attribute__((__deprecated__(msg))) /** - Indicates that the previously deprecated API is now unavailable. Code that - uses the API will not work and the declaration of the API is only a stub meant - to display the given message detailing the actions for the user to take - immediately. + * Indicates that the previously deprecated API is now unavailable. Code that + * uses the API will not work and the declaration of the API is only a stub + * meant to display the given message detailing the actions for the user to take + * immediately. */ #define FLUTTER_UNAVAILABLE(msg) __attribute__((__unavailable__(msg))) diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterNavigationController.h b/shell/platform/darwin/ios/framework/Headers/FlutterNavigationController.h deleted file mode 100644 index 1ff0911bd685..000000000000 --- a/shell/platform/darwin/ios/framework/Headers/FlutterNavigationController.h +++ /dev/null @@ -1,9 +0,0 @@ -// 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 - -@interface FlutterNavigationController : UINavigationController - -@end diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h b/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h index c077d52cd2a0..2e3f85c6054e 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h @@ -22,8 +22,8 @@ FLUTTER_EXPORT * The implementation of this method should create a new `UIView` and return it. * * @param frame The rectangle for the newly created `UIView` measued in points. - * @param viewIdentifier A unique identifier for this `UIView`. - * @param arguments Parameters for creating the `UIView` sent from the Dart side of the Flutter app. + * @param viewId A unique identifier for this `UIView`. + * @param args Parameters for creating the `UIView` sent from the Dart side of the Flutter app. * If `createArgsCodec` is not implemented, or if no creation arguments were sent from the Dart * code, this will be null. Otherwise this will be the value sent from the Dart code as decoded by * `createArgsCodec`. diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h b/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h index 4f6497712b61..a116a95efda5 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h @@ -210,7 +210,7 @@ NS_ASSUME_NONNULL_BEGIN * Plugins expose `UIView` for embedding in Flutter apps by registering a view factory. * * @param factory The view factory that will be registered. - * @param factoryId:: A unique identifier for the factory, the Dart code of the Flutter app can use + * @param factoryId A unique identifier for the factory, the Dart code of the Flutter app can use * this identifier to request creation of a `UIView` by the registered factory. */ - (void)registerViewFactory:(NSObject*)factory diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterPluginAppLifeCycleDelegate.h b/shell/platform/darwin/ios/framework/Headers/FlutterPluginAppLifeCycleDelegate.h index 8c9c0358669e..aa93e905cb2b 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterPluginAppLifeCycleDelegate.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterPluginAppLifeCycleDelegate.h @@ -10,139 +10,140 @@ NS_ASSUME_NONNULL_BEGIN /** - Propagates `UIAppDelegate` callbacks to registered plugins. -*/ + * Propagates `UIAppDelegate` callbacks to registered plugins. + */ FLUTTER_EXPORT @interface FlutterPluginAppLifeCycleDelegate : NSObject /** - Registers `delegate` to receive life cycle callbacks via this FlutterPluginAppLifecycleDelegate as - long as it is alive. - - `delegate` will only referenced weakly. -*/ + * Registers `delegate` to receive life cycle callbacks via this FlutterPluginAppLifecycleDelegate + * as long as it is alive. + * + * `delegate` will only referenced weakly. + */ - (void)addDelegate:(NSObject*)delegate; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks. - - - Returns: `NO` if any plugin vetoes application launch. + * Calls all plugins registered for `UIApplicationDelegate` callbacks. + * + * @return `NO` if any plugin vetoes application launch. */ - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks. - - - Returns: `NO` if any plugin vetoes application launch. + * Calls all plugins registered for `UIApplicationDelegate` callbacks. + * + * @return `NO` if any plugin vetoes application launch. */ - (BOOL)application:(UIApplication*)application willFinishLaunchingWithOptions:(NSDictionary*)launchOptions; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks. + * Calls all plugins registered for `UIApplicationDelegate` callbacks. */ - (void)applicationDidBecomeActive:(UIApplication*)application; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks. + * Calls all plugins registered for `UIApplicationDelegate` callbacks. */ - (void)applicationWillResignActive:(UIApplication*)application; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks. + * Calls all plugins registered for `UIApplicationDelegate` callbacks. */ - (void)applicationDidEnterBackground:(UIApplication*)application; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks. + * Calls all plugins registered for `UIApplicationDelegate` callbacks. */ - (void)applicationWillEnterForeground:(UIApplication*)application; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks. + * Calls all plugins registered for `UIApplicationDelegate` callbacks. */ - (void)applicationWillTerminate:(UIApplication*)application; /** - Called if this plugin has been registered for `UIApplicationDelegate` callbacks. + * Called if this plugin has been registered for `UIApplicationDelegate` callbacks. */ - (void)application:(UIApplication*)application didRegisterUserNotificationSettings:(UIUserNotificationSettings*)notificationSettings; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks. + * Calls all plugins registered for `UIApplicationDelegate` callbacks. */ - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks. + * Calls all plugins registered for `UIApplicationDelegate` callbacks. */ - (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until - some plugin handles the request. - - - Returns: `YES` if any plugin handles the request. -*/ + * Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until + * some plugin handles the request. + * + * @return `YES` if any plugin handles the request. + */ - (BOOL)application:(UIApplication*)application openURL:(NSURL*)url options:(NSDictionary*)options; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until - some plugin handles the request. - - - Returns: `YES` if any plugin handles the request. + * Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until + * some plugin handles the request. + * + * @return `YES` if any plugin handles the request. */ - (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until - some plugin handles the request. - - - Returns: `YES` if any plugin handles the request. -*/ + * Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until + * some plugin handles the request. + * + * @return `YES` if any plugin handles the request. + */ - (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks. -*/ + * Calls all plugins registered for `UIApplicationDelegate` callbacks. + */ - (void)application:(UIApplication*)application performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem completionHandler:(void (^)(BOOL succeeded))completionHandler API_AVAILABLE(ios(9.0)); /** - Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until - some plugin handles the request. - - - Returns: `YES` if any plugin handles the request. -*/ + * Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until + * some plugin handles the request. + * + * @return `YES` if any plugin handles the request. + */ - (BOOL)application:(UIApplication*)application handleEventsForBackgroundURLSession:(nonnull NSString*)identifier completionHandler:(nonnull void (^)(void))completionHandler; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until - some plugin handles the request. - - - Returns: `YES` if any plugin handles the request. -*/ + * Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until + * some plugin handles the request. + * + * @returns `YES` if any plugin handles the request. + */ - (BOOL)application:(UIApplication*)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler; /** - Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until - some plugin handles the request. - - Returns: `YES` if any plugin handles the request. -*/ + * Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until + * some plugin handles the request. + * + * @return `YES` if any plugin handles the request. + */ - (BOOL)application:(UIApplication*)application continueUserActivity:(NSUserActivity*)userActivity restorationHandler:(void (^)(NSArray*))restorationHandler; diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h b/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h index f2b8670a8a9e..9fe5887593b7 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h @@ -13,12 +13,12 @@ NS_ASSUME_NONNULL_BEGIN FLUTTER_EXPORT -@protocol FlutterTexture +@protocol FlutterTexture - (CVPixelBufferRef _Nullable)copyPixelBuffer; @end FLUTTER_EXPORT -@protocol FlutterTextureRegistry +@protocol FlutterTextureRegistry - (int64_t)registerTexture:(NSObject*)texture; - (void)textureFrameAvailable:(int64_t)textureId; - (void)unregisterTexture:(int64_t)textureId; diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h b/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h index 27b7330ba345..a53f14244cea 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h @@ -10,14 +10,52 @@ #include "FlutterBinaryMessenger.h" #include "FlutterDartProject.h" +#include "FlutterEngine.h" #include "FlutterMacros.h" #include "FlutterPlugin.h" #include "FlutterTexture.h" +@class FlutterEngine; + +/** + * A `UIViewController` implementation for Flutter views. + * + * Dart execution, channel communication, texture registration, and plugin registration + * are all handled by `FlutterEngine`. Calls on this class to those members all proxy + * through to the `FlutterEngine` attached FlutterViewController. + * + * A FlutterViewController can be initialized either with an already-running `FlutterEngine`, + * or it can be initialized with a `FlutterDartProject` that will be used to spin up + * a new `FlutterEngine`. Developers looking to present and hide FlutterViewControllers + * in native iOS applications will usually want to maintain the `FlutterEngine` instance + * so as not to lose Dart-related state and asynchronous tasks when navigating back and + * forth between a FlutterViewController and other `UIViewController`s. + */ FLUTTER_EXPORT @interface FlutterViewController : UIViewController +/** + * Initializes this FlutterViewController with the specified `FlutterEngine`. + * + * The initialized viewcontroller will attach itself to the engine as part of this process. + * + * @param engine The `FlutterEngine` instance to attach to. + * @param nibNameOrNil The NIB name to initialize this UIViewController with. + * @param nibBundleOrNil The NIB bundle. + */ +- (instancetype)initWithEngine:(FlutterEngine*)engine + nibName:(NSString*)nibNameOrNil + bundle:(NSBundle*)nibBundleOrNil NS_DESIGNATED_INITIALIZER; + +/** + * Initializes a new FlutterViewController and `FlutterEngine` with the specified + * `FlutterDartProject`. + * + * @param projectOrNil The `FlutterDartProject` to initialize the `FlutterEngine` with. + * @param nibNameOrNil The NIB name to initialize this UIViewController with. + * @param nibBundleOrNil The NIB bundle. + */ - (instancetype)initWithProject:(FlutterDartProject*)projectOrNil nibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil NS_DESIGNATED_INITIALIZER; @@ -25,71 +63,78 @@ FLUTTER_EXPORT - (void)handleStatusBarTouches:(UIEvent*)event; /** - Registers a callback that will be invoked when the Flutter view has been rendered. - The callback will be fired only once. - - Replaces an existing callback. Use a `nil` callback to unregister the existing one. + * Registers a callback that will be invoked when the Flutter view has been rendered. + * The callback will be fired only once. + * + * Replaces an existing callback. Use a `nil` callback to unregister the existing one. */ - (void)setFlutterViewDidRenderCallback:(void (^)(void))callback; /** - Returns the file name for the given asset. - The returned file name can be used to access the asset in the application's main bundle. - - - Parameter asset: The name of the asset. The name can be hierarchical. - - Returns: the file name to be used for lookup in the main bundle. + * Returns the file name for the given asset. + * The returned file name can be used to access the asset in the application's + * main bundle. + * + * @param asset The name of the asset. The name can be hierarchical. + * @return The file name to be used for lookup in the main bundle. */ - (NSString*)lookupKeyForAsset:(NSString*)asset; /** - Returns the file name for the given asset which originates from the specified package. - The returned file name can be used to access the asset in the application's main bundle. - - - Parameters: - - asset: The name of the asset. The name can be hierarchical. - - package: The name of the package from which the asset originates. - - Returns: the file name to be used for lookup in the main bundle. + * Returns the file name for the given asset which originates from the specified + * package. + * The returned file name can be used to access the asset in the application's + * main bundle. + * + * @param asset The name of the asset. The name can be hierarchical. + * @param package The name of the package from which the asset originates. + * @returns: The file name to be used for lookup in the main bundle. */ - (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package; /** - Sets the first route that the Flutter app shows. The default is "/". - This method will guarnatee that the initial route is delivered, even if the - Flutter window hasn't been created yet when called. It cannot be used to update - the current route being shown in a visible FlutterViewController (see pushRoute - and popRoute). - - - Parameter route: The name of the first route to show. + * Sets the first route that the Flutter app shows. The default is "/". + * This method will guarnatee that the initial route is delivered, even if the + * Flutter window hasn't been created yet when called. It cannot be used to update + * the current route being shown in a visible FlutterViewController (see pushRoute + * and popRoute). + * + * @param route The name of the first route to show. */ - (void)setInitialRoute:(NSString*)route; /** - Instructs the Flutter Navigator (if any) to go back. + * Instructs the Flutter Navigator (if any) to go back. */ - (void)popRoute; /** - Instructs the Flutter Navigator (if any) to push a route on to the navigation - stack. The setInitialRoute method should be prefered if this is called before the - FlutterViewController has come into view. - - - Parameter route: The name of the route to push to the navigation stack. + * Instructs the Flutter Navigator (if any) to push a route on to the navigation + * stack. The setInitialRoute method should be prefered if this is called before the + * FlutterViewController has come into view. + * + * @param route The name of the route to push to the navigation stack. */ - (void)pushRoute:(NSString*)route; +/** + * The `FlutterPluginRegistry` used by this FlutterViewController. + */ - (id)pluginRegistry; /** - Specifies the view to use as a splash screen. Flutter's rendering is asynchronous, so the first - frame rendered by the Flutter application might not immediately appear when the Flutter view is - initially placed in the view hierarchy. The splash screen view will be used as a replacement - until the first frame is rendered. - - The view used should be appropriate for multiple sizes; an autoresizing mask to have a flexible - width and height will be applied automatically. - - If not specified, uses a view generated from `UILaunchStoryboardName` from the main bundle's - `Info.plist` file. + * Specifies the view to use as a splash screen. Flutter's rendering is asynchronous, so the first + * frame rendered by the Flutter application might not immediately appear when theFlutter view is + * initially placed in the view hierarchy. The splash screen view will be used as + * a replacement until the first frame is rendered. + * + * The view used should be appropriate for multiple sizes; an autoresizing mask to + * have a flexible + * width and height will be applied automatically. + * + * If not specified, uses a view generated from `UILaunchStoryboardName` from the + * main bundle's + * `Info.plist` file. */ @property(strong, nonatomic) UIView* splashScreenView; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index 22d39950d93f..24ad9d97ff7a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -193,7 +193,24 @@ - (instancetype)initWithFlutterAssetsWithScriptSnapshot:(NSURL*)flutterAssetsURL } - (shell::RunConfiguration)runConfiguration { - return shell::RunConfiguration::InferFromSettings(_settings); + return [self runConfigurationForEntrypoint:nil]; +} + +- (shell::RunConfiguration)runConfigurationForEntrypoint:(NSString*)entrypointOrNil { + return [self runConfigurationForEntrypoint:entrypointOrNil libraryOrNil:nil]; +} + +- (shell::RunConfiguration)runConfigurationForEntrypoint:(NSString*)entrypointOrNil + libraryOrNil:(NSString*)dartLibraryOrNil { + shell::RunConfiguration config = shell::RunConfiguration::InferFromSettings(_settings); + if (dartLibraryOrNil && entrypointOrNil) { + config.SetEntrypointAndLibrary(std::string([entrypointOrNil UTF8String]), + std::string([dartLibraryOrNil UTF8String])); + + } else if (entrypointOrNil) { + config.SetEntrypoint(std::string([entrypointOrNil UTF8String])); + } + return config; } #pragma mark - Assets-related utilities diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h index 155f3c8ef453..32a2c50c1d80 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h @@ -14,6 +14,9 @@ - (const blink::Settings&)settings; - (shell::RunConfiguration)runConfiguration; +- (shell::RunConfiguration)runConfigurationForEntrypoint:(NSString*)entrypointOrNil; +- (shell::RunConfiguration)runConfigurationForEntrypoint:(NSString*)entrypointOrNil + libraryOrNil:(NSString*)dartLibraryOrNil; + (NSString*)flutterAssetsName:(NSBundle*)bundle; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm new file mode 100644 index 000000000000..ef82e14e5f81 --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -0,0 +1,531 @@ +// Copyright 2018 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. + +#define FML_USED_ON_EMBEDDER + +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h" + +#include + +#include "flutter/fml/message_loop.h" +#include "flutter/fml/platform/darwin/platform_version.h" +#include "flutter/shell/common/engine.h" +#include "flutter/shell/common/platform_view.h" +#include "flutter/shell/common/shell.h" +#include "flutter/shell/common/switches.h" +#include "flutter/shell/common/thread_host.h" +#include "flutter/shell/platform/darwin/common/command_line.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h" +#include "flutter/shell/platform/darwin/ios/platform_view_ios.h" + +@interface FlutterEngine () +// Maintains a dictionary of plugin names that have registered with the engine. Used by +// FlutterEngineRegistrar to implement a FlutterPluginRegistrar. +@property(nonatomic, readonly) NSMutableDictionary* pluginPublications; +@end + +@interface FlutterEngineRegistrar : NSObject +- (instancetype)initWithPlugin:(NSString*)pluginKey flutterEngine:(FlutterEngine*)flutterEngine; +@end + +@implementation FlutterEngine { + fml::scoped_nsobject _dartProject; + shell::ThreadHost _threadHost; + std::unique_ptr _shell; + NSString* _labelPrefix; + std::unique_ptr> _weakFactory; + + fml::WeakPtr _viewController; + fml::scoped_nsobject _publisher; + + // Channels + fml::scoped_nsobject _platformPlugin; + fml::scoped_nsobject _textInputPlugin; + fml::scoped_nsobject _localizationChannel; + fml::scoped_nsobject _navigationChannel; + fml::scoped_nsobject _platformChannel; + fml::scoped_nsobject _textInputChannel; + fml::scoped_nsobject _lifecycleChannel; + fml::scoped_nsobject _systemChannel; + fml::scoped_nsobject _settingsChannel; + + int64_t _nextTextureId; +} + +- (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil { + self = [super init]; + NSAssert(self, @"Super init cannot be nil"); + NSAssert(labelPrefix, @"labelPrefix is required"); + _labelPrefix = [labelPrefix copy]; + + _weakFactory = std::make_unique>(self); + + if (projectOrNil == nil) + _dartProject.reset([[FlutterDartProject alloc] init]); + else + _dartProject.reset([projectOrNil retain]); + + _pluginPublications = [NSMutableDictionary new]; + _publisher.reset([[FlutterObservatoryPublisher alloc] init]); + + [self setupChannels]; + + return self; +} + +- (void)dealloc { + [_pluginPublications release]; + [super dealloc]; +} + +- (shell::Shell&)shell { + FML_DCHECK(_shell); + return *_shell; +} + +- (fml::WeakPtr)getWeakPtr { + return _weakFactory->GetWeakPtr(); +} + +- (void)updateViewportMetrics:(blink::ViewportMetrics)viewportMetrics { + self.shell.GetTaskRunners().GetUITaskRunner()->PostTask( + [engine = self.shell.GetEngine(), metrics = viewportMetrics]() { + if (engine) { + engine->SetViewportMetrics(std::move(metrics)); + } + }); +} + +- (void)dispatchPointerDataPacket:(std::unique_ptr)packet { + self.shell.GetTaskRunners().GetUITaskRunner()->PostTask( + fml::MakeCopyable([engine = self.shell.GetEngine(), packet = std::move(packet)] { + if (engine) { + engine->DispatchPointerDataPacket(*packet); + } + })); +} + +- (fml::WeakPtr)platformView { + FML_DCHECK(_shell); + return _shell->GetPlatformView(); +} + +- (shell::PlatformViewIOS*)iosPlatformView { + FML_DCHECK(_shell); + return static_cast(_shell->GetPlatformView().get()); +} + +- (fml::RefPtr)platformTaskRunner { + FML_DCHECK(_shell); + return _shell->GetTaskRunners().GetPlatformTaskRunner(); +} + +- (void)setViewController:(FlutterViewController*)viewController { + FML_DCHECK(self.iosPlatformView); + _viewController = [viewController getWeakPtr]; + self.iosPlatformView->SetOwnerViewController(_viewController); + [self maybeSetupPlatformViewChannels]; +} + +- (FlutterViewController*)viewController { + if (!_viewController) { + return nil; + } + return _viewController.get(); +} + +- (FlutterPlatformPlugin*)platformPlugin { + return _platformPlugin.get(); +} +- (FlutterTextInputPlugin*)textInputPlugin { + return _textInputPlugin.get(); +} +- (FlutterMethodChannel*)localizationChannel { + return _localizationChannel.get(); +} +- (FlutterMethodChannel*)navigationChannel { + return _navigationChannel.get(); +} +- (FlutterMethodChannel*)platformChannel { + return _platformChannel.get(); +} +- (FlutterMethodChannel*)textInputChannel { + return _textInputChannel.get(); +} +- (FlutterBasicMessageChannel*)lifecycleChannel { + return _lifecycleChannel.get(); +} +- (FlutterBasicMessageChannel*)systemChannel { + return _systemChannel.get(); +} +- (FlutterBasicMessageChannel*)settingsChannel { + return _settingsChannel.get(); +} + +- (void)setupChannels { + _localizationChannel.reset([[FlutterMethodChannel alloc] + initWithName:@"flutter/localization" + binaryMessenger:self + codec:[FlutterJSONMethodCodec sharedInstance]]); + + _navigationChannel.reset([[FlutterMethodChannel alloc] + initWithName:@"flutter/navigation" + binaryMessenger:self + codec:[FlutterJSONMethodCodec sharedInstance]]); + + _platformChannel.reset([[FlutterMethodChannel alloc] + initWithName:@"flutter/platform" + binaryMessenger:self + codec:[FlutterJSONMethodCodec sharedInstance]]); + + _textInputChannel.reset([[FlutterMethodChannel alloc] + initWithName:@"flutter/textinput" + binaryMessenger:self + codec:[FlutterJSONMethodCodec sharedInstance]]); + + _lifecycleChannel.reset([[FlutterBasicMessageChannel alloc] + initWithName:@"flutter/lifecycle" + binaryMessenger:self + codec:[FlutterStringCodec sharedInstance]]); + + _systemChannel.reset([[FlutterBasicMessageChannel alloc] + initWithName:@"flutter/system" + binaryMessenger:self + codec:[FlutterJSONMessageCodec sharedInstance]]); + + _settingsChannel.reset([[FlutterBasicMessageChannel alloc] + initWithName:@"flutter/settings" + binaryMessenger:self + codec:[FlutterJSONMessageCodec sharedInstance]]); + + _textInputPlugin.reset([[FlutterTextInputPlugin alloc] init]); + _textInputPlugin.get().textInputDelegate = self; + + _platformPlugin.reset([[FlutterPlatformPlugin alloc] initWithEngine:[self getWeakPtr]]); + + [self maybeSetupPlatformViewChannels]; +} + +- (void)maybeSetupPlatformViewChannels { + if (_shell && self.shell.IsSetup()) { + [_platformChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { + [_platformPlugin.get() handleMethodCall:call result:result]; + }]; + + [_textInputChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { + [_textInputPlugin.get() handleMethodCall:call result:result]; + }]; + self.iosPlatformView->SetTextInputPlugin(_textInputPlugin); + } +} + +- (shell::Rasterizer::Screenshot)screenshot:(shell::Rasterizer::ScreenshotType)type + base64Encode:(bool)base64Encode { + return self.shell.Screenshot(type, base64Encode); +} + +- (void)launchEngine:(NSString*)entrypoint libraryURI:(NSString*)libraryOrNil { + // Launch the Dart application with the inferred run configuration. + self.shell.GetTaskRunners().GetUITaskRunner()->PostTask(fml::MakeCopyable( + [engine = _shell->GetEngine(), + config = [_dartProject.get() runConfigurationForEntrypoint:entrypoint + libraryOrNil:libraryOrNil] // + ]() mutable { + if (engine) { + auto result = engine->Run(std::move(config)); + if (result == shell::Engine::RunStatus::Failure) { + FML_LOG(ERROR) << "Could not launch engine with configuration."; + } + } + })); +} + +- (bool)runWithEntrypoint:(NSString*)entrypoint libraryURI:(NSString*)libraryURI { + if (_shell != nullptr) { + FML_LOG(WARNING) << "This FlutterEngine was already invoked."; + return false; + } + + static size_t shellCount = 1; + + auto settings = [_dartProject.get() settings]; + + if (libraryURI) { + FML_DCHECK(entrypoint) << "Must specify entrypoint if specifying library"; + settings.advisory_script_entrypoint = entrypoint.UTF8String; + settings.advisory_script_uri = libraryURI.UTF8String; + } else if (entrypoint) { + settings.advisory_script_entrypoint = entrypoint.UTF8String; + settings.advisory_script_entrypoint = std::string("main.dart"); + } else { + settings.advisory_script_entrypoint = std::string("main"); + settings.advisory_script_entrypoint = std::string("main.dart"); + } + + const auto threadLabel = [NSString stringWithFormat:@"%@.%zu", _labelPrefix, shellCount++]; + FML_DLOG(INFO) << "Creating threadHost for " << threadLabel.UTF8String; + // The current thread will be used as the platform thread. Ensure that the message loop is + // initialized. + fml::MessageLoop::EnsureInitializedForCurrentThread(); + + _threadHost = { + threadLabel.UTF8String, // label + shell::ThreadHost::Type::UI | shell::ThreadHost::Type::GPU | shell::ThreadHost::Type::IO}; + + blink::TaskRunners task_runners(threadLabel.UTF8String, // label + fml::MessageLoop::GetCurrent().GetTaskRunner(), // platform + _threadHost.gpu_thread->GetTaskRunner(), // gpu + _threadHost.ui_thread->GetTaskRunner(), // ui + _threadHost.io_thread->GetTaskRunner() // io + ); + + // Lambda captures by pointers to ObjC objects are fine here because the + // create call is + // synchronous. + shell::Shell::CreateCallback on_create_platform_view = + [](shell::Shell& shell) { + return std::make_unique(shell, shell.GetTaskRunners()); + }; + + shell::Shell::CreateCallback on_create_rasterizer = [](shell::Shell& shell) { + return std::make_unique(shell.GetTaskRunners()); + }; + + // Create the shell. This is a blocking operation. + _shell = shell::Shell::Create(std::move(task_runners), // task runners + std::move(settings), // settings + on_create_platform_view, // platform view creation + on_create_rasterizer // rasterzier creation + ); + + if (_shell == nullptr) { + FML_LOG(ERROR) << "Could not start a shell FlutterEngine with entrypoint: " + << entrypoint.UTF8String; + } else { + [self maybeSetupPlatformViewChannels]; + [self launchEngine:entrypoint libraryURI:libraryURI]; + } + + return _shell != nullptr; +} + +- (bool)runWithEntrypoint:(NSString*)entrypoint { + return [self runWithEntrypoint:entrypoint libraryURI:nil]; +} + +#pragma mark - Text input delegate + +- (void)updateEditingClient:(int)client withState:(NSDictionary*)state { + [_textInputChannel.get() invokeMethod:@"TextInputClient.updateEditingState" + arguments:@[ @(client), state ]]; +} + +- (void)performAction:(FlutterTextInputAction)action withClient:(int)client { + NSString* actionString; + switch (action) { + case FlutterTextInputActionUnspecified: + // Where did the term "unspecified" come from? iOS has a "default" and Android + // has "unspecified." These 2 terms seem to mean the same thing but we need + // to pick just one. "unspecified" was chosen because "default" is often a + // reserved word in languages with switch statements (dart, java, etc). + actionString = @"TextInputAction.unspecified"; + break; + case FlutterTextInputActionDone: + actionString = @"TextInputAction.done"; + break; + case FlutterTextInputActionGo: + actionString = @"TextInputAction.go"; + break; + case FlutterTextInputActionSend: + actionString = @"TextInputAction.send"; + break; + case FlutterTextInputActionSearch: + actionString = @"TextInputAction.search"; + break; + case FlutterTextInputActionNext: + actionString = @"TextInputAction.next"; + break; + case FlutterTextInputActionContinue: + actionString = @"TextInputAction.continue"; + break; + case FlutterTextInputActionJoin: + actionString = @"TextInputAction.join"; + break; + case FlutterTextInputActionRoute: + actionString = @"TextInputAction.route"; + break; + case FlutterTextInputActionEmergencyCall: + actionString = @"TextInputAction.emergencyCall"; + break; + case FlutterTextInputActionNewline: + actionString = @"TextInputAction.newline"; + break; + } + [_textInputChannel.get() invokeMethod:@"TextInputClient.performAction" + arguments:@[ @(client), actionString ]]; +} + +#pragma mark - Screenshot Delegate + +- (shell::Rasterizer::Screenshot)takeScreenshot:(shell::Rasterizer::ScreenshotType)type + asBase64Encoded:(BOOL)base64Encode { + FML_DCHECK(_shell) << "Cannot takeScreenshot without a shell"; + return _shell->Screenshot(type, base64Encode); +} + +#pragma mark - FlutterBinaryMessenger + +- (void)sendOnChannel:(NSString*)channel message:(NSData*)message { + [self sendOnChannel:channel message:message binaryReply:nil]; +} + +- (void)sendOnChannel:(NSString*)channel + message:(NSData*)message + binaryReply:(FlutterBinaryReply)callback { + NSAssert(channel, @"The channel must not be null"); + fml::RefPtr response = + (callback == nil) ? nullptr + : fml::MakeRefCounted( + ^(NSData* reply) { + callback(reply); + }, + _shell->GetTaskRunners().GetPlatformTaskRunner()); + fml::RefPtr platformMessage = + (message == nil) ? fml::MakeRefCounted(channel.UTF8String, response) + : fml::MakeRefCounted( + channel.UTF8String, shell::GetVectorFromNSData(message), response); + + _shell->GetPlatformView()->DispatchPlatformMessage(platformMessage); +} + +- (void)setMessageHandlerOnChannel:(NSString*)channel + binaryMessageHandler:(FlutterBinaryMessageHandler)handler { + NSAssert(channel, @"The channel must not be null"); + FML_DCHECK(_shell && _shell->IsSetup()); + self.iosPlatformView->GetPlatformMessageRouter().SetMessageHandler(channel.UTF8String, handler); +} + +#pragma mark - FlutterTextureRegistry + +- (int64_t)registerTexture:(NSObject*)texture { + int64_t textureId = _nextTextureId++; + self.iosPlatformView->RegisterExternalTexture(textureId, texture); + return textureId; +} + +- (void)unregisterTexture:(int64_t)textureId { + _shell->GetPlatformView()->UnregisterTexture(textureId); +} + +- (void)textureFrameAvailable:(int64_t)textureId { + _shell->GetPlatformView()->MarkTextureFrameAvailable(textureId); +} + +- (NSString*)lookupKeyForAsset:(NSString*)asset { + return [FlutterDartProject lookupKeyForAsset:asset]; +} + +- (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package { + return [FlutterDartProject lookupKeyForAsset:asset fromPackage:package]; +} + +- (id)pluginRegistry { + return self; +} + +#pragma mark - FlutterPluginRegistry + +- (NSObject*)registrarForPlugin:(NSString*)pluginKey { + NSAssert(self.pluginPublications[pluginKey] == nil, @"Duplicate plugin key: %@", pluginKey); + self.pluginPublications[pluginKey] = [NSNull null]; + return [[FlutterEngineRegistrar alloc] initWithPlugin:pluginKey flutterEngine:self]; +} + +- (BOOL)hasPlugin:(NSString*)pluginKey { + return _pluginPublications[pluginKey] != nil; +} + +- (NSObject*)valuePublishedByPlugin:(NSString*)pluginKey { + return _pluginPublications[pluginKey]; +} + +@end + +@implementation FlutterEngineRegistrar { + NSString* _pluginKey; + FlutterEngine* _flutterEngine; +} + +- (instancetype)initWithPlugin:(NSString*)pluginKey flutterEngine:(FlutterEngine*)flutterEngine { + self = [super init]; + NSAssert(self, @"Super init cannot be nil"); + _pluginKey = [pluginKey retain]; + _flutterEngine = [flutterEngine retain]; + return self; +} + +- (void)dealloc { + [_pluginKey release]; + [_flutterEngine release]; + [super dealloc]; +} + +- (NSObject*)messenger { + return _flutterEngine; +} + +- (NSObject*)textures { + return _flutterEngine; +} + +- (void)publish:(NSObject*)value { + _flutterEngine.pluginPublications[_pluginKey] = value; +} + +- (void)addMethodCallDelegate:(NSObject*)delegate + channel:(FlutterMethodChannel*)channel { + [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { + [delegate handleMethodCall:call result:result]; + }]; +} + +- (void)addApplicationDelegate:(NSObject*)delegate { + id appDelegate = [[UIApplication sharedApplication] delegate]; + if ([appDelegate conformsToProtocol:@protocol(FlutterAppLifeCycleProvider)]) { + id lifeCycleProvider = + (id)appDelegate; + [lifeCycleProvider addApplicationLifeCycleDelegate:delegate]; + } +} + +- (NSString*)lookupKeyForAsset:(NSString*)asset { + return [_flutterEngine lookupKeyForAsset:asset]; +} + +- (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package { + return [_flutterEngine lookupKeyForAsset:asset fromPackage:package]; +} + +- (void)registerViewFactory:(NSObject*)factory + withId:(NSString*)factoryId { + // TODO(amirh/dnfield): this shouldn't need to fail - PlatformViewsController should be + // independent. Dev builds of engine should just fail here. We don't want to fail in release mode + // because this shouldn't ordinarily happen. + FML_DCHECK([_flutterEngine viewController]) + << "Cannot register a view factory on a headless engine."; + if ([_flutterEngine viewController]) { + [[_flutterEngine viewController] platformViewsController]->RegisterViewFactory(factory, + factoryId); + } else { + // Shouldn't ordinarily happen, but at least give warning if it does. + FML_LOG(ERROR) << "Cannot register a view factory on a headless engine."; + } +} + +@end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h new file mode 100644 index 000000000000..5162f9c3ce07 --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h @@ -0,0 +1,45 @@ +// Copyright 2018 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. + +#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERENGINE_INTERNAL_H_ +#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERENGINE_INTERNAL_H_ + +#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h" + +#include "flutter/fml/memory/weak_ptr.h" +#include "flutter/fml/task_runner.h" +#include "flutter/lib/ui/window/pointer_data_packet.h" +#include "flutter/lib/ui/window/viewport_metrics.h" +#include "flutter/shell/common/platform_view.h" +#include "flutter/shell/common/rasterizer.h" +#include "flutter/shell/common/shell.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h" +#include "flutter/shell/platform/darwin/ios/platform_view_ios.h" + +#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h" + +@interface FlutterEngine () + +- (shell::Shell&)shell; + +- (void)updateViewportMetrics:(blink::ViewportMetrics)viewportMetrics; +- (void)dispatchPointerDataPacket:(std::unique_ptr)packet; + +- (fml::RefPtr)platformTaskRunner; + +- (fml::WeakPtr)platformView; + +- (shell::Rasterizer::Screenshot)screenshot:(shell::Rasterizer::ScreenshotType)type + base64Encode:(bool)base64Encode; + +- (FlutterPlatformPlugin*)platformPlugin; +- (FlutterTextInputPlugin*)textInputPlugin; +- (void)launchEngine:(NSString*)entrypoint libraryURI:(NSString*)libraryOrNil; + +@end + +#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERENGINE_INTERNAL_H_ diff --git a/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm b/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm index 5d0f42af6c1e..34c854ada588 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm @@ -4,11 +4,11 @@ #define FML_USED_ON_EMBEDDER +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h" + #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h" -#include #include -#include #include "flutter/fml/make_copyable.h" #include "flutter/fml/message_loop.h" @@ -22,128 +22,15 @@ #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h" #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h" #include "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h" -#include "flutter/shell/platform/darwin/ios/headless_platform_view_ios.h" #include "flutter/shell/platform/darwin/ios/platform_view_ios.h" -static std::unique_ptr CreateHeadlessPlatformView( - shell::Shell& shell) { - return std::make_unique(shell, shell.GetTaskRunners()); -} - -static std::unique_ptr CreateHeadlessRasterizer(shell::Shell& shell) { - return std::make_unique(shell.GetTaskRunners()); -} - -static std::string CreateShellLabel() { - static size_t count = 1; - std::stringstream stream; - stream << "io.flutter.headless."; - stream << count++; - return stream.str(); -} - @implementation FlutterHeadlessDartRunner { - shell::ThreadHost _threadHost; - std::unique_ptr _shell; } -- (void)runWithEntrypointAndLibraryUri:(NSString*)entrypoint libraryUri:(NSString*)uri { - if (_shell != nullptr || entrypoint.length == 0) { - FML_LOG(ERROR) << "This headless dart runner was already used to run some code."; - return; - } - - const auto label = CreateShellLabel(); - - // Create the threads to run the shell on. - _threadHost = { - label, // native thread label - shell::ThreadHost::Type::UI // managed threads to create - }; - - // Configure shell task runners. - auto current_task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner(); - auto single_task_runner = _threadHost.ui_thread->GetTaskRunner(); - blink::TaskRunners task_runners(label, // dart thread label - current_task_runner, // platform - single_task_runner, // gpu - single_task_runner, // ui - single_task_runner // io - ); - - auto settings = shell::SettingsFromCommandLine(shell::CommandLineFromNSProcessInfo()); - - // These values set the name of the isolate for debugging. - settings.advisory_script_entrypoint = entrypoint.UTF8String; - settings.advisory_script_uri = uri.UTF8String; - - // Create the shell. This is a blocking operation. - _shell = shell::Shell::Create( - std::move(task_runners), // task runners - std::move(settings), // settings - std::bind(&CreateHeadlessPlatformView, std::placeholders::_1), // platform view creation - std::bind(&CreateHeadlessRasterizer, std::placeholders::_1) // rasterzier creation - ); - - if (_shell == nullptr) { - FML_LOG(ERROR) << "Could not start a shell for the headless dart runner with entrypoint: " - << entrypoint.UTF8String; - return; - } - - FlutterDartProject* project = [[[FlutterDartProject alloc] init] autorelease]; - - auto config = project.runConfiguration; - config.SetEntrypointAndLibrary(entrypoint.UTF8String, uri.UTF8String); - - // Override the default run configuration with the specified entrypoint. - _shell->GetTaskRunners().GetUITaskRunner()->PostTask( - fml::MakeCopyable([engine = _shell->GetEngine(), config = std::move(config)]() mutable { - BOOL success = NO; - FML_LOG(INFO) << "Attempting to launch background engine configuration..."; - if (!engine || engine->Run(std::move(config)) == shell::Engine::RunStatus::Failure) { - FML_LOG(ERROR) << "Could not launch engine with configuration."; - } else { - FML_LOG(INFO) << "Background Isolate successfully started and run."; - success = YES; - } - })); +- (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil { + return [super initWithName:labelPrefix project:projectOrNil]; } - -- (void)runWithEntrypoint:(NSString*)entrypoint { - [self runWithEntrypointAndLibraryUri:entrypoint libraryUri:nil]; -} - -#pragma mark - FlutterBinaryMessenger - -- (void)sendOnChannel:(NSString*)channel message:(NSData*)message { - [self sendOnChannel:channel message:message binaryReply:nil]; +- (instancetype)init { + return [self initWithName:@"io.flutter.headless" project:nil]; } - -- (void)sendOnChannel:(NSString*)channel - message:(NSData*)message - binaryReply:(FlutterBinaryReply)callback { - NSAssert(channel, @"The channel must not be null"); - fml::RefPtr response = - (callback == nil) ? nullptr - : fml::MakeRefCounted( - ^(NSData* reply) { - callback(reply); - }, - _shell->GetTaskRunners().GetPlatformTaskRunner()); - fml::RefPtr platformMessage = - (message == nil) ? fml::MakeRefCounted(channel.UTF8String, response) - : fml::MakeRefCounted( - channel.UTF8String, shell::GetVectorFromNSData(message), response); - - _shell->GetPlatformView()->DispatchPlatformMessage(platformMessage); -} - -- (void)setMessageHandlerOnChannel:(NSString*)channel - binaryMessageHandler:(FlutterBinaryMessageHandler)handler { - reinterpret_cast(_shell->GetPlatformView().get()) - ->GetPlatformMessageRouter() - .SetMessageHandler(channel.UTF8String, handler); -} - @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterNavigationController.mm b/shell/platform/darwin/ios/framework/Source/FlutterNavigationController.mm deleted file mode 100644 index 2ca2978a548f..000000000000 --- a/shell/platform/darwin/ios/framework/Source/FlutterNavigationController.mm +++ /dev/null @@ -1,14 +0,0 @@ -// 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 "flutter/shell/platform/darwin/ios/framework/Headers/FlutterNavigationController.h" - -@implementation FlutterNavigationController - -- (void)viewWillAppear:(BOOL)animated { - [self setNavigationBarHidden:YES]; - [super viewWillAppear:animated]; -} - -@end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h index 09bdfa8b0ea4..23d86c04c299 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h @@ -7,13 +7,11 @@ #include "flutter/fml/memory/weak_ptr.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h" - -#include +#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h" @interface FlutterPlatformPlugin : NSObject - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithViewController:(fml::WeakPtr)viewController - NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithEngine:(fml::WeakPtr)engine NS_DESIGNATED_INITIALIZER; - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result; @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm index 54873532ae18..fb52763303e0 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm @@ -33,21 +33,21 @@ using namespace shell; @implementation FlutterPlatformPlugin { - fml::WeakPtr _viewController; + fml::WeakPtr _engine; } - (instancetype)init { - @throw([NSException exceptionWithName:@"FlutterPlatformPlugin must initWithViewController" + @throw([NSException exceptionWithName:@"FlutterPlatformPlugin must initWithEngine" reason:nil userInfo:nil]); } -- (instancetype)initWithViewController:(fml::WeakPtr)viewController { - FML_DCHECK(viewController) << "viewController must be set"; +- (instancetype)initWithEngine:(fml::WeakPtr)engine { + FML_DCHECK(engine) << "engine must be set"; self = [super init]; if (self) { - _viewController = viewController; + _engine = engine; } return self; @@ -203,8 +203,13 @@ - (void)popSystemNavigator { UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController; if ([viewController isKindOfClass:[UINavigationController class]]) { [((UINavigationController*)viewController) popViewControllerAnimated:NO]; - } else if (viewController != _viewController.get()) { - [_viewController.get() dismissViewControllerAnimated:NO completion:nil]; + [_engine.get() setViewController:nil]; + } else { + auto engineViewController = static_cast([_engine.get() viewController]); + if (engineViewController != viewController) { + [engineViewController dismissViewControllerAnimated:NO completion:nil]; + [_engine.get() setViewController:nil]; + } } } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h b/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h index 3136eb08ccaf..4c3cea566fc7 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h @@ -21,7 +21,7 @@ typedef NS_ENUM(NSInteger, FlutterTextInputAction) { FlutterTextInputActionNewline, }; -@protocol FlutterTextInputDelegate +@protocol FlutterTextInputDelegate - (void)updateEditingClient:(int)client withState:(NSDictionary*)state; - (void)performAction:(FlutterTextInputAction)action withClient:(int)client; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h index 198381e4ebbc..06e5b68b69ed 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h @@ -36,7 +36,7 @@ @end /** A range of text in the buffer of a Flutter text editing widget. */ -@interface FlutterTextRange : UITextRange +@interface FlutterTextRange : UITextRange @property(nonatomic, readonly) NSRange range; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 76c6229c73ce..ea56bfc2dfca 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -14,8 +14,7 @@ #include "flutter/fml/platform/darwin/platform_version.h" #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/common/thread_host.h" -#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h" -#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h" #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h" #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h" #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h" @@ -23,31 +22,9 @@ #include "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h" #include "flutter/shell/platform/darwin/ios/platform_view_ios.h" -@interface FlutterViewController () -@property(nonatomic, readonly) NSMutableDictionary* pluginPublications; -@end - -@interface FlutterViewControllerRegistrar : NSObject -- (instancetype)initWithPlugin:(NSString*)pluginKey - flutterViewController:(FlutterViewController*)flutterViewController; -@end - @implementation FlutterViewController { - fml::scoped_nsobject _dartProject; - shell::ThreadHost _threadHost; - std::unique_ptr _shell; std::unique_ptr> _weakFactory; - - // Channels - fml::scoped_nsobject _platformPlugin; - fml::scoped_nsobject _textInputPlugin; - fml::scoped_nsobject _localizationChannel; - fml::scoped_nsobject _navigationChannel; - fml::scoped_nsobject _platformChannel; - fml::scoped_nsobject _textInputChannel; - fml::scoped_nsobject _lifecycleChannel; - fml::scoped_nsobject _systemChannel; - fml::scoped_nsobject _settingsChannel; + fml::scoped_nsobject _engine; // We keep a separate reference to this and create it ahead of time because we want to be able to // setup a shell along with its platform view before the view has to appear. @@ -58,27 +35,41 @@ @implementation FlutterViewController { UIInterfaceOrientationMask _orientationPreferences; UIStatusBarStyle _statusBarStyle; blink::ViewportMetrics _viewportMetrics; - int64_t _nextTextureId; BOOL _initialized; BOOL _viewOpaque; - - fml::scoped_nsobject _publisher; } #pragma mark - Manage and override all designated initializers +- (instancetype)initWithEngine:(FlutterEngine*)engine + nibName:(NSString*)nibNameOrNil + bundle:(NSBundle*)nibBundleOrNil { + NSAssert(engine != nil, @"Engine is required"); + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + _viewOpaque = YES; + _engine.reset([engine retain]); + _flutterView.reset([[FlutterView alloc] initWithDelegate:_engine opaque:self.isViewOpaque]); + _weakFactory = std::make_unique>(self); + + [self performCommonViewControllerInitialization]; + [engine setViewController:self]; + } + + return self; +} + - (instancetype)initWithProject:(FlutterDartProject*)projectOrNil nibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { + _viewOpaque = YES; _weakFactory = std::make_unique>(self); - if (projectOrNil == nil) - _dartProject.reset([[FlutterDartProject alloc] init]); - else - _dartProject.reset([projectOrNil retain]); - - self.viewOpaque = YES; + _engine.reset([[FlutterEngine alloc] initWithName:@"io.flutter" project:projectOrNil]); + _flutterView.reset([[FlutterView alloc] initWithDelegate:_engine opaque:self.isViewOpaque]); + [_engine.get() runWithEntrypoint:nil]; + [_engine.get() setViewController:self]; [self performCommonViewControllerInitialization]; } @@ -98,6 +89,18 @@ - (instancetype)init { return [self initWithProject:nil nibName:nil bundle:nil]; } +- (BOOL)isViewOpaque { + return _viewOpaque; +} + +- (void)setViewOpaque:(BOOL)value { + _viewOpaque = value; + if (_flutterView.get().layer.opaque != value) { + _flutterView.get().layer.opaque = value; + [_flutterView.get().layer setNeedsLayout]; + } +} + #pragma mark - Common view controller initialization tasks - (void)performCommonViewControllerInitialization { @@ -106,147 +109,19 @@ - (void)performCommonViewControllerInitialization { _initialized = YES; - _publisher.reset([[FlutterObservatoryPublisher alloc] init]); - _orientationPreferences = UIInterfaceOrientationMaskAll; _statusBarStyle = UIStatusBarStyleDefault; - if ([self setupShell]) { - [self setupChannels]; - [self setupNotificationCenterObservers]; - - _platformViewsController.reset(new shell::FlutterPlatformViewsController(self)); - _pluginPublications = [NSMutableDictionary new]; - } + [self setupNotificationCenterObservers]; + _platformViewsController.reset(new shell::FlutterPlatformViewsController(_engine.get())); } -- (shell::Shell&)shell { - FML_DCHECK(_shell); - return *_shell; +- (fml::scoped_nsobject)engine { + return _engine; } -- (fml::WeakPtr)iosPlatformView { - FML_DCHECK(_shell); - return _shell->GetPlatformView(); -} - -- (BOOL)setupShell { - FML_DCHECK(_shell == nullptr); - - static size_t shell_count = 1; - - auto threadLabel = [NSString stringWithFormat:@"io.flutter.%zu", shell_count++]; - - _threadHost = { - threadLabel.UTF8String, // label - shell::ThreadHost::Type::UI | shell::ThreadHost::Type::GPU | shell::ThreadHost::Type::IO}; - - // The current thread will be used as the platform thread. Ensure that the message loop is - // initialized. - fml::MessageLoop::EnsureInitializedForCurrentThread(); - - blink::TaskRunners task_runners(threadLabel.UTF8String, // label - fml::MessageLoop::GetCurrent().GetTaskRunner(), // platform - _threadHost.gpu_thread->GetTaskRunner(), // gpu - _threadHost.ui_thread->GetTaskRunner(), // ui - _threadHost.io_thread->GetTaskRunner() // io - ); - - _flutterView.reset([[FlutterView alloc] initWithDelegate:self opaque:self.isViewOpaque]); - - // Lambda captures by pointers to ObjC objects are fine here because the create call is - // synchronous. - shell::Shell::CreateCallback on_create_platform_view = - [flutter_view_controller = self, flutter_view = _flutterView.get()](shell::Shell& shell) { - auto platform_view_ios = std::make_unique( - shell, // delegate - shell.GetTaskRunners(), // task runners - flutter_view_controller, // flutter view controller owner - flutter_view // flutter view owner - ); - return platform_view_ios; - }; - - shell::Shell::CreateCallback on_create_rasterizer = [](shell::Shell& shell) { - return std::make_unique(shell.GetTaskRunners()); - }; - - // Create the shell. - _shell = shell::Shell::Create(std::move(task_runners), // - [_dartProject settings], // - on_create_platform_view, // - on_create_rasterizer // - ); - - if (!_shell) { - FML_LOG(ERROR) << "Could not setup a shell to run the Dart application."; - return false; - } - - return true; -} - -- (BOOL)isViewOpaque { - return _viewOpaque; -} - -- (void)setViewOpaque:(BOOL)value { - _viewOpaque = value; - if (_flutterView.get().layer.opaque != value) { - _flutterView.get().layer.opaque = value; - [_flutterView.get().layer setNeedsLayout]; - } -} - -- (void)setupChannels { - _localizationChannel.reset([[FlutterMethodChannel alloc] - initWithName:@"flutter/localization" - binaryMessenger:self - codec:[FlutterJSONMethodCodec sharedInstance]]); - - _navigationChannel.reset([[FlutterMethodChannel alloc] - initWithName:@"flutter/navigation" - binaryMessenger:self - codec:[FlutterJSONMethodCodec sharedInstance]]); - - _platformChannel.reset([[FlutterMethodChannel alloc] - initWithName:@"flutter/platform" - binaryMessenger:self - codec:[FlutterJSONMethodCodec sharedInstance]]); - - _textInputChannel.reset([[FlutterMethodChannel alloc] - initWithName:@"flutter/textinput" - binaryMessenger:self - codec:[FlutterJSONMethodCodec sharedInstance]]); - - _lifecycleChannel.reset([[FlutterBasicMessageChannel alloc] - initWithName:@"flutter/lifecycle" - binaryMessenger:self - codec:[FlutterStringCodec sharedInstance]]); - - _systemChannel.reset([[FlutterBasicMessageChannel alloc] - initWithName:@"flutter/system" - binaryMessenger:self - codec:[FlutterJSONMessageCodec sharedInstance]]); - - _settingsChannel.reset([[FlutterBasicMessageChannel alloc] - initWithName:@"flutter/settings" - binaryMessenger:self - codec:[FlutterJSONMessageCodec sharedInstance]]); - - _platformPlugin.reset( - [[FlutterPlatformPlugin alloc] initWithViewController:_weakFactory->GetWeakPtr()]); - [_platformChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { - [_platformPlugin.get() handleMethodCall:call result:result]; - }]; - - _textInputPlugin.reset([[FlutterTextInputPlugin alloc] init]); - _textInputPlugin.get().textInputDelegate = self; - [_textInputChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { - [_textInputPlugin.get() handleMethodCall:call result:result]; - }]; - static_cast(_shell->GetPlatformView().get()) - ->SetTextInputPlugin(_textInputPlugin); +- (fml::WeakPtr)getWeakPtr { + return _weakFactory->GetWeakPtr(); } - (void)setupNotificationCenterObservers { @@ -338,15 +213,15 @@ - (void)setupNotificationCenterObservers { } - (void)setInitialRoute:(NSString*)route { - [_navigationChannel.get() invokeMethod:@"setInitialRoute" arguments:route]; + [[_engine.get() navigationChannel] invokeMethod:@"setInitialRoute" arguments:route]; } - (void)popRoute { - [_navigationChannel.get() invokeMethod:@"popRoute" arguments:nil]; + [[_engine.get() navigationChannel] invokeMethod:@"popRoute" arguments:nil]; } - (void)pushRoute:(NSString*)route { - [_navigationChannel.get() invokeMethod:@"pushRoute" arguments:route]; + [[_engine.get() navigationChannel] invokeMethod:@"pushRoute" arguments:route]; } #pragma mark - Loading the view @@ -399,33 +274,36 @@ - (void)removeSplashScreenViewIfPresent { } - (void)installSplashScreenViewCallback { - if (!_shell || !_splashScreenView) { + if (!_splashScreenView) { return; } - auto weak_platform_view = _shell->GetPlatformView(); + auto weak_platform_view = [_engine.get() platformView]; if (!weak_platform_view) { return; } __unsafe_unretained auto weak_flutter_view_controller = self; // This is on the platform thread. - weak_platform_view->SetNextFrameCallback( - [weak_platform_view, weak_flutter_view_controller, - task_runner = _shell->GetTaskRunners().GetPlatformTaskRunner()]() { - // This is on the GPU thread. - task_runner->PostTask([weak_platform_view, weak_flutter_view_controller]() { - // We check if the weak platform view is alive. If it is alive, then the view controller - // also has to be alive since the view controller owns the platform view via the shell - // association. Thus, we are not convinced that the unsafe unretained weak object is in - // fact alive. - if (weak_platform_view) { - [weak_flutter_view_controller removeSplashScreenViewIfPresent]; - } - }); - }); + weak_platform_view->SetNextFrameCallback([weak_platform_view, weak_flutter_view_controller, + task_runner = [_engine.get() platformTaskRunner]]() { + // This is on the GPU thread. + task_runner->PostTask([weak_platform_view, weak_flutter_view_controller]() { + // We check if the weak platform view is alive. If it is alive, then the view controller + // also has to be alive since the view controller owns the platform view via the shell + // association. Thus, we are not convinced that the unsafe unretained weak object is in + // fact alive. + if (weak_platform_view) { + [weak_flutter_view_controller removeSplashScreenViewIfPresent]; + } + }); + }); } #pragma mark - Properties +- (FlutterView*)flutterView { + return _flutterView; +} + - (UIView*)splashScreenView { if (_splashScreenView == nullptr) { NSString* launchscreenName = @@ -481,10 +359,10 @@ - (void)surfaceUpdated:(BOOL)appeared { // NotifyCreated/NotifyDestroyed are synchronous and require hops between the UI and GPU thread. if (appeared) { [self installSplashScreenViewCallback]; - _shell->GetPlatformView()->NotifyCreated(); + [_engine.get() platformView] -> NotifyCreated(); } else { - _shell->GetPlatformView()->NotifyDestroyed(); + [_engine.get() platformView] -> NotifyDestroyed(); } } @@ -493,24 +371,11 @@ - (void)surfaceUpdated:(BOOL)appeared { - (void)viewWillAppear:(BOOL)animated { TRACE_EVENT0("flutter", "viewWillAppear"); - // Launch the Dart application with the inferred run configuration. - _shell->GetTaskRunners().GetUITaskRunner()->PostTask( - fml::MakeCopyable([engine = _shell->GetEngine(), // - config = [_dartProject.get() runConfiguration] // - ]() mutable { - if (engine) { - auto result = engine->Run(std::move(config)); - if (result == shell::Engine::RunStatus::Failure) { - FML_LOG(ERROR) << "Could not launch engine with configuration."; - } - } - })); - // Only recreate surface on subsequent appearances when viewport metrics are known. // First time surface creation is done on viewDidLayoutSubviews. if (_viewportMetrics.physical_width) [self surfaceUpdated:YES]; - [_lifecycleChannel.get() sendMessage:@"AppLifecycleState.inactive"]; + [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.inactive"]; [super viewWillAppear:animated]; } @@ -520,14 +385,14 @@ - (void)viewDidAppear:(BOOL)animated { [self onLocaleUpdated:nil]; [self onUserSettingsChanged:nil]; [self onAccessibilityStatusChanged:nil]; - [_lifecycleChannel.get() sendMessage:@"AppLifecycleState.resumed"]; + [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.resumed"]; [super viewDidAppear:animated]; } - (void)viewWillDisappear:(BOOL)animated { TRACE_EVENT0("flutter", "viewWillDisappear"); - [_lifecycleChannel.get() sendMessage:@"AppLifecycleState.inactive"]; + [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.inactive"]; [super viewWillDisappear:animated]; } @@ -535,14 +400,13 @@ - (void)viewWillDisappear:(BOOL)animated { - (void)viewDidDisappear:(BOOL)animated { TRACE_EVENT0("flutter", "viewDidDisappear"); [self surfaceUpdated:NO]; - [_lifecycleChannel.get() sendMessage:@"AppLifecycleState.paused"]; + [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.paused"]; [super viewDidDisappear:animated]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [_pluginPublications release]; [super dealloc]; } @@ -550,25 +414,25 @@ - (void)dealloc { - (void)applicationBecameActive:(NSNotification*)notification { TRACE_EVENT0("flutter", "applicationBecameActive"); - [_lifecycleChannel.get() sendMessage:@"AppLifecycleState.resumed"]; + [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.resumed"]; } - (void)applicationWillResignActive:(NSNotification*)notification { TRACE_EVENT0("flutter", "applicationWillResignActive"); - [_lifecycleChannel.get() sendMessage:@"AppLifecycleState.inactive"]; + [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.inactive"]; } - (void)applicationDidEnterBackground:(NSNotification*)notification { TRACE_EVENT0("flutter", "applicationDidEnterBackground"); [self surfaceUpdated:NO]; - [_lifecycleChannel.get() sendMessage:@"AppLifecycleState.paused"]; + [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.paused"]; } - (void)applicationWillEnterForeground:(NSNotification*)notification { TRACE_EVENT0("flutter", "applicationWillEnterForeground"); if (_viewportMetrics.physical_width) [self surfaceUpdated:YES]; - [_lifecycleChannel.get() sendMessage:@"AppLifecycleState.inactive"]; + [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.inactive"]; } #pragma mark - Touch event handling @@ -694,12 +558,7 @@ - (void)dispatchTouches:(NSSet*)touches packet->SetPointerData(pointer_index++, pointer_data); } - _shell->GetTaskRunners().GetUITaskRunner()->PostTask( - fml::MakeCopyable([engine = _shell->GetEngine(), packet = std::move(packet)] { - if (engine) { - engine->DispatchPointerDataPacket(*packet); - } - })); + [_engine.get() dispatchPointerDataPacket:std::move(packet)]; } - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { @@ -721,12 +580,7 @@ - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { #pragma mark - Handle view resizing - (void)updateViewportMetrics { - _shell->GetTaskRunners().GetUITaskRunner()->PostTask( - [engine = _shell->GetEngine(), metrics = _viewportMetrics]() { - if (engine) { - engine->SetViewportMetrics(std::move(metrics)); - } - }); + [_engine.get() updateViewportMetrics:_viewportMetrics]; } - (CGFloat)statusBarPadding { @@ -806,66 +660,6 @@ - (void)keyboardWillBeHidden:(NSNotification*)notification { [self updateViewportMetrics]; } -#pragma mark - Text input delegate - -- (void)updateEditingClient:(int)client withState:(NSDictionary*)state { - [_textInputChannel.get() invokeMethod:@"TextInputClient.updateEditingState" - arguments:@[ @(client), state ]]; -} - -- (void)performAction:(FlutterTextInputAction)action withClient:(int)client { - NSString* actionString; - switch (action) { - case FlutterTextInputActionUnspecified: - // Where did the term "unspecified" come from? iOS has a "default" and Android - // has "unspecified." These 2 terms seem to mean the same thing but we need - // to pick just one. "unspecified" was chosen because "default" is often a - // reserved word in languages with switch statements (dart, java, etc). - actionString = @"TextInputAction.unspecified"; - break; - case FlutterTextInputActionDone: - actionString = @"TextInputAction.done"; - break; - case FlutterTextInputActionGo: - actionString = @"TextInputAction.go"; - break; - case FlutterTextInputActionSend: - actionString = @"TextInputAction.send"; - break; - case FlutterTextInputActionSearch: - actionString = @"TextInputAction.search"; - break; - case FlutterTextInputActionNext: - actionString = @"TextInputAction.next"; - break; - case FlutterTextInputActionContinue: - actionString = @"TextInputAction.continue"; - break; - case FlutterTextInputActionJoin: - actionString = @"TextInputAction.join"; - break; - case FlutterTextInputActionRoute: - actionString = @"TextInputAction.route"; - break; - case FlutterTextInputActionEmergencyCall: - actionString = @"TextInputAction.emergencyCall"; - break; - case FlutterTextInputActionNewline: - actionString = @"TextInputAction.newline"; - break; - } - [_textInputChannel.get() invokeMethod:@"TextInputClient.performAction" - arguments:@[ @(client), actionString ]]; -} - -#pragma mark - Screenshot Delegate - -- (shell::Rasterizer::Screenshot)takeScreenshot:(shell::Rasterizer::ScreenshotType)type - asBase64Encoded:(BOOL)base64Encode { - FML_DCHECK(_shell) << "Cannot takeScreenshot without a shell"; - return _shell->Screenshot(type, base64Encode); -} - #pragma mark - Orientation updates - (void)onOrientationPreferencesUpdated:(NSNotification*)notification { @@ -899,7 +693,7 @@ - (NSUInteger)supportedInterfaceOrientations { #pragma mark - Accessibility - (void)onAccessibilityStatusChanged:(NSNotification*)notification { - auto platformView = _shell->GetPlatformView(); + auto platformView = [_engine.get() platformView]; int32_t flags = 0; if (UIAccessibilityIsInvertColorsEnabled()) flags ^= static_cast(blink::AccessibilityFeatureFlag::kInvertColors); @@ -925,7 +719,7 @@ - (void)onAccessibilityStatusChanged:(NSNotification*)notification { #pragma mark - Memory Notifications - (void)onMemoryWarning:(NSNotification*)notification { - [_systemChannel.get() sendMessage:@{@"type" : @"memoryPressure"}]; + [[_engine.get() systemChannel] sendMessage:@{@"type" : @"memoryPressure"}]; } #pragma mark - Locale updates @@ -950,13 +744,13 @@ - (void)onLocaleUpdated:(NSNotification*)notification { if (data.count == 0) { return; } - [_localizationChannel.get() invokeMethod:@"setLocale" arguments:data]; + [[_engine.get() localizationChannel] invokeMethod:@"setLocale" arguments:data]; } #pragma mark - Set user settings - (void)onUserSettingsChanged:(NSNotification*)notification { - [_settingsChannel.get() sendMessage:@{ + [[_engine.get() settingsChannel] sendMessage:@{ @"textScaleFactor" : @([self textScaleFactor]), @"alwaysUse24HourFormat" : @([self isAlwaysUse24HourFormat]), }]; @@ -1103,49 +897,34 @@ - (void)onPreferredStatusBarStyleUpdated:(NSNotification*)notification { #pragma mark - FlutterBinaryMessenger - (void)sendOnChannel:(NSString*)channel message:(NSData*)message { - [self sendOnChannel:channel message:message binaryReply:nil]; + [_engine.get() sendOnChannel:channel message:message]; } - (void)sendOnChannel:(NSString*)channel message:(NSData*)message binaryReply:(FlutterBinaryReply)callback { NSAssert(channel, @"The channel must not be null"); - fml::RefPtr response = - (callback == nil) ? nullptr - : fml::MakeRefCounted( - ^(NSData* reply) { - callback(reply); - }, - _shell->GetTaskRunners().GetPlatformTaskRunner()); - fml::RefPtr platformMessage = - (message == nil) ? fml::MakeRefCounted(channel.UTF8String, response) - : fml::MakeRefCounted( - channel.UTF8String, shell::GetVectorFromNSData(message), response); - - _shell->GetPlatformView()->DispatchPlatformMessage(platformMessage); + [_engine.get() sendOnChannel:channel message:message binaryReply:callback]; } - (void)setMessageHandlerOnChannel:(NSString*)channel binaryMessageHandler:(FlutterBinaryMessageHandler)handler { NSAssert(channel, @"The channel must not be null"); - [self iosPlatformView] -> GetPlatformMessageRouter().SetMessageHandler(channel.UTF8String, - handler); + [_engine.get() setMessageHandlerOnChannel:channel binaryMessageHandler:handler]; } #pragma mark - FlutterTextureRegistry - (int64_t)registerTexture:(NSObject*)texture { - int64_t textureId = _nextTextureId++; - [self iosPlatformView] -> RegisterExternalTexture(textureId, texture); - return textureId; + return [_engine.get() registerTexture:texture]; } - (void)unregisterTexture:(int64_t)textureId { - _shell->GetPlatformView()->UnregisterTexture(textureId); + [_engine.get() unregisterTexture:textureId]; } - (void)textureFrameAvailable:(int64_t)textureId { - _shell->GetPlatformView()->MarkTextureFrameAvailable(textureId); + [_engine.get() textureFrameAvailable:textureId]; } - (NSString*)lookupKeyForAsset:(NSString*)asset { @@ -1157,86 +936,21 @@ - (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package { } - (id)pluginRegistry { - return self; + return _engine; } #pragma mark - FlutterPluginRegistry - (NSObject*)registrarForPlugin:(NSString*)pluginKey { - NSAssert(self.pluginPublications[pluginKey] == nil, @"Duplicate plugin key: %@", pluginKey); - self.pluginPublications[pluginKey] = [NSNull null]; - return [[FlutterViewControllerRegistrar alloc] initWithPlugin:pluginKey - flutterViewController:self]; + return [_engine.get() registrarForPlugin:pluginKey]; } - (BOOL)hasPlugin:(NSString*)pluginKey { - return _pluginPublications[pluginKey] != nil; + return [_engine.get() hasPlugin:pluginKey]; } - (NSObject*)valuePublishedByPlugin:(NSString*)pluginKey { - return _pluginPublications[pluginKey]; -} -@end - -@implementation FlutterViewControllerRegistrar { - NSString* _pluginKey; - FlutterViewController* _flutterViewController; -} - -- (instancetype)initWithPlugin:(NSString*)pluginKey - flutterViewController:(FlutterViewController*)flutterViewController { - self = [super init]; - NSAssert(self, @"Super init cannot be nil"); - _pluginKey = [pluginKey retain]; - _flutterViewController = [flutterViewController retain]; - return self; -} - -- (void)dealloc { - [_pluginKey release]; - [_flutterViewController release]; - [super dealloc]; -} - -- (NSObject*)messenger { - return _flutterViewController; -} - -- (NSObject*)textures { - return _flutterViewController; -} - -- (void)registerViewFactory:(NSObject*)factory - withId:(NSString*)factoryId { - [_flutterViewController platformViewsController] -> RegisterViewFactory(factory, factoryId); -} - -- (void)publish:(NSObject*)value { - _flutterViewController.pluginPublications[_pluginKey] = value; -} - -- (void)addMethodCallDelegate:(NSObject*)delegate - channel:(FlutterMethodChannel*)channel { - [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { - [delegate handleMethodCall:call result:result]; - }]; -} - -- (void)addApplicationDelegate:(NSObject*)delegate { - id appDelegate = [[UIApplication sharedApplication] delegate]; - if ([appDelegate conformsToProtocol:@protocol(FlutterAppLifeCycleProvider)]) { - id lifeCycleProvider = - (id)appDelegate; - [lifeCycleProvider addApplicationLifeCycleDelegate:delegate]; - } -} - -- (NSString*)lookupKeyForAsset:(NSString*)asset { - return [_flutterViewController lookupKeyForAsset:asset]; -} - -- (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package { - return [_flutterViewController lookupKeyForAsset:asset fromPackage:package]; + return [_engine.get() valuePublishedByPlugin:pluginKey]; } -@end +@end \ No newline at end of file diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h index 482379c8f17e..75e820907cc0 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h @@ -5,12 +5,17 @@ #ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_ #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_ -#include "flutter/shell/common/shell.h" +#include "flutter/fml/memory/weak_ptr.h" +#include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h" @interface FlutterViewController () -- (shell::Shell&)shell; +- (fml::WeakPtr)getWeakPtr; +- (shell::FlutterPlatformViewsController*)platformViewsController; + +@property(readonly) fml::scoped_nsobject engine; @end diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm index 6b60bc6b3ba6..b094579c9f40 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm @@ -257,7 +257,7 @@ - (CGRect)globalRect { // `rect` is in the physical pixel coordinate system. iOS expects the accessibility frame in // the logical pixel coordinate system. Therefore, we divide by the `scale` (pixel ratio) to // convert. - CGFloat scale = [[[self bridge] -> view() window] screen].scale; + CGFloat scale = [[[self bridge]->view() window] screen].scale; auto result = CGRectMake(rect.x() / scale, rect.y() / scale, rect.width() / scale, rect.height() / scale); return UIAccessibilityConvertFrameToScreenCoordinates(result, [self bridge] -> view()); @@ -268,8 +268,8 @@ - (CGRect)globalRect { - (id)accessibilityContainer { if ([self hasChildren] || [self uid] == kRootNodeId) { if (_container == nil) - _container = - [[SemanticsObjectContainer alloc] initWithSemanticsObject:self bridge:[self bridge]]; + _container = [[SemanticsObjectContainer alloc] initWithSemanticsObject:self + bridge:[self bridge]]; return _container; } if ([self parent] == nil) { @@ -498,7 +498,7 @@ - (BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction { previous_routes_({}) { accessibility_channel_.reset([[FlutterBasicMessageChannel alloc] initWithName:@"flutter/accessibility" - binaryMessenger:platform_view->GetOwnerViewController() + binaryMessenger:platform_view->GetOwnerViewController().get() codec:[FlutterStandardMessageCodec sharedInstance]]); [accessibility_channel_.get() setMessageHandler:^(id message, FlutterReply reply) { HandleEvent((NSDictionary*)message); @@ -654,11 +654,11 @@ - (BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction { [objects_ removeObjectForKey:@(node.id)]; if (isTextField) { // Text fields are backed by objects that implement UITextInput. - object = - [[[TextInputSemanticsObject alloc] initWithBridge:GetWeakPtr() uid:uid] autorelease]; + object = [[[TextInputSemanticsObject alloc] initWithBridge:GetWeakPtr() + uid:uid] autorelease]; } else { - object = - [[[FlutterSemanticsObject alloc] initWithBridge:GetWeakPtr() uid:uid] autorelease]; + object = [[[FlutterSemanticsObject alloc] initWithBridge:GetWeakPtr() + uid:uid] autorelease]; } [object.parent.children replaceObjectAtIndex:positionInChildlist withObject:object]; objects_.get()[@(node.id)] = object; diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h b/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h index bcdebfc689de..ecc26a240a15 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h +++ b/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h @@ -11,7 +11,7 @@ * * This class is used by `TextInputSemanticsObject`. */ -@interface FlutterInactiveTextInput : UIView +@interface FlutterInactiveTextInput : UIView @property(nonatomic, copy) NSString* text; @property(nonatomic, readonly) NSMutableString* markedText; @@ -30,7 +30,7 @@ * field that currently owns input focus. Delegates to * `FlutterInactiveTextInput` otherwise. */ -@interface TextInputSemanticsObject : SemanticsObject +@interface TextInputSemanticsObject : SemanticsObject @end #endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_ACCESSIBILITY_TEXT_ENTRY_H_ diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.mm b/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.mm index ec98c5d00320..c5b63d3d3964 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.mm @@ -343,8 +343,9 @@ - (UITextPosition*)positionFromPosition:(UITextPosition*)position offset:(NSInte - (UITextPosition*)positionFromPosition:(UITextPosition*)position inDirection:(UITextLayoutDirection)direction offset:(NSInteger)offset { - return - [[self textInputSurrogate] positionFromPosition:position inDirection:direction offset:offset]; + return [[self textInputSurrogate] positionFromPosition:position + inDirection:direction + offset:offset]; } - (NSComparisonResult)comparePosition:(UITextPosition*)position toPosition:(UITextPosition*)other { @@ -362,8 +363,8 @@ - (UITextPosition*)positionWithinRange:(UITextRange*)range - (UITextRange*)characterRangeByExtendingPosition:(UITextPosition*)position inDirection:(UITextLayoutDirection)direction { - return - [[self textInputSurrogate] characterRangeByExtendingPosition:position inDirection:direction]; + return [[self textInputSurrogate] characterRangeByExtendingPosition:position + inDirection:direction]; } - (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition*)position diff --git a/shell/platform/darwin/ios/framework/Source/flutter_codecs_unittest.mm b/shell/platform/darwin/ios/framework/Source/flutter_codecs_unittest.mm index b94793d39e81..502df4b55ee8 100644 --- a/shell/platform/darwin/ios/framework/Source/flutter_codecs_unittest.mm +++ b/shell/platform/darwin/ios/framework/Source/flutter_codecs_unittest.mm @@ -56,7 +56,7 @@ } TEST(FlutterJSONCodec, CanEncodeAndDecodeDictionary) { - NSDictionary* value = @{ @"a" : @3.14, @"b" : @47, @"c" : [NSNull null], @"d" : @[ @"nested" ] }; + NSDictionary* value = @{@"a" : @3.14, @"b" : @47, @"c" : [NSNull null], @"d" : @[ @"nested" ]}; FlutterJSONMessageCodec* codec = [FlutterJSONMessageCodec sharedInstance]; NSData* encoded = [codec encode:value]; NSDictionary* decoded = [codec decode:encoded]; diff --git a/shell/platform/darwin/ios/headless_platform_view_ios.h b/shell/platform/darwin/ios/headless_platform_view_ios.h deleted file mode 100644 index 940e2ade4af5..000000000000 --- a/shell/platform/darwin/ios/headless_platform_view_ios.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2018 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. - -#ifndef SHELL_PLATFORM_IOS_HEADLESS_PLATFORM_VIEW_IOS_H_ -#define SHELL_PLATFORM_IOS_HEADLESS_PLATFORM_VIEW_IOS_H_ - -#include - -#include "flutter/fml/closure.h" -#include "flutter/fml/macros.h" -#include "flutter/fml/memory/weak_ptr.h" -#include "flutter/fml/platform/darwin/scoped_nsobject.h" -#include "flutter/shell/common/platform_view.h" -#include "flutter/shell/platform/darwin/ios/framework/Source/platform_message_router.h" - -namespace shell { - -class HeadlessPlatformViewIOS : public PlatformView { - public: - explicit HeadlessPlatformViewIOS(Delegate& delegate, - blink::TaskRunners task_runners); - virtual ~HeadlessPlatformViewIOS(); - - PlatformMessageRouter& GetPlatformMessageRouter(); - - private: - PlatformMessageRouter platform_message_router_; - - // |shell::PlatformView| - void HandlePlatformMessage(fml::RefPtr message); - - FML_DISALLOW_COPY_AND_ASSIGN(HeadlessPlatformViewIOS); -}; - -} // namespace shell - -#endif // SHELL_PLATFORM_IOS_HEADLESS_PLATFORM_VIEW_IOS_H_ diff --git a/shell/platform/darwin/ios/headless_platform_view_ios.mm b/shell/platform/darwin/ios/headless_platform_view_ios.mm deleted file mode 100644 index c49625349439..000000000000 --- a/shell/platform/darwin/ios/headless_platform_view_ios.mm +++ /dev/null @@ -1,20 +0,0 @@ - -#include "flutter/shell/platform/darwin/ios/headless_platform_view_ios.h" - -namespace shell { - -HeadlessPlatformViewIOS::HeadlessPlatformViewIOS(PlatformView::Delegate& delegate, - blink::TaskRunners task_runners) - : PlatformView(delegate, std::move(task_runners)) {} - -HeadlessPlatformViewIOS::~HeadlessPlatformViewIOS() = default; - -PlatformMessageRouter& HeadlessPlatformViewIOS::GetPlatformMessageRouter() { - return platform_message_router_; -} - -// |shell::PlatformView| -void HeadlessPlatformViewIOS::HandlePlatformMessage(fml::RefPtr message) { - platform_message_router_.HandlePlatformMessage(std::move(message)); -} -} diff --git a/shell/platform/darwin/ios/ios_external_texture_gl.h b/shell/platform/darwin/ios/ios_external_texture_gl.h index 0ad69483385f..1a1fa997f8f4 100644 --- a/shell/platform/darwin/ios/ios_external_texture_gl.h +++ b/shell/platform/darwin/ios/ios_external_texture_gl.h @@ -13,15 +13,12 @@ namespace shell { class IOSExternalTextureGL : public flow::Texture { public: - IOSExternalTextureGL(int64_t textureId, - NSObject* externalTexture); + IOSExternalTextureGL(int64_t textureId, NSObject* externalTexture); ~IOSExternalTextureGL() override; // Called from GPU thread. - virtual void Paint(SkCanvas& canvas, - const SkRect& bounds, - bool freeze) override; + virtual void Paint(SkCanvas& canvas, const SkRect& bounds, bool freeze) override; virtual void OnGrContextCreated() override; diff --git a/shell/platform/darwin/ios/ios_gl_context.mm b/shell/platform/darwin/ios/ios_gl_context.mm index 765e3c365058..b3debd6f6437 100644 --- a/shell/platform/darwin/ios/ios_gl_context.mm +++ b/shell/platform/darwin/ios/ios_gl_context.mm @@ -127,6 +127,8 @@ TRACE_EVENT_INSTANT0("flutter", "IOSGLContext::UpdateStorageSizeIfNecessary"); FML_DLOG(INFO) << "Updating render buffer storage size."; + FML_DCHECK(glGetError() == GL_NO_ERROR); + if (![EAGLContext setCurrentContext:context_]) { return false; } diff --git a/shell/platform/darwin/ios/ios_surface_software.h b/shell/platform/darwin/ios/ios_surface_software.h index 154f057489f4..25ab355b91cf 100644 --- a/shell/platform/darwin/ios/ios_surface_software.h +++ b/shell/platform/darwin/ios/ios_surface_software.h @@ -14,8 +14,7 @@ namespace shell { -class IOSSurfaceSoftware final : public IOSSurface, - public GPUSurfaceSoftwareDelegate { +class IOSSurfaceSoftware final : public IOSSurface, public GPUSurfaceSoftwareDelegate { public: IOSSurfaceSoftware(fml::scoped_nsobject layer); diff --git a/shell/platform/darwin/ios/platform_view_ios.h b/shell/platform/darwin/ios/platform_view_ios.h index 014f045f70c7..50e8fa7a1ec3 100644 --- a/shell/platform/darwin/ios/platform_view_ios.h +++ b/shell/platform/darwin/ios/platform_view_ios.h @@ -16,38 +16,41 @@ #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h" #include "flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h" -#include "flutter/shell/platform/darwin/ios/headless_platform_view_ios.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/platform_message_router.h" #include "flutter/shell/platform/darwin/ios/ios_surface.h" +@class FlutterViewController; + namespace shell { -class PlatformViewIOS final : public HeadlessPlatformViewIOS { +class PlatformViewIOS final : public PlatformView { public: - explicit PlatformViewIOS(PlatformView::Delegate& delegate, - blink::TaskRunners task_runners, - FlutterViewController* owner_controller_, - FlutterView* owner_view_); + explicit PlatformViewIOS(PlatformView::Delegate& delegate, blink::TaskRunners task_runners); + + ~PlatformViewIOS(); - ~PlatformViewIOS() override; + PlatformMessageRouter& GetPlatformMessageRouter(); - FlutterViewController* GetOwnerViewController() const; + fml::WeakPtr GetOwnerViewController() const; + void SetOwnerViewController(fml::WeakPtr owner_controller); void RegisterExternalTexture(int64_t id, NSObject* texture); fml::scoped_nsprotocol GetTextInputPlugin() const; - void SetTextInputPlugin( - fml::scoped_nsprotocol plugin); + void SetTextInputPlugin(fml::scoped_nsprotocol plugin); private: - FlutterViewController* owner_controller_; // weak reference. - FlutterView* owner_view_; // weak reference. + fml::WeakPtr owner_controller_; std::unique_ptr ios_surface_; PlatformMessageRouter platform_message_router_; std::unique_ptr accessibility_bridge_; fml::scoped_nsprotocol text_input_plugin_; fml::closure firstFrameCallback_; + // |shell::PlatformView| + void HandlePlatformMessage(fml::RefPtr message) override; + // |shell::PlatformView| std::unique_ptr CreateRenderingSurface() override; @@ -61,9 +64,8 @@ class PlatformViewIOS final : public HeadlessPlatformViewIOS { void SetAccessibilityFeatures(int32_t flags) override; // |shell::PlatformView| - void UpdateSemantics( - blink::SemanticsNodeUpdates update, - blink::CustomAccessibilityActionUpdates actions) override; + void UpdateSemantics(blink::SemanticsNodeUpdates update, + blink::CustomAccessibilityActionUpdates actions) override; // |shell::PlatformView| std::unique_ptr CreateVSyncWaiter() override; diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index 7bf089558934..6a701d06669d 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -17,25 +17,46 @@ namespace shell { -PlatformViewIOS::PlatformViewIOS(PlatformView::Delegate& delegate, - blink::TaskRunners task_runners, - FlutterViewController* owner_controller, - FlutterView* owner_view) - : HeadlessPlatformViewIOS(delegate, std::move(task_runners)), - owner_controller_(owner_controller), - owner_view_(owner_view), - ios_surface_(owner_view_.createSurface) { - FML_DCHECK(ios_surface_ != nullptr); - FML_DCHECK(owner_controller_ != nullptr); - FML_DCHECK(owner_view_ != nullptr); -} +PlatformViewIOS::PlatformViewIOS(PlatformView::Delegate& delegate, blink::TaskRunners task_runners) + : PlatformView(delegate, std::move(task_runners)) {} PlatformViewIOS::~PlatformViewIOS() = default; -FlutterViewController* PlatformViewIOS::GetOwnerViewController() const { +PlatformMessageRouter& PlatformViewIOS::GetPlatformMessageRouter() { + return platform_message_router_; +} + +// |shell::PlatformView| +void PlatformViewIOS::HandlePlatformMessage(fml::RefPtr message) { + platform_message_router_.HandlePlatformMessage(std::move(message)); +} + +fml::WeakPtr PlatformViewIOS::GetOwnerViewController() const { return owner_controller_; } +void PlatformViewIOS::SetOwnerViewController(fml::WeakPtr owner_controller) { + if (ios_surface_ || !owner_controller) { + NotifyDestroyed(); + ios_surface_.reset(); + accessibility_bridge_.reset(); + } + owner_controller_ = owner_controller; + if (owner_controller_) { + ios_surface_ = static_cast(owner_controller.get().view).createSurface; + FML_DCHECK(ios_surface_ != nullptr); + + if (accessibility_bridge_) { + accessibility_bridge_.reset( + new AccessibilityBridge(static_cast(owner_controller_.get().view), this)); + } + // Do not call `NotifyCreated()` here - let FlutterViewController take care + // of that when its Viewport is sized. If `NotifyCreated()` is called here, + // it can occasionally get invoked before the viewport is sized resulting in + // a framebuffer that will not be able to completely attach. + } +} + void PlatformViewIOS::RegisterExternalTexture(int64_t texture_id, NSObject* texture) { RegisterTexture(std::make_shared(texture_id, texture)); @@ -43,13 +64,19 @@ // |shell::PlatformView| std::unique_ptr PlatformViewIOS::CreateRenderingSurface() { + if (!ios_surface_) { + FML_DLOG(INFO) << "Could not CreateRenderingSurface, this PlatformViewIOS " + "has no ViewController."; + return nullptr; + } return ios_surface_->CreateGPUSurface(); } // |shell::PlatformView| sk_sp PlatformViewIOS::CreateResourceContext() const { - if (!ios_surface_->ResourceContextMakeCurrent()) { - FML_DLOG(INFO) << "Could not make resource context current on IO thread. Async texture uploads " + if (!ios_surface_ || !ios_surface_->ResourceContextMakeCurrent()) { + FML_DLOG(INFO) << "Could not make resource context current on IO thread. " + "Async texture uploads " "will be disabled."; return nullptr; } @@ -59,8 +86,14 @@ // |shell::PlatformView| void PlatformViewIOS::SetSemanticsEnabled(bool enabled) { + if (!owner_controller_) { + FML_DLOG(WARNING) << "Could not set semantics to enabled, this " + "PlatformViewIOS has no ViewController."; + return; + } if (enabled && !accessibility_bridge_) { - accessibility_bridge_ = std::make_unique(owner_view_, this); + accessibility_bridge_ = std::make_unique( + static_cast(owner_controller_.get().view), this); } else if (!enabled && accessibility_bridge_) { accessibility_bridge_.reset(); }