diff --git a/packages/core/src/tools/experimentalFeatures.ts b/packages/core/src/tools/experimentalFeatures.ts index 63959816e3..2438be3a4c 100644 --- a/packages/core/src/tools/experimentalFeatures.ts +++ b/packages/core/src/tools/experimentalFeatures.ts @@ -18,6 +18,7 @@ export enum ExperimentalFeature { COLLECT_FLUSH_REASON = 'collect_flush_reason', NO_RESOURCE_DURATION_FROZEN_STATE = 'no_resource_duration_frozen_state', SCROLLMAP = 'scrollmap', + DISABLE_REPLAY_INLINE_CSS = 'disable_replay_inline_css', } const enabledExperimentalFeatures: Set = new Set() diff --git a/packages/rum/src/domain/record/serialization/serializeAttributes.ts b/packages/rum/src/domain/record/serialization/serializeAttributes.ts index 40947e4868..abbbfcf04a 100644 --- a/packages/rum/src/domain/record/serialization/serializeAttributes.ts +++ b/packages/rum/src/domain/record/serialization/serializeAttributes.ts @@ -1,3 +1,5 @@ +import { ExperimentalFeature, isExperimentalFeatureEnabled } from '@datadog/browser-core' + import { NodePrivacyLevel } from '../../../constants' import { shouldMaskNode } from '../privacy' import { getElementInputValue, switchToAbsoluteUrl, getValidTagName } from './serializationUtils' @@ -51,7 +53,7 @@ export function serializeAttributes( if (tagName === 'link') { const stylesheet = Array.from(doc.styleSheets).find((s) => s.href === (element as HTMLLinkElement).href) const cssText = getCssRulesString(stylesheet) - if (cssText && stylesheet) { + if (cssText && stylesheet && !isExperimentalFeatureEnabled(ExperimentalFeature.DISABLE_REPLAY_INLINE_CSS)) { safeAttrs._cssText = cssText } } diff --git a/packages/rum/src/domain/record/serialization/serializeNode.spec.ts b/packages/rum/src/domain/record/serialization/serializeNode.spec.ts index 633ffda3fc..bc9dfbe08f 100644 --- a/packages/rum/src/domain/record/serialization/serializeNode.spec.ts +++ b/packages/rum/src/domain/record/serialization/serializeNode.spec.ts @@ -1,4 +1,10 @@ -import { isIE, noop } from '@datadog/browser-core' +import { + ExperimentalFeature, + addExperimentalFeatures, + isIE, + noop, + resetExperimentalFeatures, +} from '@datadog/browser-core' import type { RumConfiguration } from '@datadog/browser-rum-core' import { isAdoptedStyleSheetsSupported } from '@datadog/browser-core/test' @@ -71,6 +77,7 @@ describe('serializeNodeWithId', () => { afterEach(() => { sandbox.remove() + resetExperimentalFeatures() }) describe('document serialization', () => { @@ -588,6 +595,24 @@ describe('serializeNodeWithId', () => { }) }) + it('does not inline external style sheets when DISABLE_REPLAY_INLINE_CSS is enabled', () => { + addExperimentalFeatures([ExperimentalFeature.DISABLE_REPLAY_INLINE_CSS]) + const linkNode = document.createElement('link') + linkNode.setAttribute('rel', 'stylesheet') + linkNode.setAttribute('href', 'https://datadoghq.com/some/style.css') + isolatedDom.document.head.appendChild(linkNode) + Object.defineProperty(isolatedDom.document, 'styleSheets', { + value: [ + { + href: 'https://datadoghq.com/some/style.css', + cssRules: [{ cssText: 'body { width: 100%; }' }], + }, + ], + }) + + expect((serializeNodeWithId(linkNode, DEFAULT_OPTIONS) as ElementNode).attributes._cssText).toBeUndefined() + }) + it('does not serialize style node with dynamic CSS that is behind CORS', () => { const linkNode = document.createElement('link') linkNode.setAttribute('rel', 'stylesheet')