We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`ignoreDefaultArgs` launch parameter is broken
I'm trying to disable default launch arguments however when this parameter is set to True one of two things happen:

```
browser: Browser = chromium.launch(ignoreDefaultArgs=True)
```
will break with:
```
  File "/home/user/.local/lib/python3.8/site-packages/playwright/browser_type.py", line 66, in launch
    normalize_launch_params(params)
  File "/home/user/.local/lib/python3.8/site-packages/playwright/browser_type.py", line 140, in normalize_launch_params
    params["env"] = {name: str(value) for [name, value] in params["env"].items()}
KeyError: 'env'
``` 

I've made a hotfix patch here https://github.com/Granitosaurus/playwright-python/commit/2dc0e107719097e1105e36149a7fe8238c210e38  now the browser launches fine but timesout on `launch()` call:
```
Traceback (most recent call last):
  File "/home/user/.local/lib/python3.8/site-packages/playwright/browser_type.py", line 68, in launch
    return from_channel(await self._channel.send("launch", params))
  File "/home/user/.local/lib/python3.8/site-packages/playwright/connection.py", line 39, in send
    result = await callback.future
  File "/usr/lib/python3.8/asyncio/futures.py", line 260, in __await__
    yield self  # This tells Task to wait for completion.
  File "/usr/lib/python3.8/asyncio/tasks.py", line 349, in __wakeup
    future.result()
  File "/usr/lib/python3.8/asyncio/futures.py", line 178, in result
    raise self._exception
playwright.helper.TimeoutError: Timeout 30000ms exceeded.
=========================== logs ===========================
<launching> /home/user/.cache/ms-playwright/chromium-799411/chrome-linux/chrome 
<launched> pid=301672
[err] [301699:301699:0914/061714.839670:ERROR:sandbox_linux.cc(374)] InitializeSandbox() called with multiple threads in process gpu-process.
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `playwright/browser_type.py`
Content:
```
1 # Copyright (c) Microsoft Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 from pathlib import Path
16 from typing import Dict, List, Union
17 
18 from playwright.browser import Browser
19 from playwright.browser_context import BrowserContext
20 from playwright.connection import ChannelOwner, from_channel
21 from playwright.helper import (
22     ColorScheme,
23     Credentials,
24     Env,
25     Geolocation,
26     IntSize,
27     ProxyServer,
28     locals_to_params,
29     not_installed_error,
30 )
31 from playwright.network import serialize_headers
32 
33 
34 class BrowserType(ChannelOwner):
35     def __init__(
36         self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
37     ) -> None:
38         super().__init__(parent, type, guid, initializer)
39 
40     @property
41     def name(self) -> str:
42         return self._initializer["name"]
43 
44     @property
45     def executablePath(self) -> str:
46         return self._initializer["executablePath"]
47 
48     async def launch(
49         self,
50         executablePath: Union[str, Path] = None,
51         args: List[str] = None,
52         ignoreDefaultArgs: Union[bool, List[str]] = None,
53         handleSIGINT: bool = None,
54         handleSIGTERM: bool = None,
55         handleSIGHUP: bool = None,
56         timeout: int = None,
57         env: Env = None,
58         headless: bool = None,
59         devtools: bool = None,
60         proxy: ProxyServer = None,
61         downloadsPath: Union[str, Path] = None,
62         slowMo: int = None,
63         chromiumSandbox: bool = None,
64     ) -> Browser:
65         params = locals_to_params(locals())
66         normalize_launch_params(params)
67         try:
68             return from_channel(await self._channel.send("launch", params))
69         except Exception as e:
70             if f"{self.name}-" in str(e):
71                 raise not_installed_error(f'"{self.name}" browser was not found.')
72             raise e
73 
74     async def launchPersistentContext(
75         self,
76         userDataDir: Union[str, Path],
77         executablePath: Union[str, Path] = None,
78         args: List[str] = None,
79         ignoreDefaultArgs: Union[bool, List[str]] = None,
80         handleSIGINT: bool = None,
81         handleSIGTERM: bool = None,
82         handleSIGHUP: bool = None,
83         timeout: int = None,
84         env: Env = None,
85         headless: bool = None,
86         devtools: bool = None,
87         proxy: ProxyServer = None,
88         downloadsPath: Union[str, Path] = None,
89         slowMo: int = None,
90         viewport: IntSize = None,
91         ignoreHTTPSErrors: bool = None,
92         javaScriptEnabled: bool = None,
93         bypassCSP: bool = None,
94         userAgent: str = None,
95         locale: str = None,
96         timezoneId: str = None,
97         geolocation: Geolocation = None,
98         permissions: List[str] = None,
99         extraHTTPHeaders: Dict[str, str] = None,
100         offline: bool = None,
101         httpCredentials: Credentials = None,
102         deviceScaleFactor: int = None,
103         isMobile: bool = None,
104         hasTouch: bool = None,
105         colorScheme: ColorScheme = None,
106         acceptDownloads: bool = None,
107         chromiumSandbox: bool = None,
108     ) -> BrowserContext:
109         userDataDir = str(Path(userDataDir))
110         params = locals_to_params(locals())
111         if extraHTTPHeaders:
112             params["extraHTTPHeaders"] = serialize_headers(extraHTTPHeaders)
113         normalize_launch_params(params)
114         try:
115             return from_channel(
116                 await self._channel.send("launchPersistentContext", params)
117             )
118         except Exception as e:
119             if f"{self.name}-" in str(e):
120                 raise not_installed_error(f'"{self.name}" browser was not found.')
121             raise e
122 
123     async def connect(
124         self, wsEndpoint: str, slowMo: int = None, timeout: int = None
125     ) -> Browser:
126         return from_channel(
127             await self._channel.send("connect", locals_to_params(locals()))
128         )
129 
130 
131 def normalize_launch_params(params: Dict) -> None:
132     if "env" in params:
133         params["env"] = {name: str(value) for [name, value] in params["env"].items()}
134     if "ignoreDefaultArgs" in params:
135         if isinstance(params["ignoreDefaultArgs"], bool):
136             params["ignoreAllDefaultArgs"] = True
137             del params["ignoreDefaultArgs"]
138         params["env"] = {name: str(value) for [name, value] in params["env"].items()}
139     if "executablePath" in params:
140         params["executablePath"] = str(Path(params["executablePath"]))
141     if "downloadsPath" in params:
142         params["downloadsPath"] = str(Path(params["downloadsPath"]))
143
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/playwright/browser_type.py b/playwright/browser_type.py
--- a/playwright/browser_type.py
+++ b/playwright/browser_type.py
@@ -132,10 +132,9 @@
     if "env" in params:
         params["env"] = {name: str(value) for [name, value] in params["env"].items()}
     if "ignoreDefaultArgs" in params:
-        if isinstance(params["ignoreDefaultArgs"], bool):
+        if params["ignoreDefaultArgs"] is True:
             params["ignoreAllDefaultArgs"] = True
             del params["ignoreDefaultArgs"]
-        params["env"] = {name: str(value) for [name, value] in params["env"].items()}
     if "executablePath" in params:
         params["executablePath"] = str(Path(params["executablePath"]))
     if "downloadsPath" in params:

{"golden_diff": "diff --git a/playwright/browser_type.py b/playwright/browser_type.py\n--- a/playwright/browser_type.py\n+++ b/playwright/browser_type.py\n@@ -132,10 +132,9 @@\n     if \"env\" in params:\n         params[\"env\"] = {name: str(value) for [name, value] in params[\"env\"].items()}\n     if \"ignoreDefaultArgs\" in params:\n-        if isinstance(params[\"ignoreDefaultArgs\"], bool):\n+        if params[\"ignoreDefaultArgs\"] is True:\n             params[\"ignoreAllDefaultArgs\"] = True\n             del params[\"ignoreDefaultArgs\"]\n-        params[\"env\"] = {name: str(value) for [name, value] in params[\"env\"].items()}\n     if \"executablePath\" in params:\n         params[\"executablePath\"] = str(Path(params[\"executablePath\"]))\n     if \"downloadsPath\" in params:\n", "issue": "`ignoreDefaultArgs` launch parameter is broken\nI'm trying to disable default launch arguments however when this parameter is set to True one of two things happen:\r\n\r\n```\r\nbrowser: Browser = chromium.launch(ignoreDefaultArgs=True)\r\n```\r\nwill break with:\r\n```\r\n  File \"/home/user/.local/lib/python3.8/site-packages/playwright/browser_type.py\", line 66, in launch\r\n    normalize_launch_params(params)\r\n  File \"/home/user/.local/lib/python3.8/site-packages/playwright/browser_type.py\", line 140, in normalize_launch_params\r\n    params[\"env\"] = {name: str(value) for [name, value] in params[\"env\"].items()}\r\nKeyError: 'env'\r\n``` \r\n\r\nI've made a hotfix patch here https://github.com/Granitosaurus/playwright-python/commit/2dc0e107719097e1105e36149a7fe8238c210e38  now the browser launches fine but timesout on `launch()` call:\r\n```\r\nTraceback (most recent call last):\r\n  File \"/home/user/.local/lib/python3.8/site-packages/playwright/browser_type.py\", line 68, in launch\r\n    return from_channel(await self._channel.send(\"launch\", params))\r\n  File \"/home/user/.local/lib/python3.8/site-packages/playwright/connection.py\", line 39, in send\r\n    result = await callback.future\r\n  File \"/usr/lib/python3.8/asyncio/futures.py\", line 260, in __await__\r\n    yield self  # This tells Task to wait for completion.\r\n  File \"/usr/lib/python3.8/asyncio/tasks.py\", line 349, in __wakeup\r\n    future.result()\r\n  File \"/usr/lib/python3.8/asyncio/futures.py\", line 178, in result\r\n    raise self._exception\r\nplaywright.helper.TimeoutError: Timeout 30000ms exceeded.\r\n=========================== logs ===========================\r\n<launching> /home/user/.cache/ms-playwright/chromium-799411/chrome-linux/chrome \r\n<launched> pid=301672\r\n[err] [301699:301699:0914/061714.839670:ERROR:sandbox_linux.cc(374)] InitializeSandbox() called with multiple threads in process gpu-process.\r\n```\n", "before_files": [{"content": "# Copyright (c) Microsoft Corporation.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom pathlib import Path\nfrom typing import Dict, List, Union\n\nfrom playwright.browser import Browser\nfrom playwright.browser_context import BrowserContext\nfrom playwright.connection import ChannelOwner, from_channel\nfrom playwright.helper import (\n    ColorScheme,\n    Credentials,\n    Env,\n    Geolocation,\n    IntSize,\n    ProxyServer,\n    locals_to_params,\n    not_installed_error,\n)\nfrom playwright.network import serialize_headers\n\n\nclass BrowserType(ChannelOwner):\n    def __init__(\n        self, parent: ChannelOwner, type: str, guid: str, initializer: Dict\n    ) -> None:\n        super().__init__(parent, type, guid, initializer)\n\n    @property\n    def name(self) -> str:\n        return self._initializer[\"name\"]\n\n    @property\n    def executablePath(self) -> str:\n        return self._initializer[\"executablePath\"]\n\n    async def launch(\n        self,\n        executablePath: Union[str, Path] = None,\n        args: List[str] = None,\n        ignoreDefaultArgs: Union[bool, List[str]] = None,\n        handleSIGINT: bool = None,\n        handleSIGTERM: bool = None,\n        handleSIGHUP: bool = None,\n        timeout: int = None,\n        env: Env = None,\n        headless: bool = None,\n        devtools: bool = None,\n        proxy: ProxyServer = None,\n        downloadsPath: Union[str, Path] = None,\n        slowMo: int = None,\n        chromiumSandbox: bool = None,\n    ) -> Browser:\n        params = locals_to_params(locals())\n        normalize_launch_params(params)\n        try:\n            return from_channel(await self._channel.send(\"launch\", params))\n        except Exception as e:\n            if f\"{self.name}-\" in str(e):\n                raise not_installed_error(f'\"{self.name}\" browser was not found.')\n            raise e\n\n    async def launchPersistentContext(\n        self,\n        userDataDir: Union[str, Path],\n        executablePath: Union[str, Path] = None,\n        args: List[str] = None,\n        ignoreDefaultArgs: Union[bool, List[str]] = None,\n        handleSIGINT: bool = None,\n        handleSIGTERM: bool = None,\n        handleSIGHUP: bool = None,\n        timeout: int = None,\n        env: Env = None,\n        headless: bool = None,\n        devtools: bool = None,\n        proxy: ProxyServer = None,\n        downloadsPath: Union[str, Path] = None,\n        slowMo: int = None,\n        viewport: IntSize = None,\n        ignoreHTTPSErrors: bool = None,\n        javaScriptEnabled: bool = None,\n        bypassCSP: bool = None,\n        userAgent: str = None,\n        locale: str = None,\n        timezoneId: str = None,\n        geolocation: Geolocation = None,\n        permissions: List[str] = None,\n        extraHTTPHeaders: Dict[str, str] = None,\n        offline: bool = None,\n        httpCredentials: Credentials = None,\n        deviceScaleFactor: int = None,\n        isMobile: bool = None,\n        hasTouch: bool = None,\n        colorScheme: ColorScheme = None,\n        acceptDownloads: bool = None,\n        chromiumSandbox: bool = None,\n    ) -> BrowserContext:\n        userDataDir = str(Path(userDataDir))\n        params = locals_to_params(locals())\n        if extraHTTPHeaders:\n            params[\"extraHTTPHeaders\"] = serialize_headers(extraHTTPHeaders)\n        normalize_launch_params(params)\n        try:\n            return from_channel(\n                await self._channel.send(\"launchPersistentContext\", params)\n            )\n        except Exception as e:\n            if f\"{self.name}-\" in str(e):\n                raise not_installed_error(f'\"{self.name}\" browser was not found.')\n            raise e\n\n    async def connect(\n        self, wsEndpoint: str, slowMo: int = None, timeout: int = None\n    ) -> Browser:\n        return from_channel(\n            await self._channel.send(\"connect\", locals_to_params(locals()))\n        )\n\n\ndef normalize_launch_params(params: Dict) -> None:\n    if \"env\" in params:\n        params[\"env\"] = {name: str(value) for [name, value] in params[\"env\"].items()}\n    if \"ignoreDefaultArgs\" in params:\n        if isinstance(params[\"ignoreDefaultArgs\"], bool):\n            params[\"ignoreAllDefaultArgs\"] = True\n            del params[\"ignoreDefaultArgs\"]\n        params[\"env\"] = {name: str(value) for [name, value] in params[\"env\"].items()}\n    if \"executablePath\" in params:\n        params[\"executablePath\"] = str(Path(params[\"executablePath\"]))\n    if \"downloadsPath\" in params:\n        params[\"downloadsPath\"] = str(Path(params[\"downloadsPath\"]))\n", "path": "playwright/browser_type.py"}], "after_files": [{"content": "# Copyright (c) Microsoft Corporation.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom pathlib import Path\nfrom typing import Dict, List, Union\n\nfrom playwright.browser import Browser\nfrom playwright.browser_context import BrowserContext\nfrom playwright.connection import ChannelOwner, from_channel\nfrom playwright.helper import (\n    ColorScheme,\n    Credentials,\n    Env,\n    Geolocation,\n    IntSize,\n    ProxyServer,\n    locals_to_params,\n    not_installed_error,\n)\nfrom playwright.network import serialize_headers\n\n\nclass BrowserType(ChannelOwner):\n    def __init__(\n        self, parent: ChannelOwner, type: str, guid: str, initializer: Dict\n    ) -> None:\n        super().__init__(parent, type, guid, initializer)\n\n    @property\n    def name(self) -> str:\n        return self._initializer[\"name\"]\n\n    @property\n    def executablePath(self) -> str:\n        return self._initializer[\"executablePath\"]\n\n    async def launch(\n        self,\n        executablePath: Union[str, Path] = None,\n        args: List[str] = None,\n        ignoreDefaultArgs: Union[bool, List[str]] = None,\n        handleSIGINT: bool = None,\n        handleSIGTERM: bool = None,\n        handleSIGHUP: bool = None,\n        timeout: int = None,\n        env: Env = None,\n        headless: bool = None,\n        devtools: bool = None,\n        proxy: ProxyServer = None,\n        downloadsPath: Union[str, Path] = None,\n        slowMo: int = None,\n        chromiumSandbox: bool = None,\n    ) -> Browser:\n        params = locals_to_params(locals())\n        normalize_launch_params(params)\n        try:\n            return from_channel(await self._channel.send(\"launch\", params))\n        except Exception as e:\n            if f\"{self.name}-\" in str(e):\n                raise not_installed_error(f'\"{self.name}\" browser was not found.')\n            raise e\n\n    async def launchPersistentContext(\n        self,\n        userDataDir: Union[str, Path],\n        executablePath: Union[str, Path] = None,\n        args: List[str] = None,\n        ignoreDefaultArgs: Union[bool, List[str]] = None,\n        handleSIGINT: bool = None,\n        handleSIGTERM: bool = None,\n        handleSIGHUP: bool = None,\n        timeout: int = None,\n        env: Env = None,\n        headless: bool = None,\n        devtools: bool = None,\n        proxy: ProxyServer = None,\n        downloadsPath: Union[str, Path] = None,\n        slowMo: int = None,\n        viewport: IntSize = None,\n        ignoreHTTPSErrors: bool = None,\n        javaScriptEnabled: bool = None,\n        bypassCSP: bool = None,\n        userAgent: str = None,\n        locale: str = None,\n        timezoneId: str = None,\n        geolocation: Geolocation = None,\n        permissions: List[str] = None,\n        extraHTTPHeaders: Dict[str, str] = None,\n        offline: bool = None,\n        httpCredentials: Credentials = None,\n        deviceScaleFactor: int = None,\n        isMobile: bool = None,\n        hasTouch: bool = None,\n        colorScheme: ColorScheme = None,\n        acceptDownloads: bool = None,\n        chromiumSandbox: bool = None,\n    ) -> BrowserContext:\n        userDataDir = str(Path(userDataDir))\n        params = locals_to_params(locals())\n        if extraHTTPHeaders:\n            params[\"extraHTTPHeaders\"] = serialize_headers(extraHTTPHeaders)\n        normalize_launch_params(params)\n        try:\n            return from_channel(\n                await self._channel.send(\"launchPersistentContext\", params)\n            )\n        except Exception as e:\n            if f\"{self.name}-\" in str(e):\n                raise not_installed_error(f'\"{self.name}\" browser was not found.')\n            raise e\n\n    async def connect(\n        self, wsEndpoint: str, slowMo: int = None, timeout: int = None\n    ) -> Browser:\n        return from_channel(\n            await self._channel.send(\"connect\", locals_to_params(locals()))\n        )\n\n\ndef normalize_launch_params(params: Dict) -> None:\n    if \"env\" in params:\n        params[\"env\"] = {name: str(value) for [name, value] in params[\"env\"].items()}\n    if \"ignoreDefaultArgs\" in params:\n        if params[\"ignoreDefaultArgs\"] is True:\n            params[\"ignoreAllDefaultArgs\"] = True\n            del params[\"ignoreDefaultArgs\"]\n    if \"executablePath\" in params:\n        params[\"executablePath\"] = str(Path(params[\"executablePath\"]))\n    if \"downloadsPath\" in params:\n        params[\"downloadsPath\"] = str(Path(params[\"downloadsPath\"]))\n", "path": "playwright/browser_type.py"}]}