{-# LANGUAGE CPP, TypeSynonymInstances, DeriveDataTypeable, FlexibleInstances,
GeneralizedNewtypeDeriving, OverloadedStrings, FlexibleContexts #-}{-# OPTIONS_HADDOCK not-home #-}-- |A type for profile preferences. These preference values are used by both -- Firefox and Opera profiles.moduleTest.WebDriver.Common.Profile(-- *Profiles and profile preferencesProfile(..),PreparedProfile(..),ProfilePref(..),ToPref(..)-- * Preferences,getPref,addPref,deletePref-- * Extensions,addExtension,deleteExtension,hasExtension-- * Other files,addFile,deleteFile,hasFile-- *Preparing profiles from disk,prepareLoadedProfile_-- *Preparing zipped profiles,prepareZippedProfile,prepareZipArchive,prepareRawZip-- *Profile errors,ProfileParseError(..))whereimportData.AesonimportData.Aeson.TypesimportData.Attoparsec.Number(Number(..))importqualifiedData.HashMap.StrictasHMimportData.Text(Text,pack)importData.ByteString(ByteString)importqualifiedData.ByteStringasSBSimportqualifiedData.ByteString.LazyasLBSimportqualifiedData.ByteString.Base64asB64importCodec.Archive.ZipimportSystem.DirectoryimportSystem.FilePathhiding(addExtension,hasExtension)importData.FixedimportData.RatioimportData.IntimportData.WordimportData.ListimportData.MaybeimportData.TypeableimportControl.ExceptionimportControl.ApplicativeimportControl.Monad.Base-- |This structure allows you to construct and manipulate profiles in pure code,-- deferring execution of IO operations until the profile is \"prepared\". This -- type is shared by both Firefox and Opera profile code; when a distinction -- must be made, the phantom type parameter is used to differentiate.dataProfileb=Profile{-- |A set of filepaths pointing to files to place in-- the extension directory. The first tuple element is the source -- path. The second tuple element is the destination path -- relative to the extension of the file.profileFiles::[(FilePath,FilePath)]-- |A map of Firefox preferences. These are the settings-- found in the profile's prefs.js, and entries found in-- about:config,profilePrefs::HM.HashMapTextProfilePref}deriving(Eq,Show)-- |Represents a profile that has been prepared for -- network transmission. The profile cannot be modified in this form.newtypePreparedProfileb=PreparedProfileByteStringderiving(Eq,Show)instanceFromJSON(PreparedProfiles)whereparseJSONv=PreparedProfile<$>parseJSONvinstanceToJSON(PreparedProfiles)wheretoJSON(PreparedProfiles)=toJSONs-- |A profile preference value. This is the subset of JSON values that excludes-- arrays, objects, and null.dataProfilePref=PrefInteger!Integer|PrefDouble!Double|PrefString!Text|PrefBool!Boolderiving(Eq,Show)instanceToJSONProfilePrefwheretoJSONv=casevofPrefIntegeri->toJSONiPrefDoubled->toJSONdPrefStrings->toJSONsPrefBoolb->toJSONbinstanceFromJSONProfilePrefwhereparseJSON(Strings)=return$PrefStringsparseJSON(Boolb)=return$PrefBoolbparseJSON(Number(Ii))=return$PrefIntegeriparseJSON(Number(Dd))=return$PrefDoubledparseJSONother=typeMismatch"ProfilePref"otherinstanceExceptionProfileParseError-- |An error occured while attempting to parse a profile's preference file.newtypeProfileParseError=ProfileParseErrorStringderiving(Eq,Show,Read,Typeable)-- |A typeclass to convert types to profile preference valuesclassToPrefawheretoPref::a->ProfilePrefinstanceToPrefTextwheretoPref=PrefStringinstanceToPrefStringwheretoPref=toPref.packinstanceToPrefBoolwheretoPref=PrefBoolinstanceToPrefIntegerwheretoPref=PrefInteger#define I(t) instance ToPref t where toPref = PrefInteger . toIntegerI(Int)I(Int8)I(Int16)I(Int32)I(Int64)I(Word)I(Word8)I(Word16)I(Word32)I(Word64)instanceToPrefDoublewheretoPref=PrefDoubleinstanceToPrefFloatwheretoPref=PrefDouble.realToFracinstance(Integrala)=>ToPref(Ratioa)wheretoPref=PrefDouble.realToFracinstance(HasResolutionr)=>ToPref(Fixedr)wheretoPref=PrefDouble.realToFrac-- |Retrieve a preference from a profile by key name.getPref::Text->Profileb->MaybeProfilePrefgetPrefk(Profile_m)=HM.lookupkm-- |Add a new preference entry to a profile, overwriting any existing entry-- with the same key.addPref::ToPrefa=>Text->a->Profileb->ProfilebaddPrefkvp=asMapp$HM.insertk(toPrefv)-- |Delete an existing preference entry from a profile. This operation is-- silent if the preference wasn't found.deletePref::Text->Profileb->ProfilebdeletePrefkp=asMapp$HM.deletek-- |Add a file to the profile directory. The first argument is the source-- of the file on the local filesystem. The second argument is the destination -- as a path relative to a profile directory. addFile::FilePath->FilePath->Profileb->ProfilebaddFilesrcdestp=asListp((src,dest):)-- |Delete a file from the profile directory. The first argument is the name of-- file within the profile directory.deleteFile::FilePath->Profileb->ProfilebdeleteFilepathprof=asListprof$filter(\(_,p)->p==path)-- |Determines if a profile contains the given file. specified as a path relative to-- the profile directory.hasFile::String->Profileb->BoolhasFilepath(Profilefiles_)=isJust$find(\(_,d)->d==path)files-- |Add a new extension to the profile. The file path should refer to-- an .xpi file or an extension directory on the filesystem. If possible,-- you should avoiding adding the same extension twice to a given profile.addExtension::FilePath->Profileb->ProfilebaddExtensionpath=addFilepath("extensions"</>name)where(_,name)=splitFileNamepath-- |Delete an existing extension from the profile. The string parameter -- should refer to an .xpi file or directory located within the extensions -- directory of the profile. This operation has no effect if the extension was -- never added to the profile.deleteExtension::String->Profileb->ProfilebdeleteExtensionname=deleteFile("extensions"</>name)-- |Determines if a profile contains the given extension. specified as an .xpi file -- or directory namehasExtension::String->Profileb->BoolhasExtensionnameprof=hasFile("extensions"</>name)profasMap::Profileb->(HM.HashMapTextProfilePref->HM.HashMapTextProfilePref)->ProfilebasMap(Profilehshm)f=Profilehs(fhm)asList::Profileb->([(FilePath,FilePath)]->[(FilePath,FilePath)])->ProfilebasList(Profilelshm)f=Profile(fls)hm-- |Efficiently load an existing profile from disk and prepare it for network-- transmission.prepareLoadedProfile_::MonadBaseIOm=>FilePath->m(PreparedProfilea)prepareLoadedProfile_path=liftBase$dooldWd<-getCurrentDirectorysetCurrentDirectorypathprepareZipArchive<$>liftBase(addFilesToArchive[OptRecursive]emptyArchive["."])<*setCurrentDirectoryoldWd-- |Prepare a zip file of a profile on disk for network transmission.-- This function is very efficient at loading large profiles from disk.prepareZippedProfile::MonadBaseIOm=>FilePath->m(PreparedProfilea)prepareZippedProfilepath=prepareRawZip<$>liftBase(LBS.readFilepath)-- |Prepare a zip archive of a profile for network transmission.prepareZipArchive::Archive->PreparedProfileaprepareZipArchive=prepareRawZip.fromArchive-- |Prepare a ByteString of raw zip data for network transmissionprepareRawZip::LBS.ByteString->PreparedProfileaprepareRawZip=PreparedProfile.B64.encode.SBS.concat.LBS.toChunks