-
Notifications
You must be signed in to change notification settings - Fork 29.7k
[Android] Implement setting content sensitivity on Android #158473
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
|
Looking for feedback on the approach presented in this PR and the open questions I have before writing tests. Looks like there are some linting issues, but this should run, though I've been testing with the non-monorepo engine up until this point. |
justinmc
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.
Drive-by review here. I still want to look more closely at the SensitiveContent widget and maybe play with it locally. At a high level though, this approach seems good and it looks like things worked as we thought they would. I'll post back tomorrow.
One thing I remember from your Dash Forum session was we thought we would need to use FFI to communicate with the engine. Is that requirement out of date now?
Oh and I struggled in getting one of my engine/framework projects to run in the monorepo when I got back from break. I updated some docs in the process, maybe check that or feel free to reach out if you need to try it in the monorepo and get stuck. #161184
.../shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
Outdated
Show resolved
Hide resolved
engine/src/flutter/shell/platform/android/io/flutter/plugin/view/SensitiveContentPlugin.java
Outdated
Show resolved
Hide resolved
|
"so we will investigate using JNIgen in the future" I believe we should say that we do not plan to release the feature without evaluating if frame drops can occur. |
|
"Implements setting content sensitivity on Android via a new plugin called SensitiveContent" Most flutter users would view plugin in this context as something that should probably be in flutter/packages. |
|
In the pr description consider trying to more cleanly describe what is work that needs to happen in this pr but has intentionally not happened. What work is future work but still required before we ship the feature and what is work that is future work that is unplanned. |
reidbaker
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.
Reviewed android code will do a different pass on dart code later.
| * see {@link android.view.View#findViewById}. | ||
| */ | ||
| public static final int FLUTTER_VIEW_ID = View.generateViewId(); | ||
| public static final int FLUTTER_VIEW_ID = 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.
I believe this is a dangerous implementation to change.
From the docs on View.generateViewId()
Generate a value suitable for use in [setId(int)](https://developer.android.com/reference/android/view/View#setId(int)). This value will not collide with ID values generated at build time by aapt for R.id.```
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.
Agreed that this is dangerous; I didn't realize the implications went beyond debugging before.
As of now, I changed my approach to identifying the View we want to set the content sensitivity of by initializing SensitiveContentPlugins with the ID of the View that is created by a FlutterActivity or FlutterFragment. My understanding is that every FlutterActivity or FlutterFragment will (via the FlutterActivityAndFragmentDelegate code I added) provide a SensitiveContentPlugin to handle the View created for each FlutterActivity and FlutterFragment created.
This should cover regular Flutter apps as well as add-to-app use cases where a FlutterActivity or FlutterFragment is used. The only case I think left uncovered is adding a FlutterView to a native app, but it's my understanding that we are not required to handle FlutterActivityAndFragmentDelegate plumbing there (see https://docs.flutter.dev/add-to-app/android/add-flutter-view#general-approach).
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.
@reidbaker and I spoke about my new approach offline and agree it should work. In summary, we should be able to assume that each FlutterActivity and FlutterFragment should map to one FlutterView in all cases (minus the FlutterView add-to-app case) and so one SensitiveContentPlugin per FlutterActivity or FlutterFragment should be safe. @justinmc this actually will allow us to remove the singleton approach because the SensitiveContent widget no longer needs to be aware of the FlutterView that it is setting the content sensitivity of.
The only exception to that is when one FlutterEngine is used for multiple FlutterActivitys or FlutterFragments. https://docs.flutter.dev/add-to-app/android/add-flutter-screen suggests that this approach is at least possible when using a pre-warmed FlutterEngine. I think this can be fixed by not making FLUTTER_VIEW_ID static and final so that each FlutterView created gets a different ID. I will now work on making this fix, removing the singleton approach, and polishing this PR for a full review.
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.
Ok small misunderstanding...we still need the singleton approach because we need to be able to track all SensitiveContent widgets in a Flutter app.
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 need to track all sensitive content widgets in a flutter app for a flutter view. It seems to me like that singleton can/should be in dart but the android side could not be a singleton.
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.
Ah it would have been cool to get rid of the Dart singleton but that sounds good anyway.
engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java
Outdated
Show resolved
Hide resolved
.../shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
Outdated
Show resolved
Hide resolved
engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java
Outdated
Show resolved
Hide resolved
engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java
Outdated
Show resolved
Hide resolved
engine/src/flutter/shell/platform/android/io/flutter/plugin/view/SensitiveContentPlugin.java
Outdated
Show resolved
Hide resolved
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.
Lots of nits and questions here but I think the overall approach is sound. The biggest architectural thing is possibly finding a way to avoid the SensitiveContentSetting singleton (commented below), but that is not a blocker.
I'm not sure about hardcoding the view ids, hopefully someone who knows more about Android and add-to-app scenarios will know the answer. If not, maybe it's something we could expose to the framework via MediaQuery or something like that.
About autoSensitive, how do you see the distinction between Android's CONTENT_SENSITIVITY_AUTO and the feature where we automatically add a SensitiveContent widget to password fields? Maybe we should allow the user to set CONTENT_SENSITIVITY_AUTO if they really want to. Or will that literally have no effect?
Edit: I posted this review without seeing Reid's review from a few hours earlier (thanks GitHub), so sorry if there is redundancy.
| /// By default, this is 0. On Android, this is the the ID of the native | ||
| /// `View` that is created by the default `FlutterActivity`, which is used by | ||
| /// default in Flutter Android apps. |
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.
When might a user want to change this to something other than 0?
| /// Widget to set the [ContentSensitivity] level of content in a particular | ||
| /// Flutter view. |
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.
Nit: Maybe explain here what happens when multiple SensitiveContent widgets are in the tree.
| @override | ||
| void initState() { | ||
| super.initState(); | ||
| SensitiveContentSetting.register(widget.viewId, widget.sensitivityLevel); | ||
| } | ||
|
|
||
| @override | ||
| void dispose() { | ||
| SensitiveContentSetting.unregister(widget.viewId, widget.sensitivityLevel); | ||
| super.dispose(); | ||
| } |
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.
Some scenarios to try:
- What if SensitiveContent is part of an item in ListView.builder, and that item is scrolled off-screen. Will it be disposed and unregister itself? Is that desirable?
- What happens when a new full screen route is pushed on top of the route containing SensitiveContent? Does it get disposed, and is that desirable or not?
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 if SensitiveContent is part of an item in ListView.builder, and that item is scrolled off-screen. Will it be disposed and unregister itself? Is that desirable?
I don't see it unregistered and I assume that the SensitiveContent widget is actually not getting disposed, keeping the screen obscured. Will need to double check this theory by debugging. I think ideally, the screen is only obscured while the SensitiveContent widget is visible on screen; fixing this may be part of #160051 which I intend to do in a follow up PR.
- What happens when a new full screen route is pushed on top of the route containing SensitiveContent? Does it get disposed, and is that desirable or not?
If a route is pushed then the screen stays obscured. If a route is pushReplaced, then the SensitiveContent widget gets disposed and the screen does not stay obscured. As I mentioned in the first case, if we want the content sensitivity of the view to rely on widget visibility versus being disposed (meaning push and pushReplace would behave the same), this can be done as a part of #160051.
| final Map<int, ViewContentSensitivityState> _contentSensitivityStates = <int, ViewContentSensitivityState> {}; | ||
| final SensitiveContentService _sensitiveContentService = SensitiveContentService(); | ||
|
|
||
| static final SensitiveContentSetting _instance = SensitiveContentSetting._(); |
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.
One downside to this singleton pattern is that it doesn't get reset between test runs or hot reloads. I know it's currently used in many places though. But I wonder if there is a better way here.
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.
@justinmc do you have a good example of a plugin that is not a singleton that keeps track of android state?
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 wasn't able to find a good example. Maybe WidgetsBinding, but that is for communicating from the engine to widgets.
I'll ask around, but if I don't come up with anything then we can disregard this 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.
Another question I asked that may have implications here is whether we need to use FFI or not for this feature.
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'm just now seeing the issue about switching to JNIgen in the future: #160050. What's the reason behind not wanting to do that as a part of the initial PR?
I was talking to @chunhtai about how to get around using method channels and he suggested going through dart:ui as in FlutterView.updateSemantics (which I believe is handled here in the Android embedding). I've never used this approach before but it seems doable today.
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 do you mean by injecting Java code from their embedding?
In case if they implement their custom embedding, how would they handle the FFI call?
I remember the engine team alternatively suggesting checking the Java code into the engine and do something similar to dart:ui
I think they are referring to something like this
| @Native<Void Function(Bool)>(symbol: 'PlatformConfigurationNativeApi::SetNeedsReportTimings') |
create an one-off API and drill it through the engine shell to embedding
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.
In case if they implement their custom embedding, how would they handle the FFI call?
I've been giving this some thought. One solution could be keeping the sensitive content service that makes calls right now to a method channel (later will be FFI) overridable such that someone can override it to call into their custom embedding. This is not a great solution because it would require modifying the framework. On one hand, I'm not sure that this would be a huge leap for someone maintaining a custom embedding. On the other, I understand that sensitive content would be one of potentially many features switching from using a method channel to JNI/FFI, so we need to consider the larger scale impact of what that world would look like.
Frankly, I need to read up more on how custom embedders work (https://github.com/flutter/flutter/blob/main/engine/src/flutter/docs/Custom-Flutter-Engine-Embedders.md for my future reference). We'll need to set up some system like that for people to be able to override the behavior of any features that rely on FFI/JNI. I still plan to work on landing this with method channels for now, but I'll add a note to #160050 to make sure that answering this questions is part of that work.
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 agree that requiring framework changes is not a good approach. Currently I'm under the assumption that a custom embedder can simply listen for the method channel call just like we do in our embedders, so overriding something in the framework wouldn't be necessary.
And my assumption about the dart:ui FFI approach is that custom embedders need to implement some interface exposed in dart:ui, including whatever we add for sensitive content, so again no other changes would be needed. But I don't have firsthand experience with this. Maybe @stuartmorgan can clarify here?
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 don't have enough context from this thread to know what we are talking about exactly. It sounds like it's about how new Framework->embedding communication systems should work?
If so:
Currently I'm under the assumption that a custom embedder can simply listen for the method channel call just like we do in our embedders
We should absolutely not be building new features that require this behavior by embedders. Having a de-facto secondary embedding API of a bunch of method channels, which aren't tightly controlled, can much more easily be accidentally broken for third-party embeddings, and are untyped, is a terrible situation, and it should not be exacerbated with new public channels.
If some new feature is being exposed to arbitrary embeddings, it needs to be added to the formal API for embeddings, not require embedding authors to find, reverse engineer, and use a method channel.
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.
One solution could be keeping the sensitive content service that makes calls right now to a method channel (later will be FFI) overridable such that someone can override it to call into their custom embedding
I think this will be more complex then just handle the message in custom embedding.
Also any solution that require changes to framework to support a certain embedding is a big no-no.
Usually things like this we will create a new API surface drill through native dart:ui -> runtimeController -> shell -> each platform views. You can trace through FlutterView.updateSemantics to see how it is drill throw these layer.
For custom embedding, you will add a new API in embedder.h. I think the mentality is as long as the custom embedding implement function handler properly in embedder.h. Their embedding should work correctly.
Oops I meant widget not plugin :) |
|
|
||
| void main() { | ||
| // Default content sensitivity setting for testing. | ||
| final int defaultContentSensitivitySettingId = ContentSensitivity.autoSensitive.id; |
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 only tested with this as the default as of right now because I couldn't convince myself that there was greater value in testing other defaults besides the method channel setContentSensitivity method getting called (which is already tested with the other non-default modes in this test). If reviewers think that is valuable, I can make new test files to test the other modes as defaults (I think I have to do this because of the singleton pattern I used for SensitiveContentSetting).
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 it's not a big deal, in the code it looks like there is no special behavior for different default values. If you wanted to though, you could quickly do it by looping over ContentSensitivity.values and running the same test(s) for each value.
|
@justinmc @reidbaker This is ready for a full review! I know this PR is getting lengthy but I tried to address all your feedback + added tests + updated the PR description. |
|
Just found a small refactor I'd like to make while working on something else -- still ready for review! |
justinmc
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.
I have some ideas in my comments below about the dart classes in sensitive_content.dart, but most other stuff is nits.
I know we talked about mutliwindow already but I keep forgetting how that will work, is there something you can link me to that explains that?
engine/src/flutter/shell/platform/android/io/flutter/plugin/view/SensitiveContentPlugin.java
Outdated
Show resolved
Hide resolved
|
|
||
| void main() { | ||
| // Default content sensitivity setting for testing. | ||
| final int defaultContentSensitivitySettingId = ContentSensitivity.autoSensitive.id; |
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 it's not a big deal, in the code it looks like there is no special behavior for different default values. If you wanted to though, you could quickly do it by looping over ContentSensitivity.values and running the same test(s) for each value.
| expect(setContentSensitivityCallCount, 1); | ||
| }, | ||
| ); | ||
|
|
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.
Super nit: Just as a thought to reduce lines of code in these tests, you could write a single test and put it in a loop over ContentSensitivity.values, and use that value as the sensitivity for the widget that gets disposed, or something like 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.
I actually prefer having the tests loop-less so it's clear the exact use case that each one is testing. I think reading the looped version could get kinda hard to understand.
| final SensitiveContentSetting sensitiveContentSetting = SensitiveContentSetting.instance; | ||
|
|
||
| // The number of method channel calls to `SensitiveContent.setContentSensitivity`. | ||
| int setContentSensitivityCallCount = 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.
Nit: Instead of a count, you could do a List, where the length of the list is the same as the count. Then you could also test what it gets called with. Not sure if this is actually valuable or not here though, up to you.
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.
Love this idea and I think it's useful! Helps us verify what we actually requested the native side set. Done.
|
To address the multiwindow/multiview concerns:
I chatted a bit about this with reidbaker@ offline, and we concluded that we don't need to plan ahead for an unplanned feature; that is, multiwindow won't work with this PR out of the box. That is because multiwindow would involve multiple native Android I am making a PR to fix this, though, because this impacts the add-to-app multi- |
|
@justinmc @reidbaker This is ready for another look! |
That would mean that in test runs they would need to build a way to override the value. This value is sensitive and they want to protect their users but they dont want the protection during debug mode during testing. I think this user journey, the one where you want it off during testing is the one that I am the most worried about. |
|
If the I think it's fair to ask developers to build that functionality, and I don't think that making them do so is a good enough reason to decide against baking |
justinmc
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.
I think I caught a place where errors can be silently swallowed, see comment below.
About the integration test discussion above, does that situation only apply to integration tests that are actually testing sharing their screen to another device?
| } catch (e) { | ||
| // If this call fails or unexpectedly returns null, then consider setting content | ||
| // sensitivity unsupported. | ||
| return false; | ||
| } |
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 method looks like it will swallow errors and app developers might not be aware that something went wrong. They probably do want to assume that an error or null means false, but in addition I would probably do FlutterError.reportError.
You may want to do the error handling at the level of the caller of this method in order to align with how error handling is done for the other methods in this file, but it's up to you. The important part is just that errors don't get swallowed.
Yes it only applies to integration tests where the output of the screen is streamed. |
justinmc
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 👍 . Thanks for the error handling fix, looks great now.
About the integration test thing. Ok at least it's a rare case we're talking about here, but I agree we should provide a way to do this.
Would it be possible to mock isSupported and fake that sensitive content is not supported at all? It's easy to do this in a unit test (example) but I'm not sure about in an integration test.
That's what I'm thinking! For integration tests, developers would just need to expose a way to change their widget in an integration test to turn sensitive content sensitivity off. |
chunhtai
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
| throw FlutterError('Failed to retrieve content sensitivity: $e'); | ||
| } | ||
|
|
||
| final ContentSensitivity contentSensitivity = ContentSensitivity.values.firstWhere( |
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 can just be ContentSensitivity.values[result];
|
My force push was after running |
|
Well @camsim99 I messed this up. Now that the pr is closed I cant push to this branch anymore. |
> [!NOTE] > This PR lands #158473 (closed due to confusing git-isms). Please see that PR for all comments and discussion on landing this feature. ### Overview Implements setting content sensitivity on Android via a new widget called `SensitiveContent` that currently will only function on Android. ### How it's implemented There are three different content sensitivity levels: [`autoSensitive`](https://developer.android.com/reference/android/view/View#CONTENT_SENSITIVITY_AUTO), [`sensitive`](https://developer.android.com/reference/android/view/View#CONTENT_SENSITIVITY_SENSITIVE), [`notSensitive`](https://developer.android.com/reference/android/view/View#CONTENT_SENSITIVITY_NOT_SENSITIVE). All except `autoSensitive` behave as their Android counterpart level behaves (see links on the levels); for Flutter, `autoSensitive` will behave the same as `notSensitive` though it is implemented as if it works (see #160879 for more details. In any given Flutter view, each `SensitiveContent` widget sets a content sensitivity level and there may be multiple `SensitiveContent` widgets in the widget tree at a time, but only the most severe content sensitivity level in the tree will be maintained in order to ensure secure content remains obscured during screen projection. This means that even widgets that are not visible may still impact the overall content sensitivity of the entire Flutter view (see #160051 for more details). Under the hood, the implementation uses method channels. Theoretically, this could cause a delay in setting the content sensitivity level and a Flutter view being obscured during screen projection on time, so we will investigate using JNIgen in the future (see #160050 for more details). Over the method channel, the framework will send a Flutter view ID and content sensitivity level to the engine to set the expected content sensitivity level for the view. ### Timeline #### Required for feature shipping - Land this PR with the method channel implementation of content sensitivity. #### Short-term follow up tasks - Ensure every `FlutterView` has a unique ID for the native `SensitiveContentPlugin` to identify them by: #162685 - Add `SensitiveContent` widget to relevant Flutter widgets: #167302 #### Long-term follow up tasks - Convert this PR to use JNIgen: #160050. Verify no frames are dropped, revealing sensitive content during media projection: #164820. #### Stretch goals - Make the `SensitiveContent` widget sensitive to the visibility of child widgets: #160051 - Implement `autoSensitivity` mode: #160879 - Investigate backwards compatibility for APIs < 35: #159208 ### Open questions - ~Is it okay to hard-code the `FlutterActivity` and `FlutterFragment` view IDs? Does this impact add-to-app in any way? I assume we would need extenders of those classes to use a different view ID than the hardcoded one.~ Approach not used. - ~Should we expose `autoSensitive` for now? If so, what behavior should it have?~ Exposing `autoSensitive` as if it works. ### One way to test this PR (rough steps) 1. Create a Flutter app that has some number of `SensitiveContent` widgets. 9. Run the app on an emulator/device that runs API 35 and has the Google meets app downloaded. 10. Start a Google meets meeting and screen share (works with full screen and single app mode). 11. Join the Google meets meeting from another device and witness a blacked out screen if content has been marked sensitive. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
## Motivation We'd like to let users opt-in to experimental features so that they can give early feedback while we iterate on the feature. For example: Example feature flags: 1. Android sensitive content: #158473. When enabled, Flutter will tell Android when the view contains sensitive content like a password. 2. Desktop multi-window. When enabled, Flutter will use child windows to allow things like a context menu to "escape" outside of the current window. ### Use case Users will be able to turn on features by: * **Option 1**: Run `flutter config --enable-my-feature`. This enables the feature for all projects on the machine * **Option 2**: Add `enable-my-feature: true` in their `pubspec.yaml`, under the `flutter` section. This would enable the for a single project on the machine. Turning on a feature affects _both_ development-time (`flutter run`) and deployment-time (`flutter build x`). For example, I can `flutter build windows` to create an `.exe` with multi-window features enabled. ## How this works This adds a new [`runtimeId`](https://github.com/flutter/flutter/pull/168437/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R243-R247) property to the tool's `Feature` class. If a feature is on and has a `runtimeId`, its `runtimeId` will be [stamped into the Dart application as a Dart define](https://github.com/flutter/flutter/pull/168437/files#diff-bd662448bdc2e6f50e47cd3b20b22b41a828561bce65cb4d54ea4f5011cc604eR293-R327). The framework uses this Dart define to [determine which features are enabled](https://github.com/flutter/flutter/pull/168437/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45). ### Multi-window example #168697 shows how this new feature flag system can be used to add a multi-window feature flag: 1. It adds a new [multi-window feature](https://github.com/flutter/flutter/pull/168697/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R189-R198) to the Flutter tool. This can be turned on using `flutter config --enable-multi-window` or by putting `enable-multi-window: true` in an app's .pubspec, under the `flutter` section. 2. It adds a new [`isMultiWindowEnabled`](https://github.com/flutter/flutter/pull/168697/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45R7-R11) property to the framework. 3. The Material library can use this new property to determine whether it should create a new window. [Example](https://github.com/flutter/flutter/pull/168697/files#diff-2cbc1634ed6b61d61dfa090e7bfbbb7c60b74c8abc3a28df6f79eee691fd1b73). ## Limitations ### Tool and framework only For now, these feature flags are available only to the Flutter tool and Flutter framework. The flags are not automatically available to the embedder or the engine. For example, embedders need to configure their surfaces differently if Impeller is enabled. This configuration must happen before the Dart isolate is launched. As a result, the framework's feature flags is not a viable solution for this scenario for now. For these kinds of scenarios, we should continue to use platform-specific configuration like the `AndroidManifest.xml` or `Info.plist` files. This is a fixable limitation, we just need to invest in this plumbing :) ### Tree shaking Feature flags are not designed to help tree shaking. For example, you cannot conditionally import Dart code depending on the enabled feature flags. Code that is feature flagged off will still be imported into user's apps. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
<!-- start_original_pr_link --> Reverts: #168437 <!-- end_original_pr_link --> <!-- start_initiating_author --> Initiated by: chingjun <!-- end_initiating_author --> <!-- start_revert_reason --> Reason for reverting: broke internal customers <!-- end_revert_reason --> <!-- start_original_pr_author --> Original PR Author: loic-sharma <!-- end_original_pr_author --> <!-- start_reviewers --> Reviewed By: {bkonyi, justinmc, matanlurey} <!-- end_reviewers --> <!-- start_revert_body --> This change reverts the following previous change: ## Motivation We'd like to let users opt-in to experimental features so that they can give early feedback while we iterate on the feature. For example: Example feature flags: 1. Android sensitive content: #158473. When enabled, Flutter will tell Android when the view contains sensitive content like a password. 2. Desktop multi-window. When enabled, Flutter will use child windows to allow things like a context menu to "escape" outside of the current window. ### Use case Users will be able to turn on features by: * **Option 1**: Run `flutter config --enable-my-feature`. This enables the feature for all projects on the machine * **Option 2**: Add `enable-my-feature: true` in their `pubspec.yaml`, under the `flutter` section. This would enable the for a single project on the machine. Turning on a feature affects _both_ development-time (`flutter run`) and deployment-time (`flutter build x`). For example, I can `flutter build windows` to create an `.exe` with multi-window features enabled. ## How this works This adds a new [`runtimeId`](https://github.com/flutter/flutter/pull/168437/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R243-R247) property to the tool's `Feature` class. If a feature is on and has a `runtimeId`, its `runtimeId` will be [stamped into the Dart application as a Dart define](https://github.com/flutter/flutter/pull/168437/files#diff-bd662448bdc2e6f50e47cd3b20b22b41a828561bce65cb4d54ea4f5011cc604eR293-R327). The framework uses this Dart define to [determine which features are enabled](https://github.com/flutter/flutter/pull/168437/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45). ### Multi-window example #168697 shows how this new feature flag system can be used to add a multi-window feature flag: 1. It adds a new [multi-window feature](https://github.com/flutter/flutter/pull/168697/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R189-R198) to the Flutter tool. This can be turned on using `flutter config --enable-multi-window` or by putting `enable-multi-window: true` in an app's .pubspec, under the `flutter` section. 2. It adds a new [`isMultiWindowEnabled`](https://github.com/flutter/flutter/pull/168697/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45R7-R11) property to the framework. 3. The Material library can use this new property to determine whether it should create a new window. [Example](https://github.com/flutter/flutter/pull/168697/files#diff-2cbc1634ed6b61d61dfa090e7bfbbb7c60b74c8abc3a28df6f79eee691fd1b73). ## Limitations ### Tool and framework only For now, these feature flags are available only to the Flutter tool and Flutter framework. The flags are not automatically available to the embedder or the engine. For example, embedders need to configure their surfaces differently if Impeller is enabled. This configuration must happen before the Dart isolate is launched. As a result, the framework's feature flags is not a viable solution for this scenario for now. For these kinds of scenarios, we should continue to use platform-specific configuration like the `AndroidManifest.xml` or `Info.plist` files. This is a fixable limitation, we just need to invest in this plumbing :) ### Tree shaking Feature flags are not designed to help tree shaking. For example, you cannot conditionally import Dart code depending on the enabled feature flags. Code that is feature flagged off will still be imported into user's apps. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md <!-- end_revert_body --> Co-authored-by: auto-submit[bot] <[email protected]>
## Motivation We'd like to let users opt-in to experimental features so that they can give early feedback while we iterate on the feature. For example: Example feature flags: 1. Android sensitive content: flutter#158473. When enabled, Flutter will tell Android when the view contains sensitive content like a password. 2. Desktop multi-window. When enabled, Flutter will use child windows to allow things like a context menu to "escape" outside of the current window. ### Use case Users will be able to turn on features by: * **Option 1**: Run `flutter config --enable-my-feature`. This enables the feature for all projects on the machine * **Option 2**: Add `enable-my-feature: true` in their `pubspec.yaml`, under the `flutter` section. This would enable the for a single project on the machine. Turning on a feature affects _both_ development-time (`flutter run`) and deployment-time (`flutter build x`). For example, I can `flutter build windows` to create an `.exe` with multi-window features enabled. ## How this works This adds a new [`runtimeId`](https://github.com/flutter/flutter/pull/168437/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R243-R247) property to the tool's `Feature` class. If a feature is on and has a `runtimeId`, its `runtimeId` will be [stamped into the Dart application as a Dart define](https://github.com/flutter/flutter/pull/168437/files#diff-bd662448bdc2e6f50e47cd3b20b22b41a828561bce65cb4d54ea4f5011cc604eR293-R327). The framework uses this Dart define to [determine which features are enabled](https://github.com/flutter/flutter/pull/168437/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45). ### Multi-window example flutter#168697 shows how this new feature flag system can be used to add a multi-window feature flag: 1. It adds a new [multi-window feature](https://github.com/flutter/flutter/pull/168697/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R189-R198) to the Flutter tool. This can be turned on using `flutter config --enable-multi-window` or by putting `enable-multi-window: true` in an app's .pubspec, under the `flutter` section. 2. It adds a new [`isMultiWindowEnabled`](https://github.com/flutter/flutter/pull/168697/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45R7-R11) property to the framework. 3. The Material library can use this new property to determine whether it should create a new window. [Example](https://github.com/flutter/flutter/pull/168697/files#diff-2cbc1634ed6b61d61dfa090e7bfbbb7c60b74c8abc3a28df6f79eee691fd1b73). ## Limitations ### Tool and framework only For now, these feature flags are available only to the Flutter tool and Flutter framework. The flags are not automatically available to the embedder or the engine. For example, embedders need to configure their surfaces differently if Impeller is enabled. This configuration must happen before the Dart isolate is launched. As a result, the framework's feature flags is not a viable solution for this scenario for now. For these kinds of scenarios, we should continue to use platform-specific configuration like the `AndroidManifest.xml` or `Info.plist` files. This is a fixable limitation, we just need to invest in this plumbing :) ### Tree shaking Feature flags are not designed to help tree shaking. For example, you cannot conditionally import Dart code depending on the enabled feature flags. Code that is feature flagged off will still be imported into user's apps. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This relands #168437. The google3 fixes were landed in: #171547, https://critique.corp.google.com/cl/781275353, #171933. This PR is split into two commits: 1. d625379, code from #168437 without any changes 2. f35d29e, updates the PR to omit obvious types. Original PR description: ## Motivation We'd like to let users opt-in to experimental features so that they can give early feedback while we iterate on the feature. For example: Example feature flags: 1. Android sensitive content: #158473. When enabled, Flutter will tell Android when the view contains sensitive content like a password. 3. Desktop multi-window. When enabled, Flutter will use child windows to allow things like a context menu to "escape" outside of the current window. ### Use case Users will be able to turn on features by: * **Option 1**: Run `flutter config --enable-my-feature`. This enables the feature for all projects on the machine * **Option 2**: Add `enable-my-feature: true` in their `pubspec.yaml`, under the `flutter` section. This would enable the for a single project on the machine. Turning on a feature affects _both_ development-time (`flutter run`) and deployment-time (`flutter build x`). For example, I can `flutter build windows` to create an `.exe` with multi-window features enabled. ## How this works This adds a new [`runtimeId`](https://github.com/flutter/flutter/pull/168437/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R243-R247) property to the tool's `Feature` class. If a feature is on and has a `runtimeId`, its `runtimeId` will be [stamped into the Dart application as a Dart define](https://github.com/flutter/flutter/pull/168437/files#diff-bd662448bdc2e6f50e47cd3b20b22b41a828561bce65cb4d54ea4f5011cc604eR293-R327). The framework uses this Dart define to [determine which features are enabled](https://github.com/flutter/flutter/pull/168437/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45). ### Multi-window example #168697 shows how this new feature flag system can be used to add a multi-window feature flag: 1. It adds a new [multi-window feature](https://github.com/flutter/flutter/pull/168697/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R189-R198) to the Flutter tool. This can be turned on using `flutter config --enable-multi-window` or by putting `enable-multi-window: true` in an app's .pubspec, under the `flutter` section. 2. It adds a new [`isMultiWindowEnabled`](https://github.com/flutter/flutter/pull/168697/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45R7-R11) property to the framework. 4. The Material library can use this new property to determine whether it should create a new window. [Example](https://github.com/flutter/flutter/pull/168697/files#diff-2cbc1634ed6b61d61dfa090e7bfbbb7c60b74c8abc3a28df6f79eee691fd1b73). ## Limitations ### Tool and framework only For now, these feature flags are available only to the Flutter tool and Flutter framework. The flags are not automatically available to the embedder or the engine. For example, embedders need to configure their surfaces differently if Impeller is enabled. This configuration must happen before the Dart isolate is launched. As a result, the framework's feature flags is not a viable solution for this scenario for now. For these kinds of scenarios, we should continue to use platform-specific configuration like the `AndroidManifest.xml` or `Info.plist` files. This is a fixable limitation, we just need to invest in this plumbing :) ### Tree shaking Feature flags are not designed to help tree shaking. For example, you cannot conditionally import Dart code depending on the enabled feature flags. Code that is feature flagged off will still be imported into user's apps.
## Motivation We'd like to let users opt-in to experimental features so that they can give early feedback while we iterate on the feature. For example: Example feature flags: 1. Android sensitive content: flutter#158473. When enabled, Flutter will tell Android when the view contains sensitive content like a password. 2. Desktop multi-window. When enabled, Flutter will use child windows to allow things like a context menu to "escape" outside of the current window. ### Use case Users will be able to turn on features by: * **Option 1**: Run `flutter config --enable-my-feature`. This enables the feature for all projects on the machine * **Option 2**: Add `enable-my-feature: true` in their `pubspec.yaml`, under the `flutter` section. This would enable the for a single project on the machine. Turning on a feature affects _both_ development-time (`flutter run`) and deployment-time (`flutter build x`). For example, I can `flutter build windows` to create an `.exe` with multi-window features enabled. ## How this works This adds a new [`runtimeId`](https://github.com/flutter/flutter/pull/168437/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R243-R247) property to the tool's `Feature` class. If a feature is on and has a `runtimeId`, its `runtimeId` will be [stamped into the Dart application as a Dart define](https://github.com/flutter/flutter/pull/168437/files#diff-bd662448bdc2e6f50e47cd3b20b22b41a828561bce65cb4d54ea4f5011cc604eR293-R327). The framework uses this Dart define to [determine which features are enabled](https://github.com/flutter/flutter/pull/168437/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45). ### Multi-window example flutter#168697 shows how this new feature flag system can be used to add a multi-window feature flag: 1. It adds a new [multi-window feature](https://github.com/flutter/flutter/pull/168697/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R189-R198) to the Flutter tool. This can be turned on using `flutter config --enable-multi-window` or by putting `enable-multi-window: true` in an app's .pubspec, under the `flutter` section. 2. It adds a new [`isMultiWindowEnabled`](https://github.com/flutter/flutter/pull/168697/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45R7-R11) property to the framework. 3. The Material library can use this new property to determine whether it should create a new window. [Example](https://github.com/flutter/flutter/pull/168697/files#diff-2cbc1634ed6b61d61dfa090e7bfbbb7c60b74c8abc3a28df6f79eee691fd1b73). ## Limitations ### Tool and framework only For now, these feature flags are available only to the Flutter tool and Flutter framework. The flags are not automatically available to the embedder or the engine. For example, embedders need to configure their surfaces differently if Impeller is enabled. This configuration must happen before the Dart isolate is launched. As a result, the framework's feature flags is not a viable solution for this scenario for now. For these kinds of scenarios, we should continue to use platform-specific configuration like the `AndroidManifest.xml` or `Info.plist` files. This is a fixable limitation, we just need to invest in this plumbing :) ### Tree shaking Feature flags are not designed to help tree shaking. For example, you cannot conditionally import Dart code depending on the enabled feature flags. Code that is feature flagged off will still be imported into user's apps. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…r#171542) <!-- start_original_pr_link --> Reverts: flutter#168437 <!-- end_original_pr_link --> <!-- start_initiating_author --> Initiated by: chingjun <!-- end_initiating_author --> <!-- start_revert_reason --> Reason for reverting: broke internal customers <!-- end_revert_reason --> <!-- start_original_pr_author --> Original PR Author: loic-sharma <!-- end_original_pr_author --> <!-- start_reviewers --> Reviewed By: {bkonyi, justinmc, matanlurey} <!-- end_reviewers --> <!-- start_revert_body --> This change reverts the following previous change: ## Motivation We'd like to let users opt-in to experimental features so that they can give early feedback while we iterate on the feature. For example: Example feature flags: 1. Android sensitive content: flutter#158473. When enabled, Flutter will tell Android when the view contains sensitive content like a password. 2. Desktop multi-window. When enabled, Flutter will use child windows to allow things like a context menu to "escape" outside of the current window. ### Use case Users will be able to turn on features by: * **Option 1**: Run `flutter config --enable-my-feature`. This enables the feature for all projects on the machine * **Option 2**: Add `enable-my-feature: true` in their `pubspec.yaml`, under the `flutter` section. This would enable the for a single project on the machine. Turning on a feature affects _both_ development-time (`flutter run`) and deployment-time (`flutter build x`). For example, I can `flutter build windows` to create an `.exe` with multi-window features enabled. ## How this works This adds a new [`runtimeId`](https://github.com/flutter/flutter/pull/168437/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R243-R247) property to the tool's `Feature` class. If a feature is on and has a `runtimeId`, its `runtimeId` will be [stamped into the Dart application as a Dart define](https://github.com/flutter/flutter/pull/168437/files#diff-bd662448bdc2e6f50e47cd3b20b22b41a828561bce65cb4d54ea4f5011cc604eR293-R327). The framework uses this Dart define to [determine which features are enabled](https://github.com/flutter/flutter/pull/168437/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45). ### Multi-window example flutter#168697 shows how this new feature flag system can be used to add a multi-window feature flag: 1. It adds a new [multi-window feature](https://github.com/flutter/flutter/pull/168697/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R189-R198) to the Flutter tool. This can be turned on using `flutter config --enable-multi-window` or by putting `enable-multi-window: true` in an app's .pubspec, under the `flutter` section. 2. It adds a new [`isMultiWindowEnabled`](https://github.com/flutter/flutter/pull/168697/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45R7-R11) property to the framework. 3. The Material library can use this new property to determine whether it should create a new window. [Example](https://github.com/flutter/flutter/pull/168697/files#diff-2cbc1634ed6b61d61dfa090e7bfbbb7c60b74c8abc3a28df6f79eee691fd1b73). ## Limitations ### Tool and framework only For now, these feature flags are available only to the Flutter tool and Flutter framework. The flags are not automatically available to the embedder or the engine. For example, embedders need to configure their surfaces differently if Impeller is enabled. This configuration must happen before the Dart isolate is launched. As a result, the framework's feature flags is not a viable solution for this scenario for now. For these kinds of scenarios, we should continue to use platform-specific configuration like the `AndroidManifest.xml` or `Info.plist` files. This is a fixable limitation, we just need to invest in this plumbing :) ### Tree shaking Feature flags are not designed to help tree shaking. For example, you cannot conditionally import Dart code depending on the enabled feature flags. Code that is feature flagged off will still be imported into user's apps. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md <!-- end_revert_body --> Co-authored-by: auto-submit[bot] <[email protected]>
This relands flutter#168437. The google3 fixes were landed in: flutter#171547, https://critique.corp.google.com/cl/781275353, flutter#171933. This PR is split into two commits: 1. d625379, code from flutter#168437 without any changes 2. f35d29e, updates the PR to omit obvious types. Original PR description: ## Motivation We'd like to let users opt-in to experimental features so that they can give early feedback while we iterate on the feature. For example: Example feature flags: 1. Android sensitive content: flutter#158473. When enabled, Flutter will tell Android when the view contains sensitive content like a password. 3. Desktop multi-window. When enabled, Flutter will use child windows to allow things like a context menu to "escape" outside of the current window. ### Use case Users will be able to turn on features by: * **Option 1**: Run `flutter config --enable-my-feature`. This enables the feature for all projects on the machine * **Option 2**: Add `enable-my-feature: true` in their `pubspec.yaml`, under the `flutter` section. This would enable the for a single project on the machine. Turning on a feature affects _both_ development-time (`flutter run`) and deployment-time (`flutter build x`). For example, I can `flutter build windows` to create an `.exe` with multi-window features enabled. ## How this works This adds a new [`runtimeId`](https://github.com/flutter/flutter/pull/168437/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R243-R247) property to the tool's `Feature` class. If a feature is on and has a `runtimeId`, its `runtimeId` will be [stamped into the Dart application as a Dart define](https://github.com/flutter/flutter/pull/168437/files#diff-bd662448bdc2e6f50e47cd3b20b22b41a828561bce65cb4d54ea4f5011cc604eR293-R327). The framework uses this Dart define to [determine which features are enabled](https://github.com/flutter/flutter/pull/168437/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45). ### Multi-window example flutter#168697 shows how this new feature flag system can be used to add a multi-window feature flag: 1. It adds a new [multi-window feature](https://github.com/flutter/flutter/pull/168697/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R189-R198) to the Flutter tool. This can be turned on using `flutter config --enable-multi-window` or by putting `enable-multi-window: true` in an app's .pubspec, under the `flutter` section. 2. It adds a new [`isMultiWindowEnabled`](https://github.com/flutter/flutter/pull/168697/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45R7-R11) property to the framework. 4. The Material library can use this new property to determine whether it should create a new window. [Example](https://github.com/flutter/flutter/pull/168697/files#diff-2cbc1634ed6b61d61dfa090e7bfbbb7c60b74c8abc3a28df6f79eee691fd1b73). ## Limitations ### Tool and framework only For now, these feature flags are available only to the Flutter tool and Flutter framework. The flags are not automatically available to the embedder or the engine. For example, embedders need to configure their surfaces differently if Impeller is enabled. This configuration must happen before the Dart isolate is launched. As a result, the framework's feature flags is not a viable solution for this scenario for now. For these kinds of scenarios, we should continue to use platform-specific configuration like the `AndroidManifest.xml` or `Info.plist` files. This is a fixable limitation, we just need to invest in this plumbing :) ### Tree shaking Feature flags are not designed to help tree shaking. For example, you cannot conditionally import Dart code depending on the enabled feature flags. Code that is feature flagged off will still be imported into user's apps.
> [!NOTE] > This PR lands flutter#158473 (closed due to confusing git-isms). Please see that PR for all comments and discussion on landing this feature. ### Overview Implements setting content sensitivity on Android via a new widget called `SensitiveContent` that currently will only function on Android. ### How it's implemented There are three different content sensitivity levels: [`autoSensitive`](https://developer.android.com/reference/android/view/View#CONTENT_SENSITIVITY_AUTO), [`sensitive`](https://developer.android.com/reference/android/view/View#CONTENT_SENSITIVITY_SENSITIVE), [`notSensitive`](https://developer.android.com/reference/android/view/View#CONTENT_SENSITIVITY_NOT_SENSITIVE). All except `autoSensitive` behave as their Android counterpart level behaves (see links on the levels); for Flutter, `autoSensitive` will behave the same as `notSensitive` though it is implemented as if it works (see flutter#160879 for more details. In any given Flutter view, each `SensitiveContent` widget sets a content sensitivity level and there may be multiple `SensitiveContent` widgets in the widget tree at a time, but only the most severe content sensitivity level in the tree will be maintained in order to ensure secure content remains obscured during screen projection. This means that even widgets that are not visible may still impact the overall content sensitivity of the entire Flutter view (see flutter#160051 for more details). Under the hood, the implementation uses method channels. Theoretically, this could cause a delay in setting the content sensitivity level and a Flutter view being obscured during screen projection on time, so we will investigate using JNIgen in the future (see flutter#160050 for more details). Over the method channel, the framework will send a Flutter view ID and content sensitivity level to the engine to set the expected content sensitivity level for the view. ### Timeline #### Required for feature shipping - Land this PR with the method channel implementation of content sensitivity. #### Short-term follow up tasks - Ensure every `FlutterView` has a unique ID for the native `SensitiveContentPlugin` to identify them by: flutter#162685 - Add `SensitiveContent` widget to relevant Flutter widgets: flutter#167302 #### Long-term follow up tasks - Convert this PR to use JNIgen: flutter#160050. Verify no frames are dropped, revealing sensitive content during media projection: flutter#164820. #### Stretch goals - Make the `SensitiveContent` widget sensitive to the visibility of child widgets: flutter#160051 - Implement `autoSensitivity` mode: flutter#160879 - Investigate backwards compatibility for APIs < 35: flutter#159208 ### Open questions - ~Is it okay to hard-code the `FlutterActivity` and `FlutterFragment` view IDs? Does this impact add-to-app in any way? I assume we would need extenders of those classes to use a different view ID than the hardcoded one.~ Approach not used. - ~Should we expose `autoSensitive` for now? If so, what behavior should it have?~ Exposing `autoSensitive` as if it works. ### One way to test this PR (rough steps) 1. Create a Flutter app that has some number of `SensitiveContent` widgets. 9. Run the app on an emulator/device that runs API 35 and has the Google meets app downloaded. 10. Start a Google meets meeting and screen share (works with full screen and single app mode). 11. Join the Google meets meeting from another device and witness a blacked out screen if content has been marked sensitive. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This relands flutter#168437. The google3 fixes were landed in: flutter#171547, https://critique.corp.google.com/cl/781275353, flutter#171933. This PR is split into two commits: 1. d625379, code from flutter#168437 without any changes 2. f35d29e, updates the PR to omit obvious types. Original PR description: ## Motivation We'd like to let users opt-in to experimental features so that they can give early feedback while we iterate on the feature. For example: Example feature flags: 1. Android sensitive content: flutter#158473. When enabled, Flutter will tell Android when the view contains sensitive content like a password. 3. Desktop multi-window. When enabled, Flutter will use child windows to allow things like a context menu to "escape" outside of the current window. ### Use case Users will be able to turn on features by: * **Option 1**: Run `flutter config --enable-my-feature`. This enables the feature for all projects on the machine * **Option 2**: Add `enable-my-feature: true` in their `pubspec.yaml`, under the `flutter` section. This would enable the for a single project on the machine. Turning on a feature affects _both_ development-time (`flutter run`) and deployment-time (`flutter build x`). For example, I can `flutter build windows` to create an `.exe` with multi-window features enabled. ## How this works This adds a new [`runtimeId`](https://github.com/flutter/flutter/pull/168437/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R243-R247) property to the tool's `Feature` class. If a feature is on and has a `runtimeId`, its `runtimeId` will be [stamped into the Dart application as a Dart define](https://github.com/flutter/flutter/pull/168437/files#diff-bd662448bdc2e6f50e47cd3b20b22b41a828561bce65cb4d54ea4f5011cc604eR293-R327). The framework uses this Dart define to [determine which features are enabled](https://github.com/flutter/flutter/pull/168437/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45). ### Multi-window example flutter#168697 shows how this new feature flag system can be used to add a multi-window feature flag: 1. It adds a new [multi-window feature](https://github.com/flutter/flutter/pull/168697/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R189-R198) to the Flutter tool. This can be turned on using `flutter config --enable-multi-window` or by putting `enable-multi-window: true` in an app's .pubspec, under the `flutter` section. 2. It adds a new [`isMultiWindowEnabled`](https://github.com/flutter/flutter/pull/168697/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45R7-R11) property to the framework. 4. The Material library can use this new property to determine whether it should create a new window. [Example](https://github.com/flutter/flutter/pull/168697/files#diff-2cbc1634ed6b61d61dfa090e7bfbbb7c60b74c8abc3a28df6f79eee691fd1b73). ## Limitations ### Tool and framework only For now, these feature flags are available only to the Flutter tool and Flutter framework. The flags are not automatically available to the embedder or the engine. For example, embedders need to configure their surfaces differently if Impeller is enabled. This configuration must happen before the Dart isolate is launched. As a result, the framework's feature flags is not a viable solution for this scenario for now. For these kinds of scenarios, we should continue to use platform-specific configuration like the `AndroidManifest.xml` or `Info.plist` files. This is a fixable limitation, we just need to invest in this plumbing :) ### Tree shaking Feature flags are not designed to help tree shaking. For example, you cannot conditionally import Dart code depending on the enabled feature flags. Code that is feature flagged off will still be imported into user's apps.
This relands flutter#168437. The google3 fixes were landed in: flutter#171547, https://critique.corp.google.com/cl/781275353, flutter#171933. This PR is split into two commits: 1. d625379, code from flutter#168437 without any changes 2. f35d29e, updates the PR to omit obvious types. Original PR description: ## Motivation We'd like to let users opt-in to experimental features so that they can give early feedback while we iterate on the feature. For example: Example feature flags: 1. Android sensitive content: flutter#158473. When enabled, Flutter will tell Android when the view contains sensitive content like a password. 3. Desktop multi-window. When enabled, Flutter will use child windows to allow things like a context menu to "escape" outside of the current window. ### Use case Users will be able to turn on features by: * **Option 1**: Run `flutter config --enable-my-feature`. This enables the feature for all projects on the machine * **Option 2**: Add `enable-my-feature: true` in their `pubspec.yaml`, under the `flutter` section. This would enable the for a single project on the machine. Turning on a feature affects _both_ development-time (`flutter run`) and deployment-time (`flutter build x`). For example, I can `flutter build windows` to create an `.exe` with multi-window features enabled. ## How this works This adds a new [`runtimeId`](https://github.com/flutter/flutter/pull/168437/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R243-R247) property to the tool's `Feature` class. If a feature is on and has a `runtimeId`, its `runtimeId` will be [stamped into the Dart application as a Dart define](https://github.com/flutter/flutter/pull/168437/files#diff-bd662448bdc2e6f50e47cd3b20b22b41a828561bce65cb4d54ea4f5011cc604eR293-R327). The framework uses this Dart define to [determine which features are enabled](https://github.com/flutter/flutter/pull/168437/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45). ### Multi-window example flutter#168697 shows how this new feature flag system can be used to add a multi-window feature flag: 1. It adds a new [multi-window feature](https://github.com/flutter/flutter/pull/168697/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R189-R198) to the Flutter tool. This can be turned on using `flutter config --enable-multi-window` or by putting `enable-multi-window: true` in an app's .pubspec, under the `flutter` section. 2. It adds a new [`isMultiWindowEnabled`](https://github.com/flutter/flutter/pull/168697/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45R7-R11) property to the framework. 4. The Material library can use this new property to determine whether it should create a new window. [Example](https://github.com/flutter/flutter/pull/168697/files#diff-2cbc1634ed6b61d61dfa090e7bfbbb7c60b74c8abc3a28df6f79eee691fd1b73). ## Limitations ### Tool and framework only For now, these feature flags are available only to the Flutter tool and Flutter framework. The flags are not automatically available to the embedder or the engine. For example, embedders need to configure their surfaces differently if Impeller is enabled. This configuration must happen before the Dart isolate is launched. As a result, the framework's feature flags is not a viable solution for this scenario for now. For these kinds of scenarios, we should continue to use platform-specific configuration like the `AndroidManifest.xml` or `Info.plist` files. This is a fixable limitation, we just need to invest in this plumbing :) ### Tree shaking Feature flags are not designed to help tree shaking. For example, you cannot conditionally import Dart code depending on the enabled feature flags. Code that is feature flagged off will still be imported into user's apps.
## Motivation We'd like to let users opt-in to experimental features so that they can give early feedback while we iterate on the feature. For example: Example feature flags: 1. Android sensitive content: flutter#158473. When enabled, Flutter will tell Android when the view contains sensitive content like a password. 2. Desktop multi-window. When enabled, Flutter will use child windows to allow things like a context menu to "escape" outside of the current window. ### Use case Users will be able to turn on features by: * **Option 1**: Run `flutter config --enable-my-feature`. This enables the feature for all projects on the machine * **Option 2**: Add `enable-my-feature: true` in their `pubspec.yaml`, under the `flutter` section. This would enable the for a single project on the machine. Turning on a feature affects _both_ development-time (`flutter run`) and deployment-time (`flutter build x`). For example, I can `flutter build windows` to create an `.exe` with multi-window features enabled. ## How this works This adds a new [`runtimeId`](https://github.com/flutter/flutter/pull/168437/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R243-R247) property to the tool's `Feature` class. If a feature is on and has a `runtimeId`, its `runtimeId` will be [stamped into the Dart application as a Dart define](https://github.com/flutter/flutter/pull/168437/files#diff-bd662448bdc2e6f50e47cd3b20b22b41a828561bce65cb4d54ea4f5011cc604eR293-R327). The framework uses this Dart define to [determine which features are enabled](https://github.com/flutter/flutter/pull/168437/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45). ### Multi-window example flutter#168697 shows how this new feature flag system can be used to add a multi-window feature flag: 1. It adds a new [multi-window feature](https://github.com/flutter/flutter/pull/168697/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R189-R198) to the Flutter tool. This can be turned on using `flutter config --enable-multi-window` or by putting `enable-multi-window: true` in an app's .pubspec, under the `flutter` section. 2. It adds a new [`isMultiWindowEnabled`](https://github.com/flutter/flutter/pull/168697/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45R7-R11) property to the framework. 3. The Material library can use this new property to determine whether it should create a new window. [Example](https://github.com/flutter/flutter/pull/168697/files#diff-2cbc1634ed6b61d61dfa090e7bfbbb7c60b74c8abc3a28df6f79eee691fd1b73). ## Limitations ### Tool and framework only For now, these feature flags are available only to the Flutter tool and Flutter framework. The flags are not automatically available to the embedder or the engine. For example, embedders need to configure their surfaces differently if Impeller is enabled. This configuration must happen before the Dart isolate is launched. As a result, the framework's feature flags is not a viable solution for this scenario for now. For these kinds of scenarios, we should continue to use platform-specific configuration like the `AndroidManifest.xml` or `Info.plist` files. This is a fixable limitation, we just need to invest in this plumbing :) ### Tree shaking Feature flags are not designed to help tree shaking. For example, you cannot conditionally import Dart code depending on the enabled feature flags. Code that is feature flagged off will still be imported into user's apps. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…r#171542) <!-- start_original_pr_link --> Reverts: flutter#168437 <!-- end_original_pr_link --> <!-- start_initiating_author --> Initiated by: chingjun <!-- end_initiating_author --> <!-- start_revert_reason --> Reason for reverting: broke internal customers <!-- end_revert_reason --> <!-- start_original_pr_author --> Original PR Author: loic-sharma <!-- end_original_pr_author --> <!-- start_reviewers --> Reviewed By: {bkonyi, justinmc, matanlurey} <!-- end_reviewers --> <!-- start_revert_body --> This change reverts the following previous change: ## Motivation We'd like to let users opt-in to experimental features so that they can give early feedback while we iterate on the feature. For example: Example feature flags: 1. Android sensitive content: flutter#158473. When enabled, Flutter will tell Android when the view contains sensitive content like a password. 2. Desktop multi-window. When enabled, Flutter will use child windows to allow things like a context menu to "escape" outside of the current window. ### Use case Users will be able to turn on features by: * **Option 1**: Run `flutter config --enable-my-feature`. This enables the feature for all projects on the machine * **Option 2**: Add `enable-my-feature: true` in their `pubspec.yaml`, under the `flutter` section. This would enable the for a single project on the machine. Turning on a feature affects _both_ development-time (`flutter run`) and deployment-time (`flutter build x`). For example, I can `flutter build windows` to create an `.exe` with multi-window features enabled. ## How this works This adds a new [`runtimeId`](https://github.com/flutter/flutter/pull/168437/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R243-R247) property to the tool's `Feature` class. If a feature is on and has a `runtimeId`, its `runtimeId` will be [stamped into the Dart application as a Dart define](https://github.com/flutter/flutter/pull/168437/files#diff-bd662448bdc2e6f50e47cd3b20b22b41a828561bce65cb4d54ea4f5011cc604eR293-R327). The framework uses this Dart define to [determine which features are enabled](https://github.com/flutter/flutter/pull/168437/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45). ### Multi-window example flutter#168697 shows how this new feature flag system can be used to add a multi-window feature flag: 1. It adds a new [multi-window feature](https://github.com/flutter/flutter/pull/168697/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R189-R198) to the Flutter tool. This can be turned on using `flutter config --enable-multi-window` or by putting `enable-multi-window: true` in an app's .pubspec, under the `flutter` section. 2. It adds a new [`isMultiWindowEnabled`](https://github.com/flutter/flutter/pull/168697/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45R7-R11) property to the framework. 3. The Material library can use this new property to determine whether it should create a new window. [Example](https://github.com/flutter/flutter/pull/168697/files#diff-2cbc1634ed6b61d61dfa090e7bfbbb7c60b74c8abc3a28df6f79eee691fd1b73). ## Limitations ### Tool and framework only For now, these feature flags are available only to the Flutter tool and Flutter framework. The flags are not automatically available to the embedder or the engine. For example, embedders need to configure their surfaces differently if Impeller is enabled. This configuration must happen before the Dart isolate is launched. As a result, the framework's feature flags is not a viable solution for this scenario for now. For these kinds of scenarios, we should continue to use platform-specific configuration like the `AndroidManifest.xml` or `Info.plist` files. This is a fixable limitation, we just need to invest in this plumbing :) ### Tree shaking Feature flags are not designed to help tree shaking. For example, you cannot conditionally import Dart code depending on the enabled feature flags. Code that is feature flagged off will still be imported into user's apps. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md <!-- end_revert_body --> Co-authored-by: auto-submit[bot] <[email protected]>
This relands flutter#168437. The google3 fixes were landed in: flutter#171547, https://critique.corp.google.com/cl/781275353, flutter#171933. This PR is split into two commits: 1. d625379, code from flutter#168437 without any changes 2. f35d29e, updates the PR to omit obvious types. Original PR description: ## Motivation We'd like to let users opt-in to experimental features so that they can give early feedback while we iterate on the feature. For example: Example feature flags: 1. Android sensitive content: flutter#158473. When enabled, Flutter will tell Android when the view contains sensitive content like a password. 3. Desktop multi-window. When enabled, Flutter will use child windows to allow things like a context menu to "escape" outside of the current window. ### Use case Users will be able to turn on features by: * **Option 1**: Run `flutter config --enable-my-feature`. This enables the feature for all projects on the machine * **Option 2**: Add `enable-my-feature: true` in their `pubspec.yaml`, under the `flutter` section. This would enable the for a single project on the machine. Turning on a feature affects _both_ development-time (`flutter run`) and deployment-time (`flutter build x`). For example, I can `flutter build windows` to create an `.exe` with multi-window features enabled. ## How this works This adds a new [`runtimeId`](https://github.com/flutter/flutter/pull/168437/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R243-R247) property to the tool's `Feature` class. If a feature is on and has a `runtimeId`, its `runtimeId` will be [stamped into the Dart application as a Dart define](https://github.com/flutter/flutter/pull/168437/files#diff-bd662448bdc2e6f50e47cd3b20b22b41a828561bce65cb4d54ea4f5011cc604eR293-R327). The framework uses this Dart define to [determine which features are enabled](https://github.com/flutter/flutter/pull/168437/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45). ### Multi-window example flutter#168697 shows how this new feature flag system can be used to add a multi-window feature flag: 1. It adds a new [multi-window feature](https://github.com/flutter/flutter/pull/168697/files#diff-0ded384225f19a4c34d43c7c11f7cb084ff3db947cfa82d8d52fc94c112bb2a7R189-R198) to the Flutter tool. This can be turned on using `flutter config --enable-multi-window` or by putting `enable-multi-window: true` in an app's .pubspec, under the `flutter` section. 2. It adds a new [`isMultiWindowEnabled`](https://github.com/flutter/flutter/pull/168697/files#diff-c8dbd5cd3103bc5be53c4ac5be8bdb9bf73e10cd5d8e4ac34e737fd1f8602d45R7-R11) property to the framework. 4. The Material library can use this new property to determine whether it should create a new window. [Example](https://github.com/flutter/flutter/pull/168697/files#diff-2cbc1634ed6b61d61dfa090e7bfbbb7c60b74c8abc3a28df6f79eee691fd1b73). ## Limitations ### Tool and framework only For now, these feature flags are available only to the Flutter tool and Flutter framework. The flags are not automatically available to the embedder or the engine. For example, embedders need to configure their surfaces differently if Impeller is enabled. This configuration must happen before the Dart isolate is launched. As a result, the framework's feature flags is not a viable solution for this scenario for now. For these kinds of scenarios, we should continue to use platform-specific configuration like the `AndroidManifest.xml` or `Info.plist` files. This is a fixable limitation, we just need to invest in this plumbing :) ### Tree shaking Feature flags are not designed to help tree shaking. For example, you cannot conditionally import Dart code depending on the enabled feature flags. Code that is feature flagged off will still be imported into user's apps.
Important
Messed up this branch :') Landed in #167815.
Overview
Implements setting content sensitivity on Android via a new widget called
SensitiveContentthat currently will only function on Android.How it's implemented
There are three different content sensitivity levels:
autoSensitive,sensitive,notSensitive. All exceptautoSensitivebehave as their Android counterpart level behaves (see links on the levels); for Flutter,autoSensitivewill behave the same asnotSensitivethough it is implemented as if it works (see #160879 for more details.In any given Flutter view, each
SensitiveContentwidget sets a content sensitivity level and there may be multipleSensitiveContentwidgets in the widget tree at a time, but only the most severe content sensitivity level in the tree will be maintained in order to ensure secure content remains obscured during screen projection. This means that even widgets that are not visible may still impact the overall content sensitivity of the entire Flutter view (see #160051 for more details).Under the hood, the implementation uses method channels. Theoretically, this could cause a delay in setting the content sensitivity level and a Flutter view being obscured during screen projection on time, so we will investigate using JNIgen in the future (see #160050 for more details). Over the method channel, the framework will send a Flutter view ID and content sensitivity level to the engine to set the expected content sensitivity level for the view.
Timeline
Required for feature shipping
Short-term follow up tasks
FlutterViewhas a unique ID for the nativeSensitiveContentPluginto identify them by: [Android] MakeFlutterViewIDs instance variables instead of a static one #162685SensitiveContentwidget to relevant Flutter widgets: [Android] AddSensitiveContentwidget to Flutter widgets that have potential security vulnerabilities during screen share #167302Long-term follow up tasks
SensitiveContentwidget potential frame drops are not visible #164820.Stretch goals
SensitiveContentwidget sensitive to the visibility of child widgets: [Android] Un-mark sensitive content when it is not visible on screen #160051autoSensitivitymode: [Android] Investigate implementingautoSensitivesensitive content mode #160879Open questions
Is it okay to hard-code theApproach not used.FlutterActivityandFlutterFragmentview IDs? Does this impact add-to-app in any way? I assume we would need extenders of those classes to use a different view ID than the hardcoded one.Should we exposeExposingautoSensitivefor now? If so, what behavior should it have?autoSensitiveas if it works.One way to test this PR (rough steps)
SensitiveContentwidgets.Pre-launch Checklist
///).