summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/tabs/head.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/test/tabs/head.js')
-rw-r--r--browser/base/content/test/tabs/head.js564
1 files changed, 564 insertions, 0 deletions
diff --git a/browser/base/content/test/tabs/head.js b/browser/base/content/test/tabs/head.js
new file mode 100644
index 0000000000..abd6c060f7
--- /dev/null
+++ b/browser/base/content/test/tabs/head.js
@@ -0,0 +1,564 @@
+function updateTabContextMenu(tab) {
+ let menu = document.getElementById("tabContextMenu");
+ if (!tab) {
+ tab = gBrowser.selectedTab;
+ }
+ var evt = new Event("");
+ tab.dispatchEvent(evt);
+ menu.openPopup(tab, "end_after", 0, 0, true, false, evt);
+ is(
+ window.TabContextMenu.contextTab,
+ tab,
+ "TabContextMenu context is the expected tab"
+ );
+ menu.hidePopup();
+}
+
+function triggerClickOn(target, options) {
+ let promise = BrowserTestUtils.waitForEvent(target, "click");
+ if (AppConstants.platform == "macosx") {
+ options = {
+ metaKey: options.ctrlKey,
+ shiftKey: options.shiftKey,
+ };
+ }
+ EventUtils.synthesizeMouseAtCenter(target, options);
+ return promise;
+}
+
+function triggerMiddleClickOn(target) {
+ let promise = BrowserTestUtils.waitForEvent(target, "click");
+ EventUtils.synthesizeMouseAtCenter(target, { button: 1 });
+ return promise;
+}
+
+async function addTab(url = "http://mochi.test:8888/", params) {
+ return addTabTo(gBrowser, url, params);
+}
+
+async function addTabTo(
+ targetBrowser,
+ url = "http://mochi.test:8888/",
+ params = {}
+) {
+ params.skipAnimation = true;
+ const tab = BrowserTestUtils.addTab(targetBrowser, url, params);
+ const browser = targetBrowser.getBrowserForTab(tab);
+ await BrowserTestUtils.browserLoaded(browser);
+ return tab;
+}
+
+async function addMediaTab() {
+ const PAGE =
+ "https://example.com/browser/browser/base/content/test/tabs/file_mediaPlayback.html";
+ const tab = BrowserTestUtils.addTab(gBrowser, PAGE, { skipAnimation: true });
+ const browser = gBrowser.getBrowserForTab(tab);
+ await BrowserTestUtils.browserLoaded(browser);
+ return tab;
+}
+
+function muted(tab) {
+ return tab.linkedBrowser.audioMuted;
+}
+
+function activeMediaBlocked(tab) {
+ return tab.activeMediaBlocked;
+}
+
+async function toggleMuteAudio(tab, expectMuted) {
+ let mutedPromise = get_wait_for_mute_promise(tab, expectMuted);
+ tab.toggleMuteAudio();
+ await mutedPromise;
+}
+
+async function pressIcon(icon) {
+ let tooltip = document.getElementById("tabbrowser-tab-tooltip");
+ await hover_icon(icon, tooltip);
+ EventUtils.synthesizeMouseAtCenter(icon, { button: 0 });
+ leave_icon(icon);
+}
+
+async function wait_for_tab_playing_event(tab, expectPlaying) {
+ if (tab.soundPlaying == expectPlaying) {
+ ok(true, "The tab should " + (expectPlaying ? "" : "not ") + "be playing");
+ return true;
+ }
+ return BrowserTestUtils.waitForEvent(tab, "TabAttrModified", false, event => {
+ if (event.detail.changed.includes("soundplaying")) {
+ is(
+ tab.hasAttribute("soundplaying"),
+ expectPlaying,
+ "The tab should " + (expectPlaying ? "" : "not ") + "be playing"
+ );
+ is(
+ tab.soundPlaying,
+ expectPlaying,
+ "The tab should " + (expectPlaying ? "" : "not ") + "be playing"
+ );
+ return true;
+ }
+ return false;
+ });
+}
+
+async function wait_for_tab_media_blocked_event(tab, expectMediaBlocked) {
+ if (tab.activeMediaBlocked == expectMediaBlocked) {
+ ok(
+ true,
+ "The tab should " +
+ (expectMediaBlocked ? "" : "not ") +
+ "be activemedia-blocked"
+ );
+ return true;
+ }
+ return BrowserTestUtils.waitForEvent(tab, "TabAttrModified", false, event => {
+ if (event.detail.changed.includes("activemedia-blocked")) {
+ is(
+ tab.hasAttribute("activemedia-blocked"),
+ expectMediaBlocked,
+ "The tab should " +
+ (expectMediaBlocked ? "" : "not ") +
+ "be activemedia-blocked"
+ );
+ is(
+ tab.activeMediaBlocked,
+ expectMediaBlocked,
+ "The tab should " +
+ (expectMediaBlocked ? "" : "not ") +
+ "be activemedia-blocked"
+ );
+ return true;
+ }
+ return false;
+ });
+}
+
+async function is_audio_playing(tab) {
+ let browser = tab.linkedBrowser;
+ let isPlaying = await SpecialPowers.spawn(browser, [], async function () {
+ let audio = content.document.querySelector("audio");
+ return !audio.paused;
+ });
+ return isPlaying;
+}
+
+async function play(tab, expectPlaying = true) {
+ let browser = tab.linkedBrowser;
+ await SpecialPowers.spawn(browser, [], async function () {
+ let audio = content.document.querySelector("audio");
+ audio.play();
+ });
+
+ // If the tab has already been muted, it means the tab won't get soundplaying,
+ // so we don't need to check this attribute.
+ if (browser.audioMuted) {
+ return;
+ }
+
+ if (expectPlaying) {
+ await wait_for_tab_playing_event(tab, true);
+ } else {
+ await wait_for_tab_media_blocked_event(tab, true);
+ }
+}
+
+function disable_non_test_mouse(disable) {
+ let utils = window.windowUtils;
+ utils.disableNonTestMouseEvents(disable);
+}
+
+function hover_icon(icon, tooltip) {
+ disable_non_test_mouse(true);
+
+ let popupShownPromise = BrowserTestUtils.waitForEvent(tooltip, "popupshown");
+ EventUtils.synthesizeMouse(icon, 1, 1, { type: "mouseover" });
+ EventUtils.synthesizeMouse(icon, 2, 2, { type: "mousemove" });
+ EventUtils.synthesizeMouse(icon, 3, 3, { type: "mousemove" });
+ EventUtils.synthesizeMouse(icon, 4, 4, { type: "mousemove" });
+ return popupShownPromise;
+}
+
+function leave_icon(icon) {
+ EventUtils.synthesizeMouse(icon, 0, 0, { type: "mouseout" });
+ EventUtils.synthesizeMouseAtCenter(document.documentElement, {
+ type: "mousemove",
+ });
+ EventUtils.synthesizeMouseAtCenter(document.documentElement, {
+ type: "mousemove",
+ });
+ EventUtils.synthesizeMouseAtCenter(document.documentElement, {
+ type: "mousemove",
+ });
+
+ disable_non_test_mouse(false);
+}
+
+// The set of tabs which have ever had their mute state changed.
+// Used to determine whether the tab should have a muteReason value.
+let everMutedTabs = new WeakSet();
+
+function get_wait_for_mute_promise(tab, expectMuted) {
+ return BrowserTestUtils.waitForEvent(tab, "TabAttrModified", false, event => {
+ if (
+ event.detail.changed.includes("muted") ||
+ event.detail.changed.includes("activemedia-blocked")
+ ) {
+ is(
+ tab.hasAttribute("muted"),
+ expectMuted,
+ "The tab should " + (expectMuted ? "" : "not ") + "be muted"
+ );
+ is(
+ tab.muted,
+ expectMuted,
+ "The tab muted property " + (expectMuted ? "" : "not ") + "be true"
+ );
+
+ if (expectMuted || everMutedTabs.has(tab)) {
+ everMutedTabs.add(tab);
+ is(tab.muteReason, null, "The tab should have a null muteReason value");
+ } else {
+ is(
+ tab.muteReason,
+ undefined,
+ "The tab should have an undefined muteReason value"
+ );
+ }
+ return true;
+ }
+ return false;
+ });
+}
+
+async function test_mute_tab(tab, icon, expectMuted) {
+ let mutedPromise = get_wait_for_mute_promise(tab, expectMuted);
+
+ let activeTab = gBrowser.selectedTab;
+
+ let tooltip = document.getElementById("tabbrowser-tab-tooltip");
+
+ await hover_icon(icon, tooltip);
+ EventUtils.synthesizeMouseAtCenter(icon, { button: 0 });
+ leave_icon(icon);
+
+ is(
+ gBrowser.selectedTab,
+ activeTab,
+ "Clicking on mute should not change the currently selected tab"
+ );
+
+ // If the audio is playing, we should check whether clicking on icon affects
+ // the media element's playing state.
+ let isAudioPlaying = await is_audio_playing(tab);
+ if (isAudioPlaying) {
+ await wait_for_tab_playing_event(tab, !expectMuted);
+ }
+
+ return mutedPromise;
+}
+
+async function dragAndDrop(
+ tab1,
+ tab2,
+ copy,
+ destWindow = window,
+ afterTab = true
+) {
+ let rect = tab2.getBoundingClientRect();
+ let event = {
+ ctrlKey: copy,
+ altKey: copy,
+ clientX: rect.left + rect.width / 2 + 10 * (afterTab ? 1 : -1),
+ clientY: rect.top + rect.height / 2,
+ };
+
+ if (destWindow != window) {
+ // Make sure that both tab1 and tab2 are visible
+ window.focus();
+ window.moveTo(rect.left, rect.top + rect.height * 3);
+ }
+
+ let originalTPos = tab1._tPos;
+ EventUtils.synthesizeDrop(
+ tab1,
+ tab2,
+ null,
+ copy ? "copy" : "move",
+ window,
+ destWindow,
+ event
+ );
+ // Ensure dnd suppression is cleared.
+ EventUtils.synthesizeMouseAtCenter(tab2, { type: "mouseup" }, destWindow);
+ if (!copy && destWindow == window) {
+ await BrowserTestUtils.waitForCondition(
+ () => tab1._tPos != originalTPos,
+ "Waiting for tab position to be updated"
+ );
+ } else if (destWindow != window) {
+ await BrowserTestUtils.waitForCondition(
+ () => tab1.closing,
+ "Waiting for tab closing"
+ );
+ }
+}
+
+function getUrl(tab) {
+ return tab.linkedBrowser.currentURI.spec;
+}
+
+/**
+ * Takes a xul:browser and makes sure that the remoteTypes for the browser in
+ * both the parent and the child processes are the same.
+ *
+ * @param {xul:browser} browser
+ * A xul:browser.
+ * @param {string} expectedRemoteType
+ * The expected remoteType value for the browser in both the parent
+ * and child processes.
+ * @param {optional string} message
+ * If provided, shows this string as the message when remoteType values
+ * do not match. If not present, it uses the default message defined
+ * in the function parameters.
+ */
+function checkBrowserRemoteType(
+ browser,
+ expectedRemoteType,
+ message = `Ensures that tab runs in the ${expectedRemoteType} content process.`
+) {
+ // Check both parent and child to ensure that they have the correct remoteType.
+ if (expectedRemoteType == E10SUtils.WEB_REMOTE_TYPE) {
+ ok(E10SUtils.isWebRemoteType(browser.remoteType), message);
+ ok(
+ E10SUtils.isWebRemoteType(browser.messageManager.remoteType),
+ "Parent and child process should agree on the remote type."
+ );
+ } else {
+ is(browser.remoteType, expectedRemoteType, message);
+ is(
+ browser.messageManager.remoteType,
+ expectedRemoteType,
+ "Parent and child process should agree on the remote type."
+ );
+ }
+}
+
+function test_url_for_process_types({
+ url,
+ chromeResult,
+ webContentResult,
+ privilegedAboutContentResult,
+ privilegedMozillaContentResult,
+ extensionProcessResult,
+}) {
+ const CHROME_PROCESS = E10SUtils.NOT_REMOTE;
+ const WEB_CONTENT_PROCESS = E10SUtils.WEB_REMOTE_TYPE;
+ const PRIVILEGEDABOUT_CONTENT_PROCESS = E10SUtils.PRIVILEGEDABOUT_REMOTE_TYPE;
+ const PRIVILEGEDMOZILLA_CONTENT_PROCESS =
+ E10SUtils.PRIVILEGEDMOZILLA_REMOTE_TYPE;
+ const EXTENSION_PROCESS = E10SUtils.EXTENSION_REMOTE_TYPE;
+
+ is(
+ E10SUtils.canLoadURIInRemoteType(url, /* fission */ false, CHROME_PROCESS),
+ chromeResult,
+ "Check URL in chrome process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url,
+ /* fission */ false,
+ WEB_CONTENT_PROCESS
+ ),
+ webContentResult,
+ "Check URL in web content process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url,
+ /* fission */ false,
+ PRIVILEGEDABOUT_CONTENT_PROCESS
+ ),
+ privilegedAboutContentResult,
+ "Check URL in privileged about content process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url,
+ /* fission */ false,
+ PRIVILEGEDMOZILLA_CONTENT_PROCESS
+ ),
+ privilegedMozillaContentResult,
+ "Check URL in privileged mozilla content process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url,
+ /* fission */ false,
+ EXTENSION_PROCESS
+ ),
+ extensionProcessResult,
+ "Check URL in extension process."
+ );
+
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "#foo",
+ /* fission */ false,
+ CHROME_PROCESS
+ ),
+ chromeResult,
+ "Check URL with ref in chrome process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "#foo",
+ /* fission */ false,
+ WEB_CONTENT_PROCESS
+ ),
+ webContentResult,
+ "Check URL with ref in web content process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "#foo",
+ /* fission */ false,
+ PRIVILEGEDABOUT_CONTENT_PROCESS
+ ),
+ privilegedAboutContentResult,
+ "Check URL with ref in privileged about content process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "#foo",
+ /* fission */ false,
+ PRIVILEGEDMOZILLA_CONTENT_PROCESS
+ ),
+ privilegedMozillaContentResult,
+ "Check URL with ref in privileged mozilla content process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "#foo",
+ /* fission */ false,
+ EXTENSION_PROCESS
+ ),
+ extensionProcessResult,
+ "Check URL with ref in extension process."
+ );
+
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "?foo",
+ /* fission */ false,
+ CHROME_PROCESS
+ ),
+ chromeResult,
+ "Check URL with query in chrome process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "?foo",
+ /* fission */ false,
+ WEB_CONTENT_PROCESS
+ ),
+ webContentResult,
+ "Check URL with query in web content process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "?foo",
+ /* fission */ false,
+ PRIVILEGEDABOUT_CONTENT_PROCESS
+ ),
+ privilegedAboutContentResult,
+ "Check URL with query in privileged about content process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "?foo",
+ /* fission */ false,
+ PRIVILEGEDMOZILLA_CONTENT_PROCESS
+ ),
+ privilegedMozillaContentResult,
+ "Check URL with query in privileged mozilla content process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "?foo",
+ /* fission */ false,
+ EXTENSION_PROCESS
+ ),
+ extensionProcessResult,
+ "Check URL with query in extension process."
+ );
+
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "?foo#bar",
+ /* fission */ false,
+ CHROME_PROCESS
+ ),
+ chromeResult,
+ "Check URL with query and ref in chrome process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "?foo#bar",
+ /* fission */ false,
+ WEB_CONTENT_PROCESS
+ ),
+ webContentResult,
+ "Check URL with query and ref in web content process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "?foo#bar",
+ /* fission */ false,
+ PRIVILEGEDABOUT_CONTENT_PROCESS
+ ),
+ privilegedAboutContentResult,
+ "Check URL with query and ref in privileged about content process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "?foo#bar",
+ /* fission */ false,
+ PRIVILEGEDMOZILLA_CONTENT_PROCESS
+ ),
+ privilegedMozillaContentResult,
+ "Check URL with query and ref in privileged mozilla content process."
+ );
+ is(
+ E10SUtils.canLoadURIInRemoteType(
+ url + "?foo#bar",
+ /* fission */ false,
+ EXTENSION_PROCESS
+ ),
+ extensionProcessResult,
+ "Check URL with query and ref in extension process."
+ );
+}
+
+/*
+ * Get a file URL for the local file name.
+ */
+function fileURL(filename) {
+ let ifile = getChromeDir(getResolvedURI(gTestPath));
+ ifile.append(filename);
+ return Services.io.newFileURI(ifile).spec;
+}
+
+/*
+ * Get a http URL for the local file name.
+ */
+function httpURL(filename, host = "https://example.com/") {
+ let root = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content/",
+ host
+ );
+ return root + filename;
+}
+
+function loadTestSubscript(filePath) {
+ Services.scriptloader.loadSubScript(new URL(filePath, gTestPath).href, this);
+}