diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index f80943a2418..d9b30258d49 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -18,7 +18,6 @@ FILE: ../../../flutter/assets/directory_asset_bundle.h FILE: ../../../flutter/benchmarking/benchmarking.cc FILE: ../../../flutter/benchmarking/benchmarking.h FILE: ../../../flutter/common/exported_symbols.sym -FILE: ../../../flutter/common/runtime.h FILE: ../../../flutter/common/settings.cc FILE: ../../../flutter/common/settings.h FILE: ../../../flutter/common/task_runners.cc diff --git a/common/BUILD.gn b/common/BUILD.gn index 69095bbcd45..b9b05073501 100644 --- a/common/BUILD.gn +++ b/common/BUILD.gn @@ -10,7 +10,6 @@ config("flutter_config") { source_set("common") { sources = [ - "runtime.h", "settings.cc", "settings.h", "task_runners.cc", diff --git a/common/config.gni b/common/config.gni index cfc4b15936d..1b7d18f670c 100644 --- a/common/config.gni +++ b/common/config.gni @@ -43,13 +43,23 @@ feature_defines_list = [ ] if (flutter_runtime_mode == "debug") { - feature_defines_list += [ "FLUTTER_RUNTIME_MODE=1" ] + feature_defines_list += [ + "FLUTTER_RUNTIME_MODE=1", + "FLUTTER_JIT_RUNTIME=1", + ] } else if (flutter_runtime_mode == "profile") { feature_defines_list += [ "FLUTTER_RUNTIME_MODE=2" ] } else if (flutter_runtime_mode == "release") { - feature_defines_list += [ "FLUTTER_RUNTIME_MODE=3" ] + feature_defines_list += [ + "FLUTTER_RUNTIME_MODE=3", + "FLUTTER_RELEASE=1", + ] } else if (flutter_runtime_mode == "jit_release") { - feature_defines_list += [ "FLUTTER_RUNTIME_MODE=4" ] + feature_defines_list += [ + "FLUTTER_RUNTIME_MODE=4", + "FLUTTER_RELEASE=1", + "FLUTTER_JIT_RUNTIME=1", + ] } else { feature_defines_list += [ "FLUTTER_RUNTIME_MODE=0" ] } diff --git a/common/runtime.h b/common/runtime.h deleted file mode 100644 index 096ffbd86f8..00000000000 --- a/common/runtime.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 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. - -namespace flutter { - -#define FLUTTER_JIT_RUNTIME \ - ((FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG) || \ - (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_JIT_RELEASE)) - -#define FLUTTER_RELEASE \ - ((FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE) || \ - (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_JIT_RELEASE)) - -} // namespace flutter diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc index d047b5340c3..a2831f83e3f 100644 --- a/flow/raster_cache.cc +++ b/flow/raster_cache.cc @@ -6,7 +6,6 @@ #include -#include "flutter/common/runtime.h" #include "flutter/flow/layers/layer.h" #include "flutter/flow/paint_utils.h" #include "flutter/fml/logging.h" diff --git a/runtime/dart_snapshot.cc b/runtime/dart_snapshot.cc index a5df79bb136..0a19b3984ca 100644 --- a/runtime/dart_snapshot.cc +++ b/runtime/dart_snapshot.cc @@ -6,7 +6,6 @@ #include -#include "flutter/common/runtime.h" #include "flutter/fml/native_library.h" #include "flutter/fml/paths.h" #include "flutter/fml/trace_event.h" diff --git a/runtime/dart_vm.cc b/runtime/dart_vm.cc index de9d08e3b3b..623242bdff6 100644 --- a/runtime/dart_vm.cc +++ b/runtime/dart_vm.cc @@ -9,7 +9,6 @@ #include #include -#include "flutter/common/runtime.h" #include "flutter/common/settings.h" #include "flutter/fml/compiler_specific.h" #include "flutter/fml/file.h" diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 060957a74de..bbd4320d42f 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -10,7 +10,6 @@ #include #include "flutter/assets/directory_asset_bundle.h" -#include "flutter/common/runtime.h" #include "flutter/fml/file.h" #include "flutter/fml/icu_util.h" #include "flutter/fml/log_settings.h" diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 840025e9965..0146619cce4 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -9,7 +9,6 @@ #include #include -#include "flutter/common/runtime.h" #include "flutter/flow/layers/layer_tree.h" #include "flutter/flow/layers/transform_layer.h" #include "flutter/fml/command_line.h" diff --git a/shell/common/switches.cc b/shell/common/switches.cc index 6d31cb99ff7..df2e51d280c 100644 --- a/shell/common/switches.cc +++ b/shell/common/switches.cc @@ -9,7 +9,6 @@ #include #include -#include "flutter/common/runtime.h" #include "flutter/fml/native_library.h" #include "flutter/fml/paths.h" #include "flutter/fml/size.h" diff --git a/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm b/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm index 147ef0d1171..5af43f0cadf 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm @@ -4,18 +4,38 @@ #define FML_USED_ON_EMBEDDER -#import - -// NSNetService works fine on physical devices, but doesn't expose the services to regular mDNS -// queries on the Simulator. We can work around this by using the lower level C API, but that's -// only available from iOS 9.3+/macOS 10.11.4+. -#if TARGET_IPHONE_SIMULATOR -#include // nogncheck -#include // nogncheck -#endif // TARGET_IPHONE_SIMULATOR - #import "FlutterObservatoryPublisher.h" +#if FLUTTER_RELEASE + +@implementation FlutterObservatoryPublisher +@end + +#else // FLUTTER_RELEASE + +#import +// NSNetService works fine on physical devices before iOS 13.2. +// However, it doesn't expose the services to regular mDNS +// queries on the Simulator or on iOS 13.2+ devices. +// +// When debugging issues with this implementation, the following is helpful: +// +// 1) Running `dns-sd -Z _dartobservatory`. This is a built-in macOS tool that +// can find advertized observatories using this method. If dns-sd can't find +// it, then the observatory is not getting advertized over any network +// interface that the host machine has access to. +// 2) The Python zeroconf package. The dns-sd tool can sometimes see things +// that aren't advertizing over a network interface - for example, simulators +// using NSNetService has been observed using dns-sd, but doesn't show up in +// the Python package (which is a high quality socket based implementation). +// If that happens, this code should be tweaked such that it shows up in both +// dns-sd's output and Python zeroconf's detection. +// 3) The Dart multicast_dns package, which is what Flutter uses to find the +// port and auth code. If the advertizement shows up in dns-sd and Python +// zeroconf but not multicast_dns, then it is a bug in multicast_dns. +#include +#include + #include "flutter/fml/logging.h" #include "flutter/fml/make_copyable.h" #include "flutter/fml/memory/weak_ptr.h" @@ -24,136 +44,80 @@ #include "flutter/fml/task_runner.h" #include "flutter/runtime/dart_service_isolate.h" -#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE || \ - FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DYNAMIC_RELEASE +@protocol FlutterObservatoryPublisherDelegate +- (instancetype)initWithOwner:(FlutterObservatoryPublisher*)owner; +- (void)publishServiceProtocolPort:(NSString*)uri; +- (void)stopService; -@implementation FlutterObservatoryPublisher { -} - -#else - -@interface FlutterObservatoryPublisher () +@property(readonly) fml::scoped_nsobject url; @end -@implementation FlutterObservatoryPublisher { - fml::scoped_nsobject _url; -#if TARGET_IPHONE_SIMULATOR +@interface FlutterObservatoryPublisher () +- (NSData*)createTxtData:(NSURL*)url; + +@property(readonly) NSString* serviceName; +@property(readonly) fml::scoped_nsobject> delegate; + +@end + +@interface ObservatoryNSNetServiceDelegate + : NSObject +@end + +@interface ObservatoryDNSServiceDelegate : NSObject +@end + +@implementation ObservatoryDNSServiceDelegate { + fml::scoped_nsobject _owner; DNSServiceRef _dnsServiceRef; -#else // TARGET_IPHONE_SIMULATOR - fml::scoped_nsobject _netService; -#endif // TARGET_IPHONE_SIMULATOR - - flutter::DartServiceIsolate::CallbackHandle _callbackHandle; - std::unique_ptr> _weakFactory; } -- (NSURL*)url { - return _url.get(); -} +@synthesize url; -- (instancetype)init { +- (instancetype)initWithOwner:(FlutterObservatoryPublisher*)owner { self = [super init]; NSAssert(self, @"Super must not return null on init."); - - _weakFactory = std::make_unique>(self); - - fml::MessageLoop::EnsureInitializedForCurrentThread(); - - _callbackHandle = flutter::DartServiceIsolate::AddServerStatusCallback( - [weak = _weakFactory->GetWeakPtr(), - runner = fml::MessageLoop::GetCurrent().GetTaskRunner()](const std::string& uri) { - runner->PostTask([weak, uri]() { - if (weak) { - [weak.get() publishServiceProtocolPort:std::move(uri)]; - } - }); - }); - + _owner.reset([owner retain]); return self; } - (void)stopService { -#if TARGET_IPHONE_SIMULATOR if (_dnsServiceRef) { DNSServiceRefDeallocate(_dnsServiceRef); _dnsServiceRef = NULL; } -#else // TARGET_IPHONE_SIMULATOR - [_netService.get() stop]; - [_netService.get() setDelegate:nil]; -#endif // TARGET_IPHONE_SIMULATOR } -- (void)dealloc { - [self stopService]; - - flutter::DartServiceIsolate::RemoveServerStatusCallback(std::move(_callbackHandle)); - [super dealloc]; -} - -- (void)publishServiceProtocolPort:(std::string)uri { - [self stopService]; - if (uri.empty()) { - return; - } +- (void)publishServiceProtocolPort:(NSString*)uri { // uri comes in as something like 'http://127.0.0.1:XXXXX/' where XXXXX is the port // number. - _url.reset([[NSURL alloc] initWithString:[NSString stringWithUTF8String:uri.c_str()]]); + url.reset([[[NSURL alloc] initWithString:uri] retain]); - NSString* serviceName = - [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]; - - // Check to see if there's an authentication code. If there is, we'll provide - // it as a txt record so flutter tools can establish a connection. - auto path = std::string{[[_url path] UTF8String]}; - if (!path.empty()) { - // Remove leading "/" - path = path.substr(1); - } - NSData* pathData = [[[NSData alloc] initWithBytes:path.c_str() length:path.length()] autorelease]; - NSDictionary* txtDict = @{ - @"authCode" : pathData, - }; - NSData* txtData = [NSNetService dataFromTXTRecordDictionary:txtDict]; - -#if TARGET_IPHONE_SIMULATOR DNSServiceFlags flags = kDNSServiceFlagsDefault; +#if TARGET_IPHONE_SIMULATOR + // Simulator needs to use local loopback explicitly to work. uint32_t interfaceIndex = if_nametoindex("lo0"); +#else // TARGET_IPHONE_SIMULATOR + // Physical devices need to request all interfaces. + uint32_t interfaceIndex = 0; +#endif // TARGET_IPHONE_SIMULATOR const char* registrationType = "_dartobservatory._tcp"; const char* domain = "local."; // default domain - uint16_t port = [[_url port] intValue]; + uint16_t port = [[url port] unsignedShortValue]; - int err = DNSServiceRegister(&_dnsServiceRef, flags, interfaceIndex, [serviceName UTF8String], - registrationType, domain, NULL, htons(port), txtData.length, - txtData.bytes, registrationCallback, NULL); + NSData* txtData = [_owner createTxtData:url.get()]; + int err = + DNSServiceRegister(&_dnsServiceRef, flags, interfaceIndex, + [_owner.get().serviceName UTF8String], registrationType, domain, NULL, + htons(port), txtData.length, txtData.bytes, registrationCallback, NULL); if (err != 0) { FML_LOG(ERROR) << "Failed to register observatory port with mDNS."; } else { DNSServiceSetDispatchQueue(_dnsServiceRef, dispatch_get_main_queue()); } -#else // TARGET_IPHONE_SIMULATOR - NSNetService* netServiceTmp = [[NSNetService alloc] initWithDomain:@"local." - type:@"_dartobservatory._tcp." - name:serviceName - port:[[_url port] intValue]]; - [netServiceTmp setTXTRecordData:txtData]; - _netService.reset(netServiceTmp); - [_netService.get() setDelegate:self]; - [_netService.get() publish]; -#endif // TARGET_IPHONE_SIMULATOR } -- (void)netServiceDidPublish:(NSNetService*)sender { - FML_DLOG(INFO) << "FlutterObservatoryPublisher is ready!"; -} - -- (void)netService:(NSNetService*)sender didNotPublish:(NSDictionary*)errorDict { - FML_LOG(ERROR) << "Could not register as server for FlutterObservatoryPublisher. Check your " - "network settings and relaunch the application."; -} - -#if TARGET_IPHONE_SIMULATOR static void DNSSD_API registrationCallback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, @@ -168,9 +132,113 @@ static void DNSSD_API registrationCallback(DNSServiceRef sdRef, "network settings and relaunch the application."; } } -#endif // TARGET_IPHONE_SIMULATOR - -#endif // FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE && FLUTTER_RUNTIME_MODE != - // FLUTTER_RUNTIME_MODE_DYNAMIC_RELEASE @end + +@implementation ObservatoryNSNetServiceDelegate { + fml::scoped_nsobject _owner; + fml::scoped_nsobject _netService; +} + +@synthesize url; + +- (instancetype)initWithOwner:(FlutterObservatoryPublisher*)owner { + self = [super init]; + NSAssert(self, @"Super must not return null on init."); + _owner.reset([owner retain]); + return self; +} + +- (void)stopService { + [_netService.get() stop]; + [_netService.get() setDelegate:nil]; +} + +- (void)publishServiceProtocolPort:(NSString*)uri { + // uri comes in as something like 'http://127.0.0.1:XXXXX/' where XXXXX is the port + // number. + url.reset([[[NSURL alloc] initWithString:uri] retain]); + + NSNetService* netServiceTmp = [[NSNetService alloc] initWithDomain:@"local." + type:@"_dartobservatory._tcp." + name:_owner.get().serviceName + port:[[url port] intValue]]; + [netServiceTmp setTXTRecordData:[_owner createTxtData:url.get()]]; + _netService.reset(netServiceTmp); + [_netService.get() setDelegate:self]; + [_netService.get() publish]; +} + +- (void)netServiceDidPublish:(NSNetService*)sender { + FML_DLOG(INFO) << "FlutterObservatoryPublisher is ready!"; +} + +- (void)netService:(NSNetService*)sender didNotPublish:(NSDictionary*)errorDict { + FML_LOG(ERROR) << "Could not register as server for FlutterObservatoryPublisher. Check your " + "network settings and relaunch the application."; +} + +@end + +@implementation FlutterObservatoryPublisher { + flutter::DartServiceIsolate::CallbackHandle _callbackHandle; + std::unique_ptr> _weakFactory; +} + +- (NSURL*)url { + return [_delegate.get().url autorelease]; +} + +- (instancetype)init { + self = [super init]; + NSAssert(self, @"Super must not return null on init."); + + if (@available(iOS 9.3, *)) { + _delegate.reset([[ObservatoryDNSServiceDelegate alloc] initWithOwner:self]); + } else { + _delegate.reset([[ObservatoryNSNetServiceDelegate alloc] initWithOwner:self]); + } + _weakFactory = std::make_unique>(self); + + fml::MessageLoop::EnsureInitializedForCurrentThread(); + + _callbackHandle = flutter::DartServiceIsolate::AddServerStatusCallback( + [weak = _weakFactory->GetWeakPtr(), + runner = fml::MessageLoop::GetCurrent().GetTaskRunner()](const std::string& uri) { + if (!uri.empty()) { + runner->PostTask([weak, uri]() { + if (weak) { + [[weak.get() delegate] + publishServiceProtocolPort:[NSString stringWithUTF8String:uri.c_str()]]; + } + }); + } + }); + + return self; +} + +- (NSString*)serviceName { + return NSBundle.mainBundle.bundleIdentifier; +} + +- (NSData*)createTxtData:(NSURL*)url { + // Check to see if there's an authentication code. If there is, we'll provide + // it as a txt record so flutter tools can establish a connection. + NSString* path = [[url path] substringFromIndex:MIN(1, [[url path] length])]; + NSData* pathData = [path dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary* txtDict = @{ + @"authCode" : pathData, + }; + return [NSNetService dataFromTXTRecordDictionary:txtDict]; +} + +- (void)dealloc { + [_delegate stopService]; + + flutter::DartServiceIsolate::RemoveServerStatusCallback(std::move(_callbackHandle)); + [super dealloc]; +} +@end + +#endif // FLUTTER_RELEASE