New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make inabox-viewport measure the top level window directly if same domain #20459
Conversation
…main Instead of sending a post message, if the inabox iframe can directly measure the host window then have it get its position directly from there.
TODO: Integration tests. I believe selectively reenabling some inabox tests added in #20154 on Safari (in particular, friendly iframe without the host script) would be a good indicator. Also if #10877 is resolved I can also piggy back off it with an amp-position-observer in FIE without host script test. |
Checking if the serve mode of the example AMP test is changed somehow
This makes the code cleaner and changes in the future easier
@zombifier is this ready for review or still WIP? |
Still sorting out some things, will notify you if ready for review. |
I believe that the while the integration tests do test the inabox host script, they're are not actually testing the local AMP inabox run time. This might have to be fixed in a separate PR.
@jeffkaufman this is ready for review, but it likely won't go in until #20599 is merged since that PR changes the position observer that this one uses. The integration tests are not ready yet though (see the comment on the latest commit to this branch). |
src/inabox/inabox-viewport.js
Outdated
} catch (unusedErr) { // eslint-disable-line no-unused-vars | ||
return false; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is copied from inabox-messaging-host.js
: can we share the code instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved the function into src/iframe-helper.js
, since that seems to be the most logical location.
src/inabox/inabox-viewport.js
Outdated
dev().fine(TAG, 'initialized inabox viewport'); | ||
} | ||
|
||
/** @override */ | ||
connect() { | ||
this.listenForPosition_(); | ||
if (this.canInspectTopWindow_()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's gate this new behavior on an experiment so we can test it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Will create an issue for cleaning up later.
resolve(layoutRectFromDomRect( | ||
this.win.frameElement./*OK*/getBoundingClientRect())); | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be gated by the experiment too, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -424,6 +424,13 @@ const EXPERIMENTS = [ | |||
spec: 'https://github.com/ampproject/amphtml/issues/20395', | |||
cleanupIssue: 'https://github.com/ampproject/amphtml/issues/20394', | |||
}, | |||
{ | |||
id: 'inabox-viewport-friendly', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we want to run experiments on driven by the ad server, you'll need to add this to allow-doc-opt-in
in prod-config.json
and canary-config.json
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Can this be done in the same PR? Since config changes are supposed to be separate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a problem to add it later. It's just a thing you'll need to add before you can start running experiments.
Cc @lannka, please take a look. |
src/inabox/inabox-viewport.js
Outdated
* @param {!../layout-rect.LayoutRectDef} viewportRect | ||
* @param {!../layout-rect.LayoutRectDef} targetRect | ||
*/ | ||
updateLayoutRects_(viewportRect, targetRect) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
coding style nit: move this method down below where it;'s been called
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/inabox/inabox-viewport.js
Outdated
this.fireScrollThrottle_(); | ||
} | ||
/** @visibleForTesting */ | ||
setUpNativeListener() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/inabox/inabox-viewport.js
Outdated
}); | ||
} | ||
|
||
/** @private */ | ||
listenForPositionSameDomain_() { | ||
this.setUpNativeListener(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this method be inlined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
setUpNativeListener() { | ||
// Set up listener but only after the resources service is properly | ||
// registered (since it's registered after the inabox services so it won't | ||
// be available immediately). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
didn't quite understand why this is needed? Is there a race condition you try to avoid? Can you explain?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The inabox-viewport requires the Resources service to remeasure child elements. It's registered after the viewport service is set up, so when we setup the native listener it will try to call getChildResources() immediately and will throw since it can't find the service. I did manual testing within a browser; without this guard the console will be swarmed by thrown errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might missed something, but my intuition is that a native listener should not need anything particular from resource service, because the parent window is not even AMP. is that a wrong dependency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Resources service comes from the AMP Inabox window itself.
Though I admit that I haven't looked very deep into what it actually does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you dig deep into it? I'm afraid something is wrong here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I think the Resource service is responsible for positioning and sizing the child elements within an AMP document. As part of its regular flow the inabox viewport calls remeasureAllElements_() when the iframe size/scroll changes, which triggers this service.
In the cross domain case the postMessage from the host window usually comes back after the Resources service is set up, but in the same domain case added by this PR the listener is set up and updates positioning immediately, which will happen before the Resources service is installed due to their order of install in amp-inabox.js. If I'm correct then this race condition has always existed within the cross domain case.
.then(() => { | ||
this.topWindowPositionObserver_ = new PositionObserver(this.win.top); | ||
this.topWindowPositionObserver_.observe( | ||
/** @type {!HTMLIFrameElement} */(this.win.frameElement), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shall we sanity check that win.top is win.parent? otherwise I don't know if the positionObserver still works as intended.
/cc @zhouyx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that the inabox iframe does not have to necessarily be the direct child of the top level window? #20599 was created specifically to handle situations where this is not the case.
@zombifier is this ready to go in? If not, who is it blocked on? |
hi @jeffkaufman , had a chat with @zombifier offline that I suspect there is a bad dependency in the current inabox implementation as I don't think there is a need for the native event listener to depend on the resourceService. I plan to take a look sometime this week. Let let me know if it's blocking anything. We can certainly get this in and fix it later. |
@lannka thanks! It's blocking our ability to experiment with stopping loading the host script in some cases for performance, but it's not that high a priority. Definitely not as high as amp-mraid! |
woops.. haven't got a chance to look at this yet. @zombifier to not block you any longer, could you add a TODO and assign me as owner? |
…n the listener. Specifically, why is Resources needed.
Thanks! Is it good to go? I can help merge. Created #21149 for the TODO |
You can merge it. Thanks. |
…main (ampproject#20459) * Make inabox-viewport measure the top level window directly if same domain Instead of sending a post message, if the inabox iframe can directly measure the host window then have it get its position directly from there. * fix types * Fix presubmit * Test disconnect function * Fix lint in new test * Try enabling friendly, no host script inabox test on Safari * Trivial fix to rerun Travis * Try the no host script test with the example AMP ad Checking if the serve mode of the example AMP test is changed somehow * don't whitelist the iframe * More work * Fix lint * Fix lint in test * fix oops * Throttle the listeners * Use the existing inabox host observer instead of rewriting a new one This makes the code cleaner and changes in the future easier * fix type issue * Revert the changes to test-amp-inabox.js I believe that the while the integration tests do test the inabox host script, they're are not actually testing the local AMP inabox run time. This might have to be fixed in a separate PR. * Gate the behavior behind experiment, and move canInspectWindow to helper file * Integrate the changes in ampproject#20599, and make sure the position observer is not null. * Inline the function * Fix type * Disconnect observer properly, and add a TODO to investigate a quirk in the listener. Specifically, why is Resources needed.
…main (ampproject#20459) * Make inabox-viewport measure the top level window directly if same domain Instead of sending a post message, if the inabox iframe can directly measure the host window then have it get its position directly from there. * fix types * Fix presubmit * Test disconnect function * Fix lint in new test * Try enabling friendly, no host script inabox test on Safari * Trivial fix to rerun Travis * Try the no host script test with the example AMP ad Checking if the serve mode of the example AMP test is changed somehow * don't whitelist the iframe * More work * Fix lint * Fix lint in test * fix oops * Throttle the listeners * Use the existing inabox host observer instead of rewriting a new one This makes the code cleaner and changes in the future easier * fix type issue * Revert the changes to test-amp-inabox.js I believe that the while the integration tests do test the inabox host script, they're are not actually testing the local AMP inabox run time. This might have to be fixed in a separate PR. * Gate the behavior behind experiment, and move canInspectWindow to helper file * Integrate the changes in ampproject#20599, and make sure the position observer is not null. * Inline the function * Fix type * Disconnect observer properly, and add a TODO to investigate a quirk in the listener. Specifically, why is Resources needed.
Instead of sending a post message to the host script, if the inabox iframe can directly measure the host window then get its position directly by doing so.
Specifically, inabox-viewport will add scroll and resize event listeners on the top level window that will trigger the measurement functions, which is mostly copied over from the inabox host's position observer.
Related issue: #19869
In the future requesting and cancel full overlay can be changed to do the same thing. This is very low priority however.