11import os
22import re
33import sys
4+ import threading
5+ import time
46import warnings
57from selenium import webdriver
68from selenium .common .exceptions import WebDriverException
79from selenium .webdriver .common .desired_capabilities import DesiredCapabilities
810from seleniumbase .config import proxy_list
911from seleniumbase .core import download_helper
12+ from seleniumbase .core import proxy_helper
1013from seleniumbase .fixtures import constants
1114from seleniumbase .fixtures import page_utils
1215from seleniumbase import drivers # webdriver storage folder for SeleniumBase
1316DRIVER_DIR = os .path .dirname (os .path .realpath (drivers .__file__ ))
17+ PROXY_ZIP_PATH = proxy_helper .PROXY_ZIP_PATH
1418PLATFORM = sys .platform
1519IS_WINDOWS = False
1620LOCAL_CHROMEDRIVER = None
@@ -49,7 +53,31 @@ def make_driver_executable_if_not(driver_path):
4953 make_executable (driver_path )
5054
5155
52- def _set_chrome_options (downloads_path , proxy_string ):
56+ def _add_chrome_proxy_extension (
57+ chrome_options , proxy_string , proxy_user , proxy_pass ):
58+ """ Implementation of https://stackoverflow.com/a/35293284 for
59+ https://stackoverflow.com/questions/12848327/
60+ (Run Selenium on a proxy server that requires authentication.)
61+ The retry_on_exception is only needed for multithreaded runs
62+ because proxy.zip is a common file shared between all tests
63+ in a single run. """
64+ if not "" .join (sys .argv ) == "-c" :
65+ # Single-threaded
66+ proxy_helper .create_proxy_zip (proxy_string , proxy_user , proxy_pass )
67+ else :
68+ # Pytest multi-threaded test
69+ lock = threading .Lock ()
70+ with lock :
71+ if not os .path .exists (PROXY_ZIP_PATH ):
72+ proxy_helper .create_proxy_zip (
73+ proxy_string , proxy_user , proxy_pass )
74+ time .sleep (0.3 )
75+ chrome_options .add_extension (PROXY_ZIP_PATH )
76+ return chrome_options
77+
78+
79+ def _set_chrome_options (
80+ downloads_path , proxy_string , proxy_auth , proxy_user , proxy_pass ):
5381 chrome_options = webdriver .ChromeOptions ()
5482 prefs = {
5583 "download.default_directory" : downloads_path ,
@@ -71,6 +99,10 @@ def _set_chrome_options(downloads_path, proxy_string):
7199 chrome_options .add_argument ("--disable-translate" )
72100 chrome_options .add_argument ("--disable-web-security" )
73101 if proxy_string :
102+ if proxy_auth :
103+ chrome_options = _add_chrome_proxy_extension (
104+ chrome_options , proxy_string , proxy_user , proxy_pass )
105+ chrome_options .add_extension (DRIVER_DIR + "/proxy.zip" )
74106 chrome_options .add_argument ('--proxy-server=%s' % proxy_string )
75107 if "win32" in sys .platform or "win64" in sys .platform :
76108 chrome_options .add_argument ("--log-level=3" )
@@ -155,22 +187,55 @@ def validate_proxy_string(proxy_string):
155187
156188def get_driver (browser_name , headless = False , use_grid = False ,
157189 servername = 'localhost' , port = 4444 , proxy_string = None ):
190+ proxy_auth = False
191+ proxy_user = None
192+ proxy_pass = None
158193 if proxy_string :
194+ username_and_password = None
195+ if "@" in proxy_string :
196+ # Format => username:password@hostname:port
197+ try :
198+ username_and_password = proxy_string .split ('@' )[0 ]
199+ proxy_string = proxy_string .split ('@' )[1 ]
200+ proxy_user = username_and_password .split (':' )[0 ]
201+ proxy_pass = username_and_password .split (':' )[1 ]
202+ except Exception :
203+ raise Exception (
204+ 'The format for using a proxy server with authentication '
205+ 'is: "username:password@hostname:port". If using a proxy '
206+ 'server without auth, the format is: "hostname:port".' )
207+ if browser_name != constants .Browser .GOOGLE_CHROME :
208+ raise Exception (
209+ "Chrome is required when using a proxy server that has "
210+ "authentication! (If using a proxy server without auth, "
211+ "either Chrome or Firefox may be used.)" )
159212 proxy_string = validate_proxy_string (proxy_string )
213+ if proxy_string and proxy_user and proxy_pass :
214+ if not os .path .exists (PROXY_ZIP_PATH ):
215+ proxy_helper .create_proxy_zip (
216+ proxy_string , proxy_user , proxy_pass )
217+ proxy_auth = True
160218 if use_grid :
161219 return get_remote_driver (
162- browser_name , headless , servername , port , proxy_string )
220+ browser_name , headless , servername , port , proxy_string , proxy_auth ,
221+ proxy_user , proxy_pass )
163222 else :
164- return get_local_driver (browser_name , headless , proxy_string )
223+ return get_local_driver (
224+ browser_name , headless , proxy_string , proxy_auth ,
225+ proxy_user , proxy_pass )
165226
166227
167- def get_remote_driver (browser_name , headless , servername , port , proxy_string ):
228+ def get_remote_driver (
229+ browser_name , headless , servername , port , proxy_string , proxy_auth ,
230+ proxy_user , proxy_pass ):
168231 downloads_path = download_helper .get_downloads_folder ()
169232 download_helper .reset_downloads_folder ()
170233 address = "http://%s:%s/wd/hub" % (servername , port )
171234
172235 if browser_name == constants .Browser .GOOGLE_CHROME :
173- chrome_options = _set_chrome_options (downloads_path , proxy_string )
236+ chrome_options = _set_chrome_options (
237+ downloads_path , proxy_string , proxy_auth ,
238+ proxy_user , proxy_pass )
174239 if headless :
175240 chrome_options .add_argument ("--headless" )
176241 chrome_options .add_argument ("--disable-gpu" )
@@ -237,7 +302,9 @@ def get_remote_driver(browser_name, headless, servername, port, proxy_string):
237302 webdriver .DesiredCapabilities .PHANTOMJS ))
238303
239304
240- def get_local_driver (browser_name , headless , proxy_string ):
305+ def get_local_driver (
306+ browser_name , headless , proxy_string , proxy_auth ,
307+ proxy_user , proxy_pass ):
241308 '''
242309 Spins up a new web browser and returns the driver.
243310 Can also be used to spin up additional browsers for the same test.
@@ -326,7 +393,9 @@ def get_local_driver(browser_name, headless, proxy_string):
326393 return webdriver .PhantomJS ()
327394 elif browser_name == constants .Browser .GOOGLE_CHROME :
328395 try :
329- chrome_options = _set_chrome_options (downloads_path , proxy_string )
396+ chrome_options = _set_chrome_options (
397+ downloads_path , proxy_string , proxy_auth ,
398+ proxy_user , proxy_pass )
330399 if headless :
331400 chrome_options .add_argument ("--headless" )
332401 chrome_options .add_argument ("--disable-gpu" )
0 commit comments