aboutsummaryrefslogtreecommitdiffstats
path: root/background_scripts
diff options
context:
space:
mode:
Diffstat (limited to 'background_scripts')
-rw-r--r--background_scripts/commands.coffee6
-rw-r--r--background_scripts/completion_engines.coffee60
-rw-r--r--background_scripts/exclusions.coffee4
-rw-r--r--background_scripts/main.coffee2
-rw-r--r--background_scripts/settings.coffee126
-rw-r--r--background_scripts/sync.coffee74
6 files changed, 42 insertions, 230 deletions
diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee
index fa5354df..bf892c1a 100644
--- a/background_scripts/commands.coffee
+++ b/background_scripts/commands.coffee
@@ -343,5 +343,11 @@ commandDescriptions =
Commands.init()
+# Register postUpdateHook for keyMappings setting.
+Settings.postUpdateHooks["keyMappings"] = (value) ->
+ Commands.clearKeyMappingsAndSetDefaults()
+ Commands.parseCustomKeyMappings value
+ refreshCompletionKeysAfterMappingSave()
+
root = exports ? window
root.Commands = Commands
diff --git a/background_scripts/completion_engines.coffee b/background_scripts/completion_engines.coffee
index 189f66f3..f15e6db4 100644
--- a/background_scripts/completion_engines.coffee
+++ b/background_scripts/completion_engines.coffee
@@ -21,12 +21,11 @@
# A base class for common regexp-based matching engines.
class RegexpEngine
- constructor: (@regexps) ->
+ constructor: (args...) -> @regexps = args.map (regexp) -> new RegExp regexp
match: (searchUrl) -> Utils.matchesAnyRegexp @regexps, searchUrl
# Several Google completion engines package XML responses in this way.
class GoogleXMLRegexpEngine extends RegexpEngine
- doNotCache: false # true (disbaled, experimental)
parse: (xhr) ->
for suggestion in xhr.responseXML.getElementsByTagName "suggestion"
continue unless suggestion = suggestion.getAttribute "data"
@@ -34,31 +33,47 @@ class GoogleXMLRegexpEngine extends RegexpEngine
class Google extends GoogleXMLRegexpEngine
# Example search URL: http://www.google.com/search?q=%s
- constructor: ->
- super [
- # We match the major English-speaking TLDs.
- new RegExp "^https?://[a-z]+\.google\.(com|ie|co\.uk|ca|com\.au)/"
- new RegExp "localhost/cgi-bin/booky" # Only for smblott.
- ]
+ constructor: (regexps = null) ->
+ super regexps ? "^https?://[a-z]+\.google\.(com|ie|co\.uk|ca|com\.au)/"
getUrl: (queryTerms) ->
Utils.createSearchUrl queryTerms,
"http://suggestqueries.google.com/complete/search?ss_protocol=legace&client=toolbar&q=%s"
+# A wrapper class for Google completions. This adds prefix terms to the query, and strips those terms from
+# the resulting suggestions. For example, for Google Maps, we add "map of" as a prefix, then strip "map of"
+# from the resulting suggestions.
+class GoogleWithPrefix
+ constructor: (prefix, args...) ->
+ @engine = new Google args...
+ @prefix = "#{prefix.trim()} "
+ @queryTerms = @prefix.split /\s+/
+ match: (args...) -> @engine.match args...
+ getUrl: (queryTerms) -> @engine.getUrl [ @queryTerms..., queryTerms... ]
+ parse: (xhr) ->
+ @engine.parse(xhr)
+ .filter (suggestion) => suggestion.startsWith @prefix
+ .map (suggestion) => suggestion[@prefix.length..].ltrim()
+
+# For Google Maps, we add the prefix "map of" to the query, and send it to Google's general search engine,
+# then strip "map of" from the resulting suggestions.
+class GoogleMaps extends GoogleWithPrefix
+ # Example search URL: https://www.google.com/maps?q=%s
+ constructor: -> super "map of", "https?://[a-z]+\.google\.(com|ie|co\.uk|ca|com\.au)/maps"
+
class Youtube extends GoogleXMLRegexpEngine
# Example search URL: http://www.youtube.com/results?search_query=%s
constructor: ->
- super [ new RegExp "^https?://[a-z]+\.youtube\.com/results" ]
+ super "^https?://[a-z]+\.youtube\.com/results"
getUrl: (queryTerms) ->
Utils.createSearchUrl queryTerms,
"http://suggestqueries.google.com/complete/search?client=youtube&ds=yt&xml=t&q=%s"
class Wikipedia extends RegexpEngine
- doNotCache: false # true (disbaled, experimental)
# Example search URL: http://www.wikipedia.org/w/index.php?title=Special:Search&search=%s
constructor: ->
- super [ new RegExp "^https?://[a-z]+\.wikipedia\.org/" ]
+ super "^https?://[a-z]+\.wikipedia\.org/"
getUrl: (queryTerms) ->
Utils.createSearchUrl queryTerms,
@@ -67,28 +82,15 @@ class Wikipedia extends RegexpEngine
parse: (xhr) ->
JSON.parse(xhr.responseText)[1]
-## Does not work...
-## class GoogleMaps extends RegexpEngine
-## # Example search URL: https://www.google.com/maps/search/%s
-## constructor: ->
-## super [ new RegExp "^https?://www\.google\.com/maps/search/" ]
-##
-## getUrl: (queryTerms) ->
-## "https://www.google.com/s?tbm=map&fp=1&gs_ri=maps&source=hp&suggest=p&authuser=0&hl=en&pf=p&tch=1&ech=2&q=#{Utils.createSearchQuery queryTerms}"
-##
-## parse: (xhr) ->
-## data = JSON.parse xhr.responseText
-## []
-
class Bing extends RegexpEngine
# Example search URL: https://www.bing.com/search?q=%s
- constructor: -> super [ new RegExp "^https?://www\.bing\.com/search" ]
+ constructor: -> super "^https?://www\.bing\.com/search"
getUrl: (queryTerms) -> Utils.createSearchUrl queryTerms, "http://api.bing.com/osjson.aspx?query=%s"
parse: (xhr) -> JSON.parse(xhr.responseText)[1]
class Amazon extends RegexpEngine
# Example search URL: http://www.amazon.com/s/?field-keywords=%s
- constructor: -> super [ new RegExp "^https?://www\.amazon\.(com|co.uk|ca|com.au)/s/" ]
+ constructor: -> super "^https?://www\.amazon\.(com|co.uk|ca|com.au)/s/"
getUrl: (queryTerms) ->
Utils.createSearchUrl queryTerms,
"https://completion.amazon.com/search/complete?method=completion&search-alias=aps&client=amazon-search-ui&mkt=1&q=%s"
@@ -96,15 +98,14 @@ class Amazon extends RegexpEngine
class DuckDuckGo extends RegexpEngine
# Example search URL: https://duckduckgo.com/?q=%s
- constructor: -> super [ new RegExp "^https?://([a-z]+\.)?duckduckgo\.com/" ]
- getUrl: (queryTerms) ->
+ constructor: -> super "^https?://([a-z]+\.)?duckduckgo\.com/"
getUrl: (queryTerms) -> Utils.createSearchUrl queryTerms, "https://duckduckgo.com/ac/?q=%s"
parse: (xhr) ->
suggestion.phrase for suggestion in JSON.parse xhr.responseText
class Webster extends RegexpEngine
# Example search URL: http://www.merriam-webster.com/dictionary/%s
- constructor: -> super [ new RegExp "^https?://www.merriam-webster.com/dictionary/" ]
+ constructor: -> super "^https?://www.merriam-webster.com/dictionary/"
getUrl: (queryTerms) -> Utils.createSearchUrl queryTerms, "http://www.merriam-webster.com/autocomplete?query=%s"
parse: (xhr) -> JSON.parse(xhr.responseText).suggestions
@@ -120,6 +121,7 @@ class DummyCompletionEngine
# Note: Order matters here.
CompletionEngines = [
Youtube
+ GoogleMaps
Google
DuckDuckGo
Wikipedia
diff --git a/background_scripts/exclusions.coffee b/background_scripts/exclusions.coffee
index 5ec76e2a..21342d61 100644
--- a/background_scripts/exclusions.coffee
+++ b/background_scripts/exclusions.coffee
@@ -73,3 +73,7 @@ if not Settings.has("exclusionRules") and Settings.has("excludedUrls")
# We'll keep a backup of the "excludedUrls" setting, just in case.
Settings.set("excludedUrlsBackup", Settings.get("excludedUrls")) if not Settings.has("excludedUrlsBackup")
Settings.clear("excludedUrls")
+
+# Register postUpdateHook for exclusionRules setting.
+Settings.postUpdateHooks["exclusionRules"] = (value) ->
+ Exclusions.postUpdateHook value
diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee
index e7a1f82c..99a5672b 100644
--- a/background_scripts/main.coffee
+++ b/background_scripts/main.coffee
@@ -744,5 +744,5 @@ chrome.windows.getAll { populate: true }, (windows) ->
chrome.tabs.sendMessage(tab.id, { name: "getScrollPosition" }, createScrollPositionHandler())
# Start pulling changes from synchronized storage.
-Sync.init()
+Settings.init()
showUpgradeMessage()
diff --git a/background_scripts/settings.coffee b/background_scripts/settings.coffee
deleted file mode 100644
index d23649ee..00000000
--- a/background_scripts/settings.coffee
+++ /dev/null
@@ -1,126 +0,0 @@
-#
-# Used by all parts of Vimium to manipulate localStorage.
-#
-
-root = exports ? window
-root.Settings = Settings =
- 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 here called from
- # options/options.coffee (when the options page is saved), and from background_scripts/sync.coffee (when an
- # update propagates from chrome.storage.sync).
- postUpdateHooks:
- keyMappings: (value) ->
- root.Commands.clearKeyMappingsAndSetDefaults()
- root.Commands.parseCustomKeyMappings value
- root.refreshCompletionKeysAfterMappingSave()
-
- exclusionRules: (value) ->
- root.Exclusions.postUpdateHook value
-
- # postUpdateHooks convenience wrapper
- performPostUpdateHook: (key, value) ->
- @postUpdateHooks[key] value if @postUpdateHooks[key]
-
- # 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()
-
-
-# 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 [])
-
diff --git a/background_scripts/sync.coffee b/background_scripts/sync.coffee
deleted file mode 100644
index d0d501d3..00000000
--- a/background_scripts/sync.coffee
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# * 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.
-#
-# Changes are propagated into vimium's state using the same mechanism
-# (Settings.performPostUpdateHook) that is used when options are changed on
-# the options page.
-#
-# 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
-root.Sync = 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
- @storeAndPropagate key, value
-
- # Asynchronous message from synced storage.
- handleStorageUpdate: (changes, area) ->
- for own key, change of changes
- @storeAndPropagate key, change?.newValue
-
- # Only ever called from asynchronous synced-storage callbacks (fetchAsync and handleStorageUpdate).
- storeAndPropagate: (key, value) ->
- return unless key of Settings.defaults
- return if not @shouldSyncKey key
- return if value and key of localStorage and localStorage[key] is value
- defaultValue = Settings.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
- Settings.performPostUpdateHook key, JSON.parse(value)
- else
- # Key has been reset to default value at remote instance.
- if key of localStorage
- delete localStorage[key]
- Settings.performPostUpdateHook key, defaultValue
-
- # 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
-