This repository has been archived on 2023-02-02. You can view files and clone it, but cannot push or open issues or pull requests.
barkshark-web/barkshark_web/component/web_context.py

207 lines
5.9 KiB
Python

from .. import protocol, var
from ..extensions import WebExtensions
from ..functions import connect
from ..widgets import FileChooser
class WebContext(WebKit2.WebContext):
def __init__(self, app):
self.app = app
## Setup storage
self.storage = WebKit2.WebsiteDataManager(
base_data_directory = app.path.storage,
base_cache_directory = app.path.cache
)
super().__init__(website_data_manager = self.storage)
self.extensions = WebExtensions(self)
self.set_property('use-system-appearance-for-scrollbars', True)
#self.set_web_extensions_initialization_user_data(GLib.Variant.new_string('heck'))
self.set_spell_checking_enabled(True)
self.set_favicon_database_directory(app.path.favicon)
self.set_web_extensions_directory(app.path.script.join('bin'))
self.set_cache_model(WebKit2.CacheModel(1))
self.set_use_system_appearance_for_scrollbars(True)
## Setup Cookie storage
self.cookiemanager = self.get_cookie_manager()
self.cookiemanager.set_persistent_storage(app.path.cookies, WebKit2.CookiePersistentStorage(1))
self.cookiemanager.set_accept_policy(WebKit2.CookieAcceptPolicy(2))
## Register local uri schemes
self.security_manager = self.get_security_manager()
self.security_manager.register_uri_scheme_as_local(var.local) #Local webui
self.security_manager.register_uri_scheme_as_local('bsweb://')
self.security_manager.register_uri_scheme_as_local('local://') #Renamed "file://" handler
self.security_manager.register_uri_scheme_as_secure('oauth://')
## Setup custom protocols
self.register_uri_scheme(var.local_proto, protocol.Local)
self.register_uri_scheme('bsweb', protocol.LocalWeb)
self.register_uri_scheme('sftp', protocol.Sftp)
self.register_uri_scheme('source', protocol.Source)
self.register_uri_scheme(protocol.Oauth.protocol, protocol.Oauth)
## Webkit won't let me set these normally
self.register_uri_scheme('filetp', protocol.Ftp)
self.register_uri_scheme('local', protocol.File)
## Connect context signals
self.connect('download-started', self.handle_new_download)
self.connect('user-message-received', self.extensions.handle_command)
@property
def window(self):
return self.app.window
def handle_new_download(self, context, download):
NewDownload(self, download)
class NewDownload(Gtk.Builder):
# Might use a response instead of a class var for the dialog
response = DotDict(
accept = Gtk.ResponseType.ACCEPT,
reject = Gtk.ResponseType.REJECT,
close = Gtk.ResponseType.CLOSE,
none = Gtk.ResponseType.NONE
)
def __init__(self, context, download):
super().__init__()
self.add_from_file(context.app.path.resources.join('download.ui'))
with context.app.db.session as s:
download_dir = s.get_config('download_dir')
self.app = context.app
self.context = context
self.window = context.window
self.download = download
self.cancel = False
self.data = DotDict(
filename = None,
path = download_dir,
url = download.get_request().get_uri()
)
self.dialog = self['download-window']
self.dialog.set_attached_to(context.window)
self.download.set_allow_overwrite(True)
# Connect dialog signals
self.Connect('download-filename', 'changed', self.handle_dialog_change_filename)
self.Connect('download-filename-set', 'clicked', self.handle_dialog_set_filename)
self.Connect('download-cancel', 'clicked', self.handle_dialog_close, True)
self.Connect('download-save', 'clicked', self.handle_dialog_close, False)
self.Connect('download-window', 'delete-event', self.dialog.destroy)
# Connect download signals
connect(download, 'decide-destination', self.handle_download_decide_destination, original_args=True)
connect(download, 'created-destination', self.handle_download_created_destination)
connect(download, 'failed', self.handle_download_failed, original_args=True)
connect(download, 'finished', self.handle_download_finish)
def __getitem__(self, key):
return self.get_object(key)
@property
def filename(self):
return Path(self['download-filename'].get_text())
@filename.setter
def filename(self, text):
self['download-filename'].set_text(text or '')
@property
def url(self):
return self['download-url'].get_text()
@url.setter
def url(self, text):
self['download-url'].set_text(text or '')
def Connect(self, name, signal, callback, *args, **kwargs):
return connect(self[name], signal, callback, *args, **kwargs)
def target_path(self, full=True):
path = self.data.path.join(self.data.filename)
if full:
return f'file://{path}'
return path
def handle_dialog_close(self, cancel):
self.cancel = cancel
self.dialog.destroy()
def handle_dialog_change_filename(self):
self.data.path, self.data.filename = self.filename.parent, self.filename.name
self['download-save'].set_label('Overwrite' if self.filename.exists() else 'Save')
def handle_dialog_set_filename(self):
with FileChooser(self.dialog, self.data.path, self.data.filename) as fc:
if not fc:
logging.verbose('Canceled file selector')
return
self.filename = fc
def handle_download_created_destination(self):
logging.debug(f'Created desination for file: {self.target_path(False)}')
def handle_download_decide_destination(self, download, filename):
self.data.filename = filename
self.url = self.data.url
self.filename = self.target_path(False)
self.handle_dialog_change_filename()
self.dialog.run()
if self.cancel:
download.cancel()
else:
download.set_destination(self.target_path())
def handle_download_failed(self, download, error):
if error.code == 400:
self.cancel = True
return
data = DotDict({
'args': error.args,
'code': error.code,
'domain': error.domain,
'message': error.message
})
logging.debug(data.to_json(4))
self.window.notification(f'Download failed: {self.target_path(False)}', system=True)
def handle_download_finish(self):
if not self.cancel:
self.window.notification(f'Download finished: {self.target_path(False)}', system=True)