Skip to content

Commit

Permalink
✨ amp-iframe: allow opaque origins for embed-size events (ampproject#…
Browse files Browse the repository at this point in the history
  • Loading branch information
aghassemi authored Jan 19, 2019
1 parent e52c0ce commit f82803c
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 12 deletions.
5 changes: 4 additions & 1 deletion extensions/amp-iframe/0.1/amp-iframe.js
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,10 @@ export class AmpIframe extends AMP.BaseElement {

listenFor(iframe, 'embed-size', data => {
this.updateSize_(data['height'], data['width']);
});
},
/*opt_is3P*/ undefined,
/*opt_includingNestedWindows*/ undefined,
/*opt_allowOpaqueOrigin*/ true);

if (this.isClickToPlay_) {
listenFor(iframe, 'embed-ready', this.activateIframe_.bind(this));
Expand Down
62 changes: 62 additions & 0 deletions extensions/amp-iframe/0.1/test/test-amp-iframe.js
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,68 @@ describes.realWin('amp-iframe', {
});
});

it('should allow resize events w/o allow-same-origin', function* () {
const ampIframe = createAmpIframe(env, {
src: iframeSrc,
sandbox: 'allow-scripts',
width: 100,
height: 100,
resizable: '',
});
yield waitForAmpIframeLayoutPromise(doc, ampIframe);
const impl = ampIframe.implementation_;
return new Promise((resolve, unusedReject) => {
impl.updateSize_ = (height, width) => {
resolve({height, width});
};
const iframe = ampIframe.querySelector('iframe');
iframe.contentWindow.postMessage({
sentinel: 'amp-test',
type: 'requestHeight',
height: 217,
width: 113,
}, '*');
}).then(res => {
expect(res.height).to.equal(217);
expect(res.width).to.equal(113);
});
});

it('should allow resize events w/ srcdoc', function* () {
const srcdoc = `
<!doctype html>>
<html>
<body>
<script>
window.parent.postMessage({
sentinel: 'amp',
type: 'embed-size',
height: 200,
width: 300,
}, '*');
</script>
</body>
</html>
`;
const ampIframe = createAmpIframe(env, {
srcdoc,
sandbox: 'allow-scripts',
width: 100,
height: 100,
resizable: '',
});
yield waitForAmpIframeLayoutPromise(doc, ampIframe);
const impl = ampIframe.implementation_;
return new Promise((resolve, unusedReject) => {
impl.updateSize_ = (height, width) => {
resolve({height, width});
};
}).then(res => {
expect(res.height).to.equal(200);
expect(res.width).to.equal(300);
});
});

it('should resize amp-iframe', function* () {
const ampIframe = createAmpIframe(env, {
src: iframeSrc,
Expand Down
38 changes: 27 additions & 11 deletions src/iframe-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ function getListenForSentinel(parentWin, sentinel, opt_create) {
* @return {?Object<string, !Array<function(!JsonObject, !Window, string)>>}
*/
function getOrCreateListenForEvents(parentWin, iframe, opt_is3P) {
const {origin} = parseUrlDeprecated(iframe.src);
const sentinel = getSentinel_(iframe, opt_is3P);
const listenSentinel = getListenForSentinel(parentWin, sentinel, true);

Expand All @@ -100,7 +99,6 @@ function getOrCreateListenForEvents(parentWin, iframe, opt_is3P) {
if (!windowEvents) {
windowEvents = {
frame: iframe,
origin,
events: Object.create(null),
};
listenSentinel.push(windowEvents);
Expand Down Expand Up @@ -133,12 +131,6 @@ function getListenForEvents(parentWin, sentinel, origin, triggerWin) {
const {contentWindow} = we.frame;
if (!contentWindow) {
setTimeout(dropListenSentinel, 0, listenSentinel);
} else if (sentinel === 'amp') {
// A non-3P code path, origin must match.
if (we.origin === origin && contentWindow == triggerWin) {
windowEvents = we;
break;
}
} else if (triggerWin == contentWindow ||
isDescendantWindow(contentWindow, triggerWin)) {
// 3p code path, we may accept messages from nested frames.
Expand Down Expand Up @@ -246,12 +238,20 @@ function registerGlobalListenerIfNeeded(parentWin) {
* @param {?function(!JsonObject, !Window, string)} callback Called when a
* message of this type arrives for this iframe.
* @param {boolean=} opt_is3P set to true if the iframe is 3p.
* @param {boolean=} opt_includingNestedWindows set to true if a messages from
* @param {boolean=} opt_includingNestedWindows set to true if messages from
* nested frames should also be accepted.
* @param {boolean=} opt_allowOpaqueOrigin set to true if messages from
opaque origins (origin == null) are allowed.
* @return {!UnlistenDef}
*/
export function listenFor(
iframe, typeOfMessage, callback, opt_is3P, opt_includingNestedWindows) {
iframe,
typeOfMessage,
callback,
opt_is3P,
opt_includingNestedWindows,
opt_allowOpaqueOrigin) {

devAssert(iframe.src, 'only iframes with src supported');
devAssert(!iframe.parentNode, 'cannot register events on an attached ' +
'iframe. It will cause hair-pulling bugs like #2942');
Expand All @@ -266,12 +266,28 @@ export function listenFor(
opt_is3P
);


const iframeOrigin = parseUrlDeprecated(iframe.src).origin;
let events = listenForEvents[typeOfMessage] ||
(listenForEvents[typeOfMessage] = []);

let unlisten;
let listener = function(data, source, origin) {
const sentinel = data['sentinel'];

// Exclude messages that don't satisfy amp sentinel rules.
if (sentinel == 'amp') {
// For `amp` sentinel, nested windows are not allowed
if (source != iframe.contentWindow) {
return;
}

// For `amp` sentinel origin must match unless opaque origin is allowed
const isOpaqueAndAllowed = origin == 'null' && opt_allowOpaqueOrigin;
if (iframeOrigin != origin && !isOpaqueAndAllowed) {
return;
}
}

// Exclude nested frames if necessary.
// Note that the source was already verified to be either the contentWindow
// of the iframe itself or a descendant window within it.
Expand Down

0 comments on commit f82803c

Please sign in to comment.