aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--background_scripts/main.coffee12
-rw-r--r--content_scripts/vimium_frontend.coffee57
-rw-r--r--manifest.json2
-rw-r--r--tests/dom_tests/chrome.coffee2
-rw-r--r--tests/dom_tests/dom_tests.coffee2
-rw-r--r--tests/unit_tests/exclusion_test.coffee12
-rw-r--r--tests/unit_tests/test_chrome_stubs.coffee6
7 files changed, 55 insertions, 38 deletions
diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee
index 642913a5..6fac032c 100644
--- a/background_scripts/main.coffee
+++ b/background_scripts/main.coffee
@@ -89,14 +89,22 @@ 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.
#
-root.isEnabledForUrl = isEnabledForUrl = (request, sender) ->
+root.isEnabledForUrl = isEnabledForUrl = (request) ->
rule = Exclusions.getRule(request.url)
{
isEnabledForUrl: not rule or rule.passKeys
passKeys: rule?.passKeys or ""
- incognito: sender.tab.incognito
}
+isEnabledForUpdatedUrl = (details) ->
+ message = isEnabledForUrl details
+ message.name = "updateEnabledForUrlState"
+ chrome.tabs.sendMessage details.tabId, message, {frameId: details.frameId}
+
+# Re-check whether Vimium is enabled for a frame when the url changes without a reload.
+chrome.webNavigation.onHistoryStateUpdated.addListener isEnabledForUpdatedUrl # history.pushState.
+chrome.webNavigation.onReferenceFragmentUpdated.addListener isEnabledForUpdatedUrl # Hash changed.
+
# Retrieves the help dialog HTML template from a file, and populates it with the latest keybindings.
# This is called by options.coffee.
root.helpDialogHtml = (showUnboundCommands, showCommandNames, customTitle) ->
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index ec39ccde..c41ca62f 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -12,7 +12,7 @@ findModeInitialRange = null
isShowingHelpDialog = false
keyPort = null
isEnabledForUrl = true
-isIncognitoMode = false
+isIncognitoMode = chrome.extension.inIncognitoContext
passKeys = null
keyQueue = null
# The user's operating system.
@@ -187,8 +187,9 @@ initializePreDomReady = ->
currentKeyQueue: (request) ->
keyQueue = request.keyQueue
handlerStack.bubbleEvent "registerKeyQueue", { keyQueue: keyQueue }
- # A frame has received the focus. We don't care, here (the Vomnibar/UI-component handles this).
+ # A frame has received the focus. We don't care here (the Vomnibar/UI-component handles this).
frameFocused: ->
+ updateEnabledForUrlState: updateEnabledForUrlState
chrome.runtime.onMessage.addListener (request, sender, sendResponse) ->
# In the options page, we will receive requests from both content and background scripts. ignore those
@@ -196,10 +197,11 @@ initializePreDomReady = ->
return if sender.tab and not sender.tab.url.startsWith 'chrome-extension://'
# These requests are delivered to the options page, but there are no handlers there.
return if request.handler in [ "registerFrame", "frameFocused", "unregisterFrame" ]
- # We handle the message if we're enabled, or if it's one of these listed message types.
- shouldHandleRequest = isEnabledForUrl or request.name in [ "executePageCommand" ]
- # Requests with a frameId of zero should only be handled in the main/top frame (regardless of whether
- # Vimium is enabled there).
+ shouldHandleRequest = isEnabledForUrl
+ # We always handle the message if it's one of these listed message types.
+ shouldHandleRequest ||= request.name in [ "executePageCommand", "updateEnabledForUrlState" ]
+ # Requests with a frameId of zero should always and only be handled in the main/top frame (regardless of
+ # whether Vimium is enabled there).
if request.frameId == 0 and DomUtils.isTopFrame()
request.frameId = frameId
shouldHandleRequest = true
@@ -217,9 +219,11 @@ installListener = (element, event, callback) ->
# Installing or uninstalling listeners is error prone. Instead we elect to check isEnabledForUrl each time so
# we know whether the listener should run or not.
# Run this as early as possible, so the page can't register any event handlers before us.
+# Note: We install the listeners even if Vimium is disabled. See comment in commit
+# 6446cf04c7b44c3d419dc450a73b60bcaf5cdf02.
#
installedListeners = false
-window.initializeWhenEnabled = ->
+window.installListeners = ->
unless installedListeners
# Key event handlers fire on window before they do on document. Prefer window for key events so the page
# can't set handlers to grab the keys before us.
@@ -583,27 +587,26 @@ onKeyup = (event) ->
checkIfEnabledForUrl = ->
url = window.location.toString()
+ chrome.runtime.sendMessage { handler: "isEnabledForUrl", url: url }, updateEnabledForUrlState
- chrome.runtime.sendMessage { handler: "isEnabledForUrl", url: url }, (response) ->
- isEnabledForUrl = response.isEnabledForUrl
- passKeys = response.passKeys
- isIncognitoMode = response.incognito
- if isEnabledForUrl
- initializeWhenEnabled()
- else if HUD.isReady()
- # Quickly hide any HUD we might already be showing, e.g. if we entered insert mode on page load.
- HUD.hide()
- handlerStack.bubbleEvent "registerStateChange",
- enabled: isEnabledForUrl
- passKeys: passKeys
- # Update the page icon, if necessary.
- if document.hasFocus()
- chrome.runtime.sendMessage
- handler: "setIcon"
- icon:
- if isEnabledForUrl and not passKeys then "enabled"
- else if isEnabledForUrl then "partial"
- else "disabled"
+updateEnabledForUrlState = (response) ->
+ { isEnabledForUrl, passKeys } = response
+ installListeners()
+ if HUD.isReady() and not isEnabledForUrl
+ # Quickly hide any HUD we might already be showing, e.g. if we entered insert mode on page load.
+ HUD.hide()
+ handlerStack.bubbleEvent "registerStateChange",
+ enabled: isEnabledForUrl
+ passKeys: passKeys
+ # Update the page icon, if necessary.
+ if document.hasFocus()
+ chrome.runtime.sendMessage
+ handler: "setIcon"
+ icon:
+ if isEnabledForUrl and not passKeys then "enabled"
+ else if isEnabledForUrl then "partial"
+ else "disabled"
+ null
# Exported to window, but only for DOM tests.
diff --git a/manifest.json b/manifest.json
index 4ba222fb..f0c297c2 100644
--- a/manifest.json
+++ b/manifest.json
@@ -2,6 +2,7 @@
"manifest_version": 2,
"name": "Vimium",
"version": "1.49",
+ "minimum_chrome_version": "41",
"description": "The Hacker's Browser. Vimium provides keyboard shortcuts for navigation and control in the spirit of Vim.",
"icons": { "16": "icons/icon16.png",
"48": "icons/icon48.png",
@@ -28,6 +29,7 @@
"storage",
"sessions",
"notifications",
+ "webNavigation",
"<all_urls>"
],
"content_scripts": [
diff --git a/tests/dom_tests/chrome.coffee b/tests/dom_tests/chrome.coffee
index 5f276649..4c9bfa52 100644
--- a/tests/dom_tests/chrome.coffee
+++ b/tests/dom_tests/chrome.coffee
@@ -29,3 +29,5 @@ root.chrome =
set: ->
onChanged:
addListener: ->
+ extension:
+ inIncognitoContext: false
diff --git a/tests/dom_tests/dom_tests.coffee b/tests/dom_tests/dom_tests.coffee
index f81982ac..bb09a0a8 100644
--- a/tests/dom_tests/dom_tests.coffee
+++ b/tests/dom_tests/dom_tests.coffee
@@ -1,6 +1,6 @@
# Install frontend event handlers.
-initializeWhenEnabled()
+installListeners()
installListener = (element, event, callback) ->
element.addEventListener event, (-> callback.apply(this, arguments)), true
diff --git a/tests/unit_tests/exclusion_test.coffee b/tests/unit_tests/exclusion_test.coffee
index 287d699d..b3ed7194 100644
--- a/tests/unit_tests/exclusion_test.coffee
+++ b/tests/unit_tests/exclusion_test.coffee
@@ -21,10 +21,6 @@ extend(global, require "../../background_scripts/exclusions.js")
extend(global, require "../../background_scripts/commands.js")
extend(global, require "../../background_scripts/main.js")
-dummyTab =
- tab:
- incognito: false
-
# These tests cover only the most basic aspects of excluded URLs and passKeys.
#
context "Excluded URLs and pass keys",
@@ -40,22 +36,22 @@ context "Excluded URLs and pass keys",
])
should "be disabled for excluded sites", ->
- rule = isEnabledForUrl({ url: 'http://mail.google.com/calendar/page' }, dummyTab)
+ rule = isEnabledForUrl({ url: 'http://mail.google.com/calendar/page' })
assert.isFalse rule.isEnabledForUrl
assert.isFalse rule.passKeys
should "be disabled for excluded sites, one exclusion", ->
- rule = isEnabledForUrl({ url: 'http://www.bbc.com/calendar/page' }, dummyTab)
+ rule = isEnabledForUrl({ url: 'http://www.bbc.com/calendar/page' })
assert.isFalse rule.isEnabledForUrl
assert.isFalse rule.passKeys
should "be enabled, but with pass keys", ->
- rule = isEnabledForUrl({ url: 'https://www.facebook.com/something' }, dummyTab)
+ rule = isEnabledForUrl({ url: 'https://www.facebook.com/something' })
assert.isTrue rule.isEnabledForUrl
assert.equal rule.passKeys, 'abcd'
should "be enabled", ->
- rule = isEnabledForUrl({ url: 'http://www.twitter.com/pages' }, dummyTab)
+ rule = isEnabledForUrl({ url: 'http://www.twitter.com/pages' })
assert.isTrue rule.isEnabledForUrl
assert.isFalse rule.passKeys
diff --git a/tests/unit_tests/test_chrome_stubs.coffee b/tests/unit_tests/test_chrome_stubs.coffee
index bc50521a..60f3a890 100644
--- a/tests/unit_tests/test_chrome_stubs.coffee
+++ b/tests/unit_tests/test_chrome_stubs.coffee
@@ -38,6 +38,12 @@ exports.chrome =
addListener: () -> true
query: () -> true
+ webNavigation:
+ onHistoryStateUpdated:
+ addListener: () ->
+ onReferenceFragmentUpdated:
+ addListener: () ->
+
windows:
onRemoved:
addListener: () -> true