Bug 481115 - remove nsIPref from extension/(layout-debug|widgetutils). r=roc+romaxa
[mozilla-central.git] / extensions / layout-debug / src / nsLayoutDebuggingTools.cpp
blob74dd0d1d7a1b2c08a9ed73e99b5549dd37ed37e4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 // vim:cindent:tabstop=4:expandtab:shiftwidth=4:
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is layout debugging code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2002
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * L. David Baron <dbaron@dbaron.org> (original author)
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "nsLayoutDebuggingTools.h"
42 #include "nsIDocShell.h"
43 #include "nsIDocShellTreeNode.h"
44 #include "nsIDocShellTreeItem.h"
45 #include "nsPIDOMWindow.h"
46 #include "nsIDocumentViewer.h"
48 #include "nsIServiceManager.h"
49 #include "nsIAtom.h"
50 #include "nsQuickSort.h"
51 #include "nsIPrefBranch.h"
52 #include "nsIPrefService.h"
54 #include "nsIContent.h"
55 #include "nsIDocument.h"
56 #include "nsIDOMDocument.h"
58 #include "nsIPresShell.h"
59 #include "nsIViewManager.h"
60 #include "nsIFrame.h"
61 #include "nsIFrameDebug.h"
63 #include "nsILayoutDebugger.h"
64 #include "nsLayoutCID.h"
65 static NS_DEFINE_CID(kLayoutDebuggerCID, NS_LAYOUT_DEBUGGER_CID);
67 #include "nsISelectionController.h"
69 static already_AddRefed<nsIContentViewer>
70 doc_viewer(nsIDocShell *aDocShell)
72 if (!aDocShell)
73 return nsnull;
74 nsIContentViewer *result = nsnull;
75 aDocShell->GetContentViewer(&result);
76 return result;
79 static already_AddRefed<nsIPresShell>
80 pres_shell(nsIDocShell *aDocShell)
82 nsCOMPtr<nsIDocumentViewer> dv =
83 do_QueryInterface(nsCOMPtr<nsIContentViewer>(doc_viewer(aDocShell)));
84 if (!dv)
85 return nsnull;
86 nsIPresShell *result = nsnull;
87 dv->GetPresShell(&result);
88 return result;
91 #if 0 // not currently needed
92 static already_AddRefed<nsPresContext>
93 pres_context(nsIDocShell *aDocShell)
95 nsCOMPtr<nsIDocumentViewer> dv =
96 do_QueryInterface(nsCOMPtr<nsIContentViewer>(doc_viewer(aDocShell)));
97 if (!dv)
98 return nsnull;
99 nsPresContext *result = nsnull;
100 dv->GetPresContext(result);
101 return result;
103 #endif
105 static nsIViewManager*
106 view_manager(nsIDocShell *aDocShell)
108 nsCOMPtr<nsIPresShell> shell(pres_shell(aDocShell));
109 if (!shell)
110 return nsnull;
111 return shell->GetViewManager();
114 #ifdef DEBUG
115 static already_AddRefed<nsIDocument>
116 document(nsIDocShell *aDocShell)
118 nsCOMPtr<nsIContentViewer> cv(doc_viewer(aDocShell));
119 if (!cv)
120 return nsnull;
121 nsCOMPtr<nsIDOMDocument> domDoc;
122 cv->GetDOMDocument(getter_AddRefs(domDoc));
123 if (!domDoc)
124 return nsnull;
125 nsIDocument *result = nsnull;
126 CallQueryInterface(domDoc, &result);
127 return result;
129 #endif
131 nsLayoutDebuggingTools::nsLayoutDebuggingTools()
132 : mPaintFlashing(PR_FALSE),
133 mPaintDumping(PR_FALSE),
134 mInvalidateDumping(PR_FALSE),
135 mEventDumping(PR_FALSE),
136 mMotionEventDumping(PR_FALSE),
137 mCrossingEventDumping(PR_FALSE),
138 mReflowCounts(PR_FALSE)
140 NewURILoaded();
143 nsLayoutDebuggingTools::~nsLayoutDebuggingTools()
147 NS_IMPL_ISUPPORTS1(nsLayoutDebuggingTools, nsILayoutDebuggingTools)
149 NS_IMETHODIMP
150 nsLayoutDebuggingTools::Init(nsIDOMWindow *aWin)
152 mPrefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
153 if (!mPrefs)
154 return NS_ERROR_UNEXPECTED;
157 nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWin);
158 if (!window)
159 return NS_ERROR_UNEXPECTED;
160 mDocShell = window->GetDocShell();
162 NS_ENSURE_TRUE(mDocShell, NS_ERROR_UNEXPECTED);
164 GetBoolPref("nglayout.debug.paint_flashing", &mPaintFlashing);
165 GetBoolPref("nglayout.debug.paint_dumping", &mPaintDumping);
166 GetBoolPref("nglayout.debug.invalidate_dumping", &mInvalidateDumping);
167 GetBoolPref("nglayout.debug.event_dumping", &mEventDumping);
168 GetBoolPref("nglayout.debug.motion_event_dumping", &mMotionEventDumping);
169 GetBoolPref("nglayout.debug.crossing_event_dumping", &mCrossingEventDumping);
170 GetBoolPref("layout.reflow.showframecounts", &mReflowCounts);
173 nsCOMPtr<nsILayoutDebugger> ld = do_GetService(kLayoutDebuggerCID);
174 if (ld) {
175 ld->GetShowFrameBorders(&mVisualDebugging);
176 ld->GetShowEventTargetFrameBorder(&mVisualEventDebugging);
180 return NS_OK;
183 NS_IMETHODIMP
184 nsLayoutDebuggingTools::NewURILoaded()
186 NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
187 // Reset all the state that should be reset between pages.
189 // XXX Some of these should instead be transferred between pages!
190 mEditorMode = PR_FALSE;
191 mVisualDebugging = PR_FALSE;
192 mVisualEventDebugging = PR_FALSE;
194 mReflowCounts = PR_FALSE;
196 ForceRefresh();
197 return NS_OK;
200 NS_IMETHODIMP
201 nsLayoutDebuggingTools::GetVisualDebugging(PRBool *aVisualDebugging)
203 *aVisualDebugging = mVisualDebugging;
204 return NS_OK;
207 NS_IMETHODIMP
208 nsLayoutDebuggingTools::SetVisualDebugging(PRBool aVisualDebugging)
210 nsCOMPtr<nsILayoutDebugger> ld = do_GetService(kLayoutDebuggerCID);
211 if (!ld)
212 return NS_ERROR_UNEXPECTED;
213 mVisualDebugging = aVisualDebugging;
214 ld->SetShowFrameBorders(aVisualDebugging);
215 ForceRefresh();
216 return NS_OK;
219 NS_IMETHODIMP
220 nsLayoutDebuggingTools::GetVisualEventDebugging(PRBool *aVisualEventDebugging)
222 *aVisualEventDebugging = mVisualEventDebugging;
223 return NS_OK;
226 NS_IMETHODIMP
227 nsLayoutDebuggingTools::SetVisualEventDebugging(PRBool aVisualEventDebugging)
229 nsCOMPtr<nsILayoutDebugger> ld = do_GetService(kLayoutDebuggerCID);
230 if (!ld)
231 return NS_ERROR_UNEXPECTED;
232 mVisualEventDebugging = aVisualEventDebugging;
233 ld->SetShowEventTargetFrameBorder(aVisualEventDebugging);
234 ForceRefresh();
235 return NS_OK;
238 NS_IMETHODIMP
239 nsLayoutDebuggingTools::GetPaintFlashing(PRBool *aPaintFlashing)
241 *aPaintFlashing = mPaintFlashing;
242 return NS_OK;
245 NS_IMETHODIMP
246 nsLayoutDebuggingTools::SetPaintFlashing(PRBool aPaintFlashing)
248 mPaintFlashing = aPaintFlashing;
249 return SetBoolPrefAndRefresh("nglayout.debug.paint_flashing", mPaintFlashing);
252 NS_IMETHODIMP
253 nsLayoutDebuggingTools::GetPaintDumping(PRBool *aPaintDumping)
255 *aPaintDumping = mPaintDumping;
256 return NS_OK;
259 NS_IMETHODIMP
260 nsLayoutDebuggingTools::SetPaintDumping(PRBool aPaintDumping)
262 mPaintDumping = aPaintDumping;
263 return SetBoolPrefAndRefresh("nglayout.debug.paint_dumping", mPaintDumping);
266 NS_IMETHODIMP
267 nsLayoutDebuggingTools::GetInvalidateDumping(PRBool *aInvalidateDumping)
269 *aInvalidateDumping = mInvalidateDumping;
270 return NS_OK;
273 NS_IMETHODIMP
274 nsLayoutDebuggingTools::SetInvalidateDumping(PRBool aInvalidateDumping)
276 mInvalidateDumping = aInvalidateDumping;
277 return SetBoolPrefAndRefresh("nglayout.debug.invalidate_dumping", mInvalidateDumping);
280 NS_IMETHODIMP
281 nsLayoutDebuggingTools::GetEventDumping(PRBool *aEventDumping)
283 *aEventDumping = mEventDumping;
284 return NS_OK;
287 NS_IMETHODIMP
288 nsLayoutDebuggingTools::SetEventDumping(PRBool aEventDumping)
290 mEventDumping = aEventDumping;
291 return SetBoolPrefAndRefresh("nglayout.debug.event_dumping", mEventDumping);
294 NS_IMETHODIMP
295 nsLayoutDebuggingTools::GetMotionEventDumping(PRBool *aMotionEventDumping)
297 *aMotionEventDumping = mMotionEventDumping;
298 return NS_OK;
301 NS_IMETHODIMP
302 nsLayoutDebuggingTools::SetMotionEventDumping(PRBool aMotionEventDumping)
304 mMotionEventDumping = aMotionEventDumping;
305 return SetBoolPrefAndRefresh("nglayout.debug.motion_event_dumping", mMotionEventDumping);
308 NS_IMETHODIMP
309 nsLayoutDebuggingTools::GetCrossingEventDumping(PRBool *aCrossingEventDumping)
311 *aCrossingEventDumping = mCrossingEventDumping;
312 return NS_OK;
315 NS_IMETHODIMP
316 nsLayoutDebuggingTools::SetCrossingEventDumping(PRBool aCrossingEventDumping)
318 mCrossingEventDumping = aCrossingEventDumping;
319 return SetBoolPrefAndRefresh("nglayout.debug.crossing_event_dumping", mCrossingEventDumping);
322 NS_IMETHODIMP
323 nsLayoutDebuggingTools::GetReflowCounts(PRBool* aShow)
325 *aShow = mReflowCounts;
326 return NS_OK;
329 NS_IMETHODIMP
330 nsLayoutDebuggingTools::SetReflowCounts(PRBool aShow)
332 NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
333 nsCOMPtr<nsIPresShell> shell(pres_shell(mDocShell));
334 if (shell) {
335 #ifdef MOZ_REFLOW_PERF
336 shell->SetPaintFrameCount(aShow);
337 SetBoolPrefAndRefresh("layout.reflow.showframecounts", aShow);
338 mReflowCounts = aShow;
339 #else
340 printf("************************************************\n");
341 printf("Sorry, you have not built with MOZ_REFLOW_PERF=1\n");
342 printf("************************************************\n");
343 #endif
345 return NS_OK;
348 static void DumpAWebShell(nsIDocShellTreeItem* aShellItem, FILE* out, PRInt32 aIndent)
350 nsXPIDLString name;
351 nsCOMPtr<nsIDocShellTreeItem> parent;
352 PRInt32 i, n;
354 for (i = aIndent; --i >= 0; )
355 fprintf(out, " ");
357 fprintf(out, "%p '", static_cast<void*>(aShellItem));
358 aShellItem->GetName(getter_Copies(name));
359 aShellItem->GetSameTypeParent(getter_AddRefs(parent));
360 fputs(NS_LossyConvertUTF16toASCII(name).get(), out);
361 fprintf(out, "' parent=%p <\n", static_cast<void*>(parent));
363 ++aIndent;
364 nsCOMPtr<nsIDocShellTreeNode> shellAsNode(do_QueryInterface(aShellItem));
365 shellAsNode->GetChildCount(&n);
366 for (i = 0; i < n; ++i) {
367 nsCOMPtr<nsIDocShellTreeItem> child;
368 shellAsNode->GetChildAt(i, getter_AddRefs(child));
369 if (child) {
370 DumpAWebShell(child, out, aIndent);
373 --aIndent;
374 for (i = aIndent; --i >= 0; )
375 fprintf(out, " ");
376 fputs(">\n", out);
379 NS_IMETHODIMP
380 nsLayoutDebuggingTools::DumpWebShells()
382 NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
383 nsCOMPtr<nsIDocShellTreeItem> shellAsItem(do_QueryInterface(mDocShell));
384 DumpAWebShell(shellAsItem, stdout, 0);
385 return NS_OK;
388 static
389 void
390 DumpContentRecur(nsIDocShell* aDocShell, FILE* out)
392 #ifdef DEBUG
393 if (nsnull != aDocShell) {
394 fprintf(out, "docshell=%p \n", static_cast<void*>(aDocShell));
395 nsCOMPtr<nsIDocument> doc(document(aDocShell));
396 if (doc) {
397 nsIContent *root = doc->GetRootContent();
398 if (root) {
399 root->List(out);
402 else {
403 fputs("no document\n", out);
405 // dump the frames of the sub documents
406 PRInt32 i, n;
407 nsCOMPtr<nsIDocShellTreeNode> docShellAsNode(do_QueryInterface(aDocShell));
408 docShellAsNode->GetChildCount(&n);
409 for (i = 0; i < n; ++i) {
410 nsCOMPtr<nsIDocShellTreeItem> child;
411 docShellAsNode->GetChildAt(i, getter_AddRefs(child));
412 nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
413 if (child) {
414 DumpContentRecur(childAsShell, out);
418 #endif
421 NS_IMETHODIMP
422 nsLayoutDebuggingTools::DumpContent()
424 NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
425 DumpContentRecur(mDocShell, stdout);
426 return NS_OK;
429 static void
430 DumpFramesRecur(nsIDocShell* aDocShell, FILE* out)
432 fprintf(out, "webshell=%p \n", static_cast<void*>(aDocShell));
433 nsCOMPtr<nsIPresShell> shell(pres_shell(aDocShell));
434 if (shell) {
435 nsIFrame* root = shell->GetRootFrame();
436 if (root) {
437 nsIFrameDebug* fdbg = do_QueryFrame(root);
438 if (fdbg) {
439 fdbg->List(out, 0);
443 else {
444 fputs("null pres shell\n", out);
447 // dump the frames of the sub documents
448 PRInt32 i, n;
449 nsCOMPtr<nsIDocShellTreeNode> docShellAsNode(do_QueryInterface(aDocShell));
450 docShellAsNode->GetChildCount(&n);
451 for (i = 0; i < n; ++i) {
452 nsCOMPtr<nsIDocShellTreeItem> child;
453 docShellAsNode->GetChildAt(i, getter_AddRefs(child));
454 nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
455 if (childAsShell) {
456 DumpFramesRecur(childAsShell, out);
461 NS_IMETHODIMP
462 nsLayoutDebuggingTools::DumpFrames()
464 NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
465 DumpFramesRecur(mDocShell, stdout);
466 return NS_OK;
469 static
470 void
471 DumpViewsRecur(nsIDocShell* aDocShell, FILE* out)
473 #ifdef DEBUG
474 fprintf(out, "docshell=%p \n", static_cast<void*>(aDocShell));
475 nsCOMPtr<nsIViewManager> vm(view_manager(aDocShell));
476 if (vm) {
477 nsIView* root;
478 vm->GetRootView(root);
479 if (nsnull != root) {
480 root->List(out);
483 else {
484 fputs("null view manager\n", out);
487 // dump the views of the sub documents
488 PRInt32 i, n;
489 nsCOMPtr<nsIDocShellTreeNode> docShellAsNode(do_QueryInterface(aDocShell));
490 docShellAsNode->GetChildCount(&n);
491 for (i = 0; i < n; i++) {
492 nsCOMPtr<nsIDocShellTreeItem> child;
493 docShellAsNode->GetChildAt(i, getter_AddRefs(child));
494 nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
495 if (childAsShell) {
496 DumpViewsRecur(childAsShell, out);
499 #endif // DEBUG
502 NS_IMETHODIMP
503 nsLayoutDebuggingTools::DumpViews()
505 NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
506 DumpViewsRecur(mDocShell, stdout);
507 return NS_OK;
510 NS_IMETHODIMP
511 nsLayoutDebuggingTools::DumpStyleSheets()
513 NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
514 #ifdef DEBUG
515 FILE *out = stdout;
516 nsCOMPtr<nsIPresShell> shell(pres_shell(mDocShell));
517 if (shell)
518 shell->ListStyleSheets(out);
519 else
520 fputs("null pres shell\n", out);
521 #endif
522 return NS_OK;
525 NS_IMETHODIMP
526 nsLayoutDebuggingTools::DumpStyleContexts()
528 NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
529 #ifdef DEBUG
530 FILE *out = stdout;
531 nsCOMPtr<nsIPresShell> shell(pres_shell(mDocShell));
532 if (shell) {
533 nsIFrame* root = shell->GetRootFrame();
534 if (!root) {
535 fputs("null root frame\n", out);
536 } else {
537 shell->ListStyleContexts(root, out);
539 } else {
540 fputs("null pres shell\n", out);
542 #endif
543 return NS_OK;
546 NS_IMETHODIMP
547 nsLayoutDebuggingTools::DumpReflowStats()
549 NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
550 #ifdef DEBUG
551 nsCOMPtr<nsIPresShell> shell(pres_shell(mDocShell));
552 if (shell) {
553 #ifdef MOZ_REFLOW_PERF
554 shell->DumpReflows();
555 #else
556 printf("************************************************\n");
557 printf("Sorry, you have not built with MOZ_REFLOW_PERF=1\n");
558 printf("************************************************\n");
559 #endif
561 #endif
562 return NS_OK;
565 void nsLayoutDebuggingTools::ForceRefresh()
567 nsCOMPtr<nsIViewManager> vm(view_manager(mDocShell));
568 if (!vm)
569 return;
570 nsIView* root = nsnull;
571 vm->GetRootView(root);
572 if (root) {
573 vm->UpdateView(root, NS_VMREFRESH_IMMEDIATE);
577 nsresult
578 nsLayoutDebuggingTools::SetBoolPrefAndRefresh(const char * aPrefName,
579 PRBool aNewVal)
581 NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
582 NS_ENSURE_TRUE(mPrefs && aPrefName, NS_OK);
584 mPrefs->SetBoolPref(aPrefName, aNewVal);
585 nsCOMPtr<nsIPrefService> prefService = do_QueryInterface(mPrefs);
586 NS_ENSURE_STATE(prefService);
587 prefService->SavePrefFile(nsnull);
589 ForceRefresh();
591 return NS_OK;
594 nsresult
595 nsLayoutDebuggingTools::GetBoolPref(const char * aPrefName,
596 PRBool *aValue)
598 NS_ENSURE_TRUE(mPrefs && aPrefName, NS_OK);
600 mPrefs->GetBoolPref(aPrefName, aValue);
602 return NS_OK;