noibu-react-native 0.0.3 → 0.0.6

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.
@@ -1,10 +1,9 @@
1
1
  import uuid from 'react-native-uuid';
2
- import { MAX_METROPLEX_SOCKET_INNACTIVE_TIME, DISABLED_STATUS_KEY, CLIENT_UNLOCK_TIME_KEY, SEVERITY_WARN, LAST_ACTIVE_TIME_KEY, CURRENT_PAGE_VISIT_COUNT_KEY, NOIBU_BROWSER_ID_KYWRD, BROWSER_ID_KEY, PV_SEQ_NUM_RESET_TIME_MINUTES, SEVERITY_ERROR, JS_ENV, PAGE_VISIT_ID_KEY, MAX_PAGEVISIT_VISITED, CLIENT_LOCK_TIME_MINUTES, GET_SCRIPT_ID, MAX_COLLECT_ERROR_LOG } from '../constants.js';
2
+ import { MAX_METROPLEX_SOCKET_INNACTIVE_TIME, SEVERITY, NOIBU_BROWSER_ID_KYWRD, PV_SEQ_NUM_RESET_TIME_MINUTES, JS_ENV, MAX_PAGEVISIT_VISITED, CLIENT_LOCK_TIME_MINUTES, GET_SCRIPT_ID, MAX_COLLECT_ERROR_LOG } from '../constants.js';
3
3
  import { stringifyJSON, getUserAgent, asString, getProperGlobalUrl, makeRequest } from '../utils/function.js';
4
4
  import Storage from '../storage/storage.js';
5
5
 
6
6
  /** @module ClientConfig */
7
-
8
7
  /**
9
8
  * Singleton class to manage the client configuration
10
9
  * this class will be responsible for controlling the disabled
@@ -12,407 +11,336 @@ import Storage from '../storage/storage.js';
12
11
  * storing and retrieval.
13
12
  */
14
13
  class ClientConfig {
15
- /**
16
- * Creates a ClientConfig singleton instance
17
- * @param {string} noibuErrorURL
18
- * @param {string} customerDomain
19
- */
20
- constructor(noibuErrorURL, customerDomain) {
21
- // sets up this.browserId, this.disabledStatus
22
- this.pageVisitId = uuid.v4();
23
- // variables stored in storage
24
- this.isClientDisabled = null;
25
- this.browserId = null;
26
- this.pageVisitSeq = null;
27
- // This variable tracks the last time the user was active in this session.
28
- // It is also written to storage. Initialized to now so the session can be
29
- // timed out even if a PV is never sent.
30
- this.lastActiveTime = new Date();
31
- // error URL to send Noibu errors to
32
- this.noibuErrorURL = noibuErrorURL;
33
- // sets up this.browserId, this.isClientDisabled, this.pageVisitSeq
34
- this._setupStorageVars();
35
- // error sent to backend counter
36
- this.cltErrorPostCounter = 0;
37
- // variables for checking if the socket is inactive
38
- // used a class variables in order to be changed in testing
39
- this.maxSocketInactiveTime = MAX_METROPLEX_SOCKET_INNACTIVE_TIME;
40
-
41
- this.customerDomain = customerDomain;
42
- }
43
-
44
- /** Configures the singleton instance */
45
- static configureInstance({ noibuErrorURL, customerDomain }) {
46
- if (!this.instance) {
47
- // Set this.noibuErrorURL preemptively in case ClientConfig isn't able to be
48
- // configured properly and throws an error.
49
- // This will ensure we get the expected error POST request at the correct URL.
50
- this.noibuErrorURL = noibuErrorURL;
51
- this.instance = new ClientConfig(noibuErrorURL, customerDomain);
52
- this.instance.noibuErrorURL = noibuErrorURL;
14
+ pageVisitId;
15
+ browserId;
16
+ pageVisitSeq;
17
+ lastActiveTime;
18
+ noibuErrorURL;
19
+ cltErrorPostCounter;
20
+ maxSocketInactiveTime;
21
+ static instance;
22
+ static noibuErrorURL;
23
+ customerDomain;
24
+ isClientDisabled;
25
+ listOfUrlsToCollectHttpDataFrom;
26
+ enableHttpDataCollection;
27
+ blockedElements;
28
+ /**
29
+ * Creates a ClientConfig singleton instance
30
+ */
31
+ constructor(noibuErrorURL, customerConfig) {
32
+ // sets up this.browserId, this.disabledStatus
33
+ this.pageVisitId = uuid.v4();
34
+ // variables stored in storage
35
+ this.isClientDisabled = false;
36
+ this.browserId = '';
37
+ this.pageVisitSeq = null;
38
+ // This variable tracks the last time the user was active in this session.
39
+ // It is also written to storage. Initialized to now so the session can be
40
+ // timed out even if a PV is never sent.
41
+ this.lastActiveTime = new Date();
42
+ // error URL to send Noibu errors to
43
+ this.noibuErrorURL = noibuErrorURL;
44
+ // sets up this.browserId, this.isClientDisabled, this.pageVisitSeq
45
+ this._setupStorageVars();
46
+ // error sent to backend counter
47
+ this.cltErrorPostCounter = 0;
48
+ // variables for checking if the socket is inactive
49
+ // used a class variables in order to be changed in testing
50
+ this.maxSocketInactiveTime = MAX_METROPLEX_SOCKET_INNACTIVE_TIME;
51
+ this.customerDomain = customerConfig.domain;
52
+ this.listOfUrlsToCollectHttpDataFrom =
53
+ customerConfig.listOfUrlsToCollectHttpDataFrom;
54
+ this.enableHttpDataCollection = customerConfig.enableHttpDataCollection;
55
+ this.blockedElements = customerConfig.blockedElements;
53
56
  }
54
- }
55
-
56
- /**
57
- * gets the singleton instance
58
- * @returns {ClientConfig}
59
- */
60
- static getInstance() {
61
- if (!this.instance) {
62
- throw new Error('ClientConfig was not configured');
57
+ /** Configures the singleton instance */
58
+ static configureInstance({ noibuErrorURL, customerConfig, }) {
59
+ if (!this.instance) {
60
+ // Set this.noibuErrorURL preemptively in case ClientConfig isn't able to be
61
+ // configured properly and throws an error.
62
+ // This will ensure we get the expected error POST request at the correct URL.
63
+ this.noibuErrorURL = noibuErrorURL;
64
+ this.instance = new ClientConfig(noibuErrorURL, customerConfig);
65
+ this.instance.noibuErrorURL = noibuErrorURL;
66
+ }
63
67
  }
64
-
65
- return this.instance;
66
- }
67
-
68
- /** lockClient will disable the client script for a single pagevisit for
69
- * duration given in minuntes */
70
- async lockClient(duration, msg) {
71
- const expiryTime = new Date();
72
- expiryTime.setMinutes(expiryTime.getMinutes() + duration);
73
-
74
- const noibuLSObject = await this._getClientState();
75
- noibuLSObject[DISABLED_STATUS_KEY] = true;
76
- noibuLSObject[CLIENT_UNLOCK_TIME_KEY] = expiryTime;
77
- await this._storeBrowserData(noibuLSObject);
78
- this.postNoibuErrorAndOptionallyDisableClient(msg, true, SEVERITY_WARN);
79
- }
80
-
81
- /** Locks the client until the next page loads */
82
- lockClientUntilNextPage(msg) {
83
- this.postNoibuErrorAndOptionallyDisableClient(msg, true, SEVERITY_WARN);
84
- }
85
-
86
- /** Updates the config object to store the given last active time */
87
- async updateLastActiveTime(lastActiveTime) {
88
- this.lastActiveTime = lastActiveTime;
89
- const newConfigData = await this._getLsObject();
90
- newConfigData[LAST_ACTIVE_TIME_KEY] = lastActiveTime;
91
- await this._storeBrowserData(newConfigData);
92
- }
93
-
94
- /** Gets the current page visit sequence number that should be used */
95
- async getPageVisitSeq() {
96
- if (await this._pageVisitSeqNeedsReset()) {
97
- // Reset the page visit sequence number to zero and store the next seq number in storage
98
- this.pageVisitSeq = 0;
99
- const newConfigData = await this._getLsObject();
100
- newConfigData[CURRENT_PAGE_VISIT_COUNT_KEY] = this.pageVisitSeq + 1;
101
- // Update the last active time since we are actively requesting the seq
102
- newConfigData[LAST_ACTIVE_TIME_KEY] = new Date();
103
- await this._storeBrowserData(newConfigData);
68
+ /**
69
+ * gets the singleton instance
70
+ * @returns {ClientConfig}
71
+ */
72
+ static getInstance() {
73
+ if (!this.instance) {
74
+ throw new Error('ClientConfig was not configured');
75
+ }
76
+ return this.instance;
104
77
  }
105
-
106
- return this.pageVisitSeq;
107
- }
108
-
109
- /**
110
- * Returns the client config object from storage or generates a new one
111
- * What is stored in storage will look like this
112
- * {
113
- * BrowserId: UUIDV4
114
- * ExpiryTime: DATE OBJ
115
- * DisabledStatus: BOOL
116
- * CurrentPageVisitCount: INT
117
- * ClientUnlockTime: DATE OBJ
118
- * LastActiveTime: DATE OBJ
119
- * }
120
- */
121
- async _getLsObject() {
122
- const storage = Storage.getInstance();
123
- const storedConfig = await storage.load(NOIBU_BROWSER_ID_KYWRD);
124
-
125
- // first time browsing since noibu was installed
126
- if (!storedConfig) {
127
- return this._generateAndStoreData();
78
+ /** lockClient will disable the client script for a single pagevisit for
79
+ * duration given in minuntes */
80
+ async lockClient(duration, msg) {
81
+ const expiryTime = new Date();
82
+ expiryTime.setMinutes(expiryTime.getMinutes() + duration);
83
+ const noibuLSObject = await this._getClientState();
84
+ noibuLSObject.DisabledStatus = true;
85
+ noibuLSObject.ClientUnlockTime = expiryTime;
86
+ await this._storeBrowserData(noibuLSObject);
87
+ this.postNoibuErrorAndOptionallyDisableClient(msg, true, SEVERITY.warn);
128
88
  }
129
-
130
- let parsedConfig = {};
131
-
132
- try {
133
- parsedConfig = JSON.parse(storedConfig);
134
- } catch (e) {
135
- return this._generateAndStoreData();
89
+ /** Locks the client until the next page loads */
90
+ lockClientUntilNextPage(msg) {
91
+ this.postNoibuErrorAndOptionallyDisableClient(msg, true, SEVERITY.warn);
136
92
  }
137
-
138
- // checking if it's a valid object. The CLIENT_UNLOCK_TIME_KEY doesn't have to exist
139
- // since it's not written to the storage object when set to null.
140
- if (
141
- parsedConfig[BROWSER_ID_KEY] == null ||
142
- parsedConfig[DISABLED_STATUS_KEY] == null ||
143
- parsedConfig[CURRENT_PAGE_VISIT_COUNT_KEY] == null ||
144
- parsedConfig[LAST_ACTIVE_TIME_KEY] == null
145
- ) {
146
- return this._generateAndStoreData();
93
+ /** Updates the config object to store the given last active time */
94
+ async updateLastActiveTime(lastActiveTime) {
95
+ this.lastActiveTime = lastActiveTime;
96
+ const newConfigData = await this._getLsObject();
97
+ newConfigData.LastActive = lastActiveTime;
98
+ await this._storeBrowserData(newConfigData);
147
99
  }
148
- return parsedConfig;
149
- }
150
-
151
- /**
152
- * Check if we have surpased the last active time and the page visit seq number needs resetting
153
- */
154
- async _pageVisitSeqNeedsReset() {
155
- const noibuLSObject = await this._getClientState();
156
- const someTimeAgo = new Date();
157
- someTimeAgo.setMinutes(
158
- someTimeAgo.getMinutes() - PV_SEQ_NUM_RESET_TIME_MINUTES,
159
- );
160
- return new Date(noibuLSObject[LAST_ACTIVE_TIME_KEY]) < someTimeAgo;
161
- }
162
-
163
- /**
164
- * _setupStorageVars will set all class variables that depend
165
- * on the storage's value.
166
- */
167
- async _setupStorageVars() {
168
- const storage = Storage.getInstance();
169
- if (!(await storage.isAvailable())) {
170
- this.postNoibuErrorAndOptionallyDisableClient(
171
- `Storage is unavailable, disabling client. ${await storage.getDiagnoseInfo()}`,
172
- true,
173
- SEVERITY_ERROR,
174
- );
175
- return;
100
+ /** Gets the current page visit sequence number that should be used */
101
+ async getPageVisitSeq() {
102
+ if (await this._pageVisitSeqNeedsReset()) {
103
+ // Reset the page visit sequence number to zero and store the next seq number in storage
104
+ this.pageVisitSeq = 0;
105
+ const newConfigData = await this._getLsObject();
106
+ newConfigData.CurrentPageVisitCount = this.pageVisitSeq + 1;
107
+ // Update the last active time since we are actively requesting the seq
108
+ newConfigData.LastActive = new Date();
109
+ await this._storeBrowserData(newConfigData);
110
+ }
111
+ return this.pageVisitSeq;
176
112
  }
177
-
178
- // getting the current content of the storage
179
- const noibuLSObject = await this._getClientState();
180
-
181
- // Check if we have surpased the last active time and reset the sequence number if so
182
- if (await this._pageVisitSeqNeedsReset()) {
183
- noibuLSObject[CURRENT_PAGE_VISIT_COUNT_KEY] = 0;
113
+ /**
114
+ * Returns the client config object from storage or generates a new one
115
+ * What is stored in storage will look like this
116
+ * {
117
+ * BrowserId: UUIDV4
118
+ * ExpiryTime: DATE OBJ
119
+ * DisabledStatus: BOOL
120
+ * CurrentPageVisitCount: INT
121
+ * ClientUnlockTime: DATE OBJ
122
+ * LastActiveTime: DATE OBJ
123
+ * }
124
+ */
125
+ async _getLsObject() {
126
+ const storage = Storage.getInstance();
127
+ const storedConfig = await storage.load(NOIBU_BROWSER_ID_KYWRD);
128
+ // first time browsing since noibu was installed
129
+ if (!storedConfig) {
130
+ return this._generateAndStoreData();
131
+ }
132
+ let parsedConfig = {};
133
+ try {
134
+ parsedConfig = JSON.parse(storedConfig);
135
+ }
136
+ catch (e) {
137
+ return this._generateAndStoreData();
138
+ }
139
+ // checking if it's a valid object. The CLIENT_UNLOCK_TIME_KEY doesn't have to exist
140
+ // since it's not written to the storage object when set to null.
141
+ if (!(parsedConfig.BrowserId &&
142
+ Boolean(parsedConfig.DisabledStatus) === parsedConfig.DisabledStatus &&
143
+ parsedConfig.CurrentPageVisitCount &&
144
+ parsedConfig.LastActive)) {
145
+ return this._generateAndStoreData();
146
+ }
147
+ return parsedConfig;
184
148
  }
185
-
186
- this.browserId = noibuLSObject[BROWSER_ID_KEY];
187
- this.pageVisitSeq = noibuLSObject[CURRENT_PAGE_VISIT_COUNT_KEY];
188
- this.isClientDisabled = noibuLSObject[DISABLED_STATUS_KEY];
189
-
190
- // If the client has been disabled just return.
191
- // Calling _getClientState() above performs the disabled expirey check
192
- if (this.isClientDisabled) return;
193
-
194
- // Update the LS object values before storing it for the next page visit
195
- noibuLSObject[CURRENT_PAGE_VISIT_COUNT_KEY] += 1;
196
- noibuLSObject[LAST_ACTIVE_TIME_KEY] = new Date();
197
-
198
- // Expose page visit ID in storage for use by Trailbreaker video tests
199
- // This will be done for the testvideo and lambdavideo bundles used by Trailbreaker
200
- if (JS_ENV().includes('video')) {
201
- noibuLSObject[PAGE_VISIT_ID_KEY] = this.pageVisitId;
149
+ /**
150
+ * Check if we have surpassed the last active time and the page visit seq number needs resetting
151
+ */
152
+ async _pageVisitSeqNeedsReset() {
153
+ const noibuLSObject = await this._getClientState();
154
+ const someTimeAgo = new Date();
155
+ someTimeAgo.setMinutes(someTimeAgo.getMinutes() - PV_SEQ_NUM_RESET_TIME_MINUTES);
156
+ if (!noibuLSObject.LastActive) {
157
+ return true;
158
+ }
159
+ return new Date(noibuLSObject.LastActive) < someTimeAgo;
202
160
  }
203
-
204
- // if we have reached the max page visits for a browser id then
205
- // we disabled collect for 45 minutes
206
- if (noibuLSObject[CURRENT_PAGE_VISIT_COUNT_KEY] >= MAX_PAGEVISIT_VISITED) {
207
- // if we bust the max pagevisit visited limit we lock the client for 45 minutes
208
- // since its probably a bot.
209
- const expiryTime = new Date();
210
- expiryTime.setMinutes(expiryTime.getMinutes() + CLIENT_LOCK_TIME_MINUTES);
211
- // setting the lock time
212
- noibuLSObject[CLIENT_UNLOCK_TIME_KEY] = expiryTime;
213
- noibuLSObject[DISABLED_STATUS_KEY] = true;
214
- this.postNoibuErrorAndOptionallyDisableClient(
215
- `Hit max page visits, disabling client for ${CLIENT_LOCK_TIME_MINUTES}mins`,
216
- true,
217
- SEVERITY_ERROR,
218
- );
219
- }
220
-
221
- // we now check if we successfully saved the data
222
- const savedData = await this._storeBrowserData(noibuLSObject);
223
-
224
- // if the browser is null, we cannot access the storage or an
225
- // error happened, thus we disable collect.
226
- if (savedData[BROWSER_ID_KEY] === null) {
227
- // we do not set a lock expiry date here since we cannot store to storage
228
- this.postNoibuErrorAndOptionallyDisableClient(
229
- `Null browser in storage, disabling client`,
230
- true,
231
- SEVERITY_ERROR,
232
- );
233
- this.browserId = null;
161
+ /**
162
+ * _setupStorageVars will set all class variables that depend
163
+ * on the storage's value.
164
+ */
165
+ async _setupStorageVars() {
166
+ const storage = Storage.getInstance();
167
+ if (!(await storage.isAvailable())) {
168
+ this.postNoibuErrorAndOptionallyDisableClient(`Storage is unavailable, disabling client. ${await storage.getDiagnoseInfo()}`, true, SEVERITY.error);
169
+ return;
170
+ }
171
+ // getting the current content of the storage
172
+ const noibuLSObject = await this._getClientState();
173
+ // Check if we have surpased the last active time and reset the sequence number if so
174
+ if (await this._pageVisitSeqNeedsReset()) {
175
+ noibuLSObject.CurrentPageVisitCount = 0;
176
+ }
177
+ this.browserId = noibuLSObject.BrowserId;
178
+ this.pageVisitSeq = noibuLSObject.CurrentPageVisitCount;
179
+ this.isClientDisabled = noibuLSObject.DisabledStatus;
180
+ // If the client has been disabled just return.
181
+ // Calling _getClientState() above performs the disabled expirey check
182
+ if (this.isClientDisabled)
183
+ return;
184
+ // Update the LS object values before storing it for the next page visit
185
+ noibuLSObject.CurrentPageVisitCount += 1;
186
+ noibuLSObject.LastActive = new Date();
187
+ // Expose page visit ID in storage for use by Trailbreaker video tests
188
+ // This will be done for the testvideo and lambdavideo bundles used by Trailbreaker
189
+ if (JS_ENV().includes('video')) {
190
+ noibuLSObject.pvId = this.pageVisitId;
191
+ }
192
+ // if we have reached the max page visits for a browser id then
193
+ // we disabled collect for 45 minutes
194
+ if (noibuLSObject.CurrentPageVisitCount >= MAX_PAGEVISIT_VISITED) {
195
+ // if we bust the max pagevisit visited limit we lock the client for 45 minutes
196
+ // since its probably a bot.
197
+ const expiryTime = new Date();
198
+ expiryTime.setMinutes(expiryTime.getMinutes() + CLIENT_LOCK_TIME_MINUTES);
199
+ // setting the lock time
200
+ noibuLSObject.ClientUnlockTime = expiryTime;
201
+ noibuLSObject.DisabledStatus = true;
202
+ this.postNoibuErrorAndOptionallyDisableClient(`Hit max page visits, disabling client for ${CLIENT_LOCK_TIME_MINUTES}mins`, true, SEVERITY.error);
203
+ }
204
+ // we now check if we successfully saved the data
205
+ const savedData = await this._storeBrowserData(noibuLSObject);
206
+ // if the browser is null, we cannot access the storage or an
207
+ // error happened, thus we disable collect.
208
+ if (!savedData.BrowserId) {
209
+ // we do not set a lock expiry date here since we cannot store to storage
210
+ this.postNoibuErrorAndOptionallyDisableClient(`Null browser in storage, disabling client`, true, SEVERITY.error);
211
+ this.browserId = '';
212
+ }
234
213
  }
235
- }
236
-
237
- /**
238
- * Function will get the Noibu Storage Object
239
- * 1. Generate a brand new one
240
- * Get it from storage if the expiry date is not in the past
241
- * Generate a brand new one if the expiry date is in the past
242
- */
243
- async _getClientState() {
244
- const newConfigData = await this._getLsObject();
245
-
246
- // if the lock expired, we remove the lock period and enable the client
247
- if (
248
- newConfigData[CLIENT_UNLOCK_TIME_KEY] &&
249
- new Date(newConfigData[CLIENT_UNLOCK_TIME_KEY]) <= new Date()
250
- ) {
251
- newConfigData[CLIENT_UNLOCK_TIME_KEY] = null;
252
- newConfigData[DISABLED_STATUS_KEY] = false;
253
- await this._storeBrowserData(newConfigData);
214
+ /**
215
+ * Function will get the Noibu Storage Object
216
+ * 1. Generate a brand new one
217
+ * Get it from storage if the expiry date is not in the past
218
+ * Generate a brand new one if the expiry date is in the past
219
+ */
220
+ async _getClientState() {
221
+ const newConfigData = await this._getLsObject();
222
+ // if the lock expired, we remove the lock period and enable the client
223
+ if (newConfigData.ClientUnlockTime &&
224
+ new Date(newConfigData.ClientUnlockTime) <= new Date()) {
225
+ newConfigData.ClientUnlockTime = undefined;
226
+ newConfigData.DisabledStatus = false;
227
+ await this._storeBrowserData(newConfigData);
228
+ }
229
+ // return the stored browserId
230
+ return newConfigData;
254
231
  }
255
- // return the stored browserId
256
- return newConfigData;
257
- }
258
-
259
- /**
260
- * _generateAndStoreData generates brand new data and then proceeds to store
261
- * it.
262
- */
263
- async _generateAndStoreData() {
264
- return this._storeBrowserData(this._generateNewBrowserData());
265
- }
266
-
267
- /**
268
- * _generateNewBrowserData will create new data to be stored in storage
269
- * and persisted throughout a session
270
- */
271
- _generateNewBrowserData() {
272
- const noibuBrowserData = {
273
- [DISABLED_STATUS_KEY]: false,
274
- [BROWSER_ID_KEY]: uuid.v4(),
275
- [CURRENT_PAGE_VISIT_COUNT_KEY]: 0,
276
- [CLIENT_UNLOCK_TIME_KEY]: null,
277
- [LAST_ACTIVE_TIME_KEY]: new Date(),
278
- };
279
-
280
- // Expose page visit ID in storage for use by Trailbreaker video tests
281
- // This will be done for the testvideo and lambdavideo bundles used by Trailbreaker
282
- if (JS_ENV().includes('video')) {
283
- noibuBrowserData[PAGE_VISIT_ID_KEY] = this.pageVisitId;
232
+ /**
233
+ * _generateAndStoreData generates brand new data and then proceeds to store
234
+ * it.
235
+ */
236
+ async _generateAndStoreData() {
237
+ return this._storeBrowserData(this._generateNewBrowserData());
284
238
  }
285
-
286
- return noibuBrowserData;
287
- }
288
-
289
- /**
290
- * _storeBrowserData will store the passed object in storage.
291
- * @param {} data the data to be stored
292
- */
293
- async _storeBrowserData(data) {
294
- const storage = Storage.getInstance();
295
- try {
296
- await storage.save(NOIBU_BROWSER_ID_KYWRD, stringifyJSON(data));
297
- return data;
298
- } catch (e) {
299
- this.postNoibuErrorAndOptionallyDisableClient(
300
- `Error writing browser data to storage, disabling client: ${e.message}, ` +
301
- `${await storage.getDiagnoseInfo()}`,
302
- true,
303
- SEVERITY_ERROR,
304
- );
305
- // sending empty fields if we encountered errors while storing in the LS
306
- return {
307
- [DISABLED_STATUS_KEY]: true,
308
- [BROWSER_ID_KEY]: null,
309
- [CURRENT_PAGE_VISIT_COUNT_KEY]: 0,
310
- };
239
+ /**
240
+ * _generateNewBrowserData will create new data to be stored in storage
241
+ * and persisted throughout a session
242
+ */
243
+ _generateNewBrowserData() {
244
+ const noibuBrowserData = {
245
+ DisabledStatus: false,
246
+ BrowserId: uuid.v4(),
247
+ CurrentPageVisitCount: 0,
248
+ LastActive: new Date(),
249
+ };
250
+ // Expose page visit ID in storage for use by Trailbreaker video tests
251
+ // This will be done for the testvideo and lambdavideo bundles used by Trailbreaker
252
+ if (JS_ENV().includes('video')) {
253
+ noibuBrowserData.pvId = this.pageVisitId;
254
+ }
255
+ return noibuBrowserData;
311
256
  }
312
- }
313
-
314
- /**
315
- * postNoibuErrorAndOptionallyDisableClient will post errors that were thrown by collect
316
- * and disable the client if required
317
- * severity expects one of the SEVERITY_x level constants, or else error will be used
318
- * @param {} error
319
- * @param {} disableClient
320
- * @param {} severity
321
- * @param {} keepAlive=false
322
- */
323
- async postNoibuErrorAndOptionallyDisableClient(
324
- error,
325
- disableClient,
326
- severity,
327
- keepAlive = false,
328
- ) {
329
- if (this.isClientDisabled) {
330
- return;
257
+ /**
258
+ * _storeBrowserData will store the passed object in storage.
259
+ * @param {} data the data to be stored
260
+ */
261
+ async _storeBrowserData(data) {
262
+ const storage = Storage.getInstance();
263
+ try {
264
+ await storage.save(NOIBU_BROWSER_ID_KYWRD, stringifyJSON(data));
265
+ return data;
266
+ }
267
+ catch (e) {
268
+ this.postNoibuErrorAndOptionallyDisableClient(`Error writing browser data to storage, disabling client: ${e.message}, ${await storage.getDiagnoseInfo()}`, true, SEVERITY.error);
269
+ // sending empty fields if we encountered errors while storing in the LS
270
+ return this._generateNewBrowserData();
271
+ }
331
272
  }
332
- if (disableClient) {
333
- this.isClientDisabled = true;
273
+ /**
274
+ * postNoibuErrorAndOptionallyDisableClient will post errors that were thrown by collect
275
+ * and disable the client if required
276
+ * severity expects one of the SEVERITY_x level constants, or else error will be used
277
+ */
278
+ async postNoibuErrorAndOptionallyDisableClient(errorMsg, disableClient, severity, keepAlive = false) {
279
+ if (this.isClientDisabled) {
280
+ return;
281
+ }
282
+ if (disableClient) {
283
+ this.isClientDisabled = true;
284
+ }
285
+ if (severity === SEVERITY.warn) {
286
+ // don't log warning messages by default, as a cost savings
287
+ return;
288
+ }
289
+ let errMsg = `Noibu Browser ID(${this.browserId ? this.browserId : ''}), PV ID ${this.pageVisitId}, Script ID ${GET_SCRIPT_ID()}, and User Agent ${await getUserAgent()} error: ${asString(errorMsg)}`;
290
+ // if the page visits sends more errors than the
291
+ // allowed threshold we disable the client
292
+ if (this.cltErrorPostCounter >= MAX_COLLECT_ERROR_LOG) {
293
+ // we disable the client for 10 minute if we sent too many logs
294
+ // we manually lock the client to not cause an infinite loop
295
+ const expiryTime = new Date();
296
+ expiryTime.setMinutes(expiryTime.getMinutes() + 10); // 10 minutes lock
297
+ const noibuLSObject = await this._getClientState();
298
+ noibuLSObject.DisabledStatus = true;
299
+ noibuLSObject.ClientUnlockTime = expiryTime;
300
+ await this._storeBrowserData(noibuLSObject);
301
+ this.isClientDisabled = true;
302
+ // end of lock
303
+ // overriding the message to be an alert that we are shutting collect off.
304
+ errMsg =
305
+ 'Shutting collect off, we reached the ' +
306
+ 'maximum limit of collect errors sent.';
307
+ }
308
+ const errorContent = {
309
+ url: getProperGlobalUrl(),
310
+ err_msg: errMsg,
311
+ sev: severity,
312
+ };
313
+ const headers = {
314
+ 'content-type': 'application/json',
315
+ 'User-Agent': await getUserAgent(),
316
+ };
317
+ if (keepAlive) {
318
+ fetch(this.noibuErrorURL, {
319
+ method: 'POST',
320
+ headers,
321
+ body: stringifyJSON(errorContent),
322
+ // keep alive outlives the current page, its the same as beacon
323
+ keepalive: true,
324
+ });
325
+ }
326
+ else {
327
+ makeRequest('POST', this.noibuErrorURL, errorContent, headers, 2000, false).catch(() => {
328
+ // we do nothing and let this error silently fail
329
+ });
330
+ }
331
+ // only increment if this was an actual error, not a warning or otherwise
332
+ if (severity === SEVERITY.error) {
333
+ this.cltErrorPostCounter += 1;
334
+ }
334
335
  }
335
- if (severity === SEVERITY_WARN) {
336
- // don't log warning messages by default, as a cost savings
337
- return;
336
+ /**
337
+ * Returns true if the page visit is considered to be inactive
338
+ */
339
+ isInactive() {
340
+ const someTimeAgo = new Date();
341
+ someTimeAgo.setSeconds(someTimeAgo.getSeconds() - this.maxSocketInactiveTime);
342
+ return this.lastActiveTime < someTimeAgo;
338
343
  }
339
-
340
- let errMsg = `Noibu Browser ID(${
341
- this.browserId ? this.browserId : ''
342
- }), PV ID ${
343
- this.pageVisitId
344
- }, Script ID ${GET_SCRIPT_ID()}, and User Agent ${await getUserAgent()} error: ${asString(
345
- error,
346
- )}`;
347
-
348
- // if the page visits sends more errors than the
349
- // allowed threshold we disable the client
350
- if (this.cltErrorPostCounter >= MAX_COLLECT_ERROR_LOG) {
351
- // we disable the client for 10 minute if we sent too many logs
352
- // we manually lock the client to not cause an infinite loop
353
- const expiryTime = new Date();
354
- expiryTime.setMinutes(expiryTime.getMinutes() + 10); // 10 minutes lock
355
-
356
- const noibuLSObject = await this._getClientState();
357
- noibuLSObject[DISABLED_STATUS_KEY] = true;
358
- noibuLSObject[CLIENT_UNLOCK_TIME_KEY] = expiryTime;
359
- await this._storeBrowserData(noibuLSObject);
360
- this.isClientDisabled = true;
361
- // end of lock
362
- // overriding the message to be an alert that we are shutting collect off.
363
- errMsg =
364
- 'Shutting collect off, we reached the ' +
365
- 'maximum limit of collect errors sent.';
366
- }
367
-
368
- const errorContent = {
369
- url: getProperGlobalUrl(),
370
- err_msg: errMsg,
371
- sev: severity,
372
- };
373
- const headers = {
374
- 'content-type': 'application/json',
375
- 'User-Agent': await getUserAgent(),
376
- };
377
-
378
- if (keepAlive) {
379
- global.fetch(this.noibuErrorURL, {
380
- method: 'POST',
381
- headers,
382
- body: stringifyJSON(errorContent),
383
- // keep alive outlives the current page, its the same as beacon
384
- keepalive: true,
385
- });
386
- } else {
387
- makeRequest(
388
- 'POST',
389
- this.noibuErrorURL,
390
- errorContent,
391
- headers,
392
- 2000,
393
- false,
394
- ).catch(() => {
395
- // we do nothing and let this error silently fail
396
- });
397
- }
398
-
399
- // only increment if this was an actual error, not a warning or otherwise
400
- if (severity === SEVERITY_ERROR) {
401
- this.cltErrorPostCounter += 1;
402
- }
403
- }
404
-
405
- /**
406
- * Returns true if the page visit is considered to be inactive
407
- */
408
- isInactive() {
409
- const someTimeAgo = new Date();
410
- someTimeAgo.setSeconds(
411
- someTimeAgo.getSeconds() - this.maxSocketInactiveTime,
412
- );
413
-
414
- return this.lastActiveTime < someTimeAgo;
415
- }
416
344
  }
417
345
 
418
346
  export { ClientConfig as default };