summaryrefslogtreecommitdiffstats
path: root/devtools/client/framework/browser-toolbox/test/browser_browser_toolbox_evaluation_context.js
blob: 34e18d15c5e3433f23c88102ef7b579b141de00a (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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

// There are shutdown issues for which multiple rejections are left uncaught.
// See bug 1018184 for resolving these issues.
const { PromiseTestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/PromiseTestUtils.sys.mjs"
);
PromiseTestUtils.allowMatchingRejectionsGlobally(/File closed/);

// On debug test machine, it takes about 50s to run the test.
requestLongerTimeout(4);

// This test is used to test fission-like features via the Browser Toolbox:
// - the evaluation context selector in the console show the right targets
// - the iframe dropdown also show the right targets
// - both are updated accordingly when toggle to parent-process only scope

add_task(async function () {
  // Forces the Browser Toolbox to open on the console by default
  await pushPref("devtools.browsertoolbox.panel", "webconsole");
  await pushPref("devtools.webconsole.input.context", true);
  // Force EFT to have targets for all WindowGlobals
  await pushPref("devtools.every-frame-target.enabled", true);
  // Enable Multiprocess Browser Toolbox
  await pushPref("devtools.browsertoolbox.scope", "everything");

  // Open the test *before* opening the Browser toolbox in order to have the right target title.
  // Once created, the target won't update its title, and so would be "New Tab", instead of "Test tab"
  const tab = await addTab(
    "https://example.com/document-builder.sjs?html=<html><title>Test tab</title></html>"
  );

  const ToolboxTask = await initBrowserToolboxTask();

  await ToolboxTask.importFunctions({
    waitUntil,
    getContextLabels,
    getFramesLabels,
  });

  const tabProcessID =
    tab.linkedBrowser.browsingContext.currentWindowGlobal.osPid;

  const decodedTabURI = decodeURI(tab.linkedBrowser.currentURI.spec);

  await ToolboxTask.spawn(
    [tabProcessID, isFissionEnabled(), decodedTabURI],
    async (processID, _isFissionEnabled, tabURI) => {
      /* global gToolbox */
      const { hud } = await gToolbox.getPanel("webconsole");

      const evaluationContextSelectorButton = hud.ui.outputNode.querySelector(
        ".webconsole-evaluation-selector-button"
      );

      is(
        !!evaluationContextSelectorButton,
        true,
        "The evaluation context selector is visible"
      );
      is(
        evaluationContextSelectorButton.innerText,
        "Top",
        "The button has the expected 'Top' text"
      );

      const labelTexts = getContextLabels(gToolbox);

      const expectedTitle = _isFissionEnabled
        ? `(pid ${processID}) https://example.com`
        : `(pid ${processID}) web`;
      ok(
        labelTexts.includes(expectedTitle),
        `${processID} content process visible in the execution context (${labelTexts})`
      );

      ok(
        labelTexts.includes(`Test tab`),
        `Test tab is visible in the execution context (${labelTexts})`
      );

      // Also assert the behavior of the iframe dropdown and the mode selector
      info("Check the iframe dropdown, start by opening it");
      const btn = gToolbox.doc.getElementById("command-button-frames");
      btn.click();

      const panel = gToolbox.doc.getElementById("command-button-frames-panel");
      ok(panel, "popup panel has created.");
      await waitUntil(
        () => panel.classList.contains("tooltip-visible"),
        "Wait for the menu to be displayed"
      );

      is(
        getFramesLabels(gToolbox)[0],
        "chrome://browser/content/browser.xhtml",
        "The iframe dropdown lists first browser.xhtml, running in the parent process"
      );
      ok(
        getFramesLabels(gToolbox).includes(tabURI),
        "The iframe dropdown lists the tab document, running in the content process"
      );

      // Click on top frame to hide the iframe picker, so clicks on other elements can be registered.
      gToolbox.doc.querySelector("#toolbox-frame-menu .command").click();

      await waitUntil(
        () => !panel.classList.contains("tooltip-visible"),
        "Wait for the menu to be hidden"
      );

      info("Check that the ChromeDebugToolbar is displayed");
      const chromeDebugToolbar = gToolbox.doc.querySelector(
        ".chrome-debug-toolbar"
      );
      ok(!!chromeDebugToolbar, "ChromeDebugToolbar is displayed");
      const chromeDebugToolbarScopeInputs = Array.from(
        chromeDebugToolbar.querySelectorAll(`[name="chrome-debug-mode"]`)
      );
      is(
        chromeDebugToolbarScopeInputs.length,
        2,
        "There are 2 mode inputs in the chromeDebugToolbar"
      );
      const [
        chromeDebugToolbarParentProcessModeInput,
        chromeDebugToolbarMultiprocessModeInput,
      ] = chromeDebugToolbarScopeInputs;
      is(
        chromeDebugToolbarParentProcessModeInput.value,
        "parent-process",
        "Got expected value for the first input"
      );
      is(
        chromeDebugToolbarMultiprocessModeInput.value,
        "everything",
        "Got expected value for the second input"
      );
      ok(
        chromeDebugToolbarMultiprocessModeInput.checked,
        "The multiprocess mode is selected"
      );

      info(
        "Click on the parent-process input and check that it restricts the targets"
      );
      chromeDebugToolbarParentProcessModeInput.click();
      info("Wait for the iframe dropdown to hide the tab target");
      await waitUntil(() => {
        return !getFramesLabels(gToolbox).includes(tabURI);
      });

      info("Wait for the context selector to hide the tab context");
      await waitUntil(() => {
        return !getContextLabels(gToolbox).includes(`Test tab`);
      });

      ok(
        !chromeDebugToolbarMultiprocessModeInput.checked,
        "Now, the multiprocess mode is disabled…"
      );
      ok(
        chromeDebugToolbarParentProcessModeInput.checked,
        "…and the parent process mode is enabled"
      );

      info("Switch back to multiprocess mode");
      chromeDebugToolbarMultiprocessModeInput.click();

      info("Wait for the iframe dropdown to show again the tab target");
      await waitUntil(() => {
        return getFramesLabels(gToolbox).includes(tabURI);
      });

      info("Wait for the context selector to show again the tab context");
      await waitUntil(() => {
        return getContextLabels(gToolbox).includes(`Test tab`);
      });
    }
  );

  await ToolboxTask.destroy();
});

function getContextLabels(toolbox) {
  // Note that the context menu is in the top level chrome document (toolbox.xhtml)
  // instead of webconsole.xhtml.
  const labels = toolbox.doc.querySelectorAll(
    "#webconsole-console-evaluation-context-selector-menu-list li .label"
  );
  return Array.from(labels).map(item => item.textContent);
}

function getFramesLabels(toolbox) {
  return Array.from(
    toolbox.doc.querySelectorAll("#toolbox-frame-menu .command .label")
  ).map(el => el.textContent);
}