summaryrefslogtreecommitdiffstats
path: root/layout/tools/layout-debug
diff options
context:
space:
mode:
Diffstat (limited to 'layout/tools/layout-debug')
-rw-r--r--layout/tools/layout-debug/application.ini12
-rw-r--r--layout/tools/layout-debug/chrome.manifest2
-rw-r--r--layout/tools/layout-debug/layoutdebug-prefs.js5
-rw-r--r--layout/tools/layout-debug/moz.build9
-rw-r--r--layout/tools/layout-debug/src/moz.build25
-rw-r--r--layout/tools/layout-debug/src/nsDebugFactory.cpp50
-rw-r--r--layout/tools/layout-debug/src/nsILayoutDebuggingTools.idl52
-rw-r--r--layout/tools/layout-debug/src/nsILayoutRegressionTester.idl46
-rw-r--r--layout/tools/layout-debug/src/nsLayoutDebugCIID.h24
-rw-r--r--layout/tools/layout-debug/src/nsLayoutDebugCLH.cpp82
-rw-r--r--layout/tools/layout-debug/src/nsLayoutDebugCLH.h29
-rw-r--r--layout/tools/layout-debug/src/nsLayoutDebuggingTools.cpp543
-rw-r--r--layout/tools/layout-debug/src/nsLayoutDebuggingTools.h44
-rw-r--r--layout/tools/layout-debug/src/nsRegressionTester.cpp138
-rw-r--r--layout/tools/layout-debug/src/nsRegressionTester.h32
-rw-r--r--layout/tools/layout-debug/tests/unit/test_componentsRegistered.js8
-rw-r--r--layout/tools/layout-debug/tests/unit/xpcshell.ini5
-rw-r--r--layout/tools/layout-debug/ui/content/layoutdebug-overlay.xul38
-rw-r--r--layout/tools/layout-debug/ui/content/layoutdebug.js434
-rw-r--r--layout/tools/layout-debug/ui/content/layoutdebug.xul187
-rw-r--r--layout/tools/layout-debug/ui/jar.mn14
-rw-r--r--layout/tools/layout-debug/ui/locale/en-US/layoutdebug-overlay.dtd8
-rw-r--r--layout/tools/layout-debug/ui/locale/en-US/layoutdebug.dtd76
-rw-r--r--layout/tools/layout-debug/ui/moz.build7
24 files changed, 1870 insertions, 0 deletions
diff --git a/layout/tools/layout-debug/application.ini b/layout/tools/layout-debug/application.ini
new file mode 100644
index 000000000..27d37b272
--- /dev/null
+++ b/layout/tools/layout-debug/application.ini
@@ -0,0 +1,12 @@
+#filter substitution
+[App]
+Vendor=MozillaTest
+Name=LayoutDebug
+Version=0.1
+BuildID=@BUILD_ID@
+Copyright=Copyright (c) 2004 Mozilla.org
+ID={da915c15-c21a-41e2-95c3-2e0f76fd3191}
+
+[Gecko]
+MinVersion=@MOZILLA_VERSION_U@
+MaxVersion=@MOZILLA_VERSION_U@
diff --git a/layout/tools/layout-debug/chrome.manifest b/layout/tools/layout-debug/chrome.manifest
new file mode 100644
index 000000000..f7e957041
--- /dev/null
+++ b/layout/tools/layout-debug/chrome.manifest
@@ -0,0 +1,2 @@
+content layoutdebug jar:layoutdebug.jar!/content/layoutdebug/
+locale layoutdebug en-US jar:layoutdebug.jar!/locale/en-US/layoutdebug/
diff --git a/layout/tools/layout-debug/layoutdebug-prefs.js b/layout/tools/layout-debug/layoutdebug-prefs.js
new file mode 100644
index 000000000..bfa8e1990
--- /dev/null
+++ b/layout/tools/layout-debug/layoutdebug-prefs.js
@@ -0,0 +1,5 @@
+/* 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/. */
+
+pref("toolkit.defaultChromeURI", "chrome://layoutdebug/content/layoutdebug.xul");
diff --git a/layout/tools/layout-debug/moz.build b/layout/tools/layout-debug/moz.build
new file mode 100644
index 000000000..84cb4fb7e
--- /dev/null
+++ b/layout/tools/layout-debug/moz.build
@@ -0,0 +1,9 @@
+# -*- 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/.
+
+DIRS += ['src', 'ui']
+
+XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
diff --git a/layout/tools/layout-debug/src/moz.build b/layout/tools/layout-debug/src/moz.build
new file mode 100644
index 000000000..be7abcab0
--- /dev/null
+++ b/layout/tools/layout-debug/src/moz.build
@@ -0,0 +1,25 @@
+# -*- 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',
+ 'nsILayoutRegressionTester.idl',
+]
+
+XPIDL_MODULE = 'layout_debug'
+
+EXPORTS += [
+ 'nsLayoutDebugCIID.h',
+]
+
+UNIFIED_SOURCES += [
+ 'nsDebugFactory.cpp',
+ 'nsLayoutDebugCLH.cpp',
+ 'nsLayoutDebuggingTools.cpp',
+ 'nsRegressionTester.cpp',
+]
+
+FINAL_LIBRARY = 'xul'
diff --git a/layout/tools/layout-debug/src/nsDebugFactory.cpp b/layout/tools/layout-debug/src/nsDebugFactory.cpp
new file mode 100644
index 000000000..c9b7caca4
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsDebugFactory.cpp
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nscore.h"
+#include "nsLayoutDebugCIID.h"
+#include "mozilla/ModuleUtils.h"
+#include "nsIFactory.h"
+#include "nsISupports.h"
+#include "nsRegressionTester.h"
+#include "nsLayoutDebuggingTools.h"
+#include "nsLayoutDebugCLH.h"
+#include "nsIServiceManager.h"
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsRegressionTester)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsLayoutDebuggingTools)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsLayoutDebugCLH)
+
+NS_DEFINE_NAMED_CID(NS_REGRESSION_TESTER_CID);
+NS_DEFINE_NAMED_CID(NS_LAYOUT_DEBUGGINGTOOLS_CID);
+NS_DEFINE_NAMED_CID(NS_LAYOUTDEBUGCLH_CID);
+
+static const mozilla::Module::CIDEntry kLayoutDebugCIDs[] = {
+ { &kNS_REGRESSION_TESTER_CID, false, nullptr, nsRegressionTesterConstructor },
+ { &kNS_LAYOUT_DEBUGGINGTOOLS_CID, false, nullptr, nsLayoutDebuggingToolsConstructor },
+ { &kNS_LAYOUTDEBUGCLH_CID, false, nullptr, nsLayoutDebugCLHConstructor },
+ { nullptr }
+};
+
+static const mozilla::Module::ContractIDEntry kLayoutDebugContracts[] = {
+ { "@mozilla.org/layout-debug/regressiontester;1", &kNS_REGRESSION_TESTER_CID },
+ { NS_LAYOUT_DEBUGGINGTOOLS_CONTRACTID, &kNS_LAYOUT_DEBUGGINGTOOLS_CID },
+ { "@mozilla.org/commandlinehandler/general-startup;1?type=layoutdebug", &kNS_LAYOUTDEBUGCLH_CID },
+ { nullptr }
+};
+
+static const mozilla::Module::CategoryEntry kLayoutDebugCategories[] = {
+ { "command-line-handler", "m-layoutdebug", "@mozilla.org/commandlinehandler/general-startup;1?type=layoutdebug" },
+ { nullptr }
+};
+
+static const mozilla::Module kLayoutDebugModule = {
+ mozilla::Module::kVersion,
+ kLayoutDebugCIDs,
+ kLayoutDebugContracts,
+ kLayoutDebugCategories
+};
+
+NSMODULE_DEFN(nsLayoutDebugModule) = &kLayoutDebugModule;
diff --git a/layout/tools/layout-debug/src/nsILayoutDebuggingTools.idl b/layout/tools/layout-debug/src/nsILayoutDebuggingTools.idl
new file mode 100644
index 000000000..18c535e53
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsILayoutDebuggingTools.idl
@@ -0,0 +1,52 @@
+/* -*- 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.
+ */
+
+[scriptable, uuid(f336d8d3-9721-4ad3-85d0-a7018c0a3383)]
+interface nsILayoutDebuggingTools : nsISupports
+{
+
+ /*
+ * Initialize debugger object to act on a docshell.
+ */
+ void init(in mozIDOMWindow win);
+
+ /*
+ * Notify the debugger that the docshell has been told to load a new
+ * URI.
+ */
+ void newURILoaded();
+
+ /* Toggle various debugging states */
+ attribute boolean visualDebugging;
+ attribute boolean visualEventDebugging;
+ attribute boolean paintFlashing;
+ attribute boolean paintDumping;
+ attribute boolean invalidateDumping;
+ attribute boolean eventDumping;
+ attribute boolean motionEventDumping;
+ attribute boolean crossingEventDumping;
+ attribute boolean reflowCounts;
+
+ /* Run various tests. */
+ void dumpWebShells();
+ void dumpContent();
+ void dumpFrames();
+ void dumpViews();
+
+ void dumpStyleSheets();
+ void dumpStyleContexts();
+
+ void dumpReflowStats();
+};
diff --git a/layout/tools/layout-debug/src/nsILayoutRegressionTester.idl b/layout/tools/layout-debug/src/nsILayoutRegressionTester.idl
new file mode 100644
index 000000000..2899a4b77
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsILayoutRegressionTester.idl
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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;
+interface nsIFile;
+
+[scriptable, uuid(0a065e41-3a55-4b5c-bb41-1e848bb2d10c)]
+interface nsILayoutRegressionTester : nsISupports
+{
+ /**
+ * Dumps the content of a window
+ * @param aWindowToDump the window to dump (may be an iframe etc)
+ * @param aFile the file to dump to. It will be created if necessary, otherwise
+ truncated. If nil, write to stdout.
+ * @param aFlagsMask some flags that determine what to dump
+ * @param aFlagsMask some flags that determine what to dump
+ * @param aResult a status value indicating whether the dump happened,
+ whether the page was still loading, or whether some other error happened.
+ */
+ const short DUMP_FLAGS_MASK_DEFAULT = 0;
+ const short DUMP_FLAGS_MASK_PRINT_MODE = 1;
+
+ const long DUMP_RESULT_COMPLETED = 0; // loaded OK
+ const long DUMP_RESULT_LOADING = 1; // still loading
+ const long DUMP_RESULT_ERROR = 2; // an error occurred
+
+ long dumpFrameModel(in mozIDOMWindow aWindowToDump,
+ in nsIFile aFile,
+ in unsigned long aFlagsMask);
+
+ /**
+ * Compares the contents of frame model files
+ * @param aBaseFile the baseline file, opened with read permissions
+ * @param aVerFile file containing the results to verify, opened with read permissions
+ * @param aFlags flags specifying output verbosity
+ * @param aResult result of the comparison: zero if the files are same, non-zero if different
+ */
+ const short COMPARE_FLAGS_VERBOSE = 0;
+ const short COMPARE_FLAGS_BRIEF = 1;
+ boolean compareFrameModels(in nsIFile aBaseFile, in nsIFile aVerFile, in unsigned long aFlags);
+};
+
diff --git a/layout/tools/layout-debug/src/nsLayoutDebugCIID.h b/layout/tools/layout-debug/src/nsLayoutDebugCIID.h
new file mode 100644
index 000000000..ceff68355
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsLayoutDebugCIID.h
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 nsFrameDebugCIID_h__
+#define nsFrameDebugCIID_h__
+
+#include "nsISupports.h"
+#include "nsIFactory.h"
+#include "nsIComponentManager.h"
+
+#define NS_REGRESSION_TESTER_CID \
+{ 0x698c54f4, 0x4ea9, 0x11d7, \
+{ 0x85, 0x9f, 0x00, 0x03, 0x93, 0x63, 0x65, 0x92 } }
+
+#define NS_LAYOUT_DEBUGGINGTOOLS_CONTRACTID \
+ "@mozilla.org/layout-debug/layout-debuggingtools;1"
+// 3f4c3b63-e640-4712-abbf-fff1301ceb60
+#define NS_LAYOUT_DEBUGGINGTOOLS_CID { 0x3f4c3b68, 0xe640, 0x4712, \
+ { 0xab, 0xbf, 0xff, 0xf1, 0x30, 0x1c, 0xeb, 0x60}}
+
+#endif // nsFrameDebugCIID_h__
+
diff --git a/layout/tools/layout-debug/src/nsLayoutDebugCLH.cpp b/layout/tools/layout-debug/src/nsLayoutDebugCLH.cpp
new file mode 100644
index 000000000..52a0d4555
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsLayoutDebugCLH.cpp
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; 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 "nsLayoutDebugCLH.h"
+#include "nsArray.h"
+#include "nsString.h"
+#include "plstr.h"
+#include "nsCOMPtr.h"
+#include "nsIWindowWatcher.h"
+#include "nsIServiceManager.h"
+#include "nsIDOMWindow.h"
+#include "nsISupportsPrimitives.h"
+#include "nsICommandLine.h"
+
+nsLayoutDebugCLH::nsLayoutDebugCLH()
+{
+}
+
+nsLayoutDebugCLH::~nsLayoutDebugCLH()
+{
+}
+
+NS_IMPL_ISUPPORTS(nsLayoutDebugCLH, ICOMMANDLINEHANDLER)
+
+NS_IMETHODIMP
+nsLayoutDebugCLH::Handle(nsICommandLine* aCmdLine)
+{
+ nsresult rv;
+
+ int32_t idx;
+ rv = aCmdLine->FindFlag(NS_LITERAL_STRING("layoutdebug"), false, &idx);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (idx < 0)
+ return NS_OK;
+
+ int32_t length;
+ aCmdLine->GetLength(&length);
+
+ nsAutoString url;
+ if (idx + 1 < length) {
+ rv = aCmdLine->GetArgument(idx + 1, url);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!url.IsEmpty() && url.CharAt(0) == '-')
+ url.Truncate();
+ }
+
+ aCmdLine->RemoveArguments(idx, idx + !url.IsEmpty());
+
+ nsCOMPtr<nsIMutableArray> argsArray = nsArray::Create();
+
+ if (!url.IsEmpty())
+ {
+ nsCOMPtr<nsISupportsString> scriptableURL =
+ do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
+ NS_ENSURE_TRUE(scriptableURL, NS_ERROR_FAILURE);
+
+ scriptableURL->SetData(url);
+ argsArray->AppendElement(scriptableURL, /*weak =*/ false);
+ }
+
+ nsCOMPtr<nsIWindowWatcher> wwatch =
+ do_GetService(NS_WINDOWWATCHER_CONTRACTID);
+ NS_ENSURE_TRUE(wwatch, NS_ERROR_FAILURE);
+
+ nsCOMPtr<mozIDOMWindowProxy> opened;
+ wwatch->OpenWindow(nullptr, "chrome://layoutdebug/content/",
+ "_blank", "chrome,dialog=no,all", 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");
+ 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 000000000..c79c8d697
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsLayoutDebugCLH.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; 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/. */
+
+#ifndef nsLayoutDebugCLH_h_
+#define nsLayoutDebugCLH_h_
+
+#include "nsICommandLineHandler.h"
+#define ICOMMANDLINEHANDLER nsICommandLineHandler
+
+#define NS_LAYOUTDEBUGCLH_CID \
+ { 0xa8f52633, 0x5ecf, 0x424a, \
+ { 0xa1, 0x47, 0x47, 0xc3, 0x22, 0xf7, 0xbc, 0xe2 }}
+
+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 000000000..4eb57ed9c
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsLayoutDebuggingTools.cpp
@@ -0,0 +1,543 @@
+/* -*- Mode: C++; 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 "nsLayoutDebuggingTools.h"
+
+#include "nsIDocShell.h"
+#include "nsPIDOMWindow.h"
+#include "nsIContentViewer.h"
+
+#include "nsIServiceManager.h"
+#include "nsIAtom.h"
+#include "nsQuickSort.h"
+
+#include "nsIContent.h"
+#include "nsIDocument.h"
+#include "nsIDOMDocument.h"
+
+#include "nsIPresShell.h"
+#include "nsViewManager.h"
+#include "nsIFrame.h"
+
+#include "nsILayoutDebugger.h"
+#include "nsLayoutCID.h"
+static NS_DEFINE_CID(kLayoutDebuggerCID, NS_LAYOUT_DEBUGGER_CID);
+
+#include "nsISelectionController.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/Preferences.h"
+
+using namespace mozilla;
+
+static already_AddRefed<nsIContentViewer>
+doc_viewer(nsIDocShell *aDocShell)
+{
+ if (!aDocShell)
+ return nullptr;
+ nsCOMPtr<nsIContentViewer> result;
+ aDocShell->GetContentViewer(getter_AddRefs(result));
+ return result.forget();
+}
+
+static already_AddRefed<nsIPresShell>
+pres_shell(nsIDocShell *aDocShell)
+{
+ nsCOMPtr<nsIContentViewer> cv = doc_viewer(aDocShell);
+ if (!cv)
+ return nullptr;
+ nsCOMPtr<nsIPresShell> result;
+ cv->GetPresShell(getter_AddRefs(result));
+ return result.forget();
+}
+
+static nsViewManager*
+view_manager(nsIDocShell *aDocShell)
+{
+ nsCOMPtr<nsIPresShell> shell(pres_shell(aDocShell));
+ if (!shell)
+ return nullptr;
+ return shell->GetViewManager();
+}
+
+#ifdef DEBUG
+static already_AddRefed<nsIDocument>
+document(nsIDocShell *aDocShell)
+{
+ nsCOMPtr<nsIContentViewer> cv(doc_viewer(aDocShell));
+ if (!cv)
+ return nullptr;
+ nsCOMPtr<nsIDOMDocument> domDoc;
+ cv->GetDOMDocument(getter_AddRefs(domDoc));
+ if (!domDoc)
+ return nullptr;
+ nsCOMPtr<nsIDocument> result = do_QueryInterface(domDoc);
+ return result.forget();
+}
+#endif
+
+nsLayoutDebuggingTools::nsLayoutDebuggingTools()
+ : mPaintFlashing(false),
+ mPaintDumping(false),
+ mInvalidateDumping(false),
+ mEventDumping(false),
+ mMotionEventDumping(false),
+ mCrossingEventDumping(false),
+ mReflowCounts(false)
+{
+ NewURILoaded();
+}
+
+nsLayoutDebuggingTools::~nsLayoutDebuggingTools()
+{
+}
+
+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);
+
+ mPaintFlashing =
+ Preferences::GetBool("nglayout.debug.paint_flashing", mPaintFlashing);
+ mPaintDumping =
+ Preferences::GetBool("nglayout.debug.paint_dumping", mPaintDumping);
+ mInvalidateDumping =
+ Preferences::GetBool("nglayout.debug.invalidate_dumping", mInvalidateDumping);
+ mEventDumping =
+ Preferences::GetBool("nglayout.debug.event_dumping", mEventDumping);
+ mMotionEventDumping =
+ Preferences::GetBool("nglayout.debug.motion_event_dumping",
+ mMotionEventDumping);
+ mCrossingEventDumping =
+ Preferences::GetBool("nglayout.debug.crossing_event_dumping",
+ mCrossingEventDumping);
+ mReflowCounts =
+ Preferences::GetBool("layout.reflow.showframecounts", mReflowCounts);
+
+ {
+ nsCOMPtr<nsILayoutDebugger> ld = do_GetService(kLayoutDebuggerCID);
+ if (ld) {
+ ld->GetShowFrameBorders(&mVisualDebugging);
+ ld->GetShowEventTargetFrameBorder(&mVisualEventDebugging);
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::NewURILoaded()
+{
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ // Reset all the state that should be reset between pages.
+
+ // XXX Some of these should instead be transferred between pages!
+ mEditorMode = false;
+ mVisualDebugging = false;
+ mVisualEventDebugging = false;
+
+ mReflowCounts = false;
+
+ ForceRefresh();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::GetVisualDebugging(bool *aVisualDebugging)
+{
+ *aVisualDebugging = mVisualDebugging;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::SetVisualDebugging(bool aVisualDebugging)
+{
+ nsCOMPtr<nsILayoutDebugger> ld = do_GetService(kLayoutDebuggerCID);
+ if (!ld)
+ return NS_ERROR_UNEXPECTED;
+ mVisualDebugging = aVisualDebugging;
+ ld->SetShowFrameBorders(aVisualDebugging);
+ ForceRefresh();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::GetVisualEventDebugging(bool *aVisualEventDebugging)
+{
+ *aVisualEventDebugging = mVisualEventDebugging;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::SetVisualEventDebugging(bool aVisualEventDebugging)
+{
+ nsCOMPtr<nsILayoutDebugger> ld = do_GetService(kLayoutDebuggerCID);
+ if (!ld)
+ return NS_ERROR_UNEXPECTED;
+ mVisualEventDebugging = aVisualEventDebugging;
+ ld->SetShowEventTargetFrameBorder(aVisualEventDebugging);
+ ForceRefresh();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::GetPaintFlashing(bool *aPaintFlashing)
+{
+ *aPaintFlashing = mPaintFlashing;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::SetPaintFlashing(bool aPaintFlashing)
+{
+ mPaintFlashing = aPaintFlashing;
+ return SetBoolPrefAndRefresh("nglayout.debug.paint_flashing", mPaintFlashing);
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::GetPaintDumping(bool *aPaintDumping)
+{
+ *aPaintDumping = mPaintDumping;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::SetPaintDumping(bool aPaintDumping)
+{
+ mPaintDumping = aPaintDumping;
+ return SetBoolPrefAndRefresh("nglayout.debug.paint_dumping", mPaintDumping);
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::GetInvalidateDumping(bool *aInvalidateDumping)
+{
+ *aInvalidateDumping = mInvalidateDumping;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::SetInvalidateDumping(bool aInvalidateDumping)
+{
+ mInvalidateDumping = aInvalidateDumping;
+ return SetBoolPrefAndRefresh("nglayout.debug.invalidate_dumping", mInvalidateDumping);
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::GetEventDumping(bool *aEventDumping)
+{
+ *aEventDumping = mEventDumping;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::SetEventDumping(bool aEventDumping)
+{
+ mEventDumping = aEventDumping;
+ return SetBoolPrefAndRefresh("nglayout.debug.event_dumping", mEventDumping);
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::GetMotionEventDumping(bool *aMotionEventDumping)
+{
+ *aMotionEventDumping = mMotionEventDumping;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::SetMotionEventDumping(bool aMotionEventDumping)
+{
+ mMotionEventDumping = aMotionEventDumping;
+ return SetBoolPrefAndRefresh("nglayout.debug.motion_event_dumping", mMotionEventDumping);
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::GetCrossingEventDumping(bool *aCrossingEventDumping)
+{
+ *aCrossingEventDumping = mCrossingEventDumping;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::SetCrossingEventDumping(bool aCrossingEventDumping)
+{
+ mCrossingEventDumping = aCrossingEventDumping;
+ return SetBoolPrefAndRefresh("nglayout.debug.crossing_event_dumping", mCrossingEventDumping);
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::GetReflowCounts(bool* aShow)
+{
+ *aShow = mReflowCounts;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::SetReflowCounts(bool aShow)
+{
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ nsCOMPtr<nsIPresShell> shell(pres_shell(mDocShell));
+ if (shell) {
+#ifdef MOZ_REFLOW_PERF
+ shell->SetPaintFrameCount(aShow);
+ SetBoolPrefAndRefresh("layout.reflow.showframecounts", aShow);
+ mReflowCounts = aShow;
+#else
+ printf("************************************************\n");
+ printf("Sorry, you have not built with MOZ_REFLOW_PERF=1\n");
+ printf("************************************************\n");
+#endif
+ }
+ return NS_OK;
+}
+
+static void DumpAWebShell(nsIDocShellTreeItem* aShellItem, FILE* out, int32_t aIndent)
+{
+ nsString name;
+ nsCOMPtr<nsIDocShellTreeItem> parent;
+ int32_t i, n;
+
+ for (i = aIndent; --i >= 0; )
+ fprintf(out, " ");
+
+ fprintf(out, "%p '", static_cast<void*>(aShellItem));
+ aShellItem->GetName(name);
+ aShellItem->GetSameTypeParent(getter_AddRefs(parent));
+ fputs(NS_LossyConvertUTF16toASCII(name).get(), out);
+ fprintf(out, "' parent=%p <\n", static_cast<void*>(parent));
+
+ ++aIndent;
+ aShellItem->GetChildCount(&n);
+ for (i = 0; i < n; ++i) {
+ nsCOMPtr<nsIDocShellTreeItem> child;
+ aShellItem->GetChildAt(i, getter_AddRefs(child));
+ if (child) {
+ DumpAWebShell(child, out, aIndent);
+ }
+ }
+ --aIndent;
+ for (i = aIndent; --i >= 0; )
+ fprintf(out, " ");
+ fputs(">\n", out);
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpWebShells()
+{
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ DumpAWebShell(mDocShell, stdout, 0);
+ return NS_OK;
+}
+
+static
+void
+DumpContentRecur(nsIDocShell* aDocShell, FILE* out)
+{
+#ifdef DEBUG
+ if (nullptr != aDocShell) {
+ fprintf(out, "docshell=%p \n", static_cast<void*>(aDocShell));
+ nsCOMPtr<nsIDocument> doc(document(aDocShell));
+ if (doc) {
+ dom::Element *root = doc->GetRootElement();
+ if (root) {
+ root->List(out);
+ }
+ }
+ else {
+ fputs("no document\n", out);
+ }
+ // dump the frames of the sub documents
+ int32_t i, n;
+ aDocShell->GetChildCount(&n);
+ for (i = 0; i < n; ++i) {
+ nsCOMPtr<nsIDocShellTreeItem> child;
+ aDocShell->GetChildAt(i, getter_AddRefs(child));
+ nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
+ if (child) {
+ DumpContentRecur(childAsShell, 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)
+{
+#ifdef DEBUG
+ fprintf(out, "webshell=%p \n", static_cast<void*>(aDocShell));
+ nsCOMPtr<nsIPresShell> shell(pres_shell(aDocShell));
+ if (shell) {
+ nsIFrame* root = shell->GetRootFrame();
+ if (root) {
+ root->List(out);
+ }
+ }
+ else {
+ fputs("null pres shell\n", out);
+ }
+
+ // dump the frames of the sub documents
+ int32_t i, n;
+ aDocShell->GetChildCount(&n);
+ for (i = 0; i < n; ++i) {
+ nsCOMPtr<nsIDocShellTreeItem> child;
+ aDocShell->GetChildAt(i, getter_AddRefs(child));
+ nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
+ if (childAsShell) {
+ DumpFramesRecur(childAsShell, out);
+ }
+ }
+#endif
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpFrames()
+{
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ DumpFramesRecur(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);
+ }
+
+ // dump the views of the sub documents
+ int32_t i, n;
+ aDocShell->GetChildCount(&n);
+ for (i = 0; i < n; i++) {
+ nsCOMPtr<nsIDocShellTreeItem> child;
+ aDocShell->GetChildAt(i, getter_AddRefs(child));
+ nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
+ if (childAsShell) {
+ DumpViewsRecur(childAsShell, out);
+ }
+ }
+#endif // DEBUG
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpViews()
+{
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+ DumpViewsRecur(mDocShell, stdout);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpStyleSheets()
+{
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+#ifdef DEBUG
+ FILE *out = stdout;
+ nsCOMPtr<nsIPresShell> shell(pres_shell(mDocShell));
+ if (shell)
+ shell->ListStyleSheets(out);
+ else
+ fputs("null pres shell\n", out);
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLayoutDebuggingTools::DumpStyleContexts()
+{
+ NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
+#ifdef DEBUG
+ FILE *out = stdout;
+ nsCOMPtr<nsIPresShell> shell(pres_shell(mDocShell));
+ if (shell) {
+ nsIFrame* root = shell->GetRootFrame();
+ if (!root) {
+ fputs("null root frame\n", out);
+ } else {
+ shell->ListStyleContexts(root, 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
+ nsCOMPtr<nsIPresShell> shell(pres_shell(mDocShell));
+ if (shell) {
+#ifdef MOZ_REFLOW_PERF
+ shell->DumpReflows();
+#else
+ printf("************************************************\n");
+ printf("Sorry, you have not built with MOZ_REFLOW_PERF=1\n");
+ printf("************************************************\n");
+#endif
+ }
+#endif
+ return NS_OK;
+}
+
+void nsLayoutDebuggingTools::ForceRefresh()
+{
+ RefPtr<nsViewManager> vm(view_manager(mDocShell));
+ if (!vm)
+ return;
+ nsView* root = vm->GetRootView();
+ if (root) {
+ vm->InvalidateView(root);
+ }
+}
+
+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 000000000..6d57c1fa1
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsLayoutDebuggingTools.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; 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/. */
+
+#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();
+
+ void ForceRefresh();
+ nsresult GetBoolPref(const char * aPrefName, bool *aValue);
+ nsresult SetBoolPrefAndRefresh(const char * aPrefName, bool aNewValue);
+
+ nsCOMPtr<nsIDocShell> mDocShell;
+
+ bool mEditorMode;
+ bool mVisualDebugging;
+ bool mVisualEventDebugging;
+ bool mPaintFlashing;
+ bool mPaintDumping;
+ bool mInvalidateDumping;
+ bool mEventDumping;
+ bool mMotionEventDumping;
+ bool mCrossingEventDumping;
+ bool mReflowCounts;
+};
+
+#endif
diff --git a/layout/tools/layout-debug/src/nsRegressionTester.cpp b/layout/tools/layout-debug/src/nsRegressionTester.cpp
new file mode 100644
index 000000000..3ac7bddca
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsRegressionTester.cpp
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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.h"
+#include "nsRegressionTester.h"
+
+#include "nsXPIDLString.h"
+#include "nsReadableUtils.h"
+#include "nsIWindowWatcher.h"
+#include "nsPIDOMWindow.h"
+#include "nsIPresShell.h"
+#include "nsIURI.h"
+#include "nsISimpleEnumerator.h"
+#include "nsIDocShell.h"
+#include "nsIContentViewer.h"
+#include "nsIContentViewerFile.h"
+#include "nsIFrame.h"
+#include "nsStyleStruct.h"
+#include "nsIFrameUtil.h"
+#include "nsLayoutCID.h"
+#include "nsIFile.h"
+#include "nsViewManager.h"
+#include "nsView.h"
+
+
+
+static NS_DEFINE_CID(kFrameUtilCID, NS_FRAME_UTIL_CID);
+
+
+nsRegressionTester::nsRegressionTester()
+{
+}
+
+nsRegressionTester::~nsRegressionTester()
+{
+}
+
+NS_IMPL_ISUPPORTS(nsRegressionTester, nsILayoutRegressionTester)
+
+NS_IMETHODIMP
+nsRegressionTester::DumpFrameModel(mozIDOMWindow* aWindowToDump,
+ nsIFile *aDestFile,
+ uint32_t aFlagsMask, int32_t *aResult)
+{
+ NS_ENSURE_ARG(aWindowToDump);
+ NS_ENSURE_ARG_POINTER(aResult);
+
+ *aResult = DUMP_RESULT_ERROR;
+
+#ifndef DEBUG
+ return NS_ERROR_NOT_AVAILABLE;
+#else
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ uint32_t busyFlags;
+ bool stillLoading;
+
+ auto* windowToDump = nsPIDOMWindowInner::From(aWindowToDump);
+
+ nsCOMPtr<nsIDocShell> docShell = windowToDump->GetDocShell();
+
+ // find out if the document is loaded
+ docShell->GetBusyFlags(&busyFlags);
+ stillLoading = busyFlags & (nsIDocShell::BUSY_FLAGS_BUSY |
+ nsIDocShell::BUSY_FLAGS_PAGE_LOADING);
+ if (stillLoading)
+ {
+ *aResult = DUMP_RESULT_LOADING;
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
+
+ nsIFrame* root = presShell->GetRootFrame();
+
+ FILE* fp = stdout;
+ if (aDestFile)
+ {
+ rv = aDestFile->OpenANSIFileDesc("w", &fp);
+ if (NS_FAILED(rv)) return rv;
+ }
+ if (aFlagsMask & DUMP_FLAGS_MASK_PRINT_MODE) {
+ nsCOMPtr <nsIContentViewer> viewer;
+ docShell->GetContentViewer(getter_AddRefs(viewer));
+ if (viewer){
+ nsCOMPtr<nsIContentViewerFile> viewerFile = do_QueryInterface(viewer);
+ if (viewerFile) {
+ viewerFile->Print(true, fp, nullptr);
+ }
+ }
+ }
+ else {
+ root->DumpRegressionData(presShell->GetPresContext(), fp, 0);
+ }
+ if (fp != stdout)
+ fclose(fp);
+ *aResult = DUMP_RESULT_COMPLETED;
+ return NS_OK;
+#endif
+}
+
+NS_IMETHODIMP
+nsRegressionTester::CompareFrameModels(nsIFile *aBaseFile, nsIFile *aVerFile,
+ uint32_t aFlags, bool *aResult)
+{
+ NS_ENSURE_ARG(aBaseFile);
+ NS_ENSURE_ARG(aVerFile);
+ NS_ENSURE_ARG_POINTER(aResult);
+
+ *aResult = false;
+
+ nsresult rv;
+ FILE* baseFile;
+ rv = aBaseFile->OpenANSIFileDesc("r", &baseFile);
+ if (NS_FAILED(rv)) return rv;
+
+ FILE* verFile;
+ rv = aVerFile->OpenANSIFileDesc("r", &verFile);
+ if (NS_FAILED(rv)) {
+ fclose(baseFile);
+ return rv;
+ }
+
+ nsCOMPtr<nsIFrameUtil> frameUtil = do_CreateInstance(kFrameUtilCID, &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ int32_t outputLevel = (aFlags == COMPARE_FLAGS_VERBOSE) ? 0 : 1;
+ rv = frameUtil->CompareRegressionData(baseFile, verFile, outputLevel);
+ // CompareRegressionData closes |baseFile| and |verFile|.
+ } else {
+ fclose(verFile);
+ fclose(baseFile);
+ }
+
+ *aResult = NS_FAILED(rv);
+ return NS_OK;
+}
diff --git a/layout/tools/layout-debug/src/nsRegressionTester.h b/layout/tools/layout-debug/src/nsRegressionTester.h
new file mode 100644
index 000000000..b0f36f9b5
--- /dev/null
+++ b/layout/tools/layout-debug/src/nsRegressionTester.h
@@ -0,0 +1,32 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * 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 nsRegressionTester_h__
+#define nsRegressionTester_h__
+
+#include "nsCOMPtr.h"
+
+#include "nsILayoutRegressionTester.h"
+#include "nsILayoutDebugger.h"
+
+//*****************************************************************************
+//*** nsRegressionTester
+//*****************************************************************************
+class nsRegressionTester : public nsILayoutRegressionTester
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSILAYOUTREGRESSIONTESTER
+
+ nsRegressionTester();
+
+protected:
+ virtual ~nsRegressionTester();
+};
+
+
+
+#endif /* nsRegressionTester_h__ */
diff --git a/layout/tools/layout-debug/tests/unit/test_componentsRegistered.js b/layout/tools/layout-debug/tests/unit/test_componentsRegistered.js
new file mode 100644
index 000000000..6a528b768
--- /dev/null
+++ b/layout/tools/layout-debug/tests/unit/test_componentsRegistered.js
@@ -0,0 +1,8 @@
+function run_test() {
+ do_check_true("@mozilla.org/layout-debug/regressiontester;1" in
+ Components.classes);
+ do_check_true("@mozilla.org/layout-debug/layout-debuggingtools;1" in
+ Components.classes);
+ do_check_true("@mozilla.org/commandlinehandler/general-startup;1?type=layoutdebug" in
+ Components.classes);
+} \ No newline at end of file
diff --git a/layout/tools/layout-debug/tests/unit/xpcshell.ini b/layout/tools/layout-debug/tests/unit/xpcshell.ini
new file mode 100644
index 000000000..e0ee46a2c
--- /dev/null
+++ b/layout/tools/layout-debug/tests/unit/xpcshell.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+head =
+tail =
+
+[test_componentsRegistered.js]
diff --git a/layout/tools/layout-debug/ui/content/layoutdebug-overlay.xul b/layout/tools/layout-debug/ui/content/layoutdebug-overlay.xul
new file mode 100644
index 000000000..df34e0953
--- /dev/null
+++ b/layout/tools/layout-debug/ui/content/layoutdebug-overlay.xul
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+
+<!--
+ -
+ - 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/. -->
+
+
+<!--
+ This file contains the nodes that will be overlayed on top of
+ <chrome://communicator/content/tasksOverlay.xul>.
+ Declare XML entites that this file refers to in layoutdebug-overlay.dtd.
+ -->
+
+<!DOCTYPE window SYSTEM "chrome://layoutdebug/locale/layoutdebug-overlay.dtd" >
+
+<overlay id="layoutdebugTaskMenuID"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<!-- SeaMonkey -->
+<menupopup id="taskPopup">
+ <menuitem label="&ldbCmd.label;"
+ accesskey="&ldbCmd.accesskey;"
+ oncommand="toOpenWindowByType('mozapp:layoutdebug',
+ 'chrome://layoutdebug/content/');"/>
+</menupopup>
+
+<!-- Firefox -->
+<menupopup id="menu_ToolsPopup">
+ <menuitem label="&ldbCmd.label;"
+ accesskey="&ldbCmd.accesskey;"
+ insertafter="javascriptConsole"
+ oncommand="toOpenWindowByType('mozapp:layoutdebug',
+ 'chrome://layoutdebug/content/');"/>
+</menupopup>
+
+</overlay>
diff --git a/layout/tools/layout-debug/ui/content/layoutdebug.js b/layout/tools/layout-debug/ui/content/layoutdebug.js
new file mode 100644
index 000000000..71142fa39
--- /dev/null
+++ b/layout/tools/layout-debug/ui/content/layoutdebug.js
@@ -0,0 +1,434 @@
+/* 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/. */
+
+var gBrowser;
+var gProgressListener;
+var gDebugger;
+var gRTestIndexList;
+var gRTestURLList = null;
+
+const nsILayoutDebuggingTools = Components.interfaces.nsILayoutDebuggingTools;
+const nsIDocShell = Components.interfaces.nsIDocShell;
+const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
+
+const NS_LAYOUT_DEBUGGINGTOOLS_CONTRACTID = "@mozilla.org/layout-debug/layout-debuggingtools;1";
+
+
+function nsLDBBrowserContentListener()
+{
+ this.init();
+}
+
+nsLDBBrowserContentListener.prototype = {
+
+ init : function()
+ {
+ this.mStatusText = document.getElementById("status-text");
+ this.mURLBar = document.getElementById("urlbar");
+ this.mForwardButton = document.getElementById("forward-button");
+ this.mBackButton = document.getElementById("back-button");
+ this.mStopButton = document.getElementById("stop-button");
+ },
+
+ QueryInterface : function(aIID)
+ {
+ if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
+ aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
+ aIID.equals(Components.interfaces.nsISupports))
+ return this;
+ throw Components.results.NS_NOINTERFACE;
+ },
+
+ // nsIWebProgressListener implementation
+ onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
+ {
+ if (!(aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) ||
+ aWebProgress != gBrowser.webProgress)
+ return;
+
+ if (aStateFlags & nsIWebProgressListener.STATE_START) {
+ this.setButtonEnabled(this.mStopButton, true);
+ this.setButtonEnabled(this.mForwardButton, gBrowser.canGoForward);
+ this.setButtonEnabled(this.mBackButton, gBrowser.canGoBack);
+ this.mStatusText.value = "loading...";
+ this.mLoading = true;
+
+ } else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
+ this.setButtonEnabled(this.mStopButton, false);
+ this.mStatusText.value = this.mURLBar.value + " loaded";
+
+ if (gRTestURLList && this.mLoading) {
+ // Let other things happen in the first 20ms, since this
+ // doesn't really seem to be when the page is done loading.
+ setTimeout("gRTestURLList.doneURL()", 20);
+ }
+ this.mLoading = false;
+ }
+ },
+
+ onProgressChange : function(aWebProgress, aRequest,
+ aCurSelfProgress, aMaxSelfProgress,
+ aCurTotalProgress, aMaxTotalProgress)
+ {
+ },
+
+ onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags)
+ {
+ this.mURLBar.value = aLocation.spec;
+ this.setButtonEnabled(this.mForwardButton, gBrowser.canGoForward);
+ this.setButtonEnabled(this.mBackButton, gBrowser.canGoBack);
+ },
+
+ onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
+ {
+ this.mStatusText.value = aMessage;
+ },
+
+ onSecurityChange : function(aWebProgress, aRequest, aState)
+ {
+ },
+
+ // non-interface methods
+ setButtonEnabled : function(aButtonElement, aEnabled)
+ {
+ if (aEnabled)
+ aButtonElement.removeAttribute("disabled");
+ else
+ aButtonElement.setAttribute("disabled", "true");
+ },
+
+ mStatusText : null,
+ mURLBar : null,
+ mForwardButton : null,
+ mBackButton : null,
+ mStopButton : null,
+
+ mLoading : false
+
+}
+
+function OnLDBLoad()
+{
+ gBrowser = document.getElementById("browser");
+
+ gProgressListener = new nsLDBBrowserContentListener();
+ gBrowser.addProgressListener(gProgressListener);
+
+ gDebugger = Components.classes[NS_LAYOUT_DEBUGGINGTOOLS_CONTRACTID].
+ createInstance(nsILayoutDebuggingTools);
+
+ if (window.arguments && window.arguments[0])
+ gBrowser.loadURI(window.arguments[0]);
+ else
+ gBrowser.goHome();
+
+ gDebugger.init(gBrowser.contentWindow);
+
+ checkPersistentMenus();
+ gRTestIndexList = new RTestIndexList();
+}
+
+function checkPersistentMenu(item)
+{
+ var menuitem = document.getElementById("menu_" + item);
+ menuitem.setAttribute("checked", gDebugger[item]);
+}
+
+function checkPersistentMenus()
+{
+ // Restore the toggles that are stored in prefs.
+ checkPersistentMenu("paintFlashing");
+ checkPersistentMenu("paintDumping");
+ checkPersistentMenu("invalidateDumping");
+ checkPersistentMenu("eventDumping");
+ checkPersistentMenu("motionEventDumping");
+ checkPersistentMenu("crossingEventDumping");
+ checkPersistentMenu("reflowCounts");
+}
+
+
+function OnLDBUnload()
+{
+ gBrowser.removeProgressListener(gProgressListener);
+}
+
+function toggle(menuitem)
+{
+ // trim the initial "menu_"
+ var feature = menuitem.id.substring(5);
+ gDebugger[feature] = menuitem.getAttribute("checked") == "true";
+}
+
+function openFile()
+{
+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var fp = Components.classes["@mozilla.org/filepicker;1"]
+ .createInstance(nsIFilePicker);
+ fp.init(window, "Select a File", nsIFilePicker.modeOpen);
+ fp.appendFilters(nsIFilePicker.filterHTML | nsIFilePicker.filterAll);
+ if (fp.show() == nsIFilePicker.returnOK && fp.fileURL.spec &&
+ fp.fileURL.spec.length > 0) {
+ gBrowser.loadURI(fp.fileURL.spec);
+ }
+}
+const LDB_RDFNS = "http://mozilla.org/newlayout/LDB-rdf#";
+const NC_RDFNS = "http://home.netscape.com/NC-rdf#";
+
+function RTestIndexList() {
+ this.init();
+}
+
+RTestIndexList.prototype = {
+
+ init : function()
+ {
+ const nsIPrefService = Components.interfaces.nsIPrefService;
+ const PREF_SERVICE_CONTRACTID = "@mozilla.org/preferences-service;1";
+ const PREF_BRANCH_NAME = "layout_debugger.rtest_url.";
+ const nsIRDFService = Components.interfaces.nsIRDFService;
+ const RDF_SERVICE_CONTRACTID = "@mozilla.org/rdf/rdf-service;1";
+ const nsIRDFDataSource = Components.interfaces.nsIRDFDataSource;
+ const RDF_DATASOURCE_CONTRACTID =
+ "@mozilla.org/rdf/datasource;1?name=in-memory-datasource";
+
+ this.mPrefService = Components.classes[PREF_SERVICE_CONTRACTID].
+ getService(nsIPrefService);
+ this.mPrefBranch = this.mPrefService.getBranch(PREF_BRANCH_NAME);
+
+ this.mRDFService = Components.classes[RDF_SERVICE_CONTRACTID].
+ getService(nsIRDFService);
+ this.mDataSource = Components.classes[RDF_DATASOURCE_CONTRACTID].
+ createInstance(nsIRDFDataSource);
+
+ this.mLDB_Root = this.mRDFService.GetResource(LDB_RDFNS + "Root");
+ this.mNC_Name = this.mRDFService.GetResource(NC_RDFNS + "name");
+ this.mNC_Child = this.mRDFService.GetResource(NC_RDFNS + "child");
+
+ this.load();
+
+ document.getElementById("menu_RTest_baseline").database.
+ AddDataSource(this.mDataSource);
+ document.getElementById("menu_RTest_verify").database.
+ AddDataSource(this.mDataSource);
+ document.getElementById("menu_RTest_remove").database.
+ AddDataSource(this.mDataSource);
+ },
+
+ save : function()
+ {
+ this.mPrefBranch.deleteBranch("");
+
+ const nsIRDFLiteral = Components.interfaces.nsIRDFLiteral;
+ const nsIRDFResource = Components.interfaces.nsIRDFResource;
+ var etor = this.mDataSource.GetTargets(this.mLDB_Root,
+ this.mNC_Child, true);
+ var i = 0;
+ while (etor.hasMoreElements()) {
+ var resource = etor.getNext().QueryInterface(nsIRDFResource);
+ var literal = this.mDataSource.GetTarget(resource, this.mNC_Name, true);
+ literal = literal.QueryInterface(nsIRDFLiteral);
+ this.mPrefBranch.setCharPref(i.toString(), literal.Value);
+ ++i;
+ }
+
+ this.mPrefService.savePrefFile(null);
+ },
+
+ load : function()
+ {
+ var prefList = this.mPrefBranch.getChildList("");
+
+ var i = 0;
+ for (var pref in prefList) {
+ var file = this.mPrefBranch.getCharPref(pref);
+ var resource = this.mRDFService.GetResource(file);
+ var literal = this.mRDFService.GetLiteral(file);
+ this.mDataSource.Assert(this.mLDB_Root, this.mNC_Child, resource, true);
+ this.mDataSource.Assert(resource, this.mNC_Name, literal, true);
+ ++i;
+ }
+
+ },
+
+ /* Add a new list of regression tests to the menus. */
+ add : function()
+ {
+ const nsIFilePicker = Components.interfaces.nsIFilePicker;
+ const NS_FILEPICKER_CONTRACTID = "@mozilla.org/filepicker;1";
+
+ var fp = Components.classes[NS_FILEPICKER_CONTRACTID].
+ createInstance(nsIFilePicker);
+
+ // XXX l10n (but this is just for 5 developers, so no problem)
+ fp.init(window, "New Regression Test List", nsIFilePicker.modeOpen);
+ fp.appendFilters(nsIFilePicker.filterAll);
+ fp.defaultString = "rtest.lst";
+ if (fp.show() != nsIFilePicker.returnOK)
+ return;
+
+ var file = fp.file.persistentDescriptor;
+ var resource = this.mRDFService.GetResource(file);
+ var literal = this.mRDFService.GetLiteral(file);
+ this.mDataSource.Assert(this.mLDB_Root, this.mNC_Child, resource, true);
+ this.mDataSource.Assert(resource, this.mNC_Name, literal, true);
+
+ this.save();
+
+ },
+
+ remove : function(file)
+ {
+ var resource = this.mRDFService.GetResource(file);
+ var literal = this.mRDFService.GetLiteral(file);
+ this.mDataSource.Unassert(this.mLDB_Root, this.mNC_Child, resource);
+ this.mDataSource.Unassert(resource, this.mNC_Name, literal);
+
+ this.save();
+ },
+
+ mPrefBranch : null,
+ mPrefService : null,
+ mRDFService : null,
+ mDataSource : null,
+ mLDB_Root : null,
+ mNC_Child : null,
+ mNC_Name : null
+}
+
+const nsIFileInputStream = Components.interfaces.nsIFileInputStream;
+const nsILineInputStream = Components.interfaces.nsILineInputStream;
+const nsIFile = Components.interfaces.nsIFile;
+const nsILocalFile = Components.interfaces.nsILocalFile;
+const nsIFileURL = Components.interfaces.nsIFileURL;
+const nsIIOService = Components.interfaces.nsIIOService;
+const nsILayoutRegressionTester = Components.interfaces.nsILayoutRegressionTester;
+
+const NS_LOCAL_FILE_CONTRACTID = "@mozilla.org/file/local;1";
+const IO_SERVICE_CONTRACTID = "@mozilla.org/network/io-service;1";
+const NS_LOCALFILEINPUTSTREAM_CONTRACTID =
+ "@mozilla.org/network/file-input-stream;1";
+
+
+function RunRTest(aFilename, aIsBaseline, aIsPrinting)
+{
+ if (gRTestURLList) {
+ // XXX Does alert work?
+ alert("Already running regression test.\n");
+ return;
+ }
+ dump("Running " + (aIsBaseline?"baseline":"verify") +
+ (aIsPrinting?" PrintMode":"") + " test for " + aFilename + ".\n");
+
+ var listFile = Components.classes[NS_LOCAL_FILE_CONTRACTID].
+ createInstance(nsILocalFile);
+ listFile.persistentDescriptor = aFilename;
+ gRTestURLList = new RTestURLList(listFile, aIsBaseline, aIsPrinting);
+ gRTestURLList.startURL();
+}
+
+function RTestURLList(aLocalFile, aIsBaseline, aIsPrinting) {
+ this.init(aLocalFile, aIsBaseline, aIsPrinting);
+}
+
+RTestURLList.prototype = {
+ init : function(aLocalFile, aIsBaseline, aIsPrinting)
+ {
+ this.mIsBaseline = aIsBaseline;
+ this.mIsPrinting = aIsPrinting;
+ this.mURLs = new Array();
+ this.readFileList(aLocalFile);
+ this.mRegressionTester =
+ Components.classes["@mozilla.org/layout-debug/regressiontester;1"].
+ createInstance(nsILayoutRegressionTester)
+ },
+
+ readFileList : function(aLocalFile)
+ {
+ var ios = Components.classes[IO_SERVICE_CONTRACTID]
+ .getService(nsIIOService);
+ var dirURL = ios.newFileURI(aLocalFile.parent);
+
+ var fis = Components.classes[NS_LOCALFILEINPUTSTREAM_CONTRACTID].
+ createInstance(nsIFileInputStream);
+ fis.init(aLocalFile, -1, -1, false);
+ var lis = fis.QueryInterface(nsILineInputStream);
+
+ var line = {value:null};
+ do {
+ var more = lis.readLine(line);
+ var str = line.value;
+ str = /^[^#]*/.exec(str); // strip everything after "#"
+ str = /\S*/.exec(str); // take the first chunk of non-whitespace
+ if (!str || str == "")
+ continue;
+
+ var item = dirURL.resolve(str);
+ if (item.match(/\/rtest.lst$/)) {
+ var itemurl = ios.newURI(item, null, null);
+ itemurl = itemurl.QueryInterface(nsIFileURL);
+ this.readFileList(itemurl.file);
+ } else {
+ this.mURLs.push( {url:item, dir:aLocalFile.parent, relurl:str} );
+ }
+ } while (more);
+ },
+
+ doneURL : function()
+ {
+ var basename =
+ String(this.mCurrentURL.relurl).replace(/[:=&.\/?]/g, "_") + ".rgd";
+
+ var data = this.mCurrentURL.dir.clone();
+ data.append( this.mIsBaseline ? "baseline" : "verify");
+ if (!data.exists())
+ data.create(nsIFile.DIRECTORY_TYPE, 0o777)
+ data.append(basename);
+
+ dump("Writing regression data to " +
+ data.QueryInterface(nsILocalFile).persistentDescriptor + "\n");
+ if (this.mIsPrinting) {
+ this.mRegressionTester.dumpFrameModel(gBrowser.contentWindow, data,
+ nsILayoutRegressionTester.DUMP_FLAGS_MASK_PRINT_MODE);
+ }
+ else {
+ this.mRegressionTester.dumpFrameModel(gBrowser.contentWindow, data, 0);
+ }
+
+
+
+ if (!this.mIsBaseline) {
+ var base_data = this.mCurrentURL.dir.clone();
+ base_data.append("baseline");
+ base_data.append(basename);
+ dump("Comparing to regression data from " +
+ base_data.QueryInterface(nsILocalFile).persistentDescriptor + "\n");
+ var filesDiffer =
+ this.mRegressionTester.compareFrameModels(base_data, data,
+ nsILayoutRegressionTester.COMPARE_FLAGS_BRIEF)
+ dump("Comparison for " + this.mCurrentURL.url + " " +
+ (filesDiffer ? "failed" : "passed") + ".\n");
+ }
+
+ this.mCurrentURL = null;
+
+ this.startURL();
+ },
+
+ startURL : function()
+ {
+ this.mCurrentURL = this.mURLs.shift();
+ if (!this.mCurrentURL) {
+ gRTestURLList = null;
+ return;
+ }
+
+ gBrowser.loadURI(this.mCurrentURL.url);
+ },
+
+ mURLs : null,
+ mCurrentURL : null, // url (string), dir (nsIFileURL), relurl (string)
+ mIsBaseline : null,
+ mRegressionTester : null,
+ mIsPrinting : null
+}
diff --git a/layout/tools/layout-debug/ui/content/layoutdebug.xul b/layout/tools/layout-debug/ui/content/layoutdebug.xul
new file mode 100644
index 000000000..8de04847f
--- /dev/null
+++ b/layout/tools/layout-debug/ui/content/layoutdebug.xul
@@ -0,0 +1,187 @@
+<?xml version="1.0"?>
+<!-- vim: set shiftwidth=2 tabstop=8 expandtab :
+ -
+ -
+ - 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 window [
+ <!ENTITY % layoutdebugDTD
+ SYSTEM "chrome://layoutdebug/locale/layoutdebug.dtd">
+ %layoutdebugDTD;
+
+ <!ENTITY W3C_RDFNS "http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <!ENTITY NC_RDFNS "http://home.netscape.com/NC-rdf#">
+ <!ENTITY LDB_RDFNS "http://mozilla.org/newlayout/LDB-rdf#">
+]>
+
+<?xml-stylesheet href="chrome://communicator/skin/" type="text/css" ?>
+
+<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
+<?xul-overlay href="chrome://communicator/content/tasksOverlay.xul"?>
+
+<!--
+
+ NOTE: Because this window is used for layout regression tests, the
+ persist attribute should never be used on anything. Otherwise there
+ is a risk of running baseline and verify runs under different
+ conditions.
+
+-->
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:rdf="&W3C_RDFNS;"
+ id="main-window"
+ align="stretch"
+ title="&ldb.MainWindow.title;"
+ titlemodifier="&ldb.MainWindow.title;"
+ contenttitlesetting="true"
+ titlemenuseparator=" - "
+ windowtype="mozapp:layoutdebug"
+ onload="OnLDBLoad();"
+ onunload="OnLDBUnload();"
+ width="610" height="450"
+ screenX="4" screenY="4"
+ >
+
+ <script src="chrome://layoutdebug/content/layoutdebug.js"/>
+
+ <commandset id="tasksCommands">
+ <command id="cmd_close" oncommand="window.close();"/>
+ <command id="cmd_quit"/>
+ </commandset>
+
+ <keyset id="tasksKeys">
+ <key id="openFileKb" key="&ldb.Open.commandkey;" oncommand="openFile()" modifiers="accel"/>
+ <key id="key_close"/>
+ <key id="key_quit"/>
+ </keyset>
+
+ <vbox flex="1">
+
+ <toolbox>
+ <menubar id="main-menubar" grippyhidden="true">
+ <menu id="menu_file" label="File" accesskey="F">
+ <menupopup id="menu_FilePopup">
+ <menuitem id="menu_open" label="&ldb.Open.label;" accesskey="&ldb.Open.accesskey;" key="openFileKb" oncommand="openFile()"/>
+ <menuitem id="menu_close" label="Close" accesskey="C" oncommand="window.close();"/>
+ </menupopup>
+ </menu>
+ <menu label="&ldb.RegressionTestMenu.label;"
+ accesskey="&ldb.RegressionTestMenu.accesskey;">
+ <menupopup>
+ <menuitem type="checkbox" id="menu_RTestPrintMode" label="&ldb.RegressionPrintMode.label;" accesskey="&ldb.RegressionPrintMode.accesskey;"/>
+ <menu label="&ldb.RunBaselineMenu.label;"
+ accesskey="&ldb.RunBaselineMenu.accesskey;"
+ id="menu_RTest_baseline"
+ datasources="rdf:null"
+ containment="&NC_RDFNS;child"
+ ref="&LDB_RDFNS;Root">
+ <template>
+ <menupopup>
+ <menuitem uri="rdf:*"
+ label="rdf:&NC_RDFNS;name"
+ name="rdf:&NC_RDFNS;name"
+ oncommand="RunRTest(this.getAttribute('name'), true, document.getElementById('menu_RTestPrintMode').getAttribute('checked'));" />
+ </menupopup>
+ </template>
+ </menu>
+ <menu label="&ldb.RunVerifyMenu.label;"
+ accesskey="&ldb.RunVerifyMenu.accesskey;"
+ id="menu_RTest_verify"
+ datasources="rdf:null"
+ containment="&NC_RDFNS;child"
+ ref="&LDB_RDFNS;Root">
+ <template>
+ <menupopup>
+ <menuitem uri="rdf:*"
+ label="rdf:&NC_RDFNS;name"
+ name="rdf:&NC_RDFNS;name"
+ oncommand="RunRTest(this.getAttribute('name'), false, document.getElementById('menu_RTestPrintMode').getAttribute('checked'));" />
+ </menupopup>
+ </template>
+ </menu>
+ <menuseparator />
+ <menuitem id="menu_AddNewList" label="&ldb.AddNewList.label;" accesskey="&ldb.AddNewList.accesskey;" oncommand="gRTestIndexList.add();" />
+ <menu label="&ldb.RemoveListMenu.label;"
+ accesskey="&ldb.RemoveListMenu.accesskey;"
+ id="menu_RTest_remove"
+ datasources="rdf:null"
+ containment="&NC_RDFNS;child"
+ ref="&LDB_RDFNS;Root">
+ <template>
+ <menupopup>
+ <menuitem uri="rdf:*"
+ label="rdf:&NC_RDFNS;name"
+ name="rdf:&NC_RDFNS;name"
+ oncommand="gRTestIndexList.remove(this.getAttribute('name'));" />
+ </menupopup>
+ </template>
+ </menu>
+ </menupopup>
+ </menu>
+ <menu label="&ldb.ToggleMenu.label;"
+ accesskey="&ldb.ToggleMenu.accesskey;">
+ <menupopup>
+ <menuitem type="checkbox" id="menu_visualDebugging" label="&ldb.visualDebugging.label;" accesskey="&ldb.visualDebugging.accesskey;" oncommand="toggle(this);" />
+ <menuitem type="checkbox" id="menu_visualEventDebugging" label="&ldb.visualEventDebugging.label;" accesskey="&ldb.visualEventDebugging.accesskey;" oncommand="toggle(this);" />
+ <menuseparator />
+ <menuitem type="checkbox" id="menu_paintFlashing" label="&ldb.paintFlashing.label;" accesskey="&ldb.paintFlashing.accesskey;" oncommand="toggle(this);" />
+ <menuitem type="checkbox" id="menu_paintDumping" label="&ldb.paintDumping.label;" accesskey="&ldb.paintDumping.accesskey;" oncommand="toggle(this);" />
+ <menuitem type="checkbox" id="menu_invalidateDumping" label="&ldb.invalidateDumping.label;" accesskey="&ldb.invalidateDumping.accesskey;" oncommand="toggle(this);" />
+ <menuseparator />
+ <menuitem type="checkbox" id="menu_eventDumping" label="&ldb.eventDumping.label;" accesskey="&ldb.eventDumping.accesskey;" oncommand="toggle(this);" />
+ <menuitem type="checkbox" id="menu_motionEventDumping" label="&ldb.motionEventDumping.label;" accesskey="&ldb.motionEventDumping.accesskey;" oncommand="toggle(this);" />
+ <menuitem type="checkbox" id="menu_crossingEventDumping" label="&ldb.crossingEventDumping.label;" accesskey="&ldb.crossingEventDumping.accesskey;" oncommand="toggle(this);" />
+ <menuseparator />
+ <menuitem type="checkbox" id="menu_reflowCounts" label="&ldb.reflowCounts.label;" accesskey="&ldb.reflowCounts.accesskey;" oncommand="toggle(this);" />
+ </menupopup>
+ </menu>
+ <menu label="&ldb.DumpMenu.label;"
+ accesskey="&ldb.DumpMenu.accesskey;">
+ <menupopup>
+ <menuitem id="menu_dumpWebShells" label="&ldb.dumpWebShells.label;" accesskey="&ldb.dumpWebShells.accesskey;" oncommand="gDebugger.dumpWebShells();" />
+ <menuitem id="menu_dumpContent" label="&ldb.dumpContent.label;" accesskey="&ldb.dumpContent.accesskey;" oncommand="gDebugger.dumpContent();" />
+ <menuitem id="menu_dumpFrames" label="&ldb.dumpFrames.label;" accesskey="&ldb.dumpFrames.accesskey;" oncommand="gDebugger.dumpFrames();" />
+ <menuitem id="menu_dumpViews" label="&ldb.dumpViews.label;" accesskey="&ldb.dumpViews.accesskey;" oncommand="gDebugger.dumpViews();" />
+ <menuseparator />
+ <menuitem id="menu_dumpStyleSheets" label="&ldb.dumpStyleSheets.label;" accesskey="&ldb.dumpStyleSheets.accesskey;" oncommand="gDebugger.dumpStyleSheets();" />
+ <menuitem id="menu_dumpStyleContexts" label="&ldb.dumpStyleContexts.label;" accesskey="&ldb.dumpStyleContexts.accesskey;" oncommand="gDebugger.dumpStyleContexts();" />
+ <menuseparator />
+ <menuitem id="menu_dumpReflowStats" label="&ldb.dumpReflowStats.label;" accesskey="&ldb.dumpReflowStats.accesskey;" oncommand="gDebugger.dumpReflowStats();" />
+ </menupopup>
+ </menu>
+ <menu id="tasksMenu"/>
+ <menu id="windowMenu"/>
+ <menu id="menu_Help"/>
+ </menubar>
+
+ <toolbar grippyhidden="true">
+ <toolbarbutton id="back-button" class="toolbarbutton-1"
+ label="&ldb.BackButton.label;"
+ oncommand="gBrowser.goBack();" />
+ <toolbarbutton id="forward-button" class="toolbarbutton-1"
+ label="&ldb.ForwardButton.label;"
+ oncommand="gBrowser.goForward();" />
+ <toolbarbutton id="reload-button" class="toolbarbutton-1"
+ label="&ldb.ReloadButton.label;"
+ oncommand="gBrowser.reload();" />
+ <toolbarbutton id="stop-button" class="toolbarbutton-1"
+ label="&ldb.StopButton.label;"
+ oncommand="gBrowser.stop();" />
+
+ <textbox id="urlbar" flex="1"
+ onkeypress="if (event.keyCode == 13)
+ gBrowser.loadURI(this.value);" />
+ </toolbar>
+ </toolbox>
+
+ <browser flex="1" id="browser" type="content-primary"
+ homepage="about:blank" />
+
+ <hbox>
+ <description id="status-text" value="" />
+ </hbox>
+ </vbox>
+</window>
diff --git a/layout/tools/layout-debug/ui/jar.mn b/layout/tools/layout-debug/ui/jar.mn
new file mode 100644
index 000000000..91924bd91
--- /dev/null
+++ b/layout/tools/layout-debug/ui/jar.mn
@@ -0,0 +1,14 @@
+# 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/.
+
+layoutdebug.jar:
+% content layoutdebug %content/layoutdebug/
+% overlay chrome://browser/content/browser.xul chrome://layoutdebug/content/layoutdebug-overlay.xul
+% overlay chrome://communicator/content/tasksOverlay.xul chrome://layoutdebug/content/layoutdebug-overlay.xul
+% locale layoutdebug en-US %locale/en-US/layoutdebug/
+ content/layoutdebug/layoutdebug.xul (content/layoutdebug.xul)
+ content/layoutdebug/layoutdebug.js (content/layoutdebug.js)
+ content/layoutdebug/layoutdebug-overlay.xul (content/layoutdebug-overlay.xul)
+ locale/en-US/layoutdebug/layoutdebug.dtd (locale/en-US/layoutdebug.dtd)
+ locale/en-US/layoutdebug/layoutdebug-overlay.dtd (locale/en-US/layoutdebug-overlay.dtd)
diff --git a/layout/tools/layout-debug/ui/locale/en-US/layoutdebug-overlay.dtd b/layout/tools/layout-debug/ui/locale/en-US/layoutdebug-overlay.dtd
new file mode 100644
index 000000000..47996b2ec
--- /dev/null
+++ b/layout/tools/layout-debug/ui/locale/en-US/layoutdebug-overlay.dtd
@@ -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/. -->
+
+<!ENTITY ldbCmd.label "Layout Debugger">
+<!ENTITY ldbCmd.accesskey "L">
diff --git a/layout/tools/layout-debug/ui/locale/en-US/layoutdebug.dtd b/layout/tools/layout-debug/ui/locale/en-US/layoutdebug.dtd
new file mode 100644
index 000000000..747ae9ae1
--- /dev/null
+++ b/layout/tools/layout-debug/ui/locale/en-US/layoutdebug.dtd
@@ -0,0 +1,76 @@
+<!--
+ -
+ - 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/. -->
+
+<!ENTITY app.name.short "layoutdebug">
+<!ENTITY app.name.long "Layout Debugger">
+<!ENTITY app.version "prototype_a">
+<!ENTITY app.author "mozilla.org">
+
+<!ENTITY ldb.MainWindow.title "Layout Debugger">
+
+<!ENTITY ldb.Open.label "Open File…">
+<!ENTITY ldb.Open.accesskey "o">
+<!ENTITY ldb.Open.commandkey "o">
+
+<!ENTITY ldb.BackButton.label "Back">
+<!ENTITY ldb.ForwardButton.label "Forward">
+<!ENTITY ldb.ReloadButton.label "Reload">
+<!ENTITY ldb.StopButton.label "Stop">
+
+
+<!ENTITY ldb.RegressionTestMenu.label "Regression-Test">
+<!ENTITY ldb.RegressionTestMenu.accesskey "R">
+<!ENTITY ldb.RunBaselineMenu.label "Run Baseline">
+<!ENTITY ldb.RunBaselineMenu.accesskey "B">
+<!ENTITY ldb.RunVerifyMenu.label "Run Verify">
+<!ENTITY ldb.RunVerifyMenu.accesskey "V">
+<!ENTITY ldb.RegressionPrintMode.label "Print Mode">
+<!ENTITY ldb.RegressionPrintMode.accesskey "P">
+<!ENTITY ldb.AddNewList.label "Add New List…">
+<!ENTITY ldb.AddNewList.accesskey "A">
+<!ENTITY ldb.RemoveListMenu.label "Remove List">
+<!ENTITY ldb.RemoveListMenu.accesskey "R">
+
+
+<!ENTITY ldb.ToggleMenu.label "Toggle">
+<!ENTITY ldb.ToggleMenu.accesskey "T">
+
+<!ENTITY ldb.visualDebugging.label "Visual Debugging">
+<!ENTITY ldb.visualDebugging.accesskey "V">
+<!ENTITY ldb.visualEventDebugging.label "Visual Event Debugging">
+<!ENTITY ldb.visualEventDebugging.accesskey "E">
+<!ENTITY ldb.paintFlashing.label "Paint Flashing">
+<!ENTITY ldb.paintFlashing.accesskey "F">
+<!ENTITY ldb.paintDumping.label "Paint Dumping">
+<!ENTITY ldb.paintDumping.accesskey "P">
+<!ENTITY ldb.invalidateDumping.label "Invalidate Dumping">
+<!ENTITY ldb.invalidateDumping.accesskey "I">
+<!ENTITY ldb.eventDumping.label "Event Dumping">
+<!ENTITY ldb.eventDumping.accesskey "E">
+<!ENTITY ldb.motionEventDumping.label "Motion Event Dumping">
+<!ENTITY ldb.motionEventDumping.accesskey "M">
+<!ENTITY ldb.crossingEventDumping.label "Crossing Event Dumping">
+<!ENTITY ldb.crossingEventDumping.accesskey "C">
+<!ENTITY ldb.reflowCounts.label "Reflow Counts">
+<!ENTITY ldb.reflowCounts.accesskey "R">
+
+<!ENTITY ldb.DumpMenu.label "Dump">
+<!ENTITY ldb.DumpMenu.accesskey "D">
+
+<!ENTITY ldb.dumpWebShells.label "Web Shells">
+<!ENTITY ldb.dumpWebShells.accesskey "W">
+<!ENTITY ldb.dumpContent.label "Content">
+<!ENTITY ldb.dumpContent.accesskey "C">
+<!ENTITY ldb.dumpFrames.label "Frames">
+<!ENTITY ldb.dumpFrames.accesskey "F">
+<!ENTITY ldb.dumpViews.label "Views and Widgets">
+<!ENTITY ldb.dumpViews.accesskey "V">
+<!ENTITY ldb.dumpStyleSheets.label "Style Sheets">
+<!ENTITY ldb.dumpStyleSheets.accesskey "S">
+<!ENTITY ldb.dumpStyleContexts.label "Style Contexts">
+<!ENTITY ldb.dumpStyleContexts.accesskey "x">
+<!ENTITY ldb.dumpReflowStats.label "Reflow Statistics">
+<!ENTITY ldb.dumpReflowStats.accesskey "R">
diff --git a/layout/tools/layout-debug/ui/moz.build b/layout/tools/layout-debug/ui/moz.build
new file mode 100644
index 000000000..eb4454d28
--- /dev/null
+++ b/layout/tools/layout-debug/ui/moz.build
@@ -0,0 +1,7 @@
+# -*- 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/.
+
+JAR_MANIFESTS += ['jar.mn'] \ No newline at end of file