-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Add observatory Bonjour service to built iOS Info.plist bundle #64988
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| } | ||
| }); | ||
|
|
||
| if (foundProjectName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved these failures to where they are detected, instead of the end of the test.
| EchoError "========================================================================" | ||
| exit -1;; | ||
| esac | ||
| retval="${build_mode}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works, but is there a more idiomatic way to return a string from a bash function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| local bitcode_flag="" | ||
| if [[ $ENABLE_BITCODE == "YES" ]]; then | ||
| if [[ "$ENABLE_BITCODE" == "YES" ]]; then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated to this change, but I noticed the quotes were missing.
| "observatory_bonjour_service") | ||
| AddObservatoryBonjourService ;; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a new xcode_backend entrypoint. At the least, we can tell add-to-app customers to call this in a new build script phase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I would rather not add this for add-to-app.
Those customers should be sophisticated enough to read an error log and know which plist(s) to update.
This is likely to get things wrong for some customer and we'll get requests to change it or a specific CI system or wahtever.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about .frameworks? Will those cases never work unless users type in something manually in their real checked-in info.plist?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those customers should be sophisticated enough to read an error log and know which plist(s) to update.
How would they see an error message from the VM if they can't attach? Edit: oh right, they would see it in Xcode.
It definitely requires some Xcode-foo to know you can edit the Info.plist per configuration. You need to know how to expand the build setting, which people seem confused by.

Or they can do something like Info-${CONFIGURATION}.plist
We'll have to update the docs, for sure.
Will those cases never work unless users type in something manually in their real checked-in info.plist?
Right, they would need to edit their plist.
At least in the CocoaPods case they can add the build phase I suggested in #63893 (comment)
|
Why do this in bash and not in dart? |
| # Don't override the local network description the Flutter app developer specified (uncommon). | ||
| # This text will appear below the "Your app would like to find and connect to devices on your local network" permissions popup. | ||
| if ! plutil -extract NSLocalNetworkUsageDescription xml1 -o - "${built_products_plist}"; then | ||
| RunCommand plutil -insert NSLocalNetworkUsageDescription -string "Allow Flutter tools on your computer to connect and debug your Flutter application. This prompt will not appear on release builds." "${built_products_plist}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check out the screenshot in the description. We can probably remove the second "Flutter". Maybe also "connect"?
Allow Flutter tools on your computer to debug your application. This prompt will not appear on release builds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the second connect. I'd maybe leave it. Otherwise people might think I'm just flutter running and then maybe taking a screenshot or something. I'm not technically "debugging", why doesn't it work?
On the second Flutter, don't have a strong opinion. To be specific, we're not really debugging their (objective-c) application. This is strictly dart/observatory/flutter stuff.
| await flutter('clean'); | ||
| }); | ||
|
|
||
| section('Validate debug contents'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section is new.
| ), | ||
| ], | ||
| canFail: true, | ||
| ) == 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't really care what it says since that seems like a moving target, just that it exists.
@jonahwilliams We don't do any of the post-assemble app bundling in dart (embedding frameworks, codesigning, thinning). Are you suggesting a new |
6a4cbd0 to
612818e
Compare
| @@ -0,0 +1,177 @@ | |||
| // Copyright 2014 The Flutter Authors. All rights reserved. | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was moved from general.shard, it's not a hermetic test.
| await expectXcodeBackendFails(unknownFlutterBuildMode); | ||
| await expectXcodeBackendFails(localEngineDebugBuildModeRelease); | ||
| await expectXcodeBackendFails(localEngineProfileBuildeModeRelease); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were disabled in #35707, but as an integration test they should get a precache, so I fixed them up and reenabled.
| await expectXcodeBackendFails(localEngineProfileBuildeModeRelease); | ||
| }); | ||
|
|
||
| test('Xcode backend warns archiving a non-release build.', () async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is new, the behavior changed #57688 but the installWithoutRelease test was being skipped so it didn't fail.
| if [[ "${build_mode}" == "release" ]]; then | ||
| return | ||
| fi | ||
| local built_products_plist="${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be misreading this a bit, isn't this ultimately the same plist as https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/build_system/targets/ios.dart#L341 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not the same file, that's the project's ios/Runner/Info.plist (build setting INFOPLIST_FILE), and that's checked into source code, and where the docs tell users to update some fields before they submit to the app store.
This PR is editing the Xcode-generated Info.plist that gets embedded into the Runner.app.
After Xcode compiles everything and it embeds resources (storyboards, images, etc), it creates a Runner.app/Info.plist, which is a combination what's in the user's Info.plist in Xcode, plus a bunch of other Xcode-generated keys and metadata

By editing this final generated Info.plist, we don't need to update the user's checked in Info.plist, update the template, or have a complicated migration where we set different Info.plists depending on configuration, which would cause flavor-users a bunch of pain. We know the user needs this service in debug and profile when copied to the device, and it also means it won't slip into the release version that gets submitted to the App Store.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, looking again, https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/build_system/targets/ios.dart#L341 is a different third Info.plist. It's the one that gets embedded in the App.framework.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it matter which Plist these permissions are added to, or could it be done to the flutter framework plist itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It needs to be on the app bundle, so Runner.app/Info.plist. A framework can't set app-level permission requests or entitlements. Otherwise this problem would be a whole lot simpler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
understood.
|
For the add to app case, can't we just log an appropriate error with instructions on how to update the plist in FlutterObservatoryPublisher.mm if the returncode is kDnsServiceErr_NoAuth? |
xster
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Though I'd like to figure out a workaround plan for add-to-app.
|
|
||
| Future<bool> localNetworkUsageFound(String appBundlePath) async => | ||
| await exec( | ||
| 'plutil', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh lol, TIL. So there's an actual built-in tool to turn plists to things like json so it can be more easily consumed by things like dart?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, it's being used for other plist parsing, see
| executable, '-convert', 'json', '-o', '-', normalizedPlistPath, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh lol, sad
| } | ||
|
|
||
| ParseFlutterBuildMode() { | ||
| # Use FLUTTER_BUILD_MODE if it's set, otherwise use the Xcode build configuration name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh cool, is this a whole new feature (that confused matt forever) bundled here? :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been in there for .. a while now.
Basically, we try to use the $CONFIGURATION because that's probably what the user wants if they're running from Xcode (in particular, we don't want instruments tests from debug mode Dart, and we set up instruments to run in a "PROFILE" configuration by default).
But we do let a user override it if necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this logic and error messaging was just moved into a common function so I could use it in two places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should go have Matt write this down in https://flutter.dev/docs/deployment/flavors :D
| EchoError "ERROR: Unknown FLUTTER_BUILD_MODE: ${build_mode}." | ||
| EchoError "Valid values are 'Debug', 'Profile', or 'Release' (case insensitive)." | ||
| EchoError "This is controlled by the FLUTTER_BUILD_MODE environment variable." | ||
| EchoError "If that is not set, the CONFIGURATION environment variable is used." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also add a common name (as seen in the xcode gui) for this? People might not know what the CONFIGURATION setting maps to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was all just moved.
| EchoError "" | ||
| EchoError "You can fix this by either adding an appropriately named build" | ||
| EchoError "configuration, or adding an appropriate value for FLUTTER_BUILD_MODE to the" | ||
| EchoError ".xcconfig file for the current build configuration (${CONFIGURATION})." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also add a gui description if possible (I assume people can go into the build settings tab, add a new row, expand the configurations and type in something in xcode).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CONFIGURATION is an env var provided by Xcode. It's available in the build settings if you dig into them. There's no special GUI name.
By default anXcode project has Debug and Release. We added profile to our default template when this was added.
| RunCommand codesign --force --verbose --sign "${EXPANDED_CODE_SIGN_IDENTITY}" -- "${xcode_frameworks_dir}/Flutter.framework/Flutter" | ||
| fi | ||
|
|
||
| AddObservatoryBonjourService |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come this works here and not for add-to-app? Because our template build phase puts xcode_backend.sh later than where cocoapods can help us put it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because our template build phase puts xcode_backend.sh later than where cocoapods can help us put it?
Bingo. I put some more details in #63893 (comment).
|
|
||
| # Don't override the local network description the Flutter app developer specified (uncommon). | ||
| # This text will appear below the "Your app would like to find and connect to devices on your local network" permissions popup. | ||
| if ! plutil -extract NSLocalNetworkUsageDescription xml1 -o - "${built_products_plist}"; then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Display an error message otherwise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the developer sets their own NSLocalNetworkUsageDescription because their app is doing their own local networking we don't override it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's ok. I just meant if that's the case, we should print something in the console to indicate that you'll get a popup in debug and we can't set the message in it but it's for flutter tools to connect.
| # Don't override the local network description the Flutter app developer specified (uncommon). | ||
| # This text will appear below the "Your app would like to find and connect to devices on your local network" permissions popup. | ||
| if ! plutil -extract NSLocalNetworkUsageDescription xml1 -o - "${built_products_plist}"; then | ||
| RunCommand plutil -insert NSLocalNetworkUsageDescription -string "Allow Flutter tools on your computer to connect and debug your Flutter application. This prompt will not appear on release builds." "${built_products_plist}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the second connect. I'd maybe leave it. Otherwise people might think I'm just flutter running and then maybe taking a screenshot or something. I'm not technically "debugging", why doesn't it work?
On the second Flutter, don't have a strong opinion. To be specific, we're not really debugging their (objective-c) application. This is strictly dart/observatory/flutter stuff.
| "observatory_bonjour_service") | ||
| AddObservatoryBonjourService ;; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about .frameworks? Will those cases never work unless users type in something manually in their real checked-in info.plist?
dnfield
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The more I think about this, the more I'm opposed to adding more "API surface" to our dirty little bash script :)
Is there some way we could avoid having a new "method" on there that we tell people to call?
That's definitely a good idea. |
If we decide not to allow the workaround build script I suggested at the end of #63893 (comment), we can remove this "method" but still keep the |
How is this different from us having a bunch of methods in our podhelper.rb we ask people to call? I think having dart files xcode phases calling into would be cooler but I don't know if this is particularly bad. Maybe your comment is just saying inline it into the existing function body which is fine too. |
gaaclarke
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too many cooks in the kitchen so I just gave it a quick glance through with a couple of notes. I raised a question about a tweak to this approach that might be better suited for add-to-app here: #63893 (comment)
dev/devicelab/lib/framework/ios.dart
Outdated
| return !emptyBitcodeMarkerFound; | ||
| } | ||
|
|
||
| Future<bool> bonjourServiceFound(String appBundlePath) async => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we call this dartObservatoryBonjourServiceFound? or take in _dartobservatory._tcp as a parameter? From the callsite it just looks like we are throwing if any bonjour service is found.
| if (await bonjourServiceFound(outputAppPath)) { | ||
| throw TaskResult.failure('Release bundle has unexpected NSBonjourServices'); | ||
| } | ||
| if (await localNetworkUsageFound(outputAppPath)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this throwing an error if a user legitimately has their own mdns service for their release build? We want to make sure to support that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an integration test, it doesn't have any mDNS service set. The xcode_build script handles that case, it detects if the NSBounjourServices key is set, and adds it to the list.
jonahwilliams
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Good that we have test coverage for the new stuff, even though it is bash I think that should help substantially with the maintainability.
@dnfield I kept the endpoint for the integration tests but renamed to |
dnfield
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
flutter#64988)" (flutter#65109) This reverts commit 4fde217.
Description
Add
NSBonjourServices_dartobservatory._tcpandNSLocalNetworkUsageDescriptionto debug and profileInfo.plistin the produced, bundled.app(not the user-facing Info.plist created in the template and included in Xcode).This prompts the "Your app would like to find and connect to devices on your local network" permission popup, which is required to unblock the observatory publisher on iOS 14.
NSLocalNetworkUsageDescriptionis underneath:Note: this does not add the keys for add-to-app host apps, so they still have the issue of blocking the observatory publisher.
Related Issues
Fixes #60634
Fixes #35707.
Related to conversation at #63893, but that is for add-to-app.
Tests
Updated
ios_content_validation_testto validate Release does not have the keys, but Debug does.Kudos
Thanks to @gaaclarke for suggesting to just add the keys in the generated bundle Info.plist, and not the one that's created in the template. That avoided a huge migration headache.
Checklist
///).flutter analyze --flutter-repo) does not report any problems on my PR.Breaking Change