From b26f4aed8585418d18dfc43262070c8c8741e5e3 Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Sun, 28 Dec 2014 19:24:33 +0000
Subject: Add UIComponent code for iframes
---
content_scripts/ui_component.coffee | 66 +++++++++++++++++++++++++++++++++++++
manifest.json | 1 +
2 files changed, 67 insertions(+)
create mode 100644 content_scripts/ui_component.coffee
diff --git a/content_scripts/ui_component.coffee b/content_scripts/ui_component.coffee
new file mode 100644
index 00000000..c0889e7f
--- /dev/null
+++ b/content_scripts/ui_component.coffee
@@ -0,0 +1,66 @@
+class UIComponent
+ iframeElement: null
+ iframePort: null
+ messageEventListeners: []
+ showStyle: ""
+ hideStyle: ""
+
+ constructor: (iframeUrl, className) ->
+ @iframeElement = document.createElement "iframe"
+ @iframeElement.className = className
+ @iframeElement.seamless = "seamless"
+ @iframeElement.src = chrome.runtime.getURL iframeUrl
+ @iframeElement.addEventListener "load", => @openPort()
+ document.documentElement.appendChild @iframeElement
+ @hide()
+
+ # 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 iframeMessageSecret so the iframe can determine that our message isn't the page impersonating us.
+ chrome.storage.local.get "iframeMessageSecret", ({iframeMessageSecret: secret}) =>
+ @iframeElement.contentWindow.postMessage secret, chrome.runtime.getURL(""), [messageChannel.port2]
+
+ postMessage: (data) -> @iframePort.postMessage data
+
+ # Execute each event listener on the current event until we get a falsy return value.
+ handleMessage: (event) ->
+ for listener in @messageEventListeners
+ retVal = listener.call this, event
+ return false unless retVal
+ true
+
+ addEventListener: (type, listener) ->
+ if type == "message"
+ @messageEventListeners.push listener
+ undefined
+
+ removeEventListener: (type, listener) ->
+ if type == "message"
+ listenerIndex = @messageEventListeners.indexOf listener
+ if listenerIndex > -1
+ @messageEventListeners = @messageEventListeners.splice listenerIndex, 1
+ undefined
+
+ setHideStyle: (@hideStyle) ->
+ @hide() if @showing == false
+
+ setShowStyle: (@showStyle) ->
+ @show() if @showing == true
+
+ show: ->
+ return unless @iframeElement?
+ @iframeElement.setAttribute "style", @showStyle
+ @iframeElement.focus()
+ @showing = true
+
+ hide: ->
+ return unless @iframeElement?
+ @iframeElement.setAttribute "style", @hideStyle
+ @showing = false
+
+root = exports ? window
+root.UIComponent = UIComponent
diff --git a/manifest.json b/manifest.json
index 3cd88d1e..a92ed0da 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",
--
cgit v1.2.3
From 020331fd8e120eee1fcb80ad05f7fcde33f3e981 Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Sun, 28 Dec 2014 19:41:30 +0000
Subject: Create a script for connecting UIComponent iframes with their parents
---
pages/ui_component_server.coffee | 41 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 pages/ui_component_server.coffee
diff --git a/pages/ui_component_server.coffee b/pages/ui_component_server.coffee
new file mode 100644
index 00000000..240233ed
--- /dev/null
+++ b/pages/ui_component_server.coffee
@@ -0,0 +1,41 @@
+# Register the port recieved from the parent window, and stop listening for messages on the window object.
+window.addEventListener "message", (event) ->
+ return unless event.source == window.parent
+ currentFunction = arguments.callee
+
+ # Check event.data against iframeMessageSecret so we can determine that this message hasn't been spoofed.
+ chrome.storage.local.get "iframeMessageSecret", ({iframeMessageSecret: secret}) ->
+ return unless event.data == secret
+ UIComponentServer.portOpen event.ports[0]
+ window.removeEventListener "message", currentFunction # Stop listening for message events.
+
+UIComponentServer =
+ ownerPagePort: null
+ messageEventListeners: []
+
+ portOpen: (@ownerPagePort) ->
+ @ownerPagePort.onmessage = (event) => @handleMessage event
+
+ postMessage: (data) -> @ownerPagePort.postMessage data
+
+ # Execute each event listener on the current event until we get a falsy return value.
+ handleMessage: (event) ->
+ for listener in @messageEventListeners
+ retVal = listener.call this, event
+ return false unless retVal
+ true
+
+ addEventListener: (type, listener) ->
+ if type == "message"
+ @messageEventListeners.push listener
+ undefined
+
+ removeEventListener: (type, listener) ->
+ if type == "message"
+ listenerIndex = @messageEventListeners.indexOf listener
+ if listenerIndex > -1
+ @messageEventListeners = @messageEventListeners.splice listenerIndex, 1
+ undefined
+
+root = exports ? window
+root.UIComponentServer = UIComponentServer
--
cgit v1.2.3
From 697b065f9adff48ad270d8ea85e90faa63190179 Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Sun, 28 Dec 2014 19:51:45 +0000
Subject: Fix tests for UIComponent
---
tests/dom_tests/chrome.coffee | 4 ++++
tests/dom_tests/dom_tests.html | 1 +
2 files changed, 5 insertions(+)
diff --git a/tests/dom_tests/chrome.coffee b/tests/dom_tests/chrome.coffee
index 7f99e27f..2695ef20 100644
--- a/tests/dom_tests/chrome.coffee
+++ b/tests/dom_tests/chrome.coffee
@@ -17,5 +17,9 @@ root.chrome = {
}
sendMessage: ->
getManifest: ->
+ getURL: (url) -> "../../#{url}"
}
+ storage:
+ local:
+ get: ->
}
diff --git a/tests/dom_tests/dom_tests.html b/tests/dom_tests/dom_tests.html
index feddafac..750af41d 100644
--- a/tests/dom_tests/dom_tests.html
+++ b/tests/dom_tests/dom_tests.html
@@ -34,6 +34,7 @@
+
--
cgit v1.2.3
From d20caa49075c0605ec2196416a5633d5e205b615 Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Sun, 28 Dec 2014 19:53:06 +0000
Subject: Add an example test for UIComponent
---
content_scripts/vimium_frontend.coffee | 15 +++++++++++++++
manifest.json | 5 ++++-
pages/test_ui_component.coffee | 2 ++
pages/test_ui_component.html | 10 ++++++++++
4 files changed, 31 insertions(+), 1 deletion(-)
create mode 100644 pages/test_ui_component.coffee
create mode 100644 pages/test_ui_component.html
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 1f116f88..245e481a 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -181,6 +181,8 @@ window.addEventListener "focus", ->
initializeOnDomReady = ->
enterInsertModeIfElementIsFocused() if isEnabledForUrl
+ testUIComponentSetup()
+
# Tell the background page we're in the dom ready state.
chrome.runtime.connect({ name: "domReady" })
@@ -920,6 +922,10 @@ exitFindMode = ->
window.showHelpDialog = (html, fid) ->
return if (isShowingHelpDialog || !document.body || fid != frameId)
+
+ testUIComponent.show()
+ testUIComponent.postMessage "version: #{chrome.runtime.getManifest().version}; random number: #{Math.random()}"
+
isShowingHelpDialog = true
container = document.createElement("div")
container.id = "vimiumHelpDialogContainer"
@@ -966,6 +972,9 @@ window.showHelpDialog = (html, fid) ->
hideHelpDialog = (clickEvent) ->
+
+ testUIComponent.hide()
+
isShowingHelpDialog = false
helpDialog = document.getElementById("vimiumHelpDialogContainer")
if (helpDialog)
@@ -1086,6 +1095,12 @@ Tween =
value = (elapsed / state.duration) * (state.to - state.from) + state.from
state.onUpdate(value)
+testUIComponent = null
+testUIComponentSetup = ->
+ testUIComponent = new UIComponent "pages/test_ui_component.html", "testUIComponent"
+ testUIComponent.setHideStyle "display: none;"
+ testUIComponent.setShowStyle "display: block;"
+
initializePreDomReady()
window.addEventListener("DOMContentLoaded", registerFrame)
window.addEventListener("unload", unregisterFrame)
diff --git a/manifest.json b/manifest.json
index a92ed0da..03676ebf 100644
--- a/manifest.json
+++ b/manifest.json
@@ -58,5 +58,8 @@
"browser_action": {
"default_icon": "icons/browser_action_disabled.png",
"default_popup": "pages/popup.html"
- }
+ },
+ "web_accessible_resources": [
+ "pages/test_ui_component.html"
+ ]
}
diff --git a/pages/test_ui_component.coffee b/pages/test_ui_component.coffee
new file mode 100644
index 00000000..b1d3625a
--- /dev/null
+++ b/pages/test_ui_component.coffee
@@ -0,0 +1,2 @@
+UIComponentServer.addEventListener "message", (event) ->
+ document.body.innerHTML = event.data
diff --git a/pages/test_ui_component.html b/pages/test_ui_component.html
new file mode 100644
index 00000000..b8ad7475
--- /dev/null
+++ b/pages/test_ui_component.html
@@ -0,0 +1,10 @@
+
+
+ Test
+
+
+
+
+
+
+
--
cgit v1.2.3
From 71af7f016f51e3c8b9c1fcfba46cb8289c91e030 Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Mon, 29 Dec 2014 08:12:59 +0000
Subject: IFrame framework; develop demo.
---
background_scripts/commands.coffee | 3 +++
content_scripts/vimium_frontend.coffee | 10 ++++------
pages/test_ui_component.coffee | 5 +++++
3 files changed, 12 insertions(+), 6 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/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 245e481a..5c166ff0 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -923,9 +923,6 @@ exitFindMode = ->
window.showHelpDialog = (html, fid) ->
return if (isShowingHelpDialog || !document.body || fid != frameId)
- testUIComponent.show()
- testUIComponent.postMessage "version: #{chrome.runtime.getManifest().version}; random number: #{Math.random()}"
-
isShowingHelpDialog = true
container = document.createElement("div")
container.id = "vimiumHelpDialogContainer"
@@ -972,9 +969,6 @@ window.showHelpDialog = (html, fid) ->
hideHelpDialog = (clickEvent) ->
-
- testUIComponent.hide()
-
isShowingHelpDialog = false
helpDialog = document.getElementById("vimiumHelpDialogContainer")
if (helpDialog)
@@ -1101,6 +1095,10 @@ testUIComponentSetup = ->
testUIComponent.setHideStyle "display: none;"
testUIComponent.setShowStyle "display: block;"
+window.activateTestUIComponent = ->
+ testUIComponent.show()
+ testUIComponent.postMessage "version: #{chrome.runtime.getManifest().version}; random number: #{Math.random()}"
+
initializePreDomReady()
window.addEventListener("DOMContentLoaded", registerFrame)
window.addEventListener("unload", unregisterFrame)
diff --git a/pages/test_ui_component.coffee b/pages/test_ui_component.coffee
index b1d3625a..0156c8f2 100644
--- a/pages/test_ui_component.coffee
+++ b/pages/test_ui_component.coffee
@@ -1,2 +1,7 @@
UIComponentServer.addEventListener "message", (event) ->
document.body.innerHTML = event.data
+
+document.addEventListener "DOMContentLoaded", ->
+ document.addEventListener "keydown", (event) ->
+ # Close on any key.
+ console.log "How do I close myself?"
--
cgit v1.2.3
From 5ea0f75a00b592956981bf8f6f7a0d2fa89620ae Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Mon, 29 Dec 2014 09:33:34 +0000
Subject: Close UIComponent iframes when pressing esc by default
---
content_scripts/ui_component.coffee | 11 +++++++++++
pages/test_ui_component.coffee | 5 -----
pages/test_ui_component.html | 1 +
pages/ui_component_server.coffee | 9 +++++++++
4 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/content_scripts/ui_component.coffee b/content_scripts/ui_component.coffee
index c0889e7f..f47719e5 100644
--- a/content_scripts/ui_component.coffee
+++ b/content_scripts/ui_component.coffee
@@ -14,6 +14,8 @@ class UIComponent
document.documentElement.appendChild @iframeElement
@hide()
+ @addEventListener "message", handleHideMessage
+
# Open a port and pass it to the iframe via window.postMessage.
openPort: ->
messageChannel = new MessageChannel()
@@ -30,6 +32,7 @@ class UIComponent
handleMessage: (event) ->
for listener in @messageEventListeners
retVal = listener.call this, event
+ retVal ?= true
return false unless retVal
true
@@ -60,7 +63,15 @@ class UIComponent
hide: ->
return unless @iframeElement?
@iframeElement.setAttribute "style", @hideStyle
+ window.focus()
@showing = false
+handleHideMessage = (event) ->
+ if event.data == "hide"
+ @hide()
+ false
+ else
+ true
+
root = exports ? window
root.UIComponent = UIComponent
diff --git a/pages/test_ui_component.coffee b/pages/test_ui_component.coffee
index 0156c8f2..b1d3625a 100644
--- a/pages/test_ui_component.coffee
+++ b/pages/test_ui_component.coffee
@@ -1,7 +1,2 @@
UIComponentServer.addEventListener "message", (event) ->
document.body.innerHTML = event.data
-
-document.addEventListener "DOMContentLoaded", ->
- document.addEventListener "keydown", (event) ->
- # Close on any key.
- console.log "How do I close myself?"
diff --git a/pages/test_ui_component.html b/pages/test_ui_component.html
index b8ad7475..06af346c 100644
--- a/pages/test_ui_component.html
+++ b/pages/test_ui_component.html
@@ -1,6 +1,7 @@
Test
+
diff --git a/pages/ui_component_server.coffee b/pages/ui_component_server.coffee
index 240233ed..3879cea0 100644
--- a/pages/ui_component_server.coffee
+++ b/pages/ui_component_server.coffee
@@ -7,11 +7,13 @@ window.addEventListener "message", (event) ->
chrome.storage.local.get "iframeMessageSecret", ({iframeMessageSecret: secret}) ->
return unless event.data == secret
UIComponentServer.portOpen event.ports[0]
+ window.addEventListener "keydown", (event) -> UIComponentServer.keydownListener event
window.removeEventListener "message", currentFunction # Stop listening for message events.
UIComponentServer =
ownerPagePort: null
messageEventListeners: []
+ exitOnEsc: true
portOpen: (@ownerPagePort) ->
@ownerPagePort.onmessage = (event) => @handleMessage event
@@ -37,5 +39,12 @@ UIComponentServer =
@messageEventListeners = @messageEventListeners.splice listenerIndex, 1
undefined
+ keydownListener: (event) ->
+ if @exitOnEsc and KeyboardUtils.isEscape event
+ @postMessage "hide"
+ false
+ else
+ true
+
root = exports ? window
root.UIComponentServer = UIComponentServer
--
cgit v1.2.3
From e5e0ddf24c7975e994b816651beaa4d0cefb94b7 Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Mon, 29 Dec 2014 10:07:25 +0000
Subject: Initialise hide/show styles for UIComponent
---
content_scripts/ui_component.coffee | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/content_scripts/ui_component.coffee b/content_scripts/ui_component.coffee
index f47719e5..ce1af082 100644
--- a/content_scripts/ui_component.coffee
+++ b/content_scripts/ui_component.coffee
@@ -2,8 +2,8 @@ class UIComponent
iframeElement: null
iframePort: null
messageEventListeners: []
- showStyle: ""
- hideStyle: ""
+ showStyle: "display: block;"
+ hideStyle: "display: none;"
constructor: (iframeUrl, className) ->
@iframeElement = document.createElement "iframe"
--
cgit v1.2.3
From 4e3ef0b401cfb4682a17a1ee88058ed76d64be20 Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Mon, 29 Dec 2014 10:29:09 +0000
Subject: Small changes to UIComponent
---
content_scripts/ui_component.coffee | 17 +++++++++++------
content_scripts/vimium_frontend.coffee | 1 -
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/content_scripts/ui_component.coffee b/content_scripts/ui_component.coffee
index ce1af082..b0e4f71c 100644
--- a/content_scripts/ui_component.coffee
+++ b/content_scripts/ui_component.coffee
@@ -5,13 +5,16 @@ class UIComponent
showStyle: "display: block;"
hideStyle: "display: none;"
- constructor: (iframeUrl, className) ->
+ constructor: (iframeUrl, className, showStyle, hideStyle) ->
@iframeElement = document.createElement "iframe"
@iframeElement.className = className
@iframeElement.seamless = "seamless"
@iframeElement.src = chrome.runtime.getURL iframeUrl
@iframeElement.addEventListener "load", => @openPort()
document.documentElement.appendChild @iframeElement
+
+ @setShowStyle showStyle if showStyle?
+ @setHideStyle hideStyle if showStyle?
@hide()
@addEventListener "message", handleHideMessage
@@ -43,9 +46,7 @@ class UIComponent
removeEventListener: (type, listener) ->
if type == "message"
- listenerIndex = @messageEventListeners.indexOf listener
- if listenerIndex > -1
- @messageEventListeners = @messageEventListeners.splice listenerIndex, 1
+ @messageEventListeners = @messageEventListeners.filter (f) -> f != listener
undefined
setHideStyle: (@hideStyle) ->
@@ -54,14 +55,18 @@ class UIComponent
setShowStyle: (@showStyle) ->
@show() if @showing == true
+ setStyles: (@showStyle = @showStyle, @hideStyle = @hideStyle) ->
+ if @showing
+ @show()
+ else
+ @hide()
+
show: ->
- return unless @iframeElement?
@iframeElement.setAttribute "style", @showStyle
@iframeElement.focus()
@showing = true
hide: ->
- return unless @iframeElement?
@iframeElement.setAttribute "style", @hideStyle
window.focus()
@showing = false
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 5c166ff0..a505a84a 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -922,7 +922,6 @@ exitFindMode = ->
window.showHelpDialog = (html, fid) ->
return if (isShowingHelpDialog || !document.body || fid != frameId)
-
isShowingHelpDialog = true
container = document.createElement("div")
container.id = "vimiumHelpDialogContainer"
--
cgit v1.2.3
From 0433dd338258dc39466593e0bce5fa3253f8d6d5 Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Mon, 29 Dec 2014 10:38:25 +0000
Subject: Allow message passing directly from UIComponent.show
---
content_scripts/ui_component.coffee | 7 ++++---
content_scripts/vimium_frontend.coffee | 2 --
pages/ui_component_server.coffee | 9 ++++-----
3 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/content_scripts/ui_component.coffee b/content_scripts/ui_component.coffee
index b0e4f71c..f0593f1b 100644
--- a/content_scripts/ui_component.coffee
+++ b/content_scripts/ui_component.coffee
@@ -29,9 +29,9 @@ class UIComponent
chrome.storage.local.get "iframeMessageSecret", ({iframeMessageSecret: secret}) =>
@iframeElement.contentWindow.postMessage secret, chrome.runtime.getURL(""), [messageChannel.port2]
- postMessage: (data) -> @iframePort.postMessage data
+ postMessage: (message) -> @iframePort.postMessage message
- # Execute each event listener on the current event until we get a falsy return value.
+ # Execute each event listener on the current event until we get a non-null falsy return value.
handleMessage: (event) ->
for listener in @messageEventListeners
retVal = listener.call this, event
@@ -61,7 +61,8 @@ class UIComponent
else
@hide()
- show: ->
+ show: (message) ->
+ @postMessage message if message?
@iframeElement.setAttribute "style", @showStyle
@iframeElement.focus()
@showing = true
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index a505a84a..beb6c528 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -1091,8 +1091,6 @@ Tween =
testUIComponent = null
testUIComponentSetup = ->
testUIComponent = new UIComponent "pages/test_ui_component.html", "testUIComponent"
- testUIComponent.setHideStyle "display: none;"
- testUIComponent.setShowStyle "display: block;"
window.activateTestUIComponent = ->
testUIComponent.show()
diff --git a/pages/ui_component_server.coffee b/pages/ui_component_server.coffee
index 3879cea0..7b40be63 100644
--- a/pages/ui_component_server.coffee
+++ b/pages/ui_component_server.coffee
@@ -18,12 +18,13 @@ UIComponentServer =
portOpen: (@ownerPagePort) ->
@ownerPagePort.onmessage = (event) => @handleMessage event
- postMessage: (data) -> @ownerPagePort.postMessage data
+ postMessage: (message) -> @ownerPagePort.postMessage message
- # Execute each event listener on the current event until we get a falsy return value.
+ # Execute each event listener on the current event until we get a non-null falsy return value.
handleMessage: (event) ->
for listener in @messageEventListeners
retVal = listener.call this, event
+ retVal ?= true
return false unless retVal
true
@@ -34,9 +35,7 @@ UIComponentServer =
removeEventListener: (type, listener) ->
if type == "message"
- listenerIndex = @messageEventListeners.indexOf listener
- if listenerIndex > -1
- @messageEventListeners = @messageEventListeners.splice listenerIndex, 1
+ @messageEventListeners = @messageEventListeners.filter (f) -> f != listener
undefined
keydownListener: (event) ->
--
cgit v1.2.3
From f53af786275c98ce08f51936b165d799a41de024 Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Mon, 29 Dec 2014 10:39:44 +0000
Subject: Update test for UIComponent
---
content_scripts/vimium_frontend.coffee | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index beb6c528..502ecaef 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -1093,8 +1093,7 @@ testUIComponentSetup = ->
testUIComponent = new UIComponent "pages/test_ui_component.html", "testUIComponent"
window.activateTestUIComponent = ->
- testUIComponent.show()
- testUIComponent.postMessage "version: #{chrome.runtime.getManifest().version}; random number: #{Math.random()}"
+ testUIComponent.show "version: #{chrome.runtime.getManifest().version}; random number: #{Math.random()}"
initializePreDomReady()
window.addEventListener("DOMContentLoaded", registerFrame)
--
cgit v1.2.3
From 26f37bb0dbda2d833f508db373629408c7ed6e09 Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Mon, 29 Dec 2014 10:42:28 +0000
Subject: Remove key handling in UIComponentServer/UIComponent code
---
content_scripts/ui_component.coffee | 2 --
pages/ui_component_server.coffee | 8 --------
2 files changed, 10 deletions(-)
diff --git a/content_scripts/ui_component.coffee b/content_scripts/ui_component.coffee
index f0593f1b..12a024e4 100644
--- a/content_scripts/ui_component.coffee
+++ b/content_scripts/ui_component.coffee
@@ -17,8 +17,6 @@ class UIComponent
@setHideStyle hideStyle if showStyle?
@hide()
- @addEventListener "message", handleHideMessage
-
# Open a port and pass it to the iframe via window.postMessage.
openPort: ->
messageChannel = new MessageChannel()
diff --git a/pages/ui_component_server.coffee b/pages/ui_component_server.coffee
index 7b40be63..ccbb9e2b 100644
--- a/pages/ui_component_server.coffee
+++ b/pages/ui_component_server.coffee
@@ -7,7 +7,6 @@ window.addEventListener "message", (event) ->
chrome.storage.local.get "iframeMessageSecret", ({iframeMessageSecret: secret}) ->
return unless event.data == secret
UIComponentServer.portOpen event.ports[0]
- window.addEventListener "keydown", (event) -> UIComponentServer.keydownListener event
window.removeEventListener "message", currentFunction # Stop listening for message events.
UIComponentServer =
@@ -38,12 +37,5 @@ UIComponentServer =
@messageEventListeners = @messageEventListeners.filter (f) -> f != listener
undefined
- keydownListener: (event) ->
- if @exitOnEsc and KeyboardUtils.isEscape event
- @postMessage "hide"
- false
- else
- true
-
root = exports ? window
root.UIComponentServer = UIComponentServer
--
cgit v1.2.3
From 4af43db2e65af772787ab55c44604f4760eaee3d Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Mon, 29 Dec 2014 10:46:42 +0000
Subject: Update UIComponent test
---
content_scripts/vimium_frontend.coffee | 7 +++++++
pages/test_ui_component.coffee | 4 ++++
2 files changed, 11 insertions(+)
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 502ecaef..a0623d32 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -1091,6 +1091,13 @@ Tween =
testUIComponent = null
testUIComponentSetup = ->
testUIComponent = new UIComponent "pages/test_ui_component.html", "testUIComponent"
+ testUIComponent.addEventListener "message", (event) ->
+ if event.data == "hide"
+ @hide()
+ window.focus()
+ false
+ else
+ true
window.activateTestUIComponent = ->
testUIComponent.show "version: #{chrome.runtime.getManifest().version}; random number: #{Math.random()}"
diff --git a/pages/test_ui_component.coffee b/pages/test_ui_component.coffee
index b1d3625a..886a3470 100644
--- a/pages/test_ui_component.coffee
+++ b/pages/test_ui_component.coffee
@@ -1,2 +1,6 @@
UIComponentServer.addEventListener "message", (event) ->
document.body.innerHTML = event.data
+
+window.addEventListener "keydown", (event) ->
+ if KeyboardUtils.isEscape event
+ UIComponentServer.postMessage "hide"
--
cgit v1.2.3
From f38a834cc38d17b086253dea197e6a8945551377 Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Mon, 29 Dec 2014 11:29:12 +0000
Subject: Add UIComponent.active, so we can specify whether to focus the frame
---
content_scripts/ui_component.coffee | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/content_scripts/ui_component.coffee b/content_scripts/ui_component.coffee
index 12a024e4..10450778 100644
--- a/content_scripts/ui_component.coffee
+++ b/content_scripts/ui_component.coffee
@@ -59,10 +59,14 @@ class UIComponent
else
@hide()
+ activate: (message) ->
+ @postMessage message if message?
+ @show() unless @showing
+ @iframeElement.focus()
+
show: (message) ->
@postMessage message if message?
@iframeElement.setAttribute "style", @showStyle
- @iframeElement.focus()
@showing = true
hide: ->
--
cgit v1.2.3
From a6dc63fd7c49926e6ad32174621b32eeb3fd9283 Mon Sep 17 00:00:00 2001
From: mrmr1993
Date: Mon, 29 Dec 2014 11:30:41 +0000
Subject: Update UIComponent test
---
content_scripts/vimium_frontend.coffee | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index a0623d32..3f898b74 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -1100,7 +1100,7 @@ testUIComponentSetup = ->
true
window.activateTestUIComponent = ->
- testUIComponent.show "version: #{chrome.runtime.getManifest().version}; random number: #{Math.random()}"
+ testUIComponent.activate "version: #{chrome.runtime.getManifest().version}; random number: #{Math.random()}"
initializePreDomReady()
window.addEventListener("DOMContentLoaded", registerFrame)
--
cgit v1.2.3
From 0524bdc3f76279e8930bfe4b1b42d93e0e9bf6e4 Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Mon, 29 Dec 2014 14:22:53 +0000
Subject: Refactor UIComponent, etc., and demo.
- Simplify component API.
- Iframe flashes on re-focus.
- Probably some other stuff which I've forgotten.
---
background_scripts/main.coffee | 5 ++
content_scripts/ui_component.coffee | 79 +++++++++----------------------
content_scripts/vimium_frontend.coffee | 10 ++--
pages/test_ui_component.coffee | 4 +-
pages/ui_component_server.coffee | 44 ++++++-----------
tests/dom_tests/chrome.coffee | 1 +
tests/unit_tests/test_chrome_stubs.coffee | 4 ++
7 files changed, 56 insertions(+), 91 deletions(-)
diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee
index 647923c0..b85ea844 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
index 10450778..a898d525 100644
--- a/content_scripts/ui_component.coffee
+++ b/content_scripts/ui_component.coffee
@@ -1,21 +1,19 @@
class UIComponent
iframeElement: null
iframePort: null
- messageEventListeners: []
+ showing: true
showStyle: "display: block;"
hideStyle: "display: none;"
- constructor: (iframeUrl, className, showStyle, hideStyle) ->
+ 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
-
- @setShowStyle showStyle if showStyle?
- @setHideStyle hideStyle if showStyle?
- @hide()
+ # Hide iframe, but don't interfere with the focus.
+ @hide false
# Open a port and pass it to the iframe via window.postMessage.
openPort: ->
@@ -23,63 +21,32 @@ class UIComponent
@iframePort = messageChannel.port1
@iframePort.onmessage = (event) => @handleMessage event
- # Get iframeMessageSecret so the iframe can determine that our message isn't the page impersonating us.
- chrome.storage.local.get "iframeMessageSecret", ({iframeMessageSecret: secret}) =>
+ # 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
-
- # Execute each event listener on the current event until we get a non-null falsy return value.
- handleMessage: (event) ->
- for listener in @messageEventListeners
- retVal = listener.call this, event
- retVal ?= true
- return false unless retVal
- true
-
- addEventListener: (type, listener) ->
- if type == "message"
- @messageEventListeners.push listener
- undefined
-
- removeEventListener: (type, listener) ->
- if type == "message"
- @messageEventListeners = @messageEventListeners.filter (f) -> f != listener
- undefined
-
- setHideStyle: (@hideStyle) ->
- @hide() if @showing == false
-
- setShowStyle: (@showStyle) ->
- @show() if @showing == true
-
- setStyles: (@showStyle = @showStyle, @hideStyle = @hideStyle) ->
- if @showing
- @show()
- else
- @hide()
+ postMessage: (message) ->
+ @iframePort.postMessage message
activate: (message) ->
@postMessage message if message?
- @show() unless @showing
+ 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()
- show: (message) ->
- @postMessage message if message?
- @iframeElement.setAttribute "style", @showStyle
- @showing = true
-
- hide: ->
- @iframeElement.setAttribute "style", @hideStyle
- window.focus()
- @showing = false
-
-handleHideMessage = (event) ->
- if event.data == "hide"
- @hide()
- false
- else
- true
+ hide: (focusWindow=true)->
+ if @showing
+ @iframeElement.setAttribute "style", @hideStyle
+ # TODO(smblott) Is window always the right thing to focus, here?
+ 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 3f898b74..8fcb16ed 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -1090,17 +1090,17 @@ Tween =
testUIComponent = null
testUIComponentSetup = ->
- testUIComponent = new UIComponent "pages/test_ui_component.html", "testUIComponent"
- testUIComponent.addEventListener "message", (event) ->
+ testUIComponent = new UIComponent "pages/test_ui_component.html", "testUIComponent", (event) ->
if event.data == "hide"
@hide()
window.focus()
- false
else
- true
+ # ... And we can get data back!
+ console.log event.data
window.activateTestUIComponent = ->
- testUIComponent.activate "version: #{chrome.runtime.getManifest().version}; random number: #{Math.random()}"
+ chrome.storage.local.get "vimiumSecret", ({vimiumSecret: secret}) ->
+ testUIComponent.activate [chrome.runtime.getManifest().version, secret, Math.random(), ].join "
"
initializePreDomReady()
window.addEventListener("DOMContentLoaded", registerFrame)
diff --git a/pages/test_ui_component.coffee b/pages/test_ui_component.coffee
index 886a3470..e140fb14 100644
--- a/pages/test_ui_component.coffee
+++ b/pages/test_ui_component.coffee
@@ -1,6 +1,8 @@
-UIComponentServer.addEventListener "message", (event) ->
+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/ui_component_server.coffee b/pages/ui_component_server.coffee
index ccbb9e2b..8b43095b 100644
--- a/pages/ui_component_server.coffee
+++ b/pages/ui_component_server.coffee
@@ -1,41 +1,27 @@
-# Register the port recieved from the parent window, and stop listening for messages on the window object.
-window.addEventListener "message", (event) ->
- return unless event.source == window.parent
- currentFunction = arguments.callee
- # Check event.data against iframeMessageSecret so we can determine that this message hasn't been spoofed.
- chrome.storage.local.get "iframeMessageSecret", ({iframeMessageSecret: secret}) ->
- return unless event.data == secret
+# 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", currentFunction # Stop listening for message events.
+ window.removeEventListener "message", registerPort
+
+window.addEventListener "message", registerPort
UIComponentServer =
ownerPagePort: null
- messageEventListeners: []
- exitOnEsc: true
+ handleMessage: null
portOpen: (@ownerPagePort) ->
- @ownerPagePort.onmessage = (event) => @handleMessage event
-
- postMessage: (message) -> @ownerPagePort.postMessage message
-
- # Execute each event listener on the current event until we get a non-null falsy return value.
- handleMessage: (event) ->
- for listener in @messageEventListeners
- retVal = listener.call this, event
- retVal ?= true
- return false unless retVal
- true
+ @ownerPagePort.onmessage = (event) =>
+ @handleMessage event if @handleMessage
- addEventListener: (type, listener) ->
- if type == "message"
- @messageEventListeners.push listener
- undefined
+ registerHandler: (@handleMessage) ->
- removeEventListener: (type, listener) ->
- if type == "message"
- @messageEventListeners = @messageEventListeners.filter (f) -> f != listener
- undefined
+ 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 2695ef20..a49a565a 100644
--- a/tests/dom_tests/chrome.coffee
+++ b/tests/dom_tests/chrome.coffee
@@ -22,4 +22,5 @@ root.chrome = {
storage:
local:
get: ->
+ set: ->
}
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
--
cgit v1.2.3
From 7499675455941251eaa69c93e7c66bfb1c6ae35c Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Mon, 29 Dec 2014 17:08:39 +0000
Subject: Clearer handling of @showing in UI component.
---
content_scripts/ui_component.coffee | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/content_scripts/ui_component.coffee b/content_scripts/ui_component.coffee
index a898d525..d89f0cc8 100644
--- a/content_scripts/ui_component.coffee
+++ b/content_scripts/ui_component.coffee
@@ -1,7 +1,7 @@
class UIComponent
iframeElement: null
iframePort: null
- showing: true
+ showing: null
showStyle: "display: block;"
hideStyle: "display: none;"
@@ -12,7 +12,8 @@ class UIComponent
@iframeElement.src = chrome.runtime.getURL iframeUrl
@iframeElement.addEventListener "load", => @openPort()
document.documentElement.appendChild @iframeElement
- # Hide iframe, but don't interfere with the focus.
+ @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.
@@ -44,7 +45,6 @@ class UIComponent
hide: (focusWindow=true)->
if @showing
@iframeElement.setAttribute "style", @hideStyle
- # TODO(smblott) Is window always the right thing to focus, here?
window.focus() if focusWindow
@showing = false
--
cgit v1.2.3