layout/tools/layout-debug/src/nsLayoutDebuggingTools.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 // vim:cindent:tabstop=4:expandtab:shiftwidth=4:
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "nsLayoutDebuggingTools.h"
     9 #include "nsIDocShell.h"
    10 #include "nsPIDOMWindow.h"
    11 #include "nsIContentViewer.h"
    13 #include "nsIServiceManager.h"
    14 #include "nsIAtom.h"
    15 #include "nsQuickSort.h"
    17 #include "nsIContent.h"
    18 #include "nsIDocument.h"
    19 #include "nsIDOMDocument.h"
    21 #include "nsIPresShell.h"
    22 #include "nsViewManager.h"
    23 #include "nsIFrame.h"
    25 #include "nsILayoutDebugger.h"
    26 #include "nsLayoutCID.h"
    27 static NS_DEFINE_CID(kLayoutDebuggerCID, NS_LAYOUT_DEBUGGER_CID);
    29 #include "nsISelectionController.h"
    30 #include "mozilla/dom/Element.h"
    31 #include "mozilla/Preferences.h"
    33 using namespace mozilla;
    35 static already_AddRefed<nsIContentViewer>
    36 doc_viewer(nsIDocShell *aDocShell)
    37 {
    38     if (!aDocShell)
    39         return nullptr;
    40     nsCOMPtr<nsIContentViewer> result;
    41     aDocShell->GetContentViewer(getter_AddRefs(result));
    42     return result.forget();
    43 }
    45 static already_AddRefed<nsIPresShell>
    46 pres_shell(nsIDocShell *aDocShell)
    47 {
    48     nsCOMPtr<nsIContentViewer> cv = doc_viewer(aDocShell);
    49     if (!cv)
    50         return nullptr;
    51     nsCOMPtr<nsIPresShell> result;
    52     cv->GetPresShell(getter_AddRefs(result));
    53     return result.forget();
    54 }
    56 static nsViewManager*
    57 view_manager(nsIDocShell *aDocShell)
    58 {
    59     nsCOMPtr<nsIPresShell> shell(pres_shell(aDocShell));
    60     if (!shell)
    61         return nullptr;
    62     return shell->GetViewManager();
    63 }
    65 #ifdef DEBUG
    66 static already_AddRefed<nsIDocument>
    67 document(nsIDocShell *aDocShell)
    68 {
    69     nsCOMPtr<nsIContentViewer> cv(doc_viewer(aDocShell));
    70     if (!cv)
    71         return nullptr;
    72     nsCOMPtr<nsIDOMDocument> domDoc;
    73     cv->GetDOMDocument(getter_AddRefs(domDoc));
    74     if (!domDoc)
    75         return nullptr;
    76     nsCOMPtr<nsIDocument> result = do_QueryInterface(domDoc);
    77     return result.forget();
    78 }
    79 #endif
    81 nsLayoutDebuggingTools::nsLayoutDebuggingTools()
    82   : mPaintFlashing(false),
    83     mPaintDumping(false),
    84     mInvalidateDumping(false),
    85     mEventDumping(false),
    86     mMotionEventDumping(false),
    87     mCrossingEventDumping(false),
    88     mReflowCounts(false)
    89 {
    90     NewURILoaded();
    91 }
    93 nsLayoutDebuggingTools::~nsLayoutDebuggingTools()
    94 {
    95 }
    97 NS_IMPL_ISUPPORTS(nsLayoutDebuggingTools, nsILayoutDebuggingTools)
    99 NS_IMETHODIMP
   100 nsLayoutDebuggingTools::Init(nsIDOMWindow *aWin)
   101 {
   102     if (!Preferences::GetService()) {
   103         return NS_ERROR_UNEXPECTED;
   104     }
   106     {
   107         nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWin);
   108         if (!window)
   109             return NS_ERROR_UNEXPECTED;
   110         mDocShell = window->GetDocShell();
   111     }
   112     NS_ENSURE_TRUE(mDocShell, NS_ERROR_UNEXPECTED);
   114     mPaintFlashing =
   115         Preferences::GetBool("nglayout.debug.paint_flashing", mPaintFlashing);
   116     mPaintDumping =
   117         Preferences::GetBool("nglayout.debug.paint_dumping", mPaintDumping);
   118     mInvalidateDumping =
   119         Preferences::GetBool("nglayout.debug.invalidate_dumping", mInvalidateDumping);
   120     mEventDumping =
   121         Preferences::GetBool("nglayout.debug.event_dumping", mEventDumping);
   122     mMotionEventDumping =
   123         Preferences::GetBool("nglayout.debug.motion_event_dumping",
   124                              mMotionEventDumping);
   125     mCrossingEventDumping =
   126         Preferences::GetBool("nglayout.debug.crossing_event_dumping",
   127                              mCrossingEventDumping);
   128     mReflowCounts =
   129         Preferences::GetBool("layout.reflow.showframecounts", mReflowCounts);
   131     {
   132         nsCOMPtr<nsILayoutDebugger> ld = do_GetService(kLayoutDebuggerCID);
   133         if (ld) {
   134             ld->GetShowFrameBorders(&mVisualDebugging);
   135             ld->GetShowEventTargetFrameBorder(&mVisualEventDebugging);
   136         }
   137     }
   139     return NS_OK;
   140 }
   142 NS_IMETHODIMP
   143 nsLayoutDebuggingTools::NewURILoaded()
   144 {
   145     NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
   146     // Reset all the state that should be reset between pages.
   148     // XXX Some of these should instead be transferred between pages!
   149     mEditorMode = false;
   150     mVisualDebugging = false;
   151     mVisualEventDebugging = false;
   153     mReflowCounts = false;
   155     ForceRefresh();
   156     return NS_OK;
   157 }
   159 NS_IMETHODIMP
   160 nsLayoutDebuggingTools::GetVisualDebugging(bool *aVisualDebugging)
   161 {
   162     *aVisualDebugging = mVisualDebugging;
   163     return NS_OK;
   164 }
   166 NS_IMETHODIMP
   167 nsLayoutDebuggingTools::SetVisualDebugging(bool aVisualDebugging)
   168 {
   169     nsCOMPtr<nsILayoutDebugger> ld = do_GetService(kLayoutDebuggerCID);
   170     if (!ld)
   171         return NS_ERROR_UNEXPECTED;
   172     mVisualDebugging = aVisualDebugging;
   173     ld->SetShowFrameBorders(aVisualDebugging);
   174     ForceRefresh();
   175     return NS_OK;
   176 }
   178 NS_IMETHODIMP
   179 nsLayoutDebuggingTools::GetVisualEventDebugging(bool *aVisualEventDebugging)
   180 {
   181     *aVisualEventDebugging = mVisualEventDebugging;
   182     return NS_OK;
   183 }
   185 NS_IMETHODIMP
   186 nsLayoutDebuggingTools::SetVisualEventDebugging(bool aVisualEventDebugging)
   187 {
   188     nsCOMPtr<nsILayoutDebugger> ld = do_GetService(kLayoutDebuggerCID);
   189     if (!ld)
   190         return NS_ERROR_UNEXPECTED;
   191     mVisualEventDebugging = aVisualEventDebugging;
   192     ld->SetShowEventTargetFrameBorder(aVisualEventDebugging);
   193     ForceRefresh();
   194     return NS_OK;
   195 }
   197 NS_IMETHODIMP
   198 nsLayoutDebuggingTools::GetPaintFlashing(bool *aPaintFlashing)
   199 {
   200     *aPaintFlashing = mPaintFlashing;
   201     return NS_OK;
   202 }
   204 NS_IMETHODIMP
   205 nsLayoutDebuggingTools::SetPaintFlashing(bool aPaintFlashing)
   206 {
   207     mPaintFlashing = aPaintFlashing;
   208     return SetBoolPrefAndRefresh("nglayout.debug.paint_flashing", mPaintFlashing);
   209 }
   211 NS_IMETHODIMP
   212 nsLayoutDebuggingTools::GetPaintDumping(bool *aPaintDumping)
   213 {
   214     *aPaintDumping = mPaintDumping;
   215     return NS_OK;
   216 }
   218 NS_IMETHODIMP
   219 nsLayoutDebuggingTools::SetPaintDumping(bool aPaintDumping)
   220 {
   221     mPaintDumping = aPaintDumping;
   222     return SetBoolPrefAndRefresh("nglayout.debug.paint_dumping", mPaintDumping);
   223 }
   225 NS_IMETHODIMP
   226 nsLayoutDebuggingTools::GetInvalidateDumping(bool *aInvalidateDumping)
   227 {
   228     *aInvalidateDumping = mInvalidateDumping;
   229     return NS_OK;
   230 }
   232 NS_IMETHODIMP
   233 nsLayoutDebuggingTools::SetInvalidateDumping(bool aInvalidateDumping)
   234 {
   235     mInvalidateDumping = aInvalidateDumping;
   236     return SetBoolPrefAndRefresh("nglayout.debug.invalidate_dumping", mInvalidateDumping);
   237 }
   239 NS_IMETHODIMP
   240 nsLayoutDebuggingTools::GetEventDumping(bool *aEventDumping)
   241 {
   242     *aEventDumping = mEventDumping;
   243     return NS_OK;
   244 }
   246 NS_IMETHODIMP
   247 nsLayoutDebuggingTools::SetEventDumping(bool aEventDumping)
   248 {
   249     mEventDumping = aEventDumping;
   250     return SetBoolPrefAndRefresh("nglayout.debug.event_dumping", mEventDumping);
   251 }
   253 NS_IMETHODIMP
   254 nsLayoutDebuggingTools::GetMotionEventDumping(bool *aMotionEventDumping)
   255 {
   256     *aMotionEventDumping = mMotionEventDumping;
   257     return NS_OK;
   258 }
   260 NS_IMETHODIMP
   261 nsLayoutDebuggingTools::SetMotionEventDumping(bool aMotionEventDumping)
   262 {
   263     mMotionEventDumping = aMotionEventDumping;
   264     return SetBoolPrefAndRefresh("nglayout.debug.motion_event_dumping", mMotionEventDumping);
   265 }
   267 NS_IMETHODIMP
   268 nsLayoutDebuggingTools::GetCrossingEventDumping(bool *aCrossingEventDumping)
   269 {
   270     *aCrossingEventDumping = mCrossingEventDumping;
   271     return NS_OK;
   272 }
   274 NS_IMETHODIMP
   275 nsLayoutDebuggingTools::SetCrossingEventDumping(bool aCrossingEventDumping)
   276 {
   277     mCrossingEventDumping = aCrossingEventDumping;
   278     return SetBoolPrefAndRefresh("nglayout.debug.crossing_event_dumping", mCrossingEventDumping);
   279 }
   281 NS_IMETHODIMP
   282 nsLayoutDebuggingTools::GetReflowCounts(bool* aShow)
   283 {
   284     *aShow = mReflowCounts;
   285     return NS_OK;
   286 }
   288 NS_IMETHODIMP
   289 nsLayoutDebuggingTools::SetReflowCounts(bool aShow)
   290 {
   291     NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
   292     nsCOMPtr<nsIPresShell> shell(pres_shell(mDocShell)); 
   293     if (shell) {
   294 #ifdef MOZ_REFLOW_PERF
   295         shell->SetPaintFrameCount(aShow);
   296         SetBoolPrefAndRefresh("layout.reflow.showframecounts", aShow);
   297         mReflowCounts = aShow;
   298 #else
   299         printf("************************************************\n");
   300         printf("Sorry, you have not built with MOZ_REFLOW_PERF=1\n");
   301         printf("************************************************\n");
   302 #endif
   303     }
   304     return NS_OK;
   305 }
   307 static void DumpAWebShell(nsIDocShellTreeItem* aShellItem, FILE* out, int32_t aIndent)
   308 {
   309     nsString name;
   310     nsCOMPtr<nsIDocShellTreeItem> parent;
   311     int32_t i, n;
   313     for (i = aIndent; --i >= 0; )
   314         fprintf(out, "  ");
   316     fprintf(out, "%p '", static_cast<void*>(aShellItem));
   317     aShellItem->GetName(name);
   318     aShellItem->GetSameTypeParent(getter_AddRefs(parent));
   319     fputs(NS_LossyConvertUTF16toASCII(name).get(), out);
   320     fprintf(out, "' parent=%p <\n", static_cast<void*>(parent));
   322     ++aIndent;
   323     aShellItem->GetChildCount(&n);
   324     for (i = 0; i < n; ++i) {
   325         nsCOMPtr<nsIDocShellTreeItem> child;
   326         aShellItem->GetChildAt(i, getter_AddRefs(child));
   327         if (child) {
   328             DumpAWebShell(child, out, aIndent);
   329         }
   330     }
   331     --aIndent;
   332     for (i = aIndent; --i >= 0; )
   333         fprintf(out, "  ");
   334     fputs(">\n", out);
   335 }
   337 NS_IMETHODIMP
   338 nsLayoutDebuggingTools::DumpWebShells()
   339 {
   340     NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
   341     DumpAWebShell(mDocShell, stdout, 0);
   342     return NS_OK;
   343 }
   345 static
   346 void
   347 DumpContentRecur(nsIDocShell* aDocShell, FILE* out)
   348 {
   349 #ifdef DEBUG
   350     if (nullptr != aDocShell) {
   351         fprintf(out, "docshell=%p \n", static_cast<void*>(aDocShell));
   352         nsCOMPtr<nsIDocument> doc(document(aDocShell));
   353         if (doc) {
   354             dom::Element *root = doc->GetRootElement();
   355             if (root) {
   356                 root->List(out);
   357             }
   358         }
   359         else {
   360             fputs("no document\n", out);
   361         }
   362         // dump the frames of the sub documents
   363         int32_t i, n;
   364         aDocShell->GetChildCount(&n);
   365         for (i = 0; i < n; ++i) {
   366             nsCOMPtr<nsIDocShellTreeItem> child;
   367             aDocShell->GetChildAt(i, getter_AddRefs(child));
   368             nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
   369             if (child) {
   370                 DumpContentRecur(childAsShell, out);
   371             }
   372         }
   373     }
   374 #endif
   375 }
   377 NS_IMETHODIMP
   378 nsLayoutDebuggingTools::DumpContent()
   379 {
   380     NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
   381     DumpContentRecur(mDocShell, stdout);
   382     return NS_OK;
   383 }
   385 static void
   386 DumpFramesRecur(nsIDocShell* aDocShell, FILE* out)
   387 {
   388 #ifdef DEBUG
   389     fprintf(out, "webshell=%p \n", static_cast<void*>(aDocShell));
   390     nsCOMPtr<nsIPresShell> shell(pres_shell(aDocShell));
   391     if (shell) {
   392         nsIFrame* root = shell->GetRootFrame();
   393         if (root) {
   394             root->List(out);
   395         }
   396     }
   397     else {
   398         fputs("null pres shell\n", out);
   399     }
   401     // dump the frames of the sub documents
   402     int32_t i, n;
   403     aDocShell->GetChildCount(&n);
   404     for (i = 0; i < n; ++i) {
   405         nsCOMPtr<nsIDocShellTreeItem> child;
   406         aDocShell->GetChildAt(i, getter_AddRefs(child));
   407         nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
   408         if (childAsShell) {
   409             DumpFramesRecur(childAsShell, out);
   410         }
   411     }
   412 #endif
   413 }
   415 NS_IMETHODIMP
   416 nsLayoutDebuggingTools::DumpFrames()
   417 {
   418     NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
   419     DumpFramesRecur(mDocShell, stdout);
   420     return NS_OK;
   421 }
   423 static
   424 void
   425 DumpViewsRecur(nsIDocShell* aDocShell, FILE* out)
   426 {
   427 #ifdef DEBUG
   428     fprintf(out, "docshell=%p \n", static_cast<void*>(aDocShell));
   429     nsRefPtr<nsViewManager> vm(view_manager(aDocShell));
   430     if (vm) {
   431         nsView* root = vm->GetRootView();
   432         if (root) {
   433             root->List(out);
   434         }
   435     }
   436     else {
   437         fputs("null view manager\n", out);
   438     }
   440     // dump the views of the sub documents
   441     int32_t i, n;
   442     aDocShell->GetChildCount(&n);
   443     for (i = 0; i < n; i++) {
   444         nsCOMPtr<nsIDocShellTreeItem> child;
   445         aDocShell->GetChildAt(i, getter_AddRefs(child));
   446         nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
   447         if (childAsShell) {
   448             DumpViewsRecur(childAsShell, out);
   449         }
   450     }
   451 #endif // DEBUG
   452 }
   454 NS_IMETHODIMP
   455 nsLayoutDebuggingTools::DumpViews()
   456 {
   457     NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
   458     DumpViewsRecur(mDocShell, stdout);
   459     return NS_OK;
   460 }
   462 NS_IMETHODIMP
   463 nsLayoutDebuggingTools::DumpStyleSheets()
   464 {
   465     NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
   466 #ifdef DEBUG
   467     FILE *out = stdout;
   468     nsCOMPtr<nsIPresShell> shell(pres_shell(mDocShell)); 
   469     if (shell)
   470         shell->ListStyleSheets(out);
   471     else
   472         fputs("null pres shell\n", out);
   473 #endif
   474     return NS_OK;
   475 }
   477 NS_IMETHODIMP
   478 nsLayoutDebuggingTools::DumpStyleContexts()
   479 {
   480     NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
   481 #ifdef DEBUG
   482     FILE *out = stdout;
   483     nsCOMPtr<nsIPresShell> shell(pres_shell(mDocShell)); 
   484     if (shell) {
   485         nsIFrame* root = shell->GetRootFrame();
   486         if (!root) {
   487             fputs("null root frame\n", out);
   488         } else {
   489             shell->ListStyleContexts(root, out);
   490         }
   491     } else {
   492         fputs("null pres shell\n", out);
   493     }
   494 #endif
   495     return NS_OK;
   496 }
   498 NS_IMETHODIMP
   499 nsLayoutDebuggingTools::DumpReflowStats()
   500 {
   501     NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
   502 #ifdef DEBUG
   503     nsCOMPtr<nsIPresShell> shell(pres_shell(mDocShell)); 
   504     if (shell) {
   505 #ifdef MOZ_REFLOW_PERF
   506         shell->DumpReflows();
   507 #else
   508         printf("************************************************\n");
   509         printf("Sorry, you have not built with MOZ_REFLOW_PERF=1\n");
   510         printf("************************************************\n");
   511 #endif
   512     }
   513 #endif
   514     return NS_OK;
   515 }
   517 void nsLayoutDebuggingTools::ForceRefresh()
   518 {
   519     nsRefPtr<nsViewManager> vm(view_manager(mDocShell));
   520     if (!vm)
   521         return;
   522     nsView* root = vm->GetRootView();
   523     if (root) {
   524         vm->InvalidateView(root);
   525     }
   526 }
   528 nsresult
   529 nsLayoutDebuggingTools::SetBoolPrefAndRefresh(const char * aPrefName,
   530                                               bool aNewVal)
   531 {
   532     NS_ENSURE_TRUE(mDocShell, NS_ERROR_NOT_INITIALIZED);
   534     nsIPrefService* prefService = Preferences::GetService();
   535     NS_ENSURE_TRUE(prefService && aPrefName, NS_OK);
   537     Preferences::SetBool(aPrefName, aNewVal);
   538     prefService->SavePrefFile(nullptr);
   540     ForceRefresh();
   542     return NS_OK;
   543 }

mercurial