
    ,h                       d Z ddlmZ dZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlZddlmZ ddlZddlZddlmZ ddlZddlZddlZddlmZ dd	lmZ dd
lmZ ddlmZ ddlm Z  ddl!m"Z" ddl#m$Z$ ddl#m%Z% dZ& ejN                  d      Z(e(jS                   ejN                         jU                                 G d dejV                  jX                  jV                  jZ                        Z.d Z/y)a%  

         888                                                  888         d8b
         888                                                  888         Y8P
         888                                                  888
 .d8888b 88888b.  888d888 .d88b.  88888b.d88b.   .d88b.   .d88888 888d888 888 888  888  .d88b.  888d888
d88P"    888 "88b 888P"  d88""88b 888 "888 "88b d8P  Y8b d88" 888 888P"   888 888  888 d8P  Y8b 888P"
888      888  888 888    888  888 888  888  888 88888888 888  888 888     888 Y88  88P 88888888 888
Y88b.    888  888 888    Y88..88P 888  888  888 Y8b.     Y88b 888 888     888  Y8bd8P  Y8b.     888
 "Y8888P 888  888 888     "Y88P"  888  888  888  "Y8888   "Y88888 888     888   Y88P    "Y8888  888   88888888

by UltrafunkAmsterdam (https://github.com/ultrafunkamsterdam)

    )annotationsz3.5.5N)finalize)By   CDP)start_detached)ChromeOptions)IS_POSIX)Patcher)Reactor)UCWebElement)
WebElement)Chromer
   r   r   r   find_chrome_executableucc                       e Zd ZdZ e       ZdZdZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d	 d fdZd Z	 fdZ
d Zd Zd	 Zdd
ZddZd fd	Zd Zd Z fdZd Zd Zd Zd Zd Zed        Z xZS )r   ao  

    Controls the ChromeDriver and allows you to drive the browser.

    The webdriver file will be downloaded by this module automatically,
    you do not need to specify this. however, you may if you wish.

    Attributes
    ----------

    Methods
    -------

    reconnect()

        this can be useful in case of heavy detection methods
        -stops the chromedriver service which runs in the background
        -starts the chromedriver service which runs in the background
        -recreate session


    start_session(capabilities=None, browser_profile=None)

        differentiates from the regular method in that it does not
        require a capabilities argument. The capabilities are automatically
        recreated from the options at creation time.

    --------------------------------------------------------------------------
        NOTE:
            Chrome has everything included to work out of the box.
            it does not `need` customizations.
            any customizations MAY lead to trigger bot migitation systems.

    --------------------------------------------------------------------------
    NFc                   t        | | j                  |        || _        t        ||||      | _        | j                  j                          |s
t               }	 t        |d      r|j                  t        d      | |_        |j                  sR|dk7  r|n;t        j                  j                  j                  j                   j#                         }d}d||fz  |_        n)|j                  j%                  d      \  }}t'        |      }|r|j)                  d	d
d
d       |j+                  d|z         |j+                  d|z         |r|j+                  d|z         dt-        |      }}|j.                  D ]  }t1        dD cg c]  }||v  c}      r"|j.                  j3                  |       d|_        d|v rt7        j8                  d|      }	 |d   }d|v set7        j8                  d|      }	 |d   }t<        j                  d|d|d          d} |st        |d      r[t?        |dd      rNddl }|jC                  d       |j+                  d|jD                  z         d}t<        j                  d|z         natF        jH                  jK                  tM        jN                               }d}d|z  }|j+                  |       t<        j                  d|z         |s,	 ddl(}|jS                         d   jU                  d d!      }|sd"}|j+                  d#|z         |jX                  s|xs
 t[               |_,        |jX                  r-t]        j^                  |jX                        ja                         s*tc        d$je                  tf        r
d%            d&            d'| _4        || _"        || _5        |r|j.                  jm                  d(d)g       |r|j.                  jm                  d*d+g       |st?        |d,d      rV	 | j                  jn                  d-k  r|j+                  d.       n*| j                  jn                  d-k\  r|j+                  d/       |j+                  d1       |j+                  d2       |j+                  d*       |j+                  d3|
z  xs/ ts        tu        jv                         jy                         d4      d          t        |d5      r|j{                  |       	 t}        tF        jH                  j                  |d6      d7d89      5 }t        j                  |      }|d:   d;   d|d:   d;<   |j                  dd       t        j                  ||       |j                          t<        j                  d<       ddd       || _E        |s|j                         }|s&t        |jX                  g|j.                   | _H        npt        j                  |jX                  g|j.                  t        j                  t        j                  t        j                  tf        >      } | j                  | _H        t        j                  j                  j                  j                  | j                  j                        }!t        t        | K  |!||	?       d| _S        |rytu        jv                         jy                         tt        j                  k(  r$tu        jv                  d@      j                  dA       t        |       }"|"j                          |"| _S        |rt        | _Y        nt        | _Y        |st?        |d,d      r| j                          yy# t        $ r Y w xY wc c}w # t:        $ r t<        j                  d       d}Y w xY w# t:        $ r t<        j                  d|z         Y Qw xY w# tV        $ r Y w xY w#  t<        jq                  d0       |j+                  d/       Y xY w# 1 sw Y   wxY w# tV        $ r }t<        j                  d=       Y d}~d}~ww xY w)Ban  
        Creates a new instance of the chrome driver.

        Starts the service and then creates new instance of chrome driver.

        Parameters
        ----------

        options: ChromeOptions, optional, default: None - automatic useful defaults
            this takes an instance of ChromeOptions, mainly to customize browser behavior.
            anything other dan the default, for example extensions or startup options
            are not supported in case of failure, and can probably lowers your undetectability.


        user_data_dir: str , optional, default: None (creates temp profile)
            if user_data_dir is a path to a valid chrome profile directory, use it,
            and turn off automatic removal mechanism at exit.

        driver_executable_path: str, optional, default: None(=downloads and patches new binary)

        browser_executable_path: str, optional, default: None - use find_chrome_executable
            Path to the browser executable.
            If not specified, make sure the executable's folder is in $PATH

        port: int, optional, default: 0
            port to be used by the chromedriver executable, this is NOT the debugger port.
            leave it at 0 unless you know what you are doing.
            the default value of 0 automatically picks an available port.

        enable_cdp_events: bool, default: False
            :: currently for chrome only
            this enables the handling of wire messages
            when enabled, you can subscribe to CDP events by using:

                driver.add_cdp_listener("Network.dataReceived", yourcallback)
                # yourcallback is an callable which accepts exactly 1 dict as parameter


        service_args: list of str, optional, default: None
            arguments to pass to the driver service

        desired_capabilities: dict, optional, default: None - auto from config
            Dictionary object with non-browser specific capabilities only, such as "item" or "loggingPref".

        advanced_elements:  bool, optional, default: False
            makes it easier to recognize elements like you know them from html/browser inspection, especially when working
            in an interactive environment

            default webelement repr:
            <selenium.webdriver.remote.webelement.WebElement (session="85ff0f671512fa535630e71ee951b1f2", element="6357cb55-92c3-4c0f-9416-b174f9c1b8c4")>

            advanced webelement repr
            <WebElement(<a class="mobile-show-inline-block mc-update-infos init-ok" href="#" id="main-cat-switcher-mobile">)>

            note: when retrieving large amounts of elements ( example: find_elements_by_tag("*") ) and print them, it does take a little more time.


        service_log_path: str, optional, default: None
             path to log information from the driver.

        keep_alive: bool, optional, default: True
             Whether to configure ChromeRemoteConnection to use HTTP keep-alive.

        log_level: int, optional, default: adapts to python global log level

        headless: bool, optional, default: False
            can also be specified in the options instance.
            Specify whether you want to use the browser in headless mode.
            warning: this lowers undetectability and not fully supported.

        version_main: int, optional, default: None (=auto)
            if you, for god knows whatever reason, use
            an older version of Chrome. You can specify it's full rounded version number
            here. Example: 87 for all versions of 87

        patcher_force_close: bool, optional, default: False
            instructs the patcher to do whatever it can to access the chromedriver binary
            if the file is locked, it will force shutdown all instances.
            setting it is not recommended, unless you know the implications and think
            you might need it.

        suppress_welcome: bool, optional , default: True
            a "welcome" alert might show up on *nix-like systems asking whether you want to set
            chrome as your default browser, and if you want to send even more data to google.
            now, in case you are nag-fetishist, or a diagnostics data feeder to google, you can set this to False.
            Note: if you don't handle the nag screen in time, the browser loses it's connection and throws an Exception.

        use_subprocess: bool, optional , default: True,

            False (the default) makes sure Chrome will get it's own process (so no subprocess of chromedriver.exe or python
                This fixes a LOT of issues, like multithreaded run, but mst importantly. shutting corectly after
                program exits or using .quit()
                you should be knowing what you're doing, and know how python works.

              unfortunately, there  is always an edge case in which one would like to write an single script with the only contents being:
              --start script--
              import undetected_chromedriver as uc
              d = uc.Chrome()
              d.get('https://somesite/')
              ---end script --

              and will be greeted with an error, since the program exists before chrome has a change to launch.
              in that case you can set this to `True`. The browser will start via subprocess, and will keep running most of times.
              ! setting it to True comes with NO support when being detected. !

        no_sandbox: bool, optional, default=True
             uses the --no-sandbox option, and additionally does suppress the "unsecure option" status bar
             this option has a default of True since many people seem to run this as root (....) , and chrome does not start
             when running as root without using --no-sandbox flag.

        user_multi_procs:
            set to true when you are using multithreads/multiprocessing
            ensures not all processes are trying to modify a binary which is in use by another.
            for this to work. YOU MUST HAVE AT LEAST 1 UNDETECTED_CHROMEDRIVER BINARY IN YOUR ROAMING DATA FOLDER.
            this requirement can be easily satisfied, by just running this program "normal" and close/kill it.


        )executable_pathforceversion_mainuser_multi_procs_sessionNz)you cannot reuse the ChromeOptions objectr   z	127.0.0.1z%s:%d:zgoog:loggingPrefsALL)performancebrowserz--remote-debugging-host=%sz--remote-debugging-port=%sz--user-data-dir=%s)z
--headlessheadlessTlangz(?:--)?lang(?:[ =])?(.*)r   z'will set the language to en-US,en;q=0.9zen-US,en;q=0.9zuser-data-dirz!(?:--)?user-data-dir(?:[ =])?(.*)z%user-data-dir found in user argument z => z>no user data dir could be extracted from supplied argument %s user_data_dirzusing ChromeOptions.user_data_dir might stop working in future versions.use uc.Chrome(user_data_dir='/xyz/some/data') in case you need existing profile folderz2user_data_dir property found in options object: %sFzcreated a temporary folder in which the user-data (profile) will be stored during this
session, and added it to chrome startup arguments: %s_-zen-USz	--lang=%sa  
---------------------
Could not determine browser executable.
---------------------
Make sure your browser is installed in the default location (path).
If you are sure about the browser executable, you can specify it using
the `browser_executable_path='{}` parameter.

z/path/to/browser/executablezc:/path/to/your/browser.exe   z--no-default-browser-checkz--no-first-runz--no-sandboxz--test-typer   l   z--headless=chromez--headless=newzScould not detect version_main.therefore, we are assuming it is chrome 108 or higherz--window-size=1920,1080z--start-maximizedz--log-level=%d
   handle_prefszDefault/Preferenceslatin1zr+)encodingmodeprofile	exit_typezfixed exit_type flagz"did not find a bad exit_type flag )stdinstdoutstderr	close_fds)serviceoptions
keep_alivez+selenium.webdriver.remote.remote_connection   )\r   _ensure_closedebugr   patcherautor
   hasattrr   RuntimeErrorAttributeErrordebugger_addressselenium	webdrivercommonr0   utils	free_portsplitintset_capabilityadd_argumentbool	argumentsanyremover   research
IndexErrorloggergetattrwarningswarnr    ospathnormpathtempfilemkdtemplocalegetdefaultlocalereplace	Exceptionbinary_locationr   pathlibPathexistsFileNotFoundErrorformatr   _delaykeep_user_data_dirextendr   warningdivmodlogging	getLoggergetEffectiveLevelr&   openjoinjsonloadseekdumptruncater1   to_capabilitiesr	   browser_pid
subprocessPopenPIPEpidchromiumChromiumServicer   superr   __init__reactorDEBUGsetLevelr   startr   _web_element_clsr   _configure_headless)$selfr1   r    driver_executable_pathbrowser_executable_pathportenable_cdp_eventsdesired_capabilitiesadvanced_elementsr2   	log_levelr   r   patcher_force_closesuppress_welcomeuse_subprocessr5   
no_sandboxr   kw
debug_port
debug_hostlanguager`   argr!   mrN   rU   fsconfiger   r0   rx   	__class__s$                                      b/var/www/html/Resume-Scraper/venv/lib/python3.12/site-packages/undetected_chromedriver/__init__.pyrw   zChrome.__init__i   s   ` 	t))40
2%%-	
 	 #oG	w
+0@0@0L ##NOO  '' 19 ''..66<<FFH 
 %J'.*j1I'IG$%,%=%=%C%CC%H"J
ZJ""#Uu%M 	9JFG9JFG  !5!EF'+T--@$ $$ 	C&@AAHAB!!((-#' }II8#>0 tH
 #%IIA3G$%aDMLLKNPQRSPTU *.&+	:  w0W$6  m $$%9G<Q<Q%QR%)"H=X
 !# 0 01A1A1C D%*"*]:$$S)LNQR
 !224Q7??SI "[834&&'C+A+C # &&W445<<>'G VX9i  Lii  *"4$$&BDT%UV$$nm%DEww
D97<<,,s2(()<=\\..#5(()9: 	6701^, 	y( Fg'');;=rB1E	

 7N+  /	?],AB! 5 2)$[1=59F9%k21		&"%345  ##*#:#:#< -'' *1*;*; D !&&((=7+<+<= oo!!"G  '{{D $$--55EELL((
 	fd$! 	% 	
   "446'--G!!A(2,dmGMMO"DL$0D!$.D!ww
D9$$& :u  		B B " 0LL!JK/H0 " LLXP  R7  W X$$%56$5 5  	?LL=>>	?s   #]+ ];
^ 6%^'*'_ A_ 9,` %A3`` +	]87]8  ^$#^$'!__	__(`
`` 	a#`>>ac                d      j                   t        j                  d        fd}| _         y )Nzsetting properties for headlessc                 @   j                  d      rt        j                  d       j                  dddi       t        j                  d       j                  ddj                  d	      j	                  d
d      i       j                  dddi        | i |S )Nzreturn navigator.webdriverzpatch navigator.webdriverz%Page.addScriptToEvaluateOnNewDocumentsourcea  

                           Object.defineProperty(window, "navigator", {
                                Object.defineProperty(window, "navigator", {
                                  value: new Proxy(navigator, {
                                    has: (target, key) => (key === "webdriver" ? false : key in target),
                                    get: (target, key) =>
                                      key === "webdriver"
                                        ? false
                                        : typeof target[key] === "function"
                                        ? target[key].bind(target)
                                        : target[key],
                                  }),
                                });
                    zpatch user-agent stringzNetwork.setUserAgentOverride	userAgentzreturn navigator.userAgentHeadless a  
                            Object.defineProperty(navigator, 'maxTouchPoints', {get: () => 1});
                            Object.defineProperty(navigator.connection, 'rtt', {get: () => 100});

                            // https://github.com/microlinkhq/browserless/blob/master/packages/goto/src/evasions/chrome-runtime.js
                            window.chrome = {
                                app: {
                                    isInstalled: false,
                                    InstallState: {
                                        DISABLED: 'disabled',
                                        INSTALLED: 'installed',
                                        NOT_INSTALLED: 'not_installed'
                                    },
                                    RunningState: {
                                        CANNOT_RUN: 'cannot_run',
                                        READY_TO_RUN: 'ready_to_run',
                                        RUNNING: 'running'
                                    }
                                },
                                runtime: {
                                    OnInstalledReason: {
                                        CHROME_UPDATE: 'chrome_update',
                                        INSTALL: 'install',
                                        SHARED_MODULE_UPDATE: 'shared_module_update',
                                        UPDATE: 'update'
                                    },
                                    OnRestartRequiredReason: {
                                        APP_UPDATE: 'app_update',
                                        OS_UPDATE: 'os_update',
                                        PERIODIC: 'periodic'
                                    },
                                    PlatformArch: {
                                        ARM: 'arm',
                                        ARM64: 'arm64',
                                        MIPS: 'mips',
                                        MIPS64: 'mips64',
                                        X86_32: 'x86-32',
                                        X86_64: 'x86-64'
                                    },
                                    PlatformNaclArch: {
                                        ARM: 'arm',
                                        MIPS: 'mips',
                                        MIPS64: 'mips64',
                                        X86_32: 'x86-32',
                                        X86_64: 'x86-64'
                                    },
                                    PlatformOs: {
                                        ANDROID: 'android',
                                        CROS: 'cros',
                                        LINUX: 'linux',
                                        MAC: 'mac',
                                        OPENBSD: 'openbsd',
                                        WIN: 'win'
                                    },
                                    RequestUpdateCheckStatus: {
                                        NO_UPDATE: 'no_update',
                                        THROTTLED: 'throttled',
                                        UPDATE_AVAILABLE: 'update_available'
                                    }
                                }
                            }

                            // https://github.com/microlinkhq/browserless/blob/master/packages/goto/src/evasions/navigator-permissions.js
                            if (!window.Notification) {
                                window.Notification = {
                                    permission: 'denied'
                                }
                            }

                            const originalQuery = window.navigator.permissions.query
                            window.navigator.permissions.__proto__.query = parameters =>
                                parameters.name === 'notifications'
                                    ? Promise.resolve({ state: window.Notification.permission })
                                    : originalQuery(parameters)

                            const oldCall = Function.prototype.call
                            function call() {
                                return oldCall.apply(this, arguments)
                            }
                            Function.prototype.call = call

                            const nativeToStringFunctionString = Error.toString().replace(/Error/g, 'toString')
                            const oldToString = Function.prototype.toString

                            function functionToString() {
                                if (this === window.navigator.permissions.query) {
                                    return 'function query() { [native code] }'
                                }
                                if (this === functionToString) {
                                    return nativeToStringFunctionString
                                }
                                return oldCall.call(oldToString, this)
                            }
                            // eslint-disable-next-line
                            Function.prototype.toString = functionToString
                            )execute_scriptrL   infoexecute_cdp_cmdrW   )argskwargsorig_getr~   s     r   get_wrappedz/Chrome._configure_headless.<locals>.get_wrapped  s    ""#?@78$$;  #* 56$$2#T%8%88&!'*b1 $$;  _# adJ T,V,,    )getrL   r   )r~   r   r   s   ` @r   r}   zChrome._configure_headless  s)    8856F	-P r   c                "    t         |   |      S N)rv   r   )r~   urlr   s     r   r   z
Chrome.get  s     w{3r   c                    | j                   rX| j                   Lt        | j                   t              r2| j                   j                  ||       | j                   j                  S y)NF)rx   
isinstancer   add_event_handlerhandlers)r~   
event_namecallbacks      r   add_cdp_listenerzChrome.add_cdp_listener  sH    LL(4<<1LL**:x@<<(((r   c                    | j                   r@t        | j                   t              r%| j                   j                  j	                          y y y r   )rx   r   r   r   clearr~   s    r   clear_cdp_listenerszChrome.clear_cdp_listeners  s3    <<Jt||W=LL!!'') ><r   c                    | j                  t        j                  j                  j                  j
                  j                  ddi       y )Ntypewindow)executer<   r=   remotecommandCommand
NEW_WINDOWr   s    r   
window_newzChrome.window_new  s6    %%--55@@68BT	
r   c                p    t        | d      s*ddlm}  || j                        }|j	                  |       yy)z
        this opens a url in a new tab.
        apparently, that passes all tests directly!

        Parameters
        ----------
        url

        Returns
        -------

        cdpr   r   N)r8   r   r   r1   tab_new)r~   r   r   r   s       r   r   zChrome.tab_new  s0     tU# dll#CKK	 $r   c                   	 | j                   j                          t        j                  |       	 | j                   j                          	 | j                          y # t        $ r}t        j	                  |       Y d }~ed }~ww xY w# t        $ r}t        j	                  |       Y d }~`d }~ww xY w# t        $ r}t        j	                  |       Y d }~y d }~ww xY wr   )	r0   stoprX   rL   r5   timesleepr{   start_session)r~   timeoutr   s      r   	reconnectzChrome.reconnect  s    	LL 	

7	LL 	   	LLOO	
  	LLOO	
  	LLOO	sF   A B	 B4 	B'BB		B1B,,B14	C=CCc                    |s| j                   j                         }t        t        j                  j
                  j                  j                  |   |       y r   )r1   rn   rv   r<   r=   chrome	WebDriverr   )r~   capabilitiesbrowser_profiler   s      r   r   zChrome.start_session  sB    <<779Lh  ''11;;TP	
r   c              #      K   d fd	} |       D ]  }|   j                  dd      }|D ]  } ||      D ]  }|   yw)a  
        find elements in all frames
        this is a generator function, which is needed
            since if it would return a list of elements, they
            will be stale on arrival.
        using generator, when the element is returned we are in the correct frame
        to use it directly
        Args:
            by: By
            value: str
        Returns: Generator[webelement.WebElement]
        Nc              3     K   | sj                   j                          nj                   j                  |        j                        D ]  }|  j                   j                          y wr   )	switch_todefault_contentframefind_elements)felembyr~   values     r   search_framez4Chrome.find_elements_recursive.<locals>.search_frame  s_     ..0$$Q'**2u5 
 NN**,s   A/A2zcss selectoriframer   )r   )r~   r   r   r   r   framesr   s   ```    r   find_elements_recursivezChrome.find_elements_recursive  sa     		- !N 	DJ	 ##NH=  	A$Q 
	s   AA	c           	        	 | j                   j                  j                          t        j	                  d       	 | j                  j                  j                          t        j	                  d       	 t        j                  | j                  d       t        j	                  d       t        | d      rtt        | d      rh| j                  s\t!        d      D ]N  }	 t#        j$                  | j&                  d	       t        j	                  d
| j&                  z          d | _        y  d | _        y # t
        t        t        f$ r Y w xY w# t
        $ r Y w xY w# t        $ r
}Y d }~d }~ww xY w# t(        $ r Y nPt        t        t*        f$ r:}t        j	                  d|j,                  j.                  d|d       Y d }~nd }~ww xY wt1        j2                  d       )Nzwebdriver process endedzshutting down reactor   zgracefully closed browserr`   r       F)ignore_errorszsuccessfully removed %sz"When removing the temp profile, a z
 occured: z
retrying...皙?)r0   processkillrL   r5   r:   r9   OSErrorrx   eventsetrP   ro   rX   r8   r`   rangeshutilrmtreer    r]   PermissionErrorr   __name__r   r   r6   )r~   r   r!   s      r   quitzChrome.quit  s   	LL  %%'LL23	LL""$LL01	GGD$$b)LL45 D./o.++1X  MM$"4"4EJ LL!:T=O=O!OP
 # " E g6 		
  		
  		 ) $g? LL;;//4  

3sR   9D3 9E 65E !E33E
E	EE	E0+E03	G>G0GGc                    t         |   d      st         |   |      S dd l}t         |   |      |j                        r|j	                        sfd}|S S )Nr5   r   c            	     f    t         j                  dj                  d| d|d        | i |S )Nzcalling z with args z and kwargs 
)rL   r5   __qualname__)r   r   originals     r   newfuncz(Chrome.__getattribute__.<locals>.newfunc-  s4    LL#00$@ $T4V44r   )rv   __getattribute__inspectismethodisclass)r~   itemr   r   r   r   s       @r   r   zChrome.__getattribute__$  s\    w'07+D11w/5H)'//(2K5 Or   c                    | S r    r   s    r   	__enter__zChrome.__enter__7  s    r   c                    | j                   j                          t        j                  | j                         | j                   j                          | j                          y r   )r0   r   r   r   r_   r{   r   )r~   exc_typeexc_valexc_tbs       r   __exit__zChrome.__exit__:  s>    

4;;r   c                @    t        | j                  j                        S r   )hashr1   r;   r   s    r   __hash__zChrome.__hash__@  s    DLL1122r   c                ,    t         j                  |       S r   )object__dir__r   s    r   r   zChrome.__dir__C  s    ~~d##r   c                |    	 | j                   j                  j                          | j                          y #  Y xY wr   )r0   r   r   r   r   s    r   __del__zChrome.__del__F  s2    	LL  %%' 				s   $7 ;c                    t         j                  d       t        |d      r]t        |j                  d      rFt        |j                  j                  d      r%|j                  j                  j                          y y y y )Nzensuring closer0   r   r   )rL   r   r8   r0   r   r   )clsr~   s     r   r4   zChrome._ensure_closeM  sb     	$%D)$i0,,f5LL  %%' 6 1 %r   )NNNNr   FNFTr   FNFTTFTF)r   rE   )r   str)r   )NN)r   
__module__r   __doc__r   
_instances
session_idr5   rw   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  classmethodr4   __classcell__)r   s   @r   r   r   @   s    "H JJE # $ "!!&-@', -@'DLV 
*

& 
!F&P&3$ ( (r   r   c            	     `   t               } t        rt        j                  j	                  d      j                  t        j                        D ]9  }dD ]2  }| j                  t        j                  j                  ||f             4 ; dt        j                  v rx| j                  ddg       ndt        t        j                  j                  d      D ]=  }|dD ]3  }| j                  t        j                  j                  ||d	f             5 ? | D ]  }t        j                  d
|z         t        j                   j#                  |      s;t        j$                  |t        j&                        s`t        j                  d|z         t        j                   j)                  |      c S  y)z
    Finds the chrome, chrome beta, chrome canary, chromium executable

    Returns
    -------
    executable_path :  str
        the full file path to found executable

    PATH)zgoogle-chromert   zchromium-browserr   zgoogle-chrome-stabledarwinz</Applications/Google Chrome.app/Contents/MacOS/Google Chromez2/Applications/Chromium.app/Contents/MacOS/Chromium)PROGRAMFILESzPROGRAMFILES(X86)LOCALAPPDATAPROGRAMW6432N)zGoogle/Chrome/Applicationz
chrome.exez'checking if %s exists and is executablezfound! using %s)r   r   rP   environr   rA   pathsepaddseprh   sysplatformupdatemaprL   r5   rQ   r\   accessX_OKrR   )
candidatesr   subitem	candidates       r   r   r   Y  s^    JJJNN6*00< 	=D = rvv{{D'?;<=	= s||#RH JJNNQ
 	OD   OG NN266;;g|/L#MNO	O   /	>JK77>>)$9bgg)FLL*Y6777##I..	/r   )0r  
__future__r   __version__ri   rd   rP   rZ   rI   r   rp   r  rS   r   weakrefr   !selenium.webdriver.chrome.servicer<   #selenium.webdriver.chrome.webdriverselenium.webdriver.common.byr   #selenium.webdriver.chromium.service!selenium.webdriver.remote.command#selenium.webdriver.remote.webdriverr   r   dprocessr	   r1   r
   r6   r   r   rx   r   
webelementr   r   __all__re   rL   rz   rf   r=   r   r   r   r   r   r   r   <module>r+     s    #    	  	   
    ( * + * ( *  $ "    $ " 
		4	  !!!#557 8V(X&&00:: V(r*/r   