From f037e83763b1b62e048e1fc433d52b9564ce3ba0 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sat, 23 Aug 2014 11:40:25 +0100 Subject: Allow passing of keys to the underlying page. --- background_scripts/main.coffee | 37 ++++++++++++++++++++++++++++--------- background_scripts/settings.coffee | 4 ++++ 2 files changed, 32 insertions(+), 9 deletions(-) (limited to 'background_scripts') diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index 431d9a31..e32027b6 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -69,17 +69,29 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) -> getCurrentTabUrl = (request, sender) -> sender.tab.url # -# Checks the user's preferences in local storage to determine if Vimium is enabled for the given URL. +# Checks the user's preferences in local storage to determine if Vimium is enabled for the given URL, and +# whether any keys should be passed through to the underlying page. # isEnabledForUrl = (request) -> - # excludedUrls are stored as a series of URL expressions separated by newlines. - excludedUrls = Settings.get("excludedUrls").split("\n") - isEnabled = true - for url in excludedUrls - # The user can add "*" to the URL which means ".*" - regexp = new RegExp("^" + url.replace(/\*/g, ".*") + "$") - isEnabled = false if request.url.match(regexp) - { isEnabledForUrl: isEnabled } + # Excluded URLs are stored as a series of URL expressions and optional passKeys, separated by newlines. + # Lines for which the first non-blank character is "#" are comments. + excludedLines = (line.trim() for line in Settings.get("excludedUrls").split("\n")) + excludedUrls = (line for line in excludedLines when line and line.indexOf("#") != 0) + for spec in excludedUrls + parse = spec.split(/\s+/) + if parse.length + url = parse[0] + # The user can add "*" to the URL which means ".*" + regexp = new RegExp("^" + url.replace(/\*/g, ".*") + "$") + if request.url.match(regexp) + passKeys = parse[1..].join("") + if passKeys + # Enabled, but only for these keys. + return { isEnabledForUrl: true, passKeys: passKeys } + # Disabled. + return { isEnabledForUrl: false } + # Enabled (the default). + { isEnabledForUrl: true } # Called by the popup UI. Strips leading/trailing whitespace and ignores empty strings. root.addExcludedUrl = (url) -> @@ -500,6 +512,13 @@ handleKeyDown = (request, port) -> console.log("checking keyQueue: [", keyQueue + key, "]") keyQueue = checkKeyQueue(keyQueue + key, port.sender.tab.id, request.frameId) console.log("new KeyQueue: " + keyQueue) + # Tell the front end whether there are keys in the queue. If there are, then subsequent keys in passKeys will be + # handled by vimium. + # FIXME: There is a race condition here. The behaviour depends upon whether this message gets back + # to the front end before the next keystroke or not. + chrome.tabs.sendMessage(port.sender.tab.id, + name: "currentKeyQueue", + keyQueue: keyQueue) checkKeyQueue = (keysToCheck, tabId, frameId) -> refreshedCompletionKeys = false diff --git a/background_scripts/settings.coffee b/background_scripts/settings.coffee index 175f3262..34d6e879 100644 --- a/background_scripts/settings.coffee +++ b/background_scripts/settings.coffee @@ -83,7 +83,11 @@ root.Settings = Settings = """ excludedUrls: """ + # Disable Vimium on Gmail: http*://mail.google.com/* + + # Use Facebook's own j/k bindings: + http*://www.facebook.com/* jk """ # 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 -- cgit v1.2.3 From 3581b585acf996fb8515c11d30682269557301c2 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sat, 23 Aug 2014 15:01:03 +0100 Subject: Allow passing of keys to the underlying page (minor code review). --- background_scripts/main.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'background_scripts') diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index e32027b6..6d986187 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -512,10 +512,10 @@ handleKeyDown = (request, port) -> console.log("checking keyQueue: [", keyQueue + key, "]") keyQueue = checkKeyQueue(keyQueue + key, port.sender.tab.id, request.frameId) console.log("new KeyQueue: " + keyQueue) - # Tell the front end whether there are keys in the queue. If there are, then subsequent keys in passKeys will be + # Tell the content script whether there are keys in the queue. If there are, then subsequent keys in passKeys will be # handled by vimium. # FIXME: There is a race condition here. The behaviour depends upon whether this message gets back - # to the front end before the next keystroke or not. + # to the content script before the next keystroke or not. chrome.tabs.sendMessage(port.sender.tab.id, name: "currentKeyQueue", keyQueue: keyQueue) -- cgit v1.2.3 From 951f8839d02a8d85747d86ccd09efc0ee3a72501 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sat, 23 Aug 2014 15:26:03 +0100 Subject: Allow passing of keys to the underlying page (more minor code review). --- background_scripts/main.coffee | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'background_scripts') diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index 6d986187..46a6a695 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -76,20 +76,18 @@ isEnabledForUrl = (request) -> # Excluded URLs are stored as a series of URL expressions and optional passKeys, separated by newlines. # Lines for which the first non-blank character is "#" are comments. excludedLines = (line.trim() for line in Settings.get("excludedUrls").split("\n")) - excludedUrls = (line for line in excludedLines when line and line.indexOf("#") != 0) - for spec in excludedUrls - parse = spec.split(/\s+/) - if parse.length - url = parse[0] - # The user can add "*" to the URL which means ".*" - regexp = new RegExp("^" + url.replace(/\*/g, ".*") + "$") - if request.url.match(regexp) - passKeys = parse[1..].join("") - if passKeys - # Enabled, but only for these keys. - return { isEnabledForUrl: true, passKeys: passKeys } - # Disabled. - return { isEnabledForUrl: false } + excludedSpecs = (line.split(/\s+/) for line in excludedLines when line and line.indexOf("#") != 0) + for spec in excludedSpecs + url = spec[0] + # The user can add "*" to the URL which means ".*" + regexp = new RegExp("^" + url.replace(/\*/g, ".*") + "$") + if request.url.match(regexp) + passKeys = spec[1..].join("") + if passKeys + # Enabled, but not for these keys. + return { isEnabledForUrl: true, passKeys: passKeys } + # Wholly disabled. + return { isEnabledForUrl: false } # Enabled (the default). { isEnabledForUrl: true } @@ -513,9 +511,11 @@ handleKeyDown = (request, port) -> keyQueue = checkKeyQueue(keyQueue + key, port.sender.tab.id, request.frameId) console.log("new KeyQueue: " + keyQueue) # Tell the content script whether there are keys in the queue. If there are, then subsequent keys in passKeys will be - # handled by vimium. - # FIXME: There is a race condition here. The behaviour depends upon whether this message gets back - # to the content script before the next keystroke or not. + # handled by vimium. So, if 't' is a passKey, then 'gt' and '99t' will nevertheless be handled by Vimium. + # FIXME: There is a race condition here. The behaviour in the content script depends upon whether this message gets + # back there before or after the next keystroke. + # That being said, I suspect there are other similar race conditions here, for example in checkKeyQueue(). + # Steve (23 Aug, 14). chrome.tabs.sendMessage(port.sender.tab.id, name: "currentKeyQueue", keyQueue: keyQueue) -- cgit v1.2.3 From eeda751f54fd67bb895541264fcf2b5eb91b2556 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sat, 23 Aug 2014 17:28:55 +0100 Subject: Allow passing of keys to the underlying page (populate page popup with existing rule). --- background_scripts/main.coffee | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) (limited to 'background_scripts') diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index 46a6a695..f3df2943 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -72,7 +72,7 @@ getCurrentTabUrl = (request, sender) -> sender.tab.url # Checks the user's preferences in local storage to determine if Vimium is enabled for the given URL, and # whether any keys should be passed through to the underlying page. # -isEnabledForUrl = (request) -> +root.isEnabledForUrl = isEnabledForUrl = (request) -> # Excluded URLs are stored as a series of URL expressions and optional passKeys, separated by newlines. # Lines for which the first non-blank character is "#" are comments. excludedLines = (line.trim() for line in Settings.get("excludedUrls").split("\n")) @@ -85,21 +85,39 @@ isEnabledForUrl = (request) -> passKeys = spec[1..].join("") if passKeys # Enabled, but not for these keys. - return { isEnabledForUrl: true, passKeys: passKeys } + return { isEnabledForUrl: true, passKeys: passKeys, matchingUrl: url } # Wholly disabled. - return { isEnabledForUrl: false } + return { isEnabledForUrl: false, passKeys: "", matchingUrl: url } # Enabled (the default). - { isEnabledForUrl: true } + { isEnabledForUrl: true, passKeys: undefined, matchingUrl: undefined } # Called by the popup UI. Strips leading/trailing whitespace and ignores empty strings. +# Also eliminates duplicates based on same URL/regexp. Of duplicates, the last is kept. +# Excluded URL specifications are kept in the same order as they were originally, with the new exclusion at +# the end. Passkeys, if any, are simply compied through within spec. root.addExcludedUrl = (url) -> return unless url = url.trim() - excludedUrls = Settings.get("excludedUrls") - return if excludedUrls.indexOf(url) >= 0 - - excludedUrls += "\n" + url - Settings.set("excludedUrls", excludedUrls) + excludedUrls = Settings.get("excludedUrls").split("\n") + excludedUrls.push(url) + + # Eliminate duplicates: reverse list, filter out duplicates based only on the URL/regexp, then reverse again + # and install the new excludedUrls. parse[0] is the URL/regexp. + seen = {} + newExcludedUrls = [] + for spec in excludedUrls.reverse() + spec = spec.trim() + parse = spec.split(/\s+/) + if parse.length == 0 or spec.indexOf("#") == 0 + # Keep comments and empty lines. + newExcludedUrls.push(spec) + else if !seen[parse[0]] + seen[parse[0]] = true + newExcludedUrls.push(spec) + else + console.log "addExcludedUrl: removing " + spec + + Settings.set("excludedUrls", newExcludedUrls.reverse().join("\n")) chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT, active: true }, (tabs) -> updateActiveState(tabs[0].id)) -- cgit v1.2.3 From 4dd09f77141b01d2ce99866cb52efc985f4f18a4 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sat, 23 Aug 2014 18:32:41 +0100 Subject: Allow passing of keys to the underlying page (fix/maintain order of exclusion list). --- background_scripts/main.coffee | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'background_scripts') diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index f3df2943..816e4e45 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -91,33 +91,35 @@ root.isEnabledForUrl = isEnabledForUrl = (request) -> # Enabled (the default). { isEnabledForUrl: true, passKeys: undefined, matchingUrl: undefined } -# Called by the popup UI. Strips leading/trailing whitespace and ignores empty strings. -# Also eliminates duplicates based on same URL/regexp. Of duplicates, the last is kept. -# Excluded URL specifications are kept in the same order as they were originally, with the new exclusion at -# the end. Passkeys, if any, are simply compied through within spec. +# Called by the popup UI. Strips leading/trailing whitespace and ignores new empty strings. root.addExcludedUrl = (url) -> return unless url = url.trim() + parse = url.split(/\s+/) + url = parse[0] + passKeys = parse[1..].join(" ") + newSpec = (if passKeys then url + " " + passKeys else url) + excludedUrls = Settings.get("excludedUrls").split("\n") - excludedUrls.push(url) + excludedUrls.push(newSpec) - # Eliminate duplicates: reverse list, filter out duplicates based only on the URL/regexp, then reverse again - # and install the new excludedUrls. parse[0] is the URL/regexp. - seen = {} + # Update excludedUrls. + # Try to keep the list as unchanged as possible: same order, same comments, same blank lines. + seenNew = false newExcludedUrls = [] - for spec in excludedUrls.reverse() + for spec in excludedUrls spec = spec.trim() parse = spec.split(/\s+/) - if parse.length == 0 or spec.indexOf("#") == 0 - # Keep comments and empty lines. - newExcludedUrls.push(spec) - else if !seen[parse[0]] - seen[parse[0]] = true - newExcludedUrls.push(spec) - else - console.log "addExcludedUrl: removing " + spec + # Keep just one copy of the new exclusion rule. + if parse.length and parse[0] == url + if !seenNew + newExcludedUrls.push(newSpec) + seenNew = true + continue + # And just keep everything else. + newExcludedUrls.push(spec) - Settings.set("excludedUrls", newExcludedUrls.reverse().join("\n")) + Settings.set("excludedUrls", newExcludedUrls.join("\n")) chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT, active: true }, (tabs) -> updateActiveState(tabs[0].id)) @@ -528,8 +530,7 @@ handleKeyDown = (request, port) -> console.log("checking keyQueue: [", keyQueue + key, "]") keyQueue = checkKeyQueue(keyQueue + key, port.sender.tab.id, request.frameId) console.log("new KeyQueue: " + keyQueue) - # Tell the content script whether there are keys in the queue. If there are, then subsequent keys in passKeys will be - # handled by vimium. So, if 't' is a passKey, then 'gt' and '99t' will nevertheless be handled by Vimium. + # Tell the content script whether there are keys in the queue. # FIXME: There is a race condition here. The behaviour in the content script depends upon whether this message gets # back there before or after the next keystroke. # That being said, I suspect there are other similar race conditions here, for example in checkKeyQueue(). -- cgit v1.2.3 From 7a0943b549986a060282e8047f14a58fbdb5acc3 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sat, 23 Aug 2014 20:52:56 +0100 Subject: Allow passing of keys to the underlying page (comments can start with " too). --- background_scripts/main.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'background_scripts') diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index 816e4e45..b99d5307 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -74,9 +74,9 @@ getCurrentTabUrl = (request, sender) -> sender.tab.url # root.isEnabledForUrl = isEnabledForUrl = (request) -> # Excluded URLs are stored as a series of URL expressions and optional passKeys, separated by newlines. - # Lines for which the first non-blank character is "#" are comments. + # Lines for which the first non-blank character is "#" or '"' are comments. excludedLines = (line.trim() for line in Settings.get("excludedUrls").split("\n")) - excludedSpecs = (line.split(/\s+/) for line in excludedLines when line and line.indexOf("#") != 0) + excludedSpecs = (line.split(/\s+/) for line in excludedLines when line and line.indexOf("#") != 0 and line.indexOf('"') != 0) for spec in excludedSpecs url = spec[0] # The user can add "*" to the URL which means ".*" -- cgit v1.2.3 From 12b889d9cbfaa2a47834fbf69c4f7788cbc8c361 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 24 Aug 2014 08:20:15 +0100 Subject: New icons for partially enabled, for passkeys. --- background_scripts/main.coffee | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'background_scripts') diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index b99d5307..68d1236b 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -91,7 +91,8 @@ root.isEnabledForUrl = isEnabledForUrl = (request) -> # Enabled (the default). { isEnabledForUrl: true, passKeys: undefined, matchingUrl: undefined } -# Called by the popup UI. Strips leading/trailing whitespace and ignores new empty strings. +# Called by the popup UI. Strips leading/trailing whitespace and ignores new empty strings. If an existing +# exclusion rule has been changed, then the existing rule is updated. Otherwise, the new rule is added. root.addExcludedUrl = (url) -> return unless url = url.trim() @@ -387,15 +388,20 @@ updateOpenTabs = (tab) -> updateActiveState = (tabId) -> enabledIcon = "icons/browser_action_enabled.png" disabledIcon = "icons/browser_action_disabled.png" + partialIcon = "icons/browser_action_partial.png" chrome.tabs.get(tabId, (tab) -> # Default to disabled state in case we can't connect to Vimium, primarily for the "New Tab" page. chrome.browserAction.setIcon({ path: disabledIcon }) chrome.tabs.sendMessage(tabId, { name: "getActiveState" }, (response) -> isCurrentlyEnabled = (response? && response.enabled) - shouldBeEnabled = isEnabledForUrl({url: tab.url}).isEnabledForUrl + enabledConfig = isEnabledForUrl({url: tab.url}) + shouldBeEnabled = enabledConfig.isEnabledForUrl + shouldHavePassKeys = enabledConfig.passKeys if (isCurrentlyEnabled) - if (shouldBeEnabled) + if (shouldBeEnabled and shouldHavePassKeys) + chrome.browserAction.setIcon({ path: partialIcon }) + else if (shouldBeEnabled) chrome.browserAction.setIcon({ path: enabledIcon }) else chrome.browserAction.setIcon({ path: disabledIcon }) -- cgit v1.2.3 From d230f3037e259f0bf8c3710f20a7403731caecc0 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 24 Aug 2014 10:04:03 +0100 Subject: Better state management for passkeys. --- background_scripts/main.coffee | 45 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'background_scripts') diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index 68d1236b..5412ead5 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -377,37 +377,38 @@ updateOpenTabs = (tab) -> # Frames are recreated on refresh delete framesForTab[tab.id] -# Updates the browserAction icon to indicated whether Vimium is enabled or disabled on the current page. -# Also disables Vimium if it is currently enabled but should be disabled according to the url blacklist. +setBrowserActionIcon = (tabId,path) -> + chrome.browserAction.setIcon({ tabId: tabId, path: path }) + +# Updates the browserAction icon to indicate whether Vimium is enabled or disabled on the current page. +# Also propagates new enabled/disabled/passkeys state to active window, if necessary. # This lets you disable Vimium on a page without needing to reload. -# -# Three situations are considered: -# 1. Active tab is disabled -> disable icon -# 2. Active tab is enabled and should be enabled -> enable icon -# 3. Active tab is enabled but should be disabled -> disable icon and disable vimium updateActiveState = (tabId) -> enabledIcon = "icons/browser_action_enabled.png" disabledIcon = "icons/browser_action_disabled.png" partialIcon = "icons/browser_action_partial.png" - chrome.tabs.get(tabId, (tab) -> - # Default to disabled state in case we can't connect to Vimium, primarily for the "New Tab" page. - chrome.browserAction.setIcon({ path: disabledIcon }) - chrome.tabs.sendMessage(tabId, { name: "getActiveState" }, (response) -> - isCurrentlyEnabled = (response? && response.enabled) - enabledConfig = isEnabledForUrl({url: tab.url}) - shouldBeEnabled = enabledConfig.isEnabledForUrl - shouldHavePassKeys = enabledConfig.passKeys - - if (isCurrentlyEnabled) + chrome.tabs.get tabId, (tab) -> + chrome.tabs.sendMessage tabId, { name: "getActiveState" }, (response) -> + if response + isCurrentlyEnabled = response.enabled + currentPasskeys = response.passKeys + # TODO: + # isEnabledForUrl is quite expensive to run each time we change tab. Perhaps memoize it? + shouldHaveConfig = isEnabledForUrl({url: tab.url}) + shouldBeEnabled = shouldHaveConfig.isEnabledForUrl + shouldHavePassKeys = shouldHaveConfig.passKeys if (shouldBeEnabled and shouldHavePassKeys) - chrome.browserAction.setIcon({ path: partialIcon }) + setBrowserActionIcon(tabId,partialIcon) else if (shouldBeEnabled) - chrome.browserAction.setIcon({ path: enabledIcon }) + setBrowserActionIcon(tabId,enabledIcon) else - chrome.browserAction.setIcon({ path: disabledIcon }) - chrome.tabs.sendMessage(tabId, { name: "disableVimium" }) + setBrowserActionIcon(tabId,disabledIcon) + # Propagate the new state only if it has changed. + if (isCurrentlyEnabled != shouldBeEnabled || currentPasskeys != shouldHavePassKeys) + chrome.tabs.sendMessage(tabId, { name: "setState", enabled: shouldBeEnabled, passKeys: shouldHavePassKeys }) else - chrome.browserAction.setIcon({ path: disabledIcon }))) + # We didn't get a response from the front end, so Vimium isn't running. + setBrowserActionIcon(tabId,disabledIcon) handleUpdateScrollPosition = (request, sender) -> updateScrollPosition(sender.tab, request.scrollX, request.scrollY) -- cgit v1.2.3 From b599492ea27c8c6bab38e87ef343968f5fcf58e7 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sun, 24 Aug 2014 17:05:05 +0100 Subject: Fix passKeys bug introduced in commit 700d35a --- background_scripts/main.coffee | 1 + 1 file changed, 1 insertion(+) (limited to 'background_scripts') diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index 5412ead5..dda1beae 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -389,6 +389,7 @@ updateActiveState = (tabId) -> partialIcon = "icons/browser_action_partial.png" chrome.tabs.get tabId, (tab) -> chrome.tabs.sendMessage tabId, { name: "getActiveState" }, (response) -> + console.log response if response isCurrentlyEnabled = response.enabled currentPasskeys = response.passKeys -- cgit v1.2.3