aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authormrmr19932015-04-27 20:08:11 +0100
committermrmr19932015-05-29 12:06:00 +0100
commit0c12810c4c49ade77a1c8a8b3172857e19eb01f0 (patch)
treeacd1da490584d57aa242a1cceed5803b39ed0c17 /lib
parentbfe304932b13eb1bfe65662490d3d6b830eefec7 (diff)
downloadvimium-0c12810c4c49ade77a1c8a8b3172857e19eb01f0.tar.bz2
Move settings.coffee from background_scripts/ to lib/
Diffstat (limited to 'lib')
-rw-r--r--lib/settings.coffee192
1 files changed, 192 insertions, 0 deletions
diff --git a/lib/settings.coffee b/lib/settings.coffee
new file mode 100644
index 00000000..607264a2
--- /dev/null
+++ b/lib/settings.coffee
@@ -0,0 +1,192 @@
+#
+# * Sync.set() and Sync.clear() propagate local changes to chrome.storage.sync.
+# * Sync.handleStorageUpdate() listens for changes to chrome.storage.sync and propagates those
+# changes to localStorage and into vimium's internal state.
+# * Sync.fetchAsync() polls chrome.storage.sync at startup, similarly propagating
+# changes to localStorage and into vimium's internal state.
+#
+# The effect is best-effort synchronization of vimium options/settings between
+# chrome/vimium instances.
+#
+# NOTE:
+# Values handled within this module are ALWAYS already JSON.stringifed, so
+# they're always non-empty strings.
+#
+
+root = exports ? window
+Sync =
+
+ storage: chrome.storage.sync
+ doNotSync: ["settingsVersion", "previousVersion"]
+
+ # This is called in main.coffee.
+ init: ->
+ chrome.storage.onChanged.addListener (changes, area) -> Sync.handleStorageUpdate changes, area
+ @fetchAsync()
+
+ # Asynchronous fetch from synced storage, called only at startup.
+ fetchAsync: ->
+ @storage.get null, (items) =>
+ unless chrome.runtime.lastError
+ for own key, value of items
+ Settings.storeAndPropagate key, value if @shouldSyncKey key
+
+ # Asynchronous message from synced storage.
+ handleStorageUpdate: (changes, area) ->
+ for own key, change of changes
+ Settings.storeAndPropagate key, change?.newValue if @shouldSyncKey key
+
+ # Only called synchronously from within vimium, never on a callback.
+ # No need to propagate updates to the rest of vimium, that's already been done.
+ set: (key, value) ->
+ if @shouldSyncKey key
+ setting = {}; setting[key] = value
+ @storage.set setting
+
+ # Only called synchronously from within vimium, never on a callback.
+ clear: (key) ->
+ @storage.remove key if @shouldSyncKey key
+
+ # Should we synchronize this key?
+ shouldSyncKey: (key) -> key not in @doNotSync
+
+#
+# Used by all parts of Vimium to manipulate localStorage.
+#
+
+root.Settings = Settings =
+ init: -> Sync.init()
+ get: (key) ->
+ if (key of localStorage) then JSON.parse(localStorage[key]) else @defaults[key]
+
+ set: (key, value) ->
+ # Don't store the value if it is equal to the default, so we can change the defaults in the future
+ if (value == @defaults[key])
+ @clear(key)
+ else
+ jsonValue = JSON.stringify value
+ localStorage[key] = jsonValue
+ Sync.set key, jsonValue
+
+ clear: (key) ->
+ if @has key
+ delete localStorage[key]
+ Sync.clear key
+
+ has: (key) -> key of localStorage
+
+ # For settings which require action when their value changes, add hooks to this object, to be called from
+ # options/options.coffee (when the options page is saved), and by Settings.storeAndPropagate (when an
+ # update propagates from chrome.storage.sync).
+ postUpdateHooks: {}
+
+ # postUpdateHooks convenience wrapper
+ performPostUpdateHook: (key, value) ->
+ @postUpdateHooks[key] value if @postUpdateHooks[key]
+
+ # Only ever called from asynchronous synced-storage callbacks (fetchAsync and handleStorageUpdate).
+ storeAndPropagate: (key, value) ->
+ return unless key of @defaults
+ return if value and key of localStorage and localStorage[key] is value
+ defaultValue = @defaults[key]
+ defaultValueJSON = JSON.stringify(defaultValue)
+
+ if value and value != defaultValueJSON
+ # Key/value has been changed to non-default value at remote instance.
+ localStorage[key] = value
+ @performPostUpdateHook key, JSON.parse(value)
+ else
+ # Key has been reset to default value at remote instance.
+ if key of localStorage
+ delete localStorage[key]
+ @performPostUpdateHook key, defaultValue
+
+ # options.coffee and options.html only handle booleans and strings; therefore all defaults must be booleans
+ # or strings
+ defaults:
+ scrollStepSize: 60
+ smoothScroll: true
+ keyMappings: "# Insert your preferred key mappings here."
+ linkHintCharacters: "sadfjklewcmpgh"
+ linkHintNumbers: "0123456789"
+ filterLinkHints: false
+ hideHud: false
+ userDefinedLinkHintCss:
+ """
+ div > .vimiumHintMarker {
+ /* linkhint boxes */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#FFF785),
+ color-stop(100%,#FFC542));
+ border: 1px solid #E3BE23;
+ }
+
+ div > .vimiumHintMarker span {
+ /* linkhint text */
+ color: black;
+ font-weight: bold;
+ font-size: 12px;
+ }
+
+ div > .vimiumHintMarker > .matchingCharacter {
+ }
+ """
+ # Default exclusion rules.
+ exclusionRules:
+ [
+ # Disable Vimium on Gmail.
+ { pattern: "http*://mail.google.com/*", passKeys: "" }
+ ]
+
+ # NOTE: If a page contains both a single angle-bracket link and a double angle-bracket link, then in
+ # most cases the single bracket link will be "prev/next page" and the double bracket link will be
+ # "first/last page", so we put the single bracket first in the pattern string so that it gets searched
+ # for first.
+
+ # "\bprev\b,\bprevious\b,\bback\b,<,←,«,≪,<<"
+ previousPatterns: "prev,previous,back,<,\u2190,\xab,\u226a,<<"
+ # "\bnext\b,\bmore\b,>,→,»,≫,>>"
+ nextPatterns: "next,more,>,\u2192,\xbb,\u226b,>>"
+ # default/fall back search engine
+ searchUrl: "https://www.google.com/search?q="
+ # put in an example search engine
+ searchEngines: [
+ "w: http://www.wikipedia.org/w/index.php?title=Special:Search&search=%s Wikipedia"
+ ""
+ "# More examples."
+ "#"
+ "# (Vimium has built-in completion 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"
+ "# 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"
+ "#"
+ "# Another example (for Vimium does not have completion)."
+ "#"
+ "# m: https://www.google.com/maps/search/%s Google Maps"
+ ].join "\n"
+ newTabUrl: "chrome://newtab"
+ grabBackFocus: false
+
+ settingsVersion: Utils.getCurrentVersion()
+
+# Export Sync via Settings for tests.
+root.Settings.Sync = Sync
+
+# Perform migration from old settings versions, if this is the background page.
+if Utils.isBackgroundPage()
+
+ # We use settingsVersion to coordinate any necessary schema changes.
+ if Utils.compareVersions("1.42", Settings.get("settingsVersion")) != -1
+ Settings.set("scrollStepSize", parseFloat Settings.get("scrollStepSize"))
+ Settings.set("settingsVersion", Utils.getCurrentVersion())
+
+ # Migration (after 1.49, 2015/2/1).
+ # Legacy setting: findModeRawQuery (a string).
+ # New setting: findModeRawQueryList (a list of strings), now stored in chrome.storage.local (not localStorage).
+ chrome.storage.local.get "findModeRawQueryList", (items) ->
+ unless chrome.runtime.lastError or items.findModeRawQueryList
+ rawQuery = Settings.get "findModeRawQuery"
+ chrome.storage.local.set findModeRawQueryList: (if rawQuery then [ rawQuery ] else [])