Repository: robocorp/rpaframework

Issue:
RPA.Browser.Selenium fails in cloud workers if download=TRUE
2023-05-08 12:47:36:  ==============================================================================
2023-05-08 12:47:36:  Tasks                                                                         
2023-05-08 12:47:36:  ==============================================================================
2023-05-08 12:47:46:  Minimal task                                                          | FAIL |
2023-05-08 12:47:46:  BrowserNotFoundError: Failed to start a browser:
2023-05-08 12:47:46:  - Chrome: Message: session not created: This version of ChromeDriver only supports Chrome version 113
2023-05-08 12:47:46:  Current browser version is 105.0.5195.102 with binary path /usr/bin/chromium-browser
2023-05-08 12:47:46:  Stacktrace:
2023-05-08 12:47:46:  #0 0x55e4a398c133 <unknown>
2023-05-08 12:47:46:  #1 0x55e4a36c0966 <unknown>
2023-05-08 12:47:46:  #2 0x55e4a36ee5ec <unknown>
2023-05-08 12:47:46:  #3 0x55e4a36e98da <unknown>
2023-05-08 12:47:46:  #4 0x55e4a36e607b <unknown>
2023-05-08 12:47:46:  #5 0x55e4a37259ad <unknown>
2023-05-08 12:47:46:  #6 0x55e4a372518f <unknown>
2023-05-08 12:47:46:  #7 0x55e4a371c9a3 <unknown>
2023-05-08 12:47:46:  #8 0x55e4a36f146a <unknown>
2023-05-08 12:47:46:  #9 0x55e4a36f255e <unknown>
2023-05-08 12:47:46:  #10 0x55e4a394bcae <unknown>
2023-05-08 12:47:46:  #11 0x55e4a394f8fe <unknown>
2023-05-08 12:47:46:  #12 0x55e4a3958f20 <unknown>
2023-05-08 12:47:46:  #13 0x55e4a3950923 <unknown>
2023-05-08 12:47:46:      [ Message content over the limit has been removed. ]
2023-05-08 12:47:46:  #0 0x55c657673273 <unknown>
2023-05-08 12:47:46:  #1 0x55c65738e7a1 <unknown>
2023-05-08 12:47:46:  #2 0x55c6573babeb <unknown>
2023-05-08 12:47:46:  #3 0x55c6573b5fdc <unknown>
2023-05-08 12:47:46:  #4 0x55c6573f7695 <unknown>
2023-05-08 12:47:46:  #5 0x55c6573ee723 <unknown>
2023-05-08 12:47:46:  #6 0x55c6573c17d1 <unknown>
2023-05-08 12:47:46:  #7 0x55c6573c2a0e <unknown>
2023-05-08 12:47:46:  #8 0x55c657641390 <unknown>
2023-05-08 12:47:46:  #9 0x55c657643a9e <unknown>
2023-05-08 12:47:46:  #10 0x55c6576434b9 <unknown>
2023-05-08 12:47:46:  #11 0x55c6576441a5 <unknown>
2023-05-08 12:47:46:  #12 0x55c65764ae0b <unknown>
2023-05-08 12:47:46:  #13 0x55c65764456e <unknown>
2023-05-08 12:47:46:  #14 0x55c657625373 <unknown>
2023-05-08 12:47:46:  #15 0x55c65765fc58 <unknown>
2023-05-08 12:47:46:  #16 0x55c65765fd94 <unknown>
2023-05-08 12:47:46:  #17 0x55c65766d5c6 <unknown>
2023-05-08 12:47:46:  #18 0x7f8de95b36db start_thread
2023-05-08 12:47:46:  ------------------------------------------------------------------------------
2023-05-08 12:47:46:  Tasks                                                                 | FAIL |
2023-05-08 12:47:46:  1 task, 0 passed, 1 failed
2023-05-08 12:47:46:  ==============================================================================


Discussion:
According to these [versions](https://chromedriver.chromium.org/downloads) our **core** web-driver downloader should detect the right version and download it.
<img width="410" alt="Screenshot 2023-05-10 at 16 05 34" src="https://github.com/robocorp/rpaframework/assets/709053/aecb8b75-d04a-474d-b5f4-d6727084edb4">

We can test the behaviour by evaluating in a robot ran in the cloud code like:
```
from webdriver_manager.chrome import ChromeDriverManager as CDM; print(CDM().driver.get_driver_download_url())
```
which should print an URL like:
```
https://chromedriver.storage.googleapis.com/105.0.5195.52/chromedriver_....zip
```
I confirm the issue, which looks to come from our outdated Chrome browser found in the Cloud Worker.

- Context: When the default `chromedriver` available in PATH is used everything works fine, but if a suitable web-driver is attempted to be downloaded, then we run into problems.
- Problem: There's no suitable web-driver found to be downloaded for Chrome version **105.0.5195.102**: `Incompatible release of chromedriver (version 105.0.5195.102) detected in PATH: /usr/bin/chromedriver` 
<img width="492" alt="Screenshot 2023-05-26 at 09 43 12" src="https://github.com/robocorp/rpaframework/assets/709053/74c90b01-a167-4c7b-8cb1-59ade16233e3">

- Result: Both our web-driver **core** manager and the Selenium built-in Manager fail to download a version that will satisfy the current version of the Chrome browser, thus it will fail to start. (see [Process](https://cloud.robocorp.com/orgrobocorp/solutiondemos/processes/7f0f231b-b3c6-4eb4-b27a-36844dcabd4c))
- Solution: Patching our own web-driver **core** manager in such a way it will try to download the closest version found. (instead of the latest in case of mismatch)

@kariharju Do you think we can do ourselves a favor and provide the latest Chrome (or a version that has a web-driver [available](https://chromedriver.chromium.org/downloads))? (the current browser dates back from **Aug 30, 2022**)

Resolving patch:
diff --git a/packages/core/src/RPA/core/webdriver.py b/packages/core/src/RPA/core/webdriver.py
--- a/packages/core/src/RPA/core/webdriver.py
+++ b/packages/core/src/RPA/core/webdriver.py
@@ -1,4 +1,5 @@
 import contextlib
+import functools
 import logging
 import os
 import platform
@@ -15,6 +16,7 @@
 from webdriver_manager.core.download_manager import WDMDownloadManager
 from webdriver_manager.core.http import WDMHttpClient
 from webdriver_manager.core.manager import DriverManager
+from webdriver_manager.core.utils import ChromeType, get_browser_version_from_os
 from webdriver_manager.core.utils import os_name as get_os_name
 from webdriver_manager.firefox import GeckoDriverManager
 from webdriver_manager.microsoft import EdgeChromiumDriverManager, IEDriverManager
@@ -109,6 +111,14 @@ def start(browser: str, service: Optional[Service] = None, **options) -> WebDriv
     return driver
 
 
+def _is_chromium() -> bool:
+    """Detects if Chromium is used instead of Chrome no matter the platform."""
+    is_browser = lambda browser_type: bool(  # noqa: E731
+        get_browser_version_from_os(browser_type)
+    )
+    return not is_browser(ChromeType.GOOGLE) and is_browser(ChromeType.CHROMIUM)
+
+
 def _to_manager(browser: str, *, root: Path) -> DriverManager:
     browser = browser.strip()
     manager_factory = AVAILABLE_DRIVERS.get(browser.lower())
@@ -118,6 +128,10 @@ def _to_manager(browser: str, *, root: Path) -> DriverManager:
             f" (choose from: {', '.join(SUPPORTED_BROWSERS.values())})"
         )
 
+    if manager_factory == ChromeDriverManager and _is_chromium():
+        manager_factory = functools.partial(
+            manager_factory, chrome_type=ChromeType.CHROMIUM
+        )
     downloader = Downloader()
     download_manager = WDMDownloadManager(downloader)
     manager = manager_factory(path=str(root), download_manager=download_manager)


Test patch: