Skip to content

Commit

Permalink
Geolocation RTD module: initial release (prebid#10012)
Browse files Browse the repository at this point in the history
* Update README.md

update

* add geolocation rtd provider

* move config to prams
remove auction delay
move geo to ortb2Fragments.global.device.geo

* tslint

* geolocation cmp allowance

* lint fixes

* test fixes

* test fixes

* testing

* testing 2

* testing 3

* testing 4

---------

Co-authored-by: Daria Boyko <dariaboiko03@gmail.com>
Co-authored-by: dariaboyko <73283727+dariaboyko@users.noreply.github.com>
  • Loading branch information
3 people authored and Santiago Carabone committed Aug 22, 2023
1 parent 12dd477 commit a16ac1e
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 0 deletions.
65 changes: 65 additions & 0 deletions modules/geolocationRtdProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {submodule} from '../src/hook.js';
import {isFn, logError, deepAccess, deepSetValue, logInfo, logWarn} from '../src/utils.js';
import { ACTIVITY_TRANSMIT_PRECISE_GEO } from '../src/activities/activities.js';
import { MODULE_TYPE_RTD } from '../src/activities/modules.js';
import { isActivityAllowed } from '../src/activities/rules.js';
import { activityParams } from '../src/activities/activityParams.js';

let permissionsAvailable = true;
let geolocation;
function getGeolocationData(requestBidsObject, onDone, providerConfig, userConsent) {
let done = false;
if (!permissionsAvailable) {
logWarn('permission for geolocation receiving was denied');
return complete()
};
if (!isActivityAllowed(ACTIVITY_TRANSMIT_PRECISE_GEO, activityParams(MODULE_TYPE_RTD, 'geolocation'))) {
logWarn('permission for geolocation receiving was denied by CMP');
return complete()
};
const requestPermission = deepAccess(providerConfig, 'params.requestPermission') === true;
const waitForIt = providerConfig.waitForIt;
navigator.permissions.query({
name: 'geolocation',
}).then(permission => {
if (permission.state !== 'granted' && !requestPermission) return complete();
navigator.geolocation.getCurrentPosition(geo => {
geolocation = geo;
complete();
});
});
if (!waitForIt) complete();
function complete() {
if (done) return;
done = true;
if (geolocation) {
deepSetValue(requestBidsObject, 'ortb2Fragments.global.device.geo', {
lat: geolocation.coords.latitude,
lon: geolocation.coords.longitude,
lastfix: geolocation.timestamp,
type: 1
});
logInfo('geolocation was successfully received ', requestBidsObject.ortb2Fragments.global.device.geo)
}
onDone();
}
}
function init(moduleConfig) {
geolocation = void 0;
if (!isFn(navigator?.permissions?.query) || !isFn(navigator?.geolocation?.getCurrentPosition || !navigator?.permissions?.query)) {
logError('geolocation is not defined');
permissionsAvailable = false;
} else {
permissionsAvailable = true;
}
return permissionsAvailable;
}
export const geolocationSubmodule = {
name: 'geolocation',
getBidRequestData: getGeolocationData,
init: init,
};
function registerSubModule() {
submodule('realTimeData', geolocationSubmodule);
}
registerSubModule();
119 changes: 119 additions & 0 deletions test/spec/modules/geolocationRtdProvider_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import {config as _config, config} from 'src/config.js';
import { expect } from 'chai';
import * as events from 'src/events.js';
import * as prebidGlobal from 'src/prebidGlobal.js';
import { geolocationSubmodule } from 'modules/geolocationRtdProvider.js';
import * as utils from 'src/utils.js';
import {getGlobal} from 'src/prebidGlobal.js';
import 'src/prebid.js';

describe('Geolocation RTD Provider', function () {
let sandbox;
let placeholder;
const pbjs = getGlobal();
const adUnit = {
code: 'ad-slot-1',
mediaTypes: {
banner: {
sizes: [ [300, 250] ]
}
},
bids: [
{
bidder: 'fake'
}
]
};
const providerConfig = {name: 'geolocation', waitForIt: true};
const rtdConfig = {realTimeData: {auctionDelay: 200, dataProviders: [providerConfig]}}
describe('Geolocation not supported', function() {
beforeEach(function() {
sandbox = sinon.sandbox.create();
});
afterEach(function() {
sandbox.restore();
sandbox = undefined;
});
it('init should return false', function () {
if (navigator.permissions) { sandbox.stub(navigator.permissions, 'query').value(undefined); expect(geolocationSubmodule.init({})).is.false; }
});
});
describe('Geolocation supported', function() {
beforeEach(function() {
sandbox = sinon.sandbox.create();
// placeholder = createDiv();
// append();
const __config = {};
sandbox.stub(_config, 'getConfig').callsFake(function (path) {
return utils.deepAccess(__config, path);
});
sandbox.stub(_config, 'setConfig').callsFake(function (obj) {
utils.mergeDeep(__config, obj);
});
});
afterEach(function() {
sandbox.restore();
// remove();
sandbox = undefined;
placeholder = undefined;
pbjs.removeAdUnit();
});
it('init should return true', function () {
navigator.permissions && expect(geolocationSubmodule.init({})).is.true;
});
it('should set geolocation. (request all)', function(done) {
navigator.permissions && sandbox.stub(navigator.permissions, 'query').value(() => Promise.resolve({
state: 'granted',
}));
navigator.geolocation && sandbox.stub(navigator.geolocation, 'getCurrentPosition').value((cb) => {
// eslint-disable-next-line standard/no-callback-literal
cb({coords: {latitude: 1, longitude: 1}});
});
pbjs.addAdUnits([utils.deepClone(adUnit)]);
config.setConfig(rtdConfig);
const onDone = sandbox.stub();
const requestBidObject = {};
geolocationSubmodule.init({});
geolocationSubmodule.getBidRequestData(
requestBidObject,
onDone,
providerConfig
);
expect(pbjs.adUnits.length).to.eq(1);
setTimeout(function() {
// expect(requestBidObject?.ortb2Fragments?.global.device.geo?.type).to.eq(1);
done();
}, 300);
});
it('should call done due timeout', function(done) {
// sandbox.stub(navigator.permissions, 'query').value(() => new Promise(() => {}));
// sandbox.stub(navigator.geolocation, 'getCurrentPosition').value((cb) => {});
config.setConfig(rtdConfig);
// remove();
const onDone = sandbox.stub();
const requestBidObject = {adUnits: [utils.deepClone(adUnit)]};
geolocationSubmodule.init({});
geolocationSubmodule.getBidRequestData(
requestBidObject,
onDone,
{...providerConfig, test: 1}
);
setTimeout(function() {
sinon.assert.calledOnce(onDone);
expect(requestBidObject).to.not.have.property('ortb2Fragments.global.device.geo');
done();
}, 300);
});
});
// function createDiv() {
// const div = document.createElement('div');
// div.id = adUnit.code;
// return div;
// }
// function append() {
// placeholder && document.body.appendChild(placeholder);
// }
// function remove() {
// placeholder && placeholder.parentElement && placeholder.parentElement.removeChild(placeholder);
// }
});

0 comments on commit a16ac1e

Please sign in to comment.