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 5 #include "flutter/testing/test_dart_native_resolver.h" 6 7 #include <mutex> 8 #include <vector> 9 10 #include "flutter/fml/logging.h" 11 #include "flutter/fml/synchronization/thread_annotations.h" 12 #include "third_party/tonic/logging/dart_error.h" 13 #include "tonic/converter/dart_converter.h" 14 15 namespace flutter { 16 namespace testing { 17 18 TestDartNativeResolver::TestDartNativeResolver() = default; 19 20 TestDartNativeResolver::~TestDartNativeResolver() = default; 21 AddNativeCallback(std::string name,Dart_NativeFunction callback)22void TestDartNativeResolver::AddNativeCallback(std::string name, 23 Dart_NativeFunction callback) { 24 native_callbacks_[name] = callback; 25 } 26 ResolveCallback(std::string name) const27Dart_NativeFunction TestDartNativeResolver::ResolveCallback( 28 std::string name) const { 29 auto found = native_callbacks_.find(name); 30 if (found == native_callbacks_.end()) { 31 return nullptr; 32 } 33 34 return found->second; 35 } 36 37 static std::mutex gIsolateResolversMutex; 38 static std::map<Dart_Isolate, std::weak_ptr<TestDartNativeResolver>> 39 gIsolateResolvers FML_GUARDED_BY(gIsolateResolversMutex); 40 DartNativeEntryResolverCallback(Dart_Handle dart_name,int num_of_arguments,bool * auto_setup_scope)41Dart_NativeFunction TestDartNativeResolver::DartNativeEntryResolverCallback( 42 Dart_Handle dart_name, 43 int num_of_arguments, 44 bool* auto_setup_scope) { 45 auto name = tonic::StdStringFromDart(dart_name); 46 47 std::scoped_lock lock(gIsolateResolversMutex); 48 auto found = gIsolateResolvers.find(Dart_CurrentIsolate()); 49 if (found == gIsolateResolvers.end()) { 50 FML_LOG(ERROR) << "Could not resolve native method for :" << name; 51 return nullptr; 52 } 53 54 if (auto resolver = found->second.lock()) { 55 return resolver->ResolveCallback(std::move(name)); 56 } else { 57 gIsolateResolvers.erase(found); 58 } 59 60 FML_LOG(ERROR) << "Could not resolve native method for :" << name; 61 return nullptr; 62 } 63 DartNativeEntrySymbolCallback(Dart_NativeFunction function)64static const uint8_t* DartNativeEntrySymbolCallback( 65 Dart_NativeFunction function) { 66 return reinterpret_cast<const uint8_t*>("¯\\_(ツ)_/¯"); 67 } 68 SetNativeResolverForIsolate()69void TestDartNativeResolver::SetNativeResolverForIsolate() { 70 FML_CHECK(!Dart_IsError(Dart_RootLibrary())); 71 auto result = Dart_SetNativeResolver(Dart_RootLibrary(), 72 DartNativeEntryResolverCallback, 73 DartNativeEntrySymbolCallback); 74 FML_CHECK(!tonic::LogIfError(result)) 75 << "Could not set native resolver in test."; 76 77 std::scoped_lock lock(gIsolateResolversMutex); 78 gIsolateResolvers[Dart_CurrentIsolate()] = shared_from_this(); 79 80 std::vector<Dart_Isolate> isolates_with_dead_resolvers; 81 for (const auto& entry : gIsolateResolvers) { 82 if (!entry.second.lock()) { 83 isolates_with_dead_resolvers.push_back(entry.first); 84 } 85 } 86 87 for (const auto& dead_isolate : isolates_with_dead_resolvers) { 88 gIsolateResolvers.erase(dead_isolate); 89 } 90 } 91 92 } // namespace testing 93 } // namespace flutter 94