noibu-react-native 0.0.4 → 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.
- package/README.md +22 -7
- package/dist/api/clientConfig.d.ts +101 -0
- package/dist/api/clientConfig.js +315 -387
- package/dist/api/helpCode.js +2 -2
- package/dist/api/inputManager.js +3 -9
- package/dist/api/metroplexSocket.js +6 -31
- package/dist/api/storedPageVisit.js +3 -3
- package/dist/constants.d.ts +7 -40
- package/dist/constants.js +8 -65
- package/dist/entry/index.d.ts +2 -3
- package/dist/entry/index.js +1 -9
- package/dist/entry/init.d.ts +5 -0
- package/dist/entry/init.js +54 -69
- package/dist/monitors/clickMonitor.js +9 -56
- package/dist/monitors/errorMonitor.js +1 -1
- package/dist/monitors/gqlErrorValidator.js +3 -3
- package/dist/monitors/httpDataBundler.js +10 -10
- package/dist/monitors/requestMonitor.js +8 -8
- package/dist/pageVisit/pageVisitEventError/pageVisitEventError.js +4 -4
- package/dist/storage/storage.d.ts +3 -2
- package/dist/storage/storageProvider.d.ts +6 -5
- package/dist/types/Config.d.ts +27 -0
- package/dist/types/PageVisit.d.ts +22 -0
- package/dist/types/ReactNative.d.ts +3 -0
- package/dist/types/Storage.d.ts +14 -0
- package/dist/types/globals.d.ts +34 -0
- package/dist/utils/date.js +2 -2
- package/dist/utils/eventlistener.js +3 -3
- package/dist/utils/function.d.ts +100 -0
- package/dist/utils/function.js +208 -312
- package/dist/utils/stacktrace-parser.d.ts +6 -8
- package/dist/utils/stacktrace-parser.js +5 -5
- package/package.json +2 -1
- package/dist/monitors/elementMonitor.js +0 -177
package/dist/api/clientConfig.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import uuid from 'react-native-uuid';
|
|
2
|
-
import { MAX_METROPLEX_SOCKET_INNACTIVE_TIME,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
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
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
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
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
-
|
|
333
|
-
|
|
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
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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 };
|