diff --git a/public/app/core/crash/index.ts b/public/app/core/crash/index.ts index a2f54a9d866..b7bd92e88ea 100644 --- a/public/app/core/crash/index.ts +++ b/public/app/core/crash/index.ts @@ -3,8 +3,10 @@ import { BaseStateReport } from 'crashme/dist/types'; import { nanoid } from 'nanoid'; import { config, createMonitoringLogger } from '@grafana/runtime'; +import { CorsWorker as Worker } from 'app/core/utils/CorsWorker'; import { contextSrv } from '../services/context_srv'; +import { CorsSharedWorker as SharedWorker, sharedWorkersSupported } from '../utils/CorsSharedWorker'; import { isChromePerformance, prepareContext } from './crash.utils'; @@ -30,6 +32,10 @@ interface GrafanaCrashReport extends BaseStateReport { } export function initializeCrashDetection() { + if (!sharedWorkersSupported()) { + return; + } + initCrashDetection({ id: nanoid(5), diff --git a/public/app/core/utils/CorsSharedWorker.ts b/public/app/core/utils/CorsSharedWorker.ts new file mode 100644 index 00000000000..7e697327d42 --- /dev/null +++ b/public/app/core/utils/CorsSharedWorker.ts @@ -0,0 +1,40 @@ +// Almost identical to CorsWorker.ts. Main difference being it creates a SharedWorker in runtime (if it's supported bythe browser + +export function sharedWorkersSupported() { + return typeof window.SharedWorker !== 'undefined'; +} + +class SharedWorkerNotSupported implements SharedWorker { + onerror() {} + // @ts-ignore + readonly port: MessagePort; + dispatchEvent(): boolean { + return false; + } + addEventListener(): void {} + removeEventListener(): void {} +} +const BaseSharedWorkerClass = sharedWorkersSupported() ? window.SharedWorker : SharedWorkerNotSupported; + +export class CorsSharedWorker extends BaseSharedWorkerClass { + constructor(url: URL, options?: WorkerOptions) { + // by default, worker inherits HTML document's location and pathname which leads to wrong public path value + // the CorsWorkerPlugin will override it with the value based on the initial worker chunk, ie. + // initial worker chunk: http://host.com/cdn/scripts/worker-123.js + // resulting public path: http://host.com/cdn/scripts + + const scriptUrl = url.toString(); + const urlParts = scriptUrl.split('/'); + urlParts.pop(); + const scriptsBasePathUrl = `${urlParts.join('/')}/`; + + const importScripts = `importScripts('${scriptUrl}');`; + const objectURL = URL.createObjectURL( + new Blob([`__webpack_worker_public_path__ = '${scriptsBasePathUrl}'; ${importScripts}`], { + type: 'application/javascript', + }) + ); + super(objectURL, options); + URL.revokeObjectURL(objectURL); + } +}