Support persisting clipboard prompt choices
All the promptable feature permissions so far have been of type BoolAsk. The prompt uses a "yesno" mode prompt and only results in a bool. The persistence logic only supports bools. Previously I made the shared prompt support the String type clipboard permission setting by treating non "ask" values as False (you only get prompted if the global setting is "none" anyway), but saving the prompt results with `:prompt-accept --save` didn't work because the persistence code only supported bools. What we want to do when saving is convert `False` to "none" and `True` to "access-paste". This mirrors the new webengine logic. It does mean we can't let users choose to persist either none/access/access-paste, but webengine doesn't prompt us if the page is already allowed "access" but is trying to paste anyway. If it did we would have to use a non-yesno prompt for this (perhaps it could be driven directly by the ConfigType). For now I've added a new concept to the ConfigTypes to allow them to be casted to and from bools, so that we can plumb this String type from the boolean yesno prompt. TODO: * try to make it an interface so we don't have to use `hasattr` (even if it means multiple inheritance) * add test coverage to test_configtypes.py
This commit is contained in:
parent
4c3337f553
commit
fbd148f983
|
|
@ -303,6 +303,7 @@ def feature_permission(url, option, msg, yes_action, no_action, abort_on,
|
|||
None otherwise.
|
||||
"""
|
||||
config_val = config.instance.get(option, url=url)
|
||||
opt = config.instance.get_opt(option)
|
||||
if config_val == 'ask':
|
||||
if url.isValid():
|
||||
urlstr = url.toString(QUrl.UrlFormattingOption.RemovePassword | QUrl.ComponentFormattingOption.FullyEncoded)
|
||||
|
|
@ -328,20 +329,21 @@ def feature_permission(url, option, msg, yes_action, no_action, abort_on,
|
|||
cancel_action=no_action, abort_on=abort_on,
|
||||
title='Permission request', text=text, url=urlstr,
|
||||
option=option)
|
||||
elif config_val is True:
|
||||
|
||||
if hasattr(opt.typ, "to_bool"):
|
||||
config_val = opt.typ.to_bool(config_val)
|
||||
|
||||
if config_val is True:
|
||||
yes_action()
|
||||
return None
|
||||
elif config_val is False:
|
||||
no_action()
|
||||
return None
|
||||
else:
|
||||
if option not in {
|
||||
"content.javascript.clipboard" # String type option with 'ask' value
|
||||
}:
|
||||
log.misc.warning(
|
||||
f"Unsupported value for permission prompt setting ({option}), expected boolean or "
|
||||
f"'ask', got: {config_val} ({type(config_val)})"
|
||||
)
|
||||
log.misc.warning(
|
||||
f"Unsupported value for permission prompt setting ({option}), expected boolean or "
|
||||
f"'ask', got: {config_val} ({type(config_val)})"
|
||||
)
|
||||
no_action()
|
||||
return None
|
||||
|
||||
|
|
|
|||
|
|
@ -925,7 +925,7 @@ content.javascript.alert:
|
|||
content.javascript.clipboard:
|
||||
default: ask
|
||||
type:
|
||||
name: String
|
||||
name: JSClipboardPermission
|
||||
valid_values:
|
||||
- none: Disable access to clipboard.
|
||||
- access: Allow reading from and writing to the clipboard.
|
||||
|
|
|
|||
|
|
@ -2016,3 +2016,20 @@ class StatusbarWidget(String):
|
|||
if value.startswith("text:") or value.startswith("clock:"):
|
||||
return
|
||||
super()._validate_valid_values(value)
|
||||
|
||||
|
||||
class JSClipboardPermission(String):
|
||||
|
||||
"""Permission for page JS to access the system clipboard.
|
||||
|
||||
String + BoolAsk
|
||||
"""
|
||||
|
||||
def to_bool(self, value: str) -> bool:
|
||||
return value == "access-paste"
|
||||
|
||||
def from_bool(self, value: bool) -> str:
|
||||
if value is True:
|
||||
return "access-paste"
|
||||
else:
|
||||
return "none"
|
||||
|
|
|
|||
|
|
@ -976,12 +976,23 @@ class YesNoPrompt(_BasePrompt):
|
|||
raise Error("Invalid value {} - expected yes/no!".format(value))
|
||||
|
||||
if save:
|
||||
value = self.question.answer
|
||||
opt = config.instance.get_opt(self.question.option)
|
||||
assert isinstance(opt.typ, configtypes.Bool)
|
||||
if isinstance(opt.typ, configtypes.Bool):
|
||||
pass
|
||||
elif hasattr(opt.typ, "from_bool"):
|
||||
value = opt.typ.from_bool(value)
|
||||
else:
|
||||
raise AssertionError(
|
||||
"Cannot save prompt answer. Expected 'Bool' option or "
|
||||
"option with 'from_bool()'. "
|
||||
f"option={opt.name} type={type(opt.typ)}"
|
||||
)
|
||||
|
||||
pattern = urlmatch.UrlPattern(self.question.url)
|
||||
|
||||
try:
|
||||
config.instance.set_obj(opt.name, self.question.answer,
|
||||
config.instance.set_obj(opt.name, value,
|
||||
pattern=pattern, save_yaml=True)
|
||||
except configexc.Error as e:
|
||||
raise Error(str(e))
|
||||
|
|
|
|||
|
|
@ -271,6 +271,19 @@ Feature: Prompts
|
|||
Then the javascript message "Failed to read from clipboard." should be logged
|
||||
And I run :config-unset -u localhost:* content.javascript.clipboard
|
||||
|
||||
@qt>=6.8
|
||||
Scenario: Clipboard - ask allow persistent - paste
|
||||
Given I may need a fresh instance
|
||||
When I set content.javascript.clipboard to ask
|
||||
And I open data/prompt/clipboard.html
|
||||
And I run :click-element id paste
|
||||
And I wait for a prompt
|
||||
And I run :prompt-accept --save yes
|
||||
And I wait for "*Text pasted: *" in the log
|
||||
And I reload
|
||||
And I run :click-element id paste
|
||||
Then the javascript message "Text pasted: *" should be logged
|
||||
|
||||
# SSL
|
||||
|
||||
Scenario: SSL error with content.tls.certificate_errors = load-insecurely
|
||||
|
|
|
|||
Loading…
Reference in New Issue