aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--background_scripts/commands.coffee3
-rw-r--r--background_scripts/main.coffee5
-rw-r--r--content_scripts/ui_component.coffee52
-rw-r--r--content_scripts/vimium_frontend.coffee1
-rw-r--r--manifest.json1
-rw-r--r--pages/test_ui_component.coffee8
-rw-r--r--pages/test_ui_component.html11
-rw-r--r--pages/ui_component_server.coffee27
-rw-r--r--tests/dom_tests/chrome.coffee5
-rw-r--r--tests/dom_tests/dom_tests.html1
-rw-r--r--tests/unit_tests/test_chrome_stubs.coffee4
11 files changed, 117 insertions, 1 deletions
diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee
index 585ef572..63b870cc 100644
--- a/background_scripts/commands.coffee
+++ b/background_scripts/commands.coffee
@@ -91,6 +91,7 @@ Commands =
commandGroups:
pageNavigation:
["scrollDown",
+ "activateTestUIComponent",
"scrollUp",
"scrollLeft",
"scrollRight",
@@ -252,6 +253,7 @@ defaultKeyMappings =
"m": "Marks.activateCreateMode"
"`": "Marks.activateGotoMode"
+ "D": "activateTestUIComponent"
# This is a mapping of: commandIdentifier => [description, options].
@@ -263,6 +265,7 @@ commandDescriptions =
scrollUp: ["Scroll up"]
scrollLeft: ["Scroll left"]
scrollRight: ["Scroll right"]
+ activateTestUIComponent: ["UI component test"]
scrollToTop: ["Scroll to the top of the page", { noRepeat: true }]
scrollToBottom: ["Scroll to the bottom of the page", { noRepeat: true }]
diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee
index 3753fd75..d01a3f6c 100644
--- a/background_scripts/main.coffee
+++ b/background_scripts/main.coffee
@@ -19,6 +19,11 @@ namedKeyRegex = /^(<(?:[amc]-.|(?:[amc]-)?[a-z0-9]{2,5})>)(.*)$/
selectionChangedHandlers = []
tabLoadedHandlers = {} # tabId -> function()
+# A secret, available only within the current instantiation of Vimium. The secret is big, likely unguessable
+# in practice, but less than 2^31.
+chrome.storage.local.set
+ vimiumSecret: Math.floor Math.random() * 2000000000
+
completionSources =
bookmarks: new BookmarkCompleter()
history: new HistoryCompleter()
diff --git a/content_scripts/ui_component.coffee b/content_scripts/ui_component.coffee
new file mode 100644
index 00000000..d89f0cc8
--- /dev/null
+++ b/content_scripts/ui_component.coffee
@@ -0,0 +1,52 @@
+class UIComponent
+ iframeElement: null
+ iframePort: null
+ showing: null
+ showStyle: "display: block;"
+ hideStyle: "display: none;"
+
+ constructor: (iframeUrl, className, @handleMessage) ->
+ @iframeElement = document.createElement "iframe"
+ @iframeElement.className = className
+ @iframeElement.seamless = "seamless"
+ @iframeElement.src = chrome.runtime.getURL iframeUrl
+ @iframeElement.addEventListener "load", => @openPort()
+ document.documentElement.appendChild @iframeElement
+ @showing = true # The iframe is visible now.
+ # Hide the iframe, but don't interfere with the focus.
+ @hide false
+
+ # Open a port and pass it to the iframe via window.postMessage.
+ openPort: ->
+ messageChannel = new MessageChannel()
+ @iframePort = messageChannel.port1
+ @iframePort.onmessage = (event) => @handleMessage event
+
+ # Get vimiumSecret so the iframe can determine that our message isn't the page impersonating us.
+ chrome.storage.local.get "vimiumSecret", ({vimiumSecret: secret}) =>
+ @iframeElement.contentWindow.postMessage secret, chrome.runtime.getURL(""), [messageChannel.port2]
+
+ postMessage: (message) ->
+ @iframePort.postMessage message
+
+ activate: (message) ->
+ @postMessage message if message?
+ if @showing
+ # NOTE(smblott) Experimental. Not sure this is a great idea. If the iframe was already showing, then
+ # the user gets no visual feedback when it is re-focused. So flash its border.
+ borderWas = @iframeElement.style.border
+ @iframeElement.style.border = '5px solid yellow'
+ setTimeout((=> @iframeElement.style.border = borderWas), 200)
+ else
+ @iframeElement.setAttribute "style", @showStyle
+ @showing = true
+ @iframeElement.focus()
+
+ hide: (focusWindow=true)->
+ if @showing
+ @iframeElement.setAttribute "style", @hideStyle
+ window.focus() if focusWindow
+ @showing = false
+
+root = exports ? window
+root.UIComponent = UIComponent
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 2de08c39..114786e8 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -198,7 +198,6 @@ window.addEventListener "focus", ->
#
initializeOnDomReady = ->
enterInsertModeIfElementIsFocused() if isEnabledForUrl
-
# Tell the background page we're in the dom ready state.
chrome.runtime.connect({ name: "domReady" })
CursorHider.init()
diff --git a/manifest.json b/manifest.json
index 4996d93f..96739d2e 100644
--- a/manifest.json
+++ b/manifest.json
@@ -37,6 +37,7 @@
"lib/dom_utils.js",
"lib/handler_stack.js",
"lib/clipboard.js",
+ "content_scripts/ui_component.js",
"content_scripts/link_hints.js",
"content_scripts/vomnibar.js",
"content_scripts/scroller.js",
diff --git a/pages/test_ui_component.coffee b/pages/test_ui_component.coffee
new file mode 100644
index 00000000..e140fb14
--- /dev/null
+++ b/pages/test_ui_component.coffee
@@ -0,0 +1,8 @@
+UIComponentServer.registerHandler (event) ->
+ document.body.innerHTML = event.data
+
+window.addEventListener "keydown", (event) ->
+ if KeyboardUtils.isEscape event
+ UIComponentServer.postMessage "hide"
+ else
+ UIComponentServer.postMessage event.keyCode
diff --git a/pages/test_ui_component.html b/pages/test_ui_component.html
new file mode 100644
index 00000000..06af346c
--- /dev/null
+++ b/pages/test_ui_component.html
@@ -0,0 +1,11 @@
+<html>
+ <head>
+ <title>Test</title>
+ <script type="text/javascript" src="../lib/keyboard_utils.js"></script>
+ <script type="text/javascript" src="ui_component_server.js"></script>
+ <script type="text/javascript" src="test_ui_component.js"></script>
+ <link rel="stylesheet" type="text/css" href="../content_scripts/vimium.css" />
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/pages/ui_component_server.coffee b/pages/ui_component_server.coffee
new file mode 100644
index 00000000..8b43095b
--- /dev/null
+++ b/pages/ui_component_server.coffee
@@ -0,0 +1,27 @@
+
+# Fetch the Vimium secret, register the port recieved from the parent window, and stop listening for messages
+# on the window object. vimiumSecret is accessible only within the current instantion of Vimium. So a
+# malicious host page trying to register its own port can do no better than guessing.
+registerPort = (event) ->
+ chrome.storage.local.get "vimiumSecret", ({vimiumSecret: secret}) ->
+ return unless event.source == window.parent and event.data == secret
+ UIComponentServer.portOpen event.ports[0]
+ window.removeEventListener "message", registerPort
+
+window.addEventListener "message", registerPort
+
+UIComponentServer =
+ ownerPagePort: null
+ handleMessage: null
+
+ portOpen: (@ownerPagePort) ->
+ @ownerPagePort.onmessage = (event) =>
+ @handleMessage event if @handleMessage
+
+ registerHandler: (@handleMessage) ->
+
+ postMessage: (message) ->
+ @ownerPagePort.postMessage message if @ownerPagePort
+
+root = exports ? window
+root.UIComponentServer = UIComponentServer
diff --git a/tests/dom_tests/chrome.coffee b/tests/dom_tests/chrome.coffee
index 15ed4339..ad4ae74b 100644
--- a/tests/dom_tests/chrome.coffee
+++ b/tests/dom_tests/chrome.coffee
@@ -20,5 +20,10 @@ root.chrome = {
}
sendMessage: ->
getManifest: ->
+ getURL: (url) -> "../../#{url}"
}
+ storage:
+ local:
+ get: ->
+ set: ->
}
diff --git a/tests/dom_tests/dom_tests.html b/tests/dom_tests/dom_tests.html
index 6378807f..863c5611 100644
--- a/tests/dom_tests/dom_tests.html
+++ b/tests/dom_tests/dom_tests.html
@@ -34,6 +34,7 @@
<script type="text/javascript" src="../../lib/dom_utils.js"></script>
<script type="text/javascript" src="../../lib/handler_stack.js"></script>
<script type="text/javascript" src="../../lib/clipboard.js"></script>
+ <script type="text/javascript" src="../../content_scripts/ui_component.js"></script>
<script type="text/javascript" src="../../content_scripts/link_hints.js"></script>
<!-- TODO(smblott) The following is being overridden by the inclusion of "../../pages/vomnibar.js", below,
because they both define the same Vomnibar class/object. As a result, there are currently no tests
diff --git a/tests/unit_tests/test_chrome_stubs.coffee b/tests/unit_tests/test_chrome_stubs.coffee
index 80750337..3258bcd6 100644
--- a/tests/unit_tests/test_chrome_stubs.coffee
+++ b/tests/unit_tests/test_chrome_stubs.coffee
@@ -42,6 +42,10 @@ exports.chrome =
getAll: () -> true
storage:
+ # chrome.storage.local
+ local:
+ set: ->
+
# chrome.storage.onChanged
onChanged:
addListener: (func) -> @func = func