From a363913d4f62fa6583a9b5e6d18446fec03e227e Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 23 Mar 2020 09:59:31 -0400 Subject: [PATCH 01/10] TCF Purpose 1 enforcement --- integrationExamples/gpt/hello_world.html | 1630 ++++++++++++++++++++- modules/appnexusBidAdapter.js | 7 +- modules/gdprEnforcement.js | 156 ++ modules/id5IdSystem.js | 5 + modules/rubiconBidAdapter.js | 2 + modules/userId/index.js | 40 +- src/adapters/bidderFactory.js | 36 +- src/config.js | 5 + src/storageManager.js | 147 ++ src/userSync.js | 5 +- src/utils.js | 2 +- test/spec/modules/gdprEnforcement_spec.js | 269 ++++ test/spec/modules/userId_spec.js | 7 +- 13 files changed, 2274 insertions(+), 37 deletions(-) create mode 100644 modules/gdprEnforcement.js create mode 100644 src/storageManager.js create mode 100644 test/spec/modules/gdprEnforcement_spec.js diff --git a/integrationExamples/gpt/hello_world.html b/integrationExamples/gpt/hello_world.html index d68e65011be..d7d1919033e 100755 --- a/integrationExamples/gpt/hello_world.html +++ b/integrationExamples/gpt/hello_world.html @@ -28,7 +28,14 @@ params: { placementId: 13144370 } - }] + },{ + bidder: "rubicon", + params: { + accountId: 14062, + siteId: 70608, + zoneId: 498816 + } + }] }]; @@ -43,8 +50,1629 @@ googletag.cmd.push(function() { googletag.pubads().disableInitialLoad(); }); + + var a = { + appnexus: { + bidCpmAdjustment : function(bidCpm, bid){ + // adjust the bid in real time before the auction takes place + bid.appnexus.dealPriority = 10; + if (bid.video && bid.video.dealTier && bid.video.dealTier < 6) { + delete bid.video.dealTier + } + return 10; + } + } + }; + pbjs.bidderSettings = a pbjs.que.push(function() { + pbjs.setConfig({ + // deviceAccess: false, + userSync: { + userIds: [{ + name: "id5Id", + params: { + partner: 173 // change to the Partner Number you received from ID5 + }, + storage: { + type: "cookie", + name: "pbjs-id5id", // create a cookie with this name + expires: 90, // cookie lasts for 90 days + refreshInSeconds: 8*3600 // refresh ID every 8 hours to ensure it's fresh + } + }], + syncDelay: 1000 // 1 second after the first bidRequest() + } +}); + + pbjs.setConfig({ + consentManagement: { + // gdpr: { + // cmpApi: 'iab', + // defaultGdprScope: true, + // timeout: 3000, + // // allowAuctionWithoutConsent: false, // deprecated + // rules: [{ + // purpose: 'storage', + // enforcePurpose: false, + // enforceVendor: false, + // vendorExceptions: ['bidderA'] + // }] + // } + gdpr: { + rules: [{ + purpose: 'storage', + enforcePurpose: false, + enforceVendor: false, + vendorExceptions: ['appnexus','id5Id','rubicon'] + }], + cmpApi: 'static', + allowAuctionWithoutConsent: true, + timeout: 5000, + consentData: { + getTCData: { + "tcString": "COuqj-POu90rDBcBkBENAZCgAPzAAAPAACiQFwwBAABAA1ADEAbQC4YAYAAgAxAG0A", + "cmpId": 92, + "cmpVersion": 100, + "tcfPolicyVersion": 2, + "gdprApplies": true, + "isServiceSpecific": true, + "useNonStandardStacks": false, + "purposeOneTreatment": false, + "publisherCC": "US", + "cmpStatus": "loaded", + "eventStatus": "tcloaded", + "outOfBand": { + "allowedVendors": {}, + "discloseVendors": {} + }, + "purpose": { + "consents": { + "1": true, + "2": true, + "3": true, + "4": true, + "5": true, + "6": true, + "7": false, + "8": false, + "9": true, + "10": true + }, + "legitimateInterests": { + "1": false, + "2": false, + "3": false, + "4": false, + "5": false, + "6": false, + "7": true, + "8": true, + "9": true, + "10": true + } + }, + "vendor": { + "consents": { + "1": false, + "2": true, + "3": false, + "4": false, + "5": false, + "6": false, + "7": false, + "8": false, + "9": false, + "10": false, + "11": false, + "12": false, + "13": false, + "14": false, + "15": false, + "16": false, + "17": false, + "18": false, + "19": false, + "20": false, + "21": false, + "22": false, + "23": false, + "24": false, + "25": false, + "26": false, + "27": false, + "28": false, + "29": false, + "30": false, + "31": false, + "32": false, + "33": false, + "34": false, + "35": false, + "36": false, + "37": false, + "38": false, + "39": false, + "40": false, + "41": false, + "42": false, + "43": false, + "44": false, + "45": false, + "46": false, + "47": false, + "48": false, + "49": false, + "50": false, + "51": false, + "52": false, + "53": true, + "54": false, + "55": false, + "56": false, + "57": false, + "58": false, + "59": false, + "60": false, + "61": false, + "62": false, + "63": false, + "64": false, + "65": false, + "66": false, + "67": false, + "68": false, + "69": false, + "70": false, + "71": false, + "72": false, + "73": false, + "74": false, + "75": false, + "76": false, + "77": false, + "78": false, + "79": false, + "80": false, + "81": false, + "82": false, + "83": false, + "84": false, + "85": false, + "86": false, + "87": false, + "88": false, + "89": false, + "90": false, + "91": false, + "92": false, + "93": false, + "94": false, + "95": false, + "96": false, + "97": false, + "98": true, + "99": false, + "100": false, + "101": false, + "102": false, + "103": false, + "104": false, + "105": false, + "106": false, + "107": false, + "108": false, + "109": false, + "110": false, + "111": false, + "112": false, + "113": false, + "114": false, + "115": false, + "116": false, + "117": false, + "118": false, + "119": false, + "120": false, + "121": false, + "122": false, + "123": false, + "124": false, + "125": false, + "126": false, + "127": false, + "128": false, + "129": false, + "130": false, + "131": false, + "132": false, + "133": false, + "134": false, + "135": false, + "136": false, + "137": false, + "138": false, + "139": false, + "140": false, + "141": false, + "142": false, + "143": false, + "144": false, + "145": false, + "146": false, + "147": false, + "148": false, + "149": false, + "150": false, + "151": false, + "152": false, + "153": false, + "154": false, + "155": false, + "156": false, + "157": false, + "158": false, + "159": false, + "160": false, + "161": false, + "162": false, + "163": false, + "164": false, + "165": false, + "166": false, + "167": false, + "168": false, + "169": false, + "170": false, + "171": false, + "172": false, + "173": false, + "174": false, + "175": false, + "176": false, + "177": false, + "178": false, + "179": false, + "180": false, + "181": false, + "182": false, + "183": false, + "184": false, + "185": false, + "186": false, + "187": false, + "188": false, + "189": false, + "190": false, + "191": false, + "192": false, + "193": false, + "194": false, + "195": false, + "196": false, + "197": false, + "198": false, + "199": false, + "200": false, + "201": false, + "202": false, + "203": false, + "204": false, + "205": false, + "206": false, + "207": false, + "208": false, + "209": false, + "210": false, + "211": false, + "212": false, + "213": false, + "214": false, + "215": false, + "216": false, + "217": false, + "218": false, + "219": false, + "220": false, + "221": false, + "222": false, + "223": false, + "224": false, + "225": false, + "226": false, + "227": false, + "228": false, + "229": false, + "230": false, + "231": false, + "232": false, + "233": false, + "234": false, + "235": false, + "236": false, + "237": false, + "238": false, + "239": false, + "240": false, + "241": false, + "242": false, + "243": false, + "244": false, + "245": false, + "246": false, + "247": false, + "248": false, + "249": false, + "250": false, + "251": false, + "252": false, + "253": false, + "254": false, + "255": false, + "256": false, + "257": false, + "258": false, + "259": false, + "260": false, + "261": false, + "262": false, + "263": false, + "264": false, + "265": false, + "266": false, + "267": false, + "268": false, + "269": false, + "270": false, + "271": false, + "272": false, + "273": false, + "274": false, + "275": false, + "276": false, + "277": false, + "278": false, + "279": false, + "280": false, + "281": false, + "282": false, + "283": false, + "284": false, + "285": false, + "286": false, + "287": false, + "288": false, + "289": false, + "290": false, + "291": false, + "292": false, + "293": false, + "294": false, + "295": false, + "296": false, + "297": false, + "298": false, + "299": false, + "300": false, + "301": false, + "302": false, + "303": false, + "304": false, + "305": false, + "306": false, + "307": false, + "308": false, + "309": false, + "310": false, + "311": false, + "312": false, + "313": false, + "314": false, + "315": false, + "316": false, + "317": false, + "318": false, + "319": false, + "320": false, + "321": false, + "322": false, + "323": false, + "324": false, + "325": false, + "326": false, + "327": false, + "328": false, + "329": false, + "330": false, + "331": false, + "332": false, + "333": false, + "334": false, + "335": false, + "336": false, + "337": false, + "338": false, + "339": false, + "340": false, + "341": false, + "342": false, + "343": false, + "344": false, + "345": false, + "346": false, + "347": false, + "348": false, + "349": false, + "350": false, + "351": false, + "352": false, + "353": false, + "354": false, + "355": false, + "356": false, + "357": false, + "358": false, + "359": false, + "360": false, + "361": false, + "362": false, + "363": false, + "364": false, + "365": false, + "366": false, + "367": false, + "368": false, + "369": false, + "370": false, + "371": false, + "372": false, + "373": false, + "374": false, + "375": false, + "376": false, + "377": false, + "378": false, + "379": false, + "380": false, + "381": false, + "382": false, + "383": false, + "384": false, + "385": false, + "386": false, + "387": false, + "388": false, + "389": false, + "390": false, + "391": false, + "392": false, + "393": false, + "394": false, + "395": false, + "396": false, + "397": false, + "398": false, + "399": false, + "400": false, + "401": false, + "402": false, + "403": false, + "404": false, + "405": false, + "406": false, + "407": false, + "408": false, + "409": false, + "410": false, + "411": false, + "412": false, + "413": false, + "414": false, + "415": false, + "416": false, + "417": false, + "418": false, + "419": false, + "420": false, + "421": false, + "422": false, + "423": false, + "424": false, + "425": false, + "426": false, + "427": false, + "428": false, + "429": false, + "430": false, + "431": false, + "432": false, + "433": false, + "434": false, + "435": false, + "436": true, + "437": false, + "438": false, + "439": false, + "440": false, + "441": false, + "442": false, + "443": false, + "444": false, + "445": false, + "446": false, + "447": false, + "448": false, + "449": false, + "450": false, + "451": false, + "452": false, + "453": false, + "454": false, + "455": false, + "456": false, + "457": false, + "458": false, + "459": false, + "460": false, + "461": false, + "462": false, + "463": false, + "464": false, + "465": false, + "466": false, + "467": false, + "468": false, + "469": false, + "470": false, + "471": false, + "472": false, + "473": false, + "474": false, + "475": false, + "476": false, + "477": false, + "478": false, + "479": false, + "480": false, + "481": false, + "482": false, + "483": false, + "484": false, + "485": false, + "486": false, + "487": false, + "488": false, + "489": false, + "490": false, + "491": false, + "492": false, + "493": false, + "494": false, + "495": false, + "496": false, + "497": false, + "498": false, + "499": false, + "500": false, + "501": false, + "502": false, + "503": false, + "504": false, + "505": false, + "506": false, + "507": false, + "508": false, + "509": false, + "510": false, + "511": false, + "512": false, + "513": false, + "514": false, + "515": false, + "516": false, + "517": false, + "518": false, + "519": false, + "520": false, + "521": false, + "522": false, + "523": false, + "524": false, + "525": false, + "526": false, + "527": false, + "528": false, + "529": false, + "530": false, + "531": false, + "532": false, + "533": false, + "534": false, + "535": false, + "536": false, + "537": false, + "538": false, + "539": false, + "540": false, + "541": false, + "542": false, + "543": false, + "544": false, + "545": false, + "546": false, + "547": false, + "548": false, + "549": false, + "550": false, + "551": false, + "552": false, + "553": false, + "554": false, + "555": false, + "556": false, + "557": false, + "558": false, + "559": false, + "560": false, + "561": false, + "562": false, + "563": false, + "564": false, + "565": false, + "566": false, + "567": false, + "568": false, + "569": false, + "570": false, + "571": false, + "572": false, + "573": false, + "574": false, + "575": false, + "576": false, + "577": false, + "578": false, + "579": false, + "580": false, + "581": false, + "582": false, + "583": false, + "584": false, + "585": false, + "586": false, + "587": false, + "588": false, + "589": false, + "590": false, + "591": false, + "592": false, + "593": false, + "594": false, + "595": false, + "596": false, + "597": false, + "598": false, + "599": false, + "600": false, + "601": false, + "602": false, + "603": false, + "604": false, + "605": false, + "606": false, + "607": false, + "608": false, + "609": false, + "610": false, + "611": false, + "612": false, + "613": false, + "614": false, + "615": false, + "616": false, + "617": false, + "618": false, + "619": false, + "620": false, + "621": false, + "622": false, + "623": false, + "624": false, + "625": false, + "626": false, + "627": false, + "628": false, + "629": false, + "630": false, + "631": false, + "632": false, + "633": false, + "634": false, + "635": false, + "636": false, + "637": false, + "638": false, + "639": false, + "640": false, + "641": false, + "642": false, + "643": false, + "644": false, + "645": false, + "646": false, + "647": false, + "648": false, + "649": false, + "650": false, + "651": false, + "652": false, + "653": false, + "654": false, + "655": false, + "656": false, + "657": false, + "658": false, + "659": false, + "660": false, + "661": false, + "662": false, + "663": false, + "664": false, + "665": false, + "666": false, + "667": false, + "668": false, + "669": false, + "670": false, + "671": false, + "672": false, + "673": false, + "674": false, + "675": false, + "676": false, + "677": false, + "678": false, + "679": false, + "680": false, + "681": false, + "682": false, + "683": false, + "684": false, + "685": false, + "686": false, + "687": false, + "688": false, + "689": false, + "690": false, + "691": false, + "692": false, + "693": false, + "694": false, + "695": false, + "696": false, + "697": false, + "698": false, + "699": false, + "700": false, + "701": false, + "702": false, + "703": false, + "704": false, + "705": false, + "706": false, + "707": false, + "708": false, + "709": false, + "710": false, + "711": false, + "712": false, + "713": false, + "714": false, + "715": false, + "716": false, + "717": false, + "718": false, + "719": false, + "720": false, + "721": false, + "722": false, + "723": false, + "724": false, + "725": false, + "726": false, + "727": false, + "728": false, + "729": false, + "730": false, + "731": false, + "732": false, + "733": false, + "734": false, + "735": false, + "736": false, + "737": false + }, + "legitimateInterests": { + "1": false, + "2": true, + "3": false, + "4": false, + "5": false, + "6": false, + "7": false, + "8": false, + "9": false, + "10": false, + "11": false, + "12": false, + "13": false, + "14": false, + "15": false, + "16": false, + "17": false, + "18": false, + "19": false, + "20": false, + "21": false, + "22": false, + "23": false, + "24": false, + "25": false, + "26": false, + "27": false, + "28": false, + "29": false, + "30": false, + "31": false, + "32": false, + "33": false, + "34": false, + "35": false, + "36": false, + "37": false, + "38": false, + "39": false, + "40": false, + "41": false, + "42": false, + "43": false, + "44": false, + "45": false, + "46": false, + "47": false, + "48": false, + "49": false, + "50": false, + "51": false, + "52": false, + "53": false, + "54": false, + "55": false, + "56": false, + "57": false, + "58": false, + "59": false, + "60": false, + "61": false, + "62": false, + "63": false, + "64": false, + "65": false, + "66": false, + "67": false, + "68": false, + "69": false, + "70": false, + "71": false, + "72": false, + "73": false, + "74": false, + "75": false, + "76": false, + "77": false, + "78": false, + "79": false, + "80": false, + "81": false, + "82": false, + "83": false, + "84": false, + "85": false, + "86": false, + "87": false, + "88": false, + "89": false, + "90": false, + "91": false, + "92": false, + "93": false, + "94": false, + "95": false, + "96": false, + "97": false, + "98": true, + "99": false, + "100": false, + "101": false, + "102": false, + "103": false, + "104": false, + "105": false, + "106": false, + "107": false, + "108": false, + "109": false, + "110": false, + "111": false, + "112": false, + "113": false, + "114": false, + "115": false, + "116": false, + "117": false, + "118": false, + "119": false, + "120": false, + "121": false, + "122": false, + "123": false, + "124": false, + "125": false, + "126": false, + "127": false, + "128": false, + "129": false, + "130": false, + "131": false, + "132": false, + "133": false, + "134": false, + "135": false, + "136": false, + "137": false, + "138": false, + "139": false, + "140": false, + "141": false, + "142": false, + "143": false, + "144": false, + "145": false, + "146": false, + "147": false, + "148": false, + "149": false, + "150": false, + "151": false, + "152": false, + "153": false, + "154": false, + "155": false, + "156": false, + "157": false, + "158": false, + "159": false, + "160": false, + "161": false, + "162": false, + "163": false, + "164": false, + "165": false, + "166": false, + "167": false, + "168": false, + "169": false, + "170": false, + "171": false, + "172": false, + "173": false, + "174": false, + "175": false, + "176": false, + "177": false, + "178": false, + "179": false, + "180": false, + "181": false, + "182": false, + "183": false, + "184": false, + "185": false, + "186": false, + "187": false, + "188": false, + "189": false, + "190": false, + "191": false, + "192": false, + "193": false, + "194": false, + "195": false, + "196": false, + "197": false, + "198": false, + "199": false, + "200": false, + "201": false, + "202": false, + "203": false, + "204": false, + "205": false, + "206": false, + "207": false, + "208": false, + "209": false, + "210": false, + "211": false, + "212": false, + "213": false, + "214": false, + "215": false, + "216": false, + "217": false, + "218": false, + "219": false, + "220": false, + "221": false, + "222": false, + "223": false, + "224": false, + "225": false, + "226": false, + "227": false, + "228": false, + "229": false, + "230": false, + "231": false, + "232": false, + "233": false, + "234": false, + "235": false, + "236": false, + "237": false, + "238": false, + "239": false, + "240": false, + "241": false, + "242": false, + "243": false, + "244": false, + "245": false, + "246": false, + "247": false, + "248": false, + "249": false, + "250": false, + "251": false, + "252": false, + "253": false, + "254": false, + "255": false, + "256": false, + "257": false, + "258": false, + "259": false, + "260": false, + "261": false, + "262": false, + "263": false, + "264": false, + "265": false, + "266": false, + "267": false, + "268": false, + "269": false, + "270": false, + "271": false, + "272": false, + "273": false, + "274": false, + "275": false, + "276": false, + "277": false, + "278": false, + "279": false, + "280": false, + "281": false, + "282": false, + "283": false, + "284": false, + "285": false, + "286": false, + "287": false, + "288": false, + "289": false, + "290": false, + "291": false, + "292": false, + "293": false, + "294": false, + "295": false, + "296": false, + "297": false, + "298": false, + "299": false, + "300": false, + "301": false, + "302": false, + "303": false, + "304": false, + "305": false, + "306": false, + "307": false, + "308": false, + "309": false, + "310": false, + "311": false, + "312": false, + "313": false, + "314": false, + "315": false, + "316": false, + "317": false, + "318": false, + "319": false, + "320": false, + "321": false, + "322": false, + "323": false, + "324": false, + "325": false, + "326": false, + "327": false, + "328": false, + "329": false, + "330": false, + "331": false, + "332": false, + "333": false, + "334": false, + "335": false, + "336": false, + "337": false, + "338": false, + "339": false, + "340": false, + "341": false, + "342": false, + "343": false, + "344": false, + "345": false, + "346": false, + "347": false, + "348": false, + "349": false, + "350": false, + "351": false, + "352": false, + "353": false, + "354": false, + "355": false, + "356": false, + "357": false, + "358": false, + "359": false, + "360": false, + "361": false, + "362": false, + "363": false, + "364": false, + "365": false, + "366": false, + "367": false, + "368": false, + "369": false, + "370": false, + "371": false, + "372": false, + "373": false, + "374": false, + "375": false, + "376": false, + "377": false, + "378": false, + "379": false, + "380": false, + "381": false, + "382": false, + "383": false, + "384": false, + "385": false, + "386": false, + "387": false, + "388": false, + "389": false, + "390": false, + "391": false, + "392": false, + "393": false, + "394": false, + "395": false, + "396": false, + "397": false, + "398": false, + "399": false, + "400": false, + "401": false, + "402": false, + "403": false, + "404": false, + "405": false, + "406": false, + "407": false, + "408": false, + "409": false, + "410": false, + "411": false, + "412": false, + "413": false, + "414": false, + "415": false, + "416": false, + "417": false, + "418": false, + "419": false, + "420": false, + "421": false, + "422": false, + "423": false, + "424": false, + "425": false, + "426": false, + "427": false, + "428": false, + "429": false, + "430": false, + "431": false, + "432": false, + "433": false, + "434": false, + "435": false, + "436": true, + "437": false, + "438": false, + "439": false, + "440": false, + "441": false, + "442": false, + "443": false, + "444": false, + "445": false, + "446": false, + "447": false, + "448": false, + "449": false, + "450": false, + "451": false, + "452": false, + "453": false, + "454": false, + "455": false, + "456": false, + "457": false, + "458": false, + "459": false, + "460": false, + "461": false, + "462": false, + "463": false, + "464": false, + "465": false, + "466": false, + "467": false, + "468": false, + "469": false, + "470": false, + "471": false, + "472": false, + "473": false, + "474": false, + "475": false, + "476": false, + "477": false, + "478": false, + "479": false, + "480": false, + "481": false, + "482": false, + "483": false, + "484": false, + "485": false, + "486": false, + "487": false, + "488": false, + "489": false, + "490": false, + "491": false, + "492": false, + "493": false, + "494": false, + "495": false, + "496": false, + "497": false, + "498": false, + "499": false, + "500": false, + "501": false, + "502": false, + "503": false, + "504": false, + "505": false, + "506": false, + "507": false, + "508": false, + "509": false, + "510": false, + "511": false, + "512": false, + "513": false, + "514": false, + "515": false, + "516": false, + "517": false, + "518": false, + "519": false, + "520": false, + "521": false, + "522": false, + "523": false, + "524": false, + "525": false, + "526": false, + "527": false, + "528": false, + "529": false, + "530": false, + "531": false, + "532": false, + "533": false, + "534": false, + "535": false, + "536": false, + "537": false, + "538": false, + "539": false, + "540": false, + "541": false, + "542": false, + "543": false, + "544": false, + "545": false, + "546": false, + "547": false, + "548": false, + "549": false, + "550": false, + "551": false, + "552": false, + "553": false, + "554": false, + "555": false, + "556": false, + "557": false, + "558": false, + "559": false, + "560": false, + "561": false, + "562": false, + "563": false, + "564": false, + "565": false, + "566": false, + "567": false, + "568": false, + "569": false, + "570": false, + "571": false, + "572": false, + "573": false, + "574": false, + "575": false, + "576": false, + "577": false, + "578": false, + "579": false, + "580": false, + "581": false, + "582": false, + "583": false, + "584": false, + "585": false, + "586": false, + "587": false, + "588": false, + "589": false, + "590": false, + "591": false, + "592": false, + "593": false, + "594": false, + "595": false, + "596": false, + "597": false, + "598": false, + "599": false, + "600": false, + "601": false, + "602": false, + "603": false, + "604": false, + "605": false, + "606": false, + "607": false, + "608": false, + "609": false, + "610": false, + "611": false, + "612": false, + "613": false, + "614": false, + "615": false, + "616": false, + "617": false, + "618": false, + "619": false, + "620": false, + "621": false, + "622": false, + "623": false, + "624": false, + "625": false, + "626": false, + "627": false, + "628": false, + "629": false, + "630": false, + "631": false, + "632": false, + "633": false, + "634": false, + "635": false, + "636": false, + "637": false, + "638": false, + "639": false, + "640": false, + "641": false, + "642": false, + "643": false, + "644": false, + "645": false, + "646": false, + "647": false, + "648": false, + "649": false, + "650": false, + "651": false, + "652": false, + "653": false, + "654": false, + "655": false, + "656": false, + "657": false, + "658": false, + "659": false, + "660": false, + "661": false, + "662": false, + "663": false, + "664": false, + "665": false, + "666": false, + "667": false, + "668": false, + "669": false, + "670": false, + "671": false, + "672": false, + "673": false, + "674": false, + "675": false, + "676": false, + "677": false, + "678": false, + "679": false, + "680": false, + "681": false, + "682": false, + "683": false, + "684": false, + "685": false, + "686": false, + "687": false, + "688": false, + "689": false, + "690": false, + "691": false, + "692": false, + "693": false, + "694": false, + "695": false, + "696": false, + "697": false, + "698": false, + "699": false, + "700": false, + "701": false, + "702": false, + "703": false, + "704": false, + "705": false, + "706": false, + "707": false, + "708": false, + "709": false, + "710": false, + "711": false, + "712": false, + "713": false, + "714": false, + "715": false, + "716": false, + "717": false, + "718": false, + "719": false, + "720": false, + "721": false, + "722": false, + "723": false, + "724": false, + "725": false, + "726": false, + "727": false, + "728": false, + "729": false, + "730": false, + "731": false, + "732": false, + "733": false, + "734": false, + "735": false, + "736": false, + "737": false + } + }, + "specialFeatureOptins": { + "1": false, + "2": false + }, + "restrictions": {}, + "publisher": { + "consents": { + "1": false, + "2": false, + "3": false, + "4": false, + "5": false, + "6": false, + "7": false, + "8": false, + "9": false, + "10": false + }, + "legitimateInterests": { + "1": false, + "2": false, + "3": false, + "4": false, + "5": false, + "6": false, + "7": false, + "8": false, + "9": false, + "10": false + }, + "customPurpose": { + "consents": {}, + "legitimateInterests": {} + } + } + } + } + } + } + }); + pbjs.addAdUnits(adUnits); pbjs.requestBids({ bidsBackHandler: sendAdserverRequest, diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 9f107bf54ec..92d1dcf24d2 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -7,6 +7,7 @@ import { auctionManager } from '../src/auctionManager.js'; import find from 'core-js/library/fn/array/find.js'; import includes from 'core-js/library/fn/array/includes.js'; import { OUTSTREAM, INSTREAM } from '../src/video.js'; +import { newStorageManager } from '../src/storageManager.js'; const BIDDER_CODE = 'appnexus'; const URL = 'https://ib.adnxs.com/ut/v3/prebid'; @@ -38,9 +39,12 @@ const mappingFileUrl = 'https://acdn.adnxs.com/prebid/appnexus-mapping/mappings. const SCRIPT_TAG_START = ' { + const gvlid = submodule.submodule.gvlid; + const moduleName = submodule.submodule.name; + if (gvlid) { + const purpose1Rule = find(enforcementRules, hasPurpose1); + let isAllowed = validateRules(purpose1Rule, consentData, moduleName, gvlid); + if (isAllowed) { + return submodule; + } else { + utils.logWarn(`User denied permission to fetch user id for ${moduleName} User id module`); + } + } else { + utils.logWarn(`User denied permission to fetch user id for ${moduleName} User id module`); + } + return undefined; + }).filter(module => module) + fn.call(this, userIdModules, consentData); + } else { + fn.call(this, submodules, consentData); + } +} + +const hasPurpose1 = (rule) => { return rule.purpose === purpose1 } + +export function setEnforcementConfig(config) { + const rules = utils.deepAccess(config, 'gdpr.rules'); + if (!rules) { + utils.logWarn('GDPR enforcement rules not defined, exiting enforcement module'); + return; + } + + enforcementRules = rules; + const hasDefinedPurpose1 = find(enforcementRules, hasPurpose1); + if (hasDefinedPurpose1 && !addedDeviceAccessHook) { + addedDeviceAccessHook = true; + validateStorageEnforcement.before(deviceAccessHook); + registerSyncInner.before(userSyncHook); + // Using getHook as user id and gdprEnforcement are both optional modules. Using import will auto include the file in build + getHook('validateGdprEnforcement').before(userIdHook); + } +} + +config.getConfig('consentManagement', config => setEnforcementConfig(config.consentManagement)); diff --git a/modules/id5IdSystem.js b/modules/id5IdSystem.js index 32617d2f328..1d55450239b 100644 --- a/modules/id5IdSystem.js +++ b/modules/id5IdSystem.js @@ -16,6 +16,11 @@ export const id5IdSubmodule = { * @type {string} */ name: 'id5Id', + /** + * Vendor id of ID5 + * @type {Number} + */ + gvlid: 131, /** * decode the stored id value for passing to bid requests * @function decode diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index f8288503493..18f65cf0bc4 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -10,6 +10,7 @@ export const FASTLANE_ENDPOINT = 'https://fastlane.rubiconproject.com/a/api/fast export const VIDEO_ENDPOINT = 'https://prebid-server.rubiconproject.com/openrtb2/auction'; export const SYNC_ENDPOINT = 'https://eus.rubiconproject.com/usync.html'; +const GVLID = 52; const DIGITRUST_PROP_NAMES = { FASTLANE: { id: 'dt.id', @@ -106,6 +107,7 @@ utils._each(sizeMap, (item, key) => sizeMap[item] = key); export const spec = { code: 'rubicon', + gvlid: GVLID, supportedMediaTypes: [BANNER, VIDEO], /** * @param {object} bid diff --git a/modules/userId/index.js b/modules/userId/index.js index 19eeb5b56a5..dd0d9aa3c33 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -103,14 +103,16 @@ import * as utils from '../../src/utils.js'; import {getGlobal} from '../../src/prebidGlobal.js'; import {gdprDataHandler} from '../../src/adapterManager.js'; import CONSTANTS from '../../src/constants.json'; -import {module} from '../../src/hook.js'; +import {module, hook} from '../../src/hook.js'; import {createEidsArray} from './eids.js'; +import { newStorageManager } from '../../src/storageManager.js'; const MODULE_NAME = 'User ID'; const COOKIE = 'cookie'; const LOCAL_STORAGE = 'html5'; const DEFAULT_SYNC_DELAY = 500; const NO_AUCTION_DELAY = 0; +export const coreStorage = newStorageManager({moduleName: 'userid', moduleType: 'prebid-module'}); /** @type {string[]} */ let validStorageTypes = []; @@ -150,15 +152,15 @@ function setStoredValue(storage, value) { const valueStr = utils.isPlainObject(value) ? JSON.stringify(value) : value; const expiresStr = (new Date(Date.now() + (storage.expires * (60 * 60 * 24 * 1000)))).toUTCString(); if (storage.type === COOKIE) { - utils.setCookie(storage.name, valueStr, expiresStr, 'Lax'); + coreStorage.setCookie(storage.name, valueStr, expiresStr, 'Lax'); if (typeof storage.refreshInSeconds === 'number') { - utils.setCookie(`${storage.name}_last`, new Date().toUTCString(), expiresStr); + coreStorage.setCookie(`${storage.name}_last`, new Date().toUTCString(), expiresStr); } } else if (storage.type === LOCAL_STORAGE) { - utils.setDataInLocalStorage(`${storage.name}_exp`, expiresStr); - utils.setDataInLocalStorage(storage.name, encodeURIComponent(valueStr)); + localStorage.setItem(`${storage.name}_exp`, expiresStr); + localStorage.setItem(storage.name, encodeURIComponent(valueStr)); if (typeof storage.refreshInSeconds === 'number') { - utils.setDataInLocalStorage(`${storage.name}_last`, new Date().toUTCString()); + localStorage.setItem(`${storage.name}_last`, new Date().toUTCString()); } } } catch (error) { @@ -176,15 +178,15 @@ function getStoredValue(storage, key = undefined) { let storedValue; try { if (storage.type === COOKIE) { - storedValue = utils.getCookie(storedKey); + storedValue = coreStorage.getCookie(storedKey); } else if (storage.type === LOCAL_STORAGE) { - const storedValueExp = utils.getDataFromLocalStorage(`${storage.name}_exp`); + const storedValueExp = localStorage.getItem(`${storage.name}_exp`); // empty string means no expiration set if (storedValueExp === '') { - storedValue = utils.getDataFromLocalStorage(storedKey); + storedValue = localStorage.getItem(storedKey); } else if (storedValueExp) { if ((new Date(storedValueExp)).getTime() - Date.now() > 0) { - storedValue = decodeURIComponent(utils.getDataFromLocalStorage(storedKey)); + storedValue = decodeURIComponent(localStorage.getItem(storedKey)); } } } @@ -364,6 +366,13 @@ function getUserIds() { return getCombinedSubmoduleIds(initializedSubmodules); } +/** + * This hook returns updated list of submodules which are allowed to do get user id based on TCF 2 enforcement rules configured + */ +export const validateGdprEnforcement = hook('sync', function (submodules, consentData) { + return submodules; +}, 'validateGdprEnforcement'); + /** * @param {SubmoduleContainer[]} submodules * @param {ConsentData} consentData @@ -371,12 +380,13 @@ function getUserIds() { */ function initSubmodules(submodules, consentData) { // gdpr consent with purpose one is required, otherwise exit immediately + let userIdModules = validateGdprEnforcement(submodules, consentData); if (!hasGDPRConsent(consentData)) { utils.logWarn(`${MODULE_NAME} - gdpr permission not valid for local storage or cookies, exit module`); return []; } - return submodules.reduce((carry, submodule) => { + return userIdModules.reduce((carry, submodule) => { // There are two submodule configuration types to handle: storage or value // 1. storage: retrieve user id data from cookie/html storage or with the submodule's getId method // 2. value: pass directly to bids @@ -522,17 +532,17 @@ export function init(config) { // list of browser enabled storage types validStorageTypes = [ - utils.localStorageIsEnabled() ? LOCAL_STORAGE : null, - utils.cookiesAreEnabled() ? COOKIE : null + coreStorage.localStorageIsEnabled() ? LOCAL_STORAGE : null, + coreStorage.cookiesAreEnabled() ? COOKIE : null ].filter(i => i !== null); // exit immediately if opt out cookie or local storage keys exists. - if (validStorageTypes.indexOf(COOKIE) !== -1 && (utils.getCookie('_pbjs_id_optout') || utils.getCookie('_pubcid_optout'))) { + if (validStorageTypes.indexOf(COOKIE) !== -1 && (coreStorage.getCookie('_pbjs_id_optout') || coreStorage.getCookie('_pubcid_optout'))) { utils.logInfo(`${MODULE_NAME} - opt-out cookie found, exit module`); return; } // _pubcid_optout is checked for compatiblility with pubCommonId - if (validStorageTypes.indexOf(LOCAL_STORAGE) !== -1 && (utils.getDataFromLocalStorage('_pbjs_id_optout') || utils.getDataFromLocalStorage('_pubcid_optout'))) { + if (validStorageTypes.indexOf(LOCAL_STORAGE) !== -1 && (localStorage.getItem('_pbjs_id_optout') || localStorage.getItem('_pubcid_optout'))) { utils.logInfo(`${MODULE_NAME} - opt-out localStorage found, exit module`); return; } diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 64bfe27c0c5..f18f9447581 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -11,7 +11,7 @@ import includes from 'core-js/library/fn/array/includes.js'; import { ajax } from '../ajax.js'; import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest, flatten, uniques, timestamp, setDataInLocalStorage, getDataFromLocalStorage, deepAccess, isArray } from '../utils.js'; import { ADPOD } from '../mediaTypes.js'; -import { getHook } from '../hook.js'; +import { getHook, hook } from '../hook.js'; /** * This file aims to support Adapters during the Prebid 0.x -> 1.x transition. @@ -331,21 +331,7 @@ export function newBidder(spec) { }); function registerSyncs(responses, gdprConsent, uspConsent) { - if (spec.getUserSyncs && !adapterManager.aliasRegistry[spec.code]) { - let filterConfig = config.getConfig('userSync.filterSettings'); - let syncs = spec.getUserSyncs({ - iframeEnabled: !!(filterConfig && (filterConfig.iframe || filterConfig.all)), - pixelEnabled: !!(filterConfig && (filterConfig.image || filterConfig.all)), - }, responses, gdprConsent, uspConsent); - if (syncs) { - if (!Array.isArray(syncs)) { - syncs = [syncs]; - } - syncs.forEach((sync) => { - userSync.registerSync(sync.type, spec.code, sync.url) - }); - } - } + registerSyncInner(spec, responses, gdprConsent, uspConsent); } function filterAndWarn(bid) { @@ -357,6 +343,24 @@ export function newBidder(spec) { } } +export const registerSyncInner = hook('async', function(spec, responses, gdprConsent, uspConsent) { + if (spec.getUserSyncs && !adapterManager.aliasRegistry[spec.code]) { + let filterConfig = config.getConfig('userSync.filterSettings'); + let syncs = spec.getUserSyncs({ + iframeEnabled: !!(filterConfig && (filterConfig.iframe || filterConfig.all)), + pixelEnabled: !!(filterConfig && (filterConfig.image || filterConfig.all)), + }, responses, gdprConsent, uspConsent); + if (syncs) { + if (!Array.isArray(syncs)) { + syncs = [syncs]; + } + syncs.forEach((sync) => { + userSync.registerSync(sync.type, spec.code, sync.url) + }); + } + } +}, 'registerSyncs') + export function preloadBidderMappingFile(fn, adUnits) { if (!config.getConfig('adpod.brandCategoryExclusion')) { return fn.call(this, adUnits); diff --git a/src/config.js b/src/config.js index 8484b87b77c..24962bdff37 100644 --- a/src/config.js +++ b/src/config.js @@ -450,9 +450,14 @@ export function newConfig() { } } + function getCurrentBidder() { + return currBidder; + } + resetConfig(); return { + getCurrentBidder, getConfig, setConfig, setDefaults, diff --git a/src/storageManager.js b/src/storageManager.js new file mode 100644 index 00000000000..015e22f5134 --- /dev/null +++ b/src/storageManager.js @@ -0,0 +1,147 @@ +import { hook } from './hook.js'; +import { hasDeviceAccess, logError, checkCookieSupport } from './utils.js'; +import includes from 'core-js/library/fn/array/includes.js'; + +const moduleTypeWhiteList = ['core', 'prebid-module']; + +export function newStorageManager({gvlid, moduleName, moduleType} = {}) { + function isValid() { + if (includes(moduleTypeWhiteList, moduleType)) { + return {valid: hasDeviceAccess()} + } + let result = validateStorageEnforcement(gvlid, moduleName); + return result; + } + + /** + * @param {string} key + * @param {string} value + * @param {string} [expires=''] + * @param {string} [sameSite='/'] + * @param {string} [domain] domain (e.g., 'example.com' or 'subdomain.example.com'). + * If not specified, defaults to the host portion of the current document location. + * If a domain is specified, subdomains are always included. + * Domain must match the domain of the JavaScript origin. Setting cookies to foreign domains will be silently ignored. + */ + const setCookie = function (key, value, expires, sameSite, domain) { + let result = isValid(); + if (result.valid) { + document.cookie = `${key}=${encodeURIComponent(value)}${(expires !== '') ? `; expires=${expires}` : ''}; path=/${sameSite ? `; SameSite=${sameSite}` : ''}${domain ? `; domain=${domain}` : ''}`; + } + }; + + /** + * @param {string} name + * @returns {(string|null)} + */ + const getCookie = function(name) { + let result = isValid(); + if (result.valid) { + let m = window.document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]*)\\s*(;|$)'); + return m ? decodeURIComponent(m[2]) : null; + } + return null; + }; + + /** + * @returns {boolean} + */ + const localStorageIsEnabled = function () { + let result = isValid(); + if (result.valid) { + try { + localStorage.setItem('prebid.cookieTest', '1'); + return localStorage.getItem('prebid.cookieTest') === '1'; + } catch (error) {} + } + return false; + } + + /** + * @returns {boolean} + */ + const cookiesAreEnabled = function () { + let result = isValid(); + if (result.valid) { + if (checkCookieSupport()) { + return true; + } + window.document.cookie = 'prebid.cookieTest'; + return window.document.cookie.indexOf('prebid.cookieTest') !== -1; + } + return false; + } + + /** + * @param {string} key + * @param {string} value + */ + const setDataInLocalStorage = function (key, value) { + let result = isValid(); + if (result.valid) { + window.localStorage.setItem(key, value); + } + } + + /** + * @param {string} key + * @returns {(string|null)} + */ + const getDataFromLocalStorage = function (key) { + let result = isValid(); + if (result.valid) { + return window.localStorage.getItem(key); + } + return null; + } + + /** + * @param {string} key + */ + const removeDataFromLocalStorage = function (key) { + let result = isValid(); + if (result.valid) { + window.localStorage.removeItem(key); + } + } + + /** + * @returns {boolean} + */ + const hasLocalStorage = function () { + let result = isValid(); + if (result.valid) { + try { + return !!window.localStorage; + } catch (e) { + logError('Local storage api disabled'); + } + } + return false; + } + + return { + setCookie, + getCookie, + localStorageIsEnabled, + cookiesAreEnabled, + setDataInLocalStorage, + getDataFromLocalStorage, + removeDataFromLocalStorage, + hasLocalStorage + } +} + +/** + * This hook validates the storage enforcement if gdprEnforcement module is included + */ +export const validateStorageEnforcement = hook('sync', function(result) { + if (result.hasEnforcementHook) { + return result + } else { + return { + hasEnforcementHook: false, + valid: hasDeviceAccess() + } + } +}, 'validateStorageEnforcement'); diff --git a/src/userSync.js b/src/userSync.js index e19f64d8082..58630532429 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -1,6 +1,7 @@ import * as utils from './utils.js'; import { config } from './config.js'; import includes from 'core-js/library/fn/array/includes.js'; +import { newStorageManager } from './storageManager.js'; export const USERSYNC_DEFAULT_CONFIG = { syncEnabled: true, @@ -20,6 +21,8 @@ config.setDefaults({ 'userSync': utils.deepClone(USERSYNC_DEFAULT_CONFIG) }); +const storage = newStorageManager({moduleName: 'usersync', moduleType: 'core'}); + /** * Factory function which creates a new UserSyncPool. * @@ -299,7 +302,7 @@ export function newUserSync(userSyncDependencies) { return publicApi; } -const browserSupportsCookies = !utils.isSafariBrowser() && utils.cookiesAreEnabled(); +const browserSupportsCookies = !utils.isSafariBrowser() && storage.cookiesAreEnabled(); export const userSync = newUserSync({ config: config.getConfig('userSync'), diff --git a/src/utils.js b/src/utils.js index 3c15b86dffd..6099fa9dd38 100644 --- a/src/utils.js +++ b/src/utils.js @@ -889,7 +889,7 @@ export function setCookie(key, value, expires, sameSite, domain) { /** * @returns {boolean} */ -export function localStorageIsEnabled () { +export function localStorageIsEnabled() { if (hasDeviceAccess()) { try { localStorage.setItem('prebid.cookieTest', '1'); diff --git a/test/spec/modules/gdprEnforcement_spec.js b/test/spec/modules/gdprEnforcement_spec.js new file mode 100644 index 00000000000..84b37ddbe7b --- /dev/null +++ b/test/spec/modules/gdprEnforcement_spec.js @@ -0,0 +1,269 @@ +import { deviceAccessHook, setEnforcementConfig, userSyncHook, userIdHook } from 'modules/gdprEnforcement.js'; +import { config } from 'src/config.js'; +import adapterManager, { gdprDataHandler } from 'src/adapterManager.js'; +import * as utils from 'src/utils.js'; + +describe('gdpr enforcement', function() { + let nextFnSpy; + let logWarnSpy; + let gdprDataHandlerStub; + let staticConfig = { + cmpApi: 'static', + timeout: 7500, + allowAuctionWithoutConsent: false, + consentData: { + getTCData: { + 'tcString': 'COuqj-POu90rDBcBkBENAZCgAPzAAAPAACiQFwwBAABAA1ADEAbQC4YAYAAgAxAG0A', + 'cmpId': 92, + 'cmpVersion': 100, + 'tcfPolicyVersion': 2, + 'gdprApplies': true, + 'isServiceSpecific': true, + 'useNonStandardStacks': false, + 'purposeOneTreatment': false, + 'publisherCC': 'US', + 'cmpStatus': 'loaded', + 'eventStatus': 'tcloaded', + 'outOfBand': { + 'allowedVendors': {}, + 'discloseVendors': {} + }, + 'purpose': { + 'consents': { + '1': true, + '2': true, + '3': true + }, + 'legitimateInterests': { + '1': false, + '2': false, + '3': false + } + }, + 'vendor': { + 'consents': { + '1': true, + '2': true, + '3': false + }, + 'legitimateInterests': { + '1': false, + '2': true, + '3': false, + '4': false, + '5': false + } + }, + 'specialFeatureOptins': { + '1': false, + '2': false + }, + 'restrictions': {}, + 'publisher': { + 'consents': { + '1': false, + '2': false, + '3': false + }, + 'legitimateInterests': { + '1': false, + '2': false, + '3': false + }, + 'customPurpose': { + 'consents': {}, + 'legitimateInterests': {} + } + } + } + } + }; + + describe('deviceAccessHook', function() { + beforeEach(function() { + nextFnSpy = sinon.spy(); + gdprDataHandlerStub = sinon.stub(gdprDataHandler, 'getConsentData'); + logWarnSpy = sinon.spy(utils, 'logWarn'); + }); + afterEach(function() { + config.resetConfig(); + gdprDataHandler.getConsentData.restore(); + logWarnSpy.restore(); + }); + it('should not allow device access when device access flag is set to false', function() { + config.setConfig({ + deviceAccess: false, + consentManagement: { + gdpr: { + rules: [{ + purpose: 'storage', + enforcePurpose: false, + enforceVendor: false, + vendorExceptions: ['appnexus', 'rubicon'] + }] + } + } + }); + + deviceAccessHook(nextFnSpy); + expect(nextFnSpy.calledOnce).to.equal(true); + let result = { + hasEnforcementHook: true, + valid: false + } + expect(nextFnSpy.calledWith(undefined, result)); + }); + + it('should only check for consent for vendor exceptions when enforcePurpose and enforceVendor are false', function() { + setEnforcementConfig({ + gdpr: { + rules: [{ + purpose: 'storage', + enforcePurpose: false, + enforceVendor: false, + vendorExceptions: ['appnexus'] + }] + } + }); + let consentData = {} + consentData.vendorData = staticConfig.consentData.getTCData; + consentData.apiVersion = 2; + gdprDataHandlerStub.returns(consentData); + + deviceAccessHook(nextFnSpy, 1, 'appnexus'); + deviceAccessHook(nextFnSpy, 5, 'rubicon'); + expect(logWarnSpy.callCount).to.equal(0); + }); + + it('should check consent for all vendors when enforcePurpose and enforceVendor are true', function() { + setEnforcementConfig({ + gdpr: { + rules: [{ + purpose: 'storage', + enforcePurpose: true, + enforceVendor: true, + vendorExceptions: [] + }] + } + }); + let consentData = {} + consentData.vendorData = staticConfig.consentData.getTCData; + consentData.apiVersion = 2; + gdprDataHandlerStub.returns(consentData); + + deviceAccessHook(nextFnSpy, 1, 'appnexus'); + deviceAccessHook(nextFnSpy, 3, 'rubicon'); + expect(logWarnSpy.callCount).to.equal(1); + }); + }); + + describe('userSyncHook', function() { + let curBidderStub; + let adapterManagerStub; + + beforeEach(function() { + gdprDataHandlerStub = sinon.stub(gdprDataHandler, 'getConsentData'); + logWarnSpy = sinon.spy(utils, 'logWarn'); + curBidderStub = sinon.stub(config, 'getCurrentBidder'); + adapterManagerStub = sinon.stub(adapterManager, 'getBidAdapter'); + nextFnSpy = sinon.spy(); + }); + + afterEach(function() { + config.getCurrentBidder.restore(); + config.resetConfig(); + gdprDataHandler.getConsentData.restore(); + adapterManager.getBidAdapter.restore(); + logWarnSpy.restore(); + }); + + it('should allow bidder to do user sync if consent is true', function() { + setEnforcementConfig({ + gdpr: { + rules: [{ + purpose: 'storage', + enforcePurpose: false, + enforceVendor: true, + vendorExceptions: ['sampleBidder2'] + }] + } + }); + let consentData = {} + consentData.vendorData = staticConfig.consentData.getTCData; + consentData.apiVersion = 2; + gdprDataHandlerStub.returns(consentData); + + curBidderStub.returns('sampleBidder1'); + adapterManagerStub.withArgs('sampleBidder1').returns({ + getSpec: function() { + return { + 'gvlid': 1 + } + } + }); + userSyncHook(nextFnSpy); + + curBidderStub.returns('sampleBidder2'); + adapterManagerStub.withArgs('sampleBidder2').returns({ + getSpec: function() { + return { + 'gvlid': 3 + } + } + }); + userSyncHook(nextFnSpy); + expect(nextFnSpy.calledTwice).to.equal(true); + }); + + it('should not allow bidder to do user sync if user has denied consent', function() { + setEnforcementConfig({ + gdpr: { + rules: [{ + purpose: 'storage', + enforcePurpose: false, + enforceVendor: true, + vendorExceptions: [] + }] + } + }); + let consentData = {} + consentData.vendorData = staticConfig.consentData.getTCData; + consentData.apiVersion = 2; + gdprDataHandlerStub.returns(consentData); + + curBidderStub.returns('sampleBidder1'); + adapterManagerStub.withArgs('sampleBidder1').returns({ + getSpec: function() { + return { + 'gvlid': 1 + } + } + }); + userSyncHook(nextFnSpy); + + curBidderStub.returns('sampleBidder2'); + adapterManagerStub.withArgs('sampleBidder2').returns({ + getSpec: function() { + return { + 'gvlid': 3 + } + } + }); + userSyncHook(nextFnSpy); + expect(nextFnSpy.calledOnce).to.equal(true); + expect(logWarnSpy.callCount).to.equal(1); + }); + }); + + describe('userIdHook', function() { + beforeEach(function() { + + }); + afterEach(function(){ + + }) + it('should', function() { + + }); + }); +}); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index f717ef3a714..e2564acbb3a 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -4,7 +4,8 @@ import { init, requestBidsHook, setSubmoduleRegistry, - syncDelay + syncDelay, + coreStorage } from 'modules/userId/index.js'; import {config} from 'src/config.js'; import * as utils from 'src/utils.js'; @@ -77,12 +78,14 @@ describe('User ID', function() { utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); utils.setCookie('pubcid_alt', 'altpubcid200000', (new Date(Date.now() + 5000).toUTCString())); sinon.spy(utils, 'setCookie'); + sinon.spy(coreStorage, 'setCookie'); }); afterEach(function () { $$PREBID_GLOBAL$$.requestBids.removeAll(); config.resetConfig(); utils.setCookie.restore(); + coreStorage.setCookie.restore(); }); after(function() { @@ -211,7 +214,7 @@ describe('User ID', function() { }); }); // Because extend is true, the cookie will be updated even if it exists already - expect(utils.setCookie.callCount).to.equal(1); + expect(coreStorage.setCookie.callCount).to.equal(1); }); it('Disable auto create', function () { From c59776b7b40c1df722a4a921e23a831db46136ed Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 23 Mar 2020 12:09:58 -0400 Subject: [PATCH 02/10] some more unit tests and revert hello world page --- integrationExamples/gpt/hello_world.html | 1632 +-------------------- modules/gdprEnforcement.js | 34 +- test/spec/modules/gdprEnforcement_spec.js | 81 +- 3 files changed, 107 insertions(+), 1640 deletions(-) diff --git a/integrationExamples/gpt/hello_world.html b/integrationExamples/gpt/hello_world.html index d7d1919033e..47ba5b8f18a 100755 --- a/integrationExamples/gpt/hello_world.html +++ b/integrationExamples/gpt/hello_world.html @@ -28,14 +28,7 @@ params: { placementId: 13144370 } - },{ - bidder: "rubicon", - params: { - accountId: 14062, - siteId: 70608, - zoneId: 498816 - } - }] + }] }]; @@ -50,1629 +43,8 @@ googletag.cmd.push(function() { googletag.pubads().disableInitialLoad(); }); - - var a = { - appnexus: { - bidCpmAdjustment : function(bidCpm, bid){ - // adjust the bid in real time before the auction takes place - bid.appnexus.dealPriority = 10; - if (bid.video && bid.video.dealTier && bid.video.dealTier < 6) { - delete bid.video.dealTier - } - return 10; - } - } - }; - pbjs.bidderSettings = a pbjs.que.push(function() { - pbjs.setConfig({ - // deviceAccess: false, - userSync: { - userIds: [{ - name: "id5Id", - params: { - partner: 173 // change to the Partner Number you received from ID5 - }, - storage: { - type: "cookie", - name: "pbjs-id5id", // create a cookie with this name - expires: 90, // cookie lasts for 90 days - refreshInSeconds: 8*3600 // refresh ID every 8 hours to ensure it's fresh - } - }], - syncDelay: 1000 // 1 second after the first bidRequest() - } -}); - - pbjs.setConfig({ - consentManagement: { - // gdpr: { - // cmpApi: 'iab', - // defaultGdprScope: true, - // timeout: 3000, - // // allowAuctionWithoutConsent: false, // deprecated - // rules: [{ - // purpose: 'storage', - // enforcePurpose: false, - // enforceVendor: false, - // vendorExceptions: ['bidderA'] - // }] - // } - gdpr: { - rules: [{ - purpose: 'storage', - enforcePurpose: false, - enforceVendor: false, - vendorExceptions: ['appnexus','id5Id','rubicon'] - }], - cmpApi: 'static', - allowAuctionWithoutConsent: true, - timeout: 5000, - consentData: { - getTCData: { - "tcString": "COuqj-POu90rDBcBkBENAZCgAPzAAAPAACiQFwwBAABAA1ADEAbQC4YAYAAgAxAG0A", - "cmpId": 92, - "cmpVersion": 100, - "tcfPolicyVersion": 2, - "gdprApplies": true, - "isServiceSpecific": true, - "useNonStandardStacks": false, - "purposeOneTreatment": false, - "publisherCC": "US", - "cmpStatus": "loaded", - "eventStatus": "tcloaded", - "outOfBand": { - "allowedVendors": {}, - "discloseVendors": {} - }, - "purpose": { - "consents": { - "1": true, - "2": true, - "3": true, - "4": true, - "5": true, - "6": true, - "7": false, - "8": false, - "9": true, - "10": true - }, - "legitimateInterests": { - "1": false, - "2": false, - "3": false, - "4": false, - "5": false, - "6": false, - "7": true, - "8": true, - "9": true, - "10": true - } - }, - "vendor": { - "consents": { - "1": false, - "2": true, - "3": false, - "4": false, - "5": false, - "6": false, - "7": false, - "8": false, - "9": false, - "10": false, - "11": false, - "12": false, - "13": false, - "14": false, - "15": false, - "16": false, - "17": false, - "18": false, - "19": false, - "20": false, - "21": false, - "22": false, - "23": false, - "24": false, - "25": false, - "26": false, - "27": false, - "28": false, - "29": false, - "30": false, - "31": false, - "32": false, - "33": false, - "34": false, - "35": false, - "36": false, - "37": false, - "38": false, - "39": false, - "40": false, - "41": false, - "42": false, - "43": false, - "44": false, - "45": false, - "46": false, - "47": false, - "48": false, - "49": false, - "50": false, - "51": false, - "52": false, - "53": true, - "54": false, - "55": false, - "56": false, - "57": false, - "58": false, - "59": false, - "60": false, - "61": false, - "62": false, - "63": false, - "64": false, - "65": false, - "66": false, - "67": false, - "68": false, - "69": false, - "70": false, - "71": false, - "72": false, - "73": false, - "74": false, - "75": false, - "76": false, - "77": false, - "78": false, - "79": false, - "80": false, - "81": false, - "82": false, - "83": false, - "84": false, - "85": false, - "86": false, - "87": false, - "88": false, - "89": false, - "90": false, - "91": false, - "92": false, - "93": false, - "94": false, - "95": false, - "96": false, - "97": false, - "98": true, - "99": false, - "100": false, - "101": false, - "102": false, - "103": false, - "104": false, - "105": false, - "106": false, - "107": false, - "108": false, - "109": false, - "110": false, - "111": false, - "112": false, - "113": false, - "114": false, - "115": false, - "116": false, - "117": false, - "118": false, - "119": false, - "120": false, - "121": false, - "122": false, - "123": false, - "124": false, - "125": false, - "126": false, - "127": false, - "128": false, - "129": false, - "130": false, - "131": false, - "132": false, - "133": false, - "134": false, - "135": false, - "136": false, - "137": false, - "138": false, - "139": false, - "140": false, - "141": false, - "142": false, - "143": false, - "144": false, - "145": false, - "146": false, - "147": false, - "148": false, - "149": false, - "150": false, - "151": false, - "152": false, - "153": false, - "154": false, - "155": false, - "156": false, - "157": false, - "158": false, - "159": false, - "160": false, - "161": false, - "162": false, - "163": false, - "164": false, - "165": false, - "166": false, - "167": false, - "168": false, - "169": false, - "170": false, - "171": false, - "172": false, - "173": false, - "174": false, - "175": false, - "176": false, - "177": false, - "178": false, - "179": false, - "180": false, - "181": false, - "182": false, - "183": false, - "184": false, - "185": false, - "186": false, - "187": false, - "188": false, - "189": false, - "190": false, - "191": false, - "192": false, - "193": false, - "194": false, - "195": false, - "196": false, - "197": false, - "198": false, - "199": false, - "200": false, - "201": false, - "202": false, - "203": false, - "204": false, - "205": false, - "206": false, - "207": false, - "208": false, - "209": false, - "210": false, - "211": false, - "212": false, - "213": false, - "214": false, - "215": false, - "216": false, - "217": false, - "218": false, - "219": false, - "220": false, - "221": false, - "222": false, - "223": false, - "224": false, - "225": false, - "226": false, - "227": false, - "228": false, - "229": false, - "230": false, - "231": false, - "232": false, - "233": false, - "234": false, - "235": false, - "236": false, - "237": false, - "238": false, - "239": false, - "240": false, - "241": false, - "242": false, - "243": false, - "244": false, - "245": false, - "246": false, - "247": false, - "248": false, - "249": false, - "250": false, - "251": false, - "252": false, - "253": false, - "254": false, - "255": false, - "256": false, - "257": false, - "258": false, - "259": false, - "260": false, - "261": false, - "262": false, - "263": false, - "264": false, - "265": false, - "266": false, - "267": false, - "268": false, - "269": false, - "270": false, - "271": false, - "272": false, - "273": false, - "274": false, - "275": false, - "276": false, - "277": false, - "278": false, - "279": false, - "280": false, - "281": false, - "282": false, - "283": false, - "284": false, - "285": false, - "286": false, - "287": false, - "288": false, - "289": false, - "290": false, - "291": false, - "292": false, - "293": false, - "294": false, - "295": false, - "296": false, - "297": false, - "298": false, - "299": false, - "300": false, - "301": false, - "302": false, - "303": false, - "304": false, - "305": false, - "306": false, - "307": false, - "308": false, - "309": false, - "310": false, - "311": false, - "312": false, - "313": false, - "314": false, - "315": false, - "316": false, - "317": false, - "318": false, - "319": false, - "320": false, - "321": false, - "322": false, - "323": false, - "324": false, - "325": false, - "326": false, - "327": false, - "328": false, - "329": false, - "330": false, - "331": false, - "332": false, - "333": false, - "334": false, - "335": false, - "336": false, - "337": false, - "338": false, - "339": false, - "340": false, - "341": false, - "342": false, - "343": false, - "344": false, - "345": false, - "346": false, - "347": false, - "348": false, - "349": false, - "350": false, - "351": false, - "352": false, - "353": false, - "354": false, - "355": false, - "356": false, - "357": false, - "358": false, - "359": false, - "360": false, - "361": false, - "362": false, - "363": false, - "364": false, - "365": false, - "366": false, - "367": false, - "368": false, - "369": false, - "370": false, - "371": false, - "372": false, - "373": false, - "374": false, - "375": false, - "376": false, - "377": false, - "378": false, - "379": false, - "380": false, - "381": false, - "382": false, - "383": false, - "384": false, - "385": false, - "386": false, - "387": false, - "388": false, - "389": false, - "390": false, - "391": false, - "392": false, - "393": false, - "394": false, - "395": false, - "396": false, - "397": false, - "398": false, - "399": false, - "400": false, - "401": false, - "402": false, - "403": false, - "404": false, - "405": false, - "406": false, - "407": false, - "408": false, - "409": false, - "410": false, - "411": false, - "412": false, - "413": false, - "414": false, - "415": false, - "416": false, - "417": false, - "418": false, - "419": false, - "420": false, - "421": false, - "422": false, - "423": false, - "424": false, - "425": false, - "426": false, - "427": false, - "428": false, - "429": false, - "430": false, - "431": false, - "432": false, - "433": false, - "434": false, - "435": false, - "436": true, - "437": false, - "438": false, - "439": false, - "440": false, - "441": false, - "442": false, - "443": false, - "444": false, - "445": false, - "446": false, - "447": false, - "448": false, - "449": false, - "450": false, - "451": false, - "452": false, - "453": false, - "454": false, - "455": false, - "456": false, - "457": false, - "458": false, - "459": false, - "460": false, - "461": false, - "462": false, - "463": false, - "464": false, - "465": false, - "466": false, - "467": false, - "468": false, - "469": false, - "470": false, - "471": false, - "472": false, - "473": false, - "474": false, - "475": false, - "476": false, - "477": false, - "478": false, - "479": false, - "480": false, - "481": false, - "482": false, - "483": false, - "484": false, - "485": false, - "486": false, - "487": false, - "488": false, - "489": false, - "490": false, - "491": false, - "492": false, - "493": false, - "494": false, - "495": false, - "496": false, - "497": false, - "498": false, - "499": false, - "500": false, - "501": false, - "502": false, - "503": false, - "504": false, - "505": false, - "506": false, - "507": false, - "508": false, - "509": false, - "510": false, - "511": false, - "512": false, - "513": false, - "514": false, - "515": false, - "516": false, - "517": false, - "518": false, - "519": false, - "520": false, - "521": false, - "522": false, - "523": false, - "524": false, - "525": false, - "526": false, - "527": false, - "528": false, - "529": false, - "530": false, - "531": false, - "532": false, - "533": false, - "534": false, - "535": false, - "536": false, - "537": false, - "538": false, - "539": false, - "540": false, - "541": false, - "542": false, - "543": false, - "544": false, - "545": false, - "546": false, - "547": false, - "548": false, - "549": false, - "550": false, - "551": false, - "552": false, - "553": false, - "554": false, - "555": false, - "556": false, - "557": false, - "558": false, - "559": false, - "560": false, - "561": false, - "562": false, - "563": false, - "564": false, - "565": false, - "566": false, - "567": false, - "568": false, - "569": false, - "570": false, - "571": false, - "572": false, - "573": false, - "574": false, - "575": false, - "576": false, - "577": false, - "578": false, - "579": false, - "580": false, - "581": false, - "582": false, - "583": false, - "584": false, - "585": false, - "586": false, - "587": false, - "588": false, - "589": false, - "590": false, - "591": false, - "592": false, - "593": false, - "594": false, - "595": false, - "596": false, - "597": false, - "598": false, - "599": false, - "600": false, - "601": false, - "602": false, - "603": false, - "604": false, - "605": false, - "606": false, - "607": false, - "608": false, - "609": false, - "610": false, - "611": false, - "612": false, - "613": false, - "614": false, - "615": false, - "616": false, - "617": false, - "618": false, - "619": false, - "620": false, - "621": false, - "622": false, - "623": false, - "624": false, - "625": false, - "626": false, - "627": false, - "628": false, - "629": false, - "630": false, - "631": false, - "632": false, - "633": false, - "634": false, - "635": false, - "636": false, - "637": false, - "638": false, - "639": false, - "640": false, - "641": false, - "642": false, - "643": false, - "644": false, - "645": false, - "646": false, - "647": false, - "648": false, - "649": false, - "650": false, - "651": false, - "652": false, - "653": false, - "654": false, - "655": false, - "656": false, - "657": false, - "658": false, - "659": false, - "660": false, - "661": false, - "662": false, - "663": false, - "664": false, - "665": false, - "666": false, - "667": false, - "668": false, - "669": false, - "670": false, - "671": false, - "672": false, - "673": false, - "674": false, - "675": false, - "676": false, - "677": false, - "678": false, - "679": false, - "680": false, - "681": false, - "682": false, - "683": false, - "684": false, - "685": false, - "686": false, - "687": false, - "688": false, - "689": false, - "690": false, - "691": false, - "692": false, - "693": false, - "694": false, - "695": false, - "696": false, - "697": false, - "698": false, - "699": false, - "700": false, - "701": false, - "702": false, - "703": false, - "704": false, - "705": false, - "706": false, - "707": false, - "708": false, - "709": false, - "710": false, - "711": false, - "712": false, - "713": false, - "714": false, - "715": false, - "716": false, - "717": false, - "718": false, - "719": false, - "720": false, - "721": false, - "722": false, - "723": false, - "724": false, - "725": false, - "726": false, - "727": false, - "728": false, - "729": false, - "730": false, - "731": false, - "732": false, - "733": false, - "734": false, - "735": false, - "736": false, - "737": false - }, - "legitimateInterests": { - "1": false, - "2": true, - "3": false, - "4": false, - "5": false, - "6": false, - "7": false, - "8": false, - "9": false, - "10": false, - "11": false, - "12": false, - "13": false, - "14": false, - "15": false, - "16": false, - "17": false, - "18": false, - "19": false, - "20": false, - "21": false, - "22": false, - "23": false, - "24": false, - "25": false, - "26": false, - "27": false, - "28": false, - "29": false, - "30": false, - "31": false, - "32": false, - "33": false, - "34": false, - "35": false, - "36": false, - "37": false, - "38": false, - "39": false, - "40": false, - "41": false, - "42": false, - "43": false, - "44": false, - "45": false, - "46": false, - "47": false, - "48": false, - "49": false, - "50": false, - "51": false, - "52": false, - "53": false, - "54": false, - "55": false, - "56": false, - "57": false, - "58": false, - "59": false, - "60": false, - "61": false, - "62": false, - "63": false, - "64": false, - "65": false, - "66": false, - "67": false, - "68": false, - "69": false, - "70": false, - "71": false, - "72": false, - "73": false, - "74": false, - "75": false, - "76": false, - "77": false, - "78": false, - "79": false, - "80": false, - "81": false, - "82": false, - "83": false, - "84": false, - "85": false, - "86": false, - "87": false, - "88": false, - "89": false, - "90": false, - "91": false, - "92": false, - "93": false, - "94": false, - "95": false, - "96": false, - "97": false, - "98": true, - "99": false, - "100": false, - "101": false, - "102": false, - "103": false, - "104": false, - "105": false, - "106": false, - "107": false, - "108": false, - "109": false, - "110": false, - "111": false, - "112": false, - "113": false, - "114": false, - "115": false, - "116": false, - "117": false, - "118": false, - "119": false, - "120": false, - "121": false, - "122": false, - "123": false, - "124": false, - "125": false, - "126": false, - "127": false, - "128": false, - "129": false, - "130": false, - "131": false, - "132": false, - "133": false, - "134": false, - "135": false, - "136": false, - "137": false, - "138": false, - "139": false, - "140": false, - "141": false, - "142": false, - "143": false, - "144": false, - "145": false, - "146": false, - "147": false, - "148": false, - "149": false, - "150": false, - "151": false, - "152": false, - "153": false, - "154": false, - "155": false, - "156": false, - "157": false, - "158": false, - "159": false, - "160": false, - "161": false, - "162": false, - "163": false, - "164": false, - "165": false, - "166": false, - "167": false, - "168": false, - "169": false, - "170": false, - "171": false, - "172": false, - "173": false, - "174": false, - "175": false, - "176": false, - "177": false, - "178": false, - "179": false, - "180": false, - "181": false, - "182": false, - "183": false, - "184": false, - "185": false, - "186": false, - "187": false, - "188": false, - "189": false, - "190": false, - "191": false, - "192": false, - "193": false, - "194": false, - "195": false, - "196": false, - "197": false, - "198": false, - "199": false, - "200": false, - "201": false, - "202": false, - "203": false, - "204": false, - "205": false, - "206": false, - "207": false, - "208": false, - "209": false, - "210": false, - "211": false, - "212": false, - "213": false, - "214": false, - "215": false, - "216": false, - "217": false, - "218": false, - "219": false, - "220": false, - "221": false, - "222": false, - "223": false, - "224": false, - "225": false, - "226": false, - "227": false, - "228": false, - "229": false, - "230": false, - "231": false, - "232": false, - "233": false, - "234": false, - "235": false, - "236": false, - "237": false, - "238": false, - "239": false, - "240": false, - "241": false, - "242": false, - "243": false, - "244": false, - "245": false, - "246": false, - "247": false, - "248": false, - "249": false, - "250": false, - "251": false, - "252": false, - "253": false, - "254": false, - "255": false, - "256": false, - "257": false, - "258": false, - "259": false, - "260": false, - "261": false, - "262": false, - "263": false, - "264": false, - "265": false, - "266": false, - "267": false, - "268": false, - "269": false, - "270": false, - "271": false, - "272": false, - "273": false, - "274": false, - "275": false, - "276": false, - "277": false, - "278": false, - "279": false, - "280": false, - "281": false, - "282": false, - "283": false, - "284": false, - "285": false, - "286": false, - "287": false, - "288": false, - "289": false, - "290": false, - "291": false, - "292": false, - "293": false, - "294": false, - "295": false, - "296": false, - "297": false, - "298": false, - "299": false, - "300": false, - "301": false, - "302": false, - "303": false, - "304": false, - "305": false, - "306": false, - "307": false, - "308": false, - "309": false, - "310": false, - "311": false, - "312": false, - "313": false, - "314": false, - "315": false, - "316": false, - "317": false, - "318": false, - "319": false, - "320": false, - "321": false, - "322": false, - "323": false, - "324": false, - "325": false, - "326": false, - "327": false, - "328": false, - "329": false, - "330": false, - "331": false, - "332": false, - "333": false, - "334": false, - "335": false, - "336": false, - "337": false, - "338": false, - "339": false, - "340": false, - "341": false, - "342": false, - "343": false, - "344": false, - "345": false, - "346": false, - "347": false, - "348": false, - "349": false, - "350": false, - "351": false, - "352": false, - "353": false, - "354": false, - "355": false, - "356": false, - "357": false, - "358": false, - "359": false, - "360": false, - "361": false, - "362": false, - "363": false, - "364": false, - "365": false, - "366": false, - "367": false, - "368": false, - "369": false, - "370": false, - "371": false, - "372": false, - "373": false, - "374": false, - "375": false, - "376": false, - "377": false, - "378": false, - "379": false, - "380": false, - "381": false, - "382": false, - "383": false, - "384": false, - "385": false, - "386": false, - "387": false, - "388": false, - "389": false, - "390": false, - "391": false, - "392": false, - "393": false, - "394": false, - "395": false, - "396": false, - "397": false, - "398": false, - "399": false, - "400": false, - "401": false, - "402": false, - "403": false, - "404": false, - "405": false, - "406": false, - "407": false, - "408": false, - "409": false, - "410": false, - "411": false, - "412": false, - "413": false, - "414": false, - "415": false, - "416": false, - "417": false, - "418": false, - "419": false, - "420": false, - "421": false, - "422": false, - "423": false, - "424": false, - "425": false, - "426": false, - "427": false, - "428": false, - "429": false, - "430": false, - "431": false, - "432": false, - "433": false, - "434": false, - "435": false, - "436": true, - "437": false, - "438": false, - "439": false, - "440": false, - "441": false, - "442": false, - "443": false, - "444": false, - "445": false, - "446": false, - "447": false, - "448": false, - "449": false, - "450": false, - "451": false, - "452": false, - "453": false, - "454": false, - "455": false, - "456": false, - "457": false, - "458": false, - "459": false, - "460": false, - "461": false, - "462": false, - "463": false, - "464": false, - "465": false, - "466": false, - "467": false, - "468": false, - "469": false, - "470": false, - "471": false, - "472": false, - "473": false, - "474": false, - "475": false, - "476": false, - "477": false, - "478": false, - "479": false, - "480": false, - "481": false, - "482": false, - "483": false, - "484": false, - "485": false, - "486": false, - "487": false, - "488": false, - "489": false, - "490": false, - "491": false, - "492": false, - "493": false, - "494": false, - "495": false, - "496": false, - "497": false, - "498": false, - "499": false, - "500": false, - "501": false, - "502": false, - "503": false, - "504": false, - "505": false, - "506": false, - "507": false, - "508": false, - "509": false, - "510": false, - "511": false, - "512": false, - "513": false, - "514": false, - "515": false, - "516": false, - "517": false, - "518": false, - "519": false, - "520": false, - "521": false, - "522": false, - "523": false, - "524": false, - "525": false, - "526": false, - "527": false, - "528": false, - "529": false, - "530": false, - "531": false, - "532": false, - "533": false, - "534": false, - "535": false, - "536": false, - "537": false, - "538": false, - "539": false, - "540": false, - "541": false, - "542": false, - "543": false, - "544": false, - "545": false, - "546": false, - "547": false, - "548": false, - "549": false, - "550": false, - "551": false, - "552": false, - "553": false, - "554": false, - "555": false, - "556": false, - "557": false, - "558": false, - "559": false, - "560": false, - "561": false, - "562": false, - "563": false, - "564": false, - "565": false, - "566": false, - "567": false, - "568": false, - "569": false, - "570": false, - "571": false, - "572": false, - "573": false, - "574": false, - "575": false, - "576": false, - "577": false, - "578": false, - "579": false, - "580": false, - "581": false, - "582": false, - "583": false, - "584": false, - "585": false, - "586": false, - "587": false, - "588": false, - "589": false, - "590": false, - "591": false, - "592": false, - "593": false, - "594": false, - "595": false, - "596": false, - "597": false, - "598": false, - "599": false, - "600": false, - "601": false, - "602": false, - "603": false, - "604": false, - "605": false, - "606": false, - "607": false, - "608": false, - "609": false, - "610": false, - "611": false, - "612": false, - "613": false, - "614": false, - "615": false, - "616": false, - "617": false, - "618": false, - "619": false, - "620": false, - "621": false, - "622": false, - "623": false, - "624": false, - "625": false, - "626": false, - "627": false, - "628": false, - "629": false, - "630": false, - "631": false, - "632": false, - "633": false, - "634": false, - "635": false, - "636": false, - "637": false, - "638": false, - "639": false, - "640": false, - "641": false, - "642": false, - "643": false, - "644": false, - "645": false, - "646": false, - "647": false, - "648": false, - "649": false, - "650": false, - "651": false, - "652": false, - "653": false, - "654": false, - "655": false, - "656": false, - "657": false, - "658": false, - "659": false, - "660": false, - "661": false, - "662": false, - "663": false, - "664": false, - "665": false, - "666": false, - "667": false, - "668": false, - "669": false, - "670": false, - "671": false, - "672": false, - "673": false, - "674": false, - "675": false, - "676": false, - "677": false, - "678": false, - "679": false, - "680": false, - "681": false, - "682": false, - "683": false, - "684": false, - "685": false, - "686": false, - "687": false, - "688": false, - "689": false, - "690": false, - "691": false, - "692": false, - "693": false, - "694": false, - "695": false, - "696": false, - "697": false, - "698": false, - "699": false, - "700": false, - "701": false, - "702": false, - "703": false, - "704": false, - "705": false, - "706": false, - "707": false, - "708": false, - "709": false, - "710": false, - "711": false, - "712": false, - "713": false, - "714": false, - "715": false, - "716": false, - "717": false, - "718": false, - "719": false, - "720": false, - "721": false, - "722": false, - "723": false, - "724": false, - "725": false, - "726": false, - "727": false, - "728": false, - "729": false, - "730": false, - "731": false, - "732": false, - "733": false, - "734": false, - "735": false, - "736": false, - "737": false - } - }, - "specialFeatureOptins": { - "1": false, - "2": false - }, - "restrictions": {}, - "publisher": { - "consents": { - "1": false, - "2": false, - "3": false, - "4": false, - "5": false, - "6": false, - "7": false, - "8": false, - "9": false, - "10": false - }, - "legitimateInterests": { - "1": false, - "2": false, - "3": false, - "4": false, - "5": false, - "6": false, - "7": false, - "8": false, - "9": false, - "10": false - }, - "customPurpose": { - "consents": {}, - "legitimateInterests": {} - } - } - } - } - } - } - }); - pbjs.addAdUnits(adUnits); pbjs.requestBids({ bidsBackHandler: sendAdserverRequest, @@ -1716,4 +88,4 @@
Div-1
- + \ No newline at end of file diff --git a/modules/gdprEnforcement.js b/modules/gdprEnforcement.js index 57f345b8f42..d3db5e54895 100644 --- a/modules/gdprEnforcement.js +++ b/modules/gdprEnforcement.js @@ -31,8 +31,8 @@ function getGvlid() { /** * This function takes in rules and consentData as input and validates against the consentData provided. If it returns true Prebid will allow the next call else it will log a warning - * @param {Object} rules - * @param {Object} consentData + * @param {Object} rules enforcement rules set in config + * @param {Object} consentData gdpr consent data * @returns {boolean} */ function validateRules(rule, consentData, currentModule, gvlid) { @@ -57,6 +57,12 @@ function validateRules(rule, consentData, currentModule, gvlid) { return isAllowed; } +/** + * This hook checks whether module has permission to access device or not. Device access include cookie and local storage + * @param {Function} fn reference to original function (used by hook logic) + * @param {Number=} gvlid gvlid of the module + * @param {string=} moduleName name of the module + */ export function deviceAccessHook(fn, gvlid, moduleName) { let result = { hasEnforcementHook: true @@ -81,12 +87,17 @@ export function deviceAccessHook(fn, gvlid, moduleName) { utils.logWarn(`User denied Permission for Device access for ${curModule}`); } } else { - utils.logInfo('TCF enforcement only applies to CMP version 2'); + utils.logInfo('GDPR enforcement only applies to CMP version 2'); } result.valid = false; return fn.call(this, result); } +/** + * This hook checks if a bidder has consent for user sync or not + * @param {Function} fn reference to original function (used by hook logic) + * @param {...any} args args + */ export function userSyncHook(fn, ...args) { const consentData = gdprDataHandler.getConsentData(); if (consentData && consentData.apiVersion === 2) { @@ -98,19 +109,25 @@ export function userSyncHook(fn, ...args) { if (isAllowed) { fn.call(this, ...args); } else { - utils.logWarn(`User sync not allowed for ${curBidder}`); + utils.logWarn(`User sync not allowed for ${curBidder}`); } } else { utils.logWarn(`User sync not allowed for ${curBidder}`); } } else { - utils.logInfo('TCF enforcement only applies to CMP version 2'); + utils.logInfo('GDPR enforcement only applies to CMP version 2'); fn.call(this, ...args); } } +/** + * This hook checks if user id module is given consent or not + * @param {Function} fn reference to original function (used by hook logic) + * @param {Submodule[]} submodules Array of user id submodules + * @param {Object} consentData GDPR consent data + */ export function userIdHook(fn, submodules, consentData) { - if (consentData && consentData.gdprApplies) { + if (consentData && consentData.gdprApplies && consentData.apiVersion === 2) { let userIdModules = submodules.map((submodule) => { const gvlid = submodule.submodule.gvlid; const moduleName = submodule.submodule.name; @@ -129,12 +146,17 @@ export function userIdHook(fn, submodules, consentData) { }).filter(module => module) fn.call(this, userIdModules, consentData); } else { + utils.logInfo('GDPR enforcement only applies to CMP version 2'); fn.call(this, submodules, consentData); } } const hasPurpose1 = (rule) => { return rule.purpose === purpose1 } +/** + * A configuration function that initializes some module variables, as well as add hooks + * @param {Object} config GDPR enforcement config object + */ export function setEnforcementConfig(config) { const rules = utils.deepAccess(config, 'gdpr.rules'); if (!rules) { diff --git a/test/spec/modules/gdprEnforcement_spec.js b/test/spec/modules/gdprEnforcement_spec.js index 84b37ddbe7b..740982bcd5b 100644 --- a/test/spec/modules/gdprEnforcement_spec.js +++ b/test/spec/modules/gdprEnforcement_spec.js @@ -257,13 +257,86 @@ describe('gdpr enforcement', function() { describe('userIdHook', function() { beforeEach(function() { - + logWarnSpy = sinon.spy(utils, 'logWarn'); + nextFnSpy = sinon.spy(); + }); + afterEach(function() { + config.resetConfig(); + logWarnSpy.restore(); + }); + it('should allow user id module if consent is given', function() { + setEnforcementConfig({ + gdpr: { + rules: [{ + purpose: 'storage', + enforcePurpose: false, + enforceVendor: true, + vendorExceptions: [] + }] + } + }); + let consentData = {} + consentData.vendorData = staticConfig.consentData.getTCData; + consentData.apiVersion = 2; + consentData.gdprApplies = true; + let submodules = [{ + submodule: { + gvlid: 1, + name: 'sampleUserId' + } + }] + userIdHook(nextFnSpy, submodules, consentData); + expect(nextFnSpy.calledOnce).to.equal(true); }); - afterEach(function(){ - }) - it('should', function() { + it('should allow userId module if gdpr not in scope', function() { + let submodules = [{ + submodule: { + gvlid: 1, + name: 'sampleUserId' + } + }]; + let consentData = null; + userIdHook(nextFnSpy, submodules, consentData); + expect(nextFnSpy.calledOnce).to.equal(true); + expect(nextFnSpy.calledWith(undefined, submodules, consentData)); + }); + it('should not allow user id module if user denied consent', function() { + setEnforcementConfig({ + gdpr: { + rules: [{ + purpose: 'storage', + enforcePurpose: false, + enforceVendor: true, + vendorExceptions: [] + }] + } + }); + let consentData = {} + consentData.vendorData = staticConfig.consentData.getTCData; + consentData.apiVersion = 2; + consentData.gdprApplies = true; + let submodules = [{ + submodule: { + gvlid: 1, + name: 'sampleUserId' + } + }, { + submodule: { + gvlid: 3, + name: 'sampleUserId1' + } + }] + userIdHook(nextFnSpy, submodules, consentData); + expect(logWarnSpy.callCount).to.equal(1); + let expectedSubmodules = [{ + submodule: { + gvlid: 1, + name: 'sampleUserId' + } + }] + expect(nextFnSpy.calledWith(undefined, expectedSubmodules, consentData)); }); }); }); From 185e93991c932882a75eb14e62c09013fd9ee669 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 23 Mar 2020 23:23:10 -0400 Subject: [PATCH 03/10] some updates and unit test --- modules/gdprEnforcement.js | 52 ++++++++++++++--------- src/storageManager.js | 16 +++++++ test/spec/modules/gdprEnforcement_spec.js | 28 ++++++++++++ 3 files changed, 76 insertions(+), 20 deletions(-) diff --git a/modules/gdprEnforcement.js b/modules/gdprEnforcement.js index d3db5e54895..d37c045bd7b 100644 --- a/modules/gdprEnforcement.js +++ b/modules/gdprEnforcement.js @@ -39,17 +39,17 @@ function validateRules(rule, consentData, currentModule, gvlid) { let isAllowed = false; if (rule.enforcePurpose && rule.enforceVendor) { if (includes(rule.vendorExceptions, currentModule) || - (consentData.vendorData.purpose.consents[1] === true && consentData.vendorData.vendor.consents[gvlid] === true)) { + (utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true && utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true)) { isAllowed = true; } } else if (rule.enforcePurpose === false && rule.enforceVendor === true) { if (includes(rule.vendorExceptions, currentModule) || - (consentData.vendorData.vendor.consents[gvlid] === true)) { + (utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true)) { isAllowed = true; } } else if (rule.enforcePurpose === false && rule.enforceVendor === false) { if ((includes(rule.vendorExceptions, currentModule) && - (consentData.vendorData.purpose.consents[1] === true && consentData.vendorData.vendor.consents[gvlid] === true)) || + (utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true && utils.deepAccess(consentData, `vendorData.vendor.consents${gvlid}`) === true)) || !includes(rule.vendorExceptions, currentModule)) { isAllowed = true; } @@ -63,6 +63,15 @@ function validateRules(rule, consentData, currentModule, gvlid) { * @param {Number=} gvlid gvlid of the module * @param {string=} moduleName name of the module */ + +// consent data is null as gdprapplies is false, but gdpr module is included +// this function will return false it should return true in this case + +// hasDeviceAccess has higher precedence so check for that first before everything +// it it returns false then module does not have access +// if it returns true then module may have access +// if gdpr flag is true + export function deviceAccessHook(fn, gvlid, moduleName) { let result = { hasEnforcementHook: true @@ -71,26 +80,29 @@ export function deviceAccessHook(fn, gvlid, moduleName) { utils.logWarn('Device access is disabled by Publisher'); result.valid = false; return fn.call(this, result); - } - const consentData = gdprDataHandler.getConsentData(); - if (consentData && consentData.apiVersion === 2) { - if (!gvlid) { - gvlid = getGvlid(); - } - const curModule = moduleName || config.getCurrentBidder(); - const purpose1Rule = find(enforcementRules, hasPurpose1); - let isAllowed = validateRules(purpose1Rule, consentData, curModule, gvlid); - if (isAllowed) { + } else { + const consentData = gdprDataHandler.getConsentData(); + if (consentData && consentData.gdprApplies && consentData.apiVersion === 2) { + if (!gvlid) { + gvlid = getGvlid(); + } + const curModule = moduleName || config.getCurrentBidder(); + const purpose1Rule = find(enforcementRules, hasPurpose1); + let isAllowed = validateRules(purpose1Rule, consentData, curModule, gvlid); + if (isAllowed) { + result.valid = true; + return fn.call(this, result); + } else { + utils.logWarn(`User denied Permission for Device access for ${curModule}`); + result.valid = false; + return fn.call(this, result); + } + } else { + utils.logInfo('GDPR enforcement only applies to CMP version 2'); result.valid = true; return fn.call(this, result); - } else { - utils.logWarn(`User denied Permission for Device access for ${curModule}`); } - } else { - utils.logInfo('GDPR enforcement only applies to CMP version 2'); } - result.valid = false; - return fn.call(this, result); } /** @@ -100,7 +112,7 @@ export function deviceAccessHook(fn, gvlid, moduleName) { */ export function userSyncHook(fn, ...args) { const consentData = gdprDataHandler.getConsentData(); - if (consentData && consentData.apiVersion === 2) { + if (consentData && consentData.gdprApplies && consentData.apiVersion === 2) { const gvlid = getGvlid(); const curBidder = config.getCurrentBidder(); if (gvlid) { diff --git a/src/storageManager.js b/src/storageManager.js index 015e22f5134..a9843feac4f 100644 --- a/src/storageManager.js +++ b/src/storageManager.js @@ -4,6 +4,22 @@ import includes from 'core-js/library/fn/array/includes.js'; const moduleTypeWhiteList = ['core', 'prebid-module']; +/** + * Storage options + * @typedef {Object} storageOptions + * @property {Number=} gvlid - Vendor id + * @property {string} moduleName - Module name + * @property {string=} moduleType - Module type, value can be anyone of core or prebid-module + */ + +/** + * Returns list of storage related functions with gvlid, module name and module type in its scope. + * All three argument are optional here. Below shows the usage of of these + * - GVL Id: Pass GVL id if you are a vendor + * - Module name: All modules need to pass module name + * - Module type: Some modules may need these functions but are not vendor. e.g prebid core files in src and modules like currency. + * @param {storageOptions} options + */ export function newStorageManager({gvlid, moduleName, moduleType} = {}) { function isValid() { if (includes(moduleTypeWhiteList, moduleType)) { diff --git a/test/spec/modules/gdprEnforcement_spec.js b/test/spec/modules/gdprEnforcement_spec.js index 740982bcd5b..9ed6395179a 100644 --- a/test/spec/modules/gdprEnforcement_spec.js +++ b/test/spec/modules/gdprEnforcement_spec.js @@ -148,6 +148,7 @@ describe('gdpr enforcement', function() { }); let consentData = {} consentData.vendorData = staticConfig.consentData.getTCData; + consentData.gdprApplies = true; consentData.apiVersion = 2; gdprDataHandlerStub.returns(consentData); @@ -155,6 +156,32 @@ describe('gdpr enforcement', function() { deviceAccessHook(nextFnSpy, 3, 'rubicon'); expect(logWarnSpy.callCount).to.equal(1); }); + + it('should allow device access when gdprApplies is false and hasDeviceAccess flag is true', function() { + setEnforcementConfig({ + gdpr: { + rules: [{ + purpose: 'storage', + enforcePurpose: true, + enforceVendor: true, + vendorExceptions: [] + }] + } + }); + let consentData = {} + consentData.vendorData = staticConfig.consentData.getTCData; + consentData.gdprApplies = false; + consentData.apiVersion = 2; + gdprDataHandlerStub.returns(consentData); + + deviceAccessHook(nextFnSpy, 1, 'appnexus'); + expect(nextFnSpy.calledOnce).to.equal(true); + let result = { + hasEnforcementHook: true, + valid: true + } + expect(nextFnSpy.calledWith(undefined, result)); + }); }); describe('userSyncHook', function() { @@ -229,6 +256,7 @@ describe('gdpr enforcement', function() { let consentData = {} consentData.vendorData = staticConfig.consentData.getTCData; consentData.apiVersion = 2; + consentData.gdprApplies = true; gdprDataHandlerStub.returns(consentData); curBidderStub.returns('sampleBidder1'); From 2efddad2f15be98949ce0c96938115f55d859724 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 23 Mar 2020 23:23:53 -0400 Subject: [PATCH 04/10] remove unwanted comment --- modules/gdprEnforcement.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/modules/gdprEnforcement.js b/modules/gdprEnforcement.js index d37c045bd7b..b90dc643baf 100644 --- a/modules/gdprEnforcement.js +++ b/modules/gdprEnforcement.js @@ -63,15 +63,6 @@ function validateRules(rule, consentData, currentModule, gvlid) { * @param {Number=} gvlid gvlid of the module * @param {string=} moduleName name of the module */ - -// consent data is null as gdprapplies is false, but gdpr module is included -// this function will return false it should return true in this case - -// hasDeviceAccess has higher precedence so check for that first before everything -// it it returns false then module does not have access -// if it returns true then module may have access -// if gdpr flag is true - export function deviceAccessHook(fn, gvlid, moduleName) { let result = { hasEnforcementHook: true From 227a4db3c7d0a323df872ca637d97b44875d42d1 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Sun, 29 Mar 2020 23:28:19 -0400 Subject: [PATCH 05/10] Adapter updates and some refactoring --- modules/aardvarkBidAdapter.js | 1 + modules/adagioBidAdapter.js | 11 +- modules/adkernelAdnAnalyticsAdapter.js | 6 +- modules/adspendBidAdapter.js | 8 +- modules/adtelligentBidAdapter.js | 1 + modules/aolBidAdapter.js | 1 + modules/appnexusBidAdapter.js | 5 +- modules/audigentRtdProvider.js | 7 +- modules/bidfluenceBidAdapter.js | 5 +- modules/browsiRtdProvider.js | 5 +- modules/categoryTranslation.js | 10 +- modules/ccxBidAdapter.js | 5 +- modules/cedatoBidAdapter.js | 5 +- modules/conversantBidAdapter.js | 11 +- modules/criteoBidAdapter.js | 10 +- modules/criteoIdSystem.js | 19 +- modules/digiTrustIdSystem.js | 7 +- modules/emoteevBidAdapter.js | 8 +- modules/eplanningBidAdapter.js | 15 +- modules/fidelityBidAdapter.js | 1 + modules/fintezaAnalyticsAdapter.js | 24 +- modules/gdprEnforcement.js | 153 +++++++----- modules/gumgumBidAdapter.js | 5 +- modules/invibesBidAdapter.js | 14 +- modules/ixBidAdapter.js | 1 + modules/kargoBidAdapter.js | 7 +- modules/liveIntentIdSystem.js | 5 +- modules/livewrappedBidAdapter.js | 5 +- modules/mantisBidAdapter.js | 12 +- modules/medianetBidAdapter.js | 1 + modules/mgidBidAdapter.js | 7 +- modules/nanointeractiveBidAdapter.js | 9 +- modules/newborntownWebBidAdapter.js | 9 +- modules/nobidBidAdapter.js | 7 +- modules/oneVideoBidAdapter.js | 1 + modules/openxBidAdapter.js | 1 + modules/orbidderBidAdapter.js | 6 +- modules/pubCommonId.js | 31 +-- modules/pubmaticBidAdapter.js | 1 + modules/pubwiseAnalyticsAdapter.js | 7 +- modules/pulsepointBidAdapter.js | 2 + modules/realvuAnalyticsAdapter.js | 13 +- modules/reloadBidAdapter.js | 8 +- modules/roxotAnalyticsAdapter.js | 15 +- modules/sigmoidAnalyticsAdapter.js | 19 +- modules/spotxBidAdapter.js | 1 + modules/staqAnalyticsAdapter.js | 7 +- modules/sublimeBidAdapter.js | 1 + modules/trionBidAdapter.js | 11 +- modules/unicornBidAdapter.js | 7 +- modules/userId/index.js | 18 +- modules/widespaceBidAdapter.js | 26 +- src/adapters/bidderFactory.js | 11 +- src/prebid.js | 15 ++ src/storageManager.js | 231 +++++++++++++----- src/userSync.js | 4 +- src/utils.js | 99 -------- .../spec/modules/bidfluenceBidAdapter_spec.js | 38 +-- test/spec/modules/categoryTranslation_spec.js | 4 +- .../spec/modules/conversantBidAdapter_spec.js | 22 +- test/spec/modules/criteoIdSystem_spec.js | 12 +- test/spec/modules/emoteevBidAdapter_spec.js | 17 +- test/spec/modules/eplanningBidAdapter_spec.js | 87 ++++--- test/spec/modules/gdprEnforcement_spec.js | 49 ++++ test/spec/modules/liveIntentIdSystem_spec.js | 6 +- .../modules/livewrappedBidAdapter_spec.js | 42 ++-- .../modules/newborntownWebBidAdapter_spec.js | 2 +- test/spec/modules/parrableIdSystem_spec.js | 7 +- test/spec/modules/userId_spec.js | 158 ++++++------ test/spec/modules/widespaceBidAdapter_spec.js | 13 +- test/spec/unit/core/bidderFactory_spec.js | 4 +- test/spec/unit/core/storageManager_spec.js | 43 ++++ 72 files changed, 858 insertions(+), 581 deletions(-) create mode 100644 test/spec/unit/core/storageManager_spec.js diff --git a/modules/aardvarkBidAdapter.js b/modules/aardvarkBidAdapter.js index 848a6672022..0b864286868 100644 --- a/modules/aardvarkBidAdapter.js +++ b/modules/aardvarkBidAdapter.js @@ -15,6 +15,7 @@ export function resetUserSync() { export const spec = { code: BIDDER_CODE, + gvlid: 52, aliases: ['adsparc', 'safereach'], isBidRequestValid: function(bid) { diff --git a/modules/adagioBidAdapter.js b/modules/adagioBidAdapter.js index d24350542a4..8b593c34270 100644 --- a/modules/adagioBidAdapter.js +++ b/modules/adagioBidAdapter.js @@ -4,6 +4,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import { loadExternalScript } from '../src/adloader.js' import JSEncrypt from 'jsencrypt/bin/jsencrypt.js'; import sha256 from 'crypto-js/sha256.js'; +import { getStorageManager } from '../src/storageManager.js'; const BIDDER_CODE = 'adagio'; const VERSION = '2.1.0'; @@ -12,6 +13,8 @@ const ENDPOINT = 'https://mp.4dex.io/prebid'; const SUPPORTED_MEDIA_TYPES = ['banner']; const ADAGIO_TAG_URL = 'https://script.4dex.io/localstore.js'; const ADAGIO_LOCALSTORAGE_KEY = 'adagioScript'; +const GVLID = 617; +const storage = getStorageManager(GVLID); export const ADAGIO_PUBKEY = `-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9el0+OEn6fvEh1RdVHQu4cnT0 @@ -22,7 +25,7 @@ pV6EP3MTLosuUEpLaQIDAQAB export function getAdagioScript() { try { - const ls = utils.getDataFromLocalStorage(ADAGIO_LOCALSTORAGE_KEY); + const ls = storage.getDataFromLocalStorage(ADAGIO_LOCALSTORAGE_KEY); if (!ls) { utils.logWarn('Adagio Script not found'); @@ -33,7 +36,7 @@ export function getAdagioScript() { if (!hashRgx.test(ls)) { utils.logWarn('No hash found in Adagio script'); - utils.removeDataFromLocalStorage(ADAGIO_LOCALSTORAGE_KEY); + storage.removeDataFromLocalStorage(ADAGIO_LOCALSTORAGE_KEY); } else { const r = ls.match(hashRgx); const hash = r[2]; @@ -47,7 +50,7 @@ export function getAdagioScript() { Function(ls)(); // eslint-disable-line no-new-func } else { utils.logWarn('Invalid Adagio script found'); - utils.removeDataFromLocalStorage(ADAGIO_LOCALSTORAGE_KEY); + storage.removeDataFromLocalStorage(ADAGIO_LOCALSTORAGE_KEY); } } } catch (err) { @@ -341,7 +344,7 @@ function _getGdprConsent(bidderRequest) { export const spec = { code: BIDDER_CODE, - + gvlid: GVLID, supportedMediaType: SUPPORTED_MEDIA_TYPES, isBidRequestValid: function (bid) { diff --git a/modules/adkernelAdnAnalyticsAdapter.js b/modules/adkernelAdnAnalyticsAdapter.js index 43cda60b0ec..b0bdadf57d0 100644 --- a/modules/adkernelAdnAnalyticsAdapter.js +++ b/modules/adkernelAdnAnalyticsAdapter.js @@ -4,10 +4,12 @@ import adapterManager from '../src/adapterManager.js'; import {parse} from '../src/url.js'; import * as utils from '../src/utils.js'; import {ajax} from '../src/ajax.js'; +import { getStorageManager } from '../src/storageManager.js'; const ANALYTICS_VERSION = '1.0.1'; const DEFAULT_QUEUE_TIMEOUT = 4000; const DEFAULT_HOST = 'tag.adkernel.com'; +const storageObj = getStorageManager(); const ADK_HB_EVENTS = { AUCTION_INIT: 'auctionInit', @@ -175,10 +177,10 @@ const ORGANIC = '(organic)'; export let storage = { getItem: (name) => { - return utils.getDataFromLocalStorage(name); + return storageObj.getDataFromLocalStorage(name); }, setItem: (name, value) => { - utils.setDataInLocalStorage(name, value); + storageObj.setDataInLocalStorage(name, value); } }; diff --git a/modules/adspendBidAdapter.js b/modules/adspendBidAdapter.js index 3342a1934cc..9fe70885eeb 100644 --- a/modules/adspendBidAdapter.js +++ b/modules/adspendBidAdapter.js @@ -3,7 +3,9 @@ import { ajax } from '../src/ajax.js' import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; +import { getStorageManager } from '../src/storageManager.js'; +const storage = getStorageManager(); const BIDDER_CODE = 'adspend'; const BID_URL = 'https://rtb.com.ru/headerbidding-bid'; const SYNC_URL = 'https://rtb.com.ru/headerbidding-sync?uid={UUID}'; @@ -40,7 +42,7 @@ export const spec = { bid.params.bidfloor && bid.crumbs.pubcid && utils.checkCookieSupport() && - utils.cookiesAreEnabled() + storage.cookiesAreEnabled() ); }, @@ -145,11 +147,11 @@ export const spec = { } const getUserID = () => { - const i = utils.getCookie(COOKIE_NAME); + const i = storage.getCookie(COOKIE_NAME); if (i === null) { const uuid = utils.generateUUID(); - utils.setCookie(COOKIE_NAME, uuid); + storage.setCookie(COOKIE_NAME, uuid); return uuid; } return i; diff --git a/modules/adtelligentBidAdapter.js b/modules/adtelligentBidAdapter.js index 5749866b65b..82601117017 100644 --- a/modules/adtelligentBidAdapter.js +++ b/modules/adtelligentBidAdapter.js @@ -13,6 +13,7 @@ const syncsCache = {}; export const spec = { code: BIDDER_CODE, + gvlid: 410, aliases: ['onefiftytwomedia', 'selectmedia'], supportedMediaTypes: [VIDEO, BANNER], isBidRequestValid: function (bid) { diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index d5fb2970628..d7ff7453870 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -100,6 +100,7 @@ function resolveEndpointCode(bid) { export const spec = { code: AOL_BIDDERS_CODES.AOL, + gvlid: 25, aliases: [AOL_BIDDERS_CODES.ONEMOBILE, AOL_BIDDERS_CODES.ONEDISPLAY], supportedMediaTypes: [BANNER], isBidRequestValid(bid) { diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 92d1dcf24d2..49bbf363199 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -7,7 +7,7 @@ import { auctionManager } from '../src/auctionManager.js'; import find from 'core-js/library/fn/array/find.js'; import includes from 'core-js/library/fn/array/includes.js'; import { OUTSTREAM, INSTREAM } from '../src/video.js'; -import { newStorageManager } from '../src/storageManager.js'; +import { getStorageManager } from '../src/storageManager.js'; const BIDDER_CODE = 'appnexus'; const URL = 'https://ib.adnxs.com/ut/v3/prebid'; @@ -40,7 +40,7 @@ const SCRIPT_TAG_START = ' 0)) { - storedValue = utils.getDataFromLocalStorage(key); + storedValue = storage.getDataFromLocalStorage(key); storedValue = storedValue ? decodeURIComponent(storedValue) : storedValue; } } diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index caebb12c717..65675248208 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -6,13 +6,16 @@ import { parse } from '../src/url.js'; import * as utils from '../src/utils.js'; import find from 'core-js/library/fn/array/find.js'; import { verify } from 'criteo-direct-rsa-validate/build/verify.js'; +import { getStorageManager } from '../src/storageManager.js'; +const GVLID = 91; export const ADAPTER_VERSION = 26; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = 'https://bidder.criteo.com/cdb'; const CRITEO_VENDOR_ID = 91; const PROFILE_ID_INLINE = 207; export const PROFILE_ID_PUBLISHERTAG = 185; +const storage = getStorageManager(GVLID); // Unminified source code can be found in: https://github.com/Prebid-org/prebid-js-external-js-criteo/blob/master/dist/prod.js const PUBLISHER_TAG_URL = 'https://static.criteo.net/js/ld/publishertag.prebid.js'; @@ -23,6 +26,7 @@ const FAST_BID_PUBKEY_N = 'ztQYwCE5BU7T9CDM5he6rKoabstXRmkzx54zFPZkWbK530dwtLBDe /** @type {BidderSpec} */ export const spec = { code: BIDDER_CODE, + gvlid: GVLID, supportedMediaTypes: [ BANNER, VIDEO, NATIVE ], /** @@ -423,7 +427,7 @@ export function tryGetCriteoFastBid() { try { const fastBidStorageKey = 'criteo_fast_bid'; const hashPrefix = '// Hash: '; - const fastBidFromStorage = utils.getDataFromLocalStorage(fastBidStorageKey); + const fastBidFromStorage = storage.getDataFromLocalStorage(fastBidStorageKey); if (fastBidFromStorage !== null) { // The value stored must contain the file's encrypted hash as first line @@ -432,7 +436,7 @@ export function tryGetCriteoFastBid() { if (firstLine.substr(0, hashPrefix.length) !== hashPrefix) { utils.logWarn('No hash found in FastBid'); - utils.removeDataFromLocalStorage(fastBidStorageKey); + storage.removeDataFromLocalStorage(fastBidStorageKey); } else { // Remove the hash part from the locally stored value const publisherTagHash = firstLine.substr(hashPrefix.length); @@ -446,7 +450,7 @@ export function tryGetCriteoFastBid() { utils.insertElement(script); } else { utils.logWarn('Invalid Criteo FastBid found'); - utils.removeDataFromLocalStorage(fastBidStorageKey); + storage.removeDataFromLocalStorage(fastBidStorageKey); } } } diff --git a/modules/criteoIdSystem.js b/modules/criteoIdSystem.js index 469532e4aa7..0103db8ef80 100644 --- a/modules/criteoIdSystem.js +++ b/modules/criteoIdSystem.js @@ -10,6 +10,9 @@ import * as ajax from '../src/ajax.js' import * as urlLib from '../src/url.js' import { getRefererInfo } from '../src/refererDetection.js' import { submodule } from '../src/hook.js'; +import { getStorageManager } from '../src/storageManager.js'; + +export const storage = getStorageManager(); const bididStorageKey = 'cto_bidid'; const bundleStorageKey = 'cto_bundle'; @@ -20,9 +23,9 @@ const pastDateString = new Date(0).toString(); const expirationString = new Date(utils.timestamp() + cookiesMaxAge).toString(); function areCookiesWriteable() { - utils.setCookie(cookieWriteableKey, '1'); - const canWrite = utils.getCookie(cookieWriteableKey) === '1'; - utils.setCookie(cookieWriteableKey, '', pastDateString); + storage.setCookie(cookieWriteableKey, '1'); + const canWrite = storage.getCookie(cookieWriteableKey) === '1'; + storage.setCookie(cookieWriteableKey, '', pastDateString); return canWrite; } @@ -34,19 +37,19 @@ function extractProtocolHost (url, returnOnlyHost = false) { } function getFromAllStorages(key) { - return utils.getCookie(key) || utils.getDataFromLocalStorage(key); + return storage.getCookie(key) || storage.getDataFromLocalStorage(key); } function saveOnAllStorages(key, value) { if (key && value) { - utils.setCookie(key, value, expirationString); - utils.setDataInLocalStorage(key, value); + storage.setCookie(key, value, expirationString); + storage.setDataInLocalStorage(key, value); } } function deleteFromAllStorages(key) { - utils.setCookie(key, '', pastDateString); - utils.removeDataFromLocalStorage(key); + storage.setCookie(key, '', pastDateString); + storage.removeDataFromLocalStorage(key); } function getCriteoDataFromAllStorages() { diff --git a/modules/digiTrustIdSystem.js b/modules/digiTrustIdSystem.js index 9d0b5c25e1b..8ae49b20b26 100644 --- a/modules/digiTrustIdSystem.js +++ b/modules/digiTrustIdSystem.js @@ -12,6 +12,10 @@ import * as utils from '../src/utils.js' import { ajax } from '../src/ajax.js'; import { submodule } from '../src/hook.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const DT_VENDOR_ID = 64; // cmp gvlVendorId +const storage = getStorageManager(DT_VENDOR_ID); var fallbackTimeout = 1550; // timeout value that allows userId system to execute first var fallbackTimer = 0; // timer Id for fallback init so we don't double call @@ -40,7 +44,6 @@ var noop = function () { const MAX_RETRIES = 2; const DT_ID_SVC = 'https://prebid.digitru.st/id/v1'; -const DT_VENDOR_ID = 64; // cmp gvlVendorId var isFunc = function (fn) { return typeof (fn) === 'function'; @@ -83,7 +86,7 @@ function writeDigiId(id) { var key = 'DigiTrust.v1.identity'; var date = new Date(); date.setTime(date.getTime() + 604800000); - utils.setCookie(key, encId(id), date.toUTCString(), 'none'); + storage.setCookie(key, encId(id), date.toUTCString(), 'none'); } /** diff --git a/modules/emoteevBidAdapter.js b/modules/emoteevBidAdapter.js index 254373b354a..0bdf4cda58e 100644 --- a/modules/emoteevBidAdapter.js +++ b/modules/emoteevBidAdapter.js @@ -23,11 +23,13 @@ import { deepAccess, isArray, isInteger, - getParameterByName, - getCookie + getParameterByName } from '../src/utils.js'; import {config} from '../src/config.js'; import * as url from '../src/url.js'; +import { getStorageManager } from '../src/storageManager.js'; + +export const storage = getStorageManager(); export const BIDDER_CODE = 'emoteev'; @@ -508,7 +510,7 @@ export const spec = { onBidWon: (bidObject) => triggerPixel(url.format(onBidWon( resolveEnv(config.getConfig(), getParameterByName('emoteevEnv')), - getCookie('_pubcid'), + storage.getCookie('_pubcid'), bidObject))), onTimeout: (bidRequest) => triggerPixel(url.format(onTimeout( diff --git a/modules/eplanningBidAdapter.js b/modules/eplanningBidAdapter.js index 979f6dbf464..a4b4f2d6728 100644 --- a/modules/eplanningBidAdapter.js +++ b/modules/eplanningBidAdapter.js @@ -1,5 +1,8 @@ import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { getStorageManager } from '../src/storageManager.js'; + +export const storage = getStorageManager(); const BIDDER_CODE = 'eplanning'; const rnd = Math.random(); @@ -43,7 +46,7 @@ export const spec = { url = 'https://' + (urlConfig.sv || DEFAULT_SV) + '/hb/1/' + urlConfig.ci + '/' + dfpClientId + '/' + getDomain(pageUrl) + '/' + sec; const referrerUrl = bidderRequest.refererInfo.referer.reachedTop ? encodeURIComponent(window.top.document.referrer) : encodeURIComponent(bidderRequest.refererInfo.referer); - if (utils.hasLocalStorage()) { + if (storage.hasLocalStorage()) { registerViewabilityAllBids(bidRequests); } @@ -204,7 +207,7 @@ function getSpaces(bidRequests, ml) { function getVs(bid) { let s; let vs = ''; - if (utils.hasLocalStorage()) { + if (storage.hasLocalStorage()) { s = getViewabilityData(bid); vs += s.render >= 4 ? s.ratio.toString(16) : 'F'; } else { @@ -214,8 +217,8 @@ function getVs(bid) { } function getViewabilityData(bid) { - let r = utils.getDataFromLocalStorage(STORAGE_RENDER_PREFIX + bid.adUnitCode) || 0; - let v = utils.getDataFromLocalStorage(STORAGE_VIEW_PREFIX + bid.adUnitCode) || 0; + let r = storage.getDataFromLocalStorage(STORAGE_RENDER_PREFIX + bid.adUnitCode) || 0; + let v = storage.getDataFromLocalStorage(STORAGE_VIEW_PREFIX + bid.adUnitCode) || 0; let ratio = r > 0 ? (v / r) : 0; return { render: r, @@ -408,9 +411,9 @@ function visibilityHandler(obj) { function registerAuction(storageID) { let value; try { - value = utils.getDataFromLocalStorage(storageID); + value = storage.getDataFromLocalStorage(storageID); value = value ? window.parseInt(value, 10) + 1 : 1; - utils.setDataInLocalStorage(storageID, value); + storage.setDataInLocalStorage(storageID, value); } catch (exc) { return false; } diff --git a/modules/fidelityBidAdapter.js b/modules/fidelityBidAdapter.js index a0589986af3..7bca0745cc5 100644 --- a/modules/fidelityBidAdapter.js +++ b/modules/fidelityBidAdapter.js @@ -6,6 +6,7 @@ const BIDDER_SERVER = 'x.fidelity-media.com'; const FIDELITY_VENDOR_ID = 408; export const spec = { code: BIDDER_CODE, + gvlid: 408, isBidRequestValid: function isBidRequestValid(bid) { return !!(bid && bid.params && bid.params.zoneid); }, diff --git a/modules/fintezaAnalyticsAdapter.js b/modules/fintezaAnalyticsAdapter.js index 41343cdf371..f454e6b3acb 100644 --- a/modules/fintezaAnalyticsAdapter.js +++ b/modules/fintezaAnalyticsAdapter.js @@ -3,7 +3,9 @@ import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import * as utils from '../src/utils.js'; import { parse as parseURL } from '../src/url.js'; +import { getStorageManager } from '../src/storageManager.js'; +const storage = getStorageManager(); const CONSTANTS = require('../src/constants.json'); const ANALYTICS_TYPE = 'endpoint'; @@ -46,8 +48,8 @@ function getUniqId() { let uniq = cookies[ UNIQ_ID_KEY ]; if (!uniq) { try { - if (utils.hasLocalStorage()) { - uniq = utils.getDataFromLocalStorage(UNIQ_ID_KEY) || ''; + if (storage.hasLocalStorage()) { + uniq = storage.getDataFromLocalStorage(UNIQ_ID_KEY) || ''; isUniqFromLS = true; } } catch (b) {} @@ -62,7 +64,7 @@ function getUniqId() { expires.setFullYear(expires.getFullYear() + 10); try { - utils.setCookie(UNIQ_ID_KEY, uniq, expires.toUTCString()); + storage.setCookie(UNIQ_ID_KEY, uniq, expires.toUTCString()); } catch (e) {} } @@ -90,7 +92,7 @@ function initFirstVisit() { now.setFullYear(now.getFullYear() + 20); try { - utils.setCookie(FIRST_VISIT_DATE, visitDate, now.toUTCString()); + storage.setCookie(FIRST_VISIT_DATE, visitDate, now.toUTCString()); } catch (e) {} } @@ -110,7 +112,7 @@ function parseCookies(cookie) { let param, value; let i, j; - if (!cookie || !utils.cookiesAreEnabled()) { + if (!cookie || !storage.cookiesAreEnabled()) { return {}; } @@ -203,7 +205,7 @@ function initSession() { } try { - utils.setCookie(SESSION_ID, sessionId, expires.toUTCString()); + storage.setCookie(SESSION_ID, sessionId, expires.toUTCString()); } catch (e) {} return { @@ -249,10 +251,10 @@ function saveTrackRequestTime() { const expires = new Date(now + SESSION_DURATION); try { - if (utils.hasLocalStorage()) { - utils.setDataInLocalStorage(TRACK_TIME_KEY, now.toString()); + if (storage.hasLocalStorage()) { + storage.setDataInLocalStorage(TRACK_TIME_KEY, now.toString()); } else { - utils.setCookie(TRACK_TIME_KEY, now.toString(), expires.toUTCString()); + storage.setCookie(TRACK_TIME_KEY, now.toString(), expires.toUTCString()); } } catch (a) {} } @@ -261,9 +263,9 @@ function getTrackRequestLastTime() { let cookie; try { - if (utils.hasLocalStorage()) { + if (storage.hasLocalStorage()) { return parseInt( - utils.getDataFromLocalStorage(TRACK_TIME_KEY) || 0, + storage.getDataFromLocalStorage(TRACK_TIME_KEY) || 0, 10, ); } diff --git a/modules/gdprEnforcement.js b/modules/gdprEnforcement.js index b90dc643baf..b1c53c14d11 100644 --- a/modules/gdprEnforcement.js +++ b/modules/gdprEnforcement.js @@ -24,7 +24,7 @@ function getGvlid() { const bidder = adapterManager.getBidAdapter(bidderCode); gvlid = bidder.getSpec().gvlid; } else { - utils.logWarn('Current bidder not found'); + utils.logWarn('Current module not found'); } return gvlid; } @@ -38,19 +38,47 @@ function getGvlid() { function validateRules(rule, consentData, currentModule, gvlid) { let isAllowed = false; if (rule.enforcePurpose && rule.enforceVendor) { - if (includes(rule.vendorExceptions, currentModule) || - (utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true && utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true)) { + if ( + includes(rule.vendorExceptions, currentModule) || + ( + utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true && + utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true + ) + ) { isAllowed = true; } } else if (rule.enforcePurpose === false && rule.enforceVendor === true) { - if (includes(rule.vendorExceptions, currentModule) || - (utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true)) { + if ( + includes(rule.vendorExceptions, currentModule) || + ( + utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true + ) + ) { isAllowed = true; } } else if (rule.enforcePurpose === false && rule.enforceVendor === false) { - if ((includes(rule.vendorExceptions, currentModule) && - (utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true && utils.deepAccess(consentData, `vendorData.vendor.consents${gvlid}`) === true)) || - !includes(rule.vendorExceptions, currentModule)) { + if ( + ( + includes(rule.vendorExceptions, currentModule) && + (utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true) && + (utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true) + ) || + !includes(rule.vendorExceptions, currentModule) + ) { + isAllowed = true; + } + } else if (rule.enforcePurpose === true && rule.enforceVendor === false) { + if ( + ( + !includes(rule.vendorExceptions, currentModule) && + (utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true) + ) || + ( + includes(rule.vendorExceptions, currentModule) && + (utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true) && + (utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true) + ) + ) { isAllowed = true; } } @@ -63,35 +91,40 @@ function validateRules(rule, consentData, currentModule, gvlid) { * @param {Number=} gvlid gvlid of the module * @param {string=} moduleName name of the module */ -export function deviceAccessHook(fn, gvlid, moduleName) { - let result = { +export function deviceAccessHook(fn, gvlid, moduleName, result) { + result = Object.assign({}, { hasEnforcementHook: true - } + }); if (!hasDeviceAccess()) { utils.logWarn('Device access is disabled by Publisher'); result.valid = false; - return fn.call(this, result); + fn.call(this, gvlid, moduleName, result); } else { const consentData = gdprDataHandler.getConsentData(); - if (consentData && consentData.gdprApplies && consentData.apiVersion === 2) { - if (!gvlid) { - gvlid = getGvlid(); - } - const curModule = moduleName || config.getCurrentBidder(); - const purpose1Rule = find(enforcementRules, hasPurpose1); - let isAllowed = validateRules(purpose1Rule, consentData, curModule, gvlid); - if (isAllowed) { - result.valid = true; - return fn.call(this, result); + if (consentData && consentData.gdprApplies) { + if (consentData.apiVersion === 2) { + if (!gvlid) { + gvlid = getGvlid(); + } + const curModule = moduleName || config.getCurrentBidder(); + const purpose1Rule = find(enforcementRules, hasPurpose1); + let isAllowed = validateRules(purpose1Rule, consentData, curModule, gvlid); + if (isAllowed) { + result.valid = true; + fn.call(this, gvlid, moduleName, result); + } else { + utils.logWarn(`User denied Permission for Device access for ${curModule}`); + result.valid = false; + fn.call(this, gvlid, moduleName, result); + } } else { - utils.logWarn(`User denied Permission for Device access for ${curModule}`); - result.valid = false; - return fn.call(this, result); + utils.logInfo('Enforcing TCF2 only'); + result.valid = true; + fn.call(this, gvlid, moduleName, result); } } else { - utils.logInfo('GDPR enforcement only applies to CMP version 2'); result.valid = true; - return fn.call(this, result); + fn.call(this, gvlid, moduleName, result); } } } @@ -103,22 +136,26 @@ export function deviceAccessHook(fn, gvlid, moduleName) { */ export function userSyncHook(fn, ...args) { const consentData = gdprDataHandler.getConsentData(); - if (consentData && consentData.gdprApplies && consentData.apiVersion === 2) { - const gvlid = getGvlid(); - const curBidder = config.getCurrentBidder(); - if (gvlid) { - const purpose1Rule = find(enforcementRules, hasPurpose1); - let isAllowed = validateRules(purpose1Rule, consentData, curBidder, gvlid); - if (isAllowed) { - fn.call(this, ...args); + if (consentData && consentData.gdprApplies) { + if (consentData.apiVersion === 2) { + const gvlid = getGvlid(); + const curBidder = config.getCurrentBidder(); + if (gvlid) { + const purpose1Rule = find(enforcementRules, hasPurpose1); + let isAllowed = validateRules(purpose1Rule, consentData, curBidder, gvlid); + if (isAllowed) { + fn.call(this, ...args); + } else { + utils.logWarn(`User sync not allowed for ${curBidder}`); + } } else { utils.logWarn(`User sync not allowed for ${curBidder}`); } } else { - utils.logWarn(`User sync not allowed for ${curBidder}`); + utils.logInfo('Enforcing TCF2 only'); + fn.call(this, ...args); } } else { - utils.logInfo('GDPR enforcement only applies to CMP version 2'); fn.call(this, ...args); } } @@ -130,26 +167,30 @@ export function userSyncHook(fn, ...args) { * @param {Object} consentData GDPR consent data */ export function userIdHook(fn, submodules, consentData) { - if (consentData && consentData.gdprApplies && consentData.apiVersion === 2) { - let userIdModules = submodules.map((submodule) => { - const gvlid = submodule.submodule.gvlid; - const moduleName = submodule.submodule.name; - if (gvlid) { - const purpose1Rule = find(enforcementRules, hasPurpose1); - let isAllowed = validateRules(purpose1Rule, consentData, moduleName, gvlid); - if (isAllowed) { - return submodule; + if (consentData && consentData.gdprApplies) { + if (consentData.apiVersion === 2) { + let userIdModules = submodules.map((submodule) => { + const gvlid = submodule.submodule.gvlid; + const moduleName = submodule.submodule.name; + if (gvlid) { + const purpose1Rule = find(enforcementRules, hasPurpose1); + let isAllowed = validateRules(purpose1Rule, consentData, moduleName, gvlid); + if (isAllowed) { + return submodule; + } else { + utils.logWarn(`User denied permission to fetch user id for ${moduleName} User id module`); + } } else { utils.logWarn(`User denied permission to fetch user id for ${moduleName} User id module`); } - } else { - utils.logWarn(`User denied permission to fetch user id for ${moduleName} User id module`); - } - return undefined; - }).filter(module => module) - fn.call(this, userIdModules, consentData); + return undefined; + }).filter(module => module) + fn.call(this, userIdModules, consentData); + } else { + utils.logInfo('Enforcing TCF2 only'); + fn.call(this, submodules, consentData); + } } else { - utils.logInfo('GDPR enforcement only applies to CMP version 2'); fn.call(this, submodules, consentData); } } @@ -171,10 +212,10 @@ export function setEnforcementConfig(config) { const hasDefinedPurpose1 = find(enforcementRules, hasPurpose1); if (hasDefinedPurpose1 && !addedDeviceAccessHook) { addedDeviceAccessHook = true; - validateStorageEnforcement.before(deviceAccessHook); - registerSyncInner.before(userSyncHook); + validateStorageEnforcement.before(deviceAccessHook, 49); + registerSyncInner.before(userSyncHook, 48); // Using getHook as user id and gdprEnforcement are both optional modules. Using import will auto include the file in build - getHook('validateGdprEnforcement').before(userIdHook); + getHook('validateGdprEnforcement').before(userIdHook, 47); } } diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index baa79ecfe04..3a347163e6d 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -4,6 +4,9 @@ import { config } from '../src/config.js' import { BANNER, VIDEO } from '../src/mediaTypes.js'; import includes from 'core-js/library/fn/array/includes.js'; import { registerBidder } from '../src/adapters/bidderFactory.js' +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); const BIDDER_CODE = 'gumgum' const ALIAS_BIDDER_CODE = ['gg'] @@ -55,7 +58,7 @@ function _getBrowserParams(topWindowUrl) { sw: topScreen.width, sh: topScreen.height, pu: topUrl, - ce: utils.cookiesAreEnabled(), + ce: storage.cookiesAreEnabled(), dpr: topWindow.devicePixelRatio || 1, jcsi: JSON.stringify({ t: 0, rq: 8 }), ogu: getOgURL() diff --git a/modules/invibesBidAdapter.js b/modules/invibesBidAdapter.js index 95737c15c3d..e839c173a93 100644 --- a/modules/invibesBidAdapter.js +++ b/modules/invibesBidAdapter.js @@ -1,5 +1,7 @@ import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { getStorageManager } from '../src/storageManager.js'; +const storage = getStorageManager(); const CONSTANTS = { BIDDER_CODE: 'invibes', @@ -276,14 +278,14 @@ function getCappedCampaignsAsString() { let loadData = function () { try { - return JSON.parse(utils.getDataFromLocalStorage(key)) || {}; + return JSON.parse(storage.getDataFromLocalStorage(key)) || {}; } catch (e) { return {}; } }; let saveData = function (data) { - utils.setDataInLocalStorage(key, JSON.stringify(data)); + storage.setDataInLocalStorage(key, JSON.stringify(data)); }; let clearExpired = function () { @@ -319,7 +321,7 @@ function getCappedCampaignsAsString() { const noop = function () { }; function initLogger() { - if (utils.hasLocalStorage() && localStorage.InvibesDEBUG) { + if (storage.hasLocalStorage() && localStorage.InvibesDEBUG) { return window.console; } @@ -384,7 +386,7 @@ invibes.Uid = { let cookieDomain; invibes.getCookie = function (name) { - if (!utils.cookiesAreEnabled()) { return; } + if (!storage.cookiesAreEnabled()) { return; } let i, x, y; let cookies = document.cookie.split(';'); for (i = 0; i < cookies.length; i++) { @@ -398,7 +400,7 @@ invibes.getCookie = function (name) { }; invibes.setCookie = function (name, value, exdays, domain) { - if (!utils.cookiesAreEnabled()) { return; } + if (!storage.cookiesAreEnabled()) { return; } let whiteListed = name == 'ivNoCookie' || name == 'IvbsCampIdsLocal'; if (invibes.noCookies && !whiteListed && (exdays || 0) >= 0) { return; } if (exdays > 365) { exdays = 365; } @@ -406,7 +408,7 @@ invibes.setCookie = function (name, value, exdays, domain) { let exdate = new Date(); let exms = exdays * 24 * 60 * 60 * 1000; exdate.setTime(exdate.getTime() + exms); - utils.setCookie(name, value, exdate.toUTCString(), undefined, domain); + storage.setCookie(name, value, exdate.toUTCString(), undefined, domain); }; let detectTopmostCookieDomain = function () { diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index fd22a21b94f..82ae3ef0e0f 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -328,6 +328,7 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) { export const spec = { code: BIDDER_CODE, + gvlid: 10, supportedMediaTypes: SUPPORTED_AD_TYPES, /** diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 6d86038e6bd..31c35f4afe3 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -1,6 +1,9 @@ import * as utils from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); const BIDDER_CODE = 'kargo'; const HOST = 'https://krk.kargo.com'; const SYNC = 'https://crb.kargo.com/api/v1/initsyncrnd/{UUID}?seed={SEED}&idx={INDEX}'; @@ -98,7 +101,7 @@ export const spec = { // PRIVATE _readCookie(name) { - if (!utils.cookiesAreEnabled()) { + if (!storage.cookiesAreEnabled()) { return null; } let nameEquals = `${name}=`; @@ -173,7 +176,7 @@ export const spec = { _getLocalStorageSafely(key) { try { - return utils.getDataFromLocalStorage(key); + return storage.getDataFromLocalStorage(key); } catch (e) { return null; } diff --git a/modules/liveIntentIdSystem.js b/modules/liveIntentIdSystem.js index ffbbc71ead4..cc0e3964f80 100644 --- a/modules/liveIntentIdSystem.js +++ b/modules/liveIntentIdSystem.js @@ -7,6 +7,9 @@ import * as utils from '../src/utils.js' import {ajax} from '../src/ajax.js'; import {submodule} from '../src/hook.js'; +import { getStorageManager } from '../src/storageManager.js'; + +export const storage = getStorageManager(); const MODULE_NAME = 'liveIntentId'; const LIVE_CONNECT_DUID_KEY = '_li_duid'; @@ -63,7 +66,7 @@ export const liveIntentIdSubmodule = { const additionalIdentifierNames = configParams.identifiersToResolve || []; const additionalIdentifiers = additionalIdentifierNames.concat([LIVE_CONNECT_DUID_KEY]).reduce((obj, identifier) => { - const value = utils.getCookie(identifier) || utils.getDataFromLocalStorage(identifier); + const value = storage.getCookie(identifier) || storage.getDataFromLocalStorage(identifier); const key = identifier.replace(LIVE_CONNECT_DUID_KEY, DOMAIN_USER_ID_QUERY_PARAM_KEY); if (value) { if (typeof value === 'object') { diff --git a/modules/livewrappedBidAdapter.js b/modules/livewrappedBidAdapter.js index 0e478869b53..5a9ef302d51 100644 --- a/modules/livewrappedBidAdapter.js +++ b/modules/livewrappedBidAdapter.js @@ -3,6 +3,9 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import find from 'core-js/library/fn/array/find.js'; import { BANNER, NATIVE } from '../src/mediaTypes.js'; +import { getStorageManager } from '../src/storageManager.js'; + +export const storage = getStorageManager(); const BIDDER_CODE = 'livewrapped'; export const URL = 'https://lwadm.com/ad'; @@ -71,7 +74,7 @@ export const spec = { version: VERSION, gdprApplies: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, gdprConsent: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined, - cookieSupport: !utils.isSafariBrowser() && utils.cookiesAreEnabled(), + cookieSupport: !utils.isSafariBrowser() && storage.cookiesAreEnabled(), rcv: getAdblockerRecovered(), adRequests: [...adRequests], rtbData: handleEids(bidRequests) diff --git a/modules/mantisBidAdapter.js b/modules/mantisBidAdapter.js index 4e32f3f70ac..19e70a3e68b 100644 --- a/modules/mantisBidAdapter.js +++ b/modules/mantisBidAdapter.js @@ -1,5 +1,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; -import * as utils from '../src/utils.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); function inIframe() { try { @@ -93,9 +95,9 @@ function storeUuid(uuid) { return false; } window.mantis_uuid = uuid; - if (utils.hasLocalStorage()) { + if (storage.hasLocalStorage()) { try { - utils.setDataInLocalStorage('mantis:uuid', uuid); + storage.setDataInLocalStorage('mantis:uuid', uuid); } catch (ex) { } } @@ -176,8 +178,8 @@ function buildMantisUrl(path, data, domain) { } if (window.mantis_uuid) { params.uuid = window.mantis_uuid; - } else if (utils.hasLocalStorage()) { - var localUuid = utils.getDataFromLocalStorage('mantis:uuid'); + } else if (storage.hasLocalStorage()) { + var localUuid = storage.getDataFromLocalStorage('mantis:uuid'); if (localUuid) { params.uuid = localUuid; } diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index f68f263a0d5..d944f354c83 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -297,6 +297,7 @@ function clearMnData() { export const spec = { code: BIDDER_CODE, + gvlid: 142, supportedMediaTypes: [BANNER, NATIVE], diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index f423f5d474b..194a8255641 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -3,6 +3,9 @@ import * as utils from '../src/utils.js'; import * as urlUtils from '../src/url.js'; import {BANNER, NATIVE} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); const DEFAULT_CUR = 'USD'; const BIDDER_CODE = 'mgid'; const ENDPOINT_URL = 'https://prebid.mgid.com/prebid/'; @@ -342,7 +345,7 @@ function getLanguage() { function getLocalStorageSafely(key) { try { - return utils.getDataFromLocalStorage(key); + return storage.getDataFromLocalStorage(key); } catch (e) { return null; } @@ -350,7 +353,7 @@ function getLocalStorageSafely(key) { function setLocalStorageSafely(key, val) { try { - return utils.setDataInLocalStorage(key, val); + return storage.setDataInLocalStorage(key, val); } catch (e) { return null; } diff --git a/modules/nanointeractiveBidAdapter.js b/modules/nanointeractiveBidAdapter.js index 3dfd4811bcd..42a343efc03 100644 --- a/modules/nanointeractiveBidAdapter.js +++ b/modules/nanointeractiveBidAdapter.js @@ -1,6 +1,9 @@ import * as utils from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); export const BIDDER_CODE = 'nanointeractive'; export const END_POINT_URL = 'https://ad.audiencemanager.de'; @@ -97,7 +100,7 @@ function createSingleBidRequest(bid, bidderRequest) { function createSingleBidResponse(serverBid) { if (serverBid.userId) { - utils.setDataInLocalStorage('lsUserId', serverBid.userId); + storage.setDataInLocalStorage('lsUserId', serverBid.userId); } return { requestId: serverBid.id, @@ -147,8 +150,8 @@ function getEndpointUrl() { } function getLsUserId() { - if (utils.getDataFromLocalStorage('lsUserId') != null) { - return utils.getDataFromLocalStorage('lsUserId'); + if (storage.getDataFromLocalStorage('lsUserId') != null) { + return storage.getDataFromLocalStorage('lsUserId'); } return null; } diff --git a/modules/newborntownWebBidAdapter.js b/modules/newborntownWebBidAdapter.js index 0ad3e212089..56c63e2bb4d 100644 --- a/modules/newborntownWebBidAdapter.js +++ b/modules/newborntownWebBidAdapter.js @@ -1,6 +1,9 @@ import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, NATIVE} from '../src/mediaTypes.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); const BIDDER_CODE = 'newborntownWeb'; const REQUEST_URL = 'https://us-west.solortb.com/adx/api/rtb?from=4' @@ -53,10 +56,10 @@ export const spec = { return null; } var guid; - if (utils.getDataFromLocalStorage('sax_user_id') == null) { - utils.setDataInLocalStorage('sax_user_id', generateGUID()) + if (storage.getDataFromLocalStorage('sax_user_id') == null) { + storage.setDataInLocalStorage('sax_user_id', generateGUID()) } - guid = utils.getDataFromLocalStorage('sax_user_id') + guid = storage.getDataFromLocalStorage('sax_user_id') utils._each(validBidRequests, function(bidRequest) { const bidRequestObj = bidRequest.params var req = { diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js index a845693425d..dead2d48ed4 100644 --- a/modules/nobidBidAdapter.js +++ b/modules/nobidBidAdapter.js @@ -2,6 +2,9 @@ import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); const BIDDER_CODE = 'nobid'; window.nobidVersion = '1.2.4'; window.nobid = window.nobid || {}; @@ -16,10 +19,10 @@ function nobidSetCookie(cname, cvalue, hours) { var d = new Date(); d.setTime(d.getTime() + (hours * 60 * 60 * 1000)); var expires = 'expires=' + d.toUTCString(); - utils.setCookie(cname, cvalue, expires); + storage.setCookie(cname, cvalue, expires); } function nobidGetCookie(cname) { - return utils.getCookie(cname); + return storage.getCookie(cname); } function nobidBuildRequests(bids, bidderRequest) { var serializeState = function(divIds, siteId, adunits) { diff --git a/modules/oneVideoBidAdapter.js b/modules/oneVideoBidAdapter.js index 9d3fabcd3b6..933f2d7a4c8 100644 --- a/modules/oneVideoBidAdapter.js +++ b/modules/oneVideoBidAdapter.js @@ -3,6 +3,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'oneVideo'; export const spec = { code: 'oneVideo', + gvlid: 25, VERSION: '3.0.0', ENDPOINT: 'https://ads.adaptv.advertising.com/rtb/openrtb?ext_id=', SYNC_ENDPOINT1: 'https://cm.g.doubleclick.net/pixel?google_nid=adaptv_dbm&google_cm&google_sc', diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index b0d1ae3a075..95ae017b1a3 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -18,6 +18,7 @@ const USER_ID_CODE_TO_QUERY_ARG = { export const spec = { code: BIDDER_CODE, + gvlid: 69, supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function (bidRequest) { const hasDelDomainOrPlatform = bidRequest.params.delDomain || bidRequest.params.platform; diff --git a/modules/orbidderBidAdapter.js b/modules/orbidderBidAdapter.js index 3461aaf66a4..d7ce5aa859a 100644 --- a/modules/orbidderBidAdapter.js +++ b/modules/orbidderBidAdapter.js @@ -1,7 +1,9 @@ import {detectReferer} from '../src/refererDetection.js'; import {ajax} from '../src/ajax.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; -import * as utils from '../src/utils.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); export const spec = { code: 'orbidder', @@ -9,7 +11,7 @@ export const spec = { orbidderHost: (() => { let ret = 'https://orbidder.otto.de'; try { - ret = utils.getDataFromLocalStorage('ov_orbidder_host') || ret; + ret = storage.getDataFromLocalStorage('ov_orbidder_host') || ret; } catch (e) { } return ret; diff --git a/modules/pubCommonId.js b/modules/pubCommonId.js index f476091ce2b..d69ce0f2086 100644 --- a/modules/pubCommonId.js +++ b/modules/pubCommonId.js @@ -8,6 +8,9 @@ import { config } from '../src/config.js'; import events from '../src/events.js'; import * as url from '../src/url.js'; import CONSTANTS from '../src/constants.json'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); const ID_NAME = '_pubcid'; const OPTOUT_NAME = '_pubcid_optout'; @@ -37,10 +40,10 @@ export function setStorageItem(key, val, expires) { try { if (expires !== undefined && expires != null) { const expStr = (new Date(Date.now() + (expires * 60 * 1000))).toUTCString(); - utils.setDataInLocalStorage(key + EXP_SUFFIX, expStr); + storage.setDataInLocalStorage(key + EXP_SUFFIX, expStr); } - utils.setDataInLocalStorage(key, val); + storage.setDataInLocalStorage(key, val); } catch (e) { utils.logMessage(e); } @@ -55,18 +58,18 @@ export function getStorageItem(key) { let val = null; try { - const expVal = utils.getDataFromLocalStorage(key + EXP_SUFFIX); + const expVal = storage.getDataFromLocalStorage(key + EXP_SUFFIX); if (!expVal) { // If there is no expiry time, then just return the item - val = utils.getDataFromLocalStorage(key); + val = storage.getDataFromLocalStorage(key); } else { // Only return the item if it hasn't expired yet. // Otherwise delete the item. const expDate = new Date(expVal); const isValid = (expDate.getTime() - Date.now()) > 0; if (isValid) { - val = utils.getDataFromLocalStorage(key); + val = storage.getDataFromLocalStorage(key); } else { removeStorageItem(key); } @@ -84,8 +87,8 @@ export function getStorageItem(key) { */ export function removeStorageItem(key) { try { - utils.removeDataFromLocalStorage(key + EXP_SUFFIX); - utils.removeDataFromLocalStorage(key); + storage.removeDataFromLocalStorage(key + EXP_SUFFIX); + storage.removeDataFromLocalStorage(key); } catch (e) { utils.logMessage(e); } @@ -101,7 +104,7 @@ function readValue(name, type) { let value; if (!type) { type = pubcidConfig.typeEnabled; } if (type === COOKIE) { - value = utils.getCookie(name); + value = storage.getCookie(name); } else if (type === LOCAL_STORAGE) { value = getStorageItem(name); } @@ -223,12 +226,12 @@ export function requestBidHook(next, config) { export function setCookie(name, value, expires, sameSite) { let expTime = new Date(); expTime.setTime(expTime.getTime() + expires * 1000 * 60); - utils.setCookie(name, value, expTime.toGMTString(), sameSite); + storage.setCookie(name, value, expTime.toGMTString(), sameSite); } // Helper to read a cookie export function getCookie(name) { - return utils.getCookie(name); + return storage.getCookie(name); } /** @@ -263,12 +266,12 @@ export function setConfig({ enable, expInterval, type = 'html5,cookie', create, for (let i = 0; i < typeArray.length; ++i) { const name = typeArray[i].trim(); if (name === COOKIE) { - if (utils.cookiesAreEnabled()) { + if (storage.cookiesAreEnabled()) { pubcidConfig.typeEnabled = COOKIE; break; } } else if (name === LOCAL_STORAGE) { - if (utils.hasLocalStorage()) { + if (storage.hasLocalStorage()) { pubcidConfig.typeEnabled = LOCAL_STORAGE; break; } @@ -282,8 +285,8 @@ export function setConfig({ enable, expInterval, type = 'html5,cookie', create, export function initPubcid() { config.getConfig('pubcid', config => setConfig(config.pubcid)); - const optout = (utils.cookiesAreEnabled() && readValue(OPTOUT_NAME, COOKIE)) || - (utils.hasLocalStorage() && readValue(OPTOUT_NAME, LOCAL_STORAGE)); + const optout = (storage.cookiesAreEnabled() && readValue(OPTOUT_NAME, COOKIE)) || + (storage.hasLocalStorage() && readValue(OPTOUT_NAME, LOCAL_STORAGE)); if (!optout) { $$PREBID_GLOBAL$$.requestBids.before(requestBidHook); diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 1a5de695c3c..92dbe9727aa 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -816,6 +816,7 @@ function _handleDealCustomTargetings(payload, dctrArr, validBidRequests) { export const spec = { code: BIDDER_CODE, + gvlid: 76, supportedMediaTypes: [BANNER, VIDEO, NATIVE], /** * Determines whether or not the given bid request is valid. Valid bid request must have placementId and hbid diff --git a/modules/pubwiseAnalyticsAdapter.js b/modules/pubwiseAnalyticsAdapter.js index df38b3ab076..915aeb58f99 100644 --- a/modules/pubwiseAnalyticsAdapter.js +++ b/modules/pubwiseAnalyticsAdapter.js @@ -2,8 +2,11 @@ import {ajax} from '../src/ajax.js'; import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; +import { getStorageManager } from '../src/storageManager.js'; const utils = require('../src/utils.js'); +const storage = getStorageManager(); + /**** * PubWise.io Analytics * Contact: support@pubwise.io @@ -59,14 +62,14 @@ function enrichWithUTM(dataBag) { if (newUtm === false) { for (let prop in utmKeys) { - let itemValue = utils.getDataFromLocalStorage(`pw-${prop}`); + let itemValue = storage.getDataFromLocalStorage(`pw-${prop}`); if (itemValue.length !== 0) { dataBag[prop] = itemValue; } } } else { for (let prop in utmKeys) { - utils.setDataInLocalStorage(`pw-${prop}`, utmKeys[prop]); + storage.setDataInLocalStorage(`pw-${prop}`, utmKeys[prop]); } } } catch (e) { diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index cbe37e66cd7..6d1c2eb9229 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -28,6 +28,8 @@ export const spec = { code: 'pulsepoint', + gvlid: 81, + aliases: ['pulseLite', 'pulsepointLite'], supportedMediaTypes: ['banner', 'native', 'video'], diff --git a/modules/realvuAnalyticsAdapter.js b/modules/realvuAnalyticsAdapter.js index 4b05a998788..95e62397c2c 100644 --- a/modules/realvuAnalyticsAdapter.js +++ b/modules/realvuAnalyticsAdapter.js @@ -2,6 +2,9 @@ import adapter from '../src/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); const utils = require('../src/utils.js'); @@ -779,7 +782,7 @@ export let lib = { writePos: function (a) { try { let v = a.x + ',' + a.y + ',' + a.w + ',' + a.h; - utils.setDataInLocalStorage(this.keyPos(a), v); + storage.setDataInLocalStorage(this.keyPos(a), v); } catch (ex) { /* continue regardless of error */ } @@ -787,7 +790,7 @@ export let lib = { readPos: function (a) { try { - let s = utils.getDataFromLocalStorage(this.keyPos(a)); + let s = storage.getDataFromLocalStorage(this.keyPos(a)); if (s) { let v = s.split(','); a.x = parseInt(v[0], 10); @@ -806,7 +809,7 @@ export let lib = { incrMem: function(a, evt, name) { try { let k1 = this.keyPos(a) + '.' + name; - let vmem = utils.getDataFromLocalStorage(k1); + let vmem = storage.getDataFromLocalStorage(k1); if (vmem == null) vmem = '1:3'; let vr = vmem.split(':'); let nv = parseInt(vr[0], 10); @@ -819,7 +822,7 @@ export let lib = { if (evt == 'v') { nv |= 1; } - utils.setDataInLocalStorage(k1, nv + ':' + nr); + storage.setDataInLocalStorage(k1, nv + ':' + nr); } catch (ex) { /* do nothing */ } @@ -827,7 +830,7 @@ export let lib = { score: function (a, name) { try { - let vstr = utils.getDataFromLocalStorage(this.keyPos(a) + '.' + name); + let vstr = storage.getDataFromLocalStorage(this.keyPos(a) + '.' + name); if (vstr != null) { let vr = vstr.split(':'); let nv = parseInt(vr[0], 10); diff --git a/modules/reloadBidAdapter.js b/modules/reloadBidAdapter.js index dd4514c99c8..94ea4be281f 100644 --- a/modules/reloadBidAdapter.js +++ b/modules/reloadBidAdapter.js @@ -3,6 +3,10 @@ import { } from '../src/adapters/bidderFactory.js'; import * as utils from '../src/utils.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); + const BIDDER_CODE = 'reload'; const VERSION_ADAPTER = '1.10'; export const spec = { @@ -390,14 +394,14 @@ function ReloadClientTool(args) { var stgFileStr = JSON.stringify(stgFileObj); - utils.setDataInLocalStorage(name, stgFileStr); + storage.setDataInLocalStorage(name, stgFileStr); return true; } function _getItem (name) { try { - var obStgFileStr = utils.getDataFromLocalStorage(name); + var obStgFileStr = storage.getDataFromLocalStorage(name); if (obStgFileStr === null) return null; var stgFileObj = JSON.parse(obStgFileStr); diff --git a/modules/roxotAnalyticsAdapter.js b/modules/roxotAnalyticsAdapter.js index a077c7ac7e0..0e9cda9b6bc 100644 --- a/modules/roxotAnalyticsAdapter.js +++ b/modules/roxotAnalyticsAdapter.js @@ -3,6 +3,9 @@ import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; import includes from 'core-js/library/fn/array/includes.js'; import {ajaxBuilder} from '../src/ajax.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); const utils = require('../src/utils.js'); let ajax = ajaxBuilder(0); @@ -68,17 +71,17 @@ function detectDevice() { function checkIsNewFlag() { let key = buildLocalStorageKey(isNewKey); - let lastUpdate = Number(utils.getDataFromLocalStorage(key)); - utils.setDataInLocalStorage(key, Date.now()); + let lastUpdate = Number(storage.getDataFromLocalStorage(key)); + storage.setDataInLocalStorage(key, Date.now()); return Date.now() - lastUpdate > isNewTtl; } function updateUtmTimeout() { - utils.setDataInLocalStorage(buildLocalStorageKey(utmTtlKey), Date.now()); + storage.setDataInLocalStorage(buildLocalStorageKey(utmTtlKey), Date.now()); } function isUtmTimeoutExpired() { - let utmTimestamp = utils.getDataFromLocalStorage(buildLocalStorageKey(utmTtlKey)); + let utmTimestamp = storage.getDataFromLocalStorage(buildLocalStorageKey(utmTtlKey)); return (Date.now() - utmTimestamp) > utmTtl; } @@ -356,11 +359,11 @@ roxotAdapter.buildUtmTagData = function () { }); utmTags.forEach(function (utmTagKey) { if (utmTagsDetected) { - utils.setDataInLocalStorage(buildLocalStorageKey(utmTagKey), utmTagData[utmTagKey]); + storage.setDataInLocalStorage(buildLocalStorageKey(utmTagKey), utmTagData[utmTagKey]); updateUtmTimeout(); } else { if (!isUtmTimeoutExpired()) { - utmTagData[utmTagKey] = utils.getDataFromLocalStorage(buildLocalStorageKey(utmTagKey)) ? utils.getDataFromLocalStorage(buildLocalStorageKey(utmTagKey)) : ''; + utmTagData[utmTagKey] = storage.getDataFromLocalStorage(buildLocalStorageKey(utmTagKey)) ? storage.getDataFromLocalStorage(buildLocalStorageKey(utmTagKey)) : ''; updateUtmTimeout(); } } diff --git a/modules/sigmoidAnalyticsAdapter.js b/modules/sigmoidAnalyticsAdapter.js index fac23730864..88bb5eb23a9 100644 --- a/modules/sigmoidAnalyticsAdapter.js +++ b/modules/sigmoidAnalyticsAdapter.js @@ -4,6 +4,9 @@ import includes from 'core-js/library/fn/array/includes.js'; import adapter from '../src/AnalyticsAdapter.js'; import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); const utils = require('../src/utils.js'); @@ -54,31 +57,31 @@ function buildSessionIdTimeoutLocalStorageKey() { function updateSessionId() { if (isSessionIdTimeoutExpired()) { let newSessionId = utils.generateUUID(); - utils.setDataInLocalStorage(buildSessionIdLocalStorageKey(), newSessionId); + storage.setDataInLocalStorage(buildSessionIdLocalStorageKey(), newSessionId); } initOptions.sessionId = getSessionId(); updateSessionIdTimeout(); } function updateSessionIdTimeout() { - utils.setDataInLocalStorage(buildSessionIdTimeoutLocalStorageKey(), Date.now()); + storage.setDataInLocalStorage(buildSessionIdTimeoutLocalStorageKey(), Date.now()); } function isSessionIdTimeoutExpired() { - let cpmSessionTimestamp = utils.getDataFromLocalStorage(buildSessionIdTimeoutLocalStorageKey()); + let cpmSessionTimestamp = storage.getDataFromLocalStorage(buildSessionIdTimeoutLocalStorageKey()); return Date.now() - cpmSessionTimestamp > sessionTimeout; } function getSessionId() { - return utils.getDataFromLocalStorage(buildSessionIdLocalStorageKey()) ? utils.getDataFromLocalStorage(buildSessionIdLocalStorageKey()) : ''; + return storage.getDataFromLocalStorage(buildSessionIdLocalStorageKey()) ? storage.getDataFromLocalStorage(buildSessionIdLocalStorageKey()) : ''; } function updateUtmTimeout() { - utils.setDataInLocalStorage(buildUtmLocalStorageTimeoutKey(), Date.now()); + storage.setDataInLocalStorage(buildUtmLocalStorageTimeoutKey(), Date.now()); } function isUtmTimeoutExpired() { - let utmTimestamp = utils.getDataFromLocalStorage(buildUtmLocalStorageTimeoutKey()); + let utmTimestamp = storage.getDataFromLocalStorage(buildUtmLocalStorageTimeoutKey()); return (Date.now() - utmTimestamp) > utmTimeout; } @@ -219,11 +222,11 @@ sigmoidAdapter.buildUtmTagData = function () { }); utmTags.forEach(function(utmTagKey) { if (utmTagsDetected) { - utils.setDataInLocalStorage(buildUtmLocalStorageKey(utmTagKey), utmTagData[utmTagKey]); + storage.setDataInLocalStorage(buildUtmLocalStorageKey(utmTagKey), utmTagData[utmTagKey]); updateUtmTimeout(); } else { if (!isUtmTimeoutExpired()) { - utmTagData[utmTagKey] = utils.getDataFromLocalStorage(buildUtmLocalStorageKey(utmTagKey)) ? utils.getDataFromLocalStorage(buildUtmLocalStorageKey(utmTagKey)) : ''; + utmTagData[utmTagKey] = storage.getDataFromLocalStorage(buildUtmLocalStorageKey(utmTagKey)) ? storage.getDataFromLocalStorage(buildUtmLocalStorageKey(utmTagKey)) : ''; updateUtmTimeout(); } } diff --git a/modules/spotxBidAdapter.js b/modules/spotxBidAdapter.js index fe42523e737..210153548b2 100644 --- a/modules/spotxBidAdapter.js +++ b/modules/spotxBidAdapter.js @@ -10,6 +10,7 @@ export const GOOGLE_CONSENT = { consented_providers: ['3', '7', '11', '12', '15' export const spec = { code: BIDDER_CODE, + gvlid: 165, aliases: ['spotx'], supportedMediaTypes: [VIDEO], diff --git a/modules/staqAnalyticsAdapter.js b/modules/staqAnalyticsAdapter.js index 2bcb175e531..31b231637f4 100644 --- a/modules/staqAnalyticsAdapter.js +++ b/modules/staqAnalyticsAdapter.js @@ -5,6 +5,9 @@ import { getRefererInfo } from '../src/refererDetection.js'; import { parse } from '../src/url.js'; import * as utils from '../src/utils.js'; import { ajax } from '../src/ajax.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storageObj = getStorageManager(); const ANALYTICS_VERSION = '1.0.0'; const DEFAULT_QUEUE_TIMEOUT = 4000; @@ -212,10 +215,10 @@ const ORGANIC = '(organic)'; export let storage = { getItem: (name) => { - return utils.getDataFromLocalStorage(name); + return storageObj.getDataFromLocalStorage(name); }, setItem: (name, value) => { - utils.setDataInLocalStorage(name, value); + storageObj.setDataInLocalStorage(name, value); } }; diff --git a/modules/sublimeBidAdapter.js b/modules/sublimeBidAdapter.js index 63f851c5b4d..951b7b86ca9 100644 --- a/modules/sublimeBidAdapter.js +++ b/modules/sublimeBidAdapter.js @@ -10,6 +10,7 @@ const SUBLIME_VERSION = '0.4.0'; export const spec = { code: BIDDER_CODE, + gvlid: 114, aliases: [], /** diff --git a/modules/trionBidAdapter.js b/modules/trionBidAdapter.js index 846711a2721..37d54e60cd2 100644 --- a/modules/trionBidAdapter.js +++ b/modules/trionBidAdapter.js @@ -1,5 +1,8 @@ import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); const BID_REQUEST_BASE_URL = 'https://in-appadvertising.com/api/bidRequest'; const USER_SYNC_URL = 'https://in-appadvertising.com/api/userSync.html'; @@ -176,8 +179,8 @@ function handlePostMessage() { export function getStorageData(key) { var item = null; try { - if (utils.hasLocalStorage()) { - item = utils.getDataFromLocalStorage(key); + if (storage.hasLocalStorage()) { + item = storage.getDataFromLocalStorage(key); } } catch (e) { } @@ -186,8 +189,8 @@ export function getStorageData(key) { export function setStorageData(key, item) { try { - if (utils.hasLocalStorage()) { - utils.setDataInLocalStorage(key, item); + if (storage.hasLocalStorage()) { + storage.setDataInLocalStorage(key, item); } } catch (e) { } diff --git a/modules/unicornBidAdapter.js b/modules/unicornBidAdapter.js index b782c716323..cc320dc68a8 100644 --- a/modules/unicornBidAdapter.js +++ b/modules/unicornBidAdapter.js @@ -1,6 +1,9 @@ import * as utils from '../src/utils.js'; import { BANNER } from '../src/mediaTypes.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { getStorageManager } from '../src/storageManager.js'; + +const storage = getStorageManager(); const BIDDER_CODE = 'unicorn'; const UNICORN_ENDPOINT = 'https://ds.uncn.jp/pb/0/bid.json'; const UNICORN_DEFAULT_CURRENCY = 'JPY'; @@ -119,7 +122,7 @@ const interpretResponse = (serverResponse, request) => { * Get or Create Uid for First Party Cookie */ const getUid = () => { - const ck = utils.getCookie(UNICORN_PB_COOKIE_KEY); + const ck = storage.getCookie(UNICORN_PB_COOKIE_KEY); if (ck) { return JSON.parse(ck)['uid']; } else { @@ -127,7 +130,7 @@ const getUid = () => { uid: utils.generateUUID() }; const expireIn = new Date(Date.now() + 24 * 60 * 60 * 10000).toUTCString(); - utils.setCookie(UNICORN_PB_COOKIE_KEY, JSON.stringify(newCk), expireIn); + storage.setCookie(UNICORN_PB_COOKIE_KEY, JSON.stringify(newCk), expireIn); return newCk.uid; } }; diff --git a/modules/userId/index.js b/modules/userId/index.js index dd0d9aa3c33..c94ada3c7b8 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -105,14 +105,14 @@ import {gdprDataHandler} from '../../src/adapterManager.js'; import CONSTANTS from '../../src/constants.json'; import {module, hook} from '../../src/hook.js'; import {createEidsArray} from './eids.js'; -import { newStorageManager } from '../../src/storageManager.js'; +import { getCoreStorageManager } from '../../src/storageManager.js'; const MODULE_NAME = 'User ID'; const COOKIE = 'cookie'; const LOCAL_STORAGE = 'html5'; const DEFAULT_SYNC_DELAY = 500; const NO_AUCTION_DELAY = 0; -export const coreStorage = newStorageManager({moduleName: 'userid', moduleType: 'prebid-module'}); +export const coreStorage = getCoreStorageManager('userid'); /** @type {string[]} */ let validStorageTypes = []; @@ -157,10 +157,10 @@ function setStoredValue(storage, value) { coreStorage.setCookie(`${storage.name}_last`, new Date().toUTCString(), expiresStr); } } else if (storage.type === LOCAL_STORAGE) { - localStorage.setItem(`${storage.name}_exp`, expiresStr); - localStorage.setItem(storage.name, encodeURIComponent(valueStr)); + coreStorage.setDataInLocalStorage(`${storage.name}_exp`, expiresStr); + coreStorage.setDataInLocalStorage(storage.name, encodeURIComponent(valueStr)); if (typeof storage.refreshInSeconds === 'number') { - localStorage.setItem(`${storage.name}_last`, new Date().toUTCString()); + coreStorage.setDataInLocalStorage(`${storage.name}_last`, new Date().toUTCString()); } } } catch (error) { @@ -180,13 +180,13 @@ function getStoredValue(storage, key = undefined) { if (storage.type === COOKIE) { storedValue = coreStorage.getCookie(storedKey); } else if (storage.type === LOCAL_STORAGE) { - const storedValueExp = localStorage.getItem(`${storage.name}_exp`); + const storedValueExp = coreStorage.getDataFromLocalStorage(`${storage.name}_exp`); // empty string means no expiration set if (storedValueExp === '') { - storedValue = localStorage.getItem(storedKey); + storedValue = coreStorage.getDataFromLocalStorage(storedKey); } else if (storedValueExp) { if ((new Date(storedValueExp)).getTime() - Date.now() > 0) { - storedValue = decodeURIComponent(localStorage.getItem(storedKey)); + storedValue = decodeURIComponent(coreStorage.getDataFromLocalStorage(storedKey)); } } } @@ -542,7 +542,7 @@ export function init(config) { return; } // _pubcid_optout is checked for compatiblility with pubCommonId - if (validStorageTypes.indexOf(LOCAL_STORAGE) !== -1 && (localStorage.getItem('_pbjs_id_optout') || localStorage.getItem('_pubcid_optout'))) { + if (validStorageTypes.indexOf(LOCAL_STORAGE) !== -1 && (coreStorage.getDataFromLocalStorage('_pbjs_id_optout') || coreStorage.getDataFromLocalStorage('_pubcid_optout'))) { utils.logInfo(`${MODULE_NAME} - opt-out localStorage found, exit module`); return; } diff --git a/modules/widespaceBidAdapter.js b/modules/widespaceBidAdapter.js index 26ced2bb802..5165b00a98c 100644 --- a/modules/widespaceBidAdapter.js +++ b/modules/widespaceBidAdapter.js @@ -1,19 +1,17 @@ import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { - cookiesAreEnabled, - hasLocalStorage, parseQueryStringParameters, parseSizesInput } from '../src/utils.js'; import includes from 'core-js/library/fn/array/includes.js'; import find from 'core-js/library/fn/array/find.js'; -import * as utils from '../src/utils.js'; +import { getStorageManager } from '../src/storageManager.js'; + +export const storage = getStorageManager(); const BIDDER_CODE = 'widespace'; const WS_ADAPTER_VERSION = '2.0.1'; -const LOCAL_STORAGE_AVAILABLE = hasLocalStorage(); -const COOKIE_ENABLED = cookiesAreEnabled(); const LS_KEYS = { PERF_DATA: 'wsPerfData', LC_UID: 'wsLcuid', @@ -177,37 +175,37 @@ export const spec = { function storeData(data, name, stringify = true) { const value = stringify ? JSON.stringify(data) : data; - if (LOCAL_STORAGE_AVAILABLE) { - utils.setDataInLocalStorage(name, value); + if (storage.hasLocalStorage()) { + storage.setDataInLocalStorage(name, value); return true; - } else if (COOKIE_ENABLED) { + } else if (storage.cookiesAreEnabled()) { const theDate = new Date(); const expDate = new Date(theDate.setMonth(theDate.getMonth() + 12)).toGMTString(); - utils.setCookie(name, value, expDate); + storage.setCookie(name, value, expDate); return true; } } function getData(name, remove = true) { let data = []; - if (LOCAL_STORAGE_AVAILABLE) { + if (storage.hasLocalStorage()) { Object.keys(localStorage).filter((key) => { if (key.indexOf(name) > -1) { - data.push(utils.getDataFromLocalStorage(key)); + data.push(storage.getDataFromLocalStorage(key)); if (remove) { - utils.removeDataFromLocalStorage(key); + storage.removeDataFromLocalStorage(key); } } }); } - if (COOKIE_ENABLED) { + if (storage.cookiesAreEnabled()) { document.cookie.split(';').forEach((item) => { let value = item.split('='); if (value[0].indexOf(name) > -1) { data.push(value[1]); if (remove) { - utils.setCookie(value[0], '', 'Thu, 01 Jan 1970 00:00:01 GMT'); + storage.setCookie(value[0], '', 'Thu, 01 Jan 1970 00:00:01 GMT'); } } }); diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index f18f9447581..a1ec639d901 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -9,9 +9,12 @@ import CONSTANTS from '../constants.json'; import events from '../events.js'; import includes from 'core-js/library/fn/array/includes.js'; import { ajax } from '../ajax.js'; -import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest, flatten, uniques, timestamp, setDataInLocalStorage, getDataFromLocalStorage, deepAccess, isArray } from '../utils.js'; +import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest, flatten, uniques, timestamp, deepAccess, isArray } from '../utils.js'; import { ADPOD } from '../mediaTypes.js'; import { getHook, hook } from '../hook.js'; +import { getCoreStorageManager } from '../storageManager.js'; + +export const storage = getCoreStorageManager('bidderFactory'); /** * This file aims to support Adapters during the Prebid 0.x -> 1.x transition. @@ -377,7 +380,7 @@ export function preloadBidderMappingFile(fn, adUnits) { let info = bidderSpec.getSpec().getMappingFileInfo(); let refreshInDays = (info.refreshInDays) ? info.refreshInDays : DEFAULT_REFRESHIN_DAYS; let key = (info.localStorageKey) ? info.localStorageKey : bidderSpec.getSpec().code; - let mappingData = getDataFromLocalStorage(key); + let mappingData = storage.getDataFromLocalStorage(key); if (!mappingData || timestamp() < mappingData.lastUpdated + refreshInDays * 24 * 60 * 60 * 1000) { ajax(info.url, { @@ -388,7 +391,7 @@ export function preloadBidderMappingFile(fn, adUnits) { lastUpdated: timestamp(), mapping: response.mapping } - setDataInLocalStorage(key, JSON.stringify(mapping)); + storage.setDataInLocalStorage(key, JSON.stringify(mapping)); } catch (error) { logError(`Failed to parse ${bidder} bidder translation mapping file`); } @@ -416,7 +419,7 @@ export function getIabSubCategory(bidderCode, category) { if (bidderSpec.getSpec().getMappingFileInfo) { let info = bidderSpec.getSpec().getMappingFileInfo(); let key = (info.localStorageKey) ? info.localStorageKey : bidderSpec.getBidderCode(); - let data = getDataFromLocalStorage(key); + let data = storage.getDataFromLocalStorage(key); if (data) { try { data = JSON.parse(data); diff --git a/src/prebid.js b/src/prebid.js index aa2d2493e7b..480e3afa6fc 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -13,6 +13,7 @@ import includes from 'core-js/library/fn/array/includes.js'; import { adunitCounter } from './adUnits.js'; import { isRendererRequired, executeRenderer } from './Renderer.js'; import { createBid } from './bidfactory.js'; +import { storageCallbacks } from './storageManager.js'; const $$PREBID_GLOBAL$$ = getGlobal(); const CONSTANTS = require('./constants.json'); @@ -523,6 +524,20 @@ $$PREBID_GLOBAL$$.requestBids = hook('async', function ({ bidsBackHandler, timeo return auction; }); +export function executeStorageCallbacks(fn, reqBidsConfigObj) { + runAll(storageCallbacks); + fn.call(this, reqBidsConfigObj); + function runAll(queue) { + var queued; + while ((queued = queue.shift())) { + queued(); + } + } +} + +// This hook will execute all storage callbacks which were registered before gdpr enforcement hook was added. Some bidders, user id modules use storage functions when module is parsed but gdpr enforcement hook is not added at that stage as setConfig callbacks are yet to be called. Hence for such calls we execute all the stored callbacks just before requestBids. At this hook point we will know for sure that gdprEnforcement module is added or not +$$PREBID_GLOBAL$$.requestBids.before(executeStorageCallbacks, 49); + /** * * Add adunit(s) diff --git a/src/storageManager.js b/src/storageManager.js index a9843feac4f..4467ba6bec0 100644 --- a/src/storageManager.js +++ b/src/storageManager.js @@ -1,9 +1,11 @@ import { hook } from './hook.js'; -import { hasDeviceAccess, logError, checkCookieSupport } from './utils.js'; +import * as utils from './utils.js'; import includes from 'core-js/library/fn/array/includes.js'; const moduleTypeWhiteList = ['core', 'prebid-module']; +export let storageCallbacks = []; + /** * Storage options * @typedef {Object} storageOptions @@ -21,12 +23,30 @@ const moduleTypeWhiteList = ['core', 'prebid-module']; * @param {storageOptions} options */ export function newStorageManager({gvlid, moduleName, moduleType} = {}) { - function isValid() { + function isValid(cb) { if (includes(moduleTypeWhiteList, moduleType)) { - return {valid: hasDeviceAccess()} + let result = { + valid: true + } + return cb(result); + } else { + let value; + let hookDetails = { + hasEnforcementHook: false + } + validateStorageEnforcement(gvlid, moduleName, hookDetails, function(result) { + if (result && result.hasEnforcementHook) { + value = cb(result); + } else { + let result = { + hasEnforcementHook: false, + valid: utils.hasDeviceAccess() + } + value = cb(result); + } + }); + return value; } - let result = validateStorageEnforcement(gvlid, moduleName); - return result; } /** @@ -39,10 +59,19 @@ export function newStorageManager({gvlid, moduleName, moduleType} = {}) { * If a domain is specified, subdomains are always included. * Domain must match the domain of the JavaScript origin. Setting cookies to foreign domains will be silently ignored. */ - const setCookie = function (key, value, expires, sameSite, domain) { - let result = isValid(); - if (result.valid) { - document.cookie = `${key}=${encodeURIComponent(value)}${(expires !== '') ? `; expires=${expires}` : ''}; path=/${sameSite ? `; SameSite=${sameSite}` : ''}${domain ? `; domain=${domain}` : ''}`; + const setCookie = function (key, value, expires, sameSite, domain, done) { + let cb = function (result) { + if (result && result.valid) { + document.cookie = `${key}=${encodeURIComponent(value)}${(expires !== '') ? `; expires=${expires}` : ''}; path=/${sameSite ? `; SameSite=${sameSite}` : ''}${domain ? `; domain=${domain}` : ''}`; + } + } + if (done && typeof done === 'function') { + storageCallbacks.push(function() { + let result = isValid(cb); + done(result); + }); + } else { + return isValid(cb); } }; @@ -50,52 +79,88 @@ export function newStorageManager({gvlid, moduleName, moduleType} = {}) { * @param {string} name * @returns {(string|null)} */ - const getCookie = function(name) { - let result = isValid(); - if (result.valid) { - let m = window.document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]*)\\s*(;|$)'); - return m ? decodeURIComponent(m[2]) : null; + const getCookie = function(name, done) { + let cb = function (result) { + if (result && result.valid) { + let m = window.document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]*)\\s*(;|$)'); + return m ? decodeURIComponent(m[2]) : null; + } + return null; + } + if (done && typeof done === 'function') { + storageCallbacks.push(function() { + let result = isValid(cb); + done(result); + }); + } else { + return isValid(cb); } - return null; }; /** * @returns {boolean} */ - const localStorageIsEnabled = function () { - let result = isValid(); - if (result.valid) { - try { - localStorage.setItem('prebid.cookieTest', '1'); - return localStorage.getItem('prebid.cookieTest') === '1'; - } catch (error) {} - } - return false; + const localStorageIsEnabled = function (done) { + let cb = function (result) { + if (result && result.valid) { + try { + localStorage.setItem('prebid.cookieTest', '1'); + return localStorage.getItem('prebid.cookieTest') === '1'; + } catch (error) {} + } + return false; + } + if (done && typeof done === 'function') { + storageCallbacks.push(function() { + let result = isValid(cb); + done(result); + }); + } else { + return isValid(cb); + } } /** * @returns {boolean} */ - const cookiesAreEnabled = function () { - let result = isValid(); - if (result.valid) { - if (checkCookieSupport()) { - return true; + const cookiesAreEnabled = function (done) { + let cb = function (result) { + if (result && result.valid) { + if (utils.checkCookieSupport()) { + return true; + } + window.document.cookie = 'prebid.cookieTest'; + return window.document.cookie.indexOf('prebid.cookieTest') !== -1; } - window.document.cookie = 'prebid.cookieTest'; - return window.document.cookie.indexOf('prebid.cookieTest') !== -1; + return false; + } + if (done && typeof done === 'function') { + storageCallbacks.push(function() { + let result = isValid(cb); + done(result); + }); + } else { + return isValid(cb); } - return false; } /** * @param {string} key * @param {string} value */ - const setDataInLocalStorage = function (key, value) { - let result = isValid(); - if (result.valid) { - window.localStorage.setItem(key, value); + const setDataInLocalStorage = function (key, value, done) { + let cb = function (result) { + if (result && result.valid) { + window.localStorage.setItem(key, value); + } + } + if (done && typeof done === 'function') { + storageCallbacks.push(function() { + let result = isValid(cb); + done(result); + }); + } else { + return isValid(cb); } } @@ -103,37 +168,64 @@ export function newStorageManager({gvlid, moduleName, moduleType} = {}) { * @param {string} key * @returns {(string|null)} */ - const getDataFromLocalStorage = function (key) { - let result = isValid(); - if (result.valid) { - return window.localStorage.getItem(key); + const getDataFromLocalStorage = function (key, done) { + let cb = function (result) { + if (result && result.valid) { + return window.localStorage.getItem(key); + } + return null; + } + if (done && typeof done === 'function') { + storageCallbacks.push(function() { + let result = isValid(cb); + done(result); + }); + } else { + return isValid(cb); } - return null; } /** * @param {string} key */ - const removeDataFromLocalStorage = function (key) { - let result = isValid(); - if (result.valid) { - window.localStorage.removeItem(key); + const removeDataFromLocalStorage = function (key, done) { + let cb = function (result) { + if (result && result.valid) { + window.localStorage.removeItem(key); + } + } + if (done && typeof done === 'function') { + storageCallbacks.push(function() { + let result = isValid(cb); + done(result); + }); + } else { + return isValid(cb); } } /** * @returns {boolean} */ - const hasLocalStorage = function () { - let result = isValid(); - if (result.valid) { - try { - return !!window.localStorage; - } catch (e) { - logError('Local storage api disabled'); + const hasLocalStorage = function (done) { + let cb = function (result) { + if (result && result.valid) { + try { + return !!window.localStorage; + } catch (e) { + utils.logError('Local storage api disabled'); + } } + return false; + } + if (done && typeof done === 'function') { + storageCallbacks.push(function() { + let result = isValid(cb); + done(result); + }); + } else { + return isValid(cb); } - return false; } return { @@ -151,13 +243,28 @@ export function newStorageManager({gvlid, moduleName, moduleType} = {}) { /** * This hook validates the storage enforcement if gdprEnforcement module is included */ -export const validateStorageEnforcement = hook('sync', function(result) { - if (result.hasEnforcementHook) { - return result - } else { - return { - hasEnforcementHook: false, - valid: hasDeviceAccess() - } - } +export const validateStorageEnforcement = hook('async', function(gvlid, moduleName, hookDetails, callback) { + callback(hookDetails); }, 'validateStorageEnforcement'); + +/** + * This function returns storage functions to access cookies and localstorage. This function will bypass the gdpr enforcement requirement. Prebid as a software needs to use storage in some scenarios and is not a vendor so GDPR enforcement rules does not apply on Prebid. + * @param {string} moduleName Module name + */ +export function getCoreStorageManager(moduleName) { + return newStorageManager({moduleName: moduleName, moduleType: 'core'}); +} + +/** + * Note: Core modules or Prebid modules like Currency, SizeMapping should use getCoreStorageManager + * This function returns storage functions to access cookies and localstorage. Bidders and User id modules should import this and use it in their module if needed. GVL ID and Module name are optional param but gvl id is needed for when gdpr enforcement module is used. + * @param {Number=} gvlid Vendor id + * @param {string=} moduleName BidderCode or module name + */ +export function getStorageManager(gvlid, moduleName) { + return newStorageManager({gvlid: gvlid, moduleName: moduleName}); +} + +export function resetData() { + storageCallbacks = []; +} diff --git a/src/userSync.js b/src/userSync.js index 58630532429..5da22254f2c 100644 --- a/src/userSync.js +++ b/src/userSync.js @@ -1,7 +1,7 @@ import * as utils from './utils.js'; import { config } from './config.js'; import includes from 'core-js/library/fn/array/includes.js'; -import { newStorageManager } from './storageManager.js'; +import { getCoreStorageManager } from './storageManager.js'; export const USERSYNC_DEFAULT_CONFIG = { syncEnabled: true, @@ -21,7 +21,7 @@ config.setDefaults({ 'userSync': utils.deepClone(USERSYNC_DEFAULT_CONFIG) }); -const storage = newStorageManager({moduleName: 'usersync', moduleType: 'core'}); +const storage = getCoreStorageManager('usersync'); /** * Factory function which creates a new UserSyncPool. diff --git a/src/utils.js b/src/utils.js index 6099fa9dd38..e19690b4618 100644 --- a/src/utils.js +++ b/src/utils.js @@ -844,61 +844,6 @@ export function checkCookieSupport() { } } -/** - * @returns {boolean} - */ -export function cookiesAreEnabled() { - if (hasDeviceAccess()) { - if (internal.checkCookieSupport()) { - return true; - } - window.document.cookie = 'prebid.cookieTest'; - return window.document.cookie.indexOf('prebid.cookieTest') !== -1; - } - return false; -} - -/** - * @param {string} name - * @returns {(string|null)} - */ -export function getCookie(name) { - if (hasDeviceAccess()) { - let m = window.document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]*)\\s*(;|$)'); - return m ? decodeURIComponent(m[2]) : null; - } - return null; -} - -/** - * @param {string} key - * @param {string} value - * @param {string} [expires=''] - * @param {string} [sameSite='/'] - * @param {string} [domain] domain (e.g., 'example.com' or 'subdomain.example.com'). - * If not specified, defaults to the host portion of the current document location. - * If a domain is specified, subdomains are always included. - * Domain must match the domain of the JavaScript origin. Setting cookies to foreign domains will be silently ignored. - */ -export function setCookie(key, value, expires, sameSite, domain) { - if (hasDeviceAccess()) { - document.cookie = `${key}=${encodeURIComponent(value)}${(expires !== '') ? `; expires=${expires}` : ''}; path=/${sameSite ? `; SameSite=${sameSite}` : ''}${domain ? `; domain=${domain}` : ''}`; - } -} - -/** - * @returns {boolean} - */ -export function localStorageIsEnabled() { - if (hasDeviceAccess()) { - try { - localStorage.setItem('prebid.cookieTest', '1'); - return localStorage.getItem('prebid.cookieTest') === '1'; - } catch (error) {} - } - return false; -} - /** * Given a function, return a function which only executes the original after * it's been called numRequiredCalls times. @@ -1217,50 +1162,6 @@ export function convertTypes(types, params) { return params; } -/** - * @param {string} key - * @param {string} value - */ -export function setDataInLocalStorage(key, value) { - if (hasLocalStorage()) { - window.localStorage.setItem(key, value); - } -} - -/** - * @param {string} key - * @returns {(string|null)} - */ -export function getDataFromLocalStorage(key) { - if (hasLocalStorage()) { - return window.localStorage.getItem(key); - } - return null; -} - -/** - * @param {string} key - */ -export function removeDataFromLocalStorage(key) { - if (hasLocalStorage()) { - window.localStorage.removeItem(key); - } -} - -/** - * @returns {boolean} - */ -export function hasLocalStorage() { - if (hasDeviceAccess()) { - try { - return !!window.localStorage; - } catch (e) { - logError('Local storage api disabled'); - } - } - return false; -} - export function isArrayOfNums(val, size) { return (isArray(val)) && ((size) ? val.length === size : true) && (val.every(v => isInteger(v))); } diff --git a/test/spec/modules/bidfluenceBidAdapter_spec.js b/test/spec/modules/bidfluenceBidAdapter_spec.js index ff33715a176..6b3a0c2b044 100644 --- a/test/spec/modules/bidfluenceBidAdapter_spec.js +++ b/test/spec/modules/bidfluenceBidAdapter_spec.js @@ -51,30 +51,30 @@ describe('Bidfluence Adapter test', () => { }); describe('buildRequests', function () { - const request = spec.buildRequests(validBidRequests, bidderRequest); - it('sends bid request to our endpoint via POST', function () { + const request = spec.buildRequests(validBidRequests, bidderRequest); expect(request.method).to.equal('POST'); - }); + const payload = JSON.parse(request.data); - const payload = JSON.parse(request.data); - - expect(payload.bids[0].bid).to.equal(validBidRequests[0].bidId); - expect(payload.azr).to.equal(true); - expect(payload.ck).to.not.be.undefined; - expect(payload.bids[0].tid).to.equal(PLACEMENT_ID); - expect(payload.bids[0].pid).to.equal(PUB_ID); - expect(payload.bids[0].rp).to.be.a('number'); - expect(payload.re).to.not.be.undefined; - expect(payload.st).to.not.be.undefined; - expect(payload.tz).to.not.be.undefined; - expect(payload.sr).to.not.be.undefined; - expect(payload.vp).to.not.be.undefined; - expect(payload.sdt).to.not.be.undefined; - expect(payload.bids[0].w).to.equal('300'); - expect(payload.bids[0].h).to.equal('250'); + expect(payload.bids[0].bid).to.equal(validBidRequests[0].bidId); + expect(payload.azr).to.equal(true); + expect(payload.ck).to.not.be.undefined; + expect(payload.bids[0].tid).to.equal(PLACEMENT_ID); + expect(payload.bids[0].pid).to.equal(PUB_ID); + expect(payload.bids[0].rp).to.be.a('number'); + expect(payload.re).to.not.be.undefined; + expect(payload.st).to.not.be.undefined; + expect(payload.tz).to.not.be.undefined; + expect(payload.sr).to.not.be.undefined; + expect(payload.vp).to.not.be.undefined; + expect(payload.sdt).to.not.be.undefined; + expect(payload.bids[0].w).to.equal('300'); + expect(payload.bids[0].h).to.equal('250'); + }); it('sends gdpr info if exists', function () { + const request = spec.buildRequests(validBidRequests, bidderRequest); + const payload = JSON.parse(request.data); expect(payload.gdpr).to.equal(true); expect(payload.gdprc).to.equal(CONSENT_STRING); }); diff --git a/test/spec/modules/categoryTranslation_spec.js b/test/spec/modules/categoryTranslation_spec.js index f8684c0d7c0..555fe3d6357 100644 --- a/test/spec/modules/categoryTranslation_spec.js +++ b/test/spec/modules/categoryTranslation_spec.js @@ -1,4 +1,4 @@ -import { getAdserverCategoryHook, initTranslation } from 'modules/categoryTranslation.js'; +import { getAdserverCategoryHook, initTranslation, storage } from 'modules/categoryTranslation.js'; import { config } from 'src/config.js'; import * as utils from 'src/utils.js'; import { expect } from 'chai'; @@ -9,7 +9,7 @@ describe('category translation', function () { beforeEach(function () { fakeTranslationServer = sinon.fakeServer.create(); - getLocalStorageStub = sinon.stub(utils, 'getDataFromLocalStorage'); + getLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage'); }); afterEach(function() { diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index 7ad37a91afe..3d6a6be9fa1 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -1,5 +1,5 @@ import {expect} from 'chai'; -import {spec} from 'modules/conversantBidAdapter.js'; +import {spec, storage} from 'modules/conversantBidAdapter.js'; import * as utils from 'src/utils.js'; import { createEidsArray } from 'modules/userId/eids.js'; @@ -508,7 +508,7 @@ describe('Conversant adapter tests', function() { const requests = utils.deepClone(bidRequests); // add a pubcid cookie - utils.setCookie(ID_NAME, '12345', expStr(TIMEOUT)); + storage.setCookie(ID_NAME, '12345', expStr(TIMEOUT)); // construct http post payload const payload = spec.buildRequests(requests).data; @@ -521,7 +521,7 @@ describe('Conversant adapter tests', function() { requests[0].params.pubcid_name = CUSTOM_ID_NAME; // add a pubcid cookie - utils.setCookie(CUSTOM_ID_NAME, '12345', expStr(TIMEOUT)); + storage.setCookie(CUSTOM_ID_NAME, '12345', expStr(TIMEOUT)); // construct http post payload const payload = spec.buildRequests(requests).data; @@ -533,8 +533,8 @@ describe('Conversant adapter tests', function() { const requests = utils.deepClone(bidRequests); // add a pubcid in local storage - utils.setDataInLocalStorage(ID_NAME + EXP, ''); - utils.setDataInLocalStorage(ID_NAME, 'abcde'); + storage.setDataInLocalStorage(ID_NAME + EXP, ''); + storage.setDataInLocalStorage(ID_NAME, 'abcde'); // construct http post payload const payload = spec.buildRequests(requests).data; @@ -546,8 +546,8 @@ describe('Conversant adapter tests', function() { const requests = utils.deepClone(bidRequests); // add a pubcid in local storage - utils.setDataInLocalStorage(ID_NAME + EXP, expStr(TIMEOUT)); - utils.setDataInLocalStorage(ID_NAME, 'fghijk'); + storage.setDataInLocalStorage(ID_NAME + EXP, expStr(TIMEOUT)); + storage.setDataInLocalStorage(ID_NAME, 'fghijk'); // construct http post payload const payload = spec.buildRequests(requests).data; @@ -559,8 +559,8 @@ describe('Conversant adapter tests', function() { const requests = utils.deepClone(bidRequests); // add a pubcid in local storage - utils.setDataInLocalStorage(ID_NAME + EXP, expStr(-TIMEOUT)); - utils.setDataInLocalStorage(ID_NAME, 'lmnopq'); + storage.setDataInLocalStorage(ID_NAME + EXP, expStr(-TIMEOUT)); + storage.setDataInLocalStorage(ID_NAME, 'lmnopq'); // construct http post payload const payload = spec.buildRequests(requests).data; @@ -573,8 +573,8 @@ describe('Conversant adapter tests', function() { requests[0].params.pubcid_name = CUSTOM_ID_NAME; // add a pubcid in local storage - utils.setDataInLocalStorage(CUSTOM_ID_NAME + EXP, expStr(TIMEOUT)); - utils.setDataInLocalStorage(CUSTOM_ID_NAME, 'fghijk'); + storage.setDataInLocalStorage(CUSTOM_ID_NAME + EXP, expStr(TIMEOUT)); + storage.setDataInLocalStorage(CUSTOM_ID_NAME, 'fghijk'); // construct http post payload const payload = spec.buildRequests(requests).data; diff --git a/test/spec/modules/criteoIdSystem_spec.js b/test/spec/modules/criteoIdSystem_spec.js index c36852251f8..dee9a0563e2 100644 --- a/test/spec/modules/criteoIdSystem_spec.js +++ b/test/spec/modules/criteoIdSystem_spec.js @@ -1,4 +1,4 @@ -import { criteoIdSubmodule } from 'modules/criteoIdSystem.js'; +import { criteoIdSubmodule, storage } from 'modules/criteoIdSystem.js'; import * as utils from 'src/utils.js'; import * as ajaxLib from 'src/ajax.js'; import * as urlLib from 'src/url.js'; @@ -27,11 +27,11 @@ describe('CriteoId module', function () { let triggerPixelStub; beforeEach(function (done) { - getCookieStub = sinon.stub(utils, 'getCookie'); - setCookieStub = sinon.stub(utils, 'setCookie'); - getLocalStorageStub = sinon.stub(utils, 'getDataFromLocalStorage'); - setLocalStorageStub = sinon.stub(utils, 'setDataInLocalStorage'); - removeFromLocalStorageStub = sinon.stub(utils, 'removeDataFromLocalStorage'); + getCookieStub = sinon.stub(storage, 'getCookie'); + setCookieStub = sinon.stub(storage, 'setCookie'); + getLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage'); + setLocalStorageStub = sinon.stub(storage, 'setDataInLocalStorage'); + removeFromLocalStorageStub = sinon.stub(storage, 'removeDataFromLocalStorage'); timeStampStub = sinon.stub(utils, 'timestamp').returns(nowTimestamp); ajaxBuilderStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(mockResponse('{}')); parseUrlStub = sinon.stub(urlLib, 'parse').returns({protocol: 'https', hostname: 'testdev.com'}) diff --git a/test/spec/modules/emoteevBidAdapter_spec.js b/test/spec/modules/emoteevBidAdapter_spec.js index b967eee33b6..bf5bcc9e063 100644 --- a/test/spec/modules/emoteevBidAdapter_spec.js +++ b/test/spec/modules/emoteevBidAdapter_spec.js @@ -47,6 +47,7 @@ import { validateExternalId, VENDOR_ID, WALLPAPER, + storage } from 'modules/emoteevBidAdapter.js'; import * as url from '../../../src/url.js'; import * as utils from '../../../src/utils.js'; @@ -749,7 +750,7 @@ describe('emoteevBidAdapter', function () { }); beforeEach(function () { triggerPixelStub = sinon.stub(utils, 'triggerPixel'); - getCookieSpy = sinon.spy(utils, 'getCookie'); + getCookieSpy = sinon.spy(storage, 'getCookie'); getConfigSpy = sinon.spy(config, 'getConfig'); getParameterByNameSpy = sinon.spy(utils, 'getParameterByName'); }); @@ -776,7 +777,7 @@ describe('emoteevBidAdapter', function () { }; spec.isBidRequestValid(validBidRequest); sinon.assert.notCalled(utils.triggerPixel); - sinon.assert.notCalled(utils.getCookie); + sinon.assert.notCalled(storage.getCookie); // sinon.assert.notCalled(config.getConfig); sinon.assert.notCalled(utils.getParameterByName); }); @@ -786,7 +787,7 @@ describe('emoteevBidAdapter', function () { const invalidBidRequest = {}; spec.isBidRequestValid(invalidBidRequest); sinon.assert.notCalled(utils.triggerPixel); - sinon.assert.notCalled(utils.getCookie); + sinon.assert.notCalled(storage.getCookie); // disabling these getConfig tests as they have been flaky in browserstack testing // sinon.assert.notCalled(config.getConfig); sinon.assert.notCalled(utils.getParameterByName); @@ -796,7 +797,7 @@ describe('emoteevBidAdapter', function () { it('has intended side-effects', function () { spec.buildRequests(cannedValidBidRequests, cannedBidderRequest); sinon.assert.notCalled(utils.triggerPixel); - sinon.assert.notCalled(utils.getCookie); + sinon.assert.notCalled(storage.getCookie); // sinon.assert.callCount(config.getConfig, 3); sinon.assert.callCount(utils.getParameterByName, 2); }); @@ -805,7 +806,7 @@ describe('emoteevBidAdapter', function () { it('has intended side-effects', function () { spec.interpretResponse(serverResponse); sinon.assert.notCalled(utils.triggerPixel); - sinon.assert.notCalled(utils.getCookie); + sinon.assert.notCalled(storage.getCookie); // sinon.assert.notCalled(config.getConfig); sinon.assert.notCalled(utils.getParameterByName); }); @@ -815,7 +816,7 @@ describe('emoteevBidAdapter', function () { const bidObject = serverResponse.body[0]; spec.onBidWon(bidObject); sinon.assert.calledOnce(utils.triggerPixel); - sinon.assert.calledOnce(utils.getCookie); + sinon.assert.calledOnce(storage.getCookie); // sinon.assert.calledOnce(config.getConfig); sinon.assert.calledOnce(utils.getParameterByName); }); @@ -824,7 +825,7 @@ describe('emoteevBidAdapter', function () { it('has intended side-effects', function () { spec.onTimeout(cannedValidBidRequests[0]); sinon.assert.calledOnce(utils.triggerPixel); - sinon.assert.notCalled(utils.getCookie); + sinon.assert.notCalled(storage.getCookie); // sinon.assert.calledOnce(config.getConfig); sinon.assert.calledOnce(utils.getParameterByName); }); @@ -833,7 +834,7 @@ describe('emoteevBidAdapter', function () { it('has intended side-effects', function () { spec.getUserSyncs({}); sinon.assert.notCalled(utils.triggerPixel); - sinon.assert.notCalled(utils.getCookie); + sinon.assert.notCalled(storage.getCookie); // sinon.assert.calledOnce(config.getConfig); sinon.assert.calledOnce(utils.getParameterByName); }); diff --git a/test/spec/modules/eplanningBidAdapter_spec.js b/test/spec/modules/eplanningBidAdapter_spec.js index e9d478f911f..ff03bf033af 100644 --- a/test/spec/modules/eplanningBidAdapter_spec.js +++ b/test/spec/modules/eplanningBidAdapter_spec.js @@ -1,7 +1,6 @@ import { expect } from 'chai'; -import { spec } from 'modules/eplanningBidAdapter.js'; +import { spec, storage } from 'modules/eplanningBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; -import * as utils from 'src/utils.js'; describe('E-Planning Adapter', function () { const adapter = newBidder('spec'); @@ -559,10 +558,10 @@ describe('E-Planning Adapter', function () { }); } beforeEach(function () { - getLocalStorageSpy = sandbox.spy(utils, 'getDataFromLocalStorage'); - setDataInLocalStorageSpy = sandbox.spy(utils, 'setDataInLocalStorage'); + getLocalStorageSpy = sandbox.spy(storage, 'getDataFromLocalStorage'); + setDataInLocalStorageSpy = sandbox.spy(storage, 'setDataInLocalStorage'); - hasLocalStorageStub = sandbox.stub(utils, 'hasLocalStorage'); + hasLocalStorageStub = sandbox.stub(storage, 'hasLocalStorage'); hasLocalStorageStub.returns(true); clock = sandbox.useFakeTimers(); @@ -603,7 +602,7 @@ describe('E-Planning Adapter', function () { sinon.assert.calledWith(getLocalStorageSpy, storageIdRender); sinon.assert.calledWith(setDataInLocalStorageSpy, storageIdRender); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('1'); }); context('when element is fully in view', function() { @@ -617,29 +616,29 @@ describe('E-Planning Adapter', function () { expect(respuesta.data.vs).to.equal('F'); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('1'); - expect(utils.getDataFromLocalStorage(storageIdView)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdView)).to.equal('1'); }); it('when you have more than four render', function() { - utils.setDataInLocalStorage(storageIdRender, 4); + storage.setDataInLocalStorage(storageIdRender, 4); respuesta = spec.buildRequests(bidRequests, bidderRequest); clock.tick(1005); expect(respuesta.data.vs).to.equal('0'); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('5'); - expect(utils.getDataFromLocalStorage(storageIdView)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('5'); + expect(storage.getDataFromLocalStorage(storageIdView)).to.equal('1'); }); it('when you have more than four render and already record visibility', function() { - utils.setDataInLocalStorage(storageIdRender, 4); - utils.setDataInLocalStorage(storageIdView, 4); + storage.setDataInLocalStorage(storageIdRender, 4); + storage.setDataInLocalStorage(storageIdView, 4); respuesta = spec.buildRequests(bidRequests, bidderRequest); clock.tick(1005); expect(respuesta.data.vs).to.equal('a'); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('5'); - expect(utils.getDataFromLocalStorage(storageIdView)).to.equal('5'); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('5'); + expect(storage.getDataFromLocalStorage(storageIdView)).to.equal('5'); }); }); @@ -654,17 +653,17 @@ describe('E-Planning Adapter', function () { clock.tick(1005); expect(respuesta.data.vs).to.equal('F'); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('1'); - expect(utils.getDataFromLocalStorage(storageIdView)).to.equal(null); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdView)).to.equal(null); }); it('when you have more than four render', function() { - utils.setDataInLocalStorage(storageIdRender, 4); + storage.setDataInLocalStorage(storageIdRender, 4); respuesta = spec.buildRequests(bidRequests, bidderRequest); clock.tick(1005); expect(respuesta.data.vs).to.equal('0'); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('5'); - expect(utils.getDataFromLocalStorage(storageIdView)).to.equal(null); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('5'); + expect(storage.getDataFromLocalStorage(storageIdView)).to.equal(null); }); }); @@ -675,16 +674,16 @@ describe('E-Planning Adapter', function () { respuesta = spec.buildRequests(bidRequests, bidderRequest); clock.tick(1005); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('1'); - expect(utils.getDataFromLocalStorage(storageIdView)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdView)).to.equal('1'); }); it('you should not register visibility with less than 50%', function() { createPartiallyInvisibleElement(); respuesta = spec.buildRequests(bidRequests, bidderRequest); clock.tick(1005); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('1'); - expect(utils.getDataFromLocalStorage(storageIdView)).to.equal(null); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdView)).to.equal(null); }); }); context('when width or height of the element is zero', function() { @@ -696,16 +695,16 @@ describe('E-Planning Adapter', function () { spec.buildRequests(bidRequests, bidderRequest) clock.tick(1005); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('1'); - expect(utils.getDataFromLocalStorage(storageIdView)).to.equal(null); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdView)).to.equal(null); }); it('if the height is zero but the width is within the range', function() { element.style.height = '0px'; spec.buildRequests(bidRequests, bidderRequest) clock.tick(1005); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('1'); - expect(utils.getDataFromLocalStorage(storageIdView)).to.equal(null); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdView)).to.equal(null); }); it('if both are zero', function() { element.style.height = '0px'; @@ -713,8 +712,8 @@ describe('E-Planning Adapter', function () { spec.buildRequests(bidRequests, bidderRequest) clock.tick(1005); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('1'); - expect(utils.getDataFromLocalStorage(storageIdView)).to.equal(null); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdView)).to.equal(null); }); }); context('when tab is inactive', function() { @@ -723,8 +722,8 @@ describe('E-Planning Adapter', function () { focusStub.returns(false); spec.buildRequests(bidRequests, bidderRequest); clock.tick(1005); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('1'); - expect(utils.getDataFromLocalStorage(storageIdView)).to.equal(null); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdView)).to.equal(null); }); }); context('segmentBeginsBeforeTheVisibleRange', function() { @@ -732,16 +731,16 @@ describe('E-Planning Adapter', function () { createElementOutOfRange(); spec.buildRequests(bidRequests, bidderRequest); clock.tick(1005); - expect(utils.getDataFromLocalStorage(storageIdRender)).to.equal('1'); - expect(utils.getDataFromLocalStorage(storageIdView)).to.equal(null); + expect(storage.getDataFromLocalStorage(storageIdRender)).to.equal('1'); + expect(storage.getDataFromLocalStorage(storageIdView)).to.equal(null); }); }); context('when there are multiple adunit', function() { let respuesta; beforeEach(function () { [ADUNIT_CODE_VIEW, ADUNIT_CODE_VIEW2, ADUNIT_CODE_VIEW3].forEach(ac => { - utils.setDataInLocalStorage('pbsr_' + ac, 5); - utils.setDataInLocalStorage('pbvi_' + ac, 5); + storage.setDataInLocalStorage('pbsr_' + ac, 5); + storage.setDataInLocalStorage('pbvi_' + ac, 5); }); }); afterEach(function () { @@ -761,8 +760,8 @@ describe('E-Planning Adapter', function () { respuesta = spec.buildRequests(bidRequestMultiple, bidderRequest); clock.tick(1005); [ADUNIT_CODE_VIEW, ADUNIT_CODE_VIEW2, ADUNIT_CODE_VIEW3].forEach(ac => { - expect(utils.getDataFromLocalStorage('pbsr_' + ac)).to.equal('6'); - expect(utils.getDataFromLocalStorage('pbvi_' + ac)).to.equal('6'); + expect(storage.getDataFromLocalStorage('pbsr_' + ac)).to.equal('6'); + expect(storage.getDataFromLocalStorage('pbvi_' + ac)).to.equal('6'); }); expect('aaa').to.equal(respuesta.data.vs); }); @@ -774,8 +773,8 @@ describe('E-Planning Adapter', function () { respuesta = spec.buildRequests(bidRequestMultiple, bidderRequest); clock.tick(1005); [ADUNIT_CODE_VIEW, ADUNIT_CODE_VIEW2, ADUNIT_CODE_VIEW3].forEach(ac => { - expect(utils.getDataFromLocalStorage('pbsr_' + ac)).to.equal('6'); - expect(utils.getDataFromLocalStorage('pbvi_' + ac)).to.equal('5'); + expect(storage.getDataFromLocalStorage('pbsr_' + ac)).to.equal('6'); + expect(storage.getDataFromLocalStorage('pbvi_' + ac)).to.equal('5'); }); expect('aaa').to.equal(respuesta.data.vs); @@ -787,11 +786,11 @@ describe('E-Planning Adapter', function () { respuesta = spec.buildRequests(bidRequestMultiple, bidderRequest); clock.tick(1005); - expect(utils.getDataFromLocalStorage('pbsr_' + ADUNIT_CODE_VIEW)).to.equal('6'); - expect(utils.getDataFromLocalStorage('pbvi_' + ADUNIT_CODE_VIEW)).to.equal('6'); + expect(storage.getDataFromLocalStorage('pbsr_' + ADUNIT_CODE_VIEW)).to.equal('6'); + expect(storage.getDataFromLocalStorage('pbvi_' + ADUNIT_CODE_VIEW)).to.equal('6'); [ADUNIT_CODE_VIEW2, ADUNIT_CODE_VIEW3].forEach(ac => { - expect(utils.getDataFromLocalStorage('pbsr_' + ac)).to.equal('6'); - expect(utils.getDataFromLocalStorage('pbvi_' + ac)).to.equal('5'); + expect(storage.getDataFromLocalStorage('pbsr_' + ac)).to.equal('6'); + expect(storage.getDataFromLocalStorage('pbvi_' + ac)).to.equal('5'); }); expect('aaa').to.equal(respuesta.data.vs); }); diff --git a/test/spec/modules/gdprEnforcement_spec.js b/test/spec/modules/gdprEnforcement_spec.js index 9ed6395179a..f0dc79e3f89 100644 --- a/test/spec/modules/gdprEnforcement_spec.js +++ b/test/spec/modules/gdprEnforcement_spec.js @@ -2,6 +2,8 @@ import { deviceAccessHook, setEnforcementConfig, userSyncHook, userIdHook } from import { config } from 'src/config.js'; import adapterManager, { gdprDataHandler } from 'src/adapterManager.js'; import * as utils from 'src/utils.js'; +import { validateStorageEnforcement } from 'src/storageManager.js'; +import { executeStorageCallbacks } from 'src/prebid.js'; describe('gdpr enforcement', function() { let nextFnSpy; @@ -79,6 +81,11 @@ describe('gdpr enforcement', function() { } }; + after(function() { + validateStorageEnforcement.getHooks({hook: deviceAccessHook}).remove(); + $$PREBID_GLOBAL$$.requestBids.getHooks({hook: executeStorageCallbacks}).remove(); + }) + describe('deviceAccessHook', function() { beforeEach(function() { nextFnSpy = sinon.spy(); @@ -127,6 +134,7 @@ describe('gdpr enforcement', function() { }); let consentData = {} consentData.vendorData = staticConfig.consentData.getTCData; + consentData.gdprApplies = true; consentData.apiVersion = 2; gdprDataHandlerStub.returns(consentData); @@ -217,6 +225,7 @@ describe('gdpr enforcement', function() { }); let consentData = {} consentData.vendorData = staticConfig.consentData.getTCData; + consentData.gdprApplies = true; consentData.apiVersion = 2; gdprDataHandlerStub.returns(consentData); @@ -281,6 +290,46 @@ describe('gdpr enforcement', function() { expect(nextFnSpy.calledOnce).to.equal(true); expect(logWarnSpy.callCount).to.equal(1); }); + + it('should not check vendor consent when enforceVendor is false', function() { + setEnforcementConfig({ + gdpr: { + rules: [{ + purpose: 'storage', + enforcePurpose: true, + enforceVendor: false, + vendorExceptions: ['sampleBidder1'] + }] + } + }); + let consentData = {} + consentData.vendorData = staticConfig.consentData.getTCData; + consentData.apiVersion = 2; + consentData.gdprApplies = true; + gdprDataHandlerStub.returns(consentData); + + curBidderStub.returns('sampleBidder1'); + adapterManagerStub.withArgs('sampleBidder1').returns({ + getSpec: function() { + return { + 'gvlid': 1 + } + } + }); + userSyncHook(nextFnSpy); + + curBidderStub.returns('sampleBidder2'); + adapterManagerStub.withArgs('sampleBidder2').returns({ + getSpec: function() { + return { + 'gvlid': 3 + } + } + }); + userSyncHook(nextFnSpy); + expect(nextFnSpy.calledTwice).to.equal(true); + expect(logWarnSpy.callCount).to.equal(0); + }); }); describe('userIdHook', function() { diff --git a/test/spec/modules/liveIntentIdSystem_spec.js b/test/spec/modules/liveIntentIdSystem_spec.js index 450c4b71bd7..2f4fe830847 100644 --- a/test/spec/modules/liveIntentIdSystem_spec.js +++ b/test/spec/modules/liveIntentIdSystem_spec.js @@ -1,4 +1,4 @@ -import { liveIntentIdSubmodule } from 'modules/liveIntentIdSystem.js'; +import { liveIntentIdSubmodule, storage } from 'modules/liveIntentIdSystem.js'; import * as utils from 'src/utils.js'; import { server } from 'test/mocks/xhr.js'; @@ -11,8 +11,8 @@ describe('LiveIntentId', function() { const responseHeader = { 'Content-Type': 'application/json' } beforeEach(function () { - getCookieStub = sinon.stub(utils, 'getCookie'); - getDataFromLocalStorageStub = sinon.stub(utils, 'getDataFromLocalStorage'); + getCookieStub = sinon.stub(storage, 'getCookie'); + getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage'); logErrorStub = sinon.stub(utils, 'logError'); }); diff --git a/test/spec/modules/livewrappedBidAdapter_spec.js b/test/spec/modules/livewrappedBidAdapter_spec.js index a48c00b6890..7b26f5b533d 100644 --- a/test/spec/modules/livewrappedBidAdapter_spec.js +++ b/test/spec/modules/livewrappedBidAdapter_spec.js @@ -1,5 +1,5 @@ import {expect} from 'chai'; -import {spec} from 'modules/livewrappedBidAdapter.js'; +import {spec, storage} from 'modules/livewrappedBidAdapter.js'; import {config} from 'src/config.js'; import * as utils from 'src/utils.js'; import { BANNER, NATIVE } from 'src/mediaTypes.js'; @@ -88,7 +88,7 @@ describe('Livewrapped adapter tests', function () { describe('buildRequests', function() { it('should make a well-formed single request object', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let result = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = JSON.parse(result.data); @@ -116,7 +116,7 @@ describe('Livewrapped adapter tests', function () { it('should make a well-formed multiple request object', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let multiplebidRequest = clone(bidderRequest); multiplebidRequest.bids.push(clone(bidderRequest.bids[0])); multiplebidRequest.bids[1].adUnitCode = 'box_d_1'; @@ -156,7 +156,7 @@ describe('Livewrapped adapter tests', function () { it('should make a well-formed single request object with AdUnitName', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); testbidRequest.bids[0].params.adUnitName = 'caller id 1'; delete testbidRequest.bids[0].params.adUnitId; @@ -186,7 +186,7 @@ describe('Livewrapped adapter tests', function () { it('should make a well-formed single request object with less parameters', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); delete testbidRequest.bids[0].params.userId; delete testbidRequest.bids[0].params.seats; @@ -215,7 +215,7 @@ describe('Livewrapped adapter tests', function () { it('should make a well-formed single request object with less parameters, no publisherId', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); delete testbidRequest.bids[0].params.userId; delete testbidRequest.bids[0].params.seats; @@ -244,7 +244,7 @@ describe('Livewrapped adapter tests', function () { it('should make a well-formed single request object with app parameters', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); delete testbidRequest.bids[0].params.userId; delete testbidRequest.bids[0].params.seats; @@ -275,7 +275,7 @@ describe('Livewrapped adapter tests', function () { it('should make a well-formed single request object with debug parameters', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); delete testbidRequest.bids[0].params.userId; delete testbidRequest.bids[0].params.seats; @@ -306,7 +306,7 @@ describe('Livewrapped adapter tests', function () { it('should make a well-formed single request object with optional parameters', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); delete testbidRequest.bids[0].params.userId; delete testbidRequest.bids[0].params.seats; @@ -336,7 +336,7 @@ describe('Livewrapped adapter tests', function () { it('should make a well-formed single request object with ad blocker revovered parameter', function() { sandbox.stub(utils, 'getWindowTop').returns({ I12C: { Morph: 1 } }); sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); delete testbidRequest.bids[0].params.userId; delete testbidRequest.bids[0].params.seats; @@ -364,7 +364,7 @@ describe('Livewrapped adapter tests', function () { it('should make a well-formed single request object with native only parameters', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); delete testbidRequest.bids[0].params.userId; delete testbidRequest.bids[0].params.seats; @@ -393,7 +393,7 @@ describe('Livewrapped adapter tests', function () { it('should make a well-formed single request object with native and banner parameters', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); delete testbidRequest.bids[0].params.userId; delete testbidRequest.bids[0].params.seats; @@ -423,7 +423,7 @@ describe('Livewrapped adapter tests', function () { it('should use mediaTypes.banner.sizes before legacy sizes', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); delete testbidRequest.bids[0].params.userId; delete testbidRequest.bids[0].params.seats; @@ -451,7 +451,7 @@ describe('Livewrapped adapter tests', function () { it('should pass gdpr true parameters', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testRequest = clone(bidderRequest); testRequest.gdprConsent = { gdprApplies: true, @@ -486,7 +486,7 @@ describe('Livewrapped adapter tests', function () { it('should pass gdpr false parameters', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testRequest = clone(bidderRequest); testRequest.gdprConsent = { gdprApplies: false @@ -518,7 +518,7 @@ describe('Livewrapped adapter tests', function () { }); it('should pass no cookie support', function() { - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => false); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => false); sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); let result = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = JSON.parse(result.data); @@ -546,7 +546,7 @@ describe('Livewrapped adapter tests', function () { }); it('should pass no cookie support Safari', function() { - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); sandbox.stub(utils, 'isSafariBrowser').callsFake(() => true); let result = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = JSON.parse(result.data); @@ -605,7 +605,7 @@ describe('Livewrapped adapter tests', function () { it('should make use of pubcid if available', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); delete testbidRequest.bids[0].params.userId; testbidRequest.bids[0].crumbs = {pubcid: 'pubcid 123'}; @@ -636,7 +636,7 @@ describe('Livewrapped adapter tests', function () { it('should make userId take precedence over pubcid', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); testbidRequest.bids[0].crumbs = {pubcid: 'pubcid 123'}; let result = spec.buildRequests(testbidRequest.bids, testbidRequest); @@ -667,7 +667,7 @@ describe('Livewrapped adapter tests', function () { it('should make use of Id5-Id if available', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); delete testbidRequest.bids[0].params.userId; testbidRequest.bids[0].userId = {}; @@ -686,7 +686,7 @@ describe('Livewrapped adapter tests', function () { it('should make use of publisher common Id if available', function() { sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false); - sandbox.stub(utils, 'cookiesAreEnabled').callsFake(() => true); + sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true); let testbidRequest = clone(bidderRequest); delete testbidRequest.bids[0].params.userId; testbidRequest.bids[0].userId = {}; diff --git a/test/spec/modules/newborntownWebBidAdapter_spec.js b/test/spec/modules/newborntownWebBidAdapter_spec.js index 84937d00012..3d3285328fe 100644 --- a/test/spec/modules/newborntownWebBidAdapter_spec.js +++ b/test/spec/modules/newborntownWebBidAdapter_spec.js @@ -54,8 +54,8 @@ describe('NewborntownWebAdapter', function() { 'timeout': 9000, 'start': 1573123289383 } - const request = spec.buildRequests(bidderRequest['bids'], bidderRequest); it('Returns POST method', function () { + const request = spec.buildRequests(bidderRequest['bids'], bidderRequest); expect(request[0].method).to.equal('POST'); expect(request[0].url.indexOf('//us-west.solortb.com/adx/api/rtb?from=4') !== -1).to.equal(true); expect(request[0].data).to.exist; diff --git a/test/spec/modules/parrableIdSystem_spec.js b/test/spec/modules/parrableIdSystem_spec.js index 936b4c3a824..93415126a0a 100644 --- a/test/spec/modules/parrableIdSystem_spec.js +++ b/test/spec/modules/parrableIdSystem_spec.js @@ -3,6 +3,9 @@ import {config} from 'src/config.js'; import * as utils from 'src/utils.js'; import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js'; import { parrableIdSubmodule } from 'modules/parrableIdSystem.js'; +import { newStorageManager } from 'src/storageManager.js'; + +const storage = newStorageManager(); const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; const P_COOKIE_NAME = '_parrable_eid'; @@ -52,7 +55,7 @@ describe('Parrable ID System', function() { it('should append parrableid to bid request', function(done) { // simulate existing browser local storage values - utils.setCookie( + storage.setCookie( P_COOKIE_NAME, P_COOKIE_VALUE, (new Date(Date.now() + 5000).toUTCString()) @@ -69,7 +72,7 @@ describe('Parrable ID System', function() { expect(bid.userId.parrableid).to.equal(P_COOKIE_VALUE); }); }); - utils.setCookie(P_COOKIE_NAME, '', EXPIRED_COOKIE_DATE); + storage.setCookie(P_COOKIE_NAME, '', EXPIRED_COOKIE_DATE); done(); }, { adUnits }); }); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index e2564acbb3a..6ff2095665d 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -68,29 +68,27 @@ describe('User ID', function() { } before(function() { - utils.setCookie('_pubcid_optout', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('_pubcid_optout', '', EXPIRED_COOKIE_DATE); localStorage.removeItem('_pbjs_id_optout'); localStorage.removeItem('_pubcid_optout'); }); describe('Decorate Ad Units', function() { beforeEach(function() { - utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('pubcid_alt', 'altpubcid200000', (new Date(Date.now() + 5000).toUTCString())); - sinon.spy(utils, 'setCookie'); + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('pubcid_alt', 'altpubcid200000', (new Date(Date.now() + 5000).toUTCString())); sinon.spy(coreStorage, 'setCookie'); }); afterEach(function () { $$PREBID_GLOBAL$$.requestBids.removeAll(); config.resetConfig(); - utils.setCookie.restore(); coreStorage.setCookie.restore(); }); after(function() { - utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('pubcid_alt', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('pubcid_alt', '', EXPIRED_COOKIE_DATE); }); it('Check same cookie behavior', function () { @@ -99,7 +97,7 @@ describe('User ID', function() { let innerAdUnits1; let innerAdUnits2; - let pubcid = utils.getCookie('pubcid'); + let pubcid = coreStorage.getCookie('pubcid'); expect(pubcid).to.be.null; // there should be no cookie initially setSubmoduleRegistry([pubCommonIdSubmodule]); @@ -107,7 +105,7 @@ describe('User ID', function() { config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook(config => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); - pubcid = utils.getCookie('pubcid'); // cookies is created after requestbidHook + pubcid = coreStorage.getCookie('pubcid'); // cookies is created after requestbidHook innerAdUnits1.forEach(unit => { unit.bids.forEach(bid => { @@ -136,8 +134,8 @@ describe('User ID', function() { init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); - pubcid1 = utils.getCookie('pubcid'); // get first cookie - utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); // erase cookie + pubcid1 = coreStorage.getCookie('pubcid'); // get first cookie + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); // erase cookie innerAdUnits1.forEach((unit) => { unit.bids.forEach((bid) => { @@ -155,7 +153,7 @@ describe('User ID', function() { config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); requestBidsHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); - pubcid2 = utils.getCookie('pubcid'); // get second cookie + pubcid2 = coreStorage.getCookie('pubcid'); // get second cookie innerAdUnits2.forEach((unit) => { unit.bids.forEach((bid) => { @@ -190,7 +188,7 @@ describe('User ID', function() { }); }); // Because the cookie exists already, there should be no setCookie call by default - expect(utils.setCookie.callCount).to.equal(0); + expect(coreStorage.setCookie.callCount).to.equal(0); }); it('Extend cookie', function () { @@ -233,13 +231,13 @@ describe('User ID', function() { expect(bid).to.not.have.deep.nested.property('userIdAsEids'); }); }); - expect(utils.setCookie.callCount).to.equal(0); + expect(coreStorage.setCookie.callCount).to.equal(0); }); }); describe('Opt out', function () { before(function () { - utils.setCookie('_pbjs_id_optout', '1', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('_pbjs_id_optout', '1', (new Date(Date.now() + 5000).toUTCString())); }); beforeEach(function () { @@ -248,14 +246,14 @@ describe('User ID', function() { afterEach(function () { // removed cookie - utils.setCookie('_pbjs_id_optout', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('_pbjs_id_optout', '', EXPIRED_COOKIE_DATE); $$PREBID_GLOBAL$$.requestBids.removeAll(); utils.logInfo.restore(); config.resetConfig(); }); after(function () { - utils.setCookie('_pbjs_id_optout', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('_pbjs_id_optout', '', EXPIRED_COOKIE_DATE); }); it('fails initialization if opt out cookie exists', function () { @@ -425,7 +423,7 @@ describe('User ID', function() { sandbox.stub(events, 'on'); // remove cookie - utils.setCookie('MOCKID', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('MOCKID', '', EXPIRED_COOKIE_DATE); adUnits = [getAdUnitMock()]; @@ -439,7 +437,7 @@ describe('User ID', function() { }; }, getId: function() { - const storedId = utils.getCookie('MOCKID'); + const storedId = coreStorage.getCookie('MOCKID'); if (storedId) { return {id: {'MOCKID': storedId}}; } @@ -596,7 +594,7 @@ describe('User ID', function() { }); it('does not delay auction if there are no ids to fetch', function() { - utils.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); config.setConfig({ userSync: { @@ -627,7 +625,7 @@ describe('User ID', function() { }); it('test hook from pubcommonid cookie', function(done) { - utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 100000).toUTCString())); + coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); @@ -644,7 +642,7 @@ describe('User ID', function() { }); }); }); - utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); @@ -718,7 +716,7 @@ describe('User ID', function() { }); it('test hook from identityLink cookie', function(done) { - utils.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 100000).toUTCString())); + coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([identityLinkSubmodule]); init(config); @@ -735,7 +733,7 @@ describe('User ID', function() { }); }); }); - utils.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); @@ -766,7 +764,7 @@ describe('User ID', function() { }); it('test hook from liveIntentId cookie', function(done) { - utils.setCookie('_li_pbid', JSON.stringify({'unifiedId': 'random-cookie-identifier'}), (new Date(Date.now() + 100000).toUTCString())); + coreStorage.setCookie('_li_pbid', JSON.stringify({'unifiedId': 'random-cookie-identifier'}), (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([liveIntentIdSubmodule]); init(config); @@ -783,15 +781,15 @@ describe('User ID', function() { }); }); }); - utils.setCookie('_li_pbid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('_li_pbid', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); it('test hook from id5id cookies when refresh needed', function(done) { // simulate existing browser local storage values - utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('id5id_last', (new Date(Date.now() - 7200 * 1000)).toUTCString(), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('id5id_last', (new Date(Date.now() - 7200 * 1000)).toUTCString(), (new Date(Date.now() + 5000).toUTCString())); sinon.stub(utils, 'logError'); // getId should failed with a logError as it has no partnerId @@ -811,7 +809,7 @@ describe('User ID', function() { }); }); sinon.assert.calledOnce(utils.logError); - utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('id5id', '', EXPIRED_COOKIE_DATE); utils.logError.restore(); done(); }, {adUnits}); @@ -865,7 +863,7 @@ describe('User ID', function() { }); it('test hook from liveIntentId cookie', function(done) { - utils.setCookie('_li_pbid', JSON.stringify({'unifiedId': 'random-cookie-identifier', 'segments': ['123']}), (new Date(Date.now() + 100000).toUTCString())); + coreStorage.setCookie('_li_pbid', JSON.stringify({'unifiedId': 'random-cookie-identifier', 'segments': ['123']}), (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([liveIntentIdSubmodule]); init(config); @@ -884,14 +882,14 @@ describe('User ID', function() { }); }); }); - utils.setCookie('_li_pbid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('_li_pbid', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); it('test hook from britepoolid cookies', function(done) { // simulate existing browser local storage values - utils.setCookie('britepoolid', JSON.stringify({'primaryBPID': '279c0161-5152-487f-809e-05d7f7e653fd'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': '279c0161-5152-487f-809e-05d7f7e653fd'}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([britepoolIdSubmodule]); init(config); @@ -908,14 +906,14 @@ describe('User ID', function() { }); }); }); - utils.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); it('test hook from netId cookies', function(done) { // simulate existing browser local storage values - utils.setCookie('netId', JSON.stringify({'netId': 'fH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('netId', JSON.stringify({'netId': 'fH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg'}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([netIdSubmodule]); init(config); @@ -932,18 +930,18 @@ describe('User ID', function() { }); }); }); - utils.setCookie('netId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId and netId have data to pass', function(done) { - utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule]); init(config); @@ -978,23 +976,23 @@ describe('User ID', function() { expect(bid.userIdAsEids.length).to.equal(6); }); }); - utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); - utils.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); - utils.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('netId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); it('test hook when pubCommonId, unifiedId, id5Id, britepoolId and netId have their modules added before and after init', function(done) { - utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); - utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); - utils.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([]); @@ -1041,24 +1039,24 @@ describe('User ID', function() { expect(bid.userIdAsEids.length).to.equal(6); }); }); - utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); - utils.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); - utils.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('netId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); it('should add new id system ', function(done) { - utils.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); - utils.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); - utils.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); - utils.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), new Date(Date.now() + 5000).toUTCString()); - utils.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule]); init(config); @@ -1125,13 +1123,13 @@ describe('User ID', function() { expect(bid.userIdAsEids.length).to.equal(6);// mid is unknown for eids.js }); }); - utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('id5id', '', EXPIRED_COOKIE_DATE); - utils.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); - utils.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('netId', '', EXPIRED_COOKIE_DATE); - utils.setCookie('MOCKID', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('MOCKID', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); @@ -1141,17 +1139,17 @@ describe('User ID', function() { beforeEach(function() { sinon.stub(events, 'getEvents').returns([]); sinon.stub(utils, 'triggerPixel'); - utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('_parrable_eid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('_parrable_eid', '', EXPIRED_COOKIE_DATE); }); afterEach(function() { events.getEvents.restore(); utils.triggerPixel.restore(); - utils.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); - utils.setCookie('_parrable_eid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('_parrable_eid', '', EXPIRED_COOKIE_DATE); }); it('pubcid callback with url', function () { @@ -1207,7 +1205,7 @@ describe('User ID', function() { let innerAdUnits; const parrableStoredId = '01.1111111111.test-eid'; const parrableRefreshedId = '02.2222222222.test-eid'; - utils.setCookie('_parrable_eid', parrableStoredId, (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('_parrable_eid', parrableStoredId, (new Date(Date.now() + 5000).toUTCString())); const parrableIdSubmoduleMock = { name: 'parrableId', diff --git a/test/spec/modules/widespaceBidAdapter_spec.js b/test/spec/modules/widespaceBidAdapter_spec.js index c7d4f3bdaf9..95f0117e5d1 100644 --- a/test/spec/modules/widespaceBidAdapter_spec.js +++ b/test/spec/modules/widespaceBidAdapter_spec.js @@ -1,5 +1,5 @@ import {expect} from 'chai'; -import {spec} from 'modules/widespaceBidAdapter.js'; +import {spec, storage} from 'modules/widespaceBidAdapter.js'; import includes from 'core-js/library/fn/array/includes.js'; describe('+widespaceAdatperTest', function () { @@ -141,8 +141,11 @@ describe('+widespaceAdatperTest', function () { }); describe('+bidRequest', function () { - const request = spec.buildRequests(bidRequest, bidderRequest); + let request; const UrlRegExp = /^((ftp|http|https):)?\/\/[^ "]+$/; + before(function() { + request = spec.buildRequests(bidRequest, bidderRequest); + }) let fakeLocalStorage = {}; let lsSetStub; @@ -150,15 +153,15 @@ describe('+widespaceAdatperTest', function () { let lsRemoveStub; beforeEach(function () { - lsSetStub = sinon.stub(window.localStorage, 'setItem').callsFake(function (name, value) { + lsSetStub = sinon.stub(storage, 'setDataInLocalStorage').callsFake(function (name, value) { fakeLocalStorage[name] = value; }); - lsGetStub = sinon.stub(window.localStorage, 'getItem').callsFake(function (key) { + lsGetStub = sinon.stub(storage, 'getDataFromLocalStorage').callsFake(function (key) { return fakeLocalStorage[key] || null; }); - lsRemoveStub = sinon.stub(window.localStorage, 'removeItem').callsFake(function (key) { + lsRemoveStub = sinon.stub(storage, 'removeDataFromLocalStorage').callsFake(function (key) { if (key && (fakeLocalStorage[key] !== null || fakeLocalStorage[key] !== undefined)) { delete fakeLocalStorage[key]; } diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index c06eb29b6b9..a50cb6d9e58 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -1,4 +1,4 @@ -import { newBidder, registerBidder, preloadBidderMappingFile } from 'src/adapters/bidderFactory.js'; +import { newBidder, registerBidder, preloadBidderMappingFile, storage } from 'src/adapters/bidderFactory.js'; import adapterManager from 'src/adapterManager.js'; import * as ajax from 'src/ajax.js'; import { expect } from 'chai'; @@ -793,7 +793,7 @@ describe('preload mapping url hook', function() { beforeEach(function () { fakeTranslationServer = server; - getLocalStorageStub = sinon.stub(utils, 'getDataFromLocalStorage'); + getLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage'); adapterManagerStub = sinon.stub(adapterManager, 'getBidAdapter'); }); diff --git a/test/spec/unit/core/storageManager_spec.js b/test/spec/unit/core/storageManager_spec.js new file mode 100644 index 00000000000..9efb05b94ed --- /dev/null +++ b/test/spec/unit/core/storageManager_spec.js @@ -0,0 +1,43 @@ +import { resetData, getCoreStorageManager, storageCallbacks, getStorageManager } from 'src/storageManager.js'; +import { config } from 'src/config.js'; +import * as utils from 'src/utils.js'; + +describe('storage manager', function() { + beforeEach(function() { + resetData(); + }); + + afterEach(function() { + config.resetConfig(); + }) + + it('should allow to set cookie for core modules without checking gdpr enforcements', function() { + const coreStorage = getCoreStorageManager(); + coreStorage.setCookie('hello', 'world'); + expect(coreStorage.getCookie('hello')).to.equal('world'); + }); + + it('should add done callbacks to storageCallbacks array', function() { + let noop = sinon.spy(); + const coreStorage = getStorageManager(); + + coreStorage.setCookie('hello', 'world', null, null, null, noop); + coreStorage.getCookie('hello', noop); + coreStorage.localStorageIsEnabled(noop); + coreStorage.cookiesAreEnabled(noop); + coreStorage.setDataInLocalStorage('foo', 'bar', noop); + coreStorage.getDataFromLocalStorage('foo', noop); + coreStorage.removeDataFromLocalStorage('foo', noop); + coreStorage.hasLocalStorage(noop); + + expect(storageCallbacks.length).to.equal(8); + }); + + it('should allow bidder to access device if gdpr enforcement module is not included', function() { + let deviceAccessSpy = sinon.spy(utils, 'hasDeviceAccess'); + const storage = getStorageManager(); + storage.setCookie('hello', 'world'); + expect(deviceAccessSpy.calledOnce).to.equal(true); + deviceAccessSpy.restore(); + }) +}); From 97c586177f5da1f9d5e76e7af2e4c0f95d111f7a Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 30 Mar 2020 01:11:34 -0400 Subject: [PATCH 06/10] add expires for ie11 --- src/storageManager.js | 2 +- test/spec/unit/core/storageManager_spec.js | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/storageManager.js b/src/storageManager.js index 4467ba6bec0..a23ca63854d 100644 --- a/src/storageManager.js +++ b/src/storageManager.js @@ -62,7 +62,7 @@ export function newStorageManager({gvlid, moduleName, moduleType} = {}) { const setCookie = function (key, value, expires, sameSite, domain, done) { let cb = function (result) { if (result && result.valid) { - document.cookie = `${key}=${encodeURIComponent(value)}${(expires !== '') ? `; expires=${expires}` : ''}; path=/${sameSite ? `; SameSite=${sameSite}` : ''}${domain ? `; domain=${domain}` : ''}`; + document.cookie = `${key}=${encodeURIComponent(value)}${(typeof expires !== 'undefined') ? `; expires=${expires}` : ''}; path=/${sameSite ? `; SameSite=${sameSite}` : ''}${domain ? `; domain=${domain}` : ''}`; } } if (done && typeof done === 'function') { diff --git a/test/spec/unit/core/storageManager_spec.js b/test/spec/unit/core/storageManager_spec.js index 9efb05b94ed..0b406242f90 100644 --- a/test/spec/unit/core/storageManager_spec.js +++ b/test/spec/unit/core/storageManager_spec.js @@ -13,7 +13,10 @@ describe('storage manager', function() { it('should allow to set cookie for core modules without checking gdpr enforcements', function() { const coreStorage = getCoreStorageManager(); - coreStorage.setCookie('hello', 'world'); + let date = new Date(); + date.setTime(date.getTime() + (24 * 60 * 60 * 1000)); + let expires = date.toUTCString(); + coreStorage.setCookie('hello', 'world', expires); expect(coreStorage.getCookie('hello')).to.equal('world'); }); @@ -21,8 +24,8 @@ describe('storage manager', function() { let noop = sinon.spy(); const coreStorage = getStorageManager(); - coreStorage.setCookie('hello', 'world', null, null, null, noop); - coreStorage.getCookie('hello', noop); + coreStorage.setCookie('foo', 'bar', null, null, null, noop); + coreStorage.getCookie('foo', noop); coreStorage.localStorageIsEnabled(noop); coreStorage.cookiesAreEnabled(noop); coreStorage.setDataInLocalStorage('foo', 'bar', noop); @@ -36,7 +39,7 @@ describe('storage manager', function() { it('should allow bidder to access device if gdpr enforcement module is not included', function() { let deviceAccessSpy = sinon.spy(utils, 'hasDeviceAccess'); const storage = getStorageManager(); - storage.setCookie('hello', 'world'); + storage.setCookie('foo1', 'baz1'); expect(deviceAccessSpy.calledOnce).to.equal(true); deviceAccessSpy.restore(); }) From 506f95890fa79407f238de74bdbd19814bb6d6da Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 31 Mar 2020 14:14:16 -0400 Subject: [PATCH 07/10] adding withCredentials false to appnexus adapter --- modules/appnexusBidAdapter.js | 22 ++++++++++++++-- modules/quantcastBidAdapter.js | 1 + test/spec/modules/appnexusBidAdapter_spec.js | 27 ++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 981813ec8f9..7add5f11999 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -408,8 +408,24 @@ function getViewabilityScriptUrlFromPayload(viewJsPayload) { return jsTrackerSrc; } +function hasPurpose1Consent(bidderRequest) { + let result = true; + if (bidderRequest && bidderRequest.gdprConsent) { + if (bidderRequest.gdprConsent.gdprApplies && bidderRequest.gdprConsent.apiVersion === 2) { + result = !!(utils.deepAccess(bidderRequest.gdprConsent, `vendorData.vendor.consents.${GVLID}`)); + } + } + return result; +} + function formatRequest(payload, bidderRequest) { let request = []; + let options = {}; + if (!hasPurpose1Consent(bidderRequest)) { + options = { + withCredentials: false + } + } if (payload.tags.length > MAX_IMPS_PER_REQUEST) { const clonedPayload = utils.deepClone(payload); @@ -421,7 +437,8 @@ function formatRequest(payload, bidderRequest) { method: 'POST', url: URL, data: payloadString, - bidderRequest + bidderRequest, + options }); }); } else { @@ -430,7 +447,8 @@ function formatRequest(payload, bidderRequest) { method: 'POST', url: URL, data: payloadString, - bidderRequest + bidderRequest, + options }; } diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 4ffb84b8934..ab7ea54bfb6 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -78,6 +78,7 @@ function getDomain(url) { */ export const spec = { code: BIDDER_CODE, + GVLID: 11, supportedMediaTypes: ['banner', 'video'], /** diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index c61b1cf1979..6febb8ecc9a 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -624,6 +624,7 @@ describe('AppNexusAdapter', function () { bidderRequest.bids = bidRequests; const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.options).to.be.empty; const payload = JSON.parse(request.data); expect(payload.gdpr_consent).to.exist; @@ -774,6 +775,32 @@ describe('AppNexusAdapter', function () { config.getConfig.restore(); }); + + it('should set withCredentials to false if purpose 1 consent is not given', function () { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + let bidderRequest = { + 'bidderCode': 'appnexus', + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000, + 'gdprConsent': { + consentString: consentString, + gdprApplies: true, + apiVersion: 2, + vendorData: { + vendor: { + consents: { + 32: false + } + } + } + } + }; + bidderRequest.bids = bidRequests; + + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.options).to.deep.equal({withCredentials: false}); + }); }) describe('interpretResponse', function () { From a138650749bc6a54786889453ae7daa57764ffbe Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 31 Mar 2020 15:07:59 -0400 Subject: [PATCH 08/10] improving conditions --- modules/gdprEnforcement.js | 14 +++++++------- test/spec/modules/gdprEnforcement_spec.js | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/modules/gdprEnforcement.js b/modules/gdprEnforcement.js index b1c53c14d11..caefcaf0faa 100644 --- a/modules/gdprEnforcement.js +++ b/modules/gdprEnforcement.js @@ -37,6 +37,7 @@ function getGvlid() { */ function validateRules(rule, consentData, currentModule, gvlid) { let isAllowed = false; + if (!rule.vendorExceptions) rule.vendorExceptions = []; if (rule.enforcePurpose && rule.enforceVendor) { if ( includes(rule.vendorExceptions, currentModule) || @@ -69,14 +70,13 @@ function validateRules(rule, consentData, currentModule, gvlid) { } } else if (rule.enforcePurpose === true && rule.enforceVendor === false) { if ( + (utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true) && ( - !includes(rule.vendorExceptions, currentModule) && - (utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true) - ) || - ( - includes(rule.vendorExceptions, currentModule) && - (utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true) && - (utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true) + !includes(rule.vendorExceptions, currentModule) || + ( + includes(rule.vendorExceptions, currentModule) && + (utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true) + ) ) ) { isAllowed = true; diff --git a/test/spec/modules/gdprEnforcement_spec.js b/test/spec/modules/gdprEnforcement_spec.js index f0dc79e3f89..5b46441cbbb 100644 --- a/test/spec/modules/gdprEnforcement_spec.js +++ b/test/spec/modules/gdprEnforcement_spec.js @@ -150,7 +150,6 @@ describe('gdpr enforcement', function() { purpose: 'storage', enforcePurpose: true, enforceVendor: true, - vendorExceptions: [] }] } }); From e48fdf7ede1ecad559087d342957e5efd77e9c9c Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 31 Mar 2020 17:18:55 -0400 Subject: [PATCH 09/10] improving conditions --- modules/gdprEnforcement.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/modules/gdprEnforcement.js b/modules/gdprEnforcement.js index caefcaf0faa..363d0e396f8 100644 --- a/modules/gdprEnforcement.js +++ b/modules/gdprEnforcement.js @@ -59,12 +59,11 @@ function validateRules(rule, consentData, currentModule, gvlid) { } } else if (rule.enforcePurpose === false && rule.enforceVendor === false) { if ( + !includes(rule.vendorExceptions, currentModule) || ( - includes(rule.vendorExceptions, currentModule) && (utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true) && (utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true) - ) || - !includes(rule.vendorExceptions, currentModule) + ) ) { isAllowed = true; } @@ -73,10 +72,7 @@ function validateRules(rule, consentData, currentModule, gvlid) { (utils.deepAccess(consentData, 'vendorData.purpose.consents.1') === true) && ( !includes(rule.vendorExceptions, currentModule) || - ( - includes(rule.vendorExceptions, currentModule) && - (utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true) - ) + (utils.deepAccess(consentData, `vendorData.vendor.consents.${gvlid}`) === true) ) ) { isAllowed = true; From 74e38b7eaff8c47a1f1abf6aff8ddca7d0904f25 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Tue, 31 Mar 2020 18:34:00 -0400 Subject: [PATCH 10/10] Including changes for liveintent --- modules/liveIntentIdSystem.js | 4 +- src/storageManager.js | 43 +++++++++++++++++++- test/spec/modules/liveIntentIdSystem_spec.js | 7 +--- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/modules/liveIntentIdSystem.js b/modules/liveIntentIdSystem.js index c020e80d2c6..3f5d0602166 100644 --- a/modules/liveIntentIdSystem.js +++ b/modules/liveIntentIdSystem.js @@ -9,8 +9,10 @@ import { ajax } from '../src/ajax.js'; import { submodule } from '../src/hook.js'; import { LiveConnect } from 'live-connect-js/cjs/live-connect.js'; import { uspDataHandler } from '../src/adapterManager.js'; +import { getStorageManager } from '../src/storageManager.js'; const MODULE_NAME = 'liveIntentId'; +export const storage = getStorageManager(null, MODULE_NAME); let eventFired = false; let liveConnect = null; @@ -83,7 +85,7 @@ function initializeLiveConnect(configParams) { } // The second param is the storage object, which means that all LS & Cookie manipulation will go through PBJS utils. - liveConnect = LiveConnect(liveConnectConfig, utils); + liveConnect = LiveConnect(liveConnectConfig, storage); return liveConnect; } diff --git a/src/storageManager.js b/src/storageManager.js index a23ca63854d..abda0ccb180 100644 --- a/src/storageManager.js +++ b/src/storageManager.js @@ -62,7 +62,9 @@ export function newStorageManager({gvlid, moduleName, moduleType} = {}) { const setCookie = function (key, value, expires, sameSite, domain, done) { let cb = function (result) { if (result && result.valid) { - document.cookie = `${key}=${encodeURIComponent(value)}${(typeof expires !== 'undefined') ? `; expires=${expires}` : ''}; path=/${sameSite ? `; SameSite=${sameSite}` : ''}${domain ? `; domain=${domain}` : ''}`; + const domainPortion = (domain && domain !== '') ? ` ;domain=${encodeURIComponent(domain)}` : ''; + const expiresPortion = (expires && expires !== '') ? ` ;expires=${expires}` : ''; + document.cookie = `${key}=${encodeURIComponent(value)}${expiresPortion}; path=/${domainPortion}${sameSite ? `; SameSite=${sameSite}` : ''}`; } } if (done && typeof done === 'function') { @@ -228,6 +230,42 @@ export function newStorageManager({gvlid, moduleName, moduleType} = {}) { } } + /** + * Returns all cookie values from the jar whose names contain the `keyLike` + * Needs to exist in `utils.js` as it follows the StorageHandler interface defined in live-connect-js. If that module were to be removed, this function can go as well. + * @param {string} keyLike + * @return {[]} + */ + const findSimilarCookies = function(keyLike, done) { + let cb = function (result) { + if (result && result.valid) { + const all = []; + if (utils.hasDeviceAccess()) { + const cookies = document.cookie.split(';'); + while (cookies.length) { + const cookie = cookies.pop(); + let separatorIndex = cookie.indexOf('='); + separatorIndex = separatorIndex < 0 ? cookie.length : separatorIndex; + const cookieName = decodeURIComponent(cookie.slice(0, separatorIndex).replace(/^\s+/, '')); + if (cookieName.indexOf(keyLike) >= 0) { + all.push(decodeURIComponent(cookie.slice(separatorIndex + 1))); + } + } + } + return all; + } + } + + if (done && typeof done === 'function') { + storageCallbacks.push(function() { + let result = isValid(cb); + done(result); + }); + } else { + return isValid(cb); + } + } + return { setCookie, getCookie, @@ -236,7 +274,8 @@ export function newStorageManager({gvlid, moduleName, moduleType} = {}) { setDataInLocalStorage, getDataFromLocalStorage, removeDataFromLocalStorage, - hasLocalStorage + hasLocalStorage, + findSimilarCookies } } diff --git a/test/spec/modules/liveIntentIdSystem_spec.js b/test/spec/modules/liveIntentIdSystem_spec.js index eaf94aec8de..c3c9c8dc38d 100644 --- a/test/spec/modules/liveIntentIdSystem_spec.js +++ b/test/spec/modules/liveIntentIdSystem_spec.js @@ -1,16 +1,13 @@ -import {liveIntentIdSubmodule, reset as resetLiveIntentIdSubmodule} from 'modules/liveIntentIdSystem.js'; +import {liveIntentIdSubmodule, reset as resetLiveIntentIdSubmodule, storage} from 'modules/liveIntentIdSystem.js'; import * as utils from 'src/utils.js'; import {uspDataHandler} from '../../../src/adapterManager.js'; import {server} from 'test/mocks/xhr.js'; -import { getStorageManager } from 'src/storageManager.js'; - -const storage = getStorageManager(); const PUBLISHER_ID = '89899'; const defaultConfigParams = {publisherId: PUBLISHER_ID}; const responseHeader = {'Content-Type': 'application/json'} -describe.skip('LiveIntentId', function () { +describe('LiveIntentId', function () { let pixel = {}; let logErrorStub; let consentDataStub;