@@ -118,12 +118,20 @@ def __str__(self) -> str:
118118
119119class ChromeDriverManager :
120120 def get_chrome_driver (
121- self , path_to_cache_dir : str , verify_ssl : bool = True
121+ self ,
122+ path_to_cache_dir : str ,
123+ verify_ssl : bool = True ,
124+ chrome_binary : Optional [str ] = None ,
122125 ) -> str :
123- chrome_version : Optional [str ] = self .get_chrome_version ()
126+ chrome_version : Optional [str ] = self .get_chrome_version (chrome_binary )
124127
125128 # If Web Driver Manager cannot detect Chrome, it returns None.
126129 if chrome_version is None :
130+ if chrome_binary is not None :
131+ raise HPDError (
132+ f"Could not determine the Chrome version from --chrome-binary: { chrome_binary !r} ." ,
133+ exit_code = HPDExitCode .COULD_NOT_FIND_CHROME ,
134+ )
127135 raise HPDError (
128136 "Web Driver Manager could not detect an existing Chrome installation." ,
129137 exit_code = HPDExitCode .COULD_NOT_FIND_CHROME ,
@@ -296,7 +304,30 @@ def send_http_get_request(url: str, verify_ssl: bool = True) -> Response:
296304 ) from last_error
297305
298306 @staticmethod
299- def get_chrome_version () -> Optional [str ]:
307+ def _probe_chrome_version (chrome_binary : str ) -> str :
308+ # Shared by the macOS special case below and --chrome-binary.
309+ version_output = subprocess .run (
310+ [chrome_binary , "--version" ],
311+ capture_output = True ,
312+ text = True ,
313+ check = True ,
314+ )
315+ chrome_version = version_output .stdout .strip ()
316+ match = re .search (r"\d+(\.\d+)+" , chrome_version )
317+ if not match :
318+ raise RuntimeError ("Cannot extract the version part using regex." )
319+ return match .group (0 )
320+
321+ @staticmethod
322+ def get_chrome_version (
323+ chrome_binary : Optional [str ] = None ,
324+ ) -> Optional [str ]:
325+ if chrome_binary is not None :
326+ try :
327+ return ChromeDriverManager ._probe_chrome_version (chrome_binary )
328+ except (OSError , subprocess .CalledProcessError , RuntimeError ):
329+ return None
330+
300331 # Special case: GitHub Actions macOS CI machines have both
301332 # Google Chrome for Testing and normal Google Chrome installed, and
302333 # sometimes their versions are of different major version families.
@@ -311,20 +342,9 @@ def get_chrome_version() -> Optional[str]:
311342 "a normal Chrome available."
312343 )
313344
314- version_output = subprocess .run (
315- [chrome_path , "--version" ],
316- capture_output = True ,
317- text = True ,
318- check = True ,
345+ chrome_version = ChromeDriverManager ._probe_chrome_version (
346+ chrome_path
319347 )
320- chrome_version = version_output .stdout .strip ()
321- match = re .search (r"\d+(\.\d+)+" , chrome_version )
322- if not match :
323- raise RuntimeError (
324- "Cannot extract the version part using regex."
325- )
326-
327- chrome_version = match .group (0 )
328348
329349 print ( # noqa: T201
330350 f"html2pdf4doc: Google Chrome for Testing Version: { chrome_version } "
@@ -462,13 +482,16 @@ def create_webdriver(
462482 page_load_timeout : int ,
463483 verify_ssl : bool = True ,
464484 debug : bool = False ,
485+ chrome_binary : Optional [str ] = None ,
465486) -> webdriver .Chrome :
466487 print ("html2pdf4doc: Creating ChromeDriver service." , flush = True ) # noqa: T201
467488
468489 path_to_chrome_driver : str
469490 if chromedriver_argument is None :
470491 path_to_chrome_driver = chrome_driver_manager .get_chrome_driver (
471- path_to_cache_dir , verify_ssl = verify_ssl
492+ path_to_cache_dir ,
493+ verify_ssl = verify_ssl ,
494+ chrome_binary = chrome_binary ,
472495 )
473496 else :
474497 path_to_chrome_driver = chromedriver_argument
@@ -484,6 +507,8 @@ def create_webdriver(
484507 service = Service (path_to_chrome_driver )
485508
486509 webdriver_options = Options ()
510+ if chrome_binary is not None :
511+ webdriver_options .binary_location = chrome_binary
487512 webdriver_options .add_argument ("start-maximized" )
488513 webdriver_options .add_argument ("disable-infobars" )
489514 # Doesn't seem to be needed.
@@ -591,6 +616,11 @@ def _main() -> None:
591616 "By default SSL certificate verification is enabled."
592617 ),
593618 )
619+ command_parser_get_driver .add_argument (
620+ "--chrome-binary" ,
621+ type = str ,
622+ help = "Optional path to a Chrome/Chromium binary. Falls back to $HTML2PDF4DOC_CHROME_BINARY, then auto-detection." ,
623+ )
594624
595625 #
596626 # Print command.
@@ -649,6 +679,11 @@ def _main() -> None:
649679 "message is printed and the execution continues."
650680 ),
651681 )
682+ command_parser_print .add_argument (
683+ "--chrome-binary" ,
684+ type = str ,
685+ help = "Optional path to a Chrome/Chromium binary. Falls back to $HTML2PDF4DOC_CHROME_BINARY, then auto-detection." ,
686+ )
652687 command_parser_print .add_argument (
653688 "--strict2" ,
654689 action = "store_true" ,
@@ -665,6 +700,10 @@ def _main() -> None:
665700
666701 args = parser .parse_args ()
667702
703+ chrome_binary : Optional [str ] = args .chrome_binary or os .environ .get (
704+ "HTML2PDF4DOC_CHROME_BINARY"
705+ )
706+
668707 chrome_driver_manager = ChromeDriverManager ()
669708
670709 path_to_cache_dir : str
@@ -676,6 +715,7 @@ def _main() -> None:
676715 path_to_chrome = chrome_driver_manager .get_chrome_driver (
677716 path_to_cache_dir ,
678717 verify_ssl = not args .disable_ssl_check ,
718+ chrome_binary = chrome_binary ,
679719 )
680720 print (f"html2pdf4doc: ChromeDriver available at path: { path_to_chrome } " ) # noqa: T201
681721 sys .exit (0 )
@@ -695,6 +735,7 @@ def _main() -> None:
695735 page_load_timeout ,
696736 verify_ssl = not args .disable_ssl_check ,
697737 debug = args .debug ,
738+ chrome_binary = chrome_binary ,
698739 )
699740
700741 @atexit .register
0 commit comments