Skip to content

Commit a889cd2

Browse files
authored
Fixes #70: Ignore errors created from browser extensions (#123)
* Fixes #70: Ignore errors created from browser extensions * Fixed lint error
1 parent 71c8246 commit a889cd2

File tree

7 files changed

+84
-1
lines changed

7 files changed

+84
-1
lines changed

example/browser/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ <h1>Error Submission</h1>
1515
<button onclick="throwReferenceError('function-does-exist')">Throw uncaught reference error</button>
1616
<button id="throw-jquery-ajax-error">Throw jQuery ajax error</button>
1717
<button id="throw-promise-unhandled-rejection">Throw promise unhandled rejection</button>
18+
<button id="throw-browser-extension-error">Throw brower extension error</button>
1819

1920
<h1>Log Submission</h1>
2021
<button class="submit-log">Submit log event</button>

example/browser/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ document.addEventListener("DOMContentLoaded", () => {
5353
await builder.submit();
5454
});
5555

56+
document
57+
.querySelector("#throw-browser-extension-error")
58+
.addEventListener("click", () => {
59+
const error = new Error("A Browser Extension Error");
60+
error.stack = "at <anonymous>() in chrome-extension://bmagokdooijbeehmkpknfglimnifench/firebug-lite.js:line 9716:col 29"
61+
62+
throw error;
63+
});
64+
5665
document
5766
.querySelector("#throw-custom-error")
5867
.addEventListener("click", () => {

packages/browser/src/BrowserExceptionlessClient.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Configuration, ExceptionlessClient, SimpleErrorPlugin } from "@exceptio
22

33
import { BrowserErrorPlugin } from "./plugins/BrowserErrorPlugin.js";
44
import { BrowserGlobalHandlerPlugin } from "./plugins/BrowserGlobalHandlerPlugin.js";
5+
import { BrowserIgnoreExtensionErrorsPlugin } from "./plugins/BrowserIgnoreExtensionErrorsPlugin.js";
56
import { BrowserLifeCyclePlugin } from "./plugins/BrowserLifeCyclePlugin.js";
67
import { BrowserModuleInfoPlugin } from "./plugins/BrowserModuleInfoPlugin.js";
78
import { BrowserRequestInfoPlugin } from "./plugins/BrowserRequestInfoPlugin.js";
@@ -13,6 +14,7 @@ export class BrowserExceptionlessClient extends ExceptionlessClient {
1314
config.useLocalStorage();
1415

1516
config.addPlugin(new BrowserGlobalHandlerPlugin());
17+
config.addPlugin(new BrowserIgnoreExtensionErrorsPlugin());
1618
config.addPlugin(new BrowserLifeCyclePlugin());
1719
config.addPlugin(new BrowserModuleInfoPlugin());
1820
config.addPlugin(new BrowserRequestInfoPlugin());

packages/browser/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export { BrowserErrorPlugin } from "./plugins/BrowserErrorPlugin.js"
22
export { BrowserGlobalHandlerPlugin } from "./plugins/BrowserGlobalHandlerPlugin.js";
3+
export { BrowserIgnoreExtensionErrorsPlugin } from "./plugins/BrowserIgnoreExtensionErrorsPlugin.js";
34
export { BrowserLifeCyclePlugin } from "./plugins/BrowserLifeCyclePlugin.js";
45
export { BrowserModuleInfoPlugin } from "./plugins/BrowserModuleInfoPlugin.js";
56
export { BrowserRequestInfoPlugin } from "./plugins/BrowserRequestInfoPlugin.js";

packages/browser/src/plugins/BrowserGlobalHandlerPlugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class BrowserGlobalHandlerPlugin implements IEventPlugin {
4646
void this._client?.submitNotFound(settings.url);
4747
} else if (xhr.status !== 401) {
4848
// TODO: Handle async
49-
void this._client?.createUnhandledException(toError(error) as Error, "JQuery.ajaxError")
49+
void this._client?.createUnhandledException(toError(error), "JQuery.ajaxError")
5050
.setSource(settings.url)
5151
.setProperty("status", xhr.status)
5252
.setProperty("request", settings.data)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {
2+
EventPluginContext,
3+
IEventPlugin
4+
} from "@exceptionless/core";
5+
6+
export class BrowserIgnoreExtensionErrorsPlugin implements IEventPlugin {
7+
public priority = 15;
8+
public name = "BrowserIgnoreExtensionErrorsPlugin";
9+
10+
public async run(context: EventPluginContext): Promise<void> {
11+
const exception = context.eventContext.getException();
12+
if (exception?.stack && exception.stack.includes("-extension://")) {
13+
// Handles all extensions like chrome-extension://, moz-extension://, ms-browser-extension://, safari-extension://
14+
context.log.info("Ignoring event with error stack containing browser extension");
15+
context.cancelled = true;
16+
}
17+
18+
return Promise.resolve();
19+
}
20+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { describe, test } from "@jest/globals";
2+
import { expect } from "expect";
3+
4+
import {
5+
EventContext,
6+
EventPluginContext,
7+
ExceptionlessClient
8+
} from "@exceptionless/core";
9+
10+
import { BrowserIgnoreExtensionErrorsPlugin } from "../../src/plugins/BrowserIgnoreExtensionErrorsPlugin.js";
11+
12+
describe("BrowserIgnoreExtensionErrorsPlugin", () => {
13+
let client: ExceptionlessClient;
14+
let plugin: BrowserIgnoreExtensionErrorsPlugin;
15+
16+
beforeEach(() => {
17+
client = new ExceptionlessClient();
18+
plugin = new BrowserIgnoreExtensionErrorsPlugin();
19+
});
20+
21+
const run = async (stackTrace?: string | undefined): Promise<EventPluginContext> => {
22+
const error = new Error("Test");
23+
if (stackTrace) {
24+
error.stack = stackTrace;
25+
}
26+
27+
const eventContext = new EventContext();
28+
eventContext.setException(error);
29+
30+
const context = new EventPluginContext(client, { type: "error" }, eventContext);
31+
32+
await plugin.run(context);
33+
return context;
34+
}
35+
36+
test("should not cancel empty stack trace", async () => {
37+
const context = await run();
38+
expect(context.cancelled).toBe(false);
39+
});
40+
41+
test("should not cancel normal stack trace", async () => {
42+
const context = await run("at t() in https://test/Content/js/Exceptionless/exceptionless.min.js:line 1:col 260");
43+
expect(context.cancelled).toBe(false);
44+
});
45+
46+
test("should cancel browser extension stack trace", async () => {
47+
const context = await run("at Object.initialize() in chrome-extension://bmagokdooijbeehmkpknfglimnifench/firebug-lite.js:line 6289:col 29");
48+
expect(context.cancelled).toBe(true);
49+
});
50+
});

0 commit comments

Comments
 (0)