summaryrefslogtreecommitdiffstats
path: root/layout/tools/layout-debug/src
diff options
context:
space:
mode:
Diffstat (limited to 'layout/tools/layout-debug/src')
-rw-r--r--layout/tools/layout-debug/src/components.conf21
-rw-r--r--layout/tools/layout-debug/src/moz.build24
-rw-r--r--layout/tools/layout-debug/src/nsILayoutDebuggingTools.idl44
-rw-r--r--layout/tools/layout-debug/src/nsLayoutDebugCLH.cpp187
-rw-r--r--layout/tools/layout-debug/src/nsLayoutDebugCLH.h24
-rw-r--r--layout/tools/layout-debug/src/nsLayoutDebuggingTools.cpp327
-rw-r--r--layout/tools/layout-debug/src/nsLayoutDebuggingTools.h30
7 files changed, 657 insertions, 0 deletions
diff --git a/layout/tools/layout-debug/src/components.conf b/layout/tools/layout-debug/src/components.conf
new file mode 100644
index 0000000000..07ad3d155d
--- /dev/null
+++ b/layout/tools/layout-debug/src/components.conf
@@ -0,0 +1,21 @@
+# -*- 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': '{3f4c3b63-e640-4712-abbf-fff1301ceb60}',
+ 'contract_ids': ['@mozilla.org/layout-debug/layout-debuggingtools;1'],
+ 'type': 'nsLayoutDebuggingTools',
+ 'headers': ['/layout/tools/layout-debug/src/nsLayoutDebuggingTools.h'],
+ },
+ {
+ 'cid': '{a8f52633-5ecf-424a-a147-47c322f7bc2e}',
+ 'contract_ids': ['@mozilla.org/commandlinehandler/general-startup;1?type=layoutdebug'],
+ 'type': 'nsLayoutDebugCLH',
+ 'headers': ['/layout/tools/layout-debug/src/nsLayoutDebugCLH.h'],
+ 'categories': {'command-line-handler': 'm-layoutdebug'},
+ },
+]
diff --git a/layout/tools/layout-debug/src/moz.build b/layout/tools/layout-debug/src/moz.build
new file mode 100644
index 0000000000..37f9389fa3
--- /dev/null
+++ b/layout/tools/layout-debug/src/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/.
+
+XPIDL_SOURCES += [
+ "nsILayoutDebuggingTools.idl",
+]
+
+XPIDL_MODULE = "layout_debug"
+
+UNIFIED_SOURCES += [
+ "nsLayoutDebugCLH.cpp",
+ "nsLayoutDebuggingTools.cpp",
+]
+
+XPCOM_MANIFESTS += [
+ "components.conf",
+]
+
+include("/ipc/chromium/chromium-config.mozbuild")
+
+FINAL_LIBRARY = "xul"
diff --git a/layout/tools/layout-debug/src/nsILayoutDebuggingTools.idl b/layout/tools/layout-debug/src/nsILayoutDebuggingTools.idl
new file mode 100644
index 0000000000..f689734a46
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsILayoutDebuggingTools.idl
@@ -0,0 +1,44 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+// vim:cindent:tabstop=4:expandtab:shiftwidth=4:
+/* 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 mozIDOMWindow;
+
+/**
+ * A series of hooks into non-IDL-ized layout code to allow all the
+ * layout debugging functions to be used from chrome.
+ */
+
+[builtinclass, scriptable, uuid(f336d8d3-9721-4ad3-85d0-a7018c0a3383)]
+interface nsILayoutDebuggingTools : nsISupports
+{
+ /*
+ * Initialize debugger object to act on a docshell.
+ */
+ void init(in mozIDOMWindow win);
+
+ // Repaint the window.
+ void forceRefresh();
+
+ /* Toggle various debugging states */
+ void setReflowCounts(in boolean enabled);
+ void setPagedMode(in boolean enabled);
+
+ /* Run various tests. */
+ void dumpContent();
+ void dumpFrames();
+ void dumpFramesInCSSPixels();
+ void dumpTextRuns();
+ void dumpViews();
+ void dumpCounterManager();
+
+ void dumpStyleSheets();
+ void dumpMatchedRules();
+ void dumpComputedStyles();
+
+ void dumpReflowStats();
+};
diff --git a/layout/tools/layout-debug/src/nsLayoutDebugCLH.cpp b/layout/tools/layout-debug/src/nsLayoutDebugCLH.cpp
new file mode 100644
index 0000000000..c50f3af44a
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsLayoutDebugCLH.cpp
@@ -0,0 +1,187 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:tabstop=4:expandtab:shiftwidth=4:
+/* 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 "nsLayoutDebugCLH.h"
+#include "mozIDOMWindow.h"
+#include "nsArray.h"
+#include "nsString.h"
+#include "nsComponentManagerUtils.h"
+#include "nsCOMPtr.h"
+#include "nsIWindowWatcher.h"
+#include "nsISupportsPrimitives.h"
+#include "nsICommandLine.h"
+#include "nsIURI.h"
+#include "nsServiceManagerUtils.h"
+
+nsLayoutDebugCLH::nsLayoutDebugCLH() = default;
+
+nsLayoutDebugCLH::~nsLayoutDebugCLH() = default;
+
+NS_IMPL_ISUPPORTS(nsLayoutDebugCLH, ICOMMANDLINEHANDLER)
+
+static nsresult HandleFlagWithOptionalArgument(nsICommandLine* aCmdLine,
+ const nsAString& aName,
+ const nsAString& aDefaultValue,
+ nsAString& aValue,
+ bool& aFlagPresent) {
+ aValue.Truncate();
+ aFlagPresent = false;
+
+ nsresult rv;
+ int32_t idx;
+
+ rv = aCmdLine->FindFlag(aName, false, &idx);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (idx < 0) return NS_OK;
+
+ aFlagPresent = true;
+
+ int32_t length;
+ aCmdLine->GetLength(&length);
+
+ bool argPresent = false;
+
+ if (idx + 1 < length) {
+ rv = aCmdLine->GetArgument(idx + 1, aValue);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!aValue.IsEmpty() && aValue.CharAt(0) == '-') {
+ aValue.Truncate();
+ } else {
+ argPresent = true;
+ }
+ }
+
+ if (!argPresent) {
+ aValue = aDefaultValue;
+ }
+
+ return aCmdLine->RemoveArguments(idx, idx + argPresent);
+}
+
+static nsresult HandleFlagWithOptionalArgument(nsICommandLine* aCmdLine,
+ const nsAString& aName,
+ double aDefaultValue,
+ double& aValue,
+ bool& aFlagPresent) {
+ nsresult rv;
+ nsString s;
+
+ rv =
+ HandleFlagWithOptionalArgument(aCmdLine, aName, u"0"_ns, s, aFlagPresent);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!aFlagPresent) {
+ aValue = 0.0;
+ return NS_OK;
+ }
+
+ aValue = s.ToDouble(&rv);
+ return rv;
+}
+
+static nsresult AppendArg(nsIMutableArray* aArray, const nsAString& aString) {
+ nsCOMPtr<nsISupportsString> s =
+ do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
+ NS_ENSURE_TRUE(s, NS_ERROR_FAILURE);
+ s->SetData(aString);
+ return aArray->AppendElement(s);
+}
+
+NS_IMETHODIMP
+nsLayoutDebugCLH::Handle(nsICommandLine* aCmdLine) {
+ nsresult rv;
+ bool flagPresent;
+
+ nsString url;
+ bool autoclose = false;
+ double delay = 0.0;
+ bool captureProfile = false;
+ nsString profileFilename;
+ bool paged = false;
+
+ rv = HandleFlagWithOptionalArgument(aCmdLine, u"layoutdebug"_ns,
+ u"about:blank"_ns, url, flagPresent);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!flagPresent) {
+ return NS_OK;
+ }
+
+ rv = HandleFlagWithOptionalArgument(aCmdLine, u"autoclose"_ns, 0.0, delay,
+ autoclose);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = HandleFlagWithOptionalArgument(aCmdLine, u"capture-profile"_ns,
+ u"profile.json"_ns, profileFilename,
+ captureProfile);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = aCmdLine->HandleFlag(u"paged"_ns, false, &paged);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMutableArray> argsArray = nsArray::Create();
+
+ nsCOMPtr<nsIURI> uri;
+ nsAutoCString resolvedSpec;
+
+ rv = aCmdLine->ResolveURI(url, getter_AddRefs(uri));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = uri->GetSpec(resolvedSpec);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = AppendArg(argsArray, NS_ConvertUTF8toUTF16(resolvedSpec));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (autoclose) {
+ nsString arg;
+ arg.AppendPrintf("autoclose=%f", delay);
+
+ rv = AppendArg(argsArray, arg);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ if (captureProfile) {
+ nsString arg;
+ arg.AppendLiteral("profile=");
+ arg.Append(profileFilename);
+
+ rv = AppendArg(argsArray, arg);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ if (paged) {
+ rv = AppendArg(argsArray, u"paged"_ns);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ nsCOMPtr<nsIWindowWatcher> wwatch =
+ do_GetService(NS_WINDOWWATCHER_CONTRACTID);
+ NS_ENSURE_TRUE(wwatch, NS_ERROR_FAILURE);
+
+ nsCOMPtr<mozIDOMWindowProxy> opened;
+ wwatch->OpenWindow(
+ nullptr, "chrome://layoutdebug/content/layoutdebug.xhtml"_ns, "_blank"_ns,
+ "chrome,dialog=no,all"_ns, argsArray, getter_AddRefs(opened));
+ aCmdLine->SetPreventDefault(true);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebugCLH::GetHelpInfo(nsACString& aResult) {
+ aResult.AssignLiteral(
+ " --layoutdebug [<url>] Start with Layout Debugger\n"
+ " --autoclose [<seconds>] Automatically close the Layout Debugger once\n"
+ " the page has loaded, after delaying the specified\n"
+ " number of seconds (which defaults to 0).\n"
+ " --capture-profile [<filename>] Capture a profile of the Layout\n"
+ " Debugger using the Gecko Profiler, and save the\n"
+ " profile to the specified file (which defaults to\n"
+ " profile.json).\n"
+ " --paged Layout the page in paginated mode.\n");
+ return NS_OK;
+}
diff --git a/layout/tools/layout-debug/src/nsLayoutDebugCLH.h b/layout/tools/layout-debug/src/nsLayoutDebugCLH.h
new file mode 100644
index 0000000000..aa99bf9eff
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsLayoutDebugCLH.h
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:tabstop=4:expandtab:shiftwidth=4:
+/* 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 nsLayoutDebugCLH_h_
+#define nsLayoutDebugCLH_h_
+
+#include "nsICommandLineHandler.h"
+#define ICOMMANDLINEHANDLER nsICommandLineHandler
+
+class nsLayoutDebugCLH : public ICOMMANDLINEHANDLER {
+ public:
+ nsLayoutDebugCLH();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICOMMANDLINEHANDLER
+
+ protected:
+ virtual ~nsLayoutDebugCLH();
+};
+
+#endif /* !defined(nsLayoutDebugCLH_h_) */
diff --git a/layout/tools/layout-debug/src/nsLayoutDebuggingTools.cpp b/layout/tools/layout-debug/src/nsLayoutDebuggingTools.cpp
new file mode 100644
index 0000000000..72bb48f5d4
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsLayoutDebuggingTools.cpp
@@ -0,0 +1,327 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:tabstop=4:expandtab:shiftwidth=4:
+/* 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 "nsLayoutDebuggingTools.h"
+
+#include "nsIDocShell.h"
+#include "nsPIDOMWindow.h"
+#include "nsIContentViewer.h"
+#include "nsIPrintSettings.h"
+#include "nsIPrintSettingsService.h"
+
+#include "nsAtom.h"
+#include "nsQuickSort.h"
+
+#include "nsIContent.h"
+
+#include "nsCounterManager.h"
+#include "nsCSSFrameConstructor.h"
+#include "nsViewManager.h"
+#include "nsIFrame.h"
+
+#include "nsLayoutCID.h"
+
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/PresShell.h"
+
+using namespace mozilla;
+using mozilla::dom::Document;
+
+static already_AddRefed<nsIContentViewer> doc_viewer(nsIDocShell* aDocShell) {
+ if (!aDocShell) return nullptr;
+ nsCOMPtr<nsIContentViewer> result;
+ aDocShell->GetContentViewer(getter_AddRefs(result));
+ return result.forget();
+}
+
+static PresShell* GetPresShell(nsIDocShell* aDocShell) {
+ nsCOMPtr<nsIContentViewer> cv = doc_viewer(aDocShell);
+ if (!cv) return nullptr;
+ return cv->GetPresShell();
+}
+
+static nsViewManager* view_manager(nsIDocShell* aDocShell) {
+ PresShell* presShell = GetPresShell(aDocShell);
+ if (!presShell) {
+ return nullptr;
+ }
+ return presShell->GetViewManager();
+}
+
+#ifdef DEBUG
+static already_AddRefed<Document> document(nsIDocShell* aDocShell) {
+ nsCOMPtr<nsIContentViewer> cv(doc_viewer(aDocShell));
+ if (!cv) return nullptr;
+ RefPtr<Document> result = cv->GetDocument();
+ return result.forget();
+}
+#endif
+
+nsLayoutDebuggingTools::nsLayoutDebuggingTools() { ForceRefresh(); }
+
+nsLayoutDebuggingTools::~nsLayoutDebuggingTools() = default;
+
+NS_IMPL_ISUPPORTS(nsLayoutDebuggingTools, nsILayoutDebuggingTools)
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::Init(mozIDOMWindow* aWin) {
+ if (!Preferences::GetService()) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ {
+ if (!aWin) return NS_ERROR_UNEXPECTED;
+ auto* window = nsPIDOMWindowInner::From(aWin);
+ mDocShell = window->GetDocShell();
+ }
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_UNEXPECTED);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::SetReflowCounts(bool aShow) {
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ if (PresShell* presShell = GetPresShell(mDocShell)) {
+#ifdef MOZ_REFLOW_PERF
+ presShell->SetPaintFrameCount(aShow);
+#else
+ printf("************************************************\n");
+ printf("Sorry, you have not built with MOZ_REFLOW_PERF=1\n");
+ printf("************************************************\n");
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::SetPagedMode(bool aPagedMode) {
+ nsCOMPtr<nsIPrintSettingsService> printSettingsService =
+ do_GetService("@mozilla.org/gfx/printsettings-service;1");
+ nsCOMPtr<nsIPrintSettings> printSettings;
+
+ printSettingsService->CreateNewPrintSettings(getter_AddRefs(printSettings));
+
+ // Use the same setup as setupPrintMode() in reftest-content.js.
+ printSettings->SetPaperWidth(5);
+ printSettings->SetPaperHeight(3);
+
+ nsIntMargin unwriteableMargin(0, 0, 0, 0);
+ printSettings->SetUnwriteableMarginInTwips(unwriteableMargin);
+
+ printSettings->SetHeaderStrLeft(u""_ns);
+ printSettings->SetHeaderStrCenter(u""_ns);
+ printSettings->SetHeaderStrRight(u""_ns);
+
+ printSettings->SetFooterStrLeft(u""_ns);
+ printSettings->SetFooterStrCenter(u""_ns);
+ printSettings->SetFooterStrRight(u""_ns);
+
+ printSettings->SetPrintBGColors(true);
+ printSettings->SetPrintBGImages(true);
+
+ nsCOMPtr<nsIContentViewer> contentViewer(doc_viewer(mDocShell));
+ contentViewer->SetPageModeForTesting(aPagedMode, printSettings);
+
+ ForceRefresh();
+ return NS_OK;
+}
+
+static void DumpContentRecur(nsIDocShell* aDocShell, FILE* out) {
+#ifdef DEBUG
+ if (nullptr != aDocShell) {
+ fprintf(out, "docshell=%p \n", static_cast<void*>(aDocShell));
+ RefPtr<Document> doc(document(aDocShell));
+ if (doc) {
+ dom::Element* root = doc->GetRootElement();
+ if (root) {
+ root->List(out);
+ }
+ } else {
+ fputs("no document\n", out);
+ }
+ }
+#endif
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpContent() {
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ DumpContentRecur(mDocShell, stdout);
+ return NS_OK;
+}
+
+static void DumpFramesRecur(
+ nsIDocShell* aDocShell, FILE* out,
+ nsIFrame::ListFlags aFlags = nsIFrame::ListFlags()) {
+ if (aFlags.contains(nsIFrame::ListFlag::DisplayInCSSPixels)) {
+ fprintf(out, "Frame tree in CSS pixels:\n");
+ } else {
+ fprintf(out, "Frame tree in app units:\n");
+ }
+
+ fprintf(out, "docshell=%p \n", aDocShell);
+ if (PresShell* presShell = GetPresShell(aDocShell)) {
+ nsIFrame* root = presShell->GetRootFrame();
+ if (root) {
+ root->List(out, "", aFlags);
+ }
+ } else {
+ fputs("null pres shell\n", out);
+ }
+}
+
+static void DumpTextRunsRecur(nsIDocShell* aDocShell, FILE* out) {
+ fprintf(out, "Text runs:\n");
+
+ fprintf(out, "docshell=%p \n", aDocShell);
+ if (PresShell* presShell = GetPresShell(aDocShell)) {
+ nsIFrame* root = presShell->GetRootFrame();
+ if (root) {
+ root->ListTextRuns(out);
+ }
+ } else {
+ fputs("null pres shell\n", out);
+ }
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpFrames() {
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ DumpFramesRecur(mDocShell, stdout);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpFramesInCSSPixels() {
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ DumpFramesRecur(mDocShell, stdout, nsIFrame::ListFlag::DisplayInCSSPixels);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpTextRuns() {
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ DumpTextRunsRecur(mDocShell, stdout);
+ return NS_OK;
+}
+
+static void DumpViewsRecur(nsIDocShell* aDocShell, FILE* out) {
+#ifdef DEBUG
+ fprintf(out, "docshell=%p \n", static_cast<void*>(aDocShell));
+ RefPtr<nsViewManager> vm(view_manager(aDocShell));
+ if (vm) {
+ nsView* root = vm->GetRootView();
+ if (root) {
+ root->List(out);
+ }
+ } else {
+ fputs("null view manager\n", out);
+ }
+#endif // DEBUG
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpViews() {
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ DumpViewsRecur(mDocShell, stdout);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpCounterManager() {
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ if (PresShell* presShell = GetPresShell(mDocShell)) {
+ presShell->FrameConstructor()->GetContainStyleScopeManager().DumpCounters();
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpStyleSheets() {
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+#if defined(DEBUG) || defined(MOZ_LAYOUT_DEBUGGER)
+ FILE* out = stdout;
+ if (PresShell* presShell = GetPresShell(mDocShell)) {
+ presShell->ListStyleSheets(out);
+ } else {
+ fputs("null pres shell\n", out);
+ }
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLayoutDebuggingTools::DumpMatchedRules() {
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ FILE* out = stdout;
+ if (PresShell* presShell = GetPresShell(mDocShell)) {
+ nsIFrame* root = presShell->GetRootFrame();
+ if (root) {
+ root->ListWithMatchedRules(out);
+ }
+ } else {
+ fputs("null pres shell\n", out);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpComputedStyles() {
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+#ifdef DEBUG
+ FILE* out = stdout;
+ if (PresShell* presShell = GetPresShell(mDocShell)) {
+ presShell->ListComputedStyles(out);
+ } else {
+ fputs("null pres shell\n", out);
+ }
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpReflowStats() {
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+#ifdef DEBUG
+ if (RefPtr<PresShell> presShell = GetPresShell(mDocShell)) {
+# ifdef MOZ_REFLOW_PERF
+ presShell->DumpReflows();
+# else
+ printf("************************************************\n");
+ printf("Sorry, you have not built with MOZ_REFLOW_PERF=1\n");
+ printf("************************************************\n");
+# endif
+ }
+#endif
+ return NS_OK;
+}
+
+nsresult nsLayoutDebuggingTools::ForceRefresh() {
+ RefPtr<nsViewManager> vm(view_manager(mDocShell));
+ if (!vm) return NS_OK;
+ nsView* root = vm->GetRootView();
+ if (root) {
+ vm->InvalidateView(root);
+ }
+ return NS_OK;
+}
+
+nsresult nsLayoutDebuggingTools::SetBoolPrefAndRefresh(const char* aPrefName,
+ bool aNewVal) {
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+
+ nsIPrefService* prefService = Preferences::GetService();
+ NS_ENSURE_TRUE(prefService && aPrefName, NS_OK);
+
+ Preferences::SetBool(aPrefName, aNewVal);
+ prefService->SavePrefFile(nullptr);
+
+ ForceRefresh();
+
+ return NS_OK;
+}
diff --git a/layout/tools/layout-debug/src/nsLayoutDebuggingTools.h b/layout/tools/layout-debug/src/nsLayoutDebuggingTools.h
new file mode 100644
index 0000000000..f6b37fecfb
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsLayoutDebuggingTools.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:tabstop=4:expandtab:shiftwidth=4:
+/* 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 nsLayoutDebuggingTools_h
+#define nsLayoutDebuggingTools_h
+
+#include "nsILayoutDebuggingTools.h"
+#include "nsIDocShell.h"
+#include "nsCOMPtr.h"
+
+class nsLayoutDebuggingTools : public nsILayoutDebuggingTools {
+ public:
+ nsLayoutDebuggingTools();
+
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSILAYOUTDEBUGGINGTOOLS
+
+ protected:
+ virtual ~nsLayoutDebuggingTools();
+
+ nsresult SetBoolPrefAndRefresh(const char* aPrefName, bool aNewValue);
+
+ nsCOMPtr<nsIDocShell> mDocShell;
+};
+
+#endif