Skip to content

Commit

Permalink
feat: add browser detection for linux
Browse files Browse the repository at this point in the history
use the webbrowser python builtin module.

Signed-off-by: Lionel Hubaut <lionel.hubaut@tessares.net>
  • Loading branch information
lion24 committed Apr 11, 2024
1 parent 29b6618 commit 9e00c0c
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 28 deletions.
52 changes: 39 additions & 13 deletions src/speed_sleuth/browser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ def get_browser() -> BrowserInterface:
from speed_sleuth.browser.ms_edge import MSEdgeBrowser

return MSEdgeBrowser(path)
case "google-chrome":
from speed_sleuth.browser.chromium import ChromiumBrower

Check warning on line 94 in src/speed_sleuth/browser/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/speed_sleuth/browser/__init__.py#L93-L94

Added lines #L93 - L94 were not covered by tests

return ChromiumBrower(path)

Check warning on line 96 in src/speed_sleuth/browser/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/speed_sleuth/browser/__init__.py#L96

Added line #L96 was not covered by tests
case _:
raise ValueError(
f"No supported browser found for {default_browser}"
Expand All @@ -114,41 +118,63 @@ def detect_default_browser() -> tuple[str, str]:
supported by this method.
"""
browser = "chrome"
path = "open" # Fall back to default "open"
# selenium is able to cope without.
osPlatform = platform.system()

match osPlatform:
case "Windows":
case "Windows": # TODO FIX THIS MESS and use webbrowser
browser = ""
path = None

Check warning on line 127 in src/speed_sleuth/browser/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/speed_sleuth/browser/__init__.py#L126-L127

Added lines #L126 - L127 were not covered by tests
try:
from winreg import (
HKEY_CLASSES_ROOT,
HKEY_CURRENT_USER,
OpenKey,
QueryValueEx,
)

with OpenKey(
reg_key = OpenKey(

Check warning on line 135 in src/speed_sleuth/browser/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/speed_sleuth/browser/__init__.py#L135

Added line #L135 was not covered by tests
HKEY_CURRENT_USER,
r"SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice", # noqa: E501
) as reg_key:
browser = QueryValueEx(reg_key, "ProgId")[0]
)
browser = reg_key.QueryValueEx(reg_key, "ProgId")[0]
reg_key.close()

Check warning on line 140 in src/speed_sleuth/browser/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/speed_sleuth/browser/__init__.py#L139-L140

Added lines #L139 - L140 were not covered by tests

with OpenKey(
reg_key = OpenKey(

Check warning on line 142 in src/speed_sleuth/browser/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/speed_sleuth/browser/__init__.py#L142

Added line #L142 was not covered by tests
HKEY_CLASSES_ROOT,
r"{}\shell\open\command".format(browser),
) as reg_key:
browser_path_tuple = QueryValueEx(reg_key, None)
path = browser_path_tuple[0].split('"')[1]
)
browser_path_tuple = reg_key.QueryValueEx(reg_key, None)
path = browser_path_tuple[0].split('"')[1]
reg_key.close()

Check warning on line 148 in src/speed_sleuth/browser/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/speed_sleuth/browser/__init__.py#L146-L148

Added lines #L146 - L148 were not covered by tests

return browser, path
except ImportError:
pass

Check warning on line 152 in src/speed_sleuth/browser/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/speed_sleuth/browser/__init__.py#L150-L152

Added lines #L150 - L152 were not covered by tests
except Exception as e:
print(
"Failed to look up default browser in system registry: ", # noqa: E501
e,
)

case "Linux":
try:
import gc
import webbrowser

browser_instance = webbrowser.get()
browser = browser_instance.basename
browser_instance = (
None # Manually free to avoid calling GC
)
del browser_instance
gc.collect()
print(f"browser: {browser}")

return browser, None
except ImportError as e:
print("Unable to import webbrowser library: ", str(e))

Check warning on line 175 in src/speed_sleuth/browser/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/speed_sleuth/browser/__init__.py#L174-L175

Added lines #L174 - L175 were not covered by tests

case _:
raise OsNotFoundException(
f"Your OS {osPlatform} is not yet implement."
)

return browser, path
17 changes: 3 additions & 14 deletions src/speed_sleuth/browser/chromium.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ class that implements the BrowserInterface for the Chrome browser,

from speed_sleuth.browser import BrowserInterface

BINARY_PATH = "/snap/chromium/2805/usr/lib/chromium-browser/chrome"


@BrowserInterface.register
class ChromiumBrower:
Expand All @@ -44,11 +42,7 @@ class ChromiumBrower:
"""

def __init__(self, binary_path=None):
# Workaround to keep backward compatibility
if binary_path:
self.binary_path = binary_path
else:
self.binary_path = BINARY_PATH
self.binary_path = binary_path

def load_driver(self) -> WebDriver:
"""Initializes and returns a Selenium WebDriver instance configured for
Expand Down Expand Up @@ -81,17 +75,12 @@ def load_driver(self) -> WebDriver:
"""
chrome_service = service.ChromiumService()
chrome_options = options.ChromiumOptions()
chrome_options.binary_location = self.binary_path
if self.binary_path:
chrome_options.binary_location = self.binary_path
# options.add_argument('--headless')
chrome_options.add_argument("--window-size=1400x900")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--lang=en_US")
return webdriver.Chrome(service=chrome_service, options=chrome_options)
# As using selenium api > 2.x, this call should block until
# readyState is hit.


if __name__ == "__main__":
import doctest

doctest.testmod()
3 changes: 2 additions & 1 deletion src/speed_sleuth/browser/ms_edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ def load_driver(self) -> WebDriver:
edge_service = service.Service()
edge_options = options.Options()

edge_options.binary_location = self.binary_path
if self.binary_path:
edge_options.binary_location = self.binary_path
edge_options.add_argument("--window-size=1400x900")
edge_options.add_argument("--disable-gpu")
edge_options.add_argument("--lang=en_US")
Expand Down
42 changes: 42 additions & 0 deletions tests/unit/test_browser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
""" TestBrowser: Test the generic methods that applied to all browsers
This also target the helpers defined in browser/__init__.py like the browser
factory for example
"""

from unittest.mock import MagicMock, patch

import pytest

from speed_sleuth.browser import BrowserFactory


class TestBrowser:
@pytest.mark.parametrize(
"os_platform, browser_name",
[("Linux", "google-chrome"), ("Windows", "MSEdgeHTM")],
)
def test_detect_default_browser(self, os_platform, browser_name):
with patch("platform.system") as mock_system:
mock_system.return_value = os_platform

if os_platform == "Windows":
with patch(
"speed_sleuth.browser.BrowserFactory.detect_default_browser" # noqa: E501
) as mock_query:
mock_query.return_value = (browser_name, None)

name, path = BrowserFactory.detect_default_browser()
assert name == browser_name
assert path is None

else:
with patch("webbrowser.get") as mock_get:
browser_instance = MagicMock()
mock_get.return_value = browser_instance

browser_instance.basename = browser_name

name, path = BrowserFactory.detect_default_browser()
assert name == browser_name
assert path is None

0 comments on commit 9e00c0c

Please sign in to comment.