blob: 2ed902505ef3b1e93d70c94be100b06ff84c71b2 [file] [log] [blame]
Adrià Vilanova Martínezdfe71fc2024-05-25 22:13:32 +02001import StylesheetManager from '../../../StylesheetManager';
2import { StylesheetAttributes } from '../../../contentScriptsUtils';
Adrià Vilanova Martínez6ecaa0d2024-10-26 17:04:32 +02003import OptionsProviderAdapter from '../../../options/OptionsProvider';
Adrià Vilanova Martínezdfe71fc2024-05-25 22:13:32 +02004import DependenciesProviderSingleton, {
5 OptionsProviderDependency,
6} from '../../dependenciesProvider/DependenciesProvider';
7import Script, { ScriptEnvironment, ScriptRunPhase } from '../Script';
8
9/**
10 * Script which injects a stylesheet depending on a set condition. It
11 * dynamically reevaluates the condition when the options configuration changes.
12 */
13export default abstract class StylesheetScript extends Script {
14 readonly environment = ScriptEnvironment.ContentScript;
15 readonly runPhase = ScriptRunPhase.Start;
16
17 /**
18 * Relative path to the stylesheet from the extension root.
19 */
20 abstract readonly stylesheet: string;
21 /**
22 * Attributes to include in the injected <link> element.
23 */
24 readonly attributes: StylesheetAttributes = {};
25
Adrià Vilanova Martínez6ecaa0d2024-10-26 17:04:32 +020026 protected optionsProvider: OptionsProviderAdapter;
Adrià Vilanova Martínezdfe71fc2024-05-25 22:13:32 +020027 private stylesheetManager: StylesheetManager;
28
29 constructor() {
30 super();
Adrià Vilanova Martínez6ecaa0d2024-10-26 17:04:32 +020031
32 // TODO(https://iavm.xyz/b/226): Retrieve this via constructor injection.
Adrià Vilanova Martínezdfe71fc2024-05-25 22:13:32 +020033 const dependenciesProvider = DependenciesProviderSingleton.getInstance();
34 this.optionsProvider = dependenciesProvider.getDependency(
35 OptionsProviderDependency,
36 );
37 }
38
39 /**
40 * Condition which decides whether the stylesheet should be injected or not.
41 *
42 * @returns {boolean} Whether the stylesheet should be injected.
43 */
44 abstract shouldBeInjected(): Promise<boolean>;
45
46 execute() {
47 this.stylesheetManager = new StylesheetManager(
48 this.stylesheet,
49 this.attributes,
50 );
51 this.optionsProvider.addListener(this.evaluateInjection.bind(this));
52 this.evaluateInjection();
53 }
54
55 async evaluateInjection() {
56 const shouldBeInjected = await this.shouldBeInjected();
57 if (!this.stylesheetManager.isInjected() && shouldBeInjected) {
58 this.stylesheetManager.inject();
59 }
60 if (this.stylesheetManager.isInjected() && !shouldBeInjected) {
61 this.stylesheetManager.remove();
62 }
63 }
64}