Skip to content

Commit

Permalink
Dynamic creatives: fix exception on rendering (prebid#11956)
Browse files Browse the repository at this point in the history
  • Loading branch information
dgirardi authored and mefjush committed Jul 19, 2024
1 parent f197432 commit 989609c
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 15 deletions.
9 changes: 6 additions & 3 deletions creative/crossDomain.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ function isPrebidWindow(win) {

export function renderer(win) {
let target = win.parent;
while (target !== win.top && !isPrebidWindow(target)) {
target = target.parent;
try {
while (target !== win.top && !isPrebidWindow(target)) {
target = target.parent;
}
if (!isPrebidWindow(target)) target = win.parent;
} catch (e) {
}
if (!isPrebidWindow(target)) target = win.parent;

return function ({adId, pubUrl, clickUrl}) {
const pubDomain = new URL(pubUrl, window.location).origin;
Expand Down
2 changes: 1 addition & 1 deletion integrationExamples/gpt/x-domain/creative.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// creative will be rendered, e.g. GAM delivering a SafeFrame

// this code is autogenerated, also available in 'build/creative/creative.js'
<script>(()=>{"use strict";const e="Prebid Event",n=(()=>{const e={frameBorder:0,scrolling:"no",marginHeight:0,marginWidth:0,topMargin:0,leftMargin:0,allowTransparency:"true"};return(n,t)=>{const r=n.createElement("iframe");return Object.entries(Object.assign({},t,e)).forEach((([e,n])=>r.setAttribute(e,n))),r}})();function t(e){return!!e.frames.__pb_locator__}window.pbRender=function(r){let o=r.parent;for(;o!==r.top&&!t(o);)o=o.parent;return t(o)||(o=r.parent),function({adId:t,pubUrl:s,clickUrl:i}){const a=new URL(s,window.location).origin;function c(e,n,r){const s=new MessageChannel;s.port1.onmessage=l(r),o.postMessage(JSON.stringify(Object.assign({message:e,adId:t},n)),a,[s.port2])}function d(n){c(e,{event:"adRenderFailed",info:{reason:n?.reason||"exception",message:n?.message}}),n?.stack&&console.error(n)}function l(e){return function(){try{return e.apply(this,arguments)}catch(e){d(e)}}}c("Prebid Request",{options:{clickUrl:i}},(function(o){let s;try{s=JSON.parse(o.data)}catch(e){return}if("Prebid Response"===s.message&&s.adId===t){const t=n(r.document,{width:0,height:0,style:"display: none",srcdoc:`<script>${s.renderer}<\/script>`});t.onload=l((function(){const o=t.contentWindow;o.Promise.resolve(o.render(s,{sendMessage:c,mkFrame:n},r)).then((()=>c(e,{event:"adRenderSucceeded"})),d)})),r.document.body.appendChild(t)}}))}}(window)})();</script>
<script>!function(){"use strict";const e="Prebid Event",n=(()=>{const e={frameBorder:0,scrolling:"no",marginHeight:0,marginWidth:0,topMargin:0,leftMargin:0,allowTransparency:"true"};return(n,t)=>{const r=n.createElement("iframe");return Object.entries(Object.assign({},t,e)).forEach((([e,n])=>r.setAttribute(e,n))),r}})();function t(e){return!!e.frames.__pb_locator__}window.pbRender=function(r){let o=r.parent;try{for(;o!==r.top&&!t(o);)o=o.parent;t(o)||(o=r.parent)}catch(e){}return function({adId:t,pubUrl:s,clickUrl:i}){const c=new URL(s,window.location).origin;function a(e,n,r){const s=new MessageChannel;s.port1.onmessage=u(r),o.postMessage(JSON.stringify(Object.assign({message:e,adId:t},n)),c,[s.port2])}function d(n){a(e,{event:"adRenderFailed",info:{reason:n?.reason||"exception",message:n?.message}}),n?.stack&&console.error(n)}function u(e){return function(){try{return e.apply(this,arguments)}catch(e){d(e)}}}a("Prebid Request",{options:{clickUrl:i}},(function(o){let s;try{s=JSON.parse(o.data)}catch(e){return}if("Prebid Response"===s.message&&s.adId===t){const t=n(r.document,{width:0,height:0,style:"display: none",srcdoc:`<script>${s.renderer}<\/script>`});t.onload=u((function(){const o=t.contentWindow;o.Promise.resolve(o.render(s,{sendMessage:a,mkFrame:n},r)).then((()=>a(e,{event:"adRenderSucceeded"})),d)})),r.document.body.appendChild(t)}}))}}(window)}();</script>

<script>
pbRender({
Expand Down
2 changes: 1 addition & 1 deletion libraries/creative-renderer-display/renderer.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion libraries/creative-renderer-native/renderer.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 26 additions & 9 deletions test/spec/creative/crossDomainCreative_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,6 @@ describe('cross-domain creative', () => {
expect(messages[0].targetOrigin).to.eql('https://domain.com:123')
});

it('posts to first parent if no __pb_locator__ can be found', () => {
delete win.parent.frames['__pb_locator__'];
renderAd({pubUrl: 'https://www.example.com'});
expect(messages.length).to.eql(1);
})

describe('when there are multiple ancestors', () => {
let target;
beforeEach(() => {
Expand All @@ -88,16 +82,39 @@ describe('cross-domain creative', () => {
parent: {
...target,
parent: {
top,
frames: {'__pb_locator__': {}},
top
parent: {
top,
frames: {}
},
}
}
}
})
it('posts message to the first ancestor with __pb_locator__ child', () => {
Object.entries({
'throws': () => { throw new DOMException() },
'does not throw': () => ({})
}).forEach(([t, getFrames]) => {
describe(`when an ancestor ${t}`, () => {
beforeEach(() => {
Object.defineProperty(win.parent.parent.parent.parent, 'frames', {get: getFrames})
})
it('posts message to the first ancestor with __pb_locator__ child', () => {
renderAd({pubUrl: 'https://www.example.com'});
expect(messages.length).to.eql(1);
});
})
})
it('posts to first restricted parent, if __pb_locator__ cannot be found', () => {
Object.defineProperty(win.parent.parent.parent, 'frames', {
get() {
throw new DOMException();
}
});
renderAd({pubUrl: 'https://www.example.com'});
expect(messages.length).to.eql(1);
});
})
})

it('generates request message with adId and clickUrl', () => {
Expand Down

0 comments on commit 989609c

Please sign in to comment.