Skip to content

Commit 2726a24

Browse files
committed
chrome: check for binary in known locations
1 parent 660ef53 commit 2726a24

1 file changed

Lines changed: 76 additions & 10 deletions

File tree

html2print/html2print.py

Lines changed: 76 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import os.path
66
import platform
77
import re
8+
import shutil
89
import subprocess
910
import sys
1011
import zipfile
@@ -39,7 +40,8 @@
3940

4041

4142
class ChromeDriverManager:
42-
def get_chrome_driver(self, path_to_cache_dir: str):
43+
def get_chrome_driver(self, path_to_cache_dir: str) -> str:
44+
"""Return path to downloaded chromedriver."""
4345
chrome_version = self.get_chrome_version()
4446

4547
# If Web Driver Manager cannot detect Chrome, it returns None.
@@ -102,15 +104,69 @@ def get_chrome_driver(self, path_to_cache_dir: str):
102104

103105
return path_to_downloaded_chrome_driver
104106

107+
@staticmethod
108+
def find_chrome() -> str:
109+
"""Find path to Chrome browser across Windows, macOS, and Linux."""
110+
111+
os_name = platform.system()
112+
if os_name == "Windows":
113+
# Check Windows standard locations for chrome and chromium
114+
userprofile = os.environ.get("LOCALAPPDATA", r"C:\Users\Default\AppData\Local")
115+
locations = [
116+
os.path.join(os.environ.get("PROGRAMFILES", r"C:\Program Files"), "Google", "Chrome", "Application", "chrome.exe"),
117+
os.path.join(os.environ.get("PROGRAMFILES(X86)", r"C:\Program Files (x86)"), "Google", "Chrome", "Application", "chrome.exe"),
118+
os.path.join(os.environ.get("PROGRAMFILES", r"C:\Program Files"), "Chromium", "Application", "chrome.exe"),
119+
os.path.join(os.environ.get("PROGRAMFILES(X86)", r"C:\Program Files (x86)"), "Chromium", "Application", "chrome.exe"),
120+
os.path.join(userprofile, "Chromium","Application","chrome.exe"),
121+
os.path.join(userprofile, "Chromium","Application","chromium.exe"),
122+
]
123+
elif os_name == "Darwin":
124+
# macOS standard locations
125+
locations = [
126+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
127+
os.path.expanduser("~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome")
128+
]
129+
elif os_name == "Linux":
130+
# Linux: check if chrome or chromium is in PATH
131+
chrome_path = shutil.which("google-chrome") or shutil.which("chrome") or shutil.which("chromium") or shutil.which("chromium-browser")
132+
if chrome_path:
133+
return chrome_path
134+
locations = [
135+
"/usr/bin/google-chrome",
136+
"/usr/local/bin/google-chrome",
137+
"/usr/bin/chromium-browser",
138+
"/snap/bin/chromium",
139+
]
140+
else:
141+
raise Exception(f"Unsupported platform: {sys.platform}")
142+
143+
for path in locations:
144+
if path and os.path.exists(path):
145+
return path
146+
147+
print("html2print: Chrome executable was not found in any usual location - falling back to webdriver's autodetection") # noqa: T201
148+
return ""
149+
105150
@staticmethod
106151
def _download_chromedriver(
107152
chrome_major_version,
108153
os_type: str,
109154
path_to_driver_cache_dir,
110155
path_to_cached_chrome_driver,
111-
):
156+
) -> str:
112157
url = "https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json"
113-
response = ChromeDriverManager.send_http_get_request(url).json()
158+
response = ChromeDriverManager.send_http_get_request(url)
159+
if response is None:
160+
raise RuntimeError(
161+
"Could not download known-good-versions-with-downloads.json"
162+
)
163+
164+
response = response.json()
165+
if response is None:
166+
raise RuntimeError(
167+
"Could not parse known-good-versions-with-downloads.json"
168+
)
169+
assert isinstance(response, dict)
114170

115171
matching_versions = [
116172
item
@@ -143,6 +199,11 @@ def _download_chromedriver(
143199
)
144200
response = ChromeDriverManager.send_http_get_request(driver_url)
145201

202+
if response is None:
203+
raise Exception(
204+
f"Could not download ChromeDriver from {driver_url}"
205+
)
206+
146207
Path(path_to_driver_cache_dir).mkdir(parents=True, exist_ok=True)
147208
zip_path = os.path.join(path_to_driver_cache_dir, "chromedriver.zip")
148209
print( # noqa: T201
@@ -160,7 +221,7 @@ def _download_chromedriver(
160221
return path_to_cached_chrome_driver
161222

162223
@staticmethod
163-
def send_http_get_request(url, params=None, **kwargs) -> Response:
224+
def send_http_get_request(url, params=None, **kwargs) -> Optional[Response]:
164225
last_error: Optional[Exception] = None
165226
for attempt in range(1, 4):
166227
print( # noqa: T201
@@ -180,9 +241,10 @@ def send_http_get_request(url, params=None, **kwargs) -> Response:
180241
f"html2print: "
181242
f"failed to get response for URL: {url} with error: {last_error}"
182243
)
244+
return None
183245

184246
@staticmethod
185-
def get_chrome_version():
247+
def get_chrome_version() -> str:
186248
# Special case: GitHub Actions macOS CI machines have both
187249
# Google Chrome for Testing and normal Google Chrome installed, and
188250
# sometimes their versions are of different major version families.
@@ -312,21 +374,25 @@ def create_webdriver(
312374
) -> webdriver.Chrome:
313375
print("html2print: creating ChromeDriver service.", flush=True) # noqa: T201
314376
if chromedriver is None:
315-
path_to_chrome = ChromeDriverManager().get_chrome_driver(
377+
path_to_chromedriver = ChromeDriverManager().get_chrome_driver(
316378
path_to_cache_dir
317379
)
318380
else:
319-
path_to_chrome = chromedriver
320-
print(f"html2print: ChromeDriver available at path: {path_to_chrome}") # noqa: T201
381+
path_to_chromedriver = chromedriver
382+
print(f"html2print: ChromeDriver available at path: {path_to_chromedriver}") # noqa: T201
321383

322384
if debug:
323385
service = Service(
324-
path_to_chrome, log_output=PATH_TO_CHROME_DRIVER_DEBUG_LOG
386+
path_to_chromedriver, log_output=PATH_TO_CHROME_DRIVER_DEBUG_LOG
325387
)
326388
else:
327-
service = Service(path_to_chrome)
389+
service = Service(path_to_chromedriver)
390+
391+
path_to_chrome = ChromeDriverManager.find_chrome()
392+
print(f"html2print: Chrome available at path: {path_to_chrome}") # noqa: T201
328393

329394
webdriver_options = Options()
395+
webdriver_options.binary_location = path_to_chrome
330396
webdriver_options.add_argument("start-maximized")
331397
webdriver_options.add_argument("disable-infobars")
332398
# Doesn't seem to be needed.

0 commit comments

Comments
 (0)