-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathutils.es6.js
More file actions
323 lines (288 loc) · 8.61 KB
/
utils.es6.js
File metadata and controls
323 lines (288 loc) · 8.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import MozAllowList from './allow-list.es6';
import DownloadAttribution from '../download-attribution/download-attribution.es6';
const COOKIE_ID = 'moz-consent-pref'; // Cookie name
const COOKIE_EXPIRY_DAYS = 182; // 6 months expiry
/**
* Sets GTAG ads consent mode
* @param {Boolean} hasConsent - if analytics pref is true or false
* @param {String} type - one of consent mode types (default|update)
* @returns {Boolean}
*/
function setGtagAdsConsentMode(hasConsent, type = 'update') {
// bail out if GTAG has not been created with GTMSnippet.loadSnippet
// this needs to run before GTM snippet loads to set proper defaults
if (typeof window.gtag === 'undefined') {
return false;
}
if (hasConsent) {
window.gtag('consent', type, {
ad_user_data: 'granted',
ad_personalization: 'granted',
ad_storage: 'granted'
});
} else {
window.gtag('consent', type, {
ad_user_data: 'denied',
ad_personalization: 'denied',
ad_storage: 'denied'
});
}
return true;
}
/**
* Sets GTAG analytics consent mode
* @param {Boolean} hasConsent - based on promoted page default or analytics cookie
* @param {String} type - one of consent mode types (default|update)
* @returns {Boolean}
*/
function setGtagAnalyticsConsentMode(hasConsent, type = 'update') {
// This is a failsafe to ensure we always remove analytics download attribution
// when consent status is denied (regardless of whether or not we are on page with
// a consent banner, i.e. the cookie policy page)
//
// This failsafe is only necessary as long as GTM is conditionally loaded
// Once it is always loaded, we can rely on GTM consent mode status
if (!hasConsent) {
DownloadAttribution.initAnalytics(false);
}
// bail out if GTAG has not been created with GTMSnippet.loadSnippet
// this needs to run before GTM snippet loads to set proper defaults
if (typeof window.gtag === 'undefined') {
return false;
}
if (hasConsent) {
window.gtag('consent', type, {
analytics_storage: 'granted'
});
// We only apply analytics information if GTAG is available
DownloadAttribution.initAnalytics(true);
} else {
window.gtag('consent', type, {
analytics_storage: 'denied'
});
}
return true;
}
/**
* Determines if the current page requires consent.
* Looks for a data attribute on the <html> tag.
*/
function consentRequired() {
const attr = document
.getElementsByTagName('html')[0]
.getAttribute('data-needs-consent');
return attr ? attr.toLowerCase() === 'true' : false;
}
/**
* Determines if Do Not Track is enabled.
* @returns {Boolean}
*/
function dntEnabled() {
return (
typeof window.Mozilla.dntEnabled === 'function' &&
window.Mozilla.dntEnabled()
);
}
/**
* Determines the hostname to set the consent cookie on.
* Typically, this is either .mozilla.org or .allizom.org.
* But otherwise, it returns null so the cookie will apply
* to the current domain.
* @param {String} hostname - The hostname of the current page.
* @returns {String|null} - Returns the domain or null.
*/
function getHostName(hostname) {
let domain = null;
if (typeof hostname !== 'string') {
return domain;
}
if (hostname.indexOf('.allizom.org') !== -1) {
domain = '.allizom.org';
}
if (hostname.indexOf('.mozilla.org') !== -1) {
domain = '.mozilla.org';
}
return domain;
}
/**
* Determines if the consent cookie exists.
* @returns {Boolean}
*/
function hasConsentCookie() {
return (
window.Mozilla.Cookies.enabled() &&
window.Mozilla.Cookies.hasItem(COOKIE_ID)
);
}
/**
* Gets the consent cookie object.
* @returns {Object|Boolean} - Returns the consent cookie object or false.
*/
function getConsentCookie() {
try {
return JSON.parse(window.Mozilla.Cookies.getItem(COOKIE_ID));
} catch (e) {
return false;
}
}
/**
* Sets consent cookie with data provided.
* @param {Object} data - Object containing consent data.
* @returns {Boolean}
*/
function setConsentCookie(data) {
try {
if (typeof data !== 'object') {
return false;
}
const date = new Date();
date.setDate(date.getDate() + COOKIE_EXPIRY_DAYS);
const expires = date.toUTCString();
window.Mozilla.Cookies.setItem(
COOKIE_ID,
JSON.stringify(data),
expires,
'/',
getHostName(window.location.hostname),
false,
'lax'
);
setGtagAdsConsentMode(data.analytics);
setGtagAnalyticsConsentMode(data.analytics);
return true;
} catch (e) {
return false;
}
}
/**
* Determines if Global Privacy Control is enabled.
* @returns {Boolean}
*/
function gpcEnabled() {
return (
typeof window.Mozilla.gpcEnabled === 'function' &&
window.Mozilla.gpcEnabled()
);
}
/**
* Determine if the current page is /thanks/.
* @param {String} location - The current page URL.
* @return {Boolean}.
*/
function isFirefoxDownloadThanks(location) {
if (typeof location !== 'string') {
return false;
}
return location.indexOf('/thanks/') > -1;
}
/**
* Determine if the current page is a promoted landing page.
* Checks for the `data-promoted-page` attribute on the <html> element.
* @return {Boolean}.
*/
function isPromotedPage() {
const attr = document.documentElement.getAttribute('data-promoted-page');
return attr ? attr.toLowerCase() === 'true' : false;
}
/**
* Determines if the current page URL contains a query string
* that allows the consent banner to be displayed.
* @param {String} search - The current page URL search string.
* @returns {Boolean}
*/
function isURLExceptionAllowed(search) {
if (typeof search !== 'string') {
return false;
}
return search.indexOf('mozcb=y') > -1;
}
/**
* Takes a given path name and checks it against the allow-list for
* displaying the consent banner.
* @param {String} pathname
* @returns {Boolean}
*/
function isURLPermitted(pathname) {
// Promoted pages are always permitted for the consent banner.
if (isPromotedPage()) {
return true;
}
let currentPath = pathname;
// Remove locale from current URL pathname;
currentPath = currentPath.replace(/^(\/\w{2}-\w{2}\/|\/\w{2,3}\/)/, '/');
for (let i = 0; i < MozAllowList.length; i++) {
// Turn allowlist path into a regex, supporting wildcards.
const pathRegex = new RegExp(
'^' + MozAllowList[i].replace(/\*/g, '.*') + '$'
);
if (pathRegex.test(currentPath)) {
return true;
}
}
return false;
}
/**
* A very primitive state machine to determine if a consent
* banner needs to be displayed or if analytics can be loaded.
* @param {Object} obj - Object containing consent state flags.
* @returns {String} Consent state message.
*/
function getConsentState(obj) {
/**
* If GPC or DNT is enabled, there's no need to show
* a banner or load analytics since we take that signal
* as a rejection to non-essential cookies and analytics.
*/
if (obj.gpcEnabled) {
return 'STATE_GPC_ENABLED';
}
if (obj.dntEnabled) {
return 'STATE_DNT_ENABLED';
}
/**
* If the visitor is in the EU, and page is on the allow-list,
* then show the cookie banner.
*/
if (obj.consentRequired) {
if (obj.isURLPermitted || obj.isURLExceptionAllowed) {
if (obj.hasConsentCookie) {
return 'STATE_HAS_CONSENT_COOKIE';
} else {
return 'STATE_SHOW_COOKIE_BANNER';
}
} else {
return 'STATE_BANNER_NOT_PERMITTED';
}
} else {
/**
* For remaining users outside of EU,
* load analytics by default.
*/
if (obj.hasConsentCookie) {
return 'STATE_HAS_CONSENT_COOKIE';
} else {
return 'STATE_COOKIES_PERMITTED';
}
}
}
export {
consentRequired,
dntEnabled,
getConsentCookie,
getConsentState,
getHostName,
gpcEnabled,
hasConsentCookie,
isFirefoxDownloadThanks,
isPromotedPage,
isURLExceptionAllowed,
isURLPermitted,
setConsentCookie,
setGtagAdsConsentMode,
setGtagAnalyticsConsentMode
};