From 6653fa0e588d9fb777b627c947b377fa0518bfc8 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Mon, 14 Mar 2016 09:20:27 +0000 Subject: Use ports to track frames. Use `onConnect()`, the `domReady` port and `onDisconnect()` to track the frames within a tab. --- content_scripts/vimium_frontend.coffee | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 037d01d3..c948f843 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -214,26 +214,14 @@ window.addEventListener "hashchange", onFocus # initializeOnDomReady = -> # Tell the background page we're in the dom ready state. - chrome.runtime.connect(name: "domReady").onDisconnect.addListener -> + port = chrome.runtime.connect name: "domReady" + port.postMessage handler: "registerFrame", frameId: frameId, isTopFrame: DomUtils.isTopFrame() + port.onDisconnect.addListener -> # We disable content scripts when we lose contact with the background page. isEnabledForUrl = false chrome.runtime.sendMessage = -> window.removeEventListener "focus", onFocus -registerFrame = -> - # Don't register frameset containers; focusing them is no use. - unless document.body?.tagName.toLowerCase() == "frameset" - chrome.runtime.sendMessage - handler: "registerFrame" - frameId: frameId - -# Unregister the frame if we're going to exit. -unregisterFrame = -> - chrome.runtime.sendMessage - handler: "unregisterFrame" - frameId: frameId - tab_is_closing: DomUtils.isTopFrame() - handleShowHUDforDuration = ({ text, duration }) -> if DomUtils.isTopFrame() DomUtils.documentReady -> HUD.showForDuration text, duration @@ -271,12 +259,12 @@ DomUtils.documentReady -> # Called from the backend in order to change frame focus. # focusThisFrame = (request) -> - if window.innerWidth < 3 or window.innerHeight < 3 - # This frame is too small to focus. Cancel and tell the background frame to focus the next one instead. - # This affects sites like Google Inbox, which have many tiny iframes. See #1317. - # Here we're assuming that there is at least one frame large enough to focus. - chrome.runtime.sendMessage({ handler: "nextFrame", frameId: frameId }) - return + unless request.forceFocusThisFrame + if window.innerWidth < 3 or window.innerHeight < 3 or document.body?.tagName.toLowerCase() == "frameset" + # This frame is too small to focus or its a frameset. Cancel and tell the background page to focus the + # next frame instead. This affects sites like Google Inbox, which have many tiny iframes. See 1317. + chrome.runtime.sendMessage handler: "nextFrame", frameId: frameId + return window.focus() flashFrame() if request.highlight @@ -317,7 +305,7 @@ extend window, goToRoot: -> window.location.href = window.location.origin - mainFrame: -> focusThisFrame highlight: true + mainFrame: -> focusThisFrame highlight: true, forceFocusThisFrame: true toggleViewSource: -> chrome.runtime.sendMessage { handler: "getCurrentTabUrl" }, (url) -> @@ -662,8 +650,6 @@ window.HelpDialog ?= initializePreDomReady() DomUtils.documentReady initializeOnDomReady -DomUtils.documentReady registerFrame -window.addEventListener "unload", unregisterFrame root = exports ? window root.handlerStack = handlerStack -- cgit v1.2.3 From 8be6acd660be212926bff495c8e8f83d3f5917be Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Mon, 14 Mar 2016 11:42:27 +0000 Subject: Use Chrome frameIds. --- content_scripts/vimium_frontend.coffee | 37 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index c948f843..ce01695a 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -30,10 +30,8 @@ textInputXPath = (-> DomUtils.makeXPath(inputElements) )() -# -# Give this frame a unique (non-zero) id. -# -frameId = 1 + Math.floor(Math.random()*999999999) +# This is set by Frame.registerFrameId(). A frameId of 0 indicates that this is the top frame in the tab. +frameId = null # For debugging only. This logs to the console on the background page. bgLog = (args...) -> @@ -170,7 +168,7 @@ initializePreDomReady = -> # Wrapper to install event listeners. Syntactic sugar. installListener = (element, event, callback) -> element.addEventListener(event, -> - if isEnabledForUrl then callback.apply(this, arguments) else true + if isEnabledForUrl and frameId? then callback.apply(this, arguments) else true , true) # @@ -209,18 +207,20 @@ onFocus = (event) -> window.addEventListener "focus", onFocus window.addEventListener "hashchange", onFocus -# -# Initialization tasks that must wait for the document to be ready. -# -initializeOnDomReady = -> - # Tell the background page we're in the dom ready state. - port = chrome.runtime.connect name: "domReady" - port.postMessage handler: "registerFrame", frameId: frameId, isTopFrame: DomUtils.isTopFrame() - port.onDisconnect.addListener -> - # We disable content scripts when we lose contact with the background page. - isEnabledForUrl = false - chrome.runtime.sendMessage = -> - window.removeEventListener "focus", onFocus +Frame = + port: null + + init: -> + # Tell the background page we're in the domReady state. + @port = chrome.runtime.connect name: "domReady" + @port.onMessage.addListener (request) => this[request.name] request + @port.onDisconnect.addListener -> + # We disable content scripts when we lose contact with the background page. + isEnabledForUrl = false + chrome.runtime.sendMessage = -> + window.removeEventListener "focus", onFocus + + registerFrameId: ({chromeFrameId}) -> frameId = window.frameId = chromeFrameId handleShowHUDforDuration = ({ text, duration }) -> if DomUtils.isTopFrame() @@ -649,10 +649,11 @@ window.HelpDialog ?= if @showing then @hide() else @show html initializePreDomReady() -DomUtils.documentReady initializeOnDomReady +DomUtils.documentReady Frame.init.bind Frame root = exports ? window root.handlerStack = handlerStack root.frameId = frameId +root.Frame = Frame root.windowIsFocused = windowIsFocused root.bgLog = bgLog -- cgit v1.2.3 From 4009213f0dbe1326263535e0a50a165d179ae47d Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Tue, 15 Mar 2016 12:38:39 +0000 Subject: Open frames port pre documentReady. The intention is to move checkIfEnabledForUrl to the frames port. That needs to run pre domReady, so first -- here -- we separate the two ports. --- content_scripts/vimium_frontend.coffee | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index ce01695a..4b461847 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -136,6 +136,7 @@ window.initializeModes = -> # Complete initialization work that sould be done prior to DOMReady. # initializePreDomReady = -> + Frame.init() checkIfEnabledForUrl() requestHandlers = @@ -207,18 +208,20 @@ onFocus = (event) -> window.addEventListener "focus", onFocus window.addEventListener "hashchange", onFocus +DomUtils.documentReady -> + # Tell the background page we're in the domReady state. + chrome.runtime.connect({name: "domReady"}).onDisconnect.addListener -> + # We disable content scripts when we lose contact with the background page. + isEnabledForUrl = false + chrome.runtime.sendMessage = -> + window.removeEventListener "focus", onFocus + Frame = port: null init: -> - # Tell the background page we're in the domReady state. - @port = chrome.runtime.connect name: "domReady" + @port = chrome.runtime.connect name: "frames" @port.onMessage.addListener (request) => this[request.name] request - @port.onDisconnect.addListener -> - # We disable content scripts when we lose contact with the background page. - isEnabledForUrl = false - chrome.runtime.sendMessage = -> - window.removeEventListener "focus", onFocus registerFrameId: ({chromeFrameId}) -> frameId = window.frameId = chromeFrameId @@ -649,7 +652,6 @@ window.HelpDialog ?= if @showing then @hide() else @show html initializePreDomReady() -DomUtils.documentReady Frame.init.bind Frame root = exports ? window root.handlerStack = handlerStack -- cgit v1.2.3 From f504fd305e5b2c16b2053a76090ea2618ab42332 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Tue, 15 Mar 2016 15:04:10 +0000 Subject: Move isEnabledForUrl to Frame.port. --- content_scripts/vimium_frontend.coffee | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 4b461847..49187e4a 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -218,12 +218,18 @@ DomUtils.documentReady -> Frame = port: null + listeners: {} - init: -> + addEventListener: (handler, callback) -> (@listeners[handler] ?= []).push callback + postMessage: (handler, request = {}) -> @port.postMessage extend request, {handler} + registerFrameId: ({chromeFrameId}) -> frameId = window.frameId = chromeFrameId + + init: (callback) -> @port = chrome.runtime.connect name: "frames" - @port.onMessage.addListener (request) => this[request.name] request + @port.onMessage.addListener (request) => + handler request for handler in @listeners[request.handler] - registerFrameId: ({chromeFrameId}) -> frameId = window.frameId = chromeFrameId + @addEventListener "registerFrameId", Frame.registerFrameId handleShowHUDforDuration = ({ text, duration }) -> if DomUtils.isTopFrame() @@ -442,10 +448,9 @@ initializeTopFrame = (request = null) -> # Checks if Vimium should be enabled or not in this frame. As a side effect, it also informs the background # page whether this frame has the focus, allowing the background page to track the active frame's URL. -checkIfEnabledForUrl = (frameIsFocused = windowIsFocused()) -> - url = window.location.toString() - chrome.runtime.sendMessage { handler: "isEnabledForUrl", url: url, frameIsFocused: frameIsFocused }, (response) -> - { isEnabledForUrl, passKeys } = response +checkIfEnabledForUrl = do -> + Frame.addEventListener "isEnabledForUrl", (response) -> + {isEnabledForUrl, passKeys, frameIsFocused} = response installListeners() # But only if they have not been installed already. # Initialize UI components. We only initialize these once we know that Vimium is enabled; see #1838. if isEnabledForUrl @@ -456,14 +461,16 @@ checkIfEnabledForUrl = (frameIsFocused = windowIsFocused()) -> HUD.hide() normalMode?.setPassKeys passKeys # Update the page icon, if necessary. - if windowIsFocused() + if frameIsFocused chrome.runtime.sendMessage handler: "setIcon" icon: if isEnabledForUrl and not passKeys then "enabled" else if isEnabledForUrl then "partial" else "disabled" - null + + (frameIsFocused = windowIsFocused()) -> + Frame.postMessage "isEnabledForUrl", {frameIsFocused, url: window.location.toString()} # When we're informed by the background page that a URL in this tab has changed, we check if we have the # correct enabled state (but only if this frame has the focus). -- cgit v1.2.3 From 309704eba6673360c8b29a103bc2c76244e82b08 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Tue, 15 Mar 2016 15:51:52 +0000 Subject: No need to block until `frameId?`. Now that we've moved Frame.init() back to before checkIfEnabledForUrl, there's no longer a need to check that frameId has been initialised. It must have been. --- content_scripts/vimium_frontend.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 49187e4a..c8a0f2c2 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -169,7 +169,7 @@ initializePreDomReady = -> # Wrapper to install event listeners. Syntactic sugar. installListener = (element, event, callback) -> element.addEventListener(event, -> - if isEnabledForUrl and frameId? then callback.apply(this, arguments) else true + if isEnabledForUrl then callback.apply(this, arguments) else true , true) # -- cgit v1.2.3 From e19ff7a58ec97de3524a6eb32d5f6e0f57696354 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Tue, 15 Mar 2016 16:02:40 +0000 Subject: Tweaks. --- content_scripts/vimium_frontend.coffee | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index c8a0f2c2..70ff19f5 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -225,12 +225,12 @@ Frame = registerFrameId: ({chromeFrameId}) -> frameId = window.frameId = chromeFrameId init: (callback) -> + @addEventListener "registerFrameId", Frame.registerFrameId @port = chrome.runtime.connect name: "frames" + @port.onDisconnect.addListener => @port.postMessage = -> @port.onMessage.addListener (request) => handler request for handler in @listeners[request.handler] - @addEventListener "registerFrameId", Frame.registerFrameId - handleShowHUDforDuration = ({ text, duration }) -> if DomUtils.isTopFrame() DomUtils.documentReady -> HUD.showForDuration text, duration @@ -270,7 +270,7 @@ DomUtils.documentReady -> focusThisFrame = (request) -> unless request.forceFocusThisFrame if window.innerWidth < 3 or window.innerHeight < 3 or document.body?.tagName.toLowerCase() == "frameset" - # This frame is too small to focus or its a frameset. Cancel and tell the background page to focus the + # This frame is too small to focus or it's a frameset. Cancel and tell the background page to focus the # next frame instead. This affects sites like Google Inbox, which have many tiny iframes. See 1317. chrome.runtime.sendMessage handler: "nextFrame", frameId: frameId return @@ -477,7 +477,6 @@ checkIfEnabledForUrl = do -> checkEnabledAfterURLChange = -> checkIfEnabledForUrl() if windowIsFocused() - window.handleEscapeForFindMode = -> document.body.classList.remove("vimiumFindMode") # removing the class does not re-color existing selections. we recreate the current selection so it reverts -- cgit v1.2.3 From d6f8e7301ed43a64df77e9bfa0ef9dd7a263faeb Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 16 Mar 2016 15:02:25 +0000 Subject: Simplify domReady handling. --- content_scripts/vimium_frontend.coffee | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 70ff19f5..36ca7834 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -1,8 +1,5 @@ # -# This content script takes input from its webpage and executes commands locally on behalf of the background -# page. It must be run prior to domReady so that we perform some operations very early. We tell the -# background page that we're in domReady and ready to accept normal commands by connectiong to a port named -# "domReady". +# This content script must be run prior to domReady so that we perform some operations very early. # isEnabledForUrl = true @@ -208,13 +205,9 @@ onFocus = (event) -> window.addEventListener "focus", onFocus window.addEventListener "hashchange", onFocus -DomUtils.documentReady -> +initializeOnDomReady = -> # Tell the background page we're in the domReady state. - chrome.runtime.connect({name: "domReady"}).onDisconnect.addListener -> - # We disable content scripts when we lose contact with the background page. - isEnabledForUrl = false - chrome.runtime.sendMessage = -> - window.removeEventListener "focus", onFocus + Frame.postMessage "domReady" Frame = port: null @@ -227,10 +220,17 @@ Frame = init: (callback) -> @addEventListener "registerFrameId", Frame.registerFrameId @port = chrome.runtime.connect name: "frames" - @port.onDisconnect.addListener => @port.postMessage = -> + @port.onMessage.addListener (request) => handler request for handler in @listeners[request.handler] + @port.onDisconnect.addListener => + # We disable content scripts when we lose contact with the background page. + isEnabledForUrl = false + chrome.runtime.sendMessage = -> + window.removeEventListener "focus", onFocus + @port.postMessage = -> + handleShowHUDforDuration = ({ text, duration }) -> if DomUtils.isTopFrame() DomUtils.documentReady -> HUD.showForDuration text, duration @@ -658,6 +658,7 @@ window.HelpDialog ?= if @showing then @hide() else @show html initializePreDomReady() +DomUtils.documentReady initializeOnDomReady root = exports ? window root.handlerStack = handlerStack -- cgit v1.2.3 From 16b150c108f72cc7b3e33c6fa46bd5c2d06c71c8 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 17 Mar 2016 12:35:33 +0000 Subject: Tweaks for #2053. --- content_scripts/vimium_frontend.coffee | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 36ca7834..a538e46e 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -1,5 +1,5 @@ # -# This content script must be run prior to domReady so that we perform some operations very early. +# This content script must be run prior to domReady so that we perform some operations very early. # isEnabledForUrl = true @@ -224,12 +224,10 @@ Frame = @port.onMessage.addListener (request) => handler request for handler in @listeners[request.handler] - @port.onDisconnect.addListener => - # We disable content scripts when we lose contact with the background page. + @port.onDisconnect.addListener -> + # We disable the content scripts when we lose contact with the background page. isEnabledForUrl = false - chrome.runtime.sendMessage = -> window.removeEventListener "focus", onFocus - @port.postMessage = -> handleShowHUDforDuration = ({ text, duration }) -> if DomUtils.isTopFrame() @@ -271,7 +269,7 @@ focusThisFrame = (request) -> unless request.forceFocusThisFrame if window.innerWidth < 3 or window.innerHeight < 3 or document.body?.tagName.toLowerCase() == "frameset" # This frame is too small to focus or it's a frameset. Cancel and tell the background page to focus the - # next frame instead. This affects sites like Google Inbox, which have many tiny iframes. See 1317. + # next frame instead. This affects sites like Google Inbox, which have many tiny iframes. See #1317. chrome.runtime.sendMessage handler: "nextFrame", frameId: frameId return window.focus() -- cgit v1.2.3 From e1aee8b4867e3d315d799ba06ba46fa7d7077c0c Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 17 Mar 2016 12:54:44 +0000 Subject: More tweaks for #2053. --- content_scripts/vimium_frontend.coffee | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index a538e46e..13d1377d 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -213,16 +213,15 @@ Frame = port: null listeners: {} - addEventListener: (handler, callback) -> (@listeners[handler] ?= []).push callback + addEventListener: (handler, callback) -> @listeners[handler] = callback postMessage: (handler, request = {}) -> @port.postMessage extend request, {handler} registerFrameId: ({chromeFrameId}) -> frameId = window.frameId = chromeFrameId init: (callback) -> - @addEventListener "registerFrameId", Frame.registerFrameId @port = chrome.runtime.connect name: "frames" @port.onMessage.addListener (request) => - handler request for handler in @listeners[request.handler] + (@listeners[request.handler] ? this[request.handler]) request @port.onDisconnect.addListener -> # We disable the content scripts when we lose contact with the background page. @@ -459,7 +458,7 @@ checkIfEnabledForUrl = do -> HUD.hide() normalMode?.setPassKeys passKeys # Update the page icon, if necessary. - if frameIsFocused + if windowIsFocused() chrome.runtime.sendMessage handler: "setIcon" icon: -- cgit v1.2.3