
    >i                    :   d dl m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	m
Z
 d dlmZ d dlmZ d dlmZ d dlmZmZmZmZmZmZ d dlmZmZ d d	lmZmZmZ d d
lm Z  d dl!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z( d dl)m*Z* d dl+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 d dl2m3Z3 d dl4m5Z5 d dl6m7Z7 d dl8m9Z9 er\d dl:m;Z; d dl<m=Z= d dl>m?Z?m@Z@mAZAmBZB d dlCmDZDmEZEmFZF d dl2mGZGmHZH d dl4mIZI d dl6mJZJ d dlKmLZLmMZMmNZNmOZOmPZP d dlQmRZR d dlSmTZTmUZUmVZVmWZW d dlXmYZY  ej                  e[      Z\ G d de	      Z]y)    )annotationsN)ABCabstractmethod)suppress)partial)randint)TYPE_CHECKINGAny	AwaitableCallableOptionaloverload)urlsplit
urlunsplit)BrowserProcessManagerProxyManagerTempDirectoryManager)Tab)BrowserCommandsEmulationCommandsFetchCommandsPageCommandsRuntimeCommandsStorageCommandsTargetCommands)ConnectionHandler)BrowserNotRunningFailedToStartBrowserInvalidConnectionPortInvalidWebSocketAddressMissingTargetOrWebSocketNoValidTabFound)DownloadBehavior)
FetchEvent)AuthChallengeResponseType)UserAgentParser)TemporaryDirectory)BrowserOptionsManager)CommandResponseT_CommandParamsT_CommandResponse)GetVersionResponseGetVersionResultGetWindowForTargetResponse)BoundsPermissionType)RequestPausedEvent)HeaderEntry)CookieCookieParamErrorReasonRequestMethodResourceType)GetCookiesResponse)CreateBrowserContextResponseCreateTargetResponseGetBrowserContextsResponseGetTargetsResponse)
TargetInfoc                  d   e Zd ZdZ	 dB	 	 	 dCdZdDdZd ZdEdZdFdGdZd Z	d	 Z
	 dH	 	 	 	 	 dId
ZdJdZdKdZdLdMdZdNdZdOdZdPdZdBdQdZ	 	 	 dR	 	 	 	 	 	 	 dSdZdBdTdZ	 dB	 	 	 dUdZdBdVdZdWdZdXdZdYdZdZdZd Zd Zd[dZ	 	 dH	 	 	 	 	 d\dZdBdTdZe 	 dF	 	 	 	 	 	 	 d]d       Z!e 	 dF	 	 	 	 	 	 	 d^d        Z!dFd_d!Z!d`d"Z"	 	 da	 	 	 dbd#Z#d$ Z$d% Z%d& Z&	 	 	 	 	 dc	 	 	 	 	 	 	 	 	 	 	 ddd'Z'ded(Z(	 	 	 df	 	 	 	 	 	 	 	 	 dgd)Z)e*dhd*       Z+did+Z,	 	 	 	 	 	 djd,Z-e*dkd-       Z.e*	 	 	 	 	 	 	 	 dld.       Z/	 	 	 	 	 	 dmd/Z0dnd0Z1dod1Z2d2 Z3	 	 	 	 dpd3Z4e*dqd4       Z5e*drd5       Z6dsdtd6Z7	 du	 	 	 	 	 dvd7Z8d8 Z9dwd9Z:dxd:Z;dod;Z<e*dyd<       Z=dyd=Z>dBdzd>Z?d{d?Z@e*	 	 	 	 d|d@       ZAeBd}dA       ZCy)~Browserz
    Abstract base class for browser automation using Chrome DevTools Protocol.

    Provides comprehensive browser control including lifecycle management,
    context handling, network interception, cookie management, and CDP commands.
    Nc           
        | j                  |       |j                         | _        t        | j                        | _        |r|nt        dd      | _        t               | _        t               | _
        d| _        t        | j                        | _        d| _        i | _        i | _        t"        j%                  d| j                   dt'        | j                  dd              y)a  
        Initialize browser instance with configuration.

        Args:
            options_manager: Manages browser options initialization and defaults.
                Must implement initialize_options() and add_default_arguments().
            connection_port: CDP WebSocket port. Random port (9223-9322) if None.

        Note:
            Call start() to actually launch the browser.
        i$  ij$  N zBrowser initialized: port=z, headless=headless)_validate_connection_portinitialize_optionsoptionsr   _proxy_managerr   _connection_portr   _browser_process_managerr   _temp_directory_manager_ws_addressr   _connection_handler_backup_preferences_dir_tabs_opened_context_proxy_authloggerdebuggetattr)selfoptions_managerconnection_ports      b/var/www/python/tenders/Scrapper/venv/lib/python3.12/site-packages/pydoll/browser/chromium/base.py__init__zBrowser.__init__U   s      	&&7&99;*4<<83BPTVZH[(=(?%';'=$*.#4T5J5J#K ')$,.?A ()>)>(? @j$?@B	
    c                8   K   t         j                  d       | S w)zAsync context manager entry.zEntering browser async context)rP   rQ   rS   s    rV   
__aenter__zBrowser.__aenter__u   s     56s   c                  K   t         j                  d|        | j                  rqt         j                  d| j                          | j                         }t	        j
                  | j                  t        j                  j                  |dd             | j                  d       d{   r| j                          d{    | j                  j                          d{    y7 ?7 )7 	w)z(Async context manager exit with cleanup.z(Exiting browser async context: exc_type=z(Restoring backup preferences directory: DefaultPreferences   timeoutN)rP   rQ   rM   _get_user_data_dirshutilcopy2ospathjoin_is_browser_runningstoprL   close)rS   exc_typeexc_valexc_tbuser_data_dirs        rV   	__aexit__zBrowser.__aexit__z   s     ?zJK''LLCDD`D`Cabc 335MLL,,]I}E ))!)444))+&&,,... 5.s6   B+C3-C-.C3C/!C3'C1(C3/C31C3c                   K   t         j                  d|        | j                  |       d{    | j                          d{   }t         j                  dt	        |              |d   S 7 B7 ,w)a  
        Connect to browser using WebSocket address. When we set
        the _ws_address attribute, the connection handler will use
        this address instead of resolving it from the connection port.

        Args:
            ws_address: WebSocket address of the browser.

        Returns:
            The first tab in the list of opened tabs.

        Note:
            You are supposed to use this method only if you want to connect to a browser
            that is already running.
        z%Connecting to browser via WebSocket: NzConnected. Tabs available: r   )rP   info_setup_ws_addressget_opened_tabslen)rS   
ws_addresstabss      rV   connectzBrowser.connect   sk       	;J<HI$$Z000))++1#d)=>Aw 	1+s!   -A6A2A6A4+A64A6c                  K   |r-t        j                  dt        d       || j                  _        | j                  j
                  xs | j                         }t        j                  d|       | j                          t        j                  d       | j                  j                         }t        j                  d| j                          | j                  j                  || j                  | j                  j                          | j#                          d{    t        j                  d       | j%                  |d	   |d
          d{    | j'                  | j)                          d{          d{   }t+        | || j                        }|| j,                  |<   | j/                  |       d{    t        j                  d|        |S 7 7 7 n7 d7 &w)a5  
        Start browser process and establish CDP connection.

        Args:
            headless: Deprecated. Use `options.headless = True` instead.

        Returns:
            Initial tab for interaction.

        Raises:
            FailedToStartBrowser: If the browser fails to start or connect.
        zvThe 'headless' parameter is deprecated and will be removed in a future version. Use `options.headless = True` instead.r_   )
stacklevelzResolved binary location: %szUser data directory configuredz!Starting browser process on port Nz&Browser process started and responsiver      )	target_idrU   zInitial tab attached: )warningswarnDeprecationWarningrF   rC   binary_location_get_default_binary_locationrP   rQ   _setup_user_dirrG   get_proxy_credentialsrq   rH   rI   start_browser_process	arguments_verify_browser_running_configure_proxy_get_valid_tab_idget_targetsr   rN   _apply_user_agent_override)rS   rC   r   proxy_configvalid_tab_idtabs         rV   startzBrowser.start   s     MM9"	 %-DLL!,,66]$:[:[:]3_E56**@@B78M8M7NOP%%;;T22DLL4J4J	
 **,,,<=##LO\!_EEE!33$:J:J:L4LMM$,@U@UV*-,'--c222,\N;<
 	-E4LM 	3sZ   DG,G" 4G,G$"G,7G&8G,G(?G,G*G,$G,&G,(G,*G,c                F  K   | j                          d{   st        j                  d       t               t        j	                  d       | j                  t        j                                d{    | j                  j                          | j                  j                          d{    t        j                  t        j                  dk(  rdnd       d{    | j                  j!                          t        j	                  d       y7 7 7 k7 ;w)a  
        Stop browser process and cleanup resources.

        Sends Browser.close command, terminates process, removes temp directories,
        and closes WebSocket connections.

        Raises:
            BrowserNotRunning: If the browser is not currently running.
        Nz&Stop called but browser is not runningzStopping browser processntg      ?g?z0Browser process stopped and resources cleaned up)rh   rP   errorr   rq   _execute_commandr   rj   rI   stop_processrL   asynciosleepre   namerJ   cleanuprZ   s    rV   ri   zBrowser.stop   s      --///LLAB#%%./##O$9$9$;<<<%%224&&,,...mm277d?C<<<$$,,.FG 0
 	=.<sF   D!DAD!5D6;D!1D21D!#D$5D!D!D!D!c                ~   K   t         j                  d       | j                  j                          d{    y7 w)zI
        Closes the WebSocket connection and releases resources.
        z$Closing browser WebSocket connectionN)rP   rq   rL   rj   rZ   s    rV   rj   zBrowser.close   s-      	:;&&,,...s   3=;=c                N  K   |}d}|r9| j                  |      \  }}t        j                  d| dt        |       d       | j	                  t        j                  ||             d{   }|d   d   }|r|| j                  |<   t        j                  d|        |S 7 7w)	a  
        Create isolated browser context (like incognito).

        Browser contexts provide isolated storage and don't share session data.
        Multiple contexts can exist simultaneously.

        Args:
            proxy_server: Optional proxy for this context only (scheme://host:port).
            proxy_bypass_list: Comma-separated hosts that bypass proxy.

        Returns:
            Browser context ID for use with other methods.
        Nz%Creating browser context with proxy: z(credentials provided=))proxy_serverproxy_bypass_listresultbrowserContextIdzCreated browser context: )	 _sanitize_proxy_and_extract_authrP   rQ   boolr   r   create_browser_contextrO   rq   )rS   r   r   sanitized_proxyextracted_authresponse
context_ids          rV   r   zBrowser.create_browser_context   s     " '48.2.S.ST`.a+O^LL77H(n)=(>aA
 8<7L7L11,"38
 2
 h'(:;
3AD$$Z0/
|<=2
s   A)B%+B#,8B%c                   K   t         j                  d|        | j                  t        j                  |             d{   S 7 w)a  
        Delete browser context and all associated tabs/resources.

        Removes all storage (cookies, localStorage, etc.) and closes all tabs.
        The default browser context cannot be deleted.

        Note:
            Closes all associated tabs immediately.
        zDeleting browser context: N)rP   rq   r   r   dispose_browser_contextrS   browser_context_ids     rV   delete_browser_contextzBrowser.delete_browser_context  sJ      	01C0DEF**223EF
 
 	
 
s   A A	AA	c                   K   | j                  t        j                                d{   }t        j	                  dt        |d   d          d       |d   d   S 7 4w)z:Get all browser context IDs including the default context.NFetched r   browserContextIdsz browser contexts)r   r   get_browser_contextsrP   rQ   rt   rS   r   s     rV   r   zBrowser.get_browser_contexts  sf     595J5J//16
 0
 	xHX$67J$K LMM^_`!"566	0
   'A A5A c                  K   t         j                  d| d       | j                  t        j                  |             d{   }|d   d   }t        | fi | j                  ||      }|| j                  |<   | j                  |       d{    | j                  ||       d{    |r|j                  |       d{    t         j                  d|        |S 7 7 U7 =7 $w)a  
        Create new tab for page interaction.

        Args:
            url: Initial URL (about:blank if empty).
            browser_context_id: Context to create tab in (default if None).

        Returns:
            Tab instance for page navigation and element interaction.
        zCreating new tab (context=r   )r   Nr   targetIdzNew tab created: )rP   rq   r   r   create_targetr   _get_tab_kwargsrN   r   !_setup_context_proxy_auth_for_tabgo_to)rS   urlr   r   r{   r   s         rV   new_tabzBrowser.new_tab%  s      	01C0DAFG/3/D/D((#50
 *

 X&z2	$N$..y:LMN'*)$--c22244S:LMMM))C.  '	{34
*
 	3M sI   AC,C$AC,C&C,*C(+C,C*C,&C,(C,*C,c                   K   | j                  t        j                                d{   }t        j	                  dt        |d   d          d       |d   d   S 7 4w)a  
        Get all active targets/pages in browser.

        Targets include pages, service workers, shared workers, and browser process.
        Useful for debugging and managing multiple tabs.

        Returns:
            List of TargetInfo objects.
        Nr   r   targetInfos targets)r   r   r   rP   rQ   rt   r   s     rV   r   zBrowser.get_targets@  s_      .2-B-B>C]C]C_-`'`xHX$6}$E FGxPQ!-00 (ar   c                  K   | j                          d{   }|D cg c]  }|d   dk(  r	d|d   vr| }}|D cg c]  }|d   	 }}t        | j                  j                               }|D cg c]	  }||vs| }}|D cg c]  }| j                  |    }}g }	t	        |      D ]G  }t        | fi | j                  |      }
| j                  |
       d{    |	j                  |
       I | j                  j                  t        t        ||	                   t        j                  dt        |       dt        |	              ||	z   S 7 ?c c}w c c}w c c}w c c}w 7 w)	a5  
        Get all opened tabs that are not extensions and have the type 'page'.
        Tabs that are already opened will be returned as is. If a new target is opened,
        a new Tab instance will be created.

        Returns:
            List of Tab instances. The last tab is the most recent one.
        Ntypepage	extensionr   r   zOpened tabs resolved: existing=z, new=)r   listrN   keysreversedr   r   r   appendupdatedictziprP   rQ   rt   )rS   targetstargetvalid_tab_targetsall_target_idsexisting_target_idsr{   remaining_target_idsexisting_tabsnew_tabsr   s              rV   rs   zBrowser.get_opened_tabsN  s     ((** "
f~'Kve},L 
 

 <MM&,MM"4#4#4#9#9#;<'5 
#J]9]I 
  
 H[[)**95[[!"67 	!Id>d229=>C11#666OOC 	! 	  c*>&I!JK-c-.@-AHW	
 x''+ +

 N 
 \ 7sV   E.EE.EE.E	)E.2	E"<E" E.E'AE.E,A8E.E.c                   K   t        | fi | j                  |d         }| j                  |       d {    |S 7 w)Nr   )r   r   r   )rS   r   r   s      rV   get_tab_by_targetzBrowser.get_tab_by_targetn  sC     $C$..vj/ABC--c222
 	3s   3><>c                   K   t         j                  d| d| d       | j                  t        j                  t
        j                  ||             d{   S 7 w)zKSet download directory path (convenience method for set_download_behavior).zSetting download path: z
 (context=r   )behaviordownload_pathr   N)rP   rq   r   r   set_download_behaviorr#   ALLOW)rS   rf   r   s      rV   set_download_pathzBrowser.set_download_paths  s_     -dV:>P=QQRST**11)//"#5
 
 	
 
s   AAAAc           
        K   t         j                  d| d| d| d|        | j                  t        j                  ||||             d{   S 7 w)aQ  
        Configure download handling.

        Args:
            behavior: ALLOW (save to path), DENY (cancel), or DEFAULT.
            download_path: Required if behavior is ALLOW.
            browser_context_id: Context to apply to (default if None).
            events_enabled: Generate download events for progress tracking.
        z$Setting download behavior: behavior=z,path=
, context=z,events=)r   r   r   events_enabledN)rP   rq   r   r   r   )rS   r   r   r   r   s        rV   r   zBrowser.set_download_behavior~  sw       	28* =!?*-?,@ A$%'	

 **11!+#5-	
 
 	
 
s   AAAAc                   K   t         j                  d| d       | j                  t        j                  |             d{   S 7 w)zNDelete all cookies (session, persistent, third-party) from browser or context.zClearing all cookies (context=r   N)rP   rq   r   r   clear_cookiesr   s     rV   delete_all_cookieszBrowser.delete_all_cookies  sA     45G4HJK**?+H+HI[+\]]]]   AA
AA
c                   K   t         j                  dt        |       d| d       | j                  t	        j
                  ||             d{   S 7 w)z+Set multiple cookies in browser or context.zSetting  cookies (context=r   N)rP   rQ   rt   r   r   set_cookies)rS   cookiesr   s      rV   r   zBrowser.set_cookies  sP      	xG~-?@R?SSTUV**?+F+FwPb+cdddds   AAAAc                   K   | j                  t        j                  |             d{   }t        j	                  dt        |d   d          d| d       |d   d   S 7 7w)zGet all cookies from browser or context.

        Note:
            This method does not work with native incognito mode (--incognito flag).
            For incognito mode, use ``tab.get_cookies()`` instead.
        Nz
Retrieved r   r   r   r   )r   r   get_cookiesrP   rQ   rt   )rS   r   r   s      rV   r   zBrowser.get_cookies  sw      .2-B-B''(:;.
 (
 	Xh/	:;<<NOaNbbcd	
 !),,(
s   (A$A"8A$c                   K   | j                  t        j                                d{   }t        j	                  d|d           |d   S 7 $w)z1Get browser version and CDP protocol information.NzBrowser version: r   )r   r   get_versionrP   rQ   r   s     rV   r   zBrowser.get_version  sM     -1-B-B?C^C^C`-a'a(();(<=>!! (bs   'AA%Ac                   K   | j                  t        j                  |             d{   }t        j	                  d| d|d   d           |d   d   S 7 -w)z@Get window ID for target (used for window manipulation via CDP).NzWindow id for target z: r   windowId)r   r   get_window_for_targetrP   rQ   )rS   r{   r   s      rV   get_window_id_for_targetz Browser.get_window_id_for_target  se     595J5J11)<6
 0
 	,YKr(8:LZ:X9YZ[!*--	0
s   (AA.Ac                   K   |j                   xs, |j                  r|j                  j                  d      d   nd}|st        j	                  d       t               | j                  |       d{   S 7 w)z+Get window ID for tab (convenience method)./Nz>Missing target id or ws address for tab when getting window id)
_target_idrK   splitrP   r   r!   r   )rS   r   r{   s      rV   get_window_id_for_tabzBrowser.get_window_id_for_tab  sa     NNcs'<'<S'A"'E^b	LLYZ*,,229====s   A0A92A73A9c                   K   | j                          d{   }| j                  |       d{   }| j                  |       d{   S 7 67 7 w)z
        Get window ID for any valid tab.

        Raises:
            NoValidTabFound: If no valid attached tab can be found.
        N)r   r   r   )rS   r   r   s      rV   get_window_idzBrowser.get_window_id  sM      ((**!33G<<22<@@@ +<@s1   AAAAAA	AAAc                   K   | j                          d{   }t        j                  d|        | j                  t	        j
                  |             d{   S 7 H7 w)z5Maximize browser window (affects all tabs in window).NzMaximizing window: id=)r   rP   rq   r   r   set_window_maximizedrS   	window_ids     rV   r   zBrowser.set_window_maximized  T     ,,..	,YK89**?+O+OPY+Z[[[ /["   A#AAA#A!A#!A#c                   K   | j                          d{   }t        j                  d|        | j                  t	        j
                  |             d{   S 7 H7 w)z(Minimize browser window to taskbar/dock.NzMinimizing window: id=)r   rP   rq   r   r   set_window_minimizedr   s     rV   r   zBrowser.set_window_minimized  r   r   c                   K   | j                          d{   }t        j                  d| d|        | j                  t	        j
                  ||             d{   S 7 L7 w)z
        Set window position and/or size.

        Args:
            bounds: Properties to modify (left, top, width, height, windowState).
                Only specified properties are changed.
        NzSetting window bounds: id=z	, bounds=)r   rP   rq   r   r   set_window_bounds)rS   boundsr   s      rV   r   zBrowser.set_window_bounds  s^      ,,..	09VHMN**?+L+LYX^+_``` /`s"   A'A#AA'A%A'%A'c           	        K   t         j                  d| d| d| d       | j                  t        j                  |||             d{   S 7 w)a]  
        Grant browser permissions (geolocation, notifications, camera, etc.).

        Bypasses normal permission prompts for automated testing.

        Args:
            permissions: Permissions to grant.
            origin: Origin to grant to (all origins if None).
            browser_context_id: Context to apply to (default if None).
        zGranting permissions: z	 (origin=r   r   N)rP   rq   r   r   grant_permissions)rS   permissionsoriginr   s       rV   r   zBrowser.grant_permissions  sa       	$[M6(*M_L``ab	
 **--k6CUV
 
 	
 
s   A	AAAc                   K   t         j                  d| d       | j                  t        j                  |             d{   S 7 w)zAReset all permissions to defaults and restore prompting behavior.zResetting permissions (context=r   N)rP   rq   r   r   reset_permissionsr   s     rV   r  zBrowser.reset_permissions  sA     56H5IKL**?+L+LM_+`aaaar   c                   K   y wN rS   
event_namecallback	temporarys       rV   onz
Browser.on           c                   K   y wr  r  r  s       rV   r	  z
Browser.on  r
  r  c           
        K   fd}t        j                        r|}n}t        j                  d| d| dt        j                                | j                  j                  |||       d{   S 7 w)a  
        Register CDP event listener at browser level.

        Callback runs in background task to prevent blocking. Affects all pages/targets.

        Args:
            event_name: CDP event name (e.g., "Network.responseReceived").
            callback: Function called on event (sync or async).
            temporary: Remove after first invocation.

        Returns:
            Callback ID for removal.

        Note:
            For page-specific events, use Tab.on() instead.
        c                D   K   t        j                   |              y wr  )r   create_task)eventr  s    rV   callback_wrapperz$Browser.on.<locals>.callback_wrapper&  s     0s    zRegistering callback: event=z, temporary=z, async=N)r   iscoroutinefunctionrP   rQ   rL   register_callback)rS   r  r  r  r  function_to_registers     `   rV   r	  z
Browser.on  s     $	1 &&x0#3 #+ *:,l9+ N00:;=	
 --??,i
 
 	
 
s   A1A;4A95A;c                   K   t         j                  d|        | j                  j                  |       d{   S 7 w)zRemove callback from browser.zRemoving callback: id=N)rP   rQ   rL   remove_callback)rS   callback_ids     rV   r  zBrowser.remove_callback5  s7     -k];<--==kJJJJs   7A >A c                   K   t         j                  d| d|        | j                  j                  t	        j
                  ||             d{   S 7 w)a  
        Enable network request interception via Fetch domain.

        Allows monitoring, modifying, or blocking requests before they're sent.
        All matching requests are paused until explicitly continued.

        Args:
            handle_auth_requests: Intercept authentication challenges.
            resource_type: Filter by type (XHR, Fetch, Document, etc.). Empty = all.

        Note:
            Paused requests must be continued or they will timeout.
        z#Enabling Fetch events: handle_auth=z, resource_type=)handle_auth_requestsresource_typeN)rP   rQ   rL   execute_commandr   enable)rS   r  r  s      rV   enable_fetch_eventszBrowser.enable_fetch_events:  sf     $ 	12F1G H*O-	
 --==  %9+
 
 	
 
s   AAAAc                   K   t         j                  d       | j                  j                  t	        j
                                d{   S 7 w)z=Disable request interception and release any paused requests.zDisabling Fetch eventsN)rP   rQ   rL   r  r   disablerZ   s    rV   disable_fetch_eventszBrowser.disable_fetch_eventsW  s9     -.--==m>S>S>UVVVV   AAA	Ac                   K   t         j                  d       | j                  j                  t	        j
                                d{   S 7 w)zEnable runtime events.zEnabling Runtime eventsN)rP   rQ   rL   r  r   r  rZ   s    rV   enable_runtime_eventszBrowser.enable_runtime_events\  s9     ./--==o>T>T>VWWWWr!  c                   K   t         j                  d       | j                  j                  t	        j
                                d{   S 7 w)zDisable runtime events.zDisabling Runtime eventsN)rP   rQ   rL   r  r   r  rZ   s    rV   disable_runtime_eventszBrowser.disable_runtime_eventsa  s9     /0--==o>U>U>WXXXXr!  c           
        K   t         j                  d|        | j                  t        j                  ||||||             d{   S 7 w)z@
        Continue paused request without modifications.
        zContinuing request: id=)
request_idr   method	post_dataheadersintercept_responseN)rP   rQ   r   r   continue_request)rS   r'  r   r(  r)  r*  r+  s          rV   r,  zBrowser.continue_requestf  sY      	.zl;<****%##5	
 	
 		
 	
r!  c                   K   t         j                  d| d|        | j                  t        j                  ||             d{   S 7 w)zFail request with error code.zFailing request: id=z	, reason=N)rP   rQ   r   r   fail_request)rS   r'  error_reasons      rV   r.  zBrowser.fail_request~  sE     +J<yOP**=+E+EjR^+_````s   AAAAc                   K   t         j                  d| d| dt        |       dt        |              | j                  t	        j
                  |||||             d{   S 7 w)z#Fulfill request with response data.zFulfilling request: id=z, code=z
, headers=z, body=)r'  response_coderesponse_headersbodyresponse_phraseN)rP   rQ   r   r   r   fulfill_request)rS   r'  r1  r2  r3  r4  s         rV   r5  zBrowser.fulfill_request  s      	%j\ H,-.gd4j\C	
 **))%+!1 /
 
 	
 
s   A A)"A'#A)c                X    | r(| dk  r"t         j                  d|         t               yy)zValidate connection port.r   zInvalid connection port: N)rP   r   r   )rU   s    rV   rD   z!Browser._validate_connection_port  s3     2LL4_4EFG'))  3?rX   c                   K   |d   d   }t         j                  d|        | j                  |       d{   S 7 w)z.Internal callback to continue paused requests.params	requestIdz'[Fetch] REQUEST_PAUSED -> continue: id=NrP   rQ   r,  )rS   r  r'  s      rV   _continue_request_callbackz"Browser._continue_request_callback  s?     8_[1
>zlKL**:6666   5><>c                  K   |d   d   }t         j                  d| dt        |              | j                  t	        j
                  |t        j                  ||             d{   }| j                          d{    |S 7 7 w)z+Internal callback for proxy authentication.r8  r9  z1[Fetch] AUTH_REQUIRED -> provide credentials: id=, user_set=)auth_challenge_responseproxy_usernameproxy_passwordN)	rP   rQ   r   r   r   continue_request_with_authr%   PROVIDE_CREDENTIALSr   )rS   r  r@  rA  r'  r   s         rV   $_continue_request_with_auth_callbackz,Browser._continue_request_with_auth_callback  s      8_[1
?
| L^,-/	
 $(#8#844(A(U(U--	$
 
 '')))
 	*s$   A&B(B)B B	B	Bc                   K   | d   d   }t         j                  d|        |j                  |       d{   S 7 w)z;Internal callback to continue paused requests at Tab level.r8  r9  z+[Tab Fetch] REQUEST_PAUSED -> continue: id=Nr:  )r  r   r'  s      rV   _tab_continue_request_callbackz&Browser._tab_continue_request_callback  sA      8_[1
B:,OP))*5555r<  c                   K   | d   d   }t         j                  d| dt        |              |j                  |t        j
                  ||       d{   }|j                          d{    |S 7 7 w)z?Internal callback for proxy/server authentication at Tab level.r8  r9  z5[Tab Fetch] AUTH_REQUIRED -> provide credentials: id=r>  )r'  r?  r@  rA  N)rP   rQ   r   continue_with_authr%   rC  r   )r  r   r@  rA  r'  r   s         rV   (_tab_continue_request_with_auth_callbackz0Browser._tab_continue_request_with_auth_callback  s      8_[1
CJ< P^,-/	
 $'#9#9!$=$Q$Q))	 $: $
 
 &&(((
 	)s$   AA8A4A8-A6.A86A8c           	       K   |sy| j                   j                  |      }|sy|\  }}t        j                  d| dt	        |              |j                  d       d{    |j                  t        j                  t        | j                  |      d       d{    |j                  t        j                  t        | j                  |||      d       d{    y7 7 H7 	w)	zKEnable proxy auth handling for a Tab if its context has credentials stored.Nz3Enabling context-level proxy auth for tab (context=r>  T)handle_auth)r   r  )r   r@  rA  )rO   getrP   rQ   r   r  r	  r$   REQUEST_PAUSEDr   rF  AUTH_REQUIREDrI  )rS   r   r   credsusernamepasswords         rV   r   z)Browser._setup_context_proxy_auth_for_tab  s     "((,,-?@"(ABTAU VX')	
 %%$%777ff%%33   
 	
 	
 ff$$==''	   	
 		
 		
 	8	
		
s7   A C."C(#>C.!C*"A C."C,#C.*C.,C.c                  K   | j                         }|syt        j                  |      }t        j	                  d|dd        |j                  t        j                  ||j                  |j                               d{    |j                  r9|j                  t        j                  |j                  d             d{    yy7 J7 w)a,  Apply consistent User-Agent override to a tab if --user-agent= is set.

        Detects the --user-agent= argument in browser options and automatically
        synchronizes HTTP headers, navigator JS properties, and Client Hints
        via CDP Emulation.setUserAgentOverride + JS injection.
        Nz Applying User-Agent override: %s<   )
user_agentplatformuser_agent_metadataT)sourcerun_immediately)_get_user_agent_from_optionsr&   parserP   rQ   r   r   set_user_agent_overriderV  rW  navigator_override_jsr   &add_script_to_evaluate_on_new_document)rS   r   rU  parseds       rV   r   z"Browser._apply_user_agent_override  s      668
 &&z27CRI""55%$*$>$>
 	
 	
 ''&&CC!77$(   (	
s%   B CCACCCCc                |    | j                   j                  D ]#  }|j                  d      s|t        d      d c S  y)z=Extract User-Agent value from --user-agent= browser argument.z--user-agent=N)rF   r   
startswithrt   rS   args     rV   rZ  z$Browser._get_user_agent_from_options  s?    <<)) 	3C~~o.3/122	3 rX   c                  K   t         j                  d| j                  j                   d       | j	                  | j                  j                         d{   st         j                  d       t               y7 $w)z
        Verify browser started successfully.

        Raises:
            FailedToStartBrowser: If the browser failed to start.
        z&Verifying browser is running (timeout=r   Nz&Browser failed to start within timeout)rP   rQ   rF   start_timeoutrh   r   r   rZ   s    rV   r   zBrowser._verify_browser_running"  sd      	=dll>X>X=YYZ[\--dll.H.HIIILLAB&(( Js   AA?A=%A?c           	       K   |syt         j                  dt        |d   xs |d                 | j                  d       d{    | j	                  t
        j                  | j                  d       d{    | j	                  t
        j                  t        | j                  |d   |d         d       d{    y7 7 M7 	w)	z.Setup proxy authentication handling if needed.Nz7Configuring proxy authentication: credentials provided=r   rz   T)r  rL  )r@  rA  )rP   rQ   r   r  r	  r$   rN  r;  rO  r   rD  )rS   private_proxyproxy_credentialss      rV   r   zBrowser._configure_proxy.  s      $$():1)=)UARSTAU$V#WY	
 &&D&AAAgg%%++  
 	
 	

 gg$$990303
   
 	
 	
 	B	

	
s7   ACC3C:C;AC C
CC
Cc                V    | j                  d      dk(  xr d| j                  dd      vS )z@Check if target is a valid browser tab (filters out extensions).r   r   zchrome-extension://r   rB   rM  )r   s    rV   _is_valid_tabzBrowser._is_valid_tabI  s0     zz&!V+b0EVZZX]_aMb0bbrX   c                   K   t        d | D        d      }|s,t        j                  dt        |        d       t	               |j                  d      }|s t        j                  d       t	        d      |S w)z~
        Find valid attached tab ID.

        Raises:
            NoValidTabFound: If no valid attached tab is found.
        c              3  p   K   | ].  }|j                  d       dk(  rd|j                  dd      vr| 0 yw)r   r   r   r   rB   Nrj  ).0r   s     rV   	<genexpr>z,Browser._get_valid_tab_id.<locals>.<genexpr>W  s;      776?f,CGGESUDV1V s   46NzNo valid tab found among r   r   zValid tab missing targetIdzTab missing targetId)nextrP   r   rt   r"   rM  )r   	valid_tabtab_ids      rV   r   zBrowser._get_valid_tab_idN  s{      "
 
	 LL4S\N(KL!##z*LL56!"899s   A7A9c                   K   t        |      D ]C  }| j                  j                          d{   r yt        j                  d       d{    E y7 &7 	w)zCCheck if browser process is running and CDP endpoint is responsive.NTrz   F)rangerL   pingr   r   )rS   ra   _s      rV   rh   zBrowser._is_browser_runningj  sT     w 	#A--22444--"""	#
 	 5"s!   ,AAAAAAc                   K   t         j                  d|j                  d       d| d       | j                  j	                  ||       d{   S 7 w)zNExecute CDP command and return result (core method for browser communication).zExecuting command: r(  z
 (timeout=r   r`   N)rP   rQ   rM  rL   r  )rS   commandra   s      rV   r   zBrowser._execute_commands  sQ      	*7;;x+@*AG9TUVW--==gw=WWWWs   AAAAc                   | j                         }|r(| j                  j                  r| j                  |       nu|ss| j                  j                         }| j                  j                  j                  d|j                          | j                  j                  r| j                  |       t        j                  d| j                                 y)z@Setup temporary user data directory if not specified in options.--user-data-dir=zUser dir setup complete: N)rb   rF   browser_preferences)_set_browser_preferences_in_user_data_dirrJ   create_temp_dirr   r   r   $_set_browser_preferences_in_temp_dirrP   rQ   )rS   rn   temp_dirs      rV   r   zBrowser._setup_user_dirz  s    //1T\\==::=I33CCEHLL"")),<X]]O*LM||//99(C01H1H1J0KLMrX   c                   t        j                  t         j                  j                  |j                  d             | j
                  j                  }t        t         j                  j                  |j                  dd      dd      5 }t        j                  ||       d d d        t        j                  d       y # 1 sw Y   xY w)Nr]   r^   wutf-8encodingz*Wrote browser preferences to temp user dir)re   mkdirrf   rg   r   rF   r{  openjsondumprP   rQ   )rS   r  preferences	json_files       rV   r~  z,Browser._set_browser_preferences_in_temp_dir  s    
hmmY78ll66GGLL	=A3QX
 	.IIk9-	. 	AB		. 	.s   C  C	c                x   t         j                  j                  |d      }t        j                  |d       t         j                  j                  |d      }t         j                  j                  |d      | _        t         j                  j                  |      r t        j                  || j                         i }t         j                  j                  |      rNt        t        j                        5  t        |dd      5 }t        j                  |      }d	d	d	       d	d	d	       |j                  | j                  j                         t        |d
d      5 }t        j                   ||d       d	d	d	       t"        j%                  d|        y	# 1 sw Y   ~xY w# 1 sw Y   xY w# 1 sw Y   :xY w)aj  
        Set browser preferences in the user data directory.

        This function will:
        1. Create a backup of the existing Preferences file if it exists
        2. Create Default directory if it doesn't exist
        3. Write the new preferences to the Preferences file

        Args:
            user_data_dir: Path to the user data directory
        r]   T)exist_okr^   zPreferences.backuprr  r  Nr  r_   )indentz.Updated browser preferences in user data dir: )re   rf   rg   makedirsrM   existsrc   rd   r   r  JSONDecodeErrorr  loadr   rF   r{  r  rP   rQ   )rS   rn   default_dirpreferences_pathr  preferences_filer  s          rV   r|  z1Browser._set_browser_preferences_in_user_data_dir  sJ    ggll=)<
K$/77<<]C')ww||KAU'V$77>>*+LL)4+G+GH77>>*+$../ >*C'B >FV"&)),<"=K>> 	4<<;;<"C': 	8iIIk9Q7	8EFVEWXY> >> >	8 	8s0   6F$FF$F0F!	F$$F-0F9c                    | j                   j                  D ]*  }|j                  d      s|j                  dd      d   c S  y )Nrz  =rz   )rF   r   ra  r   rb  s     rV   rb   zBrowser._get_user_data_dir  sC    <<)) 	,C~~01yya(++	, rX   c                    d}| j                  d      s t        j                  d       t        d      t	        | j                  d            |k  r$t        j                  d       t        d| d      y	)
zValidate WebSocket address.   )zws://zwss://z9Invalid WebSocket address: missing ws:// or wss:// prefixz1WebSocket address must start with ws:// or wss://r   z-Invalid WebSocket address: not enough slashesz(WebSocket address must contain at least z slashesN)ra  rP   r   r    rt   r   )ru   min_slashess     rV   _validate_ws_addresszBrowser._validate_ws_address  st     $$%89LLTU)*]^^z$%3LLHI):;-xP  4rX   c                   K   | j                  |       || _        | j                  | j                  _        | j                  j                          d{    t        j                  d       y7 w)z$Setup WebSocket address for browser.Nz2WebSocket address set for browser-level connection)r  rK   rL   _ensure_active_connectionrP   rq   )rS   ru   s     rV   rr   zBrowser._setup_ws_address  s[     !!*-%/3/?/?  ,&&@@BBBHI 	Cs   AA0A.A0c                    ||d}| j                   r| j                  |      |d<   n| j                  |d<   t        j	                  d| dt        | j                                 |S )a  
        Get kwargs for creating a tab based on the WebSocket address.
        If the WebSocket address is set, the tab will be created with the WebSocket address.
        Otherwise, the tab will be created with the connection port and target ID.

        Args:
            target_id: Target ID of the tab.
            browser_context_id: Browser context ID of the tab.

        Returns:
            Dict of kwargs for creating a tab.
        )r{   r   ru   rU   zTab kwargs resolved for z: using_ws=)rK   _get_tab_ws_addressrH   rP   rQ   r   )rS   r{   r   kwargss       rV   r   zBrowser._get_tab_kwargs  sm     #"4"
 #'#;#;I#FF< (,(=(=F$%/	{+d4K[K[F\E]^_rX   c                   | j                   st        d      t        | j                         }d| }t        |j                  |j
                  ||j                  |j                  f      }t        j                  d|        |S )a  
        Get WebSocket address for a specific tab, preserving any query or fragment
        components present in the original browser-level WebSocket URL.

        This ensures authentication tokens passed via query string (e.g.,
        ws://host/devtools/browser/abc?token=XYZ) are retained when switching
        to the page-level endpoint (devtools/page/<tab_id>), which is critical
        for providers like Browserless or authenticated CDP proxies.
        zWebSocket address is not setz/devtools/page/z Resolved tab WebSocket address: )
rK   r    r   r   schemenetlocqueryfragmentrP   rQ   )rS   rr  parts	page_pathwss        rV   r  zBrowser._get_tab_ws_address  ss     )*HII))*%fX.	u||YU^^\]7t<=	rX   c                   d| v r| nd|  }t        |      }|j                  }d}d|v rs|j                  dd      \  }}d|v r|j                  dd      \  }}n|d}}||f}t        |j                  ||j
                  |j                  |j                  f      }	|	|fS t        |j                  |j                  |j
                  |j                  |j                  f      }	|	|fS )a  Strip credentials from a proxy URL and return sanitized URL plus (user, pass).

        Accepts inputs like:
        - username:password@host:port
        - http://username:password@host:port
        - socks5://username:password@host:port
        - host:port (no credentials)
        Returns a (sanitized_proxy, (user, pass) | None).
        Ensures scheme is present in the sanitized URL (defaults to http).
        z://zhttp://N@rz   :rB   )r   r  r   r   r  rf   r  r  )
r   baser  r  rP  	cred_part	host_partuserpwd	sanitizeds
             rV   r   z(Browser._sanitize_proxy_and_extract_auth  s      %4|GL>:R+/&=#)<<Q#7 Iyi%OOC3	c%rc3KE"

$ I  % #

$ I %rX   c                     y)z@Get default browser executable path (implemented by subclasses).Nr  rZ   s    rV   r   z$Browser._get_default_binary_location"  s     	rX   r  )rT   r(   rU   Optional[int])returnz	'Browser')ru   strr  r   )F)rC   r   r  r   )NN)r   Optional[str]r   r  r  r  )r   r  )r  z	list[str])rB   N)r   r  r   r  r  r   )r  list[TargetInfo])r  z	list[Tab])r   r>   r  r   )rf   r  r   r  )NNF)r   r#   r   r  r   r  r   r   )r   r  )r   zlist[CookieParam]r   r  )r   r  r  zlist[Cookie])r  r.   )r{   r  r  int)r   r   r  r  )r  r  )r   r0   )r   zlist[PermissionType]r   r  r   r  )r  r  r  zCallable[[Any], Any]r  r   r  r  )r  r  r  zCallable[[Any], Awaitable[Any]]r  r   r  r  )r  r   r  r  )r  r  )FN)r  r   r  zOptional[ResourceType])NNNNN)r'  r  r   r  r(  zOptional[RequestMethod]r)  r  r*  Optional[list[HeaderEntry]]r+  zOptional[bool])r'  r  r/  r6   )NNN)
r'  r  r1  r  r2  r  r3  r  r4  r  )rU   r  )r  r2   )r  r2   r@  r  rA  r  )r  r2   r   r   )r  r2   r   r   r@  r  rA  r  )r   r   r   r  r  None)r   r   r  r  )r  r  )rg  r   rh  z#tuple[Optional[str], Optional[str]])r   r>   r  r   )r   r  r  r  )
   )ra   r  r  r   )rT  )rx  z+Command[T_CommandParams, T_CommandResponse]ra   r  r  r,   )r  r'   )rn   r  )ru   r  )r{   r  r   r  r  r   )rr  r  r  r  )r   r  r  z%tuple[str, Optional[tuple[str, str]]])r  r  )D__name__
__module____qualname____doc__rW   r[   ro   rw   r   ri   rj   r   r   r   r   r   rs   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r	  r  r  r   r#  r%  r,  r.  r5  staticmethodrD   r;  rD  rF  rI  r   r   rZ  r   r   rk  r   rh   r   r   r~  r|  rb   r  rr   r   r  r   r   r   r  rX   rV   r@   r@   M   s    *.
.
 '
@
/,*XH,/ VZ$)$ER$	$L
761(@
	
 (,,0$
"
 %
 *	

 
<^ OSe(e>Ke-".>	A\\
a !%,0	
)
 
 *	
.b
 QV)=JN	  \a)HUY	 
BK &+04
"
 .
:W
X
Y "*.#'/3-1

 
 (	

 !
 -
 +
0a 9=")-

 
 6	

 
 '
. * *7! & &	. 6 6 ! & &	 * 
 
,9 
	 
D<
)
!
6Y
6 c c  6 TVXBXMPX	XNCZ@ 
 
J0( ( ( 	.(  ( T  rX   r@   )^
__future__r   r   r  loggingre   rc   r|   abcr   r   
contextlibr   	functoolsr   randomr   typingr	   r
   r   r   r   r   urllib.parser   r   pydoll.browser.managersr   r   r   pydoll.browser.tabr   pydoll.commandsr   r   r   r   r   r   r   pydoll.connectionr   pydoll.exceptionsr   r   r   r    r!   r"   pydoll.protocol.browser.typesr#   pydoll.protocol.fetch.eventsr$   pydoll.protocol.fetch.typesr%   pydoll.utils.user_agent_parserr&   tempfiler'   pydoll.browser.interfacesr(   pydoll.protocol.baser)   r*   r+   r,   pydoll.protocol.browser.methodsr-   r.   r/   r0   r1   r2   r3   pydoll.protocol.network.typesr4   r5   r6   r7   r8   pydoll.protocol.storage.methodsr9   pydoll.protocol.target.methodsr:   r;   r<   r=   pydoll.protocol.target.typesr>   	getLoggerr  rP   r@   r  rX   rV   <module>r     s    "    	   #    N N - 
 #   0  ; 3 A :+?ZZ 
 E?7  C  8			8	$Xc XrX   