diff options
| -rw-r--r-- | background_scripts/main.coffee | 9 | ||||
| -rw-r--r-- | background_scripts/settings.coffee | 1 | ||||
| -rw-r--r-- | content_scripts/vimium_frontend.coffee | 33 | ||||
| -rw-r--r-- | content_scripts/vomnibar.coffee | 2 | ||||
| -rw-r--r-- | lib/dom_utils.coffee | 5 | ||||
| -rw-r--r-- | lib/utils.coffee | 12 | ||||
| -rw-r--r-- | pages/blank.html | 8 | ||||
| -rw-r--r-- | pages/content_script_loader.coffee | 28 | ||||
| -rw-r--r-- | pages/options.coffee | 1 | ||||
| -rw-r--r-- | pages/options.html | 27 | ||||
| -rw-r--r-- | tests/dom_tests/dom_tests.coffee | 2 | ||||
| -rw-r--r-- | tests/dom_tests/vomnibar_test.coffee | 2 | ||||
| -rw-r--r-- | tests/unit_tests/utils_test.coffee | 14 |
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}" |
