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}" | 
