summaryrefslogtreecommitdiffstats
path: root/toolkit/components/aboutwindowsmessages
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/aboutwindowsmessages')
-rw-r--r--toolkit/components/aboutwindowsmessages/AboutWindowsMessages.cpp93
-rw-r--r--toolkit/components/aboutwindowsmessages/AboutWindowsMessages.h29
-rw-r--r--toolkit/components/aboutwindowsmessages/components.conf17
-rw-r--r--toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.css15
-rw-r--r--toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.html42
-rw-r--r--toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.js70
-rw-r--r--toolkit/components/aboutwindowsmessages/jar.mn8
-rw-r--r--toolkit/components/aboutwindowsmessages/moz.build24
-rw-r--r--toolkit/components/aboutwindowsmessages/nsIAboutWindowsMessages.idl14
-rw-r--r--toolkit/components/aboutwindowsmessages/tests/browser/browser.toml3
-rw-r--r--toolkit/components/aboutwindowsmessages/tests/browser/browser_aboutwindowsmessages.js85
11 files changed, 400 insertions, 0 deletions
diff --git a/toolkit/components/aboutwindowsmessages/AboutWindowsMessages.cpp b/toolkit/components/aboutwindowsmessages/AboutWindowsMessages.cpp
new file mode 100644
index 0000000000..86308dfe13
--- /dev/null
+++ b/toolkit/components/aboutwindowsmessages/AboutWindowsMessages.cpp
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "AboutWindowsMessages.h"
+
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/StaticPtr.h"
+#include "nsThreadUtils.h"
+#include "nsPIDOMWindow.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIWindowMediator.h"
+#include "nsIAppWindow.h"
+#include "nsIBaseWindow.h"
+#include "nsIDocShell.h"
+#include "nsDocShellTreeOwner.h"
+#include "mozilla/WidgetUtils.h"
+#include "mozilla/widget/nsWindowLoggedMessages.h"
+
+namespace mozilla {
+
+static StaticRefPtr<AboutWindowsMessages> sSingleton;
+
+NS_IMPL_ISUPPORTS(AboutWindowsMessages, nsIAboutWindowsMessages);
+
+/*static*/
+already_AddRefed<AboutWindowsMessages> AboutWindowsMessages::GetSingleton() {
+ if (!sSingleton) {
+ sSingleton = new AboutWindowsMessages;
+ ClearOnShutdown(&sSingleton);
+ }
+
+ return do_AddRef(sSingleton);
+}
+
+static bool GetWindowTitleFromWindow(const nsCOMPtr<nsPIDOMWindowOuter>& window,
+ nsAutoString& title) {
+ nsIDocShell* docShell = window->GetDocShell();
+ if (docShell) {
+ nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
+ docShell->GetTreeOwner(getter_AddRefs(parentTreeOwner));
+ nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(parentTreeOwner));
+ baseWindow->GetTitle(title);
+ return true;
+ }
+ return false;
+}
+
+NS_IMETHODIMP
+AboutWindowsMessages::GetMessages(mozIDOMWindowProxy* currentWindow,
+ nsTArray<nsTArray<nsCString>>& messages,
+ nsTArray<nsString>& windowTitles) {
+ messages.Clear();
+ // Display the current window's messages first
+ auto currentWindowOuter = nsPIDOMWindowOuter::From(currentWindow);
+ RefPtr<nsIWidget> currentWidget =
+ widget::WidgetUtils::DOMWindowToWidget(currentWindowOuter);
+ nsAutoString currentWindowTitle;
+ if (GetWindowTitleFromWindow(currentWindowOuter, currentWindowTitle)) {
+ nsTArray<nsCString> windowMessages;
+ widget::GetLatestWindowMessages(currentWidget, windowMessages);
+ windowTitles.AppendElement(currentWindowTitle);
+ messages.EmplaceBack(std::move(windowMessages));
+ }
+ nsCOMPtr<nsIWindowMediator> mediator(
+ do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
+ nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
+ mediator->GetEnumerator(nullptr, getter_AddRefs(windowEnumerator));
+ if (!windowEnumerator) return NS_ERROR_FAILURE;
+ bool more;
+ while (NS_SUCCEEDED(windowEnumerator->HasMoreElements(&more)) && more) {
+ nsCOMPtr<nsISupports> isupports;
+ if (NS_FAILED(windowEnumerator->GetNext(getter_AddRefs(isupports)))) break;
+ nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(isupports);
+ NS_ASSERTION(window, "not an nsPIDOMWindowOuter");
+ RefPtr<nsIWidget> windowWidget =
+ widget::WidgetUtils::DOMWindowToWidget(window);
+ if (&*windowWidget != &*currentWidget) {
+ nsAutoString title;
+ if (GetWindowTitleFromWindow(window, title)) {
+ nsTArray<nsCString> windowMessages;
+ widget::GetLatestWindowMessages(windowWidget, windowMessages);
+ windowTitles.AppendElement(title);
+ messages.EmplaceBack(std::move(windowMessages));
+ }
+ }
+ }
+ return NS_OK;
+}
+} // namespace mozilla
diff --git a/toolkit/components/aboutwindowsmessages/AboutWindowsMessages.h b/toolkit/components/aboutwindowsmessages/AboutWindowsMessages.h
new file mode 100644
index 0000000000..c236bbcd30
--- /dev/null
+++ b/toolkit/components/aboutwindowsmessages/AboutWindowsMessages.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __AboutWindowsMessages_h__
+#define __AboutWindowsMessages_h__
+
+#include "mozilla/MozPromise.h"
+#include "nsIAboutWindowsMessages.h"
+
+namespace mozilla {
+
+class AboutWindowsMessages final : public nsIAboutWindowsMessages {
+ ~AboutWindowsMessages() = default;
+
+ public:
+ static already_AddRefed<AboutWindowsMessages> GetSingleton();
+
+ AboutWindowsMessages() = default;
+
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIABOUTWINDOWSMESSAGES
+};
+
+} // namespace mozilla
+
+#endif // __AboutWindowsMessages_h__
diff --git a/toolkit/components/aboutwindowsmessages/components.conf b/toolkit/components/aboutwindowsmessages/components.conf
new file mode 100644
index 0000000000..52e9b12abe
--- /dev/null
+++ b/toolkit/components/aboutwindowsmessages/components.conf
@@ -0,0 +1,17 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+Classes = [
+ {
+ 'cid': '{ba8cdb8a-9624-493d-aac4-23ee83378d7c}',
+ 'contract_ids': ['@mozilla.org/about-windowsmessages;1'],
+ 'type': 'AboutWindowsMessages',
+ 'singleton': True,
+ 'constructor': 'mozilla::AboutWindowsMessages::GetSingleton',
+ 'headers': ['mozilla/AboutWindowsMessages.h'],
+ 'processes': ProcessSelector.MAIN_PROCESS_ONLY,
+ },
+] \ No newline at end of file
diff --git a/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.css b/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.css
new file mode 100644
index 0000000000..de29761cc6
--- /dev/null
+++ b/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.css
@@ -0,0 +1,15 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+.card {
+ margin-bottom: 16px;
+}
+
+.window-card-title {
+ display: inline;
+}
+
+.window-card-title:not(.current-window) {
+ font-weight: normal;
+}
diff --git a/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.html b/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.html
new file mode 100644
index 0000000000..5c3145baf2
--- /dev/null
+++ b/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.html
@@ -0,0 +1,42 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE html>
+
+<html>
+ <head>
+ <title data-l10n-id="windows-messages-page-title"></title>
+ <meta
+ http-equiv="Content-Security-Policy"
+ content="default-src chrome:; object-src 'none'"
+ />
+ <meta name="color-scheme" content="light dark" />
+ <link
+ rel="stylesheet"
+ href="chrome://global/skin/in-content/info-pages.css"
+ />
+ <link
+ rel="stylesheet"
+ href="chrome://global/content/aboutWindowsMessages.css"
+ />
+ <link rel="localization" href="branding/brand.ftl" />
+ <link rel="localization" href="toolkit/about/aboutWindowsMessages.ftl" />
+ <script src="chrome://global/content/aboutWindowsMessages.js"></script>
+ </head>
+
+ <body class="wide-container">
+ <h1 data-l10n-id="windows-messages-page-title"></h1>
+ <p data-l10n-id="windows-messages-intro"></p>
+ <div id="windows-div"></div>
+
+ <template name="window-card">
+ <details class="card">
+ <summary>
+ <h3 class="window-card-title"></h3>
+ <button data-l10n-id="windows-messages-copy-to-clipboard"></button>
+ </summary>
+ </details>
+ </template>
+ </body>
+</html>
diff --git a/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.js b/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.js
new file mode 100644
index 0000000000..0896ae7669
--- /dev/null
+++ b/toolkit/components/aboutwindowsmessages/content/aboutWindowsMessages.js
@@ -0,0 +1,70 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+let AboutWindowsMessages = null;
+
+function refreshMessages() {
+ let windowMessages = {};
+ let windowTitles = {};
+ AboutWindowsMessages.getMessages(window, windowMessages, windowTitles);
+ let windowsDiv = document.getElementById("windows-div");
+ windowsDiv.innerHTML = "";
+ const templateCard = document.querySelector("template[name=window-card]");
+ for (let i = 0; i < windowTitles.value.length; ++i) {
+ let windowCard = templateCard.content
+ .cloneNode(true)
+ .querySelector("details");
+ // open the current window by default
+ windowCard.open = i === 0;
+ let summary = windowCard.querySelector("summary");
+ let titleSpan = summary.querySelector("h3.window-card-title");
+ titleSpan.appendChild(document.createTextNode(windowTitles.value[i]));
+ titleSpan.classList.toggle("current-window", windowCard.open);
+ let copyButton = summary.querySelector("button");
+ copyButton.addEventListener("click", async e => {
+ e.target.disabled = true;
+ await copyMessagesToClipboard(e);
+ e.target.disabled = false;
+ });
+ let innerUl = document.createElement("ul");
+ for (let j = 0; j < windowMessages.value[i].length; ++j) {
+ let innerLi = document.createElement("li");
+ innerLi.className = "message";
+ innerLi.innerText = windowMessages.value[i][j];
+ innerUl.appendChild(innerLi);
+ }
+ windowCard.appendChild(innerUl);
+ windowsDiv.append(windowCard);
+ }
+}
+
+async function copyMessagesToClipboard(event) {
+ const details = event.target.parentElement.parentElement;
+ // Avoid copying the window name as it is Category 3 data,
+ // and only useful for the user to identify which window
+ // is which.
+ const messagesText =
+ Array.from(details.querySelector("ul").children)
+ .map(li => li.innerText)
+ .join("\n") + "\n";
+
+ await navigator.clipboard.writeText(messagesText);
+}
+
+function onLoad() {
+ refreshMessages();
+}
+
+try {
+ AboutWindowsMessages = Cc["@mozilla.org/about-windowsmessages;1"].getService(
+ Ci.nsIAboutWindowsMessages
+ );
+ document.addEventListener("DOMContentLoaded", onLoad, { once: true });
+} catch (ex) {
+ // Do nothing if we fail to create a singleton instance,
+ // showing the default no-module message.
+ console.error(ex);
+}
diff --git a/toolkit/components/aboutwindowsmessages/jar.mn b/toolkit/components/aboutwindowsmessages/jar.mn
new file mode 100644
index 0000000000..c1d4f2b4f7
--- /dev/null
+++ b/toolkit/components/aboutwindowsmessages/jar.mn
@@ -0,0 +1,8 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+toolkit.jar:
+ content/global/aboutWindowsMessages.css (content/aboutWindowsMessages.css)
+ content/global/aboutWindowsMessages.html (content/aboutWindowsMessages.html)
+ content/global/aboutWindowsMessages.js (content/aboutWindowsMessages.js)
diff --git a/toolkit/components/aboutwindowsmessages/moz.build b/toolkit/components/aboutwindowsmessages/moz.build
new file mode 100644
index 0000000000..5827cca885
--- /dev/null
+++ b/toolkit/components/aboutwindowsmessages/moz.build
@@ -0,0 +1,24 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "Widget: Win32")
+
+FINAL_LIBRARY = "xul"
+
+BROWSER_CHROME_MANIFESTS += ["tests/browser/browser.toml"]
+JAR_MANIFESTS += ["jar.mn"]
+XPCOM_MANIFESTS += ["components.conf"]
+XPIDL_MODULE = "AboutWindowsMessages"
+XPIDL_SOURCES += ["nsIAboutWindowsMessages.idl"]
+
+EXPORTS.mozilla += [
+ "AboutWindowsMessages.h",
+]
+
+SOURCES += [
+ "AboutWindowsMessages.cpp",
+]
diff --git a/toolkit/components/aboutwindowsmessages/nsIAboutWindowsMessages.idl b/toolkit/components/aboutwindowsmessages/nsIAboutWindowsMessages.idl
new file mode 100644
index 0000000000..d240a9233a
--- /dev/null
+++ b/toolkit/components/aboutwindowsmessages/nsIAboutWindowsMessages.idl
@@ -0,0 +1,14 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+interface mozIDOMWindowProxy;
+
+[scriptable, uuid(3c5cfbfd-545c-4910-a34a-203063914f96)]
+interface nsIAboutWindowsMessages : nsISupports
+{
+ void getMessages(in mozIDOMWindowProxy currentWindow, out Array<Array<ACString> > messages, out Array<AString> windowTitles);
+};
diff --git a/toolkit/components/aboutwindowsmessages/tests/browser/browser.toml b/toolkit/components/aboutwindowsmessages/tests/browser/browser.toml
new file mode 100644
index 0000000000..650fabf228
--- /dev/null
+++ b/toolkit/components/aboutwindowsmessages/tests/browser/browser.toml
@@ -0,0 +1,3 @@
+[DEFAULT]
+
+["browser_aboutwindowsmessages.js"]
diff --git a/toolkit/components/aboutwindowsmessages/tests/browser/browser_aboutwindowsmessages.js b/toolkit/components/aboutwindowsmessages/tests/browser/browser_aboutwindowsmessages.js
new file mode 100644
index 0000000000..7c667891d6
--- /dev/null
+++ b/toolkit/components/aboutwindowsmessages/tests/browser/browser_aboutwindowsmessages.js
@@ -0,0 +1,85 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+async function resizeWindow(windowToResize, width, height) {
+ let resizePromise = BrowserTestUtils.waitForEvent(
+ windowToResize,
+ "resize",
+ false
+ );
+ windowToResize.resizeTo(width, height);
+ await resizePromise;
+}
+
+add_task(async () => {
+ const TEST_LINK = "https://example.com/";
+ let originalBrowserWindow =
+ Services.wm.getMostRecentWindow("navigator:browser");
+ let originalBrowser = originalBrowserWindow.gBrowser;
+ // Resize this window so we can check for WM_NCCALCSIZE events below
+ await resizeWindow(originalBrowserWindow, 500, 400);
+ await resizeWindow(originalBrowserWindow, 600, 500);
+ await resizeWindow(originalBrowserWindow, 700, 600);
+ let newWindow = await BrowserTestUtils.openNewBrowserWindow({
+ url: TEST_LINK,
+ });
+ registerCleanupFunction(async function () {
+ await BrowserTestUtils.closeWindow(newWindow);
+ });
+ await BrowserTestUtils.withNewTab(
+ { gBrowser: originalBrowser, url: "about:windows-messages" },
+ async browser => {
+ let messagesList = content.document.getElementById("windows-div");
+ // This is tricky because the test framework has its own windows
+ Assert.greaterOrEqual(
+ messagesList.childNodes.length,
+ 2,
+ "should have enough window entries"
+ );
+
+ let firstList = true;
+ for (let sublist of messagesList.childNodes) {
+ const messages = Array.from(sublist.querySelectorAll("li.message"));
+ const numberOfMessages = messages.length;
+ // Every window gets a few window messages when it opens, so there
+ // should be at least a few here.
+ Assert.greaterOrEqual(
+ numberOfMessages,
+ 3,
+ "should have enough messages for the current window"
+ );
+ if (firstList) {
+ // It would be nice if we could check for a less obscure event.
+ // However, since we're resizing the window programatically we don't
+ // get WM_SIZE or WM_SIZING events.
+ Assert.greaterOrEqual(
+ messages.filter(messageLi =>
+ messageLi.innerHTML.includes("WM_NCCALCSIZE")
+ ).length,
+ 5,
+ "active window should have enough WM_NCCALCSIZE events"
+ );
+ firstList = false;
+ }
+ let buttons = sublist.querySelectorAll("button");
+ Assert.equal(buttons.length, 1, "should have only one button");
+ let clipboardButton = buttons[0];
+ clipboardButton.click();
+ // Wait until copying is done and the button becomes clickable.
+ await BrowserTestUtils.waitForMutationCondition(
+ clipboardButton,
+ { attributes: true },
+ () => !clipboardButton.disabled
+ );
+ const clipboardText = await navigator.clipboard.readText();
+ const numberOfLines = Array.from(clipboardText.matchAll("\n")).length;
+ Assert.equal(
+ numberOfLines,
+ numberOfMessages,
+ "should copy the right number of lines to the clipboard"
+ );
+ }
+ }
+ );
+});