Skip to content

Commit 37e976b

Browse files
authored
feat: Enable the browser agent to run in extension background contexts (#1206)
Thanks for contributing @jspivack !
1 parent bbf414c commit 37e976b

File tree

4 files changed

+59
-5
lines changed

4 files changed

+59
-5
lines changed

src/common/harvest/harvest.js

+19
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,25 @@ export class Harvest extends SharedContext {
144144
}
145145
cbFinished(cbResult)
146146
}, eventListenerOpts(false))
147+
} else if (!opts.unload && cbFinished && submitMethod === submitData.xhrFetch) {
148+
const harvestScope = this
149+
result.then(async function (response) {
150+
const status = response.status
151+
const cbResult = { sent: true, status, fullUrl, fetchResponse: response }
152+
153+
if (response.status === 429) {
154+
cbResult.retry = true
155+
cbResult.delay = harvestScope.tooManyRequestsDelay
156+
} else if (status === 408 || status === 500 || status === 503) {
157+
cbResult.retry = true
158+
}
159+
160+
if (opts.needResponse) {
161+
cbResult.responseText = await response.text()
162+
}
163+
164+
cbFinished(cbResult)
165+
})
147166
}
148167

149168
return result

src/common/util/submit-data.js

+37-4
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,44 @@ import { isBrowserScope } from '../constants/runtime'
1717
* a final harvest within the agent.
1818
*/
1919
export function getSubmitMethod ({ isFinalHarvest = false } = {}) {
20-
return isFinalHarvest && isBrowserScope
20+
if (isFinalHarvest && isBrowserScope) {
2121
// Use sendBeacon for final harvest
22-
? beacon
23-
// If not final harvest, or not browserScope, always use xhr post
24-
: xhr
22+
return beacon
23+
}
24+
25+
// If not final harvest, or not browserScope, use XHR post if available
26+
if (typeof XMLHttpRequest !== 'undefined') {
27+
return xhr
28+
}
29+
30+
// Fallback for web workers where XMLHttpRequest is not available
31+
return xhrFetch
32+
}
33+
34+
/**
35+
*
36+
* @param url
37+
* @param body
38+
* @param method
39+
* @param headers
40+
* @returns {Promise<Response>}
41+
*/
42+
export function xhrFetch ({
43+
url,
44+
body = null,
45+
method = 'POST',
46+
headers = [{
47+
key: 'content-type',
48+
value: 'text/plain'
49+
}]
50+
}) {
51+
const objHeaders = {}
52+
53+
for (const header of headers) {
54+
objHeaders[header.key] = header.value
55+
}
56+
57+
return fetch(url, { headers: objHeaders, method, body, credentials: 'include' })
2558
}
2659

2760
/**

src/common/wrap/wrap-events.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ export function wrapEvents (sharedEE) {
3737
// Guard against instrumenting environments w/o necessary features
3838
if ('getPrototypeOf' in Object) {
3939
if (isBrowserScope) findEventListenerProtoAndCb(document, wrapNode)
40+
if (XHR) findEventListenerProtoAndCb(XHR.prototype, wrapNode)
4041
findEventListenerProtoAndCb(globalScope, wrapNode)
41-
findEventListenerProtoAndCb(XHR.prototype, wrapNode)
4242
}
4343

4444
ee.on(ADD_EVENT_LISTENER + '-start', function (args, target) {

src/common/wrap/wrap-xhr.js

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export function wrapXhr (sharedEE) {
2828
var baseEE = sharedEE || contextualEE
2929
const ee = scopedEE(baseEE)
3030

31+
if (typeof globalScope.XMLHttpRequest === 'undefined') return ee
32+
3133
// Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
3234
// then we increment the count to track # of feats using this at runtime.
3335
if (wrapped[ee.debugId]++) return ee

0 commit comments

Comments
 (0)