Skip to content

Commit

Permalink
feat: Enable the browser agent to run in extension background contexts (
Browse files Browse the repository at this point in the history
#1206)

Thanks for contributing @jspivack !
  • Loading branch information
jspivack authored Dec 2, 2024
1 parent bbf414c commit 37e976b
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 5 deletions.
19 changes: 19 additions & 0 deletions src/common/harvest/harvest.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,25 @@ export class Harvest extends SharedContext {
}
cbFinished(cbResult)
}, eventListenerOpts(false))
} else if (!opts.unload && cbFinished && submitMethod === submitData.xhrFetch) {
const harvestScope = this
result.then(async function (response) {
const status = response.status
const cbResult = { sent: true, status, fullUrl, fetchResponse: response }

if (response.status === 429) {
cbResult.retry = true
cbResult.delay = harvestScope.tooManyRequestsDelay
} else if (status === 408 || status === 500 || status === 503) {
cbResult.retry = true
}

if (opts.needResponse) {
cbResult.responseText = await response.text()
}

cbFinished(cbResult)
})
}

return result
Expand Down
41 changes: 37 additions & 4 deletions src/common/util/submit-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,44 @@ import { isBrowserScope } from '../constants/runtime'
* a final harvest within the agent.
*/
export function getSubmitMethod ({ isFinalHarvest = false } = {}) {
return isFinalHarvest && isBrowserScope
if (isFinalHarvest && isBrowserScope) {
// Use sendBeacon for final harvest
? beacon
// If not final harvest, or not browserScope, always use xhr post
: xhr
return beacon
}

// If not final harvest, or not browserScope, use XHR post if available
if (typeof XMLHttpRequest !== 'undefined') {
return xhr
}

// Fallback for web workers where XMLHttpRequest is not available
return xhrFetch
}

/**
*
* @param url
* @param body
* @param method
* @param headers
* @returns {Promise<Response>}
*/
export function xhrFetch ({
url,
body = null,
method = 'POST',
headers = [{
key: 'content-type',
value: 'text/plain'
}]
}) {
const objHeaders = {}

for (const header of headers) {
objHeaders[header.key] = header.value
}

return fetch(url, { headers: objHeaders, method, body, credentials: 'include' })
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/common/wrap/wrap-events.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export function wrapEvents (sharedEE) {
// Guard against instrumenting environments w/o necessary features
if ('getPrototypeOf' in Object) {
if (isBrowserScope) findEventListenerProtoAndCb(document, wrapNode)
if (XHR) findEventListenerProtoAndCb(XHR.prototype, wrapNode)
findEventListenerProtoAndCb(globalScope, wrapNode)
findEventListenerProtoAndCb(XHR.prototype, wrapNode)
}

ee.on(ADD_EVENT_LISTENER + '-start', function (args, target) {
Expand Down
2 changes: 2 additions & 0 deletions src/common/wrap/wrap-xhr.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export function wrapXhr (sharedEE) {
var baseEE = sharedEE || contextualEE
const ee = scopedEE(baseEE)

if (typeof globalScope.XMLHttpRequest === 'undefined') return ee

// Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
// then we increment the count to track # of feats using this at runtime.
if (wrapped[ee.debugId]++) return ee
Expand Down

0 comments on commit 37e976b

Please sign in to comment.