Reproduces the Fujitsu Panorama failure: the user exports a named
configuration snapshot, a new tab opens, and it stays a blank white page.
No file is downloaded and /safeview-fileserv/ is never
contacted.
The short version. This test can silently fail to test anything. If the surrogate is not in the right state, every case below passes and it looks like there is no bug. So: set up the four items in the checklist, run the cases, and then prove the bug was armed before you trust any result.
The surrogate sends the client a TAB_open message whose last
value is a flag called defer_initial_nav:
false --- "open a new tab and navigate it yourself, now."
The client does not wait for anybody, so nothing can go wrong.
The bug does not exist in this state.
true --- "open a new tab but leave it blank, I will tell
you where to send it shortly." The surrogate then never follows up,
because a download is not a page load. This is the bug.
You cannot set this flag from a UI. It turns on by itself, in one of two
ways (safeview.cc:3212-3217):
defer_new_tab_nav in its site flags
(safeview_site_config.cc:450-452) --- needs a policy
change; or
remain_isolate, or a non-empty switch_access
such as proxy access). Safeview::SetStickyPolicy
(safeview.cc:7602-7622) then latches
use_surrogate_led_new_tab() on for the entire surrogate
process, for every tab, and never resets it.
Route 2 is what happened in the field capture, which was
access=proxy. So the flag is not something you configure ---
it is something you verify.
Then run case 5 first as a smoke test. If a new tab does not open and render "This is basic1 page.", the environment is wrong and nothing else you observe means anything.
Do this after the run, from the client side --- it needs no surrogate access. In DevTools on this tab: Network, right-click, Save all as HAR with content. Then:
python3 check_defer_flag.py <your-run>.har
It prints every TAB_open with a verdict. TRUE
means a blank tab in cases 1-3 is a genuine reproduction;
false means the run proved nothing and you need proxy access
or the defer_new_tab_nav site flag. What you are looking for
in the raw frame is the trailing value:
["TAB_open",<N>,"<.../panorama_config_export.php?name=running-config.xml>",false,"",false,true]
^^^^
defer_initial_nav
If you do have surrogate log access, the equivalent check is the
def: field, which the TabOpen serializer prints
only when the flag is true (safeview_tc_cmds.cc:173-175):
surrogate-tab-request .* cmd=.*def:
The capture contains a DOM run and a pixel run with byte-identical
TAB_open payloads. Run every case twice, switching with
Ctrl+Alt+Shift+1 (DOM / r1) and Ctrl+Alt+Shift+2
(pixel / ACR2), each of which reloads the page. There is no r1/r2 branch
anywhere between Safeview::AddNewContents and the commit gate,
so any difference in outcome between the two modes is a finding worth
chasing.
This is what Panorama's export button does, and it matches the capture
exactly. The click keeps transient activation, so the surrogate reports
is_popup=false, the client takes the no-modal path and answers
["allow-tab-open",true,false,N] --- prompted=false,
no popup dialog.
Expected failure: a new tab opens and stays blank
white forever. No download, no download modal, no scan. The tab is never
released --- it leaks until you close it by hand, at which point the client
poller (tab.js:482-499) sends
["tab_close",N]. Between the open and your manual close the
WebSocket carries nothing but anim_ping/anim_pong.
running-config-blank.xml (target=_blank)
Same destination, reached by a link click, which goes through
tabPreOpen() (tab.js:358, called from
local-events.js:1317).
Note what that function actually does: it returns early, opening
nothing, whenever window.navigator.userActivation
exists. Chrome has it --- including the customer's Chrome 150 --- so on
Chrome this case converges onto the very same
Util.windowOpen('', '', ...) branch of
tabOpenAction as case 1, and is a duplicate. The
pre_open_windows.shift() branch is only reached on browsers
without userActivation, i.e. Safari and IE. Run this case
there if you want coverage of that branch; on Chrome, running it only
confirms the two entry points agree.
Expected failure: identical to case 1 --- blank tab, no download. On Safari, a difference from case 1 would mean the pre-open branch matters and the fix has to cover both.
The button counts down and then opens the tab. Do not click anywhere while it counts --- any click restarts the activation window and turns this back into case 1.
The wait has to exceed 5 seconds, because that is how long
Chrome keeps transient activation alive after a click. An earlier version
of this page used setTimeout(..., 0) and a real run showed it
still produced is_popup=false --- it was silently a duplicate
of case 1. Past the window the activation is genuinely gone, the surrogate
reports is_popup=true, and the client shows the popup-open
modal, answering ["allow-tab-open",true,true,N] with
prompted=true. Check the frame if in doubt: the 3rd value is
is_popup and it must be true for this case to be
doing its job.
Expected failure: popup modal, then --- after you
allow it --- the same blank tab. Included to keep the two routes apart:
this is not the reported case (the capture shows
prompted=false on all three attempts), so do not use it to
judge a fix for the reported case. It should be fixed by the same change,
but a fix that only repairs this path has not repaired the customer's.
Expected pass: the download modal appears, the
file is scanned, and running-config-same-tab.xml arrives.
This proves the PHP response, the download pipeline and
/safeview-fileserv/ are all healthy --- the attachment is not
the problem on its own. Navigating this tab away also fires
letChildrenGo() (history.js:349), so run it in a
fresh page load rather than after case 1 or 2, or it will release their
orphan tab and muddy the result.
Expected pass: the new tab pairs and renders
"This is basic1 page." Same TAB_open with
defer_initial_nav=true, but the navigation commits, so
SetClientLocation runs and client_loc with
action:"initial" is sent to the opener, which drives the child
tab. This proves deferred new-tab navigation itself works.
Cases 4 and 5 bracket the defect: download without a new tab passes, new tab without a download passes, and only case 1 --- both at once --- fails.
Client side, in the WebSocket frames for the opener tab, the whole failure signature is four messages and a gap:
S->C ["TAB_open",N,"<export url>",false,"",false,true]
C->S ["allow-tab-open",true,false,N]
C->S ["hide-tab"]
... only anim_ping / anim_pong ...
C->S ["tab_close",N] (only when you close it by hand)
Plus a negative check: zero requests to
/safeview-fileserv/, and no WebSocket ever opening with
tab_id=N.
Surrogate side, in order --- the last line is the one that must be absent:
surrogate-tab-request .* def: # deferred open, new tab N
surrogate-allow-tab-open .* new_tab=N
surrogate-policy-check-result # PE ran for the export URL
surrogate-nav-not-committed .* is_download=t # tab=N, the gate closes here
surrogate-download-requested # tab=N (the orphan), not the opener
surrogate-nav-bar-update # ABSENT for tab=N
surrogate-lost-navigator # ABSENT (distinguishes this from
# an opener-closed-early race)