1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
# Responsive Design Mode Architecture
## Context
You have a single browser tab that has visited several pages, and now has a
history that looks like, in oldest to newest order:
1. https://newsblur.com
2. https://mozilla.org (← current page)
3. https://convolv.es
## Opening RDM During Current Firefox Session
When opening RDM, the browser tab's history must preserved. Additionally, we
strive to preserve the exact state of the currently displayed page (effectively
any in-page state, which is important for single page apps where data can be
lost if they are reloaded).
This seems a bit convoluted, but one advantage of this technique is that it
preserves tab state since the same tab is reused. This helps to maintain any
extra state that may be set on tab by add-ons or others.
1. Create a temporary, hidden tab to load the tool UI.
2. Mark the tool tab browser's docshell as active so the viewport frame is
created eagerly and will be ready to swap.
3. Create the initial viewport inside the tool UI.
4. Swap tab content from the regular browser tab to the browser within the
viewport in the tool UI, preserving all state via
`gBrowser._swapBrowserDocShells`.
5. Force the original browser tab to be non-remote since the tool UI must be
loaded in the parent process, and we're about to swap the tool UI into
this tab.
6. Swap the tool UI (with viewport showing the content) into the original
browser tab and close the temporary tab used to load the tool via
`swapBrowsersAndCloseOther`.
7. Start a tunnel from the tool tab's browser to the viewport browser
so that some browser UI functions, like navigation, are connected to
the content in the viewport, instead of the tool page.
## Closing RDM During Current Firefox Session
To close RDM, we follow a similar process to the one from opening RDM so we can
restore the content back to a normal tab.
1. Stop the tunnel between outer and inner browsers.
2. Create a temporary, hidden tab to hold the content.
3. Mark the content tab browser's docshell as active so the frame is created
eagerly and will be ready to swap.
4. Swap tab content from the browser within the viewport in the tool UI to the
regular browser tab, preserving all state via
`gBrowser._swapBrowserDocShells`.
5. Force the original browser tab to be remote since web content is loaded in
the child process, and we're about to swap the content into this tab.
6. Swap the content into the original browser tab and close the temporary tab
used to hold the content via `swapBrowsersAndCloseOther`.
## Session Restore
When restarting Firefox and restoring a user's browsing session, we must
correctly restore the tab history. If the RDM tool was opened when the session
was captured, then it would be acceptable to either:
* A: Restore the tab content without any RDM tool displayed **OR**
* B: Restore the RDM tool the tab content inside, just as before the restart
We currently follow path A (no RDM after session restore), which seems more in
line with how the rest of DevTools currently functions after restore. To do so,
we watch for `beforeunload` events on the tab at shutdown and quickly exit RDM
so that session restore records only the original page content during its final
write at shutdown.
|