From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- layout/tools/layout-debug/application.ini | 12 + layout/tools/layout-debug/chrome.manifest | 2 + layout/tools/layout-debug/layoutdebug-prefs.js | 5 + layout/tools/layout-debug/moz.build | 9 + layout/tools/layout-debug/src/moz.build | 25 + layout/tools/layout-debug/src/nsDebugFactory.cpp | 50 ++ .../layout-debug/src/nsILayoutDebuggingTools.idl | 52 ++ .../layout-debug/src/nsILayoutRegressionTester.idl | 46 ++ layout/tools/layout-debug/src/nsLayoutDebugCIID.h | 24 + layout/tools/layout-debug/src/nsLayoutDebugCLH.cpp | 82 ++++ layout/tools/layout-debug/src/nsLayoutDebugCLH.h | 29 ++ .../layout-debug/src/nsLayoutDebuggingTools.cpp | 543 +++++++++++++++++++++ .../layout-debug/src/nsLayoutDebuggingTools.h | 44 ++ .../tools/layout-debug/src/nsRegressionTester.cpp | 138 ++++++ layout/tools/layout-debug/src/nsRegressionTester.h | 32 ++ .../tests/unit/test_componentsRegistered.js | 8 + layout/tools/layout-debug/tests/unit/xpcshell.ini | 5 + .../ui/content/layoutdebug-overlay.xul | 38 ++ .../tools/layout-debug/ui/content/layoutdebug.js | 434 ++++++++++++++++ .../tools/layout-debug/ui/content/layoutdebug.xul | 187 +++++++ layout/tools/layout-debug/ui/jar.mn | 14 + .../ui/locale/en-US/layoutdebug-overlay.dtd | 8 + .../layout-debug/ui/locale/en-US/layoutdebug.dtd | 76 +++ layout/tools/layout-debug/ui/moz.build | 7 + 24 files changed, 1870 insertions(+) create mode 100644 layout/tools/layout-debug/application.ini create mode 100644 layout/tools/layout-debug/chrome.manifest create mode 100644 layout/tools/layout-debug/layoutdebug-prefs.js create mode 100644 layout/tools/layout-debug/moz.build create mode 100644 layout/tools/layout-debug/src/moz.build create mode 100644 layout/tools/layout-debug/src/nsDebugFactory.cpp create mode 100644 layout/tools/layout-debug/src/nsILayoutDebuggingTools.idl create mode 100644 layout/tools/layout-debug/src/nsILayoutRegressionTester.idl create mode 100644 layout/tools/layout-debug/src/nsLayoutDebugCIID.h create mode 100644 layout/tools/layout-debug/src/nsLayoutDebugCLH.cpp create mode 100644 layout/tools/layout-debug/src/nsLayoutDebugCLH.h create mode 100644 layout/tools/layout-debug/src/nsLayoutDebuggingTools.cpp create mode 100644 layout/tools/layout-debug/src/nsLayoutDebuggingTools.h create mode 100644 layout/tools/layout-debug/src/nsRegressionTester.cpp create mode 100644 layout/tools/layout-debug/src/nsRegressionTester.h create mode 100644 layout/tools/layout-debug/tests/unit/test_componentsRegistered.js create mode 100644 layout/tools/layout-debug/tests/unit/xpcshell.ini create mode 100644 layout/tools/layout-debug/ui/content/layoutdebug-overlay.xul create mode 100644 layout/tools/layout-debug/ui/content/layoutdebug.js create mode 100644 layout/tools/layout-debug/ui/content/layoutdebug.xul create mode 100644 layout/tools/layout-debug/ui/jar.mn create mode 100644 layout/tools/layout-debug/ui/locale/en-US/layoutdebug-overlay.dtd create mode 100644 layout/tools/layout-debug/ui/locale/en-US/layoutdebug.dtd create mode 100644 layout/tools/layout-debug/ui/moz.build (limited to 'layout/tools/layout-debug') 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 argsArray = nsArray::Create(); + + if (!url.IsEmpty()) + { + nsCOMPtr scriptableURL = + do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID); + NS_ENSURE_TRUE(scriptableURL, NS_ERROR_FAILURE); + + scriptableURL->SetData(url); + argsArray->AppendElement(scriptableURL, /*weak =*/ false); + } + + nsCOMPtr wwatch = + do_GetService(NS_WINDOWWATCHER_CONTRACTID); + NS_ENSURE_TRUE(wwatch, NS_ERROR_FAILURE); + + nsCOMPtr 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 [] 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 +doc_viewer(nsIDocShell *aDocShell) +{ + if (!aDocShell) + return nullptr; + nsCOMPtr result; + aDocShell->GetContentViewer(getter_AddRefs(result)); + return result.forget(); +} + +static already_AddRefed +pres_shell(nsIDocShell *aDocShell) +{ + nsCOMPtr cv = doc_viewer(aDocShell); + if (!cv) + return nullptr; + nsCOMPtr result; + cv->GetPresShell(getter_AddRefs(result)); + return result.forget(); +} + +static nsViewManager* +view_manager(nsIDocShell *aDocShell) +{ + nsCOMPtr shell(pres_shell(aDocShell)); + if (!shell) + return nullptr; + return shell->GetViewManager(); +} + +#ifdef DEBUG +static already_AddRefed +document(nsIDocShell *aDocShell) +{ + nsCOMPtr cv(doc_viewer(aDocShell)); + if (!cv) + return nullptr; + nsCOMPtr domDoc; + cv->GetDOMDocument(getter_AddRefs(domDoc)); + if (!domDoc) + return nullptr; + nsCOMPtr 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 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 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 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 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 parent; + int32_t i, n; + + for (i = aIndent; --i >= 0; ) + fprintf(out, " "); + + fprintf(out, "%p '", static_cast(aShellItem)); + aShellItem->GetName(name); + aShellItem->GetSameTypeParent(getter_AddRefs(parent)); + fputs(NS_LossyConvertUTF16toASCII(name).get(), out); + fprintf(out, "' parent=%p <\n", static_cast(parent)); + + ++aIndent; + aShellItem->GetChildCount(&n); + for (i = 0; i < n; ++i) { + nsCOMPtr 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(aDocShell)); + nsCOMPtr 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 child; + aDocShell->GetChildAt(i, getter_AddRefs(child)); + nsCOMPtr 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(aDocShell)); + nsCOMPtr 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 child; + aDocShell->GetChildAt(i, getter_AddRefs(child)); + nsCOMPtr 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(aDocShell)); + RefPtr 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 child; + aDocShell->GetChildAt(i, getter_AddRefs(child)); + nsCOMPtr 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 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 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 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 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 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 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 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 viewer; + docShell->GetContentViewer(getter_AddRefs(viewer)); + if (viewer){ + nsCOMPtr 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 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 @@ + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + %layoutdebugDTD; + + + + +]> + + + + + + + + + + +