aboutsummaryrefslogtreecommitdiffstats
path: root/lib/settings.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'lib/settings.coffee')
-rw-r--r--lib/settings.coffee111
1 files changed, 57 insertions, 54 deletions
diff --git a/lib/settings.coffee b/lib/settings.coffee
index 92871ee2..4bfbcbf4 100644
--- a/lib/settings.coffee
+++ b/lib/settings.coffee
@@ -10,9 +10,15 @@
#
# In all cases except Settings.defaults, values are stored as jsonified strings.
+# If the current frame is the Vomnibar or the HUD, then we'll need our Chrome stubs for the tests.
+# We use "try" because this fails within iframes on Firefox (where failure doesn't actually matter).
+try window.chrome ?= window.top?.chrome
+
+storageArea = if chrome.storage.sync? then "sync" else "local"
+
Settings =
debug: false
- storage: chrome.storage.sync
+ storage: chrome.storage[storageArea]
cache: {}
isLoaded: false
onLoadedCallbacks: []
@@ -25,16 +31,26 @@ Settings =
@cache = if Utils.isBackgroundPage() then localStorage else extend {}, localStorage
@runOnLoadedCallbacks()
- chrome.storage.local.get null, (localItems) =>
- localItems = {} if chrome.runtime.lastError
- @storage.get null, (syncedItems) =>
- unless chrome.runtime.lastError
- @handleUpdateFromChromeStorage key, value for own key, value of extend localItems, syncedItems
+ # Test chrome.storage.sync to see if it is enabled.
+ # NOTE(mrmr1993, 2017-04-18): currently the API is defined in FF, but it is disabled behind a flag in
+ # about:config. Every use sets chrome.runtime.lastError, so we use that to check whether we can use it.
+ chrome.storage.sync.get null, =>
+ if chrome.runtime.lastError
+ storageArea = "local"
+ @storage = chrome.storage[storageArea]
- chrome.storage.onChanged.addListener (changes, area) =>
- @propagateChangesFromChromeStorage changes if area == "sync"
+ # Delay this initialisation until after the correct storage area is known. The significance of this is
+ # that it delays the on-loaded callbacks.
+ chrome.storage.local.get null, (localItems) =>
+ localItems = {} if chrome.runtime.lastError
+ @storage.get null, (syncedItems) =>
+ unless chrome.runtime.lastError
+ @handleUpdateFromChromeStorage key, value for own key, value of extend localItems, syncedItems
- @runOnLoadedCallbacks()
+ chrome.storage.onChanged.addListener (changes, area) =>
+ @propagateChangesFromChromeStorage changes if area == storageArea
+
+ @runOnLoadedCallbacks()
# Called after @cache has been initialized. On extension pages, this will be called twice, but that does
# not matter because it's idempotent.
@@ -71,12 +87,15 @@ Settings =
if @shouldSyncKey key
if shouldSetInSyncedStorage
setting = {}; setting[key] = @cache[key]
- @log " chrome.storage.sync.set(#{key})"
+ @log " chrome.storage.#{storageArea}.set(#{key})"
@storage.set setting
- if Utils.isBackgroundPage()
+ if Utils.isBackgroundPage() and storageArea == "sync"
# Remove options installed by the "copyNonDefaultsToChromeStorage-20150717" migration; see below.
@log " chrome.storage.local.remove(#{key})"
chrome.storage.local.remove key
+ # NOTE(mrmr1993): In FF, |value| will be garbage collected when the page owning it is unloaded.
+ # Any postUpdateHooks that can be called from the options page/exclusions popup should be careful not to
+ # use |value| asynchronously, or else it may refer to a |DeadObject| and accesses will throw an error.
@performPostUpdateHook key, value
clear: (key) ->
@@ -98,7 +117,7 @@ Settings =
nuke: (key) ->
delete localStorage[key]
chrome.storage.local.remove key
- chrome.storage.sync.remove key
+ chrome.storage.sync?.remove key
# For development only.
log: (args...) ->
@@ -153,23 +172,23 @@ Settings =
# put in an example search engine
searchEngines:
"""
- w: http://www.wikipedia.org/w/index.php?title=Special:Search&search=%s Wikipedia
+ w: https://www.wikipedia.org/w/index.php?title=Special:Search&search=%s Wikipedia
# More examples.
#
# (Vimium supports search completion Wikipedia, as
# above, and for these.)
#
- # g: http://www.google.com/search?q=%s Google
- # l: http://www.google.com/search?q=%s&btnI I'm feeling lucky...
- # y: http://www.youtube.com/results?search_query=%s Youtube
+ # g: https://www.google.com/search?q=%s Google
+ # l: https://www.google.com/search?q=%s&btnI I'm feeling lucky...
+ # y: https://www.youtube.com/results?search_query=%s Youtube
# gm: https://www.google.com/maps?q=%s Google maps
# b: https://www.bing.com/search?q=%s Bing
# d: https://duckduckgo.com/?q=%s DuckDuckGo
- # az: http://www.amazon.com/s/?field-keywords=%s Amazon
+ # az: https://www.amazon.com/s/?field-keywords=%s Amazon
# qw: https://www.qwant.com/?q=%s Qwant
"""
- newTabUrl: "chrome://newtab"
+ newTabUrl: "about:newtab"
grabBackFocus: false
regexFindMode: false
waitForEnterForFilteredHints: false # Note: this defaults to true for new users; see below.
@@ -178,46 +197,30 @@ Settings =
helpDialog_showAdvancedCommands: false
optionsPage_showAdvancedOptions: false
passNextKeyKeys: []
+ ignoreKeyboardLayout: false
Settings.init()
# Perform migration from old settings versions, if this is the background page.
if Utils.isBackgroundPage()
+ Settings.applyMigrations = ->
+ unless Settings.get "settingsVersion"
+ # This is a new install. For some settings, we retain a legacy default behaviour for existing users but
+ # use a non-default behaviour for new users.
+
+ # For waitForEnterForFilteredHints, "true" gives a better UX; see #1950. However, forcing the change on
+ # existing users would be unnecessarily disruptive. So, only new users default to "true".
+ Settings.set "waitForEnterForFilteredHints", true
+
+ # We use settingsVersion to coordinate any necessary schema changes.
+ Settings.set("settingsVersion", Utils.getCurrentVersion())
+
+ # Remove legacy key which was used to control storage migration. This was after 1.57 (2016-10-01), and can
+ # be removed after 1.58 has been out for sufficiently long.
+ Settings.nuke "copyNonDefaultsToChromeStorage-20150717"
+
+ Settings.onLoaded Settings.applyMigrations.bind Settings
- if not Settings.get "settingsVersion"
- # This is a new install. For some settings, we retain a legacy default behaviour for existing users but
- # use a non-default behaviour for new users.
-
- # For waitForEnterForFilteredHints, we (smblott) think that "true" gives a better UX; see #1950. However,
- # forcing the change on existing users would be unnecessarily disruptive. So, only new users default to
- # "true".
- Settings.set "waitForEnterForFilteredHints", true
-
- # We use settingsVersion to coordinate any necessary schema changes.
- Settings.set("settingsVersion", Utils.getCurrentVersion())
-
- # In 1.46 we migrated the old "excludedUrls" setting to the new "exclusionRules" setting. And we kept a
- # backup in "excludedUrlsBackup". Now (post 1.54, post 2016-02-12) we can clear up that backup (and any
- # extraordinalrily old "excludedUrls" setting).
- Settings.nuke "excludedUrlsBackup"
- Settings.nuke "excludedUrls"
-
- # Migration (post 1.54, post 2016-2-12). Nuke legacy "findModeRawQuery" setting.
- Settings.nuke "findModeRawQuery"
-
- # Migration (after 1.51, 2015/6/17).
- # Copy options with non-default values (and which are not in synced storage) to chrome.storage.local;
- # thereby making these settings accessible within content scripts.
- do (migrationKey = "copyNonDefaultsToChromeStorage-20150717") ->
- unless localStorage[migrationKey]
- chrome.storage.sync.get null, (items) ->
- unless chrome.runtime.lastError
- updates = {}
- for own key of localStorage
- if Settings.shouldSyncKey(key) and not items[key]
- updates[key] = localStorage[key]
- chrome.storage.local.set updates, ->
- localStorage[migrationKey] = not chrome.runtime.lastError
-
-root = exports ? window
+root = exports ? (window.root ?= {})
root.Settings = Settings
+extend window, root unless exports?