aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--background_scripts/main.coffee9
-rw-r--r--background_scripts/settings.coffee1
-rw-r--r--content_scripts/vimium_frontend.coffee33
-rw-r--r--content_scripts/vomnibar.coffee2
-rw-r--r--lib/dom_utils.coffee5
-rw-r--r--lib/utils.coffee12
-rw-r--r--pages/blank.html8
-rw-r--r--pages/content_script_loader.coffee28
-rw-r--r--pages/options.coffee1
-rw-r--r--pages/options.html27
-rw-r--r--tests/dom_tests/dom_tests.coffee2
-rw-r--r--tests/dom_tests/vomnibar_test.coffee2
-rw-r--r--tests/unit_tests/utils_test.coffee14
13 files changed, 106 insertions, 38 deletions
diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee
index 898f46f1..b40907fb 100644
--- a/background_scripts/main.coffee
+++ b/background_scripts/main.coffee
@@ -231,7 +231,7 @@ moveTab = (callback, direction) ->
# These are commands which are bound to keystroke which must be handled by the background page. They are
# mapped in commands.coffee.
BackgroundCommands =
- createTab: (callback) -> chrome.tabs.create({ url: "chrome://newtab" }, (tab) -> callback())
+ createTab: (callback) -> chrome.tabs.create({url: Settings.get("newTabUrl")}, (tab) -> callback())
duplicateTab: (callback) ->
chrome.tabs.getSelected(null, (tab) ->
chrome.tabs.duplicate(tab.id)
@@ -393,10 +393,9 @@ chrome.tabs.onUpdated.addListener (tabId, changeInfo, tab) ->
allFrames: true
code: Settings.get("userDefinedLinkHintCss")
runAt: "document_start"
- chrome.tabs.insertCSS tabId, cssConf, ->
- if not chrome.runtime.lastError
- updateOpenTabs(tab)
- updateActiveState(tabId)
+ chrome.tabs.insertCSS tabId, cssConf, -> chrome.runtime.lastError
+ updateOpenTabs(tab)
+ updateActiveState(tabId)
chrome.tabs.onAttached.addListener (tabId, attachedInfo) ->
# We should update all the tabs in the old window and the new window.
diff --git a/background_scripts/settings.coffee b/background_scripts/settings.coffee
index 7150fcba..d6e8fcde 100644
--- a/background_scripts/settings.coffee
+++ b/background_scripts/settings.coffee
@@ -105,6 +105,7 @@ root.Settings = Settings =
searchUrl: "http://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"
+ newTabUrl: "chrome://newtab"
settingsVersion: Utils.getCurrentVersion()
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 4f7becba..118f985e 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -136,31 +136,36 @@ initializePreDomReady = ->
false
# Wrapper to install event listeners. Syntactic sugar.
-installListener = (event, callback) -> document.addEventListener(event, callback, true)
+installListener = (element, event, callback) ->
+ element.addEventListener(event, ->
+ if isEnabledForUrl then callback.apply(this, arguments) else true
+ , true)
#
-# This is called once the background page has told us that Vimium should be enabled for the current URL.
-# We enable/disable Vimium by toggling isEnabledForUrl. The alternative, installing or uninstalling
-# listeners, is error prone. It's more difficult to keep track of the state.
+# 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.
#
installedListeners = false
initializeWhenEnabled = (newPassKeys) ->
isEnabledForUrl = true
passKeys = newPassKeys
if (!installedListeners)
- installListener "keydown", (event) -> if isEnabledForUrl then onKeydown(event) else true
- installListener "keypress", (event) -> if isEnabledForUrl then onKeypress(event) else true
- installListener "keyup", (event) -> if isEnabledForUrl then onKeyup(event) else true
- installListener "focus", (event) -> if isEnabledForUrl then onFocusCapturePhase(event) else true
- installListener "blur", (event) -> if isEnabledForUrl then onBlurCapturePhase(event)
- installListener "DOMActivate", (event) -> if isEnabledForUrl then onDOMActivate(event)
+ # 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.
+ installListener window, "keydown", onKeydown
+ installListener window, "keypress", onKeypress
+ installListener window, "keyup", onKeyup
+ installListener document, "focus", onFocusCapturePhase
+ installListener document, "blur", onBlurCapturePhase
+ installListener document, "DOMActivate", onDOMActivate
enterInsertModeIfElementIsFocused()
installedListeners = true
setState = (request) ->
+ initializeWhenEnabled(request.passKeys) if request.enabled
isEnabledForUrl = request.enabled
passKeys = request.passKeys
- initializeWhenEnabled(passKeys) if isEnabledForUrl and !installedListeners
#
# The backend needs to know which frame has focus.
@@ -425,7 +430,7 @@ onKeydown = (event) ->
handledKeydownEvents.push event
else if (!modifiers)
- event.stopPropagation()
+ DomUtils.suppressPropagation(event)
handledKeydownEvents.push event
else if (isShowingHelpDialog && KeyboardUtils.isEscape(event))
@@ -457,7 +462,7 @@ onKeydown = (event) ->
if (keyChar == "" && !isInsertMode() &&
(currentCompletionKeys.indexOf(KeyboardUtils.getKeyChar(event)) != -1 ||
isValidFirstKey(KeyboardUtils.getKeyChar(event))))
- event.stopPropagation()
+ DomUtils.suppressPropagation(event)
handledKeydownEvents.push event
onKeyup = (event) ->
@@ -473,7 +478,7 @@ onKeyup = (event) ->
event.keyCode == keydown.keyCode
handledKeydownEvents.splice i, 1
- event.stopPropagation()
+ DomUtils.suppressPropagation(event)
break
checkIfEnabledForUrl = ->
diff --git a/content_scripts/vomnibar.coffee b/content_scripts/vomnibar.coffee
index 22b9ed64..f1d2ccc5 100644
--- a/content_scripts/vomnibar.coffee
+++ b/content_scripts/vomnibar.coffee
@@ -139,7 +139,7 @@ class VomnibarUI
@hide()
# It seems like we have to manually suppress the event here and still return true.
- event.stopPropagation()
+ DomUtils.suppressPropagation(event)
event.preventDefault()
true
diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee
index dcdd5518..62e655e7 100644
--- a/lib/dom_utils.coffee
+++ b/lib/dom_utils.coffee
@@ -127,9 +127,12 @@ DomUtils =
document.documentElement.appendChild(flashEl)
setTimeout((-> DomUtils.removeElement flashEl), 400)
+ suppressPropagation: (event) ->
+ event.stopImmediatePropagation()
+
suppressEvent: (event) ->
event.preventDefault()
- event.stopPropagation()
+ @suppressPropagation(event)
root = exports ? window
root.DomUtils = DomUtils
diff --git a/lib/utils.coffee b/lib/utils.coffee
index a93831d7..bbcee1a0 100644
--- a/lib/utils.coffee
+++ b/lib/utils.coffee
@@ -25,11 +25,13 @@ Utils =
id = 0
-> id += 1
- hasChromePrefix: (url) ->
- chromePrefixes = [ "about", "view-source", "chrome-extension", "data" ]
- for prefix in chromePrefixes
- return true if url.startsWith prefix
- false
+ hasChromePrefix: do ->
+ chromePrefixes = [ "about:", "view-source:", "chrome-extension:", "data:" ]
+ (url) ->
+ if 0 < url.indexOf ":"
+ for prefix in chromePrefixes
+ return true if url.startsWith prefix
+ false
# Completes a partial URL (without scheme)
createFullUrl: (partialUrl) ->
diff --git a/pages/blank.html b/pages/blank.html
new file mode 100644
index 00000000..496c1868
--- /dev/null
+++ b/pages/blank.html
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <title>New Tab</title>
+ <script src="content_script_loader.js"></script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/pages/content_script_loader.coffee b/pages/content_script_loader.coffee
new file mode 100644
index 00000000..5058bb7b
--- /dev/null
+++ b/pages/content_script_loader.coffee
@@ -0,0 +1,28 @@
+injectContentScripts = ->
+ manifest = chrome.runtime.getManifest()
+ content_scripts = manifest.content_scripts
+
+ insertLocation = document.head.firstChild
+
+ for scriptInfo in content_scripts
+ continue if scriptInfo.matches.indexOf("<all_urls>") == -1
+
+ if scriptInfo.js
+ for script in scriptInfo.js
+ scriptElement = document.createElement "script"
+ scriptElement.type = "text/javascript"
+ scriptElement.async = false # Don't load out of order!
+ scriptElement.src = chrome.runtime.getURL script
+
+ insertLocation.parentElement.insertBefore scriptElement, insertLocation
+
+ if scriptInfo.css
+ for style in scriptInfo.css
+ styleElement = document.createElement "link"
+ styleElement.rel = "stylesheet"
+ styleElement.type = "text/css"
+ styleElement.href = chrome.runtime.getURL style
+
+ insertLocation.parentElement.insertBefore styleElement, insertLocation
+
+injectContentScripts()
diff --git a/pages/options.coffee b/pages/options.coffee
index bbf47b77..f5968eb9 100644
--- a/pages/options.coffee
+++ b/pages/options.coffee
@@ -191,6 +191,7 @@ document.addEventListener "DOMContentLoaded", ->
keyMappings: TextOption
linkHintCharacters: NonEmptyTextOption
linkHintNumbers: NonEmptyTextOption
+ newTabUrl: NonEmptyTextOption
nextPatterns: NonEmptyTextOption
previousPatterns: NonEmptyTextOption
regexFindMode: CheckBoxOption
diff --git a/pages/options.html b/pages/options.html
index 33272ec5..4f037ba5 100644
--- a/pages/options.html
+++ b/pages/options.html
@@ -1,15 +1,7 @@
<html>
<head>
<title>Vimium Options</title>
- <script src="../lib/utils.js"></script>
- <script src="../lib/keyboard_utils.js"></script>
- <script src="../lib/dom_utils.js"></script>
- <script src="../lib/handler_stack.js"></script>
- <script src="../lib/clipboard.js"></script>
- <script src="../content_scripts/link_hints.js"></script>
- <script src="../content_scripts/vomnibar.js"></script>
- <script src="../content_scripts/scroller.js"></script>
- <script src="../content_scripts/vimium_frontend.js"></script>
+ <script src="content_script_loader.js"></script>
<style type="text/css" media="screen">
body {
font: 14px "DejaVu Sans", "Arial", sans-serif;
@@ -138,6 +130,9 @@
input#previousPatterns, input#nextPatterns {
width: 100%;
}
+ input#newTabUrl {
+ width: 100%;
+ }
input#searchUrl {
width: 100%;
}
@@ -215,7 +210,6 @@
margin-right: 0px;
}
</style>
- <link rel="stylesheet" type="text/css" href="../content_scripts/vimium.css" />
<script type="text/javascript" src="options.js"></script>
@@ -390,6 +384,19 @@ unmapAll
</td>
</tr>
<tr>
+ <td class="caption">New tab URL</td>
+ <td verticalAlign="top">
+ <div class="help">
+ <div class="example">
+ The page to open with the "create new tab" command.
+ Set this to "<tt>pages/blank.html</tt>" for a blank page.<br />
+ </div>
+ </div>
+ <input id="newTabUrl" type="text" />
+ <div class="nonEmptyTextOption">
+ </td>
+ </tr>
+ <tr>
<td class="caption">Default search<br/>engine</td>
<td verticalAlign="top">
<div class="help">
diff --git a/tests/dom_tests/dom_tests.coffee b/tests/dom_tests/dom_tests.coffee
index ac3f9ebe..4a61877c 100644
--- a/tests/dom_tests/dom_tests.coffee
+++ b/tests/dom_tests/dom_tests.coffee
@@ -8,7 +8,7 @@ mockKeyboardEvent = (keyChar) ->
event.charCode = (if keyCodes[keyChar] isnt undefined then keyCodes[keyChar] else keyChar.charCodeAt(0))
event.keyIdentifier = "U+00" + event.charCode.toString(16)
event.keyCode = event.charCode
- event.stopPropagation = ->
+ event.stopImmediatePropagation = ->
event.preventDefault = ->
event
diff --git a/tests/dom_tests/vomnibar_test.coffee b/tests/dom_tests/vomnibar_test.coffee
index dc2a849f..b414fdfb 100644
--- a/tests/dom_tests/vomnibar_test.coffee
+++ b/tests/dom_tests/vomnibar_test.coffee
@@ -52,7 +52,7 @@ context "Keep selection within bounds",
eventMock =
preventDefault: ->
- stopPropagation: ->
+ stopImmediatePropagation: ->
@completions = [{html:'foo',type:'tab',url:'http://example.com'}]
ui.update(true)
diff --git a/tests/unit_tests/utils_test.coffee b/tests/unit_tests/utils_test.coffee
index 76a023ed..b2d656ab 100644
--- a/tests/unit_tests/utils_test.coffee
+++ b/tests/unit_tests/utils_test.coffee
@@ -47,6 +47,20 @@ context "convertToUrl",
assert.equal "http://www.google.com/search?q=google", Utils.convertToUrl("google")
assert.equal "http://www.google.com/search?q=go%20ogle.com", Utils.convertToUrl("go ogle.com")
+context "hasChromePrefix",
+ should "detect chrome prefixes of URLs", ->
+ assert.isTrue Utils.hasChromePrefix "about:foobar"
+ assert.isTrue Utils.hasChromePrefix "view-source:foobar"
+ assert.isTrue Utils.hasChromePrefix "chrome-extension:foobar"
+ assert.isTrue Utils.hasChromePrefix "data:foobar"
+ assert.isTrue Utils.hasChromePrefix "data:"
+ assert.isFalse Utils.hasChromePrefix ""
+ assert.isFalse Utils.hasChromePrefix "about"
+ assert.isFalse Utils.hasChromePrefix "view-source"
+ assert.isFalse Utils.hasChromePrefix "chrome-extension"
+ assert.isFalse Utils.hasChromePrefix "data"
+ assert.isFalse Utils.hasChromePrefix "data :foobar"
+
context "Function currying",
should "Curry correctly", ->
foo = (a, b) -> "#{a},#{b}"