@duckduckgo/autoconsent 9.1.0 → 9.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,27 @@
1
+ # v9.2.1 (Fri Jan 26 2024)
2
+
3
+ #### 🐛 Bug Fix
4
+
5
+ - Handle absence of structuredClone() [#356](https://github.com/duckduckgo/autoconsent/pull/356) ([@muodov](https://github.com/muodov))
6
+
7
+ #### Authors: 1
8
+
9
+ - Maxim Tsoy ([@muodov](https://github.com/muodov))
10
+
11
+ ---
12
+
13
+ # v9.2.0 (Thu Jan 25 2024)
14
+
15
+ #### 🚀 Enhancement
16
+
17
+ - Handle popup right after first popup detected (#326) [#327](https://github.com/duckduckgo/autoconsent/pull/327) ([@seia-soto](https://github.com/seia-soto))
18
+
19
+ #### Authors: 1
20
+
21
+ - HoJeong Go ([@seia-soto](https://github.com/seia-soto))
22
+
23
+ ---
24
+
1
25
  # v9.1.0 (Thu Jan 11 2024)
2
26
 
3
27
  #### 🚀 Enhancement
@@ -161,6 +161,12 @@
161
161
  }
162
162
 
163
163
  // lib/utils.ts
164
+ function copyObject(data) {
165
+ if (globalThis.structuredClone) {
166
+ return structuredClone(data);
167
+ }
168
+ return JSON.parse(JSON.stringify(data));
169
+ }
164
170
  function normalizeConfig(providedConfig) {
165
171
  const defaultConfig = {
166
172
  enabled: true,
@@ -180,7 +186,7 @@
180
186
  messages: false
181
187
  }
182
188
  };
183
- const updatedConfig = structuredClone(defaultConfig);
189
+ const updatedConfig = copyObject(defaultConfig);
184
190
  for (const key of Object.keys(defaultConfig)) {
185
191
  if (typeof providedConfig[key] !== "undefined") {
186
192
  updatedConfig[key] = providedConfig[key];
@@ -951,6 +951,12 @@
951
951
  }
952
952
  return false;
953
953
  }
954
+ function copyObject(data) {
955
+ if (globalThis.structuredClone) {
956
+ return structuredClone(data);
957
+ }
958
+ return JSON.parse(JSON.stringify(data));
959
+ }
954
960
  function normalizeConfig(providedConfig) {
955
961
  const defaultConfig = {
956
962
  enabled: true,
@@ -970,7 +976,7 @@
970
976
  messages: false
971
977
  }
972
978
  };
973
- const updatedConfig = structuredClone(defaultConfig);
979
+ const updatedConfig = copyObject(defaultConfig);
974
980
  for (const key of Object.keys(defaultConfig)) {
975
981
  if (typeof providedConfig[key] !== "undefined") {
976
982
  updatedConfig[key] = providedConfig[key];
@@ -1989,9 +1995,23 @@
1989
1995
  return false;
1990
1996
  }
1991
1997
  this.updateState({ lifecycle: "cmpDetected" });
1992
- let foundPopups = await this.detectPopups(foundCmps.filter((r) => !r.isCosmetic));
1998
+ const staticCmps = [];
1999
+ const cosmeticCmps = [];
2000
+ for (const cmp of foundCmps) {
2001
+ if (cmp.isCosmetic) {
2002
+ cosmeticCmps.push(cmp);
2003
+ } else {
2004
+ staticCmps.push(cmp);
2005
+ }
2006
+ }
2007
+ let result = false;
2008
+ let foundPopups = await this.detectPopups(staticCmps, async (cmp) => {
2009
+ result = await this.handlePopup(cmp);
2010
+ });
1993
2011
  if (foundPopups.length === 0) {
1994
- foundPopups = await this.detectPopups(foundCmps.filter((r) => r.isCosmetic));
2012
+ foundPopups = await this.detectPopups(cosmeticCmps, async (cmp) => {
2013
+ result = await this.handlePopup(cmp);
2014
+ });
1995
2015
  }
1996
2016
  if (foundPopups.length === 0) {
1997
2017
  logsConfig.lifecycle && console.log("no popup found");
@@ -2000,10 +2020,6 @@
2000
2020
  }
2001
2021
  return false;
2002
2022
  }
2003
- this.updateState({ lifecycle: "openPopupDetected" });
2004
- if (this.config.enablePrehide && !this.state.prehideOn) {
2005
- this.prehideElements();
2006
- }
2007
2023
  if (foundPopups.length > 1) {
2008
2024
  const errorDetails = {
2009
2025
  msg: `Found multiple CMPs, check the detection rules.`,
@@ -2015,15 +2031,7 @@
2015
2031
  details: errorDetails
2016
2032
  });
2017
2033
  }
2018
- this.foundCmp = foundPopups[0];
2019
- if (this.config.autoAction === "optOut") {
2020
- return await this.doOptOut();
2021
- } else if (this.config.autoAction === "optIn") {
2022
- return await this.doOptIn();
2023
- } else {
2024
- logsConfig.lifecycle && console.log("waiting for opt-out signal...", location.href);
2025
- return true;
2026
- }
2034
+ return result;
2027
2035
  }
2028
2036
  async findCmp(retries) {
2029
2037
  const logsConfig = this.config.logs;
@@ -2054,25 +2062,51 @@
2054
2062
  }
2055
2063
  return foundCMPs;
2056
2064
  }
2057
- async detectPopups(cmps) {
2058
- const logsConfig = this.config.logs;
2059
- const result = [];
2060
- const popupLookups = cmps.map((cmp) => this.waitForPopup(cmp).then((isOpen) => {
2061
- if (isOpen) {
2062
- this.updateState({ detectedPopups: this.state.detectedPopups.concat([cmp.name]) });
2063
- this.sendContentMessage({
2064
- type: "popupFound",
2065
- cmp: cmp.name,
2066
- url: location.href
2067
- });
2068
- result.push(cmp);
2065
+ async detectPopup(cmp) {
2066
+ const isOpen = await this.waitForPopup(cmp);
2067
+ if (isOpen) {
2068
+ this.updateState({ detectedPopups: this.state.detectedPopups.concat([cmp.name]) });
2069
+ this.sendContentMessage({
2070
+ type: "popupFound",
2071
+ cmp: cmp.name,
2072
+ url: location.href
2073
+ });
2074
+ }
2075
+ return cmp;
2076
+ }
2077
+ async detectPopups(cmps, onFirstPopupAppears) {
2078
+ const tasks = cmps.map(
2079
+ (cmp) => this.detectPopup(cmp).catch((error) => {
2080
+ this.config.logs.errors && console.warn(`error waiting for a popup for ${cmp.name}`, error);
2081
+ throw error;
2082
+ })
2083
+ );
2084
+ await Promise.any(tasks).then((cmp) => {
2085
+ onFirstPopupAppears(cmp);
2086
+ }).catch(() => null);
2087
+ const results = await Promise.allSettled(tasks);
2088
+ const popups = [];
2089
+ for (const result of results) {
2090
+ if (result.status === "fulfilled") {
2091
+ popups.push(result.value);
2069
2092
  }
2070
- }).catch((e) => {
2071
- logsConfig.errors && console.warn(`error waiting for a popup for ${cmp.name}`, e);
2072
- return null;
2073
- }));
2074
- await Promise.all(popupLookups);
2075
- return result;
2093
+ }
2094
+ return popups;
2095
+ }
2096
+ async handlePopup(cmp) {
2097
+ this.updateState({ lifecycle: "openPopupDetected" });
2098
+ if (this.config.enablePrehide && !this.state.prehideOn) {
2099
+ this.prehideElements();
2100
+ }
2101
+ this.foundCmp = cmp;
2102
+ if (this.config.autoAction === "optOut") {
2103
+ return await this.doOptOut();
2104
+ } else if (this.config.autoAction === "optIn") {
2105
+ return await this.doOptIn();
2106
+ } else {
2107
+ this.config.logs.lifecycle && console.log("waiting for opt-out signal...", location.href);
2108
+ return true;
2109
+ }
2076
2110
  }
2077
2111
  async doOptOut() {
2078
2112
  const logsConfig = this.config.logs;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 2,
3
3
  "name": "Autoconsent",
4
- "version": "2024.1.11",
4
+ "version": "2024.1.25",
5
5
  "background": {
6
6
  "scripts": [
7
7
  "background.bundle.js"
@@ -161,6 +161,12 @@
161
161
  }
162
162
 
163
163
  // lib/utils.ts
164
+ function copyObject(data) {
165
+ if (globalThis.structuredClone) {
166
+ return structuredClone(data);
167
+ }
168
+ return JSON.parse(JSON.stringify(data));
169
+ }
164
170
  function normalizeConfig(providedConfig) {
165
171
  const defaultConfig = {
166
172
  enabled: true,
@@ -180,7 +186,7 @@
180
186
  messages: false
181
187
  }
182
188
  };
183
- const updatedConfig = structuredClone(defaultConfig);
189
+ const updatedConfig = copyObject(defaultConfig);
184
190
  for (const key of Object.keys(defaultConfig)) {
185
191
  if (typeof providedConfig[key] !== "undefined") {
186
192
  updatedConfig[key] = providedConfig[key];
@@ -951,6 +951,12 @@
951
951
  }
952
952
  return false;
953
953
  }
954
+ function copyObject(data) {
955
+ if (globalThis.structuredClone) {
956
+ return structuredClone(data);
957
+ }
958
+ return JSON.parse(JSON.stringify(data));
959
+ }
954
960
  function normalizeConfig(providedConfig) {
955
961
  const defaultConfig = {
956
962
  enabled: true,
@@ -970,7 +976,7 @@
970
976
  messages: false
971
977
  }
972
978
  };
973
- const updatedConfig = structuredClone(defaultConfig);
979
+ const updatedConfig = copyObject(defaultConfig);
974
980
  for (const key of Object.keys(defaultConfig)) {
975
981
  if (typeof providedConfig[key] !== "undefined") {
976
982
  updatedConfig[key] = providedConfig[key];
@@ -1989,9 +1995,23 @@
1989
1995
  return false;
1990
1996
  }
1991
1997
  this.updateState({ lifecycle: "cmpDetected" });
1992
- let foundPopups = await this.detectPopups(foundCmps.filter((r) => !r.isCosmetic));
1998
+ const staticCmps = [];
1999
+ const cosmeticCmps = [];
2000
+ for (const cmp of foundCmps) {
2001
+ if (cmp.isCosmetic) {
2002
+ cosmeticCmps.push(cmp);
2003
+ } else {
2004
+ staticCmps.push(cmp);
2005
+ }
2006
+ }
2007
+ let result = false;
2008
+ let foundPopups = await this.detectPopups(staticCmps, async (cmp) => {
2009
+ result = await this.handlePopup(cmp);
2010
+ });
1993
2011
  if (foundPopups.length === 0) {
1994
- foundPopups = await this.detectPopups(foundCmps.filter((r) => r.isCosmetic));
2012
+ foundPopups = await this.detectPopups(cosmeticCmps, async (cmp) => {
2013
+ result = await this.handlePopup(cmp);
2014
+ });
1995
2015
  }
1996
2016
  if (foundPopups.length === 0) {
1997
2017
  logsConfig.lifecycle && console.log("no popup found");
@@ -2000,10 +2020,6 @@
2000
2020
  }
2001
2021
  return false;
2002
2022
  }
2003
- this.updateState({ lifecycle: "openPopupDetected" });
2004
- if (this.config.enablePrehide && !this.state.prehideOn) {
2005
- this.prehideElements();
2006
- }
2007
2023
  if (foundPopups.length > 1) {
2008
2024
  const errorDetails = {
2009
2025
  msg: `Found multiple CMPs, check the detection rules.`,
@@ -2015,15 +2031,7 @@
2015
2031
  details: errorDetails
2016
2032
  });
2017
2033
  }
2018
- this.foundCmp = foundPopups[0];
2019
- if (this.config.autoAction === "optOut") {
2020
- return await this.doOptOut();
2021
- } else if (this.config.autoAction === "optIn") {
2022
- return await this.doOptIn();
2023
- } else {
2024
- logsConfig.lifecycle && console.log("waiting for opt-out signal...", location.href);
2025
- return true;
2026
- }
2034
+ return result;
2027
2035
  }
2028
2036
  async findCmp(retries) {
2029
2037
  const logsConfig = this.config.logs;
@@ -2054,25 +2062,51 @@
2054
2062
  }
2055
2063
  return foundCMPs;
2056
2064
  }
2057
- async detectPopups(cmps) {
2058
- const logsConfig = this.config.logs;
2059
- const result = [];
2060
- const popupLookups = cmps.map((cmp) => this.waitForPopup(cmp).then((isOpen) => {
2061
- if (isOpen) {
2062
- this.updateState({ detectedPopups: this.state.detectedPopups.concat([cmp.name]) });
2063
- this.sendContentMessage({
2064
- type: "popupFound",
2065
- cmp: cmp.name,
2066
- url: location.href
2067
- });
2068
- result.push(cmp);
2065
+ async detectPopup(cmp) {
2066
+ const isOpen = await this.waitForPopup(cmp);
2067
+ if (isOpen) {
2068
+ this.updateState({ detectedPopups: this.state.detectedPopups.concat([cmp.name]) });
2069
+ this.sendContentMessage({
2070
+ type: "popupFound",
2071
+ cmp: cmp.name,
2072
+ url: location.href
2073
+ });
2074
+ }
2075
+ return cmp;
2076
+ }
2077
+ async detectPopups(cmps, onFirstPopupAppears) {
2078
+ const tasks = cmps.map(
2079
+ (cmp) => this.detectPopup(cmp).catch((error) => {
2080
+ this.config.logs.errors && console.warn(`error waiting for a popup for ${cmp.name}`, error);
2081
+ throw error;
2082
+ })
2083
+ );
2084
+ await Promise.any(tasks).then((cmp) => {
2085
+ onFirstPopupAppears(cmp);
2086
+ }).catch(() => null);
2087
+ const results = await Promise.allSettled(tasks);
2088
+ const popups = [];
2089
+ for (const result of results) {
2090
+ if (result.status === "fulfilled") {
2091
+ popups.push(result.value);
2069
2092
  }
2070
- }).catch((e) => {
2071
- logsConfig.errors && console.warn(`error waiting for a popup for ${cmp.name}`, e);
2072
- return null;
2073
- }));
2074
- await Promise.all(popupLookups);
2075
- return result;
2093
+ }
2094
+ return popups;
2095
+ }
2096
+ async handlePopup(cmp) {
2097
+ this.updateState({ lifecycle: "openPopupDetected" });
2098
+ if (this.config.enablePrehide && !this.state.prehideOn) {
2099
+ this.prehideElements();
2100
+ }
2101
+ this.foundCmp = cmp;
2102
+ if (this.config.autoAction === "optOut") {
2103
+ return await this.doOptOut();
2104
+ } else if (this.config.autoAction === "optIn") {
2105
+ return await this.doOptIn();
2106
+ } else {
2107
+ this.config.logs.lifecycle && console.log("waiting for opt-out signal...", location.href);
2108
+ return true;
2109
+ }
2076
2110
  }
2077
2111
  async doOptOut() {
2078
2112
  const logsConfig = this.config.logs;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Autoconsent",
4
- "version": "2024.1.11",
4
+ "version": "2024.1.25",
5
5
  "background": {
6
6
  "service_worker": "background.bundle.js"
7
7
  },
@@ -30,6 +30,12 @@
30
30
  }
31
31
 
32
32
  // lib/utils.ts
33
+ function copyObject(data) {
34
+ if (globalThis.structuredClone) {
35
+ return structuredClone(data);
36
+ }
37
+ return JSON.parse(JSON.stringify(data));
38
+ }
33
39
  function normalizeConfig(providedConfig) {
34
40
  const defaultConfig = {
35
41
  enabled: true,
@@ -49,7 +55,7 @@
49
55
  messages: false
50
56
  }
51
57
  };
52
- const updatedConfig = structuredClone(defaultConfig);
58
+ const updatedConfig = copyObject(defaultConfig);
53
59
  for (const key of Object.keys(defaultConfig)) {
54
60
  if (typeof providedConfig[key] !== "undefined") {
55
61
  updatedConfig[key] = providedConfig[key];
@@ -974,6 +974,12 @@ function isElementVisible(elem) {
974
974
  }
975
975
  return false;
976
976
  }
977
+ function copyObject(data) {
978
+ if (globalThis.structuredClone) {
979
+ return structuredClone(data);
980
+ }
981
+ return JSON.parse(JSON.stringify(data));
982
+ }
977
983
  function normalizeConfig(providedConfig) {
978
984
  const defaultConfig = {
979
985
  enabled: true,
@@ -993,7 +999,7 @@ function normalizeConfig(providedConfig) {
993
999
  messages: false
994
1000
  }
995
1001
  };
996
- const updatedConfig = structuredClone(defaultConfig);
1002
+ const updatedConfig = copyObject(defaultConfig);
997
1003
  for (const key of Object.keys(defaultConfig)) {
998
1004
  if (typeof providedConfig[key] !== "undefined") {
999
1005
  updatedConfig[key] = providedConfig[key];
@@ -2012,9 +2018,23 @@ var AutoConsent = class {
2012
2018
  return false;
2013
2019
  }
2014
2020
  this.updateState({ lifecycle: "cmpDetected" });
2015
- let foundPopups = await this.detectPopups(foundCmps.filter((r) => !r.isCosmetic));
2021
+ const staticCmps = [];
2022
+ const cosmeticCmps = [];
2023
+ for (const cmp of foundCmps) {
2024
+ if (cmp.isCosmetic) {
2025
+ cosmeticCmps.push(cmp);
2026
+ } else {
2027
+ staticCmps.push(cmp);
2028
+ }
2029
+ }
2030
+ let result = false;
2031
+ let foundPopups = await this.detectPopups(staticCmps, async (cmp) => {
2032
+ result = await this.handlePopup(cmp);
2033
+ });
2016
2034
  if (foundPopups.length === 0) {
2017
- foundPopups = await this.detectPopups(foundCmps.filter((r) => r.isCosmetic));
2035
+ foundPopups = await this.detectPopups(cosmeticCmps, async (cmp) => {
2036
+ result = await this.handlePopup(cmp);
2037
+ });
2018
2038
  }
2019
2039
  if (foundPopups.length === 0) {
2020
2040
  logsConfig.lifecycle && console.log("no popup found");
@@ -2023,10 +2043,6 @@ var AutoConsent = class {
2023
2043
  }
2024
2044
  return false;
2025
2045
  }
2026
- this.updateState({ lifecycle: "openPopupDetected" });
2027
- if (this.config.enablePrehide && !this.state.prehideOn) {
2028
- this.prehideElements();
2029
- }
2030
2046
  if (foundPopups.length > 1) {
2031
2047
  const errorDetails = {
2032
2048
  msg: `Found multiple CMPs, check the detection rules.`,
@@ -2038,15 +2054,7 @@ var AutoConsent = class {
2038
2054
  details: errorDetails
2039
2055
  });
2040
2056
  }
2041
- this.foundCmp = foundPopups[0];
2042
- if (this.config.autoAction === "optOut") {
2043
- return await this.doOptOut();
2044
- } else if (this.config.autoAction === "optIn") {
2045
- return await this.doOptIn();
2046
- } else {
2047
- logsConfig.lifecycle && console.log("waiting for opt-out signal...", location.href);
2048
- return true;
2049
- }
2057
+ return result;
2050
2058
  }
2051
2059
  async findCmp(retries) {
2052
2060
  const logsConfig = this.config.logs;
@@ -2077,25 +2085,51 @@ var AutoConsent = class {
2077
2085
  }
2078
2086
  return foundCMPs;
2079
2087
  }
2080
- async detectPopups(cmps) {
2081
- const logsConfig = this.config.logs;
2082
- const result = [];
2083
- const popupLookups = cmps.map((cmp) => this.waitForPopup(cmp).then((isOpen) => {
2084
- if (isOpen) {
2085
- this.updateState({ detectedPopups: this.state.detectedPopups.concat([cmp.name]) });
2086
- this.sendContentMessage({
2087
- type: "popupFound",
2088
- cmp: cmp.name,
2089
- url: location.href
2090
- });
2091
- result.push(cmp);
2088
+ async detectPopup(cmp) {
2089
+ const isOpen = await this.waitForPopup(cmp);
2090
+ if (isOpen) {
2091
+ this.updateState({ detectedPopups: this.state.detectedPopups.concat([cmp.name]) });
2092
+ this.sendContentMessage({
2093
+ type: "popupFound",
2094
+ cmp: cmp.name,
2095
+ url: location.href
2096
+ });
2097
+ }
2098
+ return cmp;
2099
+ }
2100
+ async detectPopups(cmps, onFirstPopupAppears) {
2101
+ const tasks = cmps.map(
2102
+ (cmp) => this.detectPopup(cmp).catch((error) => {
2103
+ this.config.logs.errors && console.warn(`error waiting for a popup for ${cmp.name}`, error);
2104
+ throw error;
2105
+ })
2106
+ );
2107
+ await Promise.any(tasks).then((cmp) => {
2108
+ onFirstPopupAppears(cmp);
2109
+ }).catch(() => null);
2110
+ const results = await Promise.allSettled(tasks);
2111
+ const popups = [];
2112
+ for (const result of results) {
2113
+ if (result.status === "fulfilled") {
2114
+ popups.push(result.value);
2092
2115
  }
2093
- }).catch((e) => {
2094
- logsConfig.errors && console.warn(`error waiting for a popup for ${cmp.name}`, e);
2095
- return null;
2096
- }));
2097
- await Promise.all(popupLookups);
2098
- return result;
2116
+ }
2117
+ return popups;
2118
+ }
2119
+ async handlePopup(cmp) {
2120
+ this.updateState({ lifecycle: "openPopupDetected" });
2121
+ if (this.config.enablePrehide && !this.state.prehideOn) {
2122
+ this.prehideElements();
2123
+ }
2124
+ this.foundCmp = cmp;
2125
+ if (this.config.autoAction === "optOut") {
2126
+ return await this.doOptOut();
2127
+ } else if (this.config.autoAction === "optIn") {
2128
+ return await this.doOptIn();
2129
+ } else {
2130
+ this.config.logs.lifecycle && console.log("waiting for opt-out signal...", location.href);
2131
+ return true;
2132
+ }
2099
2133
  }
2100
2134
  async doOptOut() {
2101
2135
  const logsConfig = this.config.logs;