diff --git a/libraries/devicePixelRatio/devicePixelRatio.js b/libraries/devicePixelRatio/devicePixelRatio.js new file mode 100644 index 00000000000..8bfe23bcb3d --- /dev/null +++ b/libraries/devicePixelRatio/devicePixelRatio.js @@ -0,0 +1,17 @@ +import {canAccessWindowTop, internal as utilsInternals} from '../../src/utils.js'; + +function getFallbackWindow(win) { + if (win) { + return win; + } + + return canAccessWindowTop() ? utilsInternals.getWindowTop() : utilsInternals.getWindowSelf(); +} + +export function getDevicePixelRatio(win) { + try { + return getFallbackWindow(win).devicePixelRatio; + } catch (e) { + } + return 1; +} diff --git a/modules/apstreamBidAdapter.js b/modules/apstreamBidAdapter.js index 838487925c8..f432c85388f 100644 --- a/modules/apstreamBidAdapter.js +++ b/modules/apstreamBidAdapter.js @@ -1,5 +1,6 @@ import {getDNT} from '../libraries/dnt/index.js'; import { generateUUID, deepAccess, createTrackPixelHtml } from '../src/utils.js'; +import { getDevicePixelRatio } from '../libraries/devicePixelRatio/devicePixelRatio.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { getStorageManager } from '../src/storageManager.js'; @@ -335,7 +336,7 @@ function injectPixels(ad, pixels, scripts) { } function getScreenParams() { - return `${window.screen.width}x${window.screen.height}@${window.devicePixelRatio}`; + return `${window.screen.width}x${window.screen.height}@${getDevicePixelRatio(window)}`; } function getBids(bids) { diff --git a/modules/datablocksBidAdapter.js b/modules/datablocksBidAdapter.js index b37ceab6631..7f5a4bedd62 100644 --- a/modules/datablocksBidAdapter.js +++ b/modules/datablocksBidAdapter.js @@ -1,3 +1,4 @@ +import {getDevicePixelRatio} from '../libraries/devicePixelRatio/devicePixelRatio.js'; import {deepAccess, getWinDimensions, getWindowTop, isGptPubadsDefined} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {config} from '../src/config.js'; @@ -135,7 +136,7 @@ export const spec = { 'whl': win.history.length, 'wxo': win.pageXOffset, 'wyo': win.pageYOffset, - 'wpr': win.devicePixelRatio, + 'wpr': getDevicePixelRatio(win), 'is_bot': botTest.doTests(), 'is_hid': win.document.hidden, 'vs': win.document.visibilityState diff --git a/modules/greenbidsBidAdapter.js b/modules/greenbidsBidAdapter.js index 490eb9e703d..58aa8608194 100644 --- a/modules/greenbidsBidAdapter.js +++ b/modules/greenbidsBidAdapter.js @@ -1,4 +1,5 @@ import { getValue, logError, deepAccess, parseSizesInput, getBidIdParameter, logInfo, getWinDimensions, getScreenOrientation } from '../src/utils.js'; +import { getDevicePixelRatio } from '../libraries/devicePixelRatio/devicePixelRatio.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { getStorageManager } from '../src/storageManager.js'; import { getHLen } from '../libraries/navigatorData/navigatorData.js'; @@ -65,7 +66,7 @@ export const spec = { device: bidderRequest?.ortb2?.device || {}, deviceWidth: screen.width, deviceHeight: screen.height, - devicePixelRatio: topWindow.devicePixelRatio, + devicePixelRatio: getDevicePixelRatio(topWindow), screenOrientation: getScreenOrientation(), historyLength: getHLen(), viewportHeight: getWinDimensions().visualViewport.height, diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 8bfb5b841d0..c1a5b8328dc 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -1,5 +1,6 @@ import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {_each, deepAccess, getWinDimensions, logError, logWarn, parseSizesInput} from '../src/utils.js'; +import {getDevicePixelRatio} from '../libraries/devicePixelRatio/devicePixelRatio.js'; import {config} from '../src/config.js'; import {getStorageManager} from '../src/storageManager.js'; @@ -89,7 +90,7 @@ function _getBrowserParams(topWindowUrl, mosttopLocation) { pu: stripGGParams(topUrl), tpl: mosttopURL, ce: storage.cookiesAreEnabled(), - dpr: topWindow.devicePixelRatio || 1, + dpr: getDevicePixelRatio(topWindow), jcsi: JSON.stringify(JCSI), ogu: getOgURL() }; diff --git a/modules/hypelabBidAdapter.js b/modules/hypelabBidAdapter.js index 9982af84cc9..bc562b84cb3 100644 --- a/modules/hypelabBidAdapter.js +++ b/modules/hypelabBidAdapter.js @@ -1,6 +1,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import { generateUUID, isFn, isPlainObject, getWinDimensions } from '../src/utils.js'; +import { getDevicePixelRatio } from '../libraries/devicePixelRatio/devicePixelRatio.js'; import { ajax } from '../src/ajax.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getWalletPresence, getWalletProviderFlags } from '../libraries/hypelabUtils/hypelabUtils.js'; @@ -40,7 +41,7 @@ function buildRequests(validBidRequests, bidderRequest) { const uuid = uids[0] ? uids[0] : generateTemporaryUUID(); const floor = getBidFloor(request, request.sizes || []); - const dpr = typeof window !== 'undefined' ? window.devicePixelRatio : 1; + const dpr = typeof window !== 'undefined' ? getDevicePixelRatio(window) : 1; const wp = getWalletPresence(); const wpfs = getWalletProviderFlags(); const winDimensions = getWinDimensions(); diff --git a/modules/oguryBidAdapter.js b/modules/oguryBidAdapter.js index 507cb63fe2a..00c8bfb77ef 100644 --- a/modules/oguryBidAdapter.js +++ b/modules/oguryBidAdapter.js @@ -2,6 +2,7 @@ import { BANNER } from '../src/mediaTypes.js'; import { getWindowSelf, getWindowTop, isFn, deepAccess, isPlainObject, deepSetValue, mergeDeep } from '../src/utils.js'; +import { getDevicePixelRatio } from '../libraries/devicePixelRatio/devicePixelRatio.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { ajax } from '../src/ajax.js'; import { getAdUnitSizes } from '../libraries/sizeUtils/sizeUtils.js'; @@ -25,7 +26,7 @@ export const ortbConverterProps = { request(buildRequest, imps, bidderRequest, context) { const req = buildRequest(imps, bidderRequest, context); req.tmax = DEFAULT_TIMEOUT; - deepSetValue(req, 'device.pxratio', window.devicePixelRatio); + deepSetValue(req, 'device.pxratio', getDevicePixelRatio(getWindowContext())); deepSetValue(req, 'site.page', getWindowContext().location.href); req.ext = mergeDeep({}, req.ext, { diff --git a/modules/sspBCBidAdapter.js b/modules/sspBCBidAdapter.js index 09b7e6a6daa..5ce8fb34492 100644 --- a/modules/sspBCBidAdapter.js +++ b/modules/sspBCBidAdapter.js @@ -1,4 +1,5 @@ import { deepAccess, getWinDimensions, getWindowTop, isArray, logInfo, logWarn } from '../src/utils.js'; +import { getDevicePixelRatio } from '../libraries/devicePixelRatio/devicePixelRatio.js'; import { ajax } from '../src/ajax.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; @@ -174,7 +175,7 @@ const applyClientHints = ortbRequest => { 'CH-SaveData': connection.saveData, 'CH-Downlink': connection.downlink, 'CH-DeviceMemory': null, - 'CH-Dpr': W.devicePixelRatio, + 'CH-Dpr': getDevicePixelRatio(W), 'CH-ViewportWidth': viewport.width, 'CH-BrowserBrands': JSON.stringify(userAgentData.brands), 'CH-isMobile': userAgentData.mobile, diff --git a/modules/teadsBidAdapter.js b/modules/teadsBidAdapter.js index 24894b9e7c1..bc2e3ef9588 100644 --- a/modules/teadsBidAdapter.js +++ b/modules/teadsBidAdapter.js @@ -1,4 +1,5 @@ import {logError, parseSizesInput, isArray, getBidIdParameter, getWinDimensions, getScreenOrientation} from '../src/utils.js'; +import {getDevicePixelRatio} from '../libraries/devicePixelRatio/devicePixelRatio.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {getStorageManager} from '../src/storageManager.js'; import {isAutoplayEnabled} from '../libraries/autoplayDetection/autoplay.js'; @@ -72,7 +73,7 @@ export const spec = { device: bidderRequest?.ortb2?.device || {}, deviceWidth: screen.width, deviceHeight: screen.height, - devicePixelRatio: topWindow.devicePixelRatio, + devicePixelRatio: getDevicePixelRatio(topWindow), screenOrientation: getScreenOrientation(), historyLength: getHLen(), viewportHeight: getWinDimensions().visualViewport.height, diff --git a/src/utils/winDimensions.js b/src/utils/winDimensions.js index 01122a9761c..2759e56eba6 100644 --- a/src/utils/winDimensions.js +++ b/src/utils/winDimensions.js @@ -34,22 +34,22 @@ const winDimensions = new CachedApiWrapper( ); export const internal = { - reset: winDimensions.reset, + winDimensions, }; export const getWinDimensions = (() => { let lastCheckTimestamp; return function () { if (!lastCheckTimestamp || (Date.now() - lastCheckTimestamp > CHECK_INTERVAL_MS)) { - internal.reset(); + internal.winDimensions.reset(); lastCheckTimestamp = Date.now(); } - return winDimensions.obj; + return internal.winDimensions.obj; } })(); export function resetWinDimensions() { - internal.reset(); + internal.winDimensions.reset(); } export function getScreenOrientation(win) { diff --git a/test/spec/modules/greenbidsBidAdapter_spec.js b/test/spec/modules/greenbidsBidAdapter_spec.js index 4cf992434dc..00c0005fe16 100644 --- a/test/spec/modules/greenbidsBidAdapter_spec.js +++ b/test/spec/modules/greenbidsBidAdapter_spec.js @@ -2,6 +2,7 @@ import { expect } from 'chai'; import { newBidder } from 'src/adapters/bidderFactory.js'; import { spec, ENDPOINT_URL } from 'modules/greenbidsBidAdapter.js'; import { getScreenOrientation } from 'src/utils.js'; +import {getDevicePixelRatio} from '../../../libraries/devicePixelRatio/devicePixelRatio.js'; const AD_SCRIPT = '"'; describe('greenbidsBidAdapter', () => { @@ -277,7 +278,7 @@ describe('greenbidsBidAdapter', () => { it('should add pixelRatio info to payload', function () { const request = spec.buildRequests(bidRequests, bidderRequestDefault); const payload = JSON.parse(request.data); - const pixelRatio = window.top.devicePixelRatio + const pixelRatio = getDevicePixelRatio() expect(payload.devicePixelRatio).to.exist; expect(payload.devicePixelRatio).to.deep.equal(pixelRatio); diff --git a/test/spec/modules/hypelabBidAdapter_spec.js b/test/spec/modules/hypelabBidAdapter_spec.js index d6c79a957cc..ff98c33b136 100644 --- a/test/spec/modules/hypelabBidAdapter_spec.js +++ b/test/spec/modules/hypelabBidAdapter_spec.js @@ -13,6 +13,7 @@ import { } from 'modules/hypelabBidAdapter.js'; import { BANNER } from 'src/mediaTypes.js'; +import {getDevicePixelRatio} from '../../../libraries/devicePixelRatio/devicePixelRatio.js'; const mockValidBidRequest = { bidder: 'hypelab', @@ -177,7 +178,7 @@ describe('hypelabBidAdapter', function () { expect(data.dpr).to.be.a('number'); expect(data.location).to.be.a('string'); expect(data.floor).to.equal(null); - expect(data.dpr).to.equal(1); + expect(data.dpr).to.equal(getDevicePixelRatio()); expect(data.wp).to.deep.equal({ ada: false, bnb: false, diff --git a/test/spec/modules/oguryBidAdapter_spec.js b/test/spec/modules/oguryBidAdapter_spec.js index 57ebea5e2ab..3cd7542f6c2 100644 --- a/test/spec/modules/oguryBidAdapter_spec.js +++ b/test/spec/modules/oguryBidAdapter_spec.js @@ -3,6 +3,7 @@ import sinon from 'sinon'; import { spec, ortbConverterProps } from 'modules/oguryBidAdapter'; import * as utils from 'src/utils.js'; import { server } from '../../mocks/xhr.js'; +import {getDevicePixelRatio} from '../../../libraries/devicePixelRatio/devicePixelRatio.js'; const BID_URL = 'https://mweb-hb.presage.io/api/header-bidding-request'; const TIMEOUT_URL = 'https://ms-ads-monitoring-events.presage.io/bid_timeout' @@ -577,10 +578,6 @@ describe('OguryBidAdapter', () => { return stubbedCurrentTime; }); - const stubbedDevicePixelMethod = sinon.stub(window, 'devicePixelRatio').get(function() { - return stubbedDevicePixelRatio; - }); - const defaultTimeout = 1000; function assertImpObject(ortbBidRequest, bidRequest) { @@ -639,7 +636,7 @@ describe('OguryBidAdapter', () => { beforeEach(() => { windowTopStub = sinon.stub(utils, 'getWindowTop'); - windowTopStub.returns({ location: { href: currentLocation } }); + windowTopStub.returns({ location: { href: currentLocation }, devicePixelRatio: stubbedDevicePixelRatio}); }); afterEach(() => { @@ -648,7 +645,6 @@ describe('OguryBidAdapter', () => { after(() => { stubbedCurrentTimeMethod.restore(); - stubbedDevicePixelMethod.restore(); }); it('sends bid request to ENDPOINT via POST', function () { diff --git a/test/spec/modules/teadsBidAdapter_spec.js b/test/spec/modules/teadsBidAdapter_spec.js index f776f5243a8..c698473260f 100644 --- a/test/spec/modules/teadsBidAdapter_spec.js +++ b/test/spec/modules/teadsBidAdapter_spec.js @@ -3,6 +3,7 @@ import * as autoplay from 'libraries/autoplayDetection/autoplay.js'; import { spec, storage } from 'modules/teadsBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; import { getScreenOrientation } from 'src/utils.js'; +import {getDevicePixelRatio} from '../../../libraries/devicePixelRatio/devicePixelRatio.js'; const ENDPOINT = 'https://a.teads.tv/hb/bid-request'; const AD_SCRIPT = '"'; @@ -360,7 +361,7 @@ describe('teadsBidAdapter', () => { it('should add pixelRatio info to payload', function () { const request = spec.buildRequests(bidRequests, bidderRequestDefault); const payload = JSON.parse(request.data); - const pixelRatio = window.top.devicePixelRatio + const pixelRatio = getDevicePixelRatio(); expect(payload.devicePixelRatio).to.exist; expect(payload.devicePixelRatio).to.deep.equal(pixelRatio); diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 1efdc5621f6..8ed2efa3b9f 100644 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -1446,7 +1446,7 @@ describe('getWinDimensions', () => { }); it('should clear cache once per 20ms', () => { - const resetWinDimensionsSpy = sinon.spy(winDimensions.internal, 'reset'); + const resetWinDimensionsSpy = sinon.spy(winDimensions.internal.winDimensions, 'reset'); expect(getWinDimensions().innerHeight).to.exist; clock.tick(1); expect(getWinDimensions().innerHeight).to.exist;