diff --git a/src/adloader.js b/src/adloader.js index 6f2bd112712..e0f2ba46cff 100644 --- a/src/adloader.js +++ b/src/adloader.js @@ -1,8 +1,14 @@ -var utils = require('./utils'); -let _requestCache = {}; +import includes from 'core-js/library/fn/array/includes'; +import * as utils from './utils'; + +const _requestCache = {}; +const _vendorWhitelist = [ + 'criteo', +] /** * Loads external javascript. Can only be used if external JS is approved by Prebid. See https://github.com/prebid/prebid-js-external-js-template#policy + * Each unique URL will be loaded at most 1 time. * @param {string} url the url to load * @param {string} moduleCode bidderCode or module code of the module requesting this resource */ @@ -11,18 +17,23 @@ exports.loadExternalScript = function(url, moduleCode) { utils.logError('cannot load external script without url and moduleCode'); return; } + if (!includes(_vendorWhitelist, moduleCode)) { + utils.logError(`${moduleCode} not whitelisted for loading external JavaScript`); + return; + } + // only load each asset once + if (_requestCache[url]) { + return; + } + utils.logWarn(`module ${moduleCode} is loading external JavaScript`); const script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; - script.src = url; - // add the new script tag to the page - const target = document.head || document.body; - if (target) { - target.appendChild(script); - } + utils.insertElement(script); + _requestCache[url] = true; }; /** diff --git a/test/spec/adloader_spec.js b/test/spec/adloader_spec.js index 951631d7eac..55224cb0aab 100644 --- a/test/spec/adloader_spec.js +++ b/test/spec/adloader_spec.js @@ -1,4 +1,31 @@ +import * as utils from 'src/utils'; +import * as adLoader from 'src/adloader'; + describe('adLoader', function () { - var assert = require('chai').assert, - adLoader = require('../../src/adloader'); + let utilsinsertElementStub; + let utilsLogErrorStub; + + beforeEach(() => { + utilsinsertElementStub = sinon.stub(utils, 'insertElement'); + utilsLogErrorStub = sinon.stub(utils, 'logError'); + }); + + afterEach(() => { + utilsinsertElementStub.restore(); + utilsLogErrorStub.restore(); + }); + + describe('loadExternalScript', () => { + it('requires moduleCode to be included on the request', () => { + adLoader.loadExternalScript('someURL'); + expect(utilsLogErrorStub.called).to.be.true; + expect(utilsinsertElementStub.called).to.be.false; + }); + + it('only allows whitelisted vendors to load scripts', () => { + adLoader.loadExternalScript('someURL', 'criteo'); + expect(utilsLogErrorStub.called).to.be.false; + expect(utilsinsertElementStub.called).to.be.true; + }); + }); }); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 1ba4edfa4ea..d7aecea890b 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -3,8 +3,6 @@ import { spec } from 'modules/appnexusBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; -const adloader = require('../../../src/adloader'); - const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; describe('AppNexusAdapter', () => { @@ -309,18 +307,6 @@ describe('AppNexusAdapter', () => { }) describe('interpretResponse', () => { - let loadScriptStub; - - beforeEach(() => { - loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { - args[1](); - }); - }); - - afterEach(() => { - loadScriptStub.restore(); - }); - let response = { 'version': '3.0.0', 'tags': [