]> git.gir.st - VimFx.git/commit
Rework "move tab to window" detection logic
authorSimon Lydell <simon.lydell@gmail.com>
Thu, 26 Nov 2015 09:51:41 +0000 (10:51 +0100)
committerSimon Lydell <simon.lydell@gmail.com>
Mon, 30 Nov 2015 12:32:00 +0000 (13:32 +0100)
commitbb70257d9fc917e6aa12947551f33490ca80167e
treebb755564405aec28bab19347b0c5856f1ea5c1e9
parent49afb612f829e303fa9e4ffa6ce8531b98291fd2
Rework "move tab to window" detection logic

The old detection was too unreliable and didn't catch all cases.

Also fixes a bug where the blacklist wasn't applied when going back or forward
in history to a blacklisted URL.

The long story:

If you move a tab into another window in multi-process, the frame script for the
web page of the tab is kept. That is good, since all state (such as scrollable
elements) is preserved.

In non-multi-process, that is not the case. A new frame script is loaded, so all
state is lost. That is unfortunate, but there's nothing we can do about it. In
non-multi-process, moving a tab to another window then works a bit like closing
the tab and opening a new one in the target winow with the same URL: All VimFx
state is lost, including the current mode. The blacklist is applied. However,
the web page content is the same, with DOM modifications and scroll position
preserved. This is not ideal for VimFx, but OK. Non-multi-process will be
dropped from Firefox not too far into the future anyway.

Let's focus on multi-process instead.

That no new frame script is loaded for the "new" (dragged) tab in the target
window has some interesting consequences. For example, `vim` objects for tabs
are created based on a frame script being loaded. Does this mean that no `vim`
object is created for this tab? It depends.

When a new tab is opened, Firefox might load a frame script for `about:blank`.
When the real web page starts loading, a new frame script is loaded.

The above can depend on whether you're moving (dragging) a tab to another
existing window, or moving a tab to an entirely new window (by right-clicking a
tab and choosing “Move to New Window” or dragging a tab and dropping it outside
a tab bar).

If a frame script for `about:blank` _is_ loaded, a `vim` object is created.
However, Firefox then moves over the web page from the old tab, and replaces the
`.messageManager` of the new tab’s `<browser>`! This means that the `vim` object
cannot receive messages from the just-moved-over web page (coming from the frame
script that was kept from the origin window, as mentioned earlier), because it
has attached its listeners to a message manager object that no longer exists.

In both cases it means that VimFx won't work correctly in those tabs. Therefore,
we need to detect tabs moved to other windows.

There does not seem to be any straight-forward way of detecting that, though.
However, we can abuse the fact the `vim` objects for those tabs will either be
missing or have the wrong `._messageManager` as a way of detecting it anyway.
(Since that isn't the case in non-multi-process, that's why we can't detect it
there.)

After having moved a tab to another window, the web page of the tab loads from
cache. This triggers a 'pageshow' event with `event.persisted === true`, just
like when navigating forward and backward in history. When this happens, the
frame scripts send a message to the UI process, which is caught at window level.
If there's no `vim` object for the `<browser>` that the message came from, or if
`vim._messageManager` is out of date, we know that the tab for the `<browser>`
element has just been moved to another window!

In that case, we want to find the `vim` object for the closed tab in the origin
window (the one that we started dragging, for example) and re-use it for the
"new" tab, in order to keep the current mode etc.

That is done be saving the `vim` object of the last closed tab, by listening for
the 'TabClose' event. It fires before the new tab in the target window is
created.

The whole process is very ugly and a bit complicated, but there's seems to be no
other way, and it does the job: Things work acceptably in non-multi-process and
(seemingly) perfectly in multi-process.
extension/lib/events-frame.coffee
extension/lib/events.coffee
extension/lib/vim.coffee
extension/lib/vimfx.coffee
Imprint / Impressum