blob: 2c541bff346ebe4464f166ed0ebd9a8a5d68b8fe [file] [log] [blame]
# These functions are used by FLEDGE to determine the logic for the ad buyer.
# For our testing purposes, we only need the minimal amount of boilerplate
# code in place to allow them to be invoked properly and move the FLEDGE
# process along. The tests generally do usually not deal with reporting results,
# so we leave `reportWin` empty unless we need to call registerAdBeacon(). See
# `generateURNFromFledge` in "utils.js" to see how this file is used.
from wptserve.utils import isomorphic_decode
def main(request, response):
# Set up response headers.
headers = [
('Content-Type', 'Application/Javascript'),
('Ad-Auction-Allowed', 'true')
]
# Parse URL params.
requested_size = request.GET.first(b"requested-size", None)
ad_with_size = request.GET.first(b"ad-with-size", None)
automatic_beacon = request.GET.first(b"automatic-beacon", None)
# Use URL params to modify Javascript.
requested_size_check = ''
if requested_size is not None:
# request.GET stores URL keys and values in iso-8859-1 binary encoding. We
# have to decode the values back to a string to parse width/height. Don't
# bother sanitizing the size, because it is sanitized before auction logic
# runs already.
width, height = isomorphic_decode(requested_size).split('-')
requested_size_check = (
f'''
if (!(browserSignals.requestedSize.width === '{width}') &&
(browserSignals.requestedSize.height === '{height}')) {{
throw new Error('requestedSize missing/incorrect in browserSignals');
}}
'''
)
render_obj = 'ad.renderURL'
if ad_with_size is not None:
render_obj = '{ url: ad.renderURL, width: "100px", height: "50px" }'
component_render_obj = 'component.renderURL'
if ad_with_size is not None:
component_render_obj = (
'''{
url: component.renderURL,
width: "100px",
height: "50px"
}
'''
)
register_ad_beacon = ''
if automatic_beacon is not None:
register_ad_beacon = (
'''registerAdBeacon({
'reserved.top_navigation_start':
browserSignals.interestGroupOwner +
'/fenced-frame/resources/automatic-beacon-store.py',
'reserved.top_navigation_commit':
browserSignals.interestGroupOwner +
'/fenced-frame/resources/automatic-beacon-store.py',
});
'''
)
# Generate Javascript.
# Note: Python fstrings use double-brackets ( {{, }} ) to insert bracket
# literals instead of substitution sequences.
generate_bid = (
f'''function generateBid(
interestGroup,
auctionSignals,
perBuyerSignals,
trustedBiddingSignals,
browserSignals) {{
{requested_size_check}
const ad = interestGroup.ads[0];
// `auctionSignals` controls whether or not component auctions are
// allowed.
let allowComponentAuction = (typeof auctionSignals === 'string' &&
auctionSignals.includes('bidderAllowsComponentAuction'));
let result = {{
'ad': ad,
'bid': 1,
'render': {render_obj},
'allowComponentAuction': allowComponentAuction
}};
if (interestGroup.adComponents && interestGroup.adComponents.length > 0)
result.adComponents = interestGroup.adComponents.map((component) => {{
return {component_render_obj};
}});
return result;
}}
'''
)
report_win = (
f'''function reportWin(
auctionSignals,
perBuyerSignals,
sellerSignals,
browserSignals) {{
{register_ad_beacon}
return;
}}
'''
)
content = f'{generate_bid}\n{report_win}'
return (headers, content)