aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Blott2015-03-17 09:59:59 +0000
committerStephen Blott2015-03-17 09:59:59 +0000
commit5abde2faa3cbcf070de82c5dffef93c553c7ad02 (patch)
treef511877ca52bdd51d98b1da55d773d18da4d371c
parent23cb1677bbc79328e7329fab4400f671ea6aee23 (diff)
parent5b84f5cf94d32b6e8be75448f9c06aa7f2068582 (diff)
downloadvimium-5abde2faa3cbcf070de82c5dffef93c553c7ad02.tar.bz2
Merge branch 'rework-exclusion-rules'
Conflicts: content_scripts/vimium_frontend.coffee
-rw-r--r--background_scripts/main.coffee56
-rw-r--r--content_scripts/vimium_frontend.coffee48
-rw-r--r--pages/options.coffee10
3 files changed, 53 insertions, 61 deletions
diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee
index fe6cc70b..f70cd8f3 100644
--- a/background_scripts/main.coffee
+++ b/background_scripts/main.coffee
@@ -26,6 +26,7 @@ validFirstKeys = {}
singleKeyCommands = []
focusedFrame = null
frameIdsForTab = {}
+root.urlForTab = {}
# Keys are either literal characters, or "named" - for example <a-b> (alt+b), <left> (left arrow) or <f12>
# This regular expression captures two groups: the first is a named key, the second is the remainder of
@@ -368,9 +369,6 @@ updateOpenTabs = (tab, deleteFrames = false) ->
# Frames are recreated on refresh
delete frameIdsForTab[tab.id] if deleteFrames
-setBrowserActionIcon = (tabId,path) ->
- chrome.browserAction.setIcon({ tabId: tabId, path: path })
-
chrome.browserAction.setBadgeBackgroundColor
# This is Vimium blue (from the icon).
# color: [102, 176, 226, 255]
@@ -390,34 +388,24 @@ setBadge = do ->
# We wait a few moments. This avoids badge flicker when there are rapid changes.
timer = setTimeout updateBadge(badge, sender.tab.id), 50
-# 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.
-# Exported via root because it's called from the page popup.
-root.updateActiveState = 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) ->
- setBadge { badge: "" }, tab: { id: tabId }
- chrome.tabs.sendMessage tabId, { name: "getActiveState" }, (response) ->
- if response
- isCurrentlyEnabled = response.enabled
- currentPasskeys = response.passKeys
- config = isEnabledForUrl { url: tab.url }, { tab: tab }
- enabled = config.isEnabledForUrl
- passKeys = config.passKeys
- if (enabled and passKeys)
- setBrowserActionIcon(tabId,partialIcon)
- else if (enabled)
- setBrowserActionIcon(tabId,enabledIcon)
- else
- setBrowserActionIcon(tabId,disabledIcon)
- # Propagate the new state only if it has changed.
- if (isCurrentlyEnabled != enabled || currentPasskeys != passKeys)
- chrome.tabs.sendMessage(tabId, { name: "setState", enabled: enabled, passKeys: passKeys, incognito: tab.incognito })
- else
- setBrowserActionIcon tabId, disabledIcon
+# Here's how we set the page icon. The default is "disabled", so if we do nothing else, then we get the
+# grey-out disabled icon. Thereafter, we only set tab-specific icons, so there's no need to update the icon
+# when we visit a tab on which Vimium isn't running.
+#
+# For active tabs, when a frame starts, it requests its active state via isEnabledForUrl. We also check the
+# state every time a frame gets the focus. Once the frame learns its active state, it updates the current
+# tab's badge (but only if that frame has the focus).
+#
+# Exclusion rule changes (from either the options page or the page popup) propagate via the subsequent focus
+# change. In particular, whenever a frame next gets the focus, it requests its new state and sets the icon
+# accordingly.
+#
+setIcon = (request, sender) ->
+ path = switch request.icon
+ when "enabled" then "icons/browser_action_enabled.png"
+ when "partial" then "icons/browser_action_partial.png"
+ when "disabled" then "icons/browser_action_disabled.png"
+ chrome.browserAction.setIcon tabId: sender.tab.id, path: path
handleUpdateScrollPosition = (request, sender) ->
updateScrollPosition(sender.tab, request.scrollX, request.scrollY)
@@ -434,7 +422,6 @@ chrome.tabs.onUpdated.addListener (tabId, changeInfo, tab) ->
runAt: "document_start"
chrome.tabs.insertCSS tabId, cssConf, -> chrome.runtime.lastError
updateOpenTabs(tab) if changeInfo.url?
- updateActiveState(tabId)
chrome.tabs.onAttached.addListener (tabId, attachedInfo) ->
# We should update all the tabs in the old window and the new window.
@@ -469,8 +456,7 @@ chrome.tabs.onRemoved.addListener (tabId) ->
tabInfoMap.deletor = -> delete tabInfoMap[tabId]
setTimeout tabInfoMap.deletor, 1000
delete frameIdsForTab[tabId]
-
-chrome.tabs.onActiveChanged.addListener (tabId, selectInfo) -> updateActiveState(tabId)
+ delete urlForTab[tabId]
unless chrome.sessions
chrome.windows.onRemoved.addListener (windowId) -> delete tabQueue[windowId]
@@ -654,6 +640,7 @@ unregisterFrame = (request, sender) ->
handleFrameFocused = (request, sender) ->
tabId = sender.tab.id
+ urlForTab[tabId] = request.url
if frameIdsForTab[tabId]?
frameIdsForTab[tabId] =
[request.frameId, (frameIdsForTab[tabId].filter (id) -> id != request.frameId)...]
@@ -684,6 +671,7 @@ sendRequestHandlers =
refreshCompleter: refreshCompleter
createMark: Marks.create.bind(Marks)
gotoMark: Marks.goto.bind(Marks)
+ setIcon: setIcon
setBadge: setBadge
# We always remove chrome.storage.local/findModeRawQueryListIncognito on startup.
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 429657fc..f3bbb868 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -162,6 +162,7 @@ initializePreDomReady = ->
isEnabledForUrl = false
chrome.runtime.sendMessage = ->
chrome.runtime.connect = ->
+ window.removeEventListener "focus", onFocus
requestHandlers =
hideUpgradeNotification: -> HUD.hideUpgradeNotification()
@@ -173,8 +174,6 @@ initializePreDomReady = ->
getScrollPosition: -> scrollX: window.scrollX, scrollY: window.scrollY
setScrollPosition: (request) -> setScrollPosition request.scrollX, request.scrollY
executePageCommand: executePageCommand
- getActiveState: getActiveState
- setState: setState
currentKeyQueue: (request) ->
keyQueue = request.keyQueue
handlerStack.bubbleEvent "registerKeyQueue", { keyQueue: keyQueue }
@@ -183,7 +182,7 @@ initializePreDomReady = ->
# In the options page, we will receive requests from both content and background scripts. ignore those
# from the former.
return if sender.tab and not sender.tab.url.startsWith 'chrome-extension://'
- return unless isEnabledForUrl or request.name == 'getActiveState' or request.name == 'setState'
+ return unless isEnabledForUrl
# These requests are delivered to the options page, but there are no handlers there.
return if request.handler in [ "registerFrame", "frameFocused", "unregisterFrame" ]
sendResponse requestHandlers[request.name](request, sender)
@@ -209,30 +208,24 @@ window.initializeWhenEnabled = ->
for type in [ "keydown", "keypress", "keyup", "click", "focus", "blur", "mousedown" ]
do (type) -> installListener window, type, (event) -> handlerStack.bubbleEvent type, event
installListener document, "DOMActivate", (event) -> handlerStack.bubbleEvent 'DOMActivate', event
- installListener window, "focus", registerFocus
installedListeners = true
FindModeHistory.init()
-setState = (request) ->
- isEnabledForUrl = request.enabled
- passKeys = request.passKeys
- isIncognitoMode = request.incognito
- initializeWhenEnabled() if isEnabledForUrl
- handlerStack.bubbleEvent "registerStateChange",
- enabled: isEnabledForUrl
- passKeys: passKeys
-
-getActiveState = ->
- Mode.updateBadge()
- return { enabled: isEnabledForUrl, passKeys: passKeys }
-
#
-# The backend needs to know which frame has focus.
+# Whenever we get the focus:
+# - Reload settings (they may have changed).
+# - Tell the background page this frame's URL.
+# - Check if we should be enabled.
#
-registerFocus = ->
- # settings may have changed since the frame last had focus
- settings.load()
- chrome.runtime.sendMessage({ handler: "frameFocused", frameId: frameId })
+onFocus = (event) ->
+ if event.target == window
+ settings.load()
+ chrome.runtime.sendMessage handler: "frameFocused", frameId: frameId, url: window.location.toString()
+ checkIfEnabledForUrl()
+
+# We install this listener directly (that is, we don't use installListener) because we still need to receive
+# events when Vimium is not enabled.
+window.addEventListener "focus", onFocus
#
# Initialization tasks that must wait for the document to be ready.
@@ -565,12 +558,21 @@ checkIfEnabledForUrl = ->
isIncognitoMode = response.incognito
if isEnabledForUrl
initializeWhenEnabled()
- else if (HUD.isReady())
+ 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"
+
# Exported to window, but only for DOM tests.
window.refreshCompletionKeys = (response) ->
diff --git a/pages/options.coffee b/pages/options.coffee
index d2950348..6545189b 100644
--- a/pages/options.coffee
+++ b/pages/options.coffee
@@ -271,8 +271,12 @@ initPopupPage = ->
exclusions = null
document.getElementById("optionsLink").setAttribute "href", chrome.runtime.getURL("pages/options.html")
+ # As the active URL, we choose the most recently registered URL from a frame in the tab, or the tab's own
+ # URL.
+ url = chrome.extension.getBackgroundPage().urlForTab[tab.id] || tab.url
+
updateState = ->
- rule = bgExclusions.getRule tab.url, exclusions.readValueFromElement()
+ rule = bgExclusions.getRule url, exclusions.readValueFromElement()
$("state").innerHTML = "Vimium will " +
if rule and rule.passKeys
"exclude <span class='code'>#{rule.passKeys}</span>"
@@ -291,8 +295,6 @@ initPopupPage = ->
Option.saveOptions()
$("saveOptions").innerHTML = "Saved"
$("saveOptions").disabled = true
- chrome.tabs.query { windowId: chrome.windows.WINDOW_ID_CURRENT, active: true }, (tabs) ->
- chrome.extension.getBackgroundPage().updateActiveState(tabs[0].id)
$("saveOptions").addEventListener "click", saveOptions
@@ -302,7 +304,7 @@ initPopupPage = ->
window.close()
# Populate options. Just one, here.
- exclusions = new ExclusionRulesOnPopupOption(tab.url, "exclusionRules", onUpdated)
+ exclusions = new ExclusionRulesOnPopupOption url, "exclusionRules", onUpdated
updateState()
document.addEventListener "keyup", updateState