Skip to content
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

Merged
merged 27 commits into from Feb 27, 2019

Conversation

zombifier
Copy link
Contributor

@zombifier zombifier commented Jan 22, 2019

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.

…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.
@zombifier
Copy link
Contributor Author

zombifier commented Jan 22, 2019

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.

@zombifier zombifier changed the title [WIP] Make inabox-viewport measure the top level window directly if same domain Make inabox-viewport measure the top level window directly if same domain Jan 29, 2019
@zombifier zombifier changed the title Make inabox-viewport measure the top level window directly if same domain [WIP] Make inabox-viewport measure the top level window directly if same domain Jan 29, 2019
This makes the code cleaner and changes in the future easier
@jeffkaufman
Copy link
Contributor

@zombifier is this ready for review or still WIP?

@zombifier
Copy link
Contributor Author

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.
@zombifier
Copy link
Contributor Author

@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 Show resolved Hide resolved
} catch (unusedErr) { // eslint-disable-line no-unused-vars
return false;
}
}
Copy link
Contributor

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?

Copy link
Contributor Author

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.

dev().fine(TAG, 'initialized inabox viewport');
}

/** @override */
connect() {
this.listenForPosition_();
if (this.canInspectTopWindow_()) {
Copy link
Contributor

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.

Copy link
Contributor Author

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()));
});
}
Copy link
Contributor

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?

Copy link
Contributor Author

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',
Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link
Contributor

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.

@zombifier zombifier changed the title [WIP] Make inabox-viewport measure the top level window directly if same domain Make inabox-viewport measure the top level window directly if same domain Feb 4, 2019
@zombifier
Copy link
Contributor Author

Cc @lannka, please take a look.

* @param {!../layout-rect.LayoutRectDef} viewportRect
* @param {!../layout-rect.LayoutRectDef} targetRect
*/
updateLayoutRects_(viewportRect, targetRect) {
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

this.fireScrollThrottle_();
}
/** @visibleForTesting */
setUpNativeListener() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

});
}

/** @private */
listenForPositionSameDomain_() {
this.setUpNativeListener();
Copy link
Contributor

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?

Copy link
Contributor Author

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).
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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),
Copy link
Contributor

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

Copy link
Contributor Author

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.

@jeffkaufman
Copy link
Contributor

@zombifier is this ready to go in? If not, who is it blocked on?

@lannka
Copy link
Contributor

lannka commented Feb 13, 2019

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.

@jeffkaufman
Copy link
Contributor

@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!

@lannka
Copy link
Contributor

lannka commented Feb 26, 2019

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?

@lannka
Copy link
Contributor

lannka commented Feb 27, 2019

Thanks! Is it good to go? I can help merge.

Created #21149 for the TODO

@zombifier
Copy link
Contributor Author

You can merge it. Thanks.

@lannka lannka merged commit 9397b59 into ampproject:master Feb 27, 2019
noranazmy pushed a commit to noranazmy/amphtml that referenced this pull request Mar 22, 2019
…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.
bramanudom pushed a commit to bramanudom/amphtml that referenced this pull request Mar 22, 2019
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants