Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/service/viewer-impl.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,19 @@ export class Viewer {
this.performanceTracking_ = this.params_['csi'] === '1';
dev().fine(TAG_, '- performanceTracking:', this.performanceTracking_);

/**
* Whether the AMP document is embedded in a webview.
* @private @const {boolean}
*/
this.isWebviewEmbedded_ = !this.isIframed_ &&
this.params_['webview'] == '1';

/**
* Whether the AMP document is embedded in a viewer, such as an iframe or
* a web view.
* @private @const {boolean}
*/
this.isEmbedded_ = (this.isIframed_ || this.params_['webview'] === '1') &&
this.isEmbedded_ = (this.isIframed_ || this.isWebviewEmbedded_) &&
!this.win.AMP_TEST_IFRAME;

/** @private {boolean} */
Expand Down Expand Up @@ -293,7 +300,7 @@ export class Viewer {
// Not embedded in IFrame - can't trust the viewer.
trustedViewerResolved = false;
trustedViewerPromise = Promise.resolve(false);
} else if (this.win.location.ancestorOrigins) {
} else if (this.win.location.ancestorOrigins && !this.isWebviewEmbedded_) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we also check that the document is NOT currently iframed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That's a great case. I've added this to the #isWebviewEmbeded boolean, and added tests.

// Ancestors when available take precedence. This is the main API used
// for this determination. Fallback is only done when this API is not
// supported by the browser.
Expand Down
117 changes: 117 additions & 0 deletions test/functional/test-viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,123 @@ describe('Viewer', () => {
});
});

describe('when in webview', () => {
it('should decide trusted on connection with origin', () => {
windowApi.parent = windowApi;
windowApi.location.hash = '#webview=1';
windowApi.location.ancestorOrigins = [];
const viewer = new Viewer(ampdoc);
viewer.setMessageDeliverer(() => {}, 'https://google.com');
return viewer.isTrustedViewer().then(res => {
expect(res).to.be.true;
});
});

it('should NOT allow channel without origin', () => {
windowApi.parent = windowApi;
windowApi.location.hash = '#webview=1';
windowApi.location.ancestorOrigins = [];
const viewer = new Viewer(ampdoc);
expect(() => {
viewer.setMessageDeliverer(() => {});
}).to.throw(/message channel must have an origin/);
});

it('should decide non-trusted on connection with wrong origin', () => {
windowApi.parent = windowApi;
windowApi.location.hash = '#webview=1';
windowApi.location.ancestorOrigins = [];
const viewer = new Viewer(ampdoc);
viewer.setMessageDeliverer(() => {}, 'https://untrusted.com');
return viewer.isTrustedViewer().then(res => {
expect(res).to.be.false;
});
});

it('should NOT give precedence to ancestor', () => {
windowApi.parent = windowApi;
windowApi.location.hash = '#webview=1';
windowApi.location.ancestorOrigins = ['https://google.com'];
const viewer = new Viewer(ampdoc);
viewer.setMessageDeliverer(() => {}, 'https://untrusted.com');
return viewer.isTrustedViewer().then(res => {
expect(res).to.be.false;
});
});
});

describe('when in a fake webview (a bad actor iframe)', () => {
it('should consider trusted by ancestor', () => {
windowApi.parent = {};
windowApi.location.hash = '#webview=1';
windowApi.location.ancestorOrigins = ['https://google.com'];
return new Viewer(ampdoc).isTrustedViewer().then(res => {
expect(res).to.be.true;
});
});

it('should consider non-trusted without ancestor', () => {
windowApi.parent = {};
windowApi.location.hash = '#webview=1';
windowApi.location.ancestorOrigins = [];
return new Viewer(ampdoc).isTrustedViewer().then(res => {
expect(res).to.be.false;
});
});

it('should consider non-trusted with wrong ancestor', () => {
windowApi.parent = {};
windowApi.location.hash = '#webview=1';
windowApi.location.ancestorOrigins = ['https://untrusted.com'];
return new Viewer(ampdoc).isTrustedViewer().then(res => {
expect(res).to.be.false;
});
});

it('should decide trusted on connection with origin', () => {
windowApi.parent = {};
windowApi.location.hash = '#webview=1';
windowApi.location.ancestorOrigins = null;
const viewer = new Viewer(ampdoc);
viewer.setMessageDeliverer(() => {}, 'https://google.com');
return viewer.isTrustedViewer().then(res => {
expect(res).to.be.true;
});
});

it('should NOT allow channel without origin', () => {
windowApi.parent = {};
windowApi.location.hash = '#webview=1';
windowApi.location.ancestorOrigins = null;
const viewer = new Viewer(ampdoc);
expect(() => {
viewer.setMessageDeliverer(() => {});
}).to.throw(/message channel must have an origin/);
});

it('should decide non-trusted on connection with wrong origin', () => {
windowApi.parent = {};
windowApi.location.hash = '#webview=1';
windowApi.location.ancestorOrigins = null;
const viewer = new Viewer(ampdoc);
viewer.setMessageDeliverer(() => {}, 'https://untrusted.com');
return viewer.isTrustedViewer().then(res => {
expect(res).to.be.false;
});
});

it('should give precedence to ancestor', () => {
windowApi.parent = {};
windowApi.location.hash = '#webview=1';
windowApi.location.ancestorOrigins = ['https://google.com'];
const viewer = new Viewer(ampdoc);
viewer.setMessageDeliverer(() => {}, 'https://untrusted.com');
return viewer.isTrustedViewer().then(res => {
expect(res).to.be.true;
});
});
});

it('should trust domain variations', () => {
test('https://google.com', true);
test('https://www.google.com', true);
Expand Down