U
    Pf5                     @   s   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mZ d dlmZ d dlmZ dZedG dd	 d	eZG d
d dZdS )    N)BytesIO)minidom)
deprecated)WebDriverExceptionzwebdriver_prefs.json/Addons must be added after starting the sessionc                   @   s   e Zd ZdZdS )AddonFormatErrorz4Exception for not well-formed add-on manifest files.N)__name__
__module____qualname____doc__ r   r   N/tmp/pip-unpacked-wheel-ds5t_0qj/selenium/webdriver/firefox/firefox_profile.pyr   &   s   r   c                   @   s  e Zd ZdZd"ddZdd Zedd#ddZd	d
 Ze	dd Z
e	eddd ZejedddddZe	eddd ZejedddddZe	eddd ZejedddddZe	edddZdd Zedd$ddZedd d! ZdS )%FirefoxProfileNc              	   C   s   i | _ |rLtjt d}tj||tdddd || _	t
| j	d nzt | _	tjsttjtjttdd}t|t_W 5 Q R X ttjd	 | _ tjd
  D ]\}}|| j |< qdS )a  Initialises a new instance of a Firefox Profile.

        :args:
         - profile_directory: Directory of profile that you want to use. If a
           directory is passed in it will be cloned and the cloned directory
           will be used by the driver when instantiated.
           This defaults to None and will create a new
           directory when object is created.
        zwebdriver-py-profilecopyzparent.locklockz.parentlock)ignore  utf-8encodingZmutablefrozenN)_desired_preferencesospathjointempfilemkdtempshutilcopytreeignore_patterns_profile_dirchmodr   DEFAULT_PREFERENCESopendirname__file__WEBDRIVER_PREFERENCESjsonloadcopydeepcopyitems)selfZprofile_directoryZnewprofZdefault_prefskeyvaluer   r   r   __init__.   s*    
  
 zFirefoxProfile.__init__c                 C   s   || j |< dS )z0Sets the preference that we want in the profile.Nr   )r+   r,   r-   r   r   r   set_preferenceM   s    zFirefoxProfile.set_preferencer   c                 C   s   |  | d S )N)_install_extension)r+   	extensionr   r   r   add_extensionQ   s    zFirefoxProfile.add_extensionc              
   C   s   t j| jd}t j|r2t |d | | t|ddd8}| j	 D ]&\}}|
d| dt| d qLW 5 Q R X d	S )
z&Writes the desired user prefs to disk.zuser.jsi  wr   r   zuser_pref("z", z);
N)r   r   r   r   isfiler    _read_existing_userjsr"   r   r*   writer&   dumps)r+   Z
user_prefsfr,   r-   r   r   r   update_preferencesU   s    
z!FirefoxProfile.update_preferencesc                 C   s   | j S )z8Gets the profile directory that is currently being used.)r   r+   r   r   r   r   a   s    zFirefoxProfile.pathz'The port is stored in the Service classc                 C   s   | j S )z+Gets the port that WebDriver is working on.)_portr;   r   r   r   portf   s    zFirefoxProfile.port)returnc              	   C   sp   t |tstdz$t|}|dk s,|dkr4tdW n  ttfk
rV   tdY nX || _| d| j dS )z0Sets the port that WebDriver will be running on.zPort needs to be an integer   i  z)Port number must be in the range 1..65535Zwebdriver_firefox_portN)
isinstanceintr   
ValueError	TypeErrorr<   r0   )r+   r=   r   r   r   r=   l   s    
z8Allowing untrusted certs is toggled in the Options classc                 C   s
   | j d S )N webdriver_accept_untrusted_certsr/   r;   r   r   r   accept_untrusted_certs{   s    z%FirefoxProfile.accept_untrusted_certsc                 C   s"   t |tstd| d| d S )N%Please pass in a Boolean to this callrD   r@   boolr   r0   r+   r-   r   r   r   rE      s    
c                 C   s
   | j d S )N!webdriver_assume_untrusted_issuerr/   r;   r   r   r   assume_untrusted_cert_issuer   s    z+FirefoxProfile.assume_untrusted_cert_issuerc                 C   s"   t |tstd| d| d S )NrF   rJ   rG   rI   r   r   r   rK      s    
c           	   	   C   s   | j r|   t }tj|dtjddX}t| jd }t	| jD ]6\}}}|D ]&}tj
||}||||d  qRqDW 5 Q R X t| dS )z]Updates preferences and creates a zipped, base64 encoded string of
        profile directory.r4   F)strict_timestampsr?   NzUTF-8)r   r:   r   zipfileZipFileZIP_DEFLATEDlenr   r   walkr   r7   base64	b64encodegetvaluedecode)	r+   fpZzippedZ	path_rootbase_filesZfylefilenamer   r   r   encoded   s    "zFirefoxProfile.encodedc                 C   s   t d}t|ddp}|D ]d}||}z t|d| j|d< W q tk
r~   t	
d|d|d   Y qX qW 5 Q R X dS )zRReads existing preferences and adds them to desired preference
        dictionary.zuser_pref\("(.*)",\s(.*)\)r   r      r?   z5(skipping) failed to json.loads existing preference: N)recompiler"   searchr&   loadsgroupr   	Exceptionwarningswarn)r+   ZuserjsZpref_patternr9   Zusrmatchesr   r   r   r6      s    

 z$FirefoxProfile._read_existing_userjsTc              
   C   s  d}d}| drtjdtj|d  d}t|d}| D ]}| dr|tj	tj
||sttj
|| qBtj	tjtj
||sttjtj
|| ||}ttj
||d}|| W 5 Q R X qB|}|}| |}	|	d	}
|
std
| tj
| jd}tj
||
}|s|	d s|rtj|stt| t|d t||d  ntj|stj||dd |rt| dS )zInstalls addon from a filepath, url or directory of addons in the
        profile.

        - path: url, absolute path to .xpi, or directory of addons
        - unpack: whether to unpack unless specified otherwise in the install.rdf
        Nz.xpi.)suffixr/wbidz!The addon id could not be found: 
extensionsunpackr   T)symlinks)endswithr   r   r   r   splitrM   rN   namelistisdirr   makedirsr#   readr"   r7   _addon_detailsgetAssertionErrorr   existsr    r   r(   r   rmtree)r+   Zaddonrn   ZtmpdirZxpifilecompressed_filenamedatar9   Zaddon_detailsZaddon_idZextensions_dir
addon_pathr   r   r   r1      s<    





z!FirefoxProfile._install_extensionc              
   C   s  ddddd}dd }dd }dd	 }t j|s@td
| zt|rt|d8}d| kr||dW  5 Q R  W S |d}W 5 Q R X nt j	|rt j
|d}t j|rt|dd}	||	 W  5 Q R  W S Q R X tt j
|ddd}	|	 }W 5 Q R X ntd| W n> ttfk
rh }
 ztt|
t d W 5 d}
~
X Y nX zt|}||d}||d}||d d}|s|dd}|jD ]0}|j|d}||kr||||i q|ds8t|jjD ]2}|j|}|j|d kr|d|ji qW n: tk
rt }
 ztt|
t d W 5 d}
~
X Y nX t |d tr|d ! dk|d< |dstd|S )a  Returns a dictionary of details about the addon.

        :param addon_path: path to the add-on directory or XPI

        Returns::

            {'id':      u'rainbow@colors.org', # id of the addon
             'version': u'1.4',                # version of the addon
             'name':    u'Rainbow',            # name of the addon
             'unpack':  False }                # whether to unpack the addon
        NF)rl   rn   r|   versionc                 S   s^   | j j}d}t|jD ]B}||j|krd||jkr||jdd d } qZq|S )N :r?   )ZdocumentElement
attributesrangelengthitemr-   r|   rq   )docurlr   	namespaceir   r   r   get_namespace_id   s    z7FirefoxProfile._addon_details.<locals>.get_namespace_idc                 S   s6   g }| j D ]}|j|jkr
||j q
d| S )z(Retrieve the text value of a given node.r   )
childNodesZnodeTypeZ	TEXT_NODEappendr}   r   strip)elementrcnoder   r   r   get_text   s
    
z/FirefoxProfile._addon_details.<locals>.get_textc                 S   sf   t | }z|d d d }W n0 tk
rN   |d ddd |d  }Y nX ||d |d d	d
S )z[Extracts the details from the contents of a WebExtensions
            `manifest.json` file.ZapplicationsZgeckorl   r|    r   @r   F)rl   r   r|   rn   )r&   r`   KeyErrorreplace)contentmanifestrl   r   r   r   parse_manifest_json  s    
"z:FirefoxProfile._addon_details.<locals>.parse_manifest_jsonzAdd-on path does not exist: ri   zmanifest.jsonzinstall.rdfr   r   z/Add-on path is neither an XPI nor a directory: r\   z#http://www.mozilla.org/2004/em-rdf#z+http://www.w3.org/1999/02/22-rdf-syntax-ns#Descriptionr   r   rl   rn   truezAdd-on id could not be found.)"r   r   ry   OSErrorrM   
is_zipfilerN   rr   ru   rs   r   r"   r   r   strsysexc_infor   parseStringZgetElementsByTagNamer   r   nodeNamer   updaterw   r   r   r   r|   r-   rb   r@   lower)r+   r~   detailsr   r   r   r{   r   Zmanifest_json_filenamer9   er   emrdfdescriptionr   entryr   	attributer   r   r   rv      sZ    
 (




(zFirefoxProfile._addon_details)N)N)T)r   r	   r
   r!   r.   r0   r   r3   r:   propertyr   r=   setterrE   rK   r   r[   r6   r1   rv   r   r   r   r   r   +   sB   

.r   )rR   r(   r&   r   r]   r   r   r   rc   rM   ior   xml.domr   Ztyping_extensionsr   Zselenium.common.exceptionsr   r%   rb   r   r   r   r   r   r   <module>   s"   