# 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) beacon = request.GET.first(b"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 beacon is not None: register_ad_beacon = ( '''registerAdBeacon({ 'reserved.top_navigation_start': browserSignals.interestGroupOwner + '/fenced-frame/resources/beacon-store.py?type=reserved.top_navigation_start', 'reserved.top_navigation_commit': browserSignals.interestGroupOwner + '/fenced-frame/resources/beacon-store.py?type=reserved.top_navigation_commit', 'click': browserSignals.interestGroupOwner + '/fenced-frame/resources/beacon-store.py?type=click', }); ''' ) # 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)