diff options
Diffstat (limited to 'lib/settings.coffee')
| -rw-r--r-- | lib/settings.coffee | 111 |
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? |
