Skip to content

Conversation

@Gustl22
Copy link
Contributor

@Gustl22 Gustl22 commented May 29, 2022

Description

Ability to set arbitrary browser flags.

Example usage:

flutter run -d chrome --web-browser-flag "--disable-web-security"
flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart -d web-server --web-browser-flag="--autoplay-policy=no-user-gesture-required"

Related issues

#65575

Change policies

If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.
I think there's no docs that need a migration guide, but we should adapt the WIKI

Notes

I could not test my changes in real use case as I get this error (on Windows Powershell):

 dart D:/Coding/git/flutter/flutter/packages/flutter_tools/bin/flutter_tools.dart drive --driver=test_driver/integration_test.dart           --target=integration_test/app_test.dart           -d web-server --browser-flags="--incognito"
Running "flutter pub get" in example...                            994ms
Launching integration_test/app_test.dart on Web Server in debug mode...
ERROR: FormatException: Could not find an option named "verbosity".

Usage: server [options] [input.dart]

If filename or uri pointing to the entrypoint is provided on the command line,
then the server compiles it, generates dill file and exits.
If no entrypoint is provided on the command line, server waits for
instructions from stdin.

Do you have a clue, how to execute the flutter tool command from source?

The unit tests seem to work fine.

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@flutter-dashboard flutter-dashboard bot added the tool Affects the "flutter" command-line tool. See also t: labels. label May 29, 2022
@christopherfujino christopherfujino added the platform-web Web applications specifically label Jun 2, 2022
@Gustl22
Copy link
Contributor Author

Gustl22 commented Jun 7, 2022

@jonahwilliams kindly asking for a review, if you have time?

Copy link
Contributor

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what that errors is caused by exactly, but could be related to a webdriver version mismatch. I would make sure your webdriver version is newer.

Does run work with this new flag?

@Gustl22
Copy link
Contributor Author

Gustl22 commented Jun 9, 2022

I would make sure your webdriver version is newer.

I checked, Chromedriver version matches the Chrome version :/

Does run work with this new flag?

Same error for run

dart D:/Coding/git/flutter/flutter/packages/flutter_tools/bin/flutter_tools.dart run lib/main.dart -d web-server --web-browser-flags="--incognito"
Launching lib/main.dart on Web Server in debug mode...
ERROR: FormatException: Could not find an option named "verbosity".

Usage: server [options] [input.dart]

Also tried it on my Linux-PC, same error message for both commands. Do I miss something? Btw: it recognizes when I use a wrong a wrong option, so the new source code seems to be valid somehow.

Edit: I think I have to upgrade flutter to the master channel. Thought this is not necessary, as the tools should be executed from the sources, but not the dart command though...

@christopherfujino
Copy link
Contributor

Edit: I think I have to upgrade flutter to the master channel. Thought this is not necessary, as the tools should be executed from the sources, but not the dart command though...

You should be testing your tool changes with the version of the Dart SDK in your Flutter commit. If you use the bin/flutter bash or bin/flutter.bat batch wrapper scripts, this will ensure you are using the correct version of Dart to compile and run the tool: https://github.com/flutter/flutter/blob/master/bin/flutter

@Gustl22
Copy link
Contributor Author

Gustl22 commented Jun 10, 2022

You should be testing your tool changes with the version of the Dart SDK in your Flutter commit.

Thanks worked now flawlessly:

D:/Coding/git/flutter/flutter/bin/dart.bat D:/Coding/git/flutter/flutter/packages/flutter_tools/bin/flutter_tools.dart run lib/main.dart -d chrome --web-browser-flags="--incognito"
D:/Coding/git/flutter/flutter/bin/dart.bat D:/Coding/git/flutter/flutter/packages/flutter_tools/bin/flutter_tools.dart drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart -d web-server --browser-flags="--incognito --autoplay-policy=no-user-gesture-required" --no-headless

@Gustl22
Copy link
Contributor Author

Gustl22 commented Jun 16, 2022

Kindly remind you for continuing the review
@christopherfujino @jonahwilliams, if you can afford the time :)

Copy link
Contributor

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jonahwilliams
Copy link
Contributor

Looks like flutter drive already has web-browser-flags? Can you de-duplicate that?

@Gustl22
Copy link
Contributor Author

Gustl22 commented Jun 23, 2022

@christopherfujino @jonahwilliams can you have a look again?
Btw: (Tests fail due to a svg pixel discrepancy, I doubt, that has anything to do with tooling)

@christopherfujino
Copy link
Contributor

@christopherfujino @jonahwilliams can you have a look again? Btw: (Tests fail due to a svg pixel discrepancy, I doubt, that has anything to do with tooling)

Can you rebase upstream? I'm sure you didn't break the goldens with this change, but a) it could be obscuring other legitimate failures, and b) we can't merge this without green pre-submits anyway.

Copy link
Contributor

@christopherfujino christopherfujino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than failing pre-submits (likely not related), LGTM

@Gustl22 Gustl22 force-pushed the 65575-browser-arbitrary-arguments branch from 45e6343 to f0e41dc Compare June 24, 2022 09:28
@Gustl22
Copy link
Contributor Author

Gustl22 commented Jun 24, 2022

@christopherfujino ok weird, the CI didn't like the merged, but rather rebased commits...

engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Jun 27, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Jun 28, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Jun 28, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Jun 28, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Jun 28, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Jun 28, 2022
camsim99 pushed a commit to camsim99/flutter that referenced this pull request Aug 10, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Aug 30, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Aug 30, 2022
@aytunch
Copy link

aytunch commented Feb 20, 2023

@Gustl22 How can we use these chrome flags in launch.json?
My current web launh config is as follows:

        {
            "name": "Web Flutter development",
            "cwd": "apps/web",
            "request": "launch",
            "type": "dart",
            "args": [
                "--flavor=development",
                "web-browser-flag=--disable-web-security"
            ]
        },

@Gustl22
Copy link
Contributor Author

Gustl22 commented Feb 20, 2023

I think like every other arg, too, by escaping the double quotes:

{
  ...
  "args": [
    "--flavor",
    "development",
    "--web-browser-flag",
    "\"--disable-web-security\""
  ]
}

or

{
  ...
  "args": [
    "--flavor=development",
    "--web-browser-flag=\"--disable-web-security\""
  ]
}

Let me know, if it's working.

@aytunch
Copy link

aytunch commented Feb 20, 2023

@Gustl22 yes it worked :)
did not even need the escape characters

            "args": [
                "--flavor=development",
                "--web-browser-flag=--disable-web-security"
            ]

Also, would this flag work in release version of our web apps as well?
Because now I see a warning in chrome:
Screenshot 2023-02-21 at 01 07 09

When I use flutter build instead of flutter run, I can not give this flag anymore. So what should we do for our release apps?

@Gustl22
Copy link
Contributor Author

Gustl22 commented Feb 20, 2023

Also, would this flag work in release version of our web apps as well? Because now I see a warning in chrome.

No this is just for development and testing. Or more specifically the user (client) can decide if they want to disable this security "feature".

To make this working in production you have to enable CORS on your server.

@balee
Copy link

balee commented Aug 26, 2023

@Gustl22

Thank you for the cool feature!

This works: flutter run -d chrome --web-browser-flag "--disable-web-security"
This also works: "c:\Program Files\Google\Chrome\Application\chrome.exe" --user-data-dir=c:\tmp\somedir

However, this doesn't work (user data dir setting is not applied): flutter run -d chrome --web-browser-flag "--user-data-dir=c:\tmp\somedir"

Any thoughts?

@Gustl22
Copy link
Contributor Author

Gustl22 commented Aug 26, 2023

However, this doesn't work (user data dir setting is not applied): flutter run -d chrome --web-browser-flag "--user-data-dir=c:\tmp\somedir"

Any thoughts?

You may need to quote the path itself, too:

flutter run -d chrome --web-browser-flag "--user-data-dir=\"c:\tmp\somedir\""
# or
flutter run -d chrome --web-browser-flag=--user-data-dir="c:\tmp\somedir"

@balee
Copy link

balee commented Aug 26, 2023

Nope :(
I have just looked at the source and found out how chrome is called.
It turned out it tries %USER%\appdata\Local\Google\Chrome\Application\chrome.exe first.
I created an empty file here and tried to run flutter like above.

The error message:

Oops; flutter has exited unexpectedly: "ProcessException: %1 is not a valid Win32 application.

  Command: C:\Users\...\AppData\Local\Google\Chrome\Application\chrome.exe
  --user-data-dir=C:\Users\...\AppData\Local\Temp\flutter_tools.af219ae6\flutter_tools_chrome_device.e9222837
  --remote-debugging-port=64216 --disable-background-timer-throttling --disable-extensions --disable-popup-blocking
  --bwsi --no-first-run --no-default-browser-check --disable-default-apps --disable-translate
  --user-data-dir=c:\tmp\somedir http://localhost:64144".

You can see that there are two --user-data-dir params and it seems the first is taken into account by chrome :(

@balee
Copy link

balee commented Aug 26, 2023

The correct solution seems to be moving ...webBrowserFlags to the front of the list so that the default parameters could be overriden, see:

    final List<String> args = <String>[
      chromeExecutable,
      // Using a tmp directory ensures that a new instance of chrome launches
      // allowing for the remote debug port to be enabled.
      '--user-data-dir=${userDataDir.path}',
      '--remote-debugging-port=$port',
      // When the DevTools has focus we don't want to slow down the application.
      '--disable-background-timer-throttling',
      // Since we are using a temp profile, disable features that slow the
      // Chrome launch.
      '--disable-extensions',
      '--disable-popup-blocking',
      '--bwsi',
      '--no-first-run',
      '--no-default-browser-check',
      '--disable-default-apps',
      '--disable-translate',
      if (headless)
        ...<String>[
          '--headless',
          '--disable-gpu',
          '--no-sandbox',
          '--window-size=2400,1800',
        ],
      ...webBrowserFlags,
      url,
    ];

github-merge-queue bot pushed a commit that referenced this pull request Jul 25, 2025
### Respect user-data-dir flag from web-browser-flag

Currently, it's already possible to pass `web-browser-flag` when
launching Chrome, but the `user-data-dir` flag doesn't work as expected,
and there are some reasons for that.

In the implementation made in [PR
#104935](#104935), the
`web-browser-flag` is appended at the end of the Chrome launch
arguments.

For most scenarios, this works fine, as demonstrated in the Chrome unit
test below:

https://source.chromium.org/chromium/chromium/src/+/main:base/command_line_unittest.cc

```
TEST(CommandLineTest, MultipleSameSwitch) {
  const CommandLine::CharType* argv[] = {
      FILE_PATH_LITERAL("program"),
      FILE_PATH_LITERAL("--foo=one"),  // --foo first time
      FILE_PATH_LITERAL("-baz"),
      FILE_PATH_LITERAL("--foo=two")   // --foo second time
  };
  CommandLine cl(std::size(argv), argv);

  EXPECT_TRUE(cl.HasSwitch("foo"));
  EXPECT_TRUE(cl.HasSwitch("baz"));

  EXPECT_EQ("two", cl.GetSwitchValueASCII("foo"));
}
```
In this scenario, the parser will consider the last occurrence of a
flag.

However, this behavior does not apply to certain flags, because Chrome
processes some of them based on the first occurrence, not the last. This
is the case for `--user-data-dir`, which is parsed very early during
Chrome startup.

The proposed code checks whether `--user-data-dir` was provided via
`web-browser-flag`, and if so, it uses that value instead of the default
`%temp%\flutter_tools_chrome_device.xpto` temporary directory.

This also resolve this comment:
#104935 (comment)

Example: `launch.json`
```
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "flutter",
      "request": "launch",
      "type": "dart"
    },
    {
      "name": "flutter (profile mode)",
      "request": "launch",
      "type": "dart",
      "flutterMode": "profile"
    },
    {
      "name": "flutter (release mode)",
      "request": "launch",
      "type": "dart",
      "flutterMode": "release"
    },
    {
      "name": "Flutter for web (hot reloadable)",
      "type": "dart",
      "request": "launch",
      "program": "lib/main.dart",
      "args": [
        "-d",
        "chrome",
        "--web-port=5000",
        "--web-experimental-hot-reload",
        "--web-browser-flag=--user-data-dir=D:\\_Desenv\\flutter_tests\\chrome_profile"
      ]
    }
  ]
}
```

`chrome://version`

| Before | After  |
|--------|--------|
|
![before](https://github.com/user-attachments/assets/b3f33419-fbf1-446e-a471-745df2e8c4f6)
|
![after](https://github.com/user-attachments/assets/ea74a203-c269-4ce1-8a9b-f97e9a4cdc78)
|

Folder
| Before | After  |
|--------|--------|
|
![before_files](https://github.com/user-attachments/assets/8522e60b-d0eb-4b66-a4b6-c2d6ed34c15b)
|
![after_files](https://github.com/user-attachments/assets/ff94b498-b319-474c-89e5-c55f6e1c4383)
|

## 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.

<!-- 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
azatech pushed a commit to azatech/flutter that referenced this pull request Jul 28, 2025
…#169445)

### Respect user-data-dir flag from web-browser-flag

Currently, it's already possible to pass `web-browser-flag` when
launching Chrome, but the `user-data-dir` flag doesn't work as expected,
and there are some reasons for that.

In the implementation made in [PR
flutter#104935](flutter#104935), the
`web-browser-flag` is appended at the end of the Chrome launch
arguments.

For most scenarios, this works fine, as demonstrated in the Chrome unit
test below:

https://source.chromium.org/chromium/chromium/src/+/main:base/command_line_unittest.cc

```
TEST(CommandLineTest, MultipleSameSwitch) {
  const CommandLine::CharType* argv[] = {
      FILE_PATH_LITERAL("program"),
      FILE_PATH_LITERAL("--foo=one"),  // --foo first time
      FILE_PATH_LITERAL("-baz"),
      FILE_PATH_LITERAL("--foo=two")   // --foo second time
  };
  CommandLine cl(std::size(argv), argv);

  EXPECT_TRUE(cl.HasSwitch("foo"));
  EXPECT_TRUE(cl.HasSwitch("baz"));

  EXPECT_EQ("two", cl.GetSwitchValueASCII("foo"));
}
```
In this scenario, the parser will consider the last occurrence of a
flag.

However, this behavior does not apply to certain flags, because Chrome
processes some of them based on the first occurrence, not the last. This
is the case for `--user-data-dir`, which is parsed very early during
Chrome startup.

The proposed code checks whether `--user-data-dir` was provided via
`web-browser-flag`, and if so, it uses that value instead of the default
`%temp%\flutter_tools_chrome_device.xpto` temporary directory.

This also resolve this comment:
flutter#104935 (comment)

Example: `launch.json`
```
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "flutter",
      "request": "launch",
      "type": "dart"
    },
    {
      "name": "flutter (profile mode)",
      "request": "launch",
      "type": "dart",
      "flutterMode": "profile"
    },
    {
      "name": "flutter (release mode)",
      "request": "launch",
      "type": "dart",
      "flutterMode": "release"
    },
    {
      "name": "Flutter for web (hot reloadable)",
      "type": "dart",
      "request": "launch",
      "program": "lib/main.dart",
      "args": [
        "-d",
        "chrome",
        "--web-port=5000",
        "--web-experimental-hot-reload",
        "--web-browser-flag=--user-data-dir=D:\\_Desenv\\flutter_tests\\chrome_profile"
      ]
    }
  ]
}
```

`chrome://version`

| Before | After  |
|--------|--------|
|
![before](https://github.com/user-attachments/assets/b3f33419-fbf1-446e-a471-745df2e8c4f6)
|
![after](https://github.com/user-attachments/assets/ea74a203-c269-4ce1-8a9b-f97e9a4cdc78)
|

Folder
| Before | After  |
|--------|--------|
|
![before_files](https://github.com/user-attachments/assets/8522e60b-d0eb-4b66-a4b6-c2d6ed34c15b)
|
![after_files](https://github.com/user-attachments/assets/ff94b498-b319-474c-89e5-c55f6e1c4383)
|

## 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.

<!-- 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
ksokolovskyi pushed a commit to ksokolovskyi/flutter that referenced this pull request Aug 19, 2025
…#169445)

### Respect user-data-dir flag from web-browser-flag

Currently, it's already possible to pass `web-browser-flag` when
launching Chrome, but the `user-data-dir` flag doesn't work as expected,
and there are some reasons for that.

In the implementation made in [PR
flutter#104935](flutter#104935), the
`web-browser-flag` is appended at the end of the Chrome launch
arguments.

For most scenarios, this works fine, as demonstrated in the Chrome unit
test below:

https://source.chromium.org/chromium/chromium/src/+/main:base/command_line_unittest.cc

```
TEST(CommandLineTest, MultipleSameSwitch) {
  const CommandLine::CharType* argv[] = {
      FILE_PATH_LITERAL("program"),
      FILE_PATH_LITERAL("--foo=one"),  // --foo first time
      FILE_PATH_LITERAL("-baz"),
      FILE_PATH_LITERAL("--foo=two")   // --foo second time
  };
  CommandLine cl(std::size(argv), argv);

  EXPECT_TRUE(cl.HasSwitch("foo"));
  EXPECT_TRUE(cl.HasSwitch("baz"));

  EXPECT_EQ("two", cl.GetSwitchValueASCII("foo"));
}
```
In this scenario, the parser will consider the last occurrence of a
flag.

However, this behavior does not apply to certain flags, because Chrome
processes some of them based on the first occurrence, not the last. This
is the case for `--user-data-dir`, which is parsed very early during
Chrome startup.

The proposed code checks whether `--user-data-dir` was provided via
`web-browser-flag`, and if so, it uses that value instead of the default
`%temp%\flutter_tools_chrome_device.xpto` temporary directory.

This also resolve this comment:
flutter#104935 (comment)

Example: `launch.json`
```
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "flutter",
      "request": "launch",
      "type": "dart"
    },
    {
      "name": "flutter (profile mode)",
      "request": "launch",
      "type": "dart",
      "flutterMode": "profile"
    },
    {
      "name": "flutter (release mode)",
      "request": "launch",
      "type": "dart",
      "flutterMode": "release"
    },
    {
      "name": "Flutter for web (hot reloadable)",
      "type": "dart",
      "request": "launch",
      "program": "lib/main.dart",
      "args": [
        "-d",
        "chrome",
        "--web-port=5000",
        "--web-experimental-hot-reload",
        "--web-browser-flag=--user-data-dir=D:\\_Desenv\\flutter_tests\\chrome_profile"
      ]
    }
  ]
}
```

`chrome://version`

| Before | After  |
|--------|--------|
|
![before](https://github.com/user-attachments/assets/b3f33419-fbf1-446e-a471-745df2e8c4f6)
|
![after](https://github.com/user-attachments/assets/ea74a203-c269-4ce1-8a9b-f97e9a4cdc78)
|

Folder
| Before | After  |
|--------|--------|
|
![before_files](https://github.com/user-attachments/assets/8522e60b-d0eb-4b66-a4b6-c2d6ed34c15b)
|
![after_files](https://github.com/user-attachments/assets/ff94b498-b319-474c-89e5-c55f6e1c4383)
|

## 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.

<!-- 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
mboetger pushed a commit to mboetger/flutter that referenced this pull request Sep 18, 2025
…#169445)

### Respect user-data-dir flag from web-browser-flag

Currently, it's already possible to pass `web-browser-flag` when
launching Chrome, but the `user-data-dir` flag doesn't work as expected,
and there are some reasons for that.

In the implementation made in [PR
flutter#104935](flutter#104935), the
`web-browser-flag` is appended at the end of the Chrome launch
arguments.

For most scenarios, this works fine, as demonstrated in the Chrome unit
test below:

https://source.chromium.org/chromium/chromium/src/+/main:base/command_line_unittest.cc

```
TEST(CommandLineTest, MultipleSameSwitch) {
  const CommandLine::CharType* argv[] = {
      FILE_PATH_LITERAL("program"),
      FILE_PATH_LITERAL("--foo=one"),  // --foo first time
      FILE_PATH_LITERAL("-baz"),
      FILE_PATH_LITERAL("--foo=two")   // --foo second time
  };
  CommandLine cl(std::size(argv), argv);

  EXPECT_TRUE(cl.HasSwitch("foo"));
  EXPECT_TRUE(cl.HasSwitch("baz"));

  EXPECT_EQ("two", cl.GetSwitchValueASCII("foo"));
}
```
In this scenario, the parser will consider the last occurrence of a
flag.

However, this behavior does not apply to certain flags, because Chrome
processes some of them based on the first occurrence, not the last. This
is the case for `--user-data-dir`, which is parsed very early during
Chrome startup.

The proposed code checks whether `--user-data-dir` was provided via
`web-browser-flag`, and if so, it uses that value instead of the default
`%temp%\flutter_tools_chrome_device.xpto` temporary directory.

This also resolve this comment:
flutter#104935 (comment)

Example: `launch.json`
```
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "flutter",
      "request": "launch",
      "type": "dart"
    },
    {
      "name": "flutter (profile mode)",
      "request": "launch",
      "type": "dart",
      "flutterMode": "profile"
    },
    {
      "name": "flutter (release mode)",
      "request": "launch",
      "type": "dart",
      "flutterMode": "release"
    },
    {
      "name": "Flutter for web (hot reloadable)",
      "type": "dart",
      "request": "launch",
      "program": "lib/main.dart",
      "args": [
        "-d",
        "chrome",
        "--web-port=5000",
        "--web-experimental-hot-reload",
        "--web-browser-flag=--user-data-dir=D:\\_Desenv\\flutter_tests\\chrome_profile"
      ]
    }
  ]
}
```

`chrome://version`

| Before | After  |
|--------|--------|
|
![before](https://github.com/user-attachments/assets/b3f33419-fbf1-446e-a471-745df2e8c4f6)
|
![after](https://github.com/user-attachments/assets/ea74a203-c269-4ce1-8a9b-f97e9a4cdc78)
|

Folder
| Before | After  |
|--------|--------|
|
![before_files](https://github.com/user-attachments/assets/8522e60b-d0eb-4b66-a4b6-c2d6ed34c15b)
|
![after_files](https://github.com/user-attachments/assets/ff94b498-b319-474c-89e5-c55f6e1c4383)
|

## 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.

<!-- 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
korca0220 pushed a commit to korca0220/flutter that referenced this pull request Sep 22, 2025
…#169445)

### Respect user-data-dir flag from web-browser-flag

Currently, it's already possible to pass `web-browser-flag` when
launching Chrome, but the `user-data-dir` flag doesn't work as expected,
and there are some reasons for that.

In the implementation made in [PR
flutter#104935](flutter#104935), the
`web-browser-flag` is appended at the end of the Chrome launch
arguments.

For most scenarios, this works fine, as demonstrated in the Chrome unit
test below:

https://source.chromium.org/chromium/chromium/src/+/main:base/command_line_unittest.cc

```
TEST(CommandLineTest, MultipleSameSwitch) {
  const CommandLine::CharType* argv[] = {
      FILE_PATH_LITERAL("program"),
      FILE_PATH_LITERAL("--foo=one"),  // --foo first time
      FILE_PATH_LITERAL("-baz"),
      FILE_PATH_LITERAL("--foo=two")   // --foo second time
  };
  CommandLine cl(std::size(argv), argv);

  EXPECT_TRUE(cl.HasSwitch("foo"));
  EXPECT_TRUE(cl.HasSwitch("baz"));

  EXPECT_EQ("two", cl.GetSwitchValueASCII("foo"));
}
```
In this scenario, the parser will consider the last occurrence of a
flag.

However, this behavior does not apply to certain flags, because Chrome
processes some of them based on the first occurrence, not the last. This
is the case for `--user-data-dir`, which is parsed very early during
Chrome startup.

The proposed code checks whether `--user-data-dir` was provided via
`web-browser-flag`, and if so, it uses that value instead of the default
`%temp%\flutter_tools_chrome_device.xpto` temporary directory.

This also resolve this comment:
flutter#104935 (comment)

Example: `launch.json`
```
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "flutter",
      "request": "launch",
      "type": "dart"
    },
    {
      "name": "flutter (profile mode)",
      "request": "launch",
      "type": "dart",
      "flutterMode": "profile"
    },
    {
      "name": "flutter (release mode)",
      "request": "launch",
      "type": "dart",
      "flutterMode": "release"
    },
    {
      "name": "Flutter for web (hot reloadable)",
      "type": "dart",
      "request": "launch",
      "program": "lib/main.dart",
      "args": [
        "-d",
        "chrome",
        "--web-port=5000",
        "--web-experimental-hot-reload",
        "--web-browser-flag=--user-data-dir=D:\\_Desenv\\flutter_tests\\chrome_profile"
      ]
    }
  ]
}
```

`chrome://version`

| Before | After  |
|--------|--------|
|
![before](https://github.com/user-attachments/assets/b3f33419-fbf1-446e-a471-745df2e8c4f6)
|
![after](https://github.com/user-attachments/assets/ea74a203-c269-4ce1-8a9b-f97e9a4cdc78)
|

Folder
| Before | After  |
|--------|--------|
|
![before_files](https://github.com/user-attachments/assets/8522e60b-d0eb-4b66-a4b6-c2d6ed34c15b)
|
![after_files](https://github.com/user-attachments/assets/ff94b498-b319-474c-89e5-c55f6e1c4383)
|

## 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.

<!-- 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
lucaantonelli pushed a commit to lucaantonelli/flutter that referenced this pull request Nov 21, 2025
…#169445)

### Respect user-data-dir flag from web-browser-flag

Currently, it's already possible to pass `web-browser-flag` when
launching Chrome, but the `user-data-dir` flag doesn't work as expected,
and there are some reasons for that.

In the implementation made in [PR
flutter#104935](flutter#104935), the
`web-browser-flag` is appended at the end of the Chrome launch
arguments.

For most scenarios, this works fine, as demonstrated in the Chrome unit
test below:

https://source.chromium.org/chromium/chromium/src/+/main:base/command_line_unittest.cc

```
TEST(CommandLineTest, MultipleSameSwitch) {
  const CommandLine::CharType* argv[] = {
      FILE_PATH_LITERAL("program"),
      FILE_PATH_LITERAL("--foo=one"),  // --foo first time
      FILE_PATH_LITERAL("-baz"),
      FILE_PATH_LITERAL("--foo=two")   // --foo second time
  };
  CommandLine cl(std::size(argv), argv);

  EXPECT_TRUE(cl.HasSwitch("foo"));
  EXPECT_TRUE(cl.HasSwitch("baz"));

  EXPECT_EQ("two", cl.GetSwitchValueASCII("foo"));
}
```
In this scenario, the parser will consider the last occurrence of a
flag.

However, this behavior does not apply to certain flags, because Chrome
processes some of them based on the first occurrence, not the last. This
is the case for `--user-data-dir`, which is parsed very early during
Chrome startup.

The proposed code checks whether `--user-data-dir` was provided via
`web-browser-flag`, and if so, it uses that value instead of the default
`%temp%\flutter_tools_chrome_device.xpto` temporary directory.

This also resolve this comment:
flutter#104935 (comment)

Example: `launch.json`
```
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "flutter",
      "request": "launch",
      "type": "dart"
    },
    {
      "name": "flutter (profile mode)",
      "request": "launch",
      "type": "dart",
      "flutterMode": "profile"
    },
    {
      "name": "flutter (release mode)",
      "request": "launch",
      "type": "dart",
      "flutterMode": "release"
    },
    {
      "name": "Flutter for web (hot reloadable)",
      "type": "dart",
      "request": "launch",
      "program": "lib/main.dart",
      "args": [
        "-d",
        "chrome",
        "--web-port=5000",
        "--web-experimental-hot-reload",
        "--web-browser-flag=--user-data-dir=D:\\_Desenv\\flutter_tests\\chrome_profile"
      ]
    }
  ]
}
```

`chrome://version`

| Before | After  |
|--------|--------|
|
![before](https://github.com/user-attachments/assets/b3f33419-fbf1-446e-a471-745df2e8c4f6)
|
![after](https://github.com/user-attachments/assets/ea74a203-c269-4ce1-8a9b-f97e9a4cdc78)
|

Folder
| Before | After  |
|--------|--------|
|
![before_files](https://github.com/user-attachments/assets/8522e60b-d0eb-4b66-a4b6-c2d6ed34c15b)
|
![after_files](https://github.com/user-attachments/assets/ff94b498-b319-474c-89e5-c55f6e1c4383)
|

## 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.

<!-- 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform-web Web applications specifically tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants