diff --git a/build-system/test-configs/dep-check-config.js b/build-system/test-configs/dep-check-config.js index c4dde1e5efbd..ab5bfcdd9984 100644 --- a/build-system/test-configs/dep-check-config.js +++ b/build-system/test-configs/dep-check-config.js @@ -329,6 +329,8 @@ exports.rules = [ // Parsing extension urls. 'extensions/amp-a4a/0.1/head-validation.js->' + 'src/service/extension-script.js', + 'extensions/amp-a4a/0.1/amp-ad-utils.js->' + + 'src/service/extension-script.js', 'extensions/amp-live-list/0.1/live-list-manager.js->' + 'src/service/extension-script.js', 'extensions/amp-video/0.1/amp-video.js->' + diff --git a/extensions/amp-a4a/0.1/amp-a4a.js b/extensions/amp-a4a/0.1/amp-a4a.js index e0caf4627b4e..ffac128b5467 100644 --- a/extensions/amp-a4a/0.1/amp-a4a.js +++ b/extensions/amp-a4a/0.1/amp-a4a.js @@ -57,12 +57,13 @@ import { } from '../../../src/consent'; import {getContextMetadata} from '../../../src/iframe-attributes'; import {getExperimentBranch, isExperimentOn} from '../../../src/experiments'; +import {getExtensionsFromMetadata} from './amp-ad-utils'; import {getMode} from '../../../src/mode'; import {insertAnalyticsElement} from '../../../src/extension-analytics'; import { installFriendlyIframeEmbed, isSrcdocSupported, - preloadFriendlyIframeEmbedExtensionIdsDeprecated, + preloadFriendlyIframeEmbedExtensions, } from '../../../src/friendly-iframe-embed'; import {installRealTimeConfigServiceForDoc} from '../../../src/service/real-time-config/real-time-config-impl'; import {installUrlReplacementsForEmbed} from '../../../src/service/url-replacements-impl'; @@ -1122,12 +1123,8 @@ export class AmpA4A extends AMP.BaseElement { // Load any extensions; do not wait on their promises as this // is just to prefetch. - // TODO(#33020): switch to `preloadFriendlyIframeEmbedExtensions` with - // the format of `[{extensionId, extensionVersion}]`. - preloadFriendlyIframeEmbedExtensionIdsDeprecated( - this.win, - creativeMetaDataDef.customElementExtensions - ); + const extensions = getExtensionsFromMetadata(creativeMetaDataDef); + preloadFriendlyIframeEmbedExtensions(this.win, extensions); // Preload any fonts. (creativeMetaDataDef.customStylesheets || []).forEach((font) => @@ -1825,13 +1822,9 @@ export class AmpA4A extends AMP.BaseElement { body ); - // TODO(ccordry): FIE does not handle extension versioning, but we have - // it accessible here. - const extensionIds = extensions.map((extension) => extension.extensionId); - const fieInstallPromise = this.installFriendlyIframeEmbed_( secureDoc, - extensionIds, + extensions, fonts, true // skipHtmlMerge ); @@ -1845,6 +1838,7 @@ export class AmpA4A extends AMP.BaseElement { } ); + const extensionIds = extensions.map((extension) => extension.extensionId); return fieInstallPromise.then((friendlyIframeEmbed) => { checkStillCurrent(); this.makeFieVisible_( @@ -1906,10 +1900,11 @@ export class AmpA4A extends AMP.BaseElement { }); } const checkStillCurrent = this.verifyStillCurrent(); - const {minifiedCreative, customElementExtensions} = creativeMetaData; + const {minifiedCreative} = creativeMetaData; + const extensions = getExtensionsFromMetadata(creativeMetaData); return this.installFriendlyIframeEmbed_( minifiedCreative, - customElementExtensions, + extensions, fontsArray || [], false // skipHtmlMerge ).then((friendlyIframeEmbed) => @@ -1924,12 +1919,12 @@ export class AmpA4A extends AMP.BaseElement { /** * Convert the iframe to FIE impl and append to DOM. * @param {string} html - * @param {!Array} extensionIds + * @param {!Array<{extensionId: string, extensionVersion: string}>} extensions * @param {!Array} fonts * @param {boolean} skipHtmlMerge * @return {!Promise} */ - installFriendlyIframeEmbed_(html, extensionIds, fonts, skipHtmlMerge) { + installFriendlyIframeEmbed_(html, extensions, fonts, skipHtmlMerge) { return installFriendlyIframeEmbed( devAssert(this.iframe), this.element, @@ -1938,9 +1933,7 @@ export class AmpA4A extends AMP.BaseElement { // Need to guarantee that this is no longer null url: devAssert(this.adUrl_), html, - // TODO(#33020): provide the `extensions` property instead, in - // the format of `[{extensionId, extensionVersion}]`. - extensionIds, + extensions, fonts, skipHtmlMerge, }, @@ -2263,6 +2256,9 @@ export class AmpA4A extends AMP.BaseElement { } else { metaData.customElementExtensions = []; } + if (metaDataObj['extensions']) { + metaData.extensions = metaDataObj['extensions']; + } if (metaDataObj['customStylesheets']) { // Expect array of objects with at least one key being 'href' whose // value is URL. diff --git a/extensions/amp-a4a/0.1/amp-ad-utils.js b/extensions/amp-a4a/0.1/amp-ad-utils.js index 30a3275c6957..bcd3cf7d7e16 100644 --- a/extensions/amp-a4a/0.1/amp-ad-utils.js +++ b/extensions/amp-a4a/0.1/amp-ad-utils.js @@ -17,6 +17,7 @@ import {Services} from '../../../src/services'; import {dev} from '../../../src/log'; import {isArray, isObject} from '../../../src/types'; import {isSecureUrlDeprecated} from '../../../src/url'; +import {parseExtensionUrl} from '../../../src/service/extension-script'; import {parseJson} from '../../../src/json'; const TAG = 'amp-ad-util'; @@ -160,3 +161,35 @@ export function getAmpAdMetadata(creative) { return null; } } + +/** + * Determine if parsed extensions metadata contains given element id. + * @param {!Array<{custom-element: string, src: string}>} extensions + * @param {string} id + * @return {boolean} + */ +export function extensionsHasElement(extensions, id) { + return extensions.some((entry) => entry['custom-element'] === id); +} + +/** + * Parses extension urls from given metadata to retrieve name and version. + * @param {!./amp-ad-type-defs.CreativeMetaDataDef} creativeMetadata + * @return {!Array} + */ +export function getExtensionsFromMetadata(creativeMetadata) { + const parsedExtensions = []; + const {extensions} = creativeMetadata; + if (!extensions || !isArray(extensions)) { + return parsedExtensions; + } + + for (let i = 0; i < extensions.length; i++) { + const extension = extensions[i]; + const extensionData = parseExtensionUrl(extension.src); + if (extensionData) { + parsedExtensions.push(extensionData); + } + } + return parsedExtensions; +} diff --git a/extensions/amp-a4a/0.1/friendly-frame-util.js b/extensions/amp-a4a/0.1/friendly-frame-util.js index d2f7b033c08e..0db1b021780c 100644 --- a/extensions/amp-a4a/0.1/friendly-frame-util.js +++ b/extensions/amp-a4a/0.1/friendly-frame-util.js @@ -17,12 +17,13 @@ import {A4AVariableSource} from '../../amp-a4a/0.1/a4a-variable-source'; import {createElementWithAttributes} from '../../../src/dom'; import {dict} from '../../../src/utils/object'; +import {getExtensionsFromMetadata} from './amp-ad-utils'; import {installFriendlyIframeEmbed} from '../../../src/friendly-iframe-embed'; import {installUrlReplacementsForEmbed} from '../../../src/service/url-replacements-impl'; import {setStyle} from '../../../src/style'; /** - * Renders a creative into a "NameFrame" iframe. + * Renders a creative into a friendly iframe. * * @param {string} adUrl The ad request URL. * @param {!./amp-ad-type-defs.LayoutInfoDef} size The size and layout of the @@ -66,6 +67,7 @@ export function renderCreativeIntoFriendlyFrame( }); } + const extensions = getExtensionsFromMetadata(creativeMetadata); return installFriendlyIframeEmbed( iframe, element, @@ -73,9 +75,7 @@ export function renderCreativeIntoFriendlyFrame( host: element, url: /** @type {string} */ (adUrl), html: creativeMetadata.minifiedCreative, - // TODO(#33020): provide the `extensions` property instead, in - // the format of `[{extensionId, extensionVersion}]`. - extensionIds: creativeMetadata.customElementExtensions || [], + extensions, fonts: fontsArray, }, (embedWin, ampdoc) => { diff --git a/extensions/amp-a4a/0.1/template-validator.js b/extensions/amp-a4a/0.1/template-validator.js index 894cc89c95f4..f0a395bbe97e 100644 --- a/extensions/amp-a4a/0.1/template-validator.js +++ b/extensions/amp-a4a/0.1/template-validator.js @@ -15,11 +15,15 @@ */ import {AdResponseType, Validator, ValidatorResult} from './amp-ad-type-defs'; -import {getAmpAdMetadata} from './amp-ad-utils'; +import { + extensionsHasElement, + getAmpAdMetadata, + getExtensionsFromMetadata, +} from './amp-ad-utils'; import {getAmpAdTemplateHelper} from './amp-ad-template-helper'; -import {preloadFriendlyIframeEmbedExtensionIdsDeprecated} from '../../../src/friendly-iframe-embed'; -import {pushIfNotExist} from '../../../src/utils/array'; +import {preloadFriendlyIframeEmbedExtensions} from '../../../src/friendly-iframe-embed'; import {tryParseJson} from '../../../src/json'; +import {urls} from '../../../src/config'; import {utf8Decode} from '../../../src/utils/bytes'; /** @const {string} */ @@ -65,21 +69,26 @@ export class TemplateValidator extends Validator { .fetch(parsedResponseBody.templateUrl) .then((template) => { const creativeMetadata = getAmpAdMetadata(template); - const customElementExtensions = - creativeMetadata['customElementExtensions']; - if (parsedResponseBody.analytics) { - pushIfNotExist(customElementExtensions, 'amp-analytics'); + creativeMetadata['extensions'] = creativeMetadata['extensions'] || []; + const extensions = creativeMetadata['extensions']; + if ( + parsedResponseBody.analytics && + !extensionsHasElement(extensions, 'amp-analytics') + ) { + extensions.push({ + 'custom-element': 'amp-analytics', + src: `${urls.cdn}/v0/amp-analytics-0.1.js`, + }); + } + if (!extensionsHasElement(extensions, 'amp-mustache')) { + extensions.push({ + 'custom-element': 'amp-mustache', + src: `${urls.cdn}/v0/amp-mustache-latest.js`, + }); } - pushIfNotExist(customElementExtensions, 'amp-mustache'); - // Load any extensions; do not wait on their promises as this - // is just to prefetch. - // TODO(#33020): switch to `preloadFriendlyIframeEmbedExtensions` with - // the format of `[{extensionId, extensionVersion}]`. - preloadFriendlyIframeEmbedExtensionIdsDeprecated( - context.win, - customElementExtensions - ); + const extensionsInfo = getExtensionsFromMetadata(creativeMetadata); + preloadFriendlyIframeEmbedExtensions(context.win, extensionsInfo); // TODO(levitzky) Add preload logic for fonts / images. return Promise.resolve( diff --git a/extensions/amp-a4a/0.1/test/test-amp-a4a.js b/extensions/amp-a4a/0.1/test/test-amp-a4a.js index 8c7e2c9b5927..2426ec86ec2e 100644 --- a/extensions/amp-a4a/0.1/test/test-amp-a4a.js +++ b/extensions/amp-a4a/0.1/test/test-amp-a4a.js @@ -2352,6 +2352,28 @@ describes.realWin('amp-a4a', {amp: true}, (env) => { expect(actual).to.deep.equal(expected); }); + it('should copy over any extensions detail', () => { + metaData.extensions = [ + { + 'custom-element': 'amp-analytics', + 'src': 'https://cdn.ampproject.org/v0/amp-analytics-0.1.js', + }, + { + 'custom-element': 'amp-mustache', + 'src': 'https://cdn.ampproject.org/v0/amp-mustache-1.0.js', + }, + ]; + const actual = a4a.getAmpAdMetadata(buildCreativeString(metaData)); + expect(actual.extensions).to.deep.include({ + 'custom-element': 'amp-analytics', + 'src': 'https://cdn.ampproject.org/v0/amp-analytics-0.1.js', + }); + expect(actual.extensions).to.deep.include({ + 'custom-element': 'amp-mustache', + 'src': 'https://cdn.ampproject.org/v0/amp-mustache-1.0.js', + }); + }); + // TODO(levitzky) remove the following two tests after metadata bug is // fixed. it('should parse metadata with wrong opening tag', () => { diff --git a/extensions/amp-a4a/0.1/test/test-amp-ad-utils.js b/extensions/amp-a4a/0.1/test/test-amp-ad-utils.js index 47cde5ec42b2..91a0da5d299e 100644 --- a/extensions/amp-a4a/0.1/test/test-amp-ad-utils.js +++ b/extensions/amp-a4a/0.1/test/test-amp-ad-utils.js @@ -15,7 +15,11 @@ */ import {data} from './testdata/valid_css_at_rules_amp.reserialized'; -import {getAmpAdMetadata} from '../amp-ad-utils'; +import { + extensionsHasElement, + getAmpAdMetadata, + getExtensionsFromMetadata, +} from '../amp-ad-utils'; describe('getAmpAdMetadata', () => { it('should parse metadata successfully', () => { @@ -56,3 +60,62 @@ describe('getAmpAdMetadata', () => { expect(creativeMetadata).to.be.null; }); }); + +describe('extensionsHasElement', () => { + it('should return true if containing extension', () => { + const extensions = [ + { + 'custom-element': 'amp-cats', + src: 'https://cdn.ampproject.org/v0/amp-cats-0.1.js', + }, + ]; + expect(extensionsHasElement(extensions, 'amp-cats')).to.be.true; + }); + + it('should return false if it does not contain extension', () => { + const extensions = [ + { + 'custom-element': 'amp-cats', + src: 'https://cdn.ampproject.org/v0/amp-cats-0.1.js', + }, + ]; + expect(extensionsHasElement(extensions, 'amp-dogs')).to.be.false; + }); + + it('should return false if empty array', () => { + const extensions = []; + expect(extensionsHasElement(extensions, 'amp-dogs')).to.be.false; + }); +}); + +describe('getExtensionsFromMetadata', () => { + it('should return extension name and version', () => { + const metadata = { + extensions: [ + { + 'custom-element': 'amp-analytics', + 'src': 'https://cdn.ampproject.org/v0/amp-analytics-0.1.js', + }, + { + 'custom-element': 'amp-mustache', + 'src': 'https://cdn.ampproject.org/v0/amp-mustache-1.0.js', + }, + ], + }; + const extensions = getExtensionsFromMetadata(metadata); + expect(extensions).to.deep.include({ + extensionId: 'amp-analytics', + extensionVersion: '0.1', + }); + expect(extensions).to.deep.include({ + extensionId: 'amp-mustache', + extensionVersion: '1.0', + }); + }); + + it('should handle no `extensions` key in metadata', () => { + const metadata = {}; + const extensions = getExtensionsFromMetadata(metadata); + expect(extensions).to.eql([]); + }); +}); diff --git a/extensions/amp-a4a/0.1/test/test-template-validator.js b/extensions/amp-a4a/0.1/test/test-template-validator.js index 3e04adb189f3..e11827b2e96a 100644 --- a/extensions/amp-a4a/0.1/test/test-template-validator.js +++ b/extensions/amp-a4a/0.1/test/test-template-validator.js @@ -130,15 +130,19 @@ describes.realWin('TemplateValidator', realWinConfig, (env) => { }); }); - it('should have amp-analytics and mustache in customElementExtensions', () => { + it('should have amp-analytics and mustache in extensions', () => { return validatorPromise.then((validatorOutput) => { expect(validatorOutput).to.be.ok; expect(validatorOutput.creativeData).to.be.ok; const {creativeMetadata} = validatorOutput.creativeData; - expect(creativeMetadata.customElementExtensions).to.deep.equal([ - 'amp-analytics', - 'amp-mustache', - ]); + expect(creativeMetadata.extensions).to.deep.include({ + 'custom-element': 'amp-analytics', + 'src': 'https://cdn.ampproject.org/v0/amp-analytics-0.1.js', + }); + expect(creativeMetadata.extensions).to.deep.include({ + 'custom-element': 'amp-mustache', + 'src': 'https://cdn.ampproject.org/v0/amp-mustache-latest.js', + }); }); }); }); diff --git a/extensions/amp-story/1.0/test/test-amp-story-page.js b/extensions/amp-story/1.0/test/test-amp-story-page.js index 73f395ddb93b..08917580aa43 100644 --- a/extensions/amp-story/1.0/test/test-amp-story-page.js +++ b/extensions/amp-story/1.0/test/test-amp-story-page.js @@ -251,6 +251,7 @@ describes.realWin('amp-story-page', {amp: {extensions}}, (env) => { const fiePromise = installFriendlyIframeEmbed(iframe, gridLayerEl, { url: 'https://amp.dev', html: '', + extensions: [], }); env.sandbox.stub(page, 'loadPromise').returns(Promise.resolve()); diff --git a/src/friendly-iframe-embed.js b/src/friendly-iframe-embed.js index 012c78b03315..e013b17e08e5 100644 --- a/src/friendly-iframe-embed.js +++ b/src/friendly-iframe-embed.js @@ -62,14 +62,12 @@ import {whenContentIniLoad} from './ini-load'; * this embed. * - fonts: An optional array of fonts used in this embed. * - * TODO(#33020): remove extensionIds once extensions is used everywhere. * * @typedef {{ * host: (?AmpElement|undefined), * url: string, * html: ?string, * extensions: (?Array<{extensionId: string, extensionVersion: string}>|undefined), - * extensionIds: (?Array|undefined), * fonts: (?Array|undefined), * skipHtmlMerge: (boolean|undefined), * }} @@ -137,6 +135,7 @@ export function preloadFriendlyIframeEmbedExtensions(win, extensions) { * @param {!Window} win * @param {!Array} extensionIds * TODO(#33020): remove this method in favor `preloadFriendlyIframeEmbedExtensions`. + * @visibleForTesting */ export function preloadFriendlyIframeEmbedExtensionIdsDeprecated( win, @@ -180,17 +179,8 @@ export function installFriendlyIframeEmbed( iframe.setAttribute('marginheight', '0'); iframe.setAttribute('marginwidth', '0'); - // Compute extensions. - const extensionIds = - // TODO(#33020): Remove extensionIds format once it's supported everywhere. - spec.extensionIds - ? spec.extensionIds - : spec.extensions - ? spec.extensions.map(({extensionId}) => extensionId) - : []; - // Pre-load extensions. - preloadFriendlyIframeEmbedExtensionIdsDeprecated(win, extensionIds); + preloadFriendlyIframeEmbedExtensions(win, spec.extensions || []); const html = spec.skipHtmlMerge ? spec.html : mergeHtml(spec); // Receive the signal when iframe is ready: it's document is formed. @@ -274,7 +264,7 @@ export function installFriendlyIframeEmbed( embed, extensionsService, ampdoc, - extensionIds, + spec.extensions, opt_preinstallCallback ).then(() => { if (!childWin.frameElement) { @@ -746,7 +736,7 @@ export class Installers { * @param {!FriendlyIframeEmbed} embed * @param {!./service/extensions-impl.Extensions} extensionsService * @param {!./service/ampdoc-impl.AmpDocFie} ampdoc - * @param {!Array} extensionIds + * @param {!Array<{extensionId: string, extensionVersion: string}>} extensions * @param {function(!Window, ?./service/ampdoc-impl.AmpDoc=)|undefined} preinstallCallback * @param {function(!Promise)=} opt_installComplete * @return {!Promise} @@ -755,7 +745,7 @@ export class Installers { embed, extensionsService, ampdoc, - extensionIds, + extensions, preinstallCallback, opt_installComplete ) { @@ -763,6 +753,9 @@ export class Installers { const parentWin = toWin(childWin.frameElement.ownerDocument.defaultView); setParentWindow(childWin, parentWin); const getDelayPromise = getDelayPromiseProducer(); + // TODO(#33020): remove this when we pass full extensions object + // to installation service + const extensionIds = extensions.map(({extensionId}) => extensionId); return getDelayPromise(undefined) .then(() => { diff --git a/test/unit/test-friendly-iframe-embed.js b/test/unit/test-friendly-iframe-embed.js index ec5def1583d6..396fba7da2b6 100644 --- a/test/unit/test-friendly-iframe-embed.js +++ b/test/unit/test-friendly-iframe-embed.js @@ -111,6 +111,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { const embedPromise = installFriendlyIframeEmbed(iframe, document.body, { url: 'https://acme.org/url1', html: '', + extensions: [], }); // Attributes set. @@ -266,88 +267,6 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { }); }); - // TODO(#33020): Remove this test once `extensions` format is supported - // everywhere. - it('should create ampdoc and install extensions with extensionIds', () => { - // AmpDoc is created. - const ampdocSignals = new Signals(); - let childWinForAmpDoc; - const ampdoc = { - get win() { - return childWinForAmpDoc; - }, - getParent: () => env.ampdoc, - setReady: env.sandbox.spy(), - signals: () => ampdocSignals, - getHeadNode: () => childWinForAmpDoc.document.head, - setExtensionsKnown: env.sandbox.stub(), - }; - ampdocServiceMock - .expects('installFieDoc') - .withExactArgs( - 'https://acme.org/url1', - env.sandbox.match((arg) => { - // Match childWin argument. - childWinForAmpDoc = arg; - return true; - }), - env.sandbox.match((arg) => { - // Match options with no signals. - expect(arg && arg.signals).to.not.be.ok; - return true; - }) - ) - .returns(ampdoc) - .once(); - - // Extensions preloading have been requested. - extensionsMock - .expects('preloadExtension') - .withExactArgs('amp-test') - .returns(Promise.resolve()) - .once(); - extensionsMock - .expects('preinstallEmbed') - .withExactArgs(ampdoc, ['amp-test']) - .once(); - extensionsMock - .expects('installExtensionsInDoc') - .withExactArgs(ampdoc, ['amp-test']) - .returns(Promise.resolve()) - .once(); - - let renderCompleteResolver = null; - const renderCompletePromise = new Promise((resolve) => { - renderCompleteResolver = resolve; - }); - env.sandbox - .stub(FriendlyIframeEmbed.prototype, 'whenRenderComplete') - .callsFake(() => renderCompletePromise); - - const embedPromise = installFriendlyIframeEmbed( - iframe, - document.body, - { - url: 'https://acme.org/url1', - html: '', - extensionIds: ['amp-test'], - }, - preinstallCallback - ); - return embedPromise - .then((embed) => { - expect(childWinForAmpDoc).to.equal(embed.win); - expect(ampdoc).to.equal(embed.ampdoc); - expect(installServicesStub).to.be.calledOnce.calledWith(ampdoc); - expect(ampdoc.setReady).to.not.be.called; - renderCompleteResolver(); - return renderCompletePromise; - }) - .then(() => { - expect(ampdoc.setReady).to.be.calledOnce; - }); - }); - it('should create ampdoc and install extensions with host', () => { // host. const hostSignals = new Signals(); @@ -418,7 +337,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { { url: 'https://acme.org/url1', html: '', - extensionIds: ['amp-test'], + extensions: [{extensionId: 'amp-test', extensionVersion: 'latest'}], host, }, preinstallCallback @@ -453,7 +372,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { { url: 'https://acme.org/url1', html: '', - extensionIds: ['amp-test'], + extensions: [{extensionId: 'amp-test', extensionVersion: 'latest'}], }, preinstallCallback ); @@ -473,6 +392,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { { url: 'https://acme.org/url1', html: '', + extensions: [], }, (embedWin) => { registerServiceBuilderInEmbedWin(embedWin, 'c', function () { @@ -528,7 +448,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { { url: 'https://acme.org/url1', html: '', - extensionIds: [], + extensions: [], }, preinstallCallback ); @@ -552,7 +472,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { { url: 'https://acme.test/url1', html: '', - extensionIds: ['amp-test'], + extensions: [{extensionId: 'amp-test', extensionVersion: 'latest'}], }, preinstallCallback ); @@ -567,7 +487,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { { url: 'https://acme.test/url1', html: '', - extensionIds: ['amp-test'], + extensions: [{extensionId: 'amp-test', extensionVersion: 'latest'}], skipHtmlMerge: true, }, preinstallCallback @@ -632,7 +552,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { { url: 'https://acme.org/url1', html: '', - extensionIds: ['amp-test'], + extensions: [{extensionId: 'amp-test', extensionVersion: 'latest'}], }, preinstallCallback ); @@ -746,6 +666,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { await installFriendlyIframeEmbed(iframe, document.body, { url: 'https://acme.org/url1', html: '', + extensions: [], }); expect(mutateSpy).to.not.be.called; @@ -963,6 +884,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { const embedPromise = installFriendlyIframeEmbed(iframe, document.body, { url: 'https://acme.org/url1', html: '', + extensions: [], }); return embedPromise.then(() => { expect(iframe.contentDocument.getElementById('a1')).to.be.ok; @@ -974,6 +896,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { const embedPromise = installFriendlyIframeEmbed(iframe, document.body, { url: 'https://acme.org/url1', html: '', + extensions: [], }); return embedPromise.then(() => { expect(iframe.contentDocument.getElementById('a1')).to.be.ok; @@ -984,6 +907,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { const embedPromise = installFriendlyIframeEmbed(iframe, document.body, { url: 'https://acme.org/url1', html: '', + extensions: [], }); return embedPromise.then((embed) => { return embed.whenWindowLoaded(); @@ -995,6 +919,7 @@ describes.realWin('friendly-iframe-embed', {amp: true}, (env) => { const embedPromise = installFriendlyIframeEmbed(iframe, document.body, { url: 'https://acme.org/url1', html: '', + extensions: [], }); return embedPromise.then((embed) => { return embed.whenWindowLoaded(); @@ -1458,7 +1383,7 @@ describes.realWin('installExtensionsInEmbed', {amp: true}, (env) => { fie, extensions, ampdoc, - ['amp-test'], + [{extensionId: 'amp-test', extensionVersion: 'latest'}], null, installComplete ); @@ -1541,7 +1466,7 @@ describes.realWin('installExtensionsInEmbed', {amp: true}, (env) => { fie, extensions, ampdoc, - ['amp-test'], + [{extensionId: 'amp-test', extensionVersion: 'latest'}], null, installComplete ); @@ -1572,7 +1497,7 @@ describes.realWin('installExtensionsInEmbed', {amp: true}, (env) => { fie, extensions, ampdoc, - ['amp-test'], + [{extensionId: 'amp-test', extensionVersion: 'latest'}], function (winArg, ampdocArg) { expect(winArg).to.equal(iframeWin); expect(ampdocArg).to.equal(ampdoc);