summaryrefslogtreecommitdiffstats
path: root/layout/base/tests/chrome/test_color_scheme_browser.xhtml
blob: 163f83b38f380f0090a0d5130f36cabd266fb50c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <head>
    <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
    <script src="chrome://mochikit/content/chrome-harness.js"></script>
    <style>
      #light { color-scheme: light }
      #dark { color-scheme: dark }
    </style>
  </head>
  <body>
    <div id="dynamic-test">
      <xul:browser type="content" remote="true" nodefaultsrc="true" class="remote" />
      <xul:browser type="content" src="about:blank" class="nonremote" />
    </div>
    <div id="light">
      <xul:browser type="content" remote="true" nodefaultsrc="true" class="remote" />
      <xul:browser type="content" src="about:blank" class="nonremote" />
    </div>
    <div id="dark">
      <xul:browser type="content" remote="true" nodefaultsrc="true" class="remote" />
      <xul:browser type="content" src="about:blank" class="nonremote" />
    </div>
    <script><![CDATA[
      SimpleTest.requestCompleteLog(); // to help diagnose intermittent bug 1787008

      // FIXME: This shouldn't be needed if remote browsers would block the load event.
      add_task(async function ensureBrowsersLoaded() {
        info("Entering ensureBrowsersLoaded callback");
        const triggeringPrincipal = document.nodePrincipal;
        for (let b of document.querySelectorAll("browser[remote=true]")) {
          let listener;
          let loaded = new Promise(resolve => {
            info("Entering 'loaded' callback; about to add progress listener");
            listener = {
              onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
                info(`Got state change for ${b.parentNode.id}: ${aStateFlags}, ${aStatus}`);
                if (
                  aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW &&
                  aStateFlags & Ci.nsIWebProgressListener.STATE_STOP
                ) {
                  resolve();
                  b.removeProgressListener(this);
                }
              },
              // Note: the following "onFoo" callbacks are only here for
              // diagnostic purposes, and otherwise aren't relevant to the test.
              onProgressChange(aWebProgress, aRequest,
                               aCurSelfProgress, aMaxSelfProgress,
                               aCurTotalProgress, aMaxTotalProgress) {
                info(`Got progress change for ${b.parentNode.id}: ` +
                     `${aCurSelfProgress}/${aMaxSelfProgress}, ` +
                     `${aCurTotalProgress}/${aMaxTotalProgress}`);
              },
              onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
                info(`Got location change for ${b.parentNode.id}: ${aLocation.spec}, ${aFlags}`);
              },
              onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {
                info(`Got status change for ${b.parentNode.id}: ${aStatus}, ${aMessage}`);
              },
              onSecurityChange(aWebProgress, aRequest, aState) {
                info(`Got security change for ${b.parentNode.id}: ${aState}`);
              },
              onContentBlockingEvent(aWebProgress, aRequest, aEvent) {
                info(`Got content blocking event for ${b.parentNode.id}: ${aEvent}`);
              },
              QueryInterface: ChromeUtils.generateQI([
                "nsIWebProgressListener",
                "nsISupportsWeakReference",
              ]),
            };
            b.addProgressListener(listener);
          });
          info(`Calling b.loadURI for ${b.parentNode.id}`);
          // Keep the listener alive, since it's a weak ref otherwise.
          window.ALIVE_LISTENER = listener;
          b.loadURI(null /*blank*/, { triggeringPrincipal });
          await loaded;
          delete window.ALIVE_LISTENER;
        }
      });
      async function getBrowserColorScheme(browser) {
        return SpecialPowers.spawn(browser, [], () => {
          return content.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
        });
      }
      async function tick() {
        return new Promise(resolve => {
          requestAnimationFrame(() => requestAnimationFrame(resolve));
        });
      }
      async function testElement(id, expectedIfTop, expectedIfNonTop) {
        let element = document.getElementById(id);
        for (let browser of element.querySelectorAll("browser")) {
          let scheme = await getBrowserColorScheme(browser);
          let expected = browser.browsingContext.top == browser.browsingContext ? expectedIfTop : expectedIfNonTop;
          is(scheme, expected, `${id}: ${browser.className} should be ${expected}`);
        }
      }
      add_task(async function test_browser_color_scheme() {
        let current = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
        for (let id of ["dynamic-test", "light", "dark"]) {
          let expected = id == "dynamic-test" ? current : id;
          await testElement(id, expected, expected);
        }
      });

      add_task(async function test_browser_color_scheme_dynamic_style() {
        let current = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
        let dynamicTest = document.getElementById("dynamic-test");
        for (let value of ["light", "dark"]) {
          await tick();
          dynamicTest.style.colorScheme = value;
          await testElement("dynamic-test", value, value);
        }
        dynamicTest.style.colorScheme = "";
        await tick();
      });

      add_task(async function test_browser_color_scheme_dynamic_system() {
        const ACTIVE_THEME_ID = Services.prefs.getCharPref("extensions.activeThemeID");
        const DEFAULT_THEME_ID = "default-theme@mozilla.org";
        if (ACTIVE_THEME_ID != DEFAULT_THEME_ID) {
          info(`skipping test_browser_color_scheme_dynamic_system because the active theme is ${ACTIVE_THEME_ID} instead of ${DEFAULT_THEME_ID}`);
          return;
        }
        for (let dark of [true, false]) {
          await SpecialPowers.pushPrefEnv({
            set: [
              ["layout.css.prefers-color-scheme.content-override", 2],
              ["ui.systemUsesDarkTheme", dark ? 1 : 0],
            ]
          });
          await tick();
          let expected = dark ? "dark" : "light";
          await testElement("dynamic-test", expected, expected);
          await SpecialPowers.popPrefEnv();
        }
      });
    ]]></script>
  </body>
</html>