Skip to content

Commit

Permalink
Add flag to not publish the observatory port over mDNS (flutter#21883)
Browse files Browse the repository at this point in the history
  • Loading branch information
jmagman authored Oct 15, 2020
1 parent 40c226e commit 4494a83
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 62 deletions.
2 changes: 2 additions & 0 deletions common/settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ std::string Settings::ToString() const {
stream << "enable_dart_profiling: " << enable_dart_profiling << std::endl;
stream << "disable_dart_asserts: " << disable_dart_asserts << std::endl;
stream << "enable_observatory: " << enable_observatory << std::endl;
stream << "enable_observatory_publication: " << enable_observatory_publication
<< std::endl;
stream << "observatory_host: " << observatory_host << std::endl;
stream << "observatory_port: " << observatory_port << std::endl;
stream << "use_test_fonts: " << use_test_fonts << std::endl;
Expand Down
5 changes: 5 additions & 0 deletions common/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ struct Settings {
// Whether the Dart VM service should be enabled.
bool enable_observatory = false;

// Whether to publish the observatory URL over mDNS.
// On iOS 14 this prompts a local network permission dialog,
// which cannot be accepted or dismissed in a CI environment.
bool enable_observatory_publication = true;

// The IP address to which the Dart VM service is bound.
std::string observatory_host;

Expand Down
4 changes: 4 additions & 0 deletions shell/common/switches.cc
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) {
settings.enable_observatory =
!command_line.HasOption(FlagForSwitch(Switch::DisableObservatory));

// Enable mDNS Observatory Publication
settings.enable_observatory_publication = !command_line.HasOption(
FlagForSwitch(Switch::DisableObservatoryPublication));

// Set Observatory Host
if (command_line.HasOption(FlagForSwitch(Switch::DeviceObservatoryHost))) {
command_line.GetOptionValue(FlagForSwitch(Switch::DeviceObservatoryHost),
Expand Down
3 changes: 3 additions & 0 deletions shell/common/switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ DEF_SWITCH(DisableObservatory,
"disable-observatory",
"Disable the Dart Observatory. The observatory is never available "
"in release mode.")
DEF_SWITCH(DisableObservatoryPublication,
"disable-observatory-publication",
"Disable mDNS Dart Observatory publication.")
DEF_SWITCH(IPv6,
"ipv6",
"Bind to the IPv6 localhost address for the Dart Observatory. "
Expand Down
3 changes: 2 additions & 1 deletion shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@ - (BOOL)createShell:(NSString*)entrypoint
if (!_platformViewsController) {
_platformViewsController.reset(new flutter::FlutterPlatformViewsController());
}
_publisher.reset([[FlutterObservatoryPublisher alloc] init]);
_publisher.reset([[FlutterObservatoryPublisher alloc]
initWithEnableObservatoryPublication:settings.enable_observatory_publication]);
[self maybeSetupPlatformViewChannels];
_shell->GetIsGpuDisabledSyncSwitch()->SetSwitch(_isGpuDisabled ? true : false);
if (profilerEnabled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

@interface FlutterObservatoryPublisher : NSObject

- (instancetype)initWithEnableObservatoryPublication:(BOOL)enableObservatoryPublication
NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;

@property(nonatomic, readonly) NSURL* url;

@end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#if FLUTTER_RELEASE

@implementation FlutterObservatoryPublisher
- (instancetype)initWithEnableObservatoryPublication:(BOOL)enableObservatoryPublication {
return [super init];
}
@end

#else // FLUTTER_RELEASE
Expand Down Expand Up @@ -37,26 +40,23 @@ @implementation FlutterObservatoryPublisher
#include <net/if.h>

#include "flutter/fml/logging.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/fml/message_loop.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/fml/task_runner.h"
#include "flutter/runtime/dart_service_isolate.h"

@protocol FlutterObservatoryPublisherDelegate
- (instancetype)initWithOwner:(FlutterObservatoryPublisher*)owner;
- (void)publishServiceProtocolPort:(NSString*)uri;
- (void)publishServiceProtocolPort:(NSURL*)uri;
- (void)stopService;

@property(readonly) fml::scoped_nsobject<NSURL> url;
@end

@interface FlutterObservatoryPublisher ()
- (NSData*)createTxtData:(NSURL*)url;
+ (NSData*)createTxtData:(NSURL*)url;

@property(readonly) NSString* serviceName;
@property(readonly, class) NSString* serviceName;
@property(readonly) fml::scoped_nsobject<NSObject<FlutterObservatoryPublisherDelegate>> delegate;
@property(nonatomic, readwrite) NSURL* url;
@property(readonly) BOOL enableObservatoryPublication;

@end

Expand All @@ -68,31 +68,17 @@ @interface ObservatoryDNSServiceDelegate : NSObject <FlutterObservatoryPublisher
@end

@implementation ObservatoryDNSServiceDelegate {
fml::scoped_nsobject<FlutterObservatoryPublisher> _owner;
DNSServiceRef _dnsServiceRef;
}

@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 {
if (_dnsServiceRef) {
DNSServiceRefDeallocate(_dnsServiceRef);
_dnsServiceRef = NULL;
}
}

- (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]);

- (void)publishServiceProtocolPort:(NSURL*)url {
DNSServiceFlags flags = kDNSServiceFlagsDefault;
#if TARGET_IPHONE_SIMULATOR
// Simulator needs to use local loopback explicitly to work.
Expand All @@ -105,11 +91,11 @@ - (void)publishServiceProtocolPort:(NSString*)uri {
const char* domain = "local."; // default domain
uint16_t port = [[url port] unsignedShortValue];

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);
NSData* txtData = [FlutterObservatoryPublisher createTxtData:url];
int err = DNSServiceRegister(&_dnsServiceRef, flags, interfaceIndex,
FlutterObservatoryPublisher.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 with error " << err << ".";
Expand All @@ -122,8 +108,8 @@ - (void)publishServiceProtocolPort:(NSString*)uri {
<< "to the 'NSBonjourServices' key in your Info.plist for the Debug/"
<< "Profile configurations. "
<< "For more information, see "
// Update link to a specific header as needed.
<< "https://flutter.dev/docs/development/add-to-app/ios/project-setup";
<< "https://flutter.dev/docs/development/add-to-app/ios/"
"project-setup#local-network-privacy-permissions";
}
} else {
DNSServiceSetDispatchQueue(_dnsServiceRef, dispatch_get_main_queue());
Expand Down Expand Up @@ -162,34 +148,21 @@ static void DNSSD_API registrationCallback(DNSServiceRef sdRef,
@end

@implementation ObservatoryNSNetServiceDelegate {
fml::scoped_nsobject<FlutterObservatoryPublisher> _owner;
fml::scoped_nsobject<NSNetService> _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]);

NSNetService* netServiceTmp = [[NSNetService alloc] initWithDomain:@"local."
type:@"_dartobservatory._tcp."
name:_owner.get().serviceName
port:[[url port] intValue]];
[netServiceTmp setTXTRecordData:[_owner createTxtData:url.get()]];
- (void)publishServiceProtocolPort:(NSURL*)url {
NSNetService* netServiceTmp =
[[NSNetService alloc] initWithDomain:@"local."
type:@"_dartobservatory._tcp."
name:FlutterObservatoryPublisher.serviceName
port:[[url port] intValue]];
[netServiceTmp setTXTRecordData:[FlutterObservatoryPublisher createTxtData:url]];
_netService.reset(netServiceTmp);
[_netService.get() setDelegate:self];
[_netService.get() publish];
Expand All @@ -211,19 +184,16 @@ @implementation FlutterObservatoryPublisher {
std::unique_ptr<fml::WeakPtrFactory<FlutterObservatoryPublisher>> _weakFactory;
}

- (NSURL*)url {
return [_delegate.get().url autorelease];
}

- (instancetype)init {
- (instancetype)initWithEnableObservatoryPublication:(BOOL)enableObservatoryPublication {
self = [super init];
NSAssert(self, @"Super must not return null on init.");

if (@available(iOS 9.3, *)) {
_delegate.reset([[ObservatoryDNSServiceDelegate alloc] initWithOwner:self]);
_delegate.reset([[ObservatoryDNSServiceDelegate alloc] init]);
} else {
_delegate.reset([[ObservatoryNSNetServiceDelegate alloc] initWithOwner:self]);
_delegate.reset([[ObservatoryNSNetServiceDelegate alloc] init]);
}
_enableObservatoryPublication = enableObservatoryPublication;
_weakFactory = std::make_unique<fml::WeakPtrFactory<FlutterObservatoryPublisher>>(self);

fml::MessageLoop::EnsureInitializedForCurrentThread();
Expand All @@ -233,9 +203,15 @@ - (instancetype)init {
runner = fml::MessageLoop::GetCurrent().GetTaskRunner()](const std::string& uri) {
if (!uri.empty()) {
runner->PostTask([weak, uri]() {
// uri comes in as something like 'http://127.0.0.1:XXXXX/' where XXXXX is the port
// number.
if (weak) {
[[weak.get() delegate]
publishServiceProtocolPort:[NSString stringWithUTF8String:uri.c_str()]];
NSURL* url =
[[NSURL alloc] initWithString:[NSString stringWithUTF8String:uri.c_str()]];
weak.get().url = url;
if (weak.get().enableObservatoryPublication) {
[[weak.get() delegate] publishServiceProtocolPort:url];
}
}
});
}
Expand All @@ -244,11 +220,11 @@ - (instancetype)init {
return self;
}

- (NSString*)serviceName {
+ (NSString*)serviceName {
return NSBundle.mainBundle.bundleIdentifier;
}

- (NSData*)createTxtData:(NSURL*)url {
+ (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])];
Expand All @@ -261,6 +237,7 @@ - (NSData*)createTxtData:(NSURL*)url {

- (void)dealloc {
[_delegate stopService];
[_url release];

flutter::DartServiceIsolate::RemoveServerStatusCallback(std::move(_callbackHandle));
[super dealloc];
Expand Down

0 comments on commit 4494a83

Please sign in to comment.