blob: 48994362538e104330e1c036344a5d9197824ac0 [file] [log] [blame]
Adrià Vilanova Martínezdfe71fc2024-05-25 22:13:32 +02001import StylesheetManager from '../../../StylesheetManager';
2import { StylesheetAttributes } from '../../../contentScriptsUtils';
Adrià Vilanova Martínezdfe71fc2024-05-25 22:13:32 +02003import DependenciesProviderSingleton, {
4 OptionsProviderDependency,
5} from '../../dependenciesProvider/DependenciesProvider';
6import Script, { ScriptEnvironment, ScriptRunPhase } from '../Script';
Adrià Vilanova Martínez7c941c72024-10-26 20:23:34 +02007import { OptionsProviderPort } from '../../../../services/options/OptionsProvider';
Adrià Vilanova Martínezdfe71fc2024-05-25 22:13:32 +02008
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ínez7c941c72024-10-26 20:23:34 +020026 protected optionsProvider: OptionsProviderPort;
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}