From 14229f898d1309e18b179d2af02bb0c5e0722d0b Mon Sep 17 00:00:00 2001 From: girst Date: Thu, 2 Jan 2020 16:46:26 +0100 Subject: [PATCH] WIP: workarounds --- extension/lib/config.coffee | 6 +- extension/lib/main.coffee | 8 +++ extension/lib/options.coffee | 57 +++++++++++++++ extension/lib/utils.coffee | 10 +++ extension/lib/workarounds.coffee | 92 +++++++++++++++++++++++++ extension/locale/en-US/vimfx.properties | 11 +++ 6 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 extension/lib/workarounds.coffee diff --git a/extension/lib/config.coffee b/extension/lib/config.coffee index ccfe9af..d4e97b5 100644 --- a/extension/lib/config.coffee +++ b/extension/lib/config.coffee @@ -30,10 +30,11 @@ load = (vimfx, options = null, callback = ->) -> messageManager.send('loadConfig', null, callback) +# returns true if the sandbox prevents access to frame.js checkSandbox = (expandedDir) -> prefix = 'security.sandbox.content' - if prefs.root.get("#{prefix}.level") > 2 - return true + if prefs.root.get("#{prefix}.level") <= 2 + return false if Services.appinfo.OS == 'Darwin' whitelisted = [ @@ -70,6 +71,7 @@ loadFile = (dir, file, scope) -> return error module.exports = { + checkSandbox load loadFile } diff --git a/extension/lib/main.coffee b/extension/lib/main.coffee index 84f3e77..62cd279 100644 --- a/extension/lib/main.coffee +++ b/extension/lib/main.coffee @@ -23,6 +23,14 @@ test = require('../test/index') {AddonManager} = Cu.import('resource://gre/modules/AddonManager.jsm', {}) module.exports = (data, reason) -> + if 0 # TODO: check if workarounds necessary; move to better location; implement callbacks; localize + utils.showPopupNotification( + 'vimfx-require-workaround', + 'VimFx needs to apply some about:config changes to function properly', + {'label':'Apply automatically', 'accessKey': 'A', 'callback': ()=>{}}, + [{'label':'See details', 'accessKey': 'S', 'callback': ()=>{}}, + {'label':'Ignore', 'accessKey': 'I', 'callback': ()=>{}}] + ) # Set default prefs and apply migrations as early as possible. prefs.default.init() applyMigrations(migrations) diff --git a/extension/lib/options.coffee b/extension/lib/options.coffee index e3e1de7..ae4e44d 100644 --- a/extension/lib/options.coffee +++ b/extension/lib/options.coffee @@ -5,6 +5,7 @@ prefs = require('./prefs') prefsBulk = require('./prefs-bulk') translate = require('./translate') utils = require('./utils') +workarounds = require('./workarounds') TYPE_MAP = { string: 'string' @@ -125,6 +126,7 @@ class Observer extends BaseObserver @injectHeader() @injectOptions() @injectShortcuts() + @injectWorkarounds() @setupKeybindings() if @vimfx.goToCommand @@ -205,6 +207,61 @@ class Observer extends BaseObserver return + injectWorkarounds: -> + @appendSetting({ + type: 'control' + title: translate('category.workaround') + class: 'first-row' + }) + + #-- + onclickHandler = (w, undo, thisButton, otherButton, restartButton) -> + thisButton.disabled = true + if undo then w.undo() else w.apply() + + if w.is_applied() ^ undo # ok + if w.restart + restartButton.disabled = false + restartButton.closest('.setting').querySelector('.desc').hidden = false + otherButton.disabled = false + else # error + description = thisButton.closest('.setting').querySelector('.desc') + description.innerText = translate('error.workaround_not_applied') + description.style.color = '#700' + #-- + restartButton = @document.createElement('button') + for w in workarounds.filter((w) -> w.is_required()) + #do (w) => # using this local variable in closures + setting = @appendSetting({ + type: 'control' + title: w.name + desc: w.desc + }) + applyButton = @document.createElement('button') + removeButton = @document.createElement('button') + applyButton.innerText = translate("workaround.apply") + applyButton.disabled = w.is_applied() + applyButton.onclick = onclickHandler.bind(null, w, false, applyButton, removeButton, restartButton) + setting.querySelector('.control').appendChild(applyButton) + removeButton.innerText = translate("workaround.remove") + removeButton.disabled = not w.is_applied() + removeButton.onclick = onclickHandler.bind(null, w, true, removeButton, applyButton, restartButton) + setting.querySelector('.control').appendChild(removeButton) + + restartSetting = @appendSetting({ + type: 'control' + title: translate('workaround.restart_title') + desc: translate('workaround.restart_desc') + }) + restartButton.disabled = true + restartButton.innerText = translate('workaround.restart') + restartButton.onclick = -> + Services.startup.quit( + Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart + ) + restartSetting.querySelector('.control').appendChild(restartButton) + restartSetting.querySelector('.desc').hidden = true + generateErrorMessage: (pref) -> commandErrors = @vimfx.errors[pref] ? [] return commandErrors.map(({id, context, subject}) -> diff --git a/extension/lib/utils.coffee b/extension/lib/utils.coffee index 4f89bb3..af9514d 100644 --- a/extension/lib/utils.coffee +++ b/extension/lib/utils.coffee @@ -718,6 +718,14 @@ openPopup = (popup) -> writeToClipboard = (text) -> nsIClipboardHelper.copyString(text) +# Displays a 'doorhanger' notification +showPopupNotification = + (popupId, message, mainAction, secondaryActions, learnMoreURL) -> + window = Services.wm.getMostRecentWindow('navigator:browser') + window.PopupNotifications.show(window.gBrowser.selectedBrowser, popupId, + message, null, mainAction, secondaryActions, {learnMoreURL, + 'popupIconURL': "#{ADDON_PATH}/content/skin/icon128.png"}) + module.exports = { @@ -791,4 +799,6 @@ module.exports = { openDropdown openPopup writeToClipboard + + showPopupNotification } diff --git a/extension/lib/workarounds.coffee b/extension/lib/workarounds.coffee new file mode 100644 index 0000000..15bc6ff --- /dev/null +++ b/extension/lib/workarounds.coffee @@ -0,0 +1,92 @@ +config = require('./config') +prefs = require('./prefs') +utils = require('./utils') +vimfx = require('./vimfx') + +sandbox = 'security.sandbox.content' + +module.exports = [ + { + name: 'Devtools stuck in normal mode' + desc: 'When blurring and refocusing the devtools, VimFx will not enter + ignore mode when focusing an input element. This workarounds sets + devtools.toolbox.content-frame to false.' + regressed_by: [1539979] + more_info: ['http://bugzil.la/1585747'] # bug we rely on to be open + is_applied: -> prefs.root.get('devtools.toolbox.content-frame') == false + is_required: -> + Cu.importGlobalProperties(['XMLHttpRequest']) + xhr = new XMLHttpRequest() # using XHR, as we need result synchronously + xhr.open( + 'GET', 'resource://devtools/client/framework/toolbox-hosts.js', false + ) + xhr.overrideMimeType('text/plain') # prevent non-fatal 'XML Parsing Error' + xhr.send() + return xhr.response.includes('devtools.toolbox.content-frame') + apply: -> prefs.root.set('devtools.toolbox.content-frame', false) + undo: -> prefs.root.set('devtools.toolbox.content-frame', null) + restart: false + }, + { + name: 'frame.js needs sandbox whitelisting' + desc: 'The browser is preventing access to the config script. This + workaround will add it to the read-only whitelist + (security.sandbox.content.read_path_whitelist on non-OSX systems or + security.sandbox.content.mac.testing_read_path1 or 2 on OSX).' + regressed_by: [1288874] + # coffeelint: disable=max_line_length + more_info: ["#{vimfx.info?.homepageURL}/tree/master/documentation/config-file.md#on-process-sandboxing"] + # coffeelint: enable=max_line_length + is_applied: -> + dir = prefs.get('config_file_directory') + return true unless dir + dir = utils.expandPath(dir) + return not config.checkSandbox(dir) + is_required: -> + prefs.get('config_file_directory') != '' and + prefs.root.get("#{sandbox}.level") > 2 + apply: -> + dir = prefs.get('config_file_directory') + return unless dir + seperator = if Services.appinfo.OS == 'WINNT' then '\\' else '/' + dir = utils.expandPath(dir) + seperator + if Services.appinfo.OS == 'Darwin' + if not prefs.root.get("#{sandbox}.mac.testing_read_path1")? + prefs.root.set("#{sandbox}.mac.testing_read_path1", dir) + else if not prefs.root.get("#{sandbox}.mac.testing_read_path2")? + prefs.root.set("#{sandbox}.mac.testing_read_path2", dir) + else + console.error('all whitelist prefs occupied, refusing to overwrite.') + else + val = prefs.root.get("#{sandbox}.read_path_whitelist").split(',') + val = val.filter((e) -> e != '') + val.push(dir) + prefs.root.set("#{sandbox}.read_path_whitelist", val.join(',')) + undo: -> + dir = prefs.get('config_file_directory') + return unless dir + dir = utils.expandPath(dir) + if Services.appinfo.OS == 'Darwin' + if prefs.root.get("#{sandbox}.mac.testing_read_path1")?.startsWith(dir) + prefs.root.set("#{sandbox}.mac.testing_read_path1", null) + if prefs.root.get("#{sandbox}.mac.testing_read_path2")?.startsWith(dir) + prefs.root.set("#{sandbox}.mac.testing_read_path2", null) + else + val = prefs.root.get("#{sandbox}.read_path_whitelist").split(',') + val = val.filter((e) -> !e.startsWith(dir)) + prefs.root.set("#{sandbox}.read_path_whitelist", val.join(',')) + restart: false + }, + { + name: 'Fission is enabled' + desc: 'VimFx is not fission compatible. This workaround flips the + fission.autostart pref off.' + regressed_by: [] + more_info: ['http://bugzil.la/fission'] + is_applied: -> prefs.root.get('fission.autostart') == false + is_required: -> prefs.root.get('fission.autostart') == true + apply: -> prefs.root.set('fission.autostart', false) + undo: -> prefs.root.set('fission.autostart', null) + restart: true + }, +] diff --git a/extension/locale/en-US/vimfx.properties b/extension/locale/en-US/vimfx.properties index b7bcc6f..fc16064 100644 --- a/extension/locale/en-US/vimfx.properties +++ b/extension/locale/en-US/vimfx.properties @@ -208,6 +208,16 @@ prefs.import.label=Import prefs.import.enter=Paste exported VimFx options: prefs.import.success=Pasted VimFx options successfully imported. +category.workaround=Workarounds +#workaround.status=Status +#workaround.applied=Applied +#workaround.not_applied=Not applied +workaround.apply=Apply +workaround.remove=Remove +workaround.restart=Restart now +workaround.restart_title=Restart browser +workaround.restart_desc=A workaround requires a browser restart to work correctly. + error.invalid_key=%S: Invalid key. error.unknown_modifier=%S: Unknown modifier: %S. Use only a, c, m and s. error.duplicate_modifier=%S: Duplicate modifier: %S. @@ -217,3 +227,4 @@ error.lone_modifier=%S: Modifier keys cannot be used on their own. error.overridden_by=%S: Overridden by: %S error.special_key.prefix_only=%S: %S is only allowed as a prefix. error.special_key.single_only=%S: %S is only allowed in single-key shortcuts. +error.workaround_not_applied=The workaround could not be applied successfully. Please report this bug! -- 2.39.3