Flutter iOS Embedder
platform_message_handler_ios.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
7 #include "flutter/fml/trace_event.h"
8 #include "flutter/lib/ui/window/platform_message.h"
9 #include "flutter/lib/ui/window/platform_message_response.h"
11 
13 
14 static uint64_t platform_message_counter = 1;
15 
17 @property(nonatomic, readonly) dispatch_queue_t queue;
18 @end
19 
20 @implementation FLTSerialTaskQueue
21 - (instancetype)init {
22  self = [super init];
23  if (self) {
24  _queue = dispatch_queue_create("FLTSerialTaskQueue", DISPATCH_QUEUE_SERIAL);
25  }
26  return self;
27 }
28 
29 - (void)dispatch:(dispatch_block_t)block {
30  dispatch_async(self.queue, block);
31 }
32 @end
33 
34 namespace flutter {
35 
36 NSObject<FlutterTaskQueue>* PlatformMessageHandlerIos::MakeBackgroundTaskQueue() {
37  return [[FLTSerialTaskQueue alloc] init];
38 }
39 
40 PlatformMessageHandlerIos::PlatformMessageHandlerIos(
41  fml::RefPtr<fml::TaskRunner> platform_task_runner)
42  : platform_task_runner_(std::move(platform_task_runner)) {}
43 
44 void PlatformMessageHandlerIos::HandlePlatformMessage(std::unique_ptr<PlatformMessage> message) {
45  // This can be called from any isolate's thread.
46  @autoreleasepool {
47  fml::RefPtr<flutter::PlatformMessageResponse> completer = message->response();
48  HandlerInfo handler_info;
49  {
50  // TODO(gaaclarke): This mutex is a bottleneck for multiple isolates sending
51  // messages at the same time. This could be potentially changed to a
52  // read-write lock.
53  std::lock_guard lock(message_handlers_mutex_);
54  auto it = message_handlers_.find(message->channel());
55  if (it != message_handlers_.end()) {
56  handler_info = it->second;
57  }
58  }
59  if (handler_info.handler) {
60  FlutterBinaryMessageHandler handler = handler_info.handler;
61  NSData* data = nil;
62  if (message->hasData()) {
63  data = ConvertMappingToNSData(message->releaseData());
64  }
65 
66  uint64_t platform_message_id = platform_message_counter++;
67  TRACE_EVENT_ASYNC_BEGIN1("flutter", "PlatformChannel ScheduleHandler", platform_message_id,
68  "channel", message->channel().c_str());
69  dispatch_block_t run_handler = ^{
70  handler(data, ^(NSData* reply) {
71  TRACE_EVENT_ASYNC_END0("flutter", "PlatformChannel ScheduleHandler", platform_message_id);
72  // Called from any thread.
73  if (completer) {
74  if (reply) {
75  completer->Complete(ConvertNSDataToMappingPtr(reply));
76  } else {
77  completer->CompleteEmpty();
78  }
79  }
80  });
81  };
82 
83  if (handler_info.task_queue.get()) {
84  [handler_info.task_queue.get() dispatch:run_handler];
85  } else {
86  dispatch_async(dispatch_get_main_queue(), run_handler);
87  }
88  } else {
89  if (completer) {
90  completer->CompleteEmpty();
91  }
92  }
93  }
94 }
95 
97  return false;
98 }
99 
101  int response_id,
102  std::unique_ptr<fml::Mapping> mapping) {
103  // Called from any thread.
104  // TODO(gaaclarke): This vestigal from the Android implementation, find a way
105  // to migrate this to PlatformMessageHandlerAndroid.
106 }
107 
109  // Called from any thread.
110  // TODO(gaaclarke): This vestigal from the Android implementation, find a way
111  // to migrate this to PlatformMessageHandlerAndroid.
112 }
113 
114 void PlatformMessageHandlerIos::SetMessageHandler(const std::string& channel,
116  NSObject<FlutterTaskQueue>* task_queue) {
117  FML_CHECK(platform_task_runner_->RunsTasksOnCurrentThread());
118  // Use `respondsToSelector` instead of `conformsToProtocol` to accomodate
119  // injecting your own `FlutterTaskQueue`. This is not a supported usage but
120  // not one worth breaking.
121  FML_CHECK(!task_queue || [task_queue respondsToSelector:@selector(dispatch:)]);
122  /// TODO(gaaclarke): This should be migrated to a lockfree datastructure.
123  std::lock_guard lock(message_handlers_mutex_);
124  message_handlers_.erase(channel);
125  if (handler) {
126  message_handlers_[channel] = {
127  .task_queue =
128  fml::scoped_nsprotocol(static_cast<NSObject<FlutterTaskQueueDispatch>*>(task_queue)),
129  .handler =
130  fml::ScopedBlock<FlutterBinaryMessageHandler>{
131  handler, fml::scoped_policy::OwnershipPolicy::kRetain},
132  };
133  }
134 }
135 } // namespace flutter
flutter::PlatformMessageHandlerIos::HandlerInfo::handler
fml::ScopedBlock< FlutterBinaryMessageHandler > handler
Definition: platform_message_handler_ios.h:37
flutter::PlatformMessageHandlerIos::InvokePlatformMessageResponseCallback
void InvokePlatformMessageResponseCallback(int response_id, std::unique_ptr< fml::Mapping > mapping) override
Definition: platform_message_handler_ios.mm:100
flutter::PlatformMessageHandlerIos::DoesHandlePlatformMessageOnPlatformThread
bool DoesHandlePlatformMessageOnPlatformThread() const override
Definition: platform_message_handler_ios.mm:96
flutter::ConvertMappingToNSData
NSData * ConvertMappingToNSData(fml::MallocMapping buffer)
Definition: buffer_conversions.mm:35
flutter::PlatformMessageHandlerIos::HandlerInfo
Definition: platform_message_handler_ios.h:35
flutter::PlatformMessageHandlerIos::HandlePlatformMessage
void HandlePlatformMessage(std::unique_ptr< PlatformMessage > message) override
Definition: platform_message_handler_ios.mm:44
flutter::PlatformMessageHandlerIos::InvokePlatformMessageEmptyResponseCallback
void InvokePlatformMessageEmptyResponseCallback(int response_id) override
Definition: platform_message_handler_ios.mm:108
FLTSerialTaskQueue::queue
dispatch_queue_t queue
Definition: platform_message_handler_ios.mm:17
flutter::PlatformMessageHandlerIos::HandlerInfo::task_queue
fml::scoped_nsprotocol< NSObject< FlutterTaskQueueDispatch > * > task_queue
Definition: platform_message_handler_ios.h:36
FlutterBinaryMessageHandler
void(^ FlutterBinaryMessageHandler)(NSData *_Nullable message, FlutterBinaryReply reply)
Definition: FlutterBinaryMessenger.h:30
flutter::ConvertNSDataToMappingPtr
std::unique_ptr< fml::Mapping > ConvertNSDataToMappingPtr(NSData *data)
Definition: buffer_conversions.mm:40
buffer_conversions.h
platform_message_counter
static FLUTTER_ASSERT_ARC uint64_t platform_message_counter
Definition: platform_message_handler_ios.mm:14
flutter
Definition: accessibility_bridge.h:28
platform_message_handler_ios.h
FlutterTaskQueueDispatch-p
Definition: flutter_task_queue_dispatch.h:16
flutter::PlatformMessageHandlerIos::SetMessageHandler
void SetMessageHandler(const std::string &channel, FlutterBinaryMessageHandler handler, NSObject< FlutterTaskQueue > *task_queue)
Definition: platform_message_handler_ios.mm:114
FLTSerialTaskQueue
Definition: platform_message_handler_ios.mm:16
FLUTTER_ASSERT_ARC
Definition: FlutterChannelKeyResponder.mm:13