/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ // Check that message persistence works - bug 705921 / bug 1307881 "use strict"; const TEST_FILE = "test-console.html"; const TEST_COM_URI = URL_ROOT_COM_SSL + TEST_FILE; const TEST_ORG_URI = URL_ROOT_ORG_SSL + TEST_FILE; // TEST_MOCHI_URI uses a non standart port and hence // is not subject to https-first mode const TEST_MOCHI_URI = URL_ROOT_MOCHI_8888 + TEST_FILE; registerCleanupFunction(() => { Services.prefs.clearUserPref("devtools.webconsole.persistlog"); }); const INITIAL_LOGS_NUMBER = 5; const { MESSAGE_TYPE, } = require("resource://devtools/client/webconsole/constants.js"); const { WILL_NAVIGATE_TIME_SHIFT, } = require("resource://devtools/server/actors/webconsole/listeners/document-events.js"); async function logAndAssertInitialMessages(hud) { await SpecialPowers.spawn( gBrowser.selectedBrowser, [INITIAL_LOGS_NUMBER], count => { content.wrappedJSObject.doLogs(count); } ); await waitFor(() => findAllMessages(hud).length === INITIAL_LOGS_NUMBER); ok(true, "Messages showed up initially"); } add_task(async function () { info("Testing that messages disappear on a refresh if logs aren't persisted"); const hud = await openNewTabAndConsole(TEST_COM_URI); await logAndAssertInitialMessages(hud); const onReloaded = hud.ui.once("reloaded"); await reloadBrowser(); await onReloaded; info("Wait for messages to be cleared"); await waitFor(() => findAllMessages(hud).length === 0); ok(true, "Messages disappeared"); await closeToolbox(); }); add_task(async function () { info( "Testing that messages disappear on a cross origin navigation if logs aren't persisted" ); const hud = await openNewTabAndConsole(TEST_COM_URI); await logAndAssertInitialMessages(hud); await navigateTo(TEST_ORG_URI); await waitFor(() => findAllMessages(hud).length === 0); ok(true, "Messages disappeared"); await closeToolbox(); }); add_task(async function () { info("Testing that messages disappear on bfcache navigations"); const firstLocation = "data:text/html,"; const secondLocation = "data:text/html,"; const hud = await openNewTabAndConsole(firstLocation); info("Wait for first page messages"); // Look into .message-body as the default selector also include the frame, // which is the document url, which also include the logged string... await waitFor( () => findMessagePartsByType(hud, { text: "first document load", typeSelector: ".console-api", partSelector: ".message-body", }).length === 1 && findMessagePartsByType(hud, { text: "first document show", typeSelector: ".console-api", partSelector: ".message-body", }).length === 1 ); const firstPageInnerWindowId = gBrowser.selectedBrowser.browsingContext.currentWindowGlobal.innerWindowId; await navigateTo(secondLocation); const secondPageInnerWindowId = gBrowser.selectedBrowser.browsingContext.currentWindowGlobal.innerWindowId; isnot( firstPageInnerWindowId, secondPageInnerWindowId, "The second page is having a distinct inner window id" ); await waitFor( () => findMessagePartsByType(hud, { text: "second", typeSelector: ".console-api", partSelector: ".message-body", }).length === 2 ); ok("Second page message appeared"); is( findMessagePartsByType(hud, { text: "first", typeSelector: ".console-api", partSelector: ".message-body", }).length, 0, "First page message disappeared" ); info("Go back to the first page"); gBrowser.selectedBrowser.goBack(); // When going pack, the page isn't reloaded, so that we only get the pageshow event await waitFor( () => findMessagePartsByType(hud, { text: "first document show", typeSelector: ".console-api", partSelector: ".message-body", }).length === 1 ); ok("First page message re-appeared"); is( gBrowser.selectedBrowser.browsingContext.currentWindowGlobal.innerWindowId, firstPageInnerWindowId, "The first page is really a bfcache navigation, keeping the same WindowGlobal" ); is( findMessagePartsByType(hud, { text: "second", typeSelector: ".console-api", partSelector: ".message-body", }).length, 0, "Second page message disappeared" ); info("Go forward to the original second page"); gBrowser.selectedBrowser.goForward(); await waitFor( () => findMessagePartsByType(hud, { text: "second document show", typeSelector: ".console-api", partSelector: ".message-body", }).length === 1 ); ok("Second page message appeared"); is( gBrowser.selectedBrowser.browsingContext.currentWindowGlobal.innerWindowId, secondPageInnerWindowId, "The second page is really a bfcache navigation, keeping the same WindowGlobal" ); is( findMessagePartsByType(hud, { text: "first", typeSelector: ".console-api", partSelector: ".message-body", }).length, 0, "First page message disappeared" ); await closeToolbox(); }); add_task(async function () { info("Testing that messages persist on a refresh if logs are persisted"); const hud = await openNewTabAndConsole(TEST_COM_URI); await toggleConsoleSetting( hud, ".webconsole-console-settings-menu-item-persistentLogs" ); await logAndAssertInitialMessages(hud); const onNavigatedMessage = waitForMessageByType( hud, "Navigated to " + TEST_COM_URI, ".navigationMarker" ); const onReloaded = hud.ui.once("reloaded"); // Because will-navigate DOCUMENT_EVENT timestamp is shifted to workaround some other limitation, // the reported time of navigation may actually be slightly off and be older than the real navigation start let timeBeforeNavigation = Date.now() - WILL_NAVIGATE_TIME_SHIFT; reloadBrowser(); await onNavigatedMessage; await onReloaded; ok(true, "Navigation message appeared as expected"); is( findAllMessages(hud).length, INITIAL_LOGS_NUMBER + 1, "Messages logged before navigation are still visible" ); assertLastMessageIsNavigationMessage(hud, timeBeforeNavigation, TEST_COM_URI); info( "Testing that messages also persist when doing a cross origin navigation if logs are persisted" ); const onNavigatedMessage2 = waitForMessageByType( hud, "Navigated to " + TEST_ORG_URI, ".navigationMarker" ); timeBeforeNavigation = Date.now() - WILL_NAVIGATE_TIME_SHIFT; await navigateTo(TEST_ORG_URI); await onNavigatedMessage2; ok(true, "Second navigation message appeared as expected"); is( findAllMessages(hud).length, INITIAL_LOGS_NUMBER + 2, "Messages logged before the second navigation are still visible" ); assertLastMessageIsNavigationMessage(hud, timeBeforeNavigation, TEST_ORG_URI); info( "Test doing a second cross origin navigation in order to triger a target switching with a target following the window global lifecycle" ); const onNavigatedMessage3 = waitForMessageByType( hud, "Navigated to " + TEST_MOCHI_URI, ".navigationMarker" ); timeBeforeNavigation = Date.now() - WILL_NAVIGATE_TIME_SHIFT; await navigateTo(TEST_MOCHI_URI); await onNavigatedMessage3; ok(true, "Third navigation message appeared as expected"); is( findAllMessages(hud).length, INITIAL_LOGS_NUMBER + 3, "Messages logged before the third navigation are still visible" ); assertLastMessageIsNavigationMessage( hud, timeBeforeNavigation, TEST_MOCHI_URI ); await closeToolbox(); }); function assertLastMessageIsNavigationMessage(hud, timeBeforeNavigation, url) { const { visibleMessages, mutableMessagesById } = hud.ui.wrapper .getStore() .getState().messages; const lastMessageId = visibleMessages.at(-1); const lastMessage = mutableMessagesById.get(lastMessageId); is( lastMessage.type, MESSAGE_TYPE.NAVIGATION_MARKER, "The last message is a navigation marker" ); is( lastMessage.messageText, "Navigated to " + url, "The navigation message is correct" ); // It is surprising, but the navigation may be timestamped at the same exact time // as timeBeforeNavigation time record. ok( lastMessage.timeStamp >= timeBeforeNavigation, "The navigation message has a timestamp newer (or equal) than the time before the navigation..." ); ok(lastMessage.timeStamp < Date.now(), "...and older than current time"); }