get-interest-group-auction-data.https.window.js (31339B)
1 // META: script=/resources/testdriver.js 2 // META: script=/resources/testdriver-vendor.js 3 // META: script=/common/utils.js 4 // META: script=resources/ba-fledge-util.sub.js 5 // META: script=resources/fledge-util.sub.js 6 // META: script=third_party/cbor-js/cbor.js 7 // META: script=/common/subset-tests.js 8 // META: timeout=long 9 // META: variant=?1-4 10 // META: variant=?5-8 11 // META: variant=?9-12 12 // META: variant=?13-16 13 // META: variant=?17-last 14 15 "use strict"; 16 17 // These tests focus on the navigator.getInterestGroupAdAuctionData() method. 18 19 // Checks various fields for decoded InterestGroupAdAuctionData that's 20 // one IG owned by this origin, and returns that IG's info. 21 function validateWithOneIg(decoded) { 22 assert_equals(decoded.message.version, 0); 23 assert_equals(decoded.message.publisher, window.location.hostname); 24 assert_equals(typeof decoded.message.generationId, 'string'); 25 let igMapKeys = Object.getOwnPropertyNames(decoded.message.interestGroups); 26 assert_array_equals(igMapKeys, [window.location.origin]); 27 let igInfo = decoded.message.interestGroups[window.location.origin]; 28 assert_true(igInfo instanceof Array); 29 assert_equals(igInfo.length, 1, 'number of IGs'); 30 return igInfo[0]; 31 } 32 33 subsetTest(promise_test, async test => { 34 const result = await navigator.getInterestGroupAdAuctionData({ 35 coordinatorOrigin: await BA.configureCoordinator(), 36 seller: window.location.origin 37 }); 38 assert_true(result.requestId !== null); 39 assert_true(result.request.length === 0); 40 }, 'getInterestGroupAdAuctionData() with no interest groups returns a zero length result.'); 41 42 async function testInvalidConfig(test, configObj, desc) { 43 if (!configObj.coordinatorOrigin) { 44 configObj.coordinatorOrigin = await BA.configureCoordinator(); 45 } 46 await promise_rejects_js( 47 test, TypeError, navigator.getInterestGroupAdAuctionData(configObj), 48 desc); 49 } 50 51 subsetTest(promise_test, async test => { 52 await testInvalidConfig(test, {}, 'no seller'); 53 await testInvalidConfig(test, {seller: 'example'}, 'invalid seller 1'); 54 await testInvalidConfig( 55 test, {seller: 'http://example.org'}, 'invalid seller 2'); 56 await testInvalidConfig( 57 test, {seller: 'https://example.org', coordinatorOrigin: 'example'}, 58 'invalid coordinator 1'); 59 await testInvalidConfig( 60 test, {seller: 'https://example.org', coordinatorOrigin: 'example.org'}, 61 'invalid coordinator 2'); 62 63 await testInvalidConfig( 64 test, {seller: 'https://example.org', perBuyerConfig: {'a': {}}}, 65 'invalid buyer 1'); 66 67 await testInvalidConfig( 68 test, 69 {seller: 'https://example.org', perBuyerConfig: {'http://a.com': {}}}, 70 'invalid buyer 2'); 71 72 await testInvalidConfig( 73 test, { 74 seller: 'https://example.org', 75 perBuyerConfig: {'https://a.com': {}, 'http://b.com': {}} 76 }, 77 'invalid buyer 3'); 78 79 await testInvalidConfig( 80 test, { 81 seller: 'https://example.org', 82 perBuyerConfig: {'https://a.com': {}, 'https://b.com': {}} 83 }, 84 'missing size info w/per-buyer config 1'); 85 86 await testInvalidConfig( 87 test, { 88 seller: 'https://example.org', 89 perBuyerConfig: 90 {'https://a.com': {targetSize: 400}, 'https://b.com': {}} 91 }, 92 'missing size info w/per-buyer config 2'); 93 94 // These two actually succeed. 95 let result = await navigator.getInterestGroupAdAuctionData({ 96 coordinatorOrigin: await BA.configureCoordinator(), 97 seller: 'https://example.org', 98 perBuyerConfig: 99 {'https://a.com': {targetSize: 400}, 'https://b.com': {targetSize: 500}} 100 }); 101 assert_true(result.requestId !== null); 102 103 result = await navigator.getInterestGroupAdAuctionData({ 104 coordinatorOrigin: await BA.configureCoordinator(), 105 seller: 'https://example.org', 106 perBuyerConfig: {'https://a.com': {targetSize: 400}, 'https://b.com': {}}, 107 requestSize: 5000 108 }); 109 assert_true(result.requestId !== null); 110 }, 'getInterestGroupAdAuctionData() config checks'); 111 112 subsetTest(promise_test, async test => { 113 const uuid = generateUuid(test); 114 await joinInterestGroup(test, uuid); 115 116 const result = await navigator.getInterestGroupAdAuctionData({ 117 coordinatorOrigin: await BA.configureCoordinator(), 118 seller: window.location.origin 119 }); 120 assert_true(result.requestId !== null); 121 assert_true(result.request.length > 0); 122 123 let decoded = await BA.decodeInterestGroupData(result.request); 124 125 // Check that the required field and one IG (but no ad data) are here, 126 // since we neither provided adRenderIds or asked for full data to be 127 // included. 128 let ig = validateWithOneIg(decoded); 129 assert_equals(ig.name, DEFAULT_INTEREST_GROUP_NAME); 130 assert_array_equals(ig.ads, []); 131 assert_equals(ig.browserSignals.joinCount, 1, 'joinCount'); 132 assert_equals(ig.browserSignals.bidCount, 0, 'bidCount'); 133 assert_array_equals(ig.browserSignals.prevWins, []); 134 }, 'getInterestGroupAdAuctionData() with one interest group returns a valid result.'); 135 136 subsetTest(promise_test, async test => { 137 const uuid = generateUuid(test); 138 await joinInterestGroup(test, uuid, { 139 ads: [ 140 {renderURL: createRenderURL(uuid) + '&a', adRenderId: 'a'}, 141 {renderURL: createRenderURL(uuid) + '&a', adRenderId: 'b'} 142 ] 143 }); 144 145 const result = await navigator.getInterestGroupAdAuctionData({ 146 coordinatorOrigin: await BA.configureCoordinator(), 147 seller: window.location.origin 148 }); 149 assert_true(result.requestId !== null); 150 assert_true(result.request.length > 0); 151 152 let decoded = await BA.decodeInterestGroupData(result.request); 153 let ig = validateWithOneIg(decoded); 154 155 // This ig should have two ads with adRenderIds, but not URLs. 156 assert_equals(ig.name, DEFAULT_INTEREST_GROUP_NAME); 157 assert_array_equals(ig.ads, ['a', 'b']); 158 assert_equals(ig.browserSignals.joinCount, 1, 'joinCount'); 159 assert_equals(ig.browserSignals.bidCount, 0, 'bidCount'); 160 assert_array_equals(ig.browserSignals.prevWins, []); 161 }, 'getInterestGroupAdAuctionData() with one interest group with two ads w/renderIds.'); 162 163 subsetTest(promise_test, async test => { 164 const uuid = generateUuid(test); 165 await joinInterestGroup(test, uuid, { 166 auctionServerRequestFlags: ['omit-ads'], 167 ads: [ 168 {renderURL: createRenderURL(uuid) + '&a', adRenderId: 'a'}, 169 {renderURL: createRenderURL(uuid) + '&a', adRenderId: 'b'} 170 ] 171 }); 172 173 const result = await navigator.getInterestGroupAdAuctionData({ 174 coordinatorOrigin: await BA.configureCoordinator(), 175 seller: window.location.origin 176 }); 177 assert_true(result.requestId !== null); 178 assert_true(result.request.length > 0); 179 180 let decoded = await BA.decodeInterestGroupData(result.request); 181 let ig = validateWithOneIg(decoded); 182 183 assert_equals(ig.name, DEFAULT_INTEREST_GROUP_NAME); 184 assert_not_own_property(ig, 'ads', 'no ads expected'); 185 assert_equals(ig.browserSignals.joinCount, 1, 'joinCount'); 186 }, 'getInterestGroupAdAuctionData() with one interest group with two ads w/renderIds and omit-ads.'); 187 188 subsetTest(promise_test, async test => { 189 const uuid = generateUuid(test); 190 191 const adsArray = [ 192 {renderURL: createRenderURL(uuid) + '&a', adRenderId: 'a'}, 193 {renderURL: createRenderURL(uuid) + '&a', adRenderId: 'b'} 194 ]; 195 await joinInterestGroup( 196 test, uuid, 197 {auctionServerRequestFlags: ['include-full-ads'], ads: adsArray}); 198 199 const result = await navigator.getInterestGroupAdAuctionData({ 200 coordinatorOrigin: await BA.configureCoordinator(), 201 seller: window.location.origin 202 }); 203 assert_true(result.requestId !== null); 204 assert_true(result.request.length > 0); 205 206 let decoded = await BA.decodeInterestGroupData(result.request); 207 let ig = validateWithOneIg(decoded); 208 209 // Since include-full-ads is on, this gets entire objects, not just 210 // adRenderId. 211 assert_equals(ig.name, DEFAULT_INTEREST_GROUP_NAME); 212 assert_equals(ig.ads.length, 2, '# of ads'); 213 assert_equals(ig.ads[0].renderURL, adsArray[0].renderURL, 'renderURL 0'); 214 assert_equals(ig.ads[1].renderURL, adsArray[1].renderURL, 'renderURL 1'); 215 assert_equals(ig.ads[0].adRenderId, adsArray[0].adRenderId, 'adRenderId 0'); 216 assert_equals(ig.ads[1].adRenderId, adsArray[1].adRenderId, 'adRenderId 1'); 217 assert_equals(ig.browserSignals.joinCount, 1, 'joinCount'); 218 }, 'getInterestGroupAdAuctionData() with one interest group with two ads w/renderIds and include-full-ads.'); 219 220 // Returns an AuctionAdInterestGroup that sets all fields that can be exported 221 // via getInterestGroupAdAuctionData(). 222 function makeTemplateIgConfig(uuid) { 223 const adsArray = [ 224 { 225 renderURL: createRenderURL(uuid) + '&a', 226 adRenderId: 'a', 227 metadata: 'ada', 228 sizeGroup: 'small' 229 }, 230 { 231 renderURL: createRenderURL(uuid) + '&b', 232 adRenderId: 'b', 233 metadata: 'adb', 234 sizeGroup: 'big' 235 } 236 ]; 237 const adComponentsArray = [ 238 { 239 renderURL: 'https://example.org/ca', 240 adRenderId: 'ca', 241 metadata: 'compa', 242 sizeGroup: 'big' 243 }, 244 { 245 renderURL: 'https://example.org/cb', 246 adRenderId: 'cb', 247 metadata: 'compb', 248 sizeGroup: 'small' 249 }, 250 { 251 renderURL: 'https://example.org/cc', 252 adRenderId: 'cc', 253 metadata: 'compc', 254 sizeGroup: 'big' 255 }, 256 ]; 257 return { 258 ads: adsArray, 259 adComponents: adComponentsArray, 260 adSizes: { 261 's': {width: '100px', height: '30px'}, 262 'xl': {width: '1000px', height: '300px'} 263 }, 264 sizeGroups: {'small': ['s'], 'big': ['xl']}, 265 trustedBiddingSignalsKeys: ['alpha', 'beta'], 266 userBiddingSignals: 14 267 }; 268 } 269 270 subsetTest(promise_test, async test => { 271 const uuid = generateUuid(test); 272 const igConfig = makeTemplateIgConfig(uuid); 273 igConfig.auctionServerRequestFlags = ['include-full-ads']; 274 await joinInterestGroup(test, uuid, igConfig); 275 276 const result = await navigator.getInterestGroupAdAuctionData({ 277 coordinatorOrigin: await BA.configureCoordinator(), 278 seller: window.location.origin 279 }); 280 assert_true(result.requestId !== null); 281 assert_true(result.request.length > 0); 282 283 let decoded = await BA.decodeInterestGroupData(result.request); 284 let ig = validateWithOneIg(decoded); 285 286 assert_equals(ig.name, DEFAULT_INTEREST_GROUP_NAME); 287 assert_true(ig.ads instanceof Array); 288 assert_equals(ig.ads.length, 2, '# of ads'); 289 assert_equals(ig.ads[0].renderURL, igConfig.ads[0].renderURL, 'renderURL 0'); 290 assert_equals(ig.ads[1].renderURL, igConfig.ads[1].renderURL, 'renderURL 1'); 291 assert_equals(ig.ads[0].adRenderId, 'a', 'adRenderId 0'); 292 assert_equals(ig.ads[1].adRenderId, 'b', 'adRenderId 1'); 293 assert_equals(ig.ads[0].metadata, '"ada"', 'metadata 0'); 294 assert_equals(ig.ads[1].metadata, '"adb"', 'metadata 1'); 295 assert_equals(ig.ads[0].sizeGroup, 'small', 'sizegroup 0'); 296 assert_equals(ig.ads[1].sizeGroup, 'big', 'sizegroup 1'); 297 298 assert_true(ig.components instanceof Array); 299 assert_equals(ig.components.length, 3, '# of component ads'); 300 assert_equals( 301 ig.components[0].renderURL, igConfig.adComponents[0].renderURL, 302 'component renderURL 0'); 303 assert_equals( 304 ig.components[1].renderURL, igConfig.adComponents[1].renderURL, 305 'component renderURL 1'); 306 assert_equals( 307 ig.components[2].renderURL, igConfig.adComponents[2].renderURL, 308 'component renderURL 2'); 309 assert_equals(ig.components[0].adRenderId, 'ca', 'component adRenderId 0'); 310 assert_equals(ig.components[1].adRenderId, 'cb', 'component adRenderId 1'); 311 assert_equals(ig.components[2].adRenderId, 'cc', 'component adRenderId 2'); 312 assert_equals(ig.components[0].metadata, '"compa"', 'component metadata 0'); 313 assert_equals(ig.components[1].metadata, '"compb"', 'component metadata 1'); 314 assert_equals(ig.components[2].metadata, '"compc"', 'component metadata 2'); 315 assert_equals(ig.components[0].sizeGroup, 'big', 'component sizegroup 0'); 316 assert_equals(ig.components[1].sizeGroup, 'small', 'component sizegroup 1'); 317 assert_equals(ig.components[2].sizeGroup, 'big', 'component sizegroup 2'); 318 319 assert_true(ig.biddingSignalsKeys instanceof Array); 320 assert_array_equals(ig.biddingSignalsKeys, ['alpha', 'beta']); 321 assert_equals(ig.userBiddingSignals, '14'); 322 }, 'getInterestGroupAdAuctionData() all IG data fields, with include-full-ads'); 323 324 subsetTest(promise_test, async test => { 325 const uuid = generateUuid(test); 326 const igConfig = makeTemplateIgConfig(uuid); 327 await joinInterestGroup(test, uuid, igConfig); 328 329 const result = await navigator.getInterestGroupAdAuctionData({ 330 coordinatorOrigin: await BA.configureCoordinator(), 331 seller: window.location.origin 332 }); 333 assert_true(result.requestId !== null); 334 assert_true(result.request.length > 0); 335 336 let decoded = await BA.decodeInterestGroupData(result.request); 337 let ig = validateWithOneIg(decoded); 338 339 assert_equals(ig.name, DEFAULT_INTEREST_GROUP_NAME); 340 assert_array_equals(ig.ads, ['a', 'b']); 341 342 assert_true(ig.components instanceof Array); 343 assert_array_equals(ig.ads, ['a', 'b']); 344 assert_array_equals(ig.components, ['ca', 'cb', 'cc']); 345 346 assert_array_equals(ig.biddingSignalsKeys, ['alpha', 'beta']); 347 assert_equals(ig.userBiddingSignals, '14'); 348 }, 'getInterestGroupAdAuctionData() all IG data fields, w/o include-full-ads'); 349 350 subsetTest(promise_test, async test => { 351 const uuid = generateUuid(test); 352 353 const igConfig = makeTemplateIgConfig(uuid); 354 igConfig.auctionServerRequestFlags = ['omit-user-bidding-signals']; 355 await joinInterestGroup(test, uuid, igConfig); 356 357 const result = await navigator.getInterestGroupAdAuctionData({ 358 coordinatorOrigin: await BA.configureCoordinator(), 359 seller: window.location.origin 360 }); 361 assert_true(result.requestId !== null); 362 assert_true(result.request.length > 0); 363 364 let decoded = await BA.decodeInterestGroupData(result.request); 365 let ig = validateWithOneIg(decoded); 366 367 assert_equals(ig.name, DEFAULT_INTEREST_GROUP_NAME); 368 assert_array_equals(ig.ads, ['a', 'b']); 369 370 assert_true(ig.components instanceof Array); 371 assert_array_equals(ig.ads, ['a', 'b']); 372 assert_array_equals(ig.components, ['ca', 'cb', 'cc']); 373 374 assert_array_equals(ig.biddingSignalsKeys, ['alpha', 'beta']); 375 assert_false('userBiddingSignals' in ig, 'userBiddingSignals'); 376 }, 'getInterestGroupAdAuctionData() all IG data fields, with omit-user-bidding-signals'); 377 378 subsetTest(promise_test, async test => { 379 const uuid = generateUuid(test); 380 381 const igConfig = makeTemplateIgConfig(uuid); 382 383 // Join twice. 384 await joinInterestGroup(test, uuid, igConfig); 385 await joinInterestGroup(test, uuid, igConfig); 386 387 // And run an auction. This is a local auction, not a B&A one, run to update 388 // bid/win stats. 389 await runBasicFledgeAuctionAndNavigate(test, uuid); 390 await waitForObservedRequests( 391 uuid, [createBidderReportURL(uuid), createSellerReportURL(uuid)]); 392 393 const result = await navigator.getInterestGroupAdAuctionData({ 394 coordinatorOrigin: await BA.configureCoordinator(), 395 seller: window.location.origin 396 }); 397 assert_true(result.requestId !== null); 398 assert_true(result.request.length > 0); 399 400 let decoded = await BA.decodeInterestGroupData(result.request); 401 let ig = validateWithOneIg(decoded); 402 assert_equals(ig.browserSignals.joinCount, 2, 'joinCount'); 403 assert_equals(ig.browserSignals.bidCount, 1, 'bidCount'); 404 405 // RecencyMs is the # of milliseconds since the join. We can't exactly say 406 // what it is, but it shouldn't be too huge. 407 assert_true(typeof ig.browserSignals.recencyMs === 'number'); 408 assert_between_inclusive( 409 ig.browserSignals.recencyMs, 0, 60000, 410 'RecencyMs is between 0 and 60 seconds'); 411 // It's also supposed to be an integer. 412 assert_equals( 413 ig.browserSignals.recencyMs, Math.round(ig.browserSignals.recencyMs), 414 'RecencyMs is an integer'); 415 416 // One win. The format here depends highly on whether full ads are used or 417 // not. 418 assert_true( 419 ig.browserSignals.prevWins instanceof Array, 'prevWins is an array'); 420 assert_equals(ig.browserSignals.prevWins.length, 1, 'prevWins length'); 421 assert_true( 422 ig.browserSignals.prevWins[0] instanceof Array, 423 'prevWins[0] is an array'); 424 assert_equals(ig.browserSignals.prevWins[0].length, 2, 'prevWins[0] length'); 425 426 // prevWins[0][0] is the time delta in second again. 427 let prevWinTime = ig.browserSignals.prevWins[0][0]; 428 assert_true(typeof prevWinTime === 'number'); 429 assert_between_inclusive( 430 prevWinTime, 0, 60, 'prevWinTime is between 0 and 60 seconds'); 431 // It's also supposed to be an integer. 432 assert_equals( 433 prevWinTime, Math.round(prevWinTime), 'prevWinTime is an integer'); 434 435 // prevWins[0][1] is the adRenderId of the winner. 436 assert_equals(ig.browserSignals.prevWins[0][1], 'a'); 437 }, 'getInterestGroupAdAuctionData() browserSignals'); 438 439 subsetTest(promise_test, async test => { 440 const uuid = generateUuid(test); 441 442 const igConfig = makeTemplateIgConfig(uuid); 443 igConfig.auctionServerRequestFlags = ['include-full-ads']; 444 445 // Join twice. 446 await joinInterestGroup(test, uuid, igConfig); 447 await joinInterestGroup(test, uuid, igConfig); 448 449 // And run an auction. This is a local auction, not a B&A one, run to update 450 // bid/win stats. 451 await runBasicFledgeAuctionAndNavigate(test, uuid); 452 await waitForObservedRequests( 453 uuid, [createBidderReportURL(uuid), createSellerReportURL(uuid)]); 454 455 const result = await navigator.getInterestGroupAdAuctionData({ 456 coordinatorOrigin: await BA.configureCoordinator(), 457 seller: window.location.origin 458 }); 459 assert_true(result.requestId !== null); 460 assert_true(result.request.length > 0); 461 462 let decoded = await BA.decodeInterestGroupData(result.request); 463 let ig = validateWithOneIg(decoded); 464 assert_equals(ig.browserSignals.joinCount, 2, 'joinCount'); 465 assert_equals(ig.browserSignals.bidCount, 1, 'bidCount'); 466 467 // RecencyMs is the # of milliseconds since the join. We can't exactly say 468 // what it is, but it shouldn't be too huge. 469 assert_true(typeof ig.browserSignals.recencyMs === 'number'); 470 assert_between_inclusive( 471 ig.browserSignals.recencyMs, 0, 60000, 472 'RecencyMs is between 0 and 60 seconds'); 473 // It's also supposed to be an integer. 474 assert_equals( 475 ig.browserSignals.recencyMs, Math.round(ig.browserSignals.recencyMs), 476 'RecencyMs is an integer'); 477 478 // One win. The format here depends highly on whether full ads are used or 479 // not. 480 assert_true( 481 ig.browserSignals.prevWins instanceof Array, 'prevWins is an array'); 482 assert_equals(ig.browserSignals.prevWins.length, 1, 'prevWins length'); 483 assert_true( 484 ig.browserSignals.prevWins[0] instanceof Array, 485 'prevWins[0] is an array'); 486 assert_equals(ig.browserSignals.prevWins[0].length, 2, 'prevWins[0] length'); 487 488 // prevWins[0][0] is the time delta in second again. 489 let prevWinTime = ig.browserSignals.prevWins[0][0]; 490 assert_true(typeof prevWinTime === 'number'); 491 assert_between_inclusive( 492 prevWinTime, 0, 60, 'prevWinTime is between 0 and 60 seconds'); 493 // It's also supposed to be an integer. 494 assert_equals( 495 prevWinTime, Math.round(prevWinTime), 'prevWinTime is an integer'); 496 497 // prevWins[0][1] is an ad object w/include-full-ads on (with renderURL, 498 // metadata, and adRenderId). 499 let prevWinAd = ig.browserSignals.prevWins[0][1]; 500 assert_equals( 501 prevWinAd.renderURL, igConfig.ads[0].renderURL, 'prevWin ad renderURL'); 502 assert_equals(prevWinAd.metadata, '"ada"', 'prevWin ad metadata'); 503 assert_equals(prevWinAd.adRenderId, 'a', 'prevWin ad adRenderId'); 504 }, 'getInterestGroupAdAuctionData() browserSignals with include-full-ads'); 505 506 subsetTest(promise_test, async test => { 507 const uuid = generateUuid(test); 508 509 const igTemplate = makeTemplateIgConfig(uuid); 510 await joinInterestGroup(test, uuid, {...igTemplate, name: 'first'}); 511 await joinInterestGroup(test, uuid, {...igTemplate, name: 'second'}); 512 513 const result = await navigator.getInterestGroupAdAuctionData({ 514 coordinatorOrigin: await BA.configureCoordinator(), 515 seller: window.location.origin 516 }); 517 assert_true(result.requestId !== null); 518 assert_true(result.request.length > 0); 519 520 let decoded = await BA.decodeInterestGroupData(result.request); 521 assert_equals(decoded.message.version, 0); 522 assert_equals(decoded.message.publisher, window.location.hostname); 523 assert_equals(typeof decoded.message.generationId, 'string'); 524 525 let origin = window.location.origin; 526 let igMapKeys = Object.getOwnPropertyNames(decoded.message.interestGroups); 527 assert_array_equals(igMapKeys, [origin]); 528 assert_equals(decoded.message.interestGroups[origin].length, 2); 529 let names = [ 530 decoded.message.interestGroups[origin][0].name, 531 decoded.message.interestGroups[origin][1].name 532 ]; 533 assert_array_equals(names.sort(), ['first', 'second']); 534 }, 'getInterestGroupAdAuctionData() with multiple interest groups'); 535 536 async function joinCrossOriginIG(test, uuid, origin, name) { 537 let iframe = await createIframe(test, origin, 'join-ad-interest-group'); 538 await runInFrame( 539 test, iframe, 540 `await joinInterestGroup(test_instance, "${uuid}", {name: "${name}"});`); 541 } 542 543 subsetTest(promise_test, async test => { 544 const uuid = generateUuid(test); 545 546 await joinCrossOriginIG(test, uuid, OTHER_ORIGIN1, 'o1'); 547 await joinCrossOriginIG(test, uuid, OTHER_ORIGIN2, 'o2'); 548 await joinCrossOriginIG(test, uuid, OTHER_ORIGIN3, 'o3'); 549 await joinCrossOriginIG(test, uuid, OTHER_ORIGIN4, 'o4'); 550 551 const result = await navigator.getInterestGroupAdAuctionData({ 552 coordinatorOrigin: await BA.configureCoordinator(), 553 seller: window.location.origin 554 }); 555 assert_true(result.requestId !== null); 556 assert_true(result.request.length > 0); 557 558 let decoded = await BA.decodeInterestGroupData(result.request); 559 assert_equals(decoded.message.version, 0); 560 assert_equals(decoded.message.publisher, window.location.hostname); 561 assert_equals(typeof decoded.message.generationId, 'string'); 562 let igMapKeys = Object.getOwnPropertyNames(decoded.message.interestGroups); 563 assert_array_equals( 564 igMapKeys.sort(), 565 [OTHER_ORIGIN1, OTHER_ORIGIN2, OTHER_ORIGIN3, OTHER_ORIGIN4].sort()); 566 assert_equals(decoded.message.interestGroups[OTHER_ORIGIN1].length, 1); 567 assert_equals(decoded.message.interestGroups[OTHER_ORIGIN1][0].name, 'o1'); 568 assert_equals(decoded.message.interestGroups[OTHER_ORIGIN2].length, 1); 569 assert_equals(decoded.message.interestGroups[OTHER_ORIGIN2][0].name, 'o2'); 570 assert_equals(decoded.message.interestGroups[OTHER_ORIGIN3].length, 1); 571 assert_equals(decoded.message.interestGroups[OTHER_ORIGIN3][0].name, 'o3'); 572 assert_equals(decoded.message.interestGroups[OTHER_ORIGIN4].length, 1); 573 assert_equals(decoded.message.interestGroups[OTHER_ORIGIN4][0].name, 'o4'); 574 }, 'getInterestGroupAdAuctionData() with multiple buyers'); 575 576 subsetTest(promise_test, async test => { 577 const uuid = generateUuid(test); 578 579 await joinCrossOriginIG(test, uuid, OTHER_ORIGIN1, 'o1'); 580 await joinCrossOriginIG(test, uuid, OTHER_ORIGIN2, 'o2'); 581 await joinCrossOriginIG(test, uuid, OTHER_ORIGIN3, 'o3'); 582 await joinCrossOriginIG(test, uuid, OTHER_ORIGIN4, 'o4'); 583 584 let config = { 585 coordinatorOrigin: await BA.configureCoordinator(), 586 seller: window.location.origin, 587 perBuyerConfig: {}, 588 requestSize: 5000 589 }; 590 config.perBuyerConfig[OTHER_ORIGIN2] = {}; 591 config.perBuyerConfig[OTHER_ORIGIN3] = {}; 592 const result = await navigator.getInterestGroupAdAuctionData(config); 593 assert_true(result.requestId !== null); 594 assert_true(result.request.length > 0); 595 596 let decoded = await BA.decodeInterestGroupData(result.request); 597 assert_equals(decoded.message.version, 0); 598 assert_equals(decoded.message.publisher, window.location.hostname); 599 assert_equals(typeof decoded.message.generationId, 'string'); 600 let igMapKeys = Object.getOwnPropertyNames(decoded.message.interestGroups); 601 assert_array_equals(igMapKeys.sort(), [OTHER_ORIGIN2, OTHER_ORIGIN3].sort()); 602 assert_equals(decoded.message.interestGroups[OTHER_ORIGIN2].length, 1); 603 assert_equals(decoded.message.interestGroups[OTHER_ORIGIN2][0].name, 'o2'); 604 assert_equals(decoded.message.interestGroups[OTHER_ORIGIN3].length, 1); 605 assert_equals(decoded.message.interestGroups[OTHER_ORIGIN3][0].name, 'o3'); 606 }, 'getInterestGroupAdAuctionData() uses perBuyerConfig to select buyers'); 607 608 subsetTest(promise_test, async test => { 609 const uuid = generateUuid(test); 610 await joinInterestGroup(test, uuid); 611 612 const result = await navigator.getInterestGroupAdAuctionData({ 613 coordinatorOrigin: await BA.configureCoordinator(), 614 seller: window.location.origin 615 }); 616 assert_true(result.requestId !== null); 617 assert_true(result.request.length > 0); 618 619 let decoded = await BA.decodeInterestGroupData(result.request); 620 621 assert_own_property(decoded.message, 'enforceKAnon'); 622 assert_equals(decoded.message.enforceKAnon, true); 623 }, 'getInterestGroupAdAuctionData() requests k-anon.'); 624 625 626 /************************************************************************* 627 * Tests for the multi-seller variant of the API 628 *************************************************************************/ 629 630 async function validateForSeller(adAuctionData, seller) { 631 assert_equals(adAuctionData.seller, seller); 632 assert_not_own_property(adAuctionData, 'error'); 633 assert_own_property(adAuctionData, 'request'); 634 assert_true(adAuctionData.request.length > 0); 635 636 let decoded = await BA.decodeInterestGroupData(adAuctionData.request); 637 let ig = validateWithOneIg(decoded); 638 639 assert_equals(ig.name, DEFAULT_INTEREST_GROUP_NAME); 640 assert_array_equals(ig.ads, ['a', 'b']); 641 642 assert_true(ig.components instanceof Array); 643 assert_array_equals(ig.components, ['ca', 'cb', 'cc']); 644 645 assert_array_equals(ig.biddingSignalsKeys, ['alpha', 'beta']); 646 assert_equals(ig.userBiddingSignals, '14'); 647 } 648 649 subsetTest(promise_test, async test => { 650 const uuid = generateUuid(test); 651 const igConfig = makeTemplateIgConfig(uuid); 652 await joinInterestGroup(test, uuid, igConfig); 653 654 const result = await navigator.getInterestGroupAdAuctionData({ 655 sellers: [{ 656 coordinatorOrigin: await BA.configureCoordinator(), 657 seller: window.location.origin, 658 }] 659 }); 660 661 assert_true(result.requestId !== null); 662 assert_own_property(result, 'requests'); 663 assert_equals(result.requests.length, 1); 664 await validateForSeller(result.requests[0], window.location.origin); 665 }, 'getInterestGroupAdAuctionData() multi-seller with single seller'); 666 667 subsetTest(promise_test, async test => { 668 const uuid = generateUuid(test); 669 const igConfig = makeTemplateIgConfig(uuid); 670 await joinInterestGroup(test, uuid, igConfig); 671 672 const result = await navigator.getInterestGroupAdAuctionData({ 673 sellers: [{ 674 coordinatorOrigin: await BA.configureCoordinator(), 675 seller: window.location.origin, 676 }, { 677 coordinatorOrigin: await BA.configureCoordinator(), 678 seller: OTHER_ORIGIN1, 679 }] 680 }); 681 682 assert_true(result.requestId !== null); 683 assert_own_property(result, 'requests'); 684 assert_equals(result.requests.length, 2, JSON.stringify(result)); 685 result.requests.sort((a,b)=> (a.seller < b.seller ? -1 : +(a.seller > b.seller))); 686 687 await validateForSeller(result.requests[0], OTHER_ORIGIN1); 688 await validateForSeller(result.requests[1], window.location.origin); 689 690 assert_not_equals(result.requests[0].request.toString(), result.requests[1].request.toString()); 691 }, 'getInterestGroupAdAuctionData() multi-seller with multiple sellers - valid'); 692 693 subsetTest(promise_test, async test => { 694 const uuid = generateUuid(test); 695 const igConfig = makeTemplateIgConfig(uuid); 696 await joinInterestGroup(test, uuid, igConfig); 697 698 const result = await navigator.getInterestGroupAdAuctionData({ 699 sellers: [{ 700 coordinatorOrigin: await BA.configureCoordinator(), 701 seller: window.location.origin, 702 }, { 703 coordinatorOrigin: "https://invalid.coordinator.test/", 704 seller: OTHER_ORIGIN1, 705 }] 706 }); 707 708 assert_true(result.requestId !== null); 709 assert_own_property(result, 'requests'); 710 assert_equals(result.requests.length, 2, JSON.stringify(result)); 711 result.requests.sort((a,b)=> (a.seller < b.seller ? -1 : +(a.seller > b.seller))); 712 713 assert_equals(result.requests[0].seller, OTHER_ORIGIN1); 714 assert_own_property(result.requests[0], 'error'); 715 assert_not_own_property(result.requests[0], 'request'); 716 717 await validateForSeller(result.requests[1], window.location.origin); 718 }, 'getInterestGroupAdAuctionData() multi-seller with multiple sellers - one invalid coordinator'); 719 720 subsetTest(promise_test, async test => { 721 const uuid = generateUuid(test); 722 const igConfig = makeTemplateIgConfig(uuid); 723 await joinInterestGroup(test, uuid, igConfig); 724 725 await promise_rejects_js(test, TypeError, navigator.getInterestGroupAdAuctionData({ 726 sellers: [{ 727 coordinatorOrigin: await BA.configureCoordinator(), 728 seller: window.location.origin, 729 }, { 730 coordinatorOrigin: await BA.configureCoordinator(), 731 seller: "http://not.secure.test/", 732 }] 733 })); 734 }, 'getInterestGroupAdAuctionData() multi-seller with multiple sellers - one invalid seller'); 735 736 subsetTest(promise_test, async test => { 737 const uuid = generateUuid(test); 738 const igConfig = makeTemplateIgConfig(uuid); 739 await joinInterestGroup(test, uuid, igConfig); 740 741 await promise_rejects_js(test, TypeError, navigator.getInterestGroupAdAuctionData({ 742 })); 743 }, 'getInterestGroupAdAuctionData() one of "seller" and "sellers" is required'); 744 745 subsetTest(promise_test, async test => { 746 const uuid = generateUuid(test); 747 const igConfig = makeTemplateIgConfig(uuid); 748 await joinInterestGroup(test, uuid, igConfig); 749 750 await promise_rejects_js(test, TypeError, navigator.getInterestGroupAdAuctionData({ 751 seller: window.location.origin, 752 sellers: [{ 753 coordinatorOrigin: await BA.configureCoordinator(), 754 seller: window.location.origin, 755 }] 756 })); 757 }, 'getInterestGroupAdAuctionData() doesn\'t allow "seller" and "sellers" fields'); 758 759 subsetTest(promise_test, async test => { 760 const uuid = generateUuid(test); 761 const igConfig = makeTemplateIgConfig(uuid); 762 await joinInterestGroup(test, uuid, igConfig); 763 764 await promise_rejects_js(test, TypeError, navigator.getInterestGroupAdAuctionData({ 765 coordinatorOrigin: window.location.origin, 766 sellers: [{ 767 coordinatorOrigin: await BA.configureCoordinator(), 768 seller: window.location.origin, 769 }] 770 })); 771 }, 'getInterestGroupAdAuctionData() doesn\'t allow "coordinatorOrigin" and "sellers" fields'); 772 773 subsetTest(promise_test, async test => { 774 const uuid = generateUuid(test); 775 const igConfig = makeTemplateIgConfig(uuid); 776 await joinInterestGroup(test, uuid, igConfig); 777 778 await promise_rejects_js(test, TypeError, navigator.getInterestGroupAdAuctionData({ 779 sellers: [{ 780 coordinatorOrigin: await BA.configureCoordinator(), 781 seller: window.location.origin, 782 }, { 783 coordinatorOrigin: await BA.configureCoordinator(), 784 seller: window.location.origin, 785 } 786 ] 787 })); 788 }, 'getInterestGroupAdAuctionData() doesn\'t allow duplicate sellers in "sellers" field'); 789 790 subsetTest(promise_test, async test => { 791 const uuid = generateUuid(test); 792 const igConfig = makeTemplateIgConfig(uuid); 793 await joinInterestGroup(test, uuid, igConfig); 794 795 const result = await navigator.getInterestGroupAdAuctionData({ 796 sellers: [] 797 }); 798 assert_equals(result.requestId, ""); 799 assert_array_equals(result.requests, []); 800 }, 'getInterestGroupAdAuctionData() with no sellers');