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