Closed webcompat-bot closed 4 years ago
Thanks for the report, I was able to reproduce the issue.
Note:
Tested with: Browser / Version: Firefox Preview Nightly 191010(🦎: 71.0a1-20191004094656) Operating System: Huawei P20 Lite (Android 8.0.0) - 1080 x 2280 pixels, 19:9 ratio (~432 ppi density), Samsung Galaxy S7 Edge (Android 8.0.0) - Resolution 1440 x 2560 pixels (~534 ppi pixel density)
Moving to Needsdiagnosis for further investigation.
Confirmed on Firefox Preview (which shows the desktop view crammed into the screen) and Firefox Preview nightly (which shows a zoomed-in desktop view instead).
Unfortuately, the remote debugger is pretty busted while testing with Firefox Preview (nightly or non-nightly), and I had to clear my caches between each attempt, so this one was a royal pain to deal with.
There is a click handler on the close button, but when I set the debugger to pause on click events, the page has already changed over to the desktop version before the click event actually fires.
When I set the debugger to pause instead on all mouse and touch events, that is early enough to catch the problem, but the remote debugger isn't able to actually do anything at that point and just sits there perma-paused like the tab has crashed.
I was able to have it log instead and persist logs and get this output:
13:30:36.149 touchend { target: button.ub-emb-close, isTrusted: true, touches: TouchList, targetTouches: TouchList, changedTouches: TouchList(1), altKey: false, metaKey: false, ctrlKey: false, shiftKey: false, view: Window, … } jquery-1.11.2.min.js:3:5183
13:30:36.157 mousemove { target: button.ub-emb-close, buttons: 0, clientX: 317, clientY: 127, layerX: 7, layerY: 12 } fromEvent.js:17
13:30:36.162 click { target: button.ub-emb-close, buttons: 0, clientX: 317, clientY: 127, layerX: 7, layerY: 12 } preact.mjs:179
13:26:02.619 GET https://casiocdn.com/casio-v2/resource/theme/images/social-icons.svg [HTTP/2.0 200 OK 175ms]
13:30:36.420 click { target: button.ub-emb-close, buttons: 0, clientX: 317, clientY: 127, layerX: -251, layerY: -382 } preact.mjs:179
13:30:36.423 click { target: button.ub-emb-close, buttons: 0, clientX: 317, clientY: 127, layerX: -251, layerY: -382 } 989b00e7def54bfb6f6f5591880b5528.js:70:22034
13:30:36.428 click { target: button.ub-emb-close, buttons: 0, clientX: 317, clientY: 127, layerX: -251, layerY: -382 } gtm.js:752:79
From there I cleared my breakpoints and set new ones on each line above, in an attempt to figure out which one was the step where the desktop version of the page appears and work from there, but I can't actually click the "play" icon after the first breakpoint is triggered in the remote debugger; it just flashes a yellow box for a moment under the play button and nothing happens, and the tab is basically crashed at that point.
And so I cleared my breakpoints and tried again, this time comparing the HTML markup before and after the popup is dismissed (by using copy outer HTML on the html tag each time, then diffing the results). The most pertinent thing that changes is that this meta viewport tag vanishes from their markup:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, shrink-to-fit=no">
And indeed, if I manually add back that meta tag, then the "desktop view" is gone, and we're back to the mobile one as though we have reloaded the page. So maybe that's the problem?
I tried setting a DOM mutation breakpoing on the removal of that node, but it didn't actually manage to break early enough for me to see the line causing the issue (plus the debugger was in a broken state again at that point).
In fact, the debugger just doesn't want to step through breakpoints today, making it impossible to confirm what might be causing the issue. But I did find a few spots where they seem to be removing meta tags, and this one is the one in the main.bundle.js seems to be the culprit (since the others seem to be hit too late, once the tag is already removed):
function o() {
var e = document.getElementById('lp-pom-root'),
t = document.querySelector('meta[name="viewport"]');
if (e && t && 600 < window.innerWidth && window.innerWidth < 1024) {
var n = window.innerWidth,
o = e.offsetWidth,
r = n / o;
t.content = o <= n ? 'initial-scale=1.0, width=device-width, user-scalable=yes' : 'initial-scale=' + r + ', user-scalable=yes'
}
}
Searching through their code, I found this spot where viewport tags seem to possibly be removed in viewportMeta.js:
function remove() {
if (document.head && document.head.querySelectorAll('meta[name="viewport"]').length > 1) {
// If a viewport meta tag already exists, we should revert this change so that the mobile
// browser will fall back to the original meta tag.
meta.removeAttribute('content');
} else {
// If this tag is the only viewport meta tag on the page then we should set the content to
// an empty string so our viewport settings are removed.
meta.setAttribute('content', '');
}
if (document.head) {
document.head.removeChild(meta);
}
}
But breakpoints are again not working, so I had to use logpoints to confirm that the remove
is called from that spot (which it is). Unfortuantely that doesn't really help much, because I don't have a call stack to know where the call is being made from.
Still, in Chrome calls the same code, and the meta tag is removed as well, so I made a reduced test-case to see what's going on, and nope: simply removing the meta tag doesn't seem to be the culprit here. Of course, that is completely at-odds with the fact that re-adding the meta tag "fixes" the problem, so I'm at a loss here.
I fear I'm basically stuck here until the remote debugger starts cooperating with breakpoints.
@karlcow, do you have any ideas?
If you'd like to try re-adding the meta tag yourself, you can run this code remote console after dismissing the popup:
var meta = document.createElement("meta")
meta.setAttribute("name","viewport")
meta.setAttribute("content","width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, shrink-to-fit=no")
document.head.appendChild(meta)
PS: I should also mention that in Fennec, the meta viewport tag does not seem to get removed, though I have not investigated why.
The click is caught by: https://connect.facebook.net/signals/config/286369075303246?v=2.9.6&r=stable
var f = c.target instanceof HTMLElement ? c.target : null;
which is happening on
<div class="ub-emb-scroll-wrapper">
<div class="ub-emb-iframe-wrapper ub-emb-mobile ub-emb-visible" style="height: 338px; width: 320px;">
<button class="ub-emb-close" type="button">×</button>
<iframe class="ub-emb-iframe" src="//1f8e679b9a124392b5b95c0bfea02da9.pages.ubembed.com/283948e4-5572-488c-b21e-60c1e49146ae/a.html?closedAt=0" style="width: 320px !important; height: 338px !important;"></iframe>
</div>
<div class="ub-emb-iframe-wrapper ub-emb-mobile" style="height: 0px; width: 0px;">
<button class="ub-emb-close" type="button">×</button>
<iframe class="ub-emb-iframe" src="" style="width: 0px !important; height: 0px !important;"></iframe>
</div>
</div>
with an impressive z-index
😉
.ub-emb-overlay.ub-emb-visible .ub-emb-backdrop, .ub-emb-overlay.ub-emb-visible .ub-emb-scroll-wrapper {
opacity: 1;
transition: opacity .4s ease;
z-index: 2147483647;
}
then it eventually reaches in https://assets.ubembed.com/universalscript/releases/v0.177.0/bundle.js
function p(e) {
return this._listeners[e.type](O.event && O.event(e) || e)
}
When exiting the p(e), it's when the view switches to desktop. This is reproducible on the RDM view and debugging. Note at this point the meta
for the viewport is still in there.
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, user-scalable=no">
So the viewport is not entirely related I guess.
Removing the cookies and restarting the step by step. This time it switched to desktop view when passing on webpack:///node_modules/preact/dist/preact.mjs
function eventProxy(e) {
return this._listeners[e.type](options.event && options.event(e) || e);
}
which is probably the same thing, but the devtools understood the semantic of the scripts I guess this time. Setting a breakpoint on this return
line instead of the click
and stepping in.
we reach webpack:///src/components/App.jsx
onClose={() => this.handleClose(emb)}
which is part of this chunk of code.
return (
<EmbeddableComponent
// We incorporate the emb's URL into the key so that if changes, for some reason,
// Preact will remove and re-add the Overlay component (including its iframes) to the
// DOM. This would cause the new URL to be preloaded and the state of the Overlay
// component to reset.
key={`${id}-${pageSrc}`}
device={state.device}
emb={emb}
isVisible={visibleEmbOfType === id}
onClose={() => this.handleClose(emb)}
scrollPosition={state.scrollPosition}
size={embPageSize}
viewport={state.viewport}
>
<IframeWrapper
// Main emb content
isMobile={isMobile}
isVisible={!showConfirmation}
size={embPageSizeCss}
hostPageUrl={state.locationHref || global.location.href}
// We append the closedAt time to the src URL so that when the emb is closed, the
// iframe reloads. This prevents embedded videos from continuing to play, but leaves
// the iframe in a loaded state, ready to be triggered again.
src={`${pageSrc}${/\?/.test(pageSrc) ? '&' : '?'}closedAt=${closedAt}`}
onClose={() => this.handleClose(emb)}
onFormConfirmation={(confirmationSize, confirmationSrc) =>
dispatch(actions.embFormConfirmation({id, confirmationSize, confirmationSrc}))}
onFormSubmit={isConversion => dispatch(actions.formSubmitEvent({id, isConversion}))}
onLinkClick={(isConversion, linkUrl = '', shouldRedirect = false) =>
dispatch(actions.linkClickEvent({id, isConversion, linkUrl, shouldRedirect}))}
onLoad={pageSize => dispatch(actions.embLoaded({id, pageSize}))}
/>
<IframeWrapper
// Form confirmation dialog
isMobile={isMobile}
isVisible={showConfirmation}
size={embConfirmationSizeCss}
hostPageUrl={state.locationHref || global.location.href}
src={emb.confirmationSrc}
onClose={() => this.handleClose(emb)}
onFormConfirmation={noop}
onFormSubmit={noop}
onLinkClick={(isConversion, linkUrl = '', shouldRedirect = false) =>
dispatch(actions.linkClickEvent({id, isConversion, linkUrl, shouldRedirect}))}
onLoad={noop}
/>
</EmbeddableComponent>
);
Not there yet but getting close @wisniewskit
Now setting a breakpoint on onClose={() => this.handleClose(emb)}
instead of the previous one.
state.device
Object { isIOS: false, isOldIOS: false, isMobile: true }
After more steps in… a lore more… we reach
webpack:///src/viewportMeta.js
function remove() {
if (document.head && document.head.querySelectorAll('meta[name="viewport"]').length > 1) {
// If a viewport meta tag already exists, we should revert this change so that the mobile
// browser will fall back to the original meta tag.
meta.removeAttribute('content');
} else {
// If this tag is the only viewport meta tag on the page then we should set the content to
// an empty string so our viewport settings are removed.
meta.setAttribute('content', '');
}
if (document.head) {
document.head.removeChild(meta);
}
}
and specifically
if (document.head) {
document.head.removeChild(meta);
}
I'm not sure why but it requires a lot of step-in to just pull out of this if
or is it a racing issue.
then we steps in webpack:///src/handleSideEffects.jsx
viewportMeta.setEnabled(next.device.isMobile && Boolean(next.visibleEmbIds.overlay));
Boolean(next.visibleEmbIds.overlay)
is false
next.device.isMobile
is true
export default {
setEnabled(shouldBeEnabled: boolean): void {
if (shouldBeEnabled && !isPresent()) {
add();
} else if (!shouldBeEnabled && isPresent()) {
remove();
}
},
};
it goes back to remove()
and this time actually change the layout to desktop.
There is an interesting comment in webpack:///src/handleSideEffects.jsx
after viewportMeta.setEnabled(next.device.isMobile && Boolean(next.visibleEmbIds.overlay));
which is
if (showingOverlay && next.device.isIOS) {
// iOS Safari seems to not always fire resize and scroll events after the viewport change that
// appending the above meta tag causes, so we dispatch a quick series of setViewport and
// setScrollPosition actions to ensure the state's viewport and scrollPosition properties are
// up-to-date. This is important because in some cases on iOS, we use those values to position
// the overlay.
timer(0, 100).pipe(
take(4),
mergeMap(() => merge(createViewportChanges(), createCurrentScrollPosition()))
)
.subscribe(dispatch);
}
I wonder if we have a similar case here but because we are not next.device.isIOS
it doesn't go through this.
Let's put a breakpoint on viewportMeta.setEnabled(…)
,
then manually override: next.device.isIOS
and set it to true
. Ah maybe that worked.
Let's change the UA to be iOS.
ah nah changing the UA to be Safari iOS didn't solve it.
@wisniewskit it's all I can do for now.
This is working for me.
I can confirm that.
Tested with: Browser / Version: Firefox Preview Nightly 200526 (🦎 78.0a1-20200522094316) Operating System: Samsung Galaxy S6 Edge (Android 7.0) - 1440 x 2560 pixels (~577 ppi pixel density)
URL: https://www.casio.com/products/watches/dress
Browser / Version: Firefox Mobile 71.0 Operating System: Android Tested Another Browser: No
Problem type: Desktop site instead of mobile site Description: A pop up redirects user to the desktop site whenever they try to exit it. Steps to Reproduce: Opened website, scrolled down until a pop up appeared, tried to tap outside of the bounds to close it, then the desktop version opened.
Browser Configuration
Submitted in the name of
@kolgza
From webcompat.com with ❤️