Source code for openwpm.commands.profile_commands
import logging
import tarfile
from pathlib import Path
from selenium.webdriver import Firefox
from openwpm.config import BrowserParamsInternal, ManagerParamsInternal
from ..errors import ProfileLoadError
from ..socket_interface import ClientSocket
from .types import BaseCommand
from .utils.firefox_profile import sleep_until_sqlite_checkpoint
logger = logging.getLogger("openwpm")
[docs]
def dump_profile(
browser_profile_path: Path,
tar_path: Path,
compress: bool,
browser_params: BrowserParamsInternal,
) -> None:
"""Dumps a browser profile to a tar file.
Should only be called when the browser is closed, to prevent
database corruption in the archived profile (see section 1.2
of https://www.sqlite.org/howtocorrupt.html).
"""
assert browser_params.browser_id is not None
# Creating the folders if need be
tar_path.parent.mkdir(exist_ok=True, parents=True)
# see if this file exists first
# if it does, delete it before we try to save the current session
if tar_path.exists():
tar_path.unlink()
# backup and tar profile
if compress:
tar = tarfile.open(tar_path, "w:gz", errorlevel=1)
else:
tar = tarfile.open(tar_path, "w", errorlevel=1)
logger.debug(
"BROWSER %i: Backing up full profile from %s to %s"
% (browser_params.browser_id, browser_profile_path, tar_path)
)
tar.add(browser_profile_path, arcname="")
archived_items = tar.getnames()
tar.close()
required_items = [
"cookies.sqlite", # cookies
"places.sqlite", # history
"storage.sqlite", # localStorage
]
for item in required_items:
if item not in archived_items:
logger.critical(
"BROWSER %i: %s NOT FOUND IN profile folder"
% (browser_params.browser_id, item)
)
raise RuntimeError("Profile dump not successful")
[docs]
class DumpProfileCommand(BaseCommand):
"""
Dumps a browser profile currently stored in <browser_params.profile_path> to
<tar_path>.
"""
def __init__(
self, tar_path: Path, close_webdriver: bool, compress: bool = True
) -> None:
self.tar_path = tar_path
self.close_webdriver = close_webdriver
self.compress = compress
def __repr__(self) -> str:
return "DumpProfileCommand({},{},{})".format(
self.tar_path, self.close_webdriver, self.compress
)
[docs]
def execute(
self,
webdriver: Firefox,
browser_params: BrowserParamsInternal,
manager_params: ManagerParamsInternal,
extension_socket: ClientSocket,
) -> None:
# if this is a dump on close, close the webdriver and wait for checkpoint
if self.close_webdriver:
webdriver.close()
sleep_until_sqlite_checkpoint(browser_params.profile_path)
assert browser_params.profile_path is not None
dump_profile(
browser_params.profile_path,
self.tar_path,
self.compress,
browser_params,
)
[docs]
def load_profile(
browser_profile_path: Path,
browser_params: BrowserParamsInternal,
tar_path: Path,
) -> None:
"""
Loads a zipped cookie-based profile stored at <tar_path> and unzips
it to <browser_profile_path>. The tar will remain unmodified.
"""
assert browser_params.browser_id is not None
try:
assert tar_path.is_file()
# Untar the loaded profile
if tar_path.name.endswith("tar.gz"):
f = tarfile.open(tar_path, "r:gz", errorlevel=1)
else:
f = tarfile.open(tar_path, "r", errorlevel=1)
f.extractall(browser_profile_path)
f.close()
logger.debug("BROWSER %i: Tarfile extracted" % browser_params.browser_id)
except Exception as ex:
logger.critical(
"BROWSER %i: Error: %s while attempting to load profile"
% (browser_params.browser_id, str(ex))
)
raise ProfileLoadError("Profile Load not successful")