LCOV - code coverage report
Current view: directory - layout/base - nsPresShell.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 3826 10 0.3 %
Date: 2012-06-02 Functions: 322 4 1.2 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2                 :  * vim: set ts=2 sw=2 et tw=78:
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       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/
      10                 :  *
      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.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Steve Clark <buster@netscape.com>
      25                 :  *   HÃ¥kan Waara <hwaara@chello.se>
      26                 :  *   Dan Rosen <dr@netscape.com>
      27                 :  *   Daniel Glazman <glazman@netscape.com>
      28                 :  *   Mats Palmgren <matspal@gmail.com>
      29                 :  *   Mihai Sucan <mihai.sucan@gmail.com>
      30                 :  *
      31                 :  * Alternatively, the contents of this file may be used under the terms of
      32                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      33                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      34                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      35                 :  * of those above. If you wish to allow use of your version of this file only
      36                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      37                 :  * use your version of this file under the terms of the MPL, indicate your
      38                 :  * decision by deleting the provisions above and replace them with the notice
      39                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      40                 :  * the provisions above, a recipient may use your version of this file under
      41                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      42                 :  *
      43                 :  * ***** END LICENSE BLOCK *****
      44                 :  *
      45                 :  * This Original Code has been modified by IBM Corporation.
      46                 :  * Modifications made by IBM described herein are
      47                 :  * Copyright (c) International Business Machines
      48                 :  * Corporation, 2000
      49                 :  *
      50                 :  * Modifications to Mozilla code or documentation
      51                 :  * identified per MPL Section 3.3
      52                 :  *
      53                 :  * Date         Modified by     Description of modification
      54                 :  * 05/03/2000   IBM Corp.       Observer events for reflow states
      55                 :  */
      56                 : 
      57                 : /* a presentation of a document, part 2 */
      58                 : 
      59                 : #include "mozilla/dom/PBrowserChild.h"
      60                 : #include "mozilla/dom/TabChild.h"
      61                 : #include "mozilla/Util.h"
      62                 : 
      63                 : #ifdef XP_WIN
      64                 : #include "winuser.h"
      65                 : #endif
      66                 : 
      67                 : #include "nsPresShell.h"
      68                 : #include "nsPresContext.h"
      69                 : #include "nsIContent.h"
      70                 : #include "mozilla/dom/Element.h"
      71                 : #include "nsIDocument.h"
      72                 : #include "nsIDOMXULDocument.h"
      73                 : #include "nsCSSStyleSheet.h" // XXX for UA sheet loading hack, can this go away please?
      74                 : #include "nsIDOMCSSStyleSheet.h"  // for Pref-related rule management (bugs 22963,20760,31816)
      75                 : #include "nsAnimationManager.h"
      76                 : #include "nsINameSpaceManager.h"  // for Pref-related rule management (bugs 22963,20760,31816)
      77                 : #include "nsIServiceManager.h"
      78                 : #include "nsFrame.h"
      79                 : #include "nsViewManager.h"
      80                 : #include "nsView.h"
      81                 : #include "nsCRTGlue.h"
      82                 : #include "prlog.h"
      83                 : #include "prmem.h"
      84                 : #include "prprf.h"
      85                 : #include "prinrval.h"
      86                 : #include "nsTArray.h"
      87                 : #include "nsCOMArray.h"
      88                 : #include "nsHashtable.h"
      89                 : #include "nsContainerFrame.h"
      90                 : #include "nsDOMEvent.h"
      91                 : #include "nsHTMLParts.h"
      92                 : #include "nsISelection.h"
      93                 : #include "nsISelectionPrivate.h"
      94                 : #include "nsLayoutCID.h"
      95                 : #include "nsGkAtoms.h"
      96                 : #include "nsIDOMRange.h"
      97                 : #include "nsIDOMDocument.h"
      98                 : #include "nsIDOMNode.h"
      99                 : #include "nsIDOMNodeList.h"
     100                 : #include "nsIDOMElement.h"
     101                 : #include "nsRange.h"
     102                 : #include "nsCSSPseudoElements.h"
     103                 : #include "nsCOMPtr.h"
     104                 : #include "nsAutoPtr.h"
     105                 : #include "nsReadableUtils.h"
     106                 : #include "nsUnicharUtils.h"
     107                 : #include "nsIPageSequenceFrame.h"
     108                 : #include "nsCaret.h"
     109                 : #include "nsIDOMHTMLDocument.h"
     110                 : #include "nsIDOMXMLDocument.h"
     111                 : #include "nsIParser.h"
     112                 : #include "nsParserCIID.h"
     113                 : #include "nsViewsCID.h"
     114                 : #include "nsFrameManager.h"
     115                 : #include "nsEventStateManager.h"
     116                 : #include "nsXPCOM.h"
     117                 : #include "nsISupportsPrimitives.h"
     118                 : #include "nsILayoutHistoryState.h"
     119                 : #include "nsILineIterator.h" // for ScrollContentIntoView
     120                 : #include "nsWeakPtr.h"
     121                 : #include "pldhash.h"
     122                 : #include "nsDOMTouchEvent.h"
     123                 : #include "nsIObserverService.h"
     124                 : #include "nsIDocShell.h"        // for reflow observation
     125                 : #include "nsIBaseWindow.h"
     126                 : #include "nsLayoutErrors.h"
     127                 : #include "nsLayoutUtils.h"
     128                 : #include "nsCSSRendering.h"
     129                 :   // for |#ifdef DEBUG| code
     130                 : #include "prenv.h"
     131                 : #include "nsAlgorithm.h"
     132                 : #include "nsIAttribute.h"
     133                 : #include "nsIGlobalHistory2.h"
     134                 : #include "nsDisplayList.h"
     135                 : #include "nsRegion.h"
     136                 : #include "nsRenderingContext.h"
     137                 : #include "nsAutoLayoutPhase.h"
     138                 : #ifdef MOZ_REFLOW_PERF
     139                 : #include "nsFontMetrics.h"
     140                 : #endif
     141                 : 
     142                 : #include "nsIReflowCallback.h"
     143                 : 
     144                 : #include "nsPIDOMWindow.h"
     145                 : #include "nsFocusManager.h"
     146                 : #include "nsNPAPIPluginInstance.h"
     147                 : #include "nsIObjectFrame.h"
     148                 : #include "nsIObjectLoadingContent.h"
     149                 : #include "nsNetUtil.h"
     150                 : #include "nsEventDispatcher.h"
     151                 : #include "nsThreadUtils.h"
     152                 : #include "nsStyleSheetService.h"
     153                 : #include "gfxImageSurface.h"
     154                 : #include "gfxContext.h"
     155                 : #ifdef MOZ_MEDIA
     156                 : #include "nsHTMLMediaElement.h"
     157                 : #endif
     158                 : #include "nsSMILAnimationController.h"
     159                 : 
     160                 : #include "nsRefreshDriver.h"
     161                 : 
     162                 : // Drag & Drop, Clipboard
     163                 : #include "nsWidgetsCID.h"
     164                 : #include "nsIClipboard.h"
     165                 : #include "nsIClipboardHelper.h"
     166                 : #include "nsIDocShellTreeItem.h"
     167                 : #include "nsIURI.h"
     168                 : #include "nsIScrollableFrame.h"
     169                 : #include "prtime.h"
     170                 : #include "prlong.h"
     171                 : #include "nsIDragService.h"
     172                 : #include "nsCopySupport.h"
     173                 : #include "nsIDOMHTMLAnchorElement.h"
     174                 : #include "nsIDOMHTMLAreaElement.h"
     175                 : #include "nsIDOMHTMLLinkElement.h"
     176                 : #include "nsITimer.h"
     177                 : #ifdef ACCESSIBILITY
     178                 : #include "nsAccessibilityService.h"
     179                 : #endif
     180                 : 
     181                 : // For style data reconstruction
     182                 : #include "nsStyleChangeList.h"
     183                 : #include "nsCSSFrameConstructor.h"
     184                 : #ifdef MOZ_XUL
     185                 : #include "nsMenuFrame.h"
     186                 : #include "nsTreeBodyFrame.h"
     187                 : #include "nsIBoxObject.h"
     188                 : #include "nsITreeBoxObject.h"
     189                 : #include "nsMenuPopupFrame.h"
     190                 : #include "nsITreeColumns.h"
     191                 : #include "nsIDOMXULMultSelectCntrlEl.h"
     192                 : #include "nsIDOMXULSelectCntrlItemEl.h"
     193                 : #include "nsIDOMXULMenuListElement.h"
     194                 : 
     195                 : #endif
     196                 : #include "nsPlaceholderFrame.h"
     197                 : #include "nsCanvasFrame.h"
     198                 : 
     199                 : // Content viewer interfaces
     200                 : #include "nsIContentViewer.h"
     201                 : #include "imgIEncoder.h"
     202                 : #include "gfxPlatform.h"
     203                 : 
     204                 : #include "mozilla/FunctionTimer.h"
     205                 : #include "mozilla/Preferences.h"
     206                 : #include "mozilla/Telemetry.h"
     207                 : #include "sampler.h"
     208                 : 
     209                 : #include "Layers.h"
     210                 : #include "nsAsyncDOMEvent.h"
     211                 : 
     212                 : #ifdef NS_FUNCTION_TIMER
     213                 : #define NS_TIME_FUNCTION_DECLARE_DOCURL                \
     214                 :   nsCAutoString docURL__("N/A");                       \
     215                 :   nsIURI *uri__ = mDocument->GetDocumentURI();         \
     216                 :   if (uri__) uri__->GetSpec(docURL__);
     217                 : #define NS_TIME_FUNCTION_WITH_DOCURL                   \
     218                 :   NS_TIME_FUNCTION_DECLARE_DOCURL                      \
     219                 :   NS_TIME_FUNCTION_MIN_FMT(1.0,                        \
     220                 :      "%s (line %d) (document: %s)", MOZ_FUNCTION_NAME, \
     221                 :      __LINE__, docURL__.get())
     222                 : #else
     223                 : #define NS_TIME_FUNCTION_WITH_DOCURL do{} while(0)
     224                 : #endif
     225                 : 
     226                 : #define ANCHOR_SCROLL_FLAGS (SCROLL_OVERFLOW_HIDDEN | SCROLL_NO_PARENT_FRAMES)
     227                 : 
     228                 : using namespace mozilla;
     229                 : using namespace mozilla::dom;
     230                 : using namespace mozilla::layers;
     231                 : 
     232                 : CapturingContentInfo nsIPresShell::gCaptureInfo =
     233                 :   { false /* mAllowed */,     false /* mRetargetToElement */,
     234                 :     false /* mPreventDrag */, nsnull /* mContent */ };
     235                 : nsIContent* nsIPresShell::gKeyDownTarget;
     236            1464 : nsInterfaceHashtable<nsUint32HashKey, nsIDOMTouch> nsIPresShell::gCaptureTouchList;
     237                 : bool nsIPresShell::gPreventMouseEvents = false;
     238                 : 
     239                 : static PRUint32
     240               0 : ChangeFlag(PRUint32 aFlags, bool aOnOff, PRUint32 aFlag)
     241                 : {
     242                 :   PRUint32 flags;
     243               0 :   if (aOnOff) {
     244               0 :     flags = (aFlags | aFlag);
     245                 :   } else {
     246               0 :     flags = (aFlag & ~aFlag);
     247                 :   }
     248               0 :   return flags;
     249                 : }
     250                 : 
     251                 : // convert a color value to a string, in the CSS format #RRGGBB
     252                 : // *  - initially created for bugs 31816, 20760, 22963
     253                 : static void ColorToString(nscolor aColor, nsAutoString &aString);
     254                 : 
     255                 : // RangePaintInfo is used to paint ranges to offscreen buffers
     256                 : struct RangePaintInfo {
     257                 :   nsRefPtr<nsRange> mRange;
     258                 :   nsDisplayListBuilder mBuilder;
     259                 :   nsDisplayList mList;
     260                 : 
     261                 :   // offset of builder's reference frame to the root frame
     262                 :   nsPoint mRootOffset;
     263                 : 
     264               0 :   RangePaintInfo(nsRange* aRange, nsIFrame* aFrame)
     265               0 :     : mRange(aRange), mBuilder(aFrame, nsDisplayListBuilder::PAINTING, false)
     266                 :   {
     267               0 :     MOZ_COUNT_CTOR(RangePaintInfo);
     268               0 :   }
     269                 : 
     270               0 :   ~RangePaintInfo()
     271               0 :   {
     272               0 :     mList.DeleteAll();
     273               0 :     MOZ_COUNT_DTOR(RangePaintInfo);
     274               0 :   }
     275                 : };
     276                 : 
     277                 : #undef NOISY
     278                 : 
     279                 : // ----------------------------------------------------------------------
     280                 : 
     281                 : #ifdef NS_DEBUG
     282                 : // Set the environment variable GECKO_VERIFY_REFLOW_FLAGS to one or
     283                 : // more of the following flags (comma separated) for handy debug
     284                 : // output.
     285                 : static PRUint32 gVerifyReflowFlags;
     286                 : 
     287                 : struct VerifyReflowFlags {
     288                 :   const char*    name;
     289                 :   PRUint32 bit;
     290                 : };
     291                 : 
     292                 : static const VerifyReflowFlags gFlags[] = {
     293                 :   { "verify",                VERIFY_REFLOW_ON },
     294                 :   { "reflow",                VERIFY_REFLOW_NOISY },
     295                 :   { "all",                   VERIFY_REFLOW_ALL },
     296                 :   { "list-commands",         VERIFY_REFLOW_DUMP_COMMANDS },
     297                 :   { "noisy-commands",        VERIFY_REFLOW_NOISY_RC },
     298                 :   { "really-noisy-commands", VERIFY_REFLOW_REALLY_NOISY_RC },
     299                 :   { "resize",                VERIFY_REFLOW_DURING_RESIZE_REFLOW },
     300                 : };
     301                 : 
     302                 : #define NUM_VERIFY_REFLOW_FLAGS (sizeof(gFlags) / sizeof(gFlags[0]))
     303                 : 
     304                 : static void
     305               0 : ShowVerifyReflowFlags()
     306                 : {
     307               0 :   printf("Here are the available GECKO_VERIFY_REFLOW_FLAGS:\n");
     308               0 :   const VerifyReflowFlags* flag = gFlags;
     309               0 :   const VerifyReflowFlags* limit = gFlags + NUM_VERIFY_REFLOW_FLAGS;
     310               0 :   while (flag < limit) {
     311               0 :     printf("  %s\n", flag->name);
     312               0 :     ++flag;
     313                 :   }
     314               0 :   printf("Note: GECKO_VERIFY_REFLOW_FLAGS is a comma separated list of flag\n");
     315               0 :   printf("names (no whitespace)\n");
     316               0 : }
     317                 : #endif
     318                 : 
     319                 : //========================================================================
     320                 : //========================================================================
     321                 : //========================================================================
     322                 : #ifdef MOZ_REFLOW_PERF
     323                 : class ReflowCountMgr;
     324                 : 
     325                 : static const char kGrandTotalsStr[] = "Grand Totals";
     326                 : 
     327                 : // Counting Class
     328                 : class ReflowCounter {
     329                 : public:
     330                 :   ReflowCounter(ReflowCountMgr * aMgr = nsnull);
     331                 :   ~ReflowCounter();
     332                 : 
     333                 :   void ClearTotals();
     334                 :   void DisplayTotals(const char * aStr);
     335                 :   void DisplayDiffTotals(const char * aStr);
     336                 :   void DisplayHTMLTotals(const char * aStr);
     337                 : 
     338               0 :   void Add()                { mTotal++;         }
     339               0 :   void Add(PRUint32 aTotal) { mTotal += aTotal; }
     340                 : 
     341                 :   void CalcDiffInTotals();
     342                 :   void SetTotalsCache();
     343                 : 
     344                 :   void SetMgr(ReflowCountMgr * aMgr) { mMgr = aMgr; }
     345                 : 
     346               0 :   PRUint32 GetTotal() { return mTotal; }
     347                 :   
     348                 : protected:
     349                 :   void DisplayTotals(PRUint32 aTotal, const char * aTitle);
     350                 :   void DisplayHTMLTotals(PRUint32 aTotal, const char * aTitle);
     351                 : 
     352                 :   PRUint32 mTotal;
     353                 :   PRUint32 mCacheTotal;
     354                 : 
     355                 :   ReflowCountMgr * mMgr; // weak reference (don't delete)
     356                 : };
     357                 : 
     358                 : // Counting Class
     359                 : class IndiReflowCounter {
     360                 : public:
     361               0 :   IndiReflowCounter(ReflowCountMgr * aMgr = nsnull)
     362                 :     : mFrame(nsnull),
     363                 :       mCount(0),
     364                 :       mMgr(aMgr),
     365                 :       mCounter(aMgr),
     366               0 :       mHasBeenOutput(false)
     367               0 :     {}
     368               0 :   virtual ~IndiReflowCounter() {}
     369                 : 
     370                 :   nsAutoString mName;
     371                 :   nsIFrame *   mFrame;   // weak reference (don't delete)
     372                 :   PRInt32      mCount;
     373                 : 
     374                 :   ReflowCountMgr * mMgr; // weak reference (don't delete)
     375                 : 
     376                 :   ReflowCounter mCounter;
     377                 :   bool          mHasBeenOutput;
     378                 : 
     379                 : };
     380                 : 
     381                 : //--------------------
     382                 : // Manager Class
     383                 : //--------------------
     384                 : class ReflowCountMgr {
     385                 : public:
     386                 :   ReflowCountMgr();
     387                 :   virtual ~ReflowCountMgr();
     388                 : 
     389                 :   void ClearTotals();
     390                 :   void ClearGrandTotals();
     391                 :   void DisplayTotals(const char * aStr);
     392                 :   void DisplayHTMLTotals(const char * aStr);
     393                 :   void DisplayDiffsInTotals(const char * aStr);
     394                 : 
     395                 :   void Add(const char * aName, nsIFrame * aFrame);
     396                 :   ReflowCounter * LookUp(const char * aName);
     397                 : 
     398                 :   void PaintCount(const char *aName, nsRenderingContext* aRenderingContext,
     399                 :                   nsPresContext *aPresContext, nsIFrame *aFrame,
     400                 :                   const nsPoint &aOffset, PRUint32 aColor);
     401                 : 
     402               0 :   FILE * GetOutFile() { return mFD; }
     403                 : 
     404                 :   PLHashTable * GetIndiFrameHT() { return mIndiFrameCounts; }
     405                 : 
     406               0 :   void SetPresContext(nsPresContext * aPresContext) { mPresContext = aPresContext; } // weak reference
     407               0 :   void SetPresShell(nsIPresShell* aPresShell) { mPresShell= aPresShell; } // weak reference
     408                 : 
     409               0 :   void SetDumpFrameCounts(bool aVal)         { mDumpFrameCounts = aVal; }
     410               0 :   void SetDumpFrameByFrameCounts(bool aVal)  { mDumpFrameByFrameCounts = aVal; }
     411               0 :   void SetPaintFrameCounts(bool aVal)        { mPaintFrameByFrameCounts = aVal; }
     412                 : 
     413               0 :   bool IsPaintingFrameCounts() { return mPaintFrameByFrameCounts; }
     414                 : 
     415                 : protected:
     416                 :   void DisplayTotals(PRUint32 aTotal, PRUint32 * aDupArray, char * aTitle);
     417                 :   void DisplayHTMLTotals(PRUint32 aTotal, PRUint32 * aDupArray, char * aTitle);
     418                 : 
     419                 :   static PRIntn RemoveItems(PLHashEntry *he, PRIntn i, void *arg);
     420                 :   static PRIntn RemoveIndiItems(PLHashEntry *he, PRIntn i, void *arg);
     421                 :   void CleanUp();
     422                 : 
     423                 :   // stdout Output Methods
     424                 :   static PRIntn DoSingleTotal(PLHashEntry *he, PRIntn i, void *arg);
     425                 :   static PRIntn DoSingleIndi(PLHashEntry *he, PRIntn i, void *arg);
     426                 : 
     427                 :   void DoGrandTotals();
     428                 :   void DoIndiTotalsTree();
     429                 : 
     430                 :   // HTML Output Methods
     431                 :   static PRIntn DoSingleHTMLTotal(PLHashEntry *he, PRIntn i, void *arg);
     432                 :   void DoGrandHTMLTotals();
     433                 : 
     434                 :   // Zero Out the Totals
     435                 :   static PRIntn DoClearTotals(PLHashEntry *he, PRIntn i, void *arg);
     436                 : 
     437                 :   // Displays the Diff Totals
     438                 :   static PRIntn DoDisplayDiffTotals(PLHashEntry *he, PRIntn i, void *arg);
     439                 : 
     440                 :   PLHashTable * mCounts;
     441                 :   PLHashTable * mIndiFrameCounts;
     442                 :   FILE * mFD;
     443                 :   
     444                 :   bool mDumpFrameCounts;
     445                 :   bool mDumpFrameByFrameCounts;
     446                 :   bool mPaintFrameByFrameCounts;
     447                 : 
     448                 :   bool mCycledOnce;
     449                 : 
     450                 :   // Root Frame for Individual Tracking
     451                 :   nsPresContext * mPresContext;
     452                 :   nsIPresShell*    mPresShell;
     453                 : 
     454                 :   // ReflowCountMgr gReflowCountMgr;
     455                 : };
     456                 : #endif
     457                 : //========================================================================
     458                 : 
     459                 : // comment out to hide caret
     460                 : #define SHOW_CARET
     461                 : 
     462                 : // The upper bound on the amount of time to spend reflowing, in
     463                 : // microseconds.  When this bound is exceeded and reflow commands are
     464                 : // still queued up, a reflow event is posted.  The idea is for reflow
     465                 : // to not hog the processor beyond the time specifed in
     466                 : // gMaxRCProcessingTime.  This data member is initialized from the
     467                 : // layout.reflow.timeslice pref.
     468                 : #define NS_MAX_REFLOW_TIME    1000000
     469                 : static PRInt32 gMaxRCProcessingTime = -1;
     470                 : 
     471               0 : StackArena::StackArena()
     472                 : {
     473               0 :   mMarkLength = 0;
     474               0 :   mMarks = nsnull;
     475                 : 
     476                 :   // allocate our stack memory
     477               0 :   mBlocks = new StackBlock();
     478               0 :   mCurBlock = mBlocks;
     479                 : 
     480               0 :   mStackTop = 0;
     481               0 :   mPos = 0;
     482               0 : }
     483                 : 
     484               0 : StackArena::~StackArena()
     485                 : {
     486                 :   // free up our data
     487               0 :   delete[] mMarks;
     488               0 :   while(mBlocks)
     489                 :   {
     490               0 :     StackBlock* toDelete = mBlocks;
     491               0 :     mBlocks = mBlocks->mNext;
     492               0 :     delete toDelete;
     493                 :   }
     494               0 : } 
     495                 : 
     496                 : void
     497               0 : StackArena::Push()
     498                 : {
     499                 :   // Resize the mark array if we overrun it.  Failure to allocate the
     500                 :   // mark array is not fatal; we just won't free to that mark.  This
     501                 :   // allows callers not to worry about error checking.
     502               0 :   if (mStackTop >= mMarkLength)
     503                 :   {
     504               0 :     PRUint32 newLength = mStackTop + STACK_ARENA_MARK_INCREMENT;
     505               0 :     StackMark* newMarks = new StackMark[newLength];
     506               0 :     if (newMarks) {
     507               0 :       if (mMarkLength)
     508               0 :         memcpy(newMarks, mMarks, sizeof(StackMark)*mMarkLength);
     509                 :       // Fill in any marks that we couldn't allocate during a prior call
     510                 :       // to Push().
     511               0 :       for (; mMarkLength < mStackTop; ++mMarkLength) {
     512               0 :         NS_NOTREACHED("should only hit this on out-of-memory");
     513               0 :         newMarks[mMarkLength].mBlock = mCurBlock;
     514               0 :         newMarks[mMarkLength].mPos = mPos;
     515                 :       }
     516               0 :       delete [] mMarks;
     517               0 :       mMarks = newMarks;
     518               0 :       mMarkLength = newLength;
     519                 :     }
     520                 :   }
     521                 : 
     522                 :   // set a mark at the top (if we can)
     523               0 :   NS_ASSERTION(mStackTop < mMarkLength, "out of memory");
     524               0 :   if (mStackTop < mMarkLength) {
     525               0 :     mMarks[mStackTop].mBlock = mCurBlock;
     526               0 :     mMarks[mStackTop].mPos = mPos;
     527                 :   }
     528                 : 
     529               0 :   mStackTop++;
     530               0 : }
     531                 : 
     532                 : void*
     533               0 : StackArena::Allocate(size_t aSize)
     534                 : {
     535               0 :   NS_ASSERTION(mStackTop > 0, "Allocate called without Push");
     536                 : 
     537                 :   // make sure we are aligned. Beard said 8 was safer then 4. 
     538                 :   // Round size to multiple of 8
     539               0 :   aSize = NS_ROUNDUP<size_t>(aSize, 8);
     540                 : 
     541                 :   // if the size makes the stack overflow. Grab another block for the stack
     542               0 :   if (mPos + aSize >= STACK_ARENA_BLOCK_INCREMENT)
     543                 :   {
     544               0 :     NS_ASSERTION(aSize <= STACK_ARENA_BLOCK_INCREMENT,
     545                 :                  "Requested memory is greater that our block size!!");
     546               0 :     if (mCurBlock->mNext == nsnull)
     547               0 :       mCurBlock->mNext = new StackBlock();
     548                 : 
     549               0 :     mCurBlock =  mCurBlock->mNext;
     550               0 :     mPos = 0;
     551                 :   }
     552                 : 
     553                 :   // return the chunk they need.
     554               0 :   void *result = mCurBlock->mBlock + mPos;
     555               0 :   mPos += aSize;
     556                 : 
     557               0 :   return result;
     558                 : }
     559                 : 
     560                 : void
     561               0 : StackArena::Pop()
     562                 : {
     563                 :   // pop off the mark
     564               0 :   NS_ASSERTION(mStackTop > 0, "unmatched pop");
     565               0 :   mStackTop--;
     566                 : 
     567               0 :   if (mStackTop >= mMarkLength) {
     568                 :     // We couldn't allocate the marks array at the time of the push, so
     569                 :     // we don't know where we're freeing to.
     570               0 :     NS_NOTREACHED("out of memory");
     571               0 :     if (mStackTop == 0) {
     572                 :       // But we do know if we've completely pushed the stack.
     573               0 :       mCurBlock = mBlocks;
     574               0 :       mPos = 0;
     575                 :     }
     576               0 :     return;
     577                 :   }
     578                 : 
     579                 : #ifdef DEBUG
     580                 :   // Mark the "freed" memory with 0xdd to help with debugging of memory
     581                 :   // allocation problems.
     582                 :   {
     583               0 :     StackBlock *block = mMarks[mStackTop].mBlock, *block_end = mCurBlock;
     584               0 :     size_t pos = mMarks[mStackTop].mPos;
     585               0 :     for (; block != block_end; block = block->mNext, pos = 0) {
     586               0 :       memset(block->mBlock + pos, 0xdd, sizeof(block->mBlock) - pos);
     587                 :     }
     588               0 :     memset(block->mBlock + pos, 0xdd, mPos - pos);
     589                 :   }
     590                 : #endif
     591                 : 
     592               0 :   mCurBlock = mMarks[mStackTop].mBlock;
     593               0 :   mPos      = mMarks[mStackTop].mPos;
     594                 : }
     595                 : 
     596                 : struct nsCallbackEventRequest
     597                 : {
     598                 :   nsIReflowCallback* callback;
     599                 :   nsCallbackEventRequest* next;
     600                 : };
     601                 : 
     602                 : // ----------------------------------------------------------------------------
     603                 : #define ASSERT_REFLOW_SCHEDULED_STATE()                                       \
     604                 :   NS_ASSERTION(mReflowScheduled ==                                            \
     605                 :                  GetPresContext()->RefreshDriver()->                          \
     606                 :                    IsLayoutFlushObserver(this), "Unexpected state")
     607                 : 
     608                 : class nsAutoCauseReflowNotifier
     609                 : {
     610                 : public:
     611               0 :   nsAutoCauseReflowNotifier(PresShell* aShell)
     612               0 :     : mShell(aShell)
     613                 :   {
     614               0 :     mShell->WillCauseReflow();
     615               0 :   }
     616               0 :   ~nsAutoCauseReflowNotifier()
     617                 :   {
     618                 :     // This check should not be needed. Currently the only place that seem
     619                 :     // to need it is the code that deals with bug 337586.
     620               0 :     if (!mShell->mHaveShutDown) {
     621               0 :       mShell->DidCauseReflow();
     622                 :     }
     623                 :     else {
     624               0 :       nsContentUtils::RemoveScriptBlocker();
     625                 :     }
     626               0 :   }
     627                 : 
     628                 :   PresShell* mShell;
     629                 : };
     630                 : 
     631                 : class NS_STACK_CLASS nsPresShellEventCB : public nsDispatchingCallback
     632               0 : {
     633                 : public:
     634               0 :   nsPresShellEventCB(PresShell* aPresShell) : mPresShell(aPresShell) {}
     635                 : 
     636               0 :   virtual void HandleEvent(nsEventChainPostVisitor& aVisitor)
     637                 :   {
     638               0 :     if (aVisitor.mPresContext && aVisitor.mEvent->eventStructType != NS_EVENT) {
     639               0 :       nsIFrame* frame = mPresShell->GetCurrentEventFrame();
     640               0 :       if (frame) {
     641                 :         frame->HandleEvent(aVisitor.mPresContext,
     642                 :                            (nsGUIEvent*) aVisitor.mEvent,
     643               0 :                            &aVisitor.mEventStatus);
     644                 :       }
     645                 :     }
     646               0 :   }
     647                 : 
     648                 :   nsRefPtr<PresShell> mPresShell;
     649                 : };
     650                 : 
     651                 : bool PresShell::sDisableNonTestMouseEvents = false;
     652                 : 
     653                 : #ifdef PR_LOGGING
     654                 : PRLogModuleInfo* PresShell::gLog;
     655                 : #endif
     656                 : 
     657                 : #ifdef NS_DEBUG
     658                 : static void
     659               0 : VerifyStyleTree(nsPresContext* aPresContext, nsFrameManager* aFrameManager)
     660                 : {
     661               0 :   if (nsFrame::GetVerifyStyleTreeEnable()) {
     662               0 :     nsIFrame* rootFrame = aFrameManager->GetRootFrame();
     663               0 :     aFrameManager->DebugVerifyStyleTree(rootFrame);
     664                 :   }
     665               0 : }
     666                 : #define VERIFY_STYLE_TREE ::VerifyStyleTree(mPresContext, mFrameConstructor)
     667                 : #else
     668                 : #define VERIFY_STYLE_TREE
     669                 : #endif
     670                 : 
     671                 : static bool gVerifyReflowEnabled;
     672                 : 
     673                 : bool
     674               0 : nsIPresShell::GetVerifyReflowEnable()
     675                 : {
     676                 : #ifdef NS_DEBUG
     677                 :   static bool firstTime = true;
     678               0 :   if (firstTime) {
     679               0 :     firstTime = false;
     680               0 :     char* flags = PR_GetEnv("GECKO_VERIFY_REFLOW_FLAGS");
     681               0 :     if (flags) {
     682               0 :       bool error = false;
     683                 : 
     684               0 :       for (;;) {
     685               0 :         char* comma = PL_strchr(flags, ',');
     686               0 :         if (comma)
     687               0 :           *comma = '\0';
     688                 : 
     689               0 :         bool found = false;
     690               0 :         const VerifyReflowFlags* flag = gFlags;
     691               0 :         const VerifyReflowFlags* limit = gFlags + NUM_VERIFY_REFLOW_FLAGS;
     692               0 :         while (flag < limit) {
     693               0 :           if (PL_strcasecmp(flag->name, flags) == 0) {
     694               0 :             gVerifyReflowFlags |= flag->bit;
     695               0 :             found = true;
     696               0 :             break;
     697                 :           }
     698               0 :           ++flag;
     699                 :         }
     700                 : 
     701               0 :         if (! found)
     702               0 :           error = true;
     703                 : 
     704               0 :         if (! comma)
     705                 :           break;
     706                 : 
     707               0 :         *comma = ',';
     708               0 :         flags = comma + 1;
     709                 :       }
     710                 : 
     711               0 :       if (error)
     712               0 :         ShowVerifyReflowFlags();
     713                 :     }
     714                 : 
     715               0 :     if (VERIFY_REFLOW_ON & gVerifyReflowFlags) {
     716               0 :       gVerifyReflowEnabled = true;
     717                 : 
     718               0 :       printf("Note: verifyreflow is enabled");
     719               0 :       if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
     720               0 :         printf(" (noisy)");
     721                 :       }
     722               0 :       if (VERIFY_REFLOW_ALL & gVerifyReflowFlags) {
     723               0 :         printf(" (all)");
     724                 :       }
     725               0 :       if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
     726               0 :         printf(" (show reflow commands)");
     727                 :       }
     728               0 :       if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
     729               0 :         printf(" (noisy reflow commands)");
     730               0 :         if (VERIFY_REFLOW_REALLY_NOISY_RC & gVerifyReflowFlags) {
     731               0 :           printf(" (REALLY noisy reflow commands)");
     732                 :         }
     733                 :       }
     734               0 :       printf("\n");
     735                 :     }
     736                 :   }
     737                 : #endif
     738               0 :   return gVerifyReflowEnabled;
     739                 : }
     740                 : 
     741                 : void
     742               0 : nsIPresShell::SetVerifyReflowEnable(bool aEnabled)
     743                 : {
     744               0 :   gVerifyReflowEnabled = aEnabled;
     745               0 : }
     746                 : 
     747                 : /* virtual */ void
     748               0 : nsIPresShell::AddWeakFrameExternal(nsWeakFrame* aWeakFrame)
     749                 : {
     750               0 :   AddWeakFrameInternal(aWeakFrame);
     751               0 : }
     752                 : 
     753                 : void
     754               0 : nsIPresShell::AddWeakFrameInternal(nsWeakFrame* aWeakFrame)
     755                 : {
     756               0 :   if (aWeakFrame->GetFrame()) {
     757               0 :     aWeakFrame->GetFrame()->AddStateBits(NS_FRAME_EXTERNAL_REFERENCE);
     758                 :   }
     759               0 :   aWeakFrame->SetPreviousWeakFrame(mWeakFrames);
     760               0 :   mWeakFrames = aWeakFrame;
     761               0 : }
     762                 : 
     763                 : /* virtual */ void
     764               0 : nsIPresShell::RemoveWeakFrameExternal(nsWeakFrame* aWeakFrame)
     765                 : {
     766               0 :   RemoveWeakFrameInternal(aWeakFrame);
     767               0 : }
     768                 : 
     769                 : void
     770               0 : nsIPresShell::RemoveWeakFrameInternal(nsWeakFrame* aWeakFrame)
     771                 : {
     772               0 :   if (mWeakFrames == aWeakFrame) {
     773               0 :     mWeakFrames = aWeakFrame->GetPreviousWeakFrame();
     774               0 :     return;
     775                 :   }
     776               0 :   nsWeakFrame* nextWeak = mWeakFrames;
     777               0 :   while (nextWeak && nextWeak->GetPreviousWeakFrame() != aWeakFrame) {
     778               0 :     nextWeak = nextWeak->GetPreviousWeakFrame();
     779                 :   }
     780               0 :   if (nextWeak) {
     781               0 :     nextWeak->SetPreviousWeakFrame(aWeakFrame->GetPreviousWeakFrame());
     782                 :   }
     783                 : }
     784                 : 
     785                 : already_AddRefed<nsFrameSelection>
     786               0 : nsIPresShell::FrameSelection()
     787                 : {
     788               0 :   NS_IF_ADDREF(mSelection);
     789               0 :   return mSelection;
     790                 : }
     791                 : 
     792                 : //----------------------------------------------------------------------
     793                 : 
     794                 : nsresult
     795               0 : NS_NewPresShell(nsIPresShell** aInstancePtrResult)
     796                 : {
     797               0 :   NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
     798                 : 
     799               0 :   if (!aInstancePtrResult)
     800               0 :     return NS_ERROR_NULL_POINTER;
     801                 : 
     802               0 :   *aInstancePtrResult = new PresShell();
     803                 : 
     804               0 :   NS_ADDREF(*aInstancePtrResult);
     805               0 :   return NS_OK;
     806                 : }
     807                 : 
     808                 : static bool sSynthMouseMove = true;
     809                 : 
     810               0 : PresShell::PresShell()
     811               0 :   : mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)
     812                 : {
     813               0 :   mSelection = nsnull;
     814                 : #ifdef MOZ_REFLOW_PERF
     815               0 :   mReflowCountMgr = new ReflowCountMgr();
     816               0 :   mReflowCountMgr->SetPresContext(mPresContext);
     817               0 :   mReflowCountMgr->SetPresShell(this);
     818                 : #endif
     819                 : #ifdef PR_LOGGING
     820               0 :   if (! gLog)
     821               0 :     gLog = PR_NewLogModule("PresShell");
     822                 : #endif
     823               0 :   mSelectionFlags = nsISelectionDisplay::DISPLAY_TEXT | nsISelectionDisplay::DISPLAY_IMAGES;
     824               0 :   mIsThemeSupportDisabled = false;
     825               0 :   mIsActive = true;
     826               0 :   mFrozen = false;
     827                 : #ifdef DEBUG
     828               0 :   mPresArenaAllocCount = 0;
     829                 : #endif
     830               0 :   mRenderFlags = 0;
     831               0 :   mXResolution = 1.0;
     832               0 :   mYResolution = 1.0;
     833               0 :   mViewportOverridden = false;
     834                 : 
     835                 :   static bool addedSynthMouseMove = false;
     836               0 :   if (!addedSynthMouseMove) {
     837                 :     Preferences::AddBoolVarCache(&sSynthMouseMove,
     838               0 :                                  "layout.reflow.synthMouseMove", true);
     839               0 :     addedSynthMouseMove = true;
     840                 :   }
     841               0 : }
     842                 : 
     843               0 : NS_IMPL_ISUPPORTS7(PresShell, nsIPresShell, nsIDocumentObserver,
     844                 :                    nsISelectionController,
     845                 :                    nsISelectionDisplay, nsIObserver, nsISupportsWeakReference,
     846                 :                    nsIMutationObserver)
     847                 : 
     848               0 : PresShell::~PresShell()
     849                 : {
     850               0 :   if (!mHaveShutDown) {
     851               0 :     NS_NOTREACHED("Someone did not call nsIPresShell::destroy");
     852               0 :     Destroy();
     853                 :   }
     854                 : 
     855               0 :   NS_ASSERTION(mCurrentEventContentStack.Count() == 0,
     856                 :                "Huh, event content left on the stack in pres shell dtor!");
     857               0 :   NS_ASSERTION(mFirstCallbackEventRequest == nsnull &&
     858                 :                mLastCallbackEventRequest == nsnull,
     859                 :                "post-reflow queues not empty.  This means we're leaking");
     860                 : 
     861                 : #ifdef DEBUG
     862               0 :   MOZ_ASSERT(mPresArenaAllocCount == 0,
     863               0 :              "Some pres arena objects were not freed");
     864                 : #endif
     865                 : 
     866               0 :   delete mStyleSet;
     867               0 :   delete mFrameConstructor;
     868                 : 
     869               0 :   mCurrentEventContent = nsnull;
     870                 : 
     871               0 :   NS_IF_RELEASE(mPresContext);
     872               0 :   NS_IF_RELEASE(mDocument);
     873               0 :   NS_IF_RELEASE(mSelection);
     874               0 : }
     875                 : 
     876                 : /**
     877                 :  * Initialize the presentation shell. Create view manager and style
     878                 :  * manager.
     879                 :  */
     880                 : nsresult
     881               0 : PresShell::Init(nsIDocument* aDocument,
     882                 :                 nsPresContext* aPresContext,
     883                 :                 nsIViewManager* aViewManager,
     884                 :                 nsStyleSet* aStyleSet,
     885                 :                 nsCompatibility aCompatMode)
     886                 : {
     887                 :   NS_TIME_FUNCTION_MIN(1.0);
     888                 : 
     889               0 :   NS_PRECONDITION(nsnull != aDocument, "null ptr");
     890               0 :   NS_PRECONDITION(nsnull != aPresContext, "null ptr");
     891               0 :   NS_PRECONDITION(nsnull != aViewManager, "null ptr");
     892                 :   nsresult result;
     893                 : 
     894               0 :   if ((nsnull == aDocument) || (nsnull == aPresContext) ||
     895                 :       (nsnull == aViewManager)) {
     896               0 :     return NS_ERROR_NULL_POINTER;
     897                 :   }
     898               0 :   if (mDocument) {
     899               0 :     NS_WARNING("PresShell double init'ed");
     900               0 :     return NS_ERROR_ALREADY_INITIALIZED;
     901                 :   }
     902               0 :   result = mStackArena.Init();
     903               0 :   NS_ENSURE_SUCCESS(result, result);
     904                 : 
     905               0 :   if (!mFramesToDirty.Init()) {
     906               0 :     return NS_ERROR_OUT_OF_MEMORY;
     907                 :   }
     908                 : 
     909               0 :   mDocument = aDocument;
     910               0 :   NS_ADDREF(mDocument);
     911               0 :   mViewManager = aViewManager;
     912                 : 
     913                 :   // Create our frame constructor.
     914               0 :   mFrameConstructor = new nsCSSFrameConstructor(mDocument, this);
     915                 : 
     916               0 :   mFrameManager = mFrameConstructor;
     917                 : 
     918                 :   // The document viewer owns both view manager and pres shell.
     919               0 :   mViewManager->SetPresShell(this);
     920                 : 
     921                 :   // Bind the context to the presentation shell.
     922               0 :   mPresContext = aPresContext;
     923               0 :   NS_ADDREF(mPresContext);
     924               0 :   aPresContext->SetShell(this);
     925                 : 
     926                 :   // Now we can initialize the style set.
     927               0 :   result = aStyleSet->Init(aPresContext);
     928               0 :   NS_ENSURE_SUCCESS(result, result);
     929                 : 
     930                 :   // From this point on, any time we return an error we need to make
     931                 :   // sure to null out mStyleSet first, since an error return from this
     932                 :   // method will cause the caller to delete the style set, so we don't
     933                 :   // want to delete it in our destructor.
     934               0 :   mStyleSet = aStyleSet;
     935                 : 
     936                 :   // Notify our prescontext that it now has a compatibility mode.  Note that
     937                 :   // this MUST happen after we set up our style set but before we create any
     938                 :   // frames.
     939               0 :   mPresContext->CompatibilityModeChanged();
     940                 : 
     941                 :   // setup the preference style rules (no forced reflow), and do it
     942                 :   // before creating any frames.
     943               0 :   SetPreferenceStyleRules(false);
     944                 : 
     945               0 :   NS_ADDREF(mSelection = new nsFrameSelection());
     946                 : 
     947                 :   // Create and initialize the frame manager
     948                 :   // XXXjwatt it would be better if we did this right after creating
     949                 :   // mFrameConstructor, since the frame constructor and frame manager
     950                 :   // are now the same object.
     951               0 :   result =  mFrameConstructor->Init(mStyleSet);
     952               0 :   if (NS_FAILED(result)) {
     953               0 :     NS_WARNING("Frame manager initialization failed");
     954               0 :     mStyleSet = nsnull;
     955               0 :     return result;
     956                 :   }
     957                 : 
     958               0 :   mSelection->Init(this, nsnull);
     959                 : 
     960                 :   // Important: this has to happen after the selection has been set up
     961                 : #ifdef SHOW_CARET
     962                 :   // make the caret
     963               0 :   mCaret = new nsCaret();
     964               0 :   mCaret->Init(this);
     965               0 :   mOriginalCaret = mCaret;
     966                 : 
     967                 :   //SetCaretEnabled(true);       // make it show in browser windows
     968                 : #endif  
     969                 :   //set up selection to be displayed in document
     970                 :   // Don't enable selection for print media
     971               0 :   nsPresContext::nsPresContextType type = aPresContext->Type();
     972               0 :   if (type != nsPresContext::eContext_PrintPreview &&
     973                 :       type != nsPresContext::eContext_Print)
     974               0 :     SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
     975                 :   
     976               0 :   if (gMaxRCProcessingTime == -1) {
     977                 :     gMaxRCProcessingTime =
     978               0 :       Preferences::GetInt("layout.reflow.timeslice", NS_MAX_REFLOW_TIME);
     979                 :   }
     980                 : 
     981                 :   {
     982               0 :     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     983               0 :     if (os) {
     984               0 :       os->AddObserver(this, "agent-sheet-added", false);
     985               0 :       os->AddObserver(this, "user-sheet-added", false);
     986               0 :       os->AddObserver(this, "agent-sheet-removed", false);
     987               0 :       os->AddObserver(this, "user-sheet-removed", false);
     988                 : #ifdef MOZ_XUL
     989               0 :       os->AddObserver(this, "chrome-flush-skin-caches", false);
     990                 : #endif
     991                 :     }
     992                 :   }
     993                 : 
     994                 :   // cache the drag service so we can check it during reflows
     995               0 :   mDragService = do_GetService("@mozilla.org/widget/dragservice;1");
     996                 : 
     997                 : #ifdef MOZ_REFLOW_PERF
     998               0 :     if (mReflowCountMgr) {
     999                 :       bool paintFrameCounts =
    1000               0 :         Preferences::GetBool("layout.reflow.showframecounts");
    1001                 : 
    1002                 :       bool dumpFrameCounts =
    1003               0 :         Preferences::GetBool("layout.reflow.dumpframecounts");
    1004                 : 
    1005                 :       bool dumpFrameByFrameCounts =
    1006               0 :         Preferences::GetBool("layout.reflow.dumpframebyframecounts");
    1007                 : 
    1008               0 :       mReflowCountMgr->SetDumpFrameCounts(dumpFrameCounts);
    1009               0 :       mReflowCountMgr->SetDumpFrameByFrameCounts(dumpFrameByFrameCounts);
    1010               0 :       mReflowCountMgr->SetPaintFrameCounts(paintFrameCounts);
    1011                 :     }
    1012                 : #endif
    1013                 : 
    1014               0 :   if (mDocument->HasAnimationController()) {
    1015               0 :     nsSMILAnimationController* animCtrl = mDocument->GetAnimationController();
    1016               0 :     animCtrl->NotifyRefreshDriverCreated(GetPresContext()->RefreshDriver());
    1017                 :   }
    1018                 : 
    1019                 :   // Get our activeness from the docShell.
    1020               0 :   QueryIsActive();
    1021                 : 
    1022               0 :   return NS_OK;
    1023                 : }
    1024                 : 
    1025                 : void
    1026               0 : PresShell::Destroy()
    1027                 : {
    1028                 :   NS_TIME_FUNCTION_MIN(1.0);
    1029                 : 
    1030               0 :   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
    1031                 :     "destroy called on presshell while scripts not blocked");
    1032                 : 
    1033                 : #ifdef MOZ_REFLOW_PERF
    1034               0 :   DumpReflows();
    1035               0 :   if (mReflowCountMgr) {
    1036               0 :     delete mReflowCountMgr;
    1037               0 :     mReflowCountMgr = nsnull;
    1038                 :   }
    1039                 : #endif
    1040                 : 
    1041               0 :   if (mHaveShutDown)
    1042               0 :     return;
    1043                 : 
    1044                 : #ifdef ACCESSIBILITY
    1045               0 :   nsAccessibilityService* accService = AccService();
    1046               0 :   if (accService) {
    1047               0 :     accService->PresShellDestroyed(this);
    1048                 :   }
    1049                 : #endif // ACCESSIBILITY
    1050                 : 
    1051               0 :   MaybeReleaseCapturingContent();
    1052                 : 
    1053               0 :   if (gKeyDownTarget && gKeyDownTarget->OwnerDoc() == mDocument) {
    1054               0 :     NS_RELEASE(gKeyDownTarget);
    1055                 :   }
    1056                 : 
    1057               0 :   mContentToScrollTo = nsnull;
    1058                 : 
    1059               0 :   if (mPresContext) {
    1060                 :     // We need to notify the destroying the nsPresContext to ESM for
    1061                 :     // suppressing to use from ESM.
    1062               0 :     mPresContext->EventStateManager()->NotifyDestroyPresContext(mPresContext);
    1063                 :   }
    1064                 : 
    1065                 :   {
    1066               0 :     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
    1067               0 :     if (os) {
    1068               0 :       os->RemoveObserver(this, "agent-sheet-added");
    1069               0 :       os->RemoveObserver(this, "user-sheet-added");
    1070               0 :       os->RemoveObserver(this, "agent-sheet-removed");
    1071               0 :       os->RemoveObserver(this, "user-sheet-removed");
    1072                 : #ifdef MOZ_XUL
    1073               0 :       os->RemoveObserver(this, "chrome-flush-skin-caches");
    1074                 : #endif
    1075                 :     }
    1076                 :   }
    1077                 : 
    1078                 :   // If our paint suppression timer is still active, kill it.
    1079               0 :   if (mPaintSuppressionTimer) {
    1080               0 :     mPaintSuppressionTimer->Cancel();
    1081               0 :     mPaintSuppressionTimer = nsnull;
    1082                 :   }
    1083                 : 
    1084                 :   // Same for our reflow continuation timer
    1085               0 :   if (mReflowContinueTimer) {
    1086               0 :     mReflowContinueTimer->Cancel();
    1087               0 :     mReflowContinueTimer = nsnull;
    1088                 :   }
    1089                 : 
    1090               0 :   mSynthMouseMoveEvent.Revoke();
    1091                 : 
    1092               0 :   if (mCaret) {
    1093               0 :     mCaret->Terminate();
    1094               0 :     mCaret = nsnull;
    1095                 :   }
    1096                 : 
    1097               0 :   if (mSelection) {
    1098               0 :     mSelection->DisconnectFromPresShell();
    1099                 :   }
    1100                 : 
    1101                 :   // release our pref style sheet, if we have one still
    1102               0 :   ClearPreferenceStyleRules();
    1103                 : 
    1104               0 :   mIsDestroying = true;
    1105                 : 
    1106                 :   // We can't release all the event content in
    1107                 :   // mCurrentEventContentStack here since there might be code on the
    1108                 :   // stack that will release the event content too. Double release
    1109                 :   // bad!
    1110                 : 
    1111                 :   // The frames will be torn down, so remove them from the current
    1112                 :   // event frame stack (since they'd be dangling references if we'd
    1113                 :   // leave them in) and null out the mCurrentEventFrame pointer as
    1114                 :   // well.
    1115                 : 
    1116               0 :   mCurrentEventFrame = nsnull;
    1117                 : 
    1118               0 :   PRInt32 i, count = mCurrentEventFrameStack.Length();
    1119               0 :   for (i = 0; i < count; i++) {
    1120               0 :     mCurrentEventFrameStack[i] = nsnull;
    1121                 :   }
    1122                 : 
    1123               0 :   mFramesToDirty.Clear();
    1124                 : 
    1125               0 :   if (mViewManager) {
    1126                 :     // Clear the view manager's weak pointer back to |this| in case it
    1127                 :     // was leaked.
    1128               0 :     mViewManager->SetPresShell(nsnull);
    1129               0 :     mViewManager = nsnull;
    1130                 :   }
    1131                 : 
    1132               0 :   mStyleSet->BeginShutdown(mPresContext);
    1133               0 :   nsRefreshDriver* rd = GetPresContext()->RefreshDriver();
    1134                 : 
    1135                 :   // This shell must be removed from the document before the frame
    1136                 :   // hierarchy is torn down to avoid finding deleted frames through
    1137                 :   // this presshell while the frames are being torn down
    1138               0 :   if (mDocument) {
    1139               0 :     NS_ASSERTION(mDocument->GetShell() == this, "Wrong shell?");
    1140               0 :     mDocument->DeleteShell();
    1141                 : 
    1142               0 :     if (mDocument->HasAnimationController()) {
    1143               0 :       mDocument->GetAnimationController()->NotifyRefreshDriverDestroying(rd);
    1144                 :     }
    1145                 :   }
    1146                 : 
    1147                 :   // Revoke any pending events.  We need to do this and cancel pending reflows
    1148                 :   // before we destroy the frame manager, since apparently frame destruction
    1149                 :   // sometimes spins the event queue when plug-ins are involved(!).
    1150               0 :   rd->RemoveLayoutFlushObserver(this);
    1151               0 :   rd->RevokeViewManagerFlush();
    1152                 : 
    1153               0 :   mResizeEvent.Revoke();
    1154               0 :   if (mAsyncResizeTimerIsActive) {
    1155               0 :     mAsyncResizeEventTimer->Cancel();
    1156               0 :     mAsyncResizeTimerIsActive = false;
    1157                 :   }
    1158                 : 
    1159               0 :   CancelAllPendingReflows();
    1160               0 :   CancelPostedReflowCallbacks();
    1161                 : 
    1162                 :   // Destroy the frame manager. This will destroy the frame hierarchy
    1163               0 :   mFrameConstructor->WillDestroyFrameTree();
    1164                 : 
    1165                 :   // Destroy all frame properties (whose destruction was suppressed
    1166                 :   // while destroying the frame tree, but which might contain more
    1167                 :   // frames within the properties.
    1168               0 :   if (mPresContext) {
    1169                 :     // Clear out the prescontext's property table -- since our frame tree is
    1170                 :     // now dead, we shouldn't be looking up any more properties in that table.
    1171                 :     // We want to do this before we call SetShell() on the prescontext, so
    1172                 :     // property destructors can usefully call GetPresShell() on the
    1173                 :     // prescontext.
    1174               0 :     mPresContext->PropertyTable()->DeleteAll();
    1175                 :   }
    1176                 : 
    1177                 : 
    1178               0 :   NS_WARN_IF_FALSE(!mWeakFrames, "Weak frames alive after destroying FrameManager");
    1179               0 :   while (mWeakFrames) {
    1180               0 :     mWeakFrames->Clear(this);
    1181                 :   }
    1182                 : 
    1183                 :   // Let the style set do its cleanup.
    1184               0 :   mStyleSet->Shutdown(mPresContext);
    1185                 : 
    1186               0 :   if (mPresContext) {
    1187                 :     // We hold a reference to the pres context, and it holds a weak link back
    1188                 :     // to us. To avoid the pres context having a dangling reference, set its 
    1189                 :     // pres shell to NULL
    1190               0 :     mPresContext->SetShell(nsnull);
    1191                 : 
    1192                 :     // Clear the link handler (weak reference) as well
    1193               0 :     mPresContext->SetLinkHandler(nsnull);
    1194                 :   }
    1195                 : 
    1196               0 :   mHaveShutDown = true;
    1197                 : }
    1198                 : 
    1199                 :                   // Dynamic stack memory allocation
    1200                 : /* virtual */ void
    1201               0 : PresShell::PushStackMemory()
    1202                 : {
    1203               0 :   mStackArena.Push();
    1204               0 : }
    1205                 : 
    1206                 : /* virtual */ void
    1207               0 : PresShell::PopStackMemory()
    1208                 : {
    1209               0 :   mStackArena.Pop();
    1210               0 : }
    1211                 : 
    1212                 : /* virtual */ void*
    1213               0 : PresShell::AllocateStackMemory(size_t aSize)
    1214                 : {
    1215               0 :   return mStackArena.Allocate(aSize);
    1216                 : }
    1217                 : 
    1218                 : void
    1219               0 : PresShell::FreeFrame(nsQueryFrame::FrameIID aCode, void* aPtr)
    1220                 : {
    1221                 : #ifdef DEBUG
    1222               0 :   mPresArenaAllocCount--;
    1223                 : #endif
    1224               0 :   if (PRESARENA_MUST_FREE_DURING_DESTROY || !mIsDestroying)
    1225               0 :     mFrameArena.FreeByCode(aCode, aPtr);
    1226               0 : }
    1227                 : 
    1228                 : void*
    1229               0 : PresShell::AllocateFrame(nsQueryFrame::FrameIID aCode, size_t aSize)
    1230                 : {
    1231                 : #ifdef DEBUG
    1232               0 :   mPresArenaAllocCount++;
    1233                 : #endif
    1234               0 :   void* result = mFrameArena.AllocateByCode(aCode, aSize);
    1235                 : 
    1236               0 :   if (result) {
    1237               0 :     memset(result, 0, aSize);
    1238                 :   }
    1239               0 :   return result;
    1240                 : }
    1241                 : 
    1242                 : void
    1243               0 : PresShell::FreeMisc(size_t aSize, void* aPtr)
    1244                 : {
    1245                 : #ifdef DEBUG
    1246               0 :   mPresArenaAllocCount--;
    1247                 : #endif
    1248               0 :   if (PRESARENA_MUST_FREE_DURING_DESTROY || !mIsDestroying)
    1249               0 :     mFrameArena.FreeBySize(aSize, aPtr);
    1250               0 : }
    1251                 : 
    1252                 : void*
    1253               0 : PresShell::AllocateMisc(size_t aSize)
    1254                 : {
    1255                 : #ifdef DEBUG
    1256               0 :   mPresArenaAllocCount++;
    1257                 : #endif
    1258               0 :   return mFrameArena.AllocateBySize(aSize);
    1259                 : }
    1260                 : 
    1261                 : void
    1262               0 : nsIPresShell::SetAuthorStyleDisabled(bool aStyleDisabled)
    1263                 : {
    1264               0 :   if (aStyleDisabled != mStyleSet->GetAuthorStyleDisabled()) {
    1265               0 :     mStyleSet->SetAuthorStyleDisabled(aStyleDisabled);
    1266               0 :     ReconstructStyleData();
    1267                 :   }
    1268               0 : }
    1269                 : 
    1270                 : bool
    1271               0 : nsIPresShell::GetAuthorStyleDisabled() const
    1272                 : {
    1273               0 :   return mStyleSet->GetAuthorStyleDisabled();
    1274                 : }
    1275                 : 
    1276                 : nsresult
    1277               0 : PresShell::SetPreferenceStyleRules(bool aForceReflow)
    1278                 : {
    1279                 :   NS_TIME_FUNCTION_MIN(1.0);
    1280                 : 
    1281               0 :   if (!mDocument) {
    1282               0 :     return NS_ERROR_NULL_POINTER;
    1283                 :   }
    1284                 : 
    1285               0 :   nsPIDOMWindow *window = mDocument->GetWindow();
    1286                 : 
    1287                 :   // If the document doesn't have a window there's no need to notify
    1288                 :   // its presshell about changes to preferences since the document is
    1289                 :   // in a state where it doesn't matter any more (see
    1290                 :   // DocumentViewerImpl::Close()).
    1291                 : 
    1292               0 :   if (!window) {
    1293               0 :     return NS_ERROR_NULL_POINTER;
    1294                 :   } 
    1295                 : 
    1296               0 :   NS_PRECONDITION(mPresContext, "presContext cannot be null");
    1297               0 :   if (mPresContext) {
    1298                 :     // first, make sure this is not a chrome shell 
    1299               0 :     if (nsContentUtils::IsInChromeDocshell(mDocument)) {
    1300               0 :       return NS_OK;
    1301                 :     }
    1302                 : 
    1303                 : #ifdef DEBUG_attinasi
    1304                 :     printf("Setting Preference Style Rules:\n");
    1305                 : #endif
    1306                 :     // if here, we need to create rules for the prefs
    1307                 :     // - this includes the background-color, the text-color,
    1308                 :     //   the link color, the visited link color and the link-underlining
    1309                 :     
    1310                 :     // first clear any exising rules
    1311               0 :     nsresult result = ClearPreferenceStyleRules();
    1312                 :       
    1313                 :     // now the link rules (must come after the color rules, or links will not be correct color!)
    1314                 :     // XXX - when there is both an override and agent pref stylesheet this won't matter,
    1315                 :     //       as the color rules will be overrides and the links rules will be agent
    1316               0 :     if (NS_SUCCEEDED(result)) {
    1317               0 :       result = SetPrefLinkRules();
    1318                 :     }
    1319               0 :     if (NS_SUCCEEDED(result)) {
    1320               0 :       result = SetPrefFocusRules();
    1321                 :     }
    1322               0 :     if (NS_SUCCEEDED(result)) {
    1323               0 :       result = SetPrefNoScriptRule();
    1324                 :     }
    1325               0 :     if (NS_SUCCEEDED(result)) {
    1326               0 :       result = SetPrefNoFramesRule();
    1327                 :     }
    1328                 : #ifdef DEBUG_attinasi
    1329                 :     printf( "Preference Style Rules set: error=%ld\n", (long)result);
    1330                 : #endif
    1331                 : 
    1332                 :     // Note that this method never needs to force any calculation; the caller
    1333                 :     // will recalculate style if needed
    1334                 : 
    1335               0 :     return result;
    1336                 :   }
    1337                 : 
    1338               0 :   return NS_ERROR_NULL_POINTER;
    1339                 : }
    1340                 : 
    1341               0 : nsresult PresShell::ClearPreferenceStyleRules(void)
    1342                 : {
    1343               0 :   nsresult result = NS_OK;
    1344               0 :   if (mPrefStyleSheet) {
    1345               0 :     NS_ASSERTION(mStyleSet, "null styleset entirely unexpected!");
    1346               0 :     if (mStyleSet) {
    1347                 :       // remove the sheet from the styleset: 
    1348                 :       // - note that we have to check for success by comparing the count before and after...
    1349                 : #ifdef NS_DEBUG
    1350               0 :       PRInt32 numBefore = mStyleSet->SheetCount(nsStyleSet::eUserSheet);
    1351               0 :       NS_ASSERTION(numBefore > 0, "no user stylesheets in styleset, but we have one!");
    1352                 : #endif
    1353               0 :       mStyleSet->RemoveStyleSheet(nsStyleSet::eUserSheet, mPrefStyleSheet);
    1354                 : 
    1355                 : #ifdef DEBUG_attinasi
    1356                 :       NS_ASSERTION((numBefore - 1) == mStyleSet->GetNumberOfUserStyleSheets(),
    1357                 :                    "Pref stylesheet was not removed");
    1358                 :       printf("PrefStyleSheet removed\n");
    1359                 : #endif
    1360                 :       // clear the sheet pointer: it is strictly historical now
    1361               0 :       mPrefStyleSheet = nsnull;
    1362                 :     }
    1363                 :   }
    1364               0 :   return result;
    1365                 : }
    1366                 : 
    1367               0 : nsresult PresShell::CreatePreferenceStyleSheet(void)
    1368                 : {
    1369                 :   NS_TIME_FUNCTION_MIN(1.0);
    1370                 : 
    1371               0 :   NS_ASSERTION(!mPrefStyleSheet, "prefStyleSheet already exists");
    1372               0 :   nsresult result = NS_NewCSSStyleSheet(getter_AddRefs(mPrefStyleSheet));
    1373               0 :   if (NS_SUCCEEDED(result)) {
    1374               0 :     NS_ASSERTION(mPrefStyleSheet, "null but no error");
    1375               0 :     nsCOMPtr<nsIURI> uri;
    1376               0 :     result = NS_NewURI(getter_AddRefs(uri), "about:PreferenceStyleSheet", nsnull);
    1377               0 :     if (NS_SUCCEEDED(result)) {
    1378               0 :       NS_ASSERTION(uri, "null but no error");
    1379               0 :       mPrefStyleSheet->SetURIs(uri, uri, uri);
    1380               0 :       mPrefStyleSheet->SetComplete();
    1381                 :       PRUint32 index;
    1382                 :       result =
    1383               0 :         mPrefStyleSheet->InsertRuleInternal(NS_LITERAL_STRING("@namespace url(http://www.w3.org/1999/xhtml);"),
    1384               0 :                                             0, &index);
    1385               0 :       if (NS_SUCCEEDED(result)) {
    1386               0 :         mStyleSet->AppendStyleSheet(nsStyleSet::eUserSheet, mPrefStyleSheet);
    1387                 :       }
    1388                 :     }
    1389                 :   }
    1390                 : 
    1391                 : #ifdef DEBUG_attinasi
    1392                 :   printf("CreatePrefStyleSheet completed: error=%ld\n",(long)result);
    1393                 : #endif
    1394                 : 
    1395               0 :   if (NS_FAILED(result)) {
    1396               0 :     mPrefStyleSheet = nsnull;
    1397                 :   }
    1398                 : 
    1399               0 :   return result;
    1400                 : }
    1401                 : 
    1402                 : // XXX We want these after the @namespace rule.  Does order matter
    1403                 : // for these rules, or can we call StyleRule::StyleRuleCount()
    1404                 : // and just "append"?
    1405                 : static PRUint32 sInsertPrefSheetRulesAt = 1;
    1406                 : 
    1407                 : nsresult
    1408               0 : PresShell::SetPrefNoScriptRule()
    1409                 : {
    1410                 :   NS_TIME_FUNCTION_MIN(1.0);
    1411                 : 
    1412               0 :   nsresult rv = NS_OK;
    1413                 : 
    1414                 :   // also handle the case where print is done from print preview
    1415                 :   // see bug #342439 for more details
    1416               0 :   nsIDocument* doc = mDocument;
    1417               0 :   if (doc->IsStaticDocument()) {
    1418               0 :     doc = doc->GetOriginalDocument();
    1419                 :   }
    1420                 : 
    1421               0 :   bool scriptEnabled = doc->IsScriptEnabled();
    1422               0 :   if (scriptEnabled) {
    1423               0 :     if (!mPrefStyleSheet) {
    1424               0 :       rv = CreatePreferenceStyleSheet();
    1425               0 :       NS_ENSURE_SUCCESS(rv, rv);
    1426                 :     }
    1427                 : 
    1428               0 :     PRUint32 index = 0;
    1429                 :     mPrefStyleSheet->
    1430               0 :       InsertRuleInternal(NS_LITERAL_STRING("noscript{display:none!important}"),
    1431               0 :                          sInsertPrefSheetRulesAt, &index);
    1432                 :   }
    1433                 : 
    1434               0 :   return rv;
    1435                 : }
    1436                 : 
    1437               0 : nsresult PresShell::SetPrefNoFramesRule(void)
    1438                 : {
    1439                 :   NS_TIME_FUNCTION_MIN(1.0);
    1440                 : 
    1441               0 :   NS_ASSERTION(mPresContext,"null prescontext not allowed");
    1442               0 :   if (!mPresContext) {
    1443               0 :     return NS_ERROR_FAILURE;
    1444                 :   }
    1445                 : 
    1446               0 :   nsresult rv = NS_OK;
    1447                 :   
    1448               0 :   if (!mPrefStyleSheet) {
    1449               0 :     rv = CreatePreferenceStyleSheet();
    1450               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1451                 :   }
    1452                 :   
    1453               0 :   NS_ASSERTION(mPrefStyleSheet, "prefstylesheet should not be null");
    1454                 :   
    1455               0 :   bool allowSubframes = true;
    1456               0 :   nsCOMPtr<nsISupports> container = mPresContext->GetContainer();     
    1457               0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
    1458               0 :   if (docShell) {
    1459               0 :     docShell->GetAllowSubframes(&allowSubframes);
    1460                 :   }
    1461               0 :   if (!allowSubframes) {
    1462               0 :     PRUint32 index = 0;
    1463                 :     rv = mPrefStyleSheet->
    1464               0 :       InsertRuleInternal(NS_LITERAL_STRING("noframes{display:block}"),
    1465               0 :                          sInsertPrefSheetRulesAt, &index);
    1466               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1467                 :     rv = mPrefStyleSheet->
    1468               0 :       InsertRuleInternal(NS_LITERAL_STRING("frame, frameset, iframe {display:none!important}"),
    1469               0 :                          sInsertPrefSheetRulesAt, &index);
    1470                 :   }
    1471               0 :   return rv;
    1472                 : }
    1473                 :   
    1474               0 : nsresult PresShell::SetPrefLinkRules(void)
    1475                 : {
    1476                 :   NS_TIME_FUNCTION_MIN(1.0);
    1477                 : 
    1478               0 :   NS_ASSERTION(mPresContext,"null prescontext not allowed");
    1479               0 :   if (!mPresContext) {
    1480               0 :     return NS_ERROR_FAILURE;
    1481                 :   }
    1482                 : 
    1483               0 :   nsresult rv = NS_OK;
    1484                 :   
    1485               0 :   if (!mPrefStyleSheet) {
    1486               0 :     rv = CreatePreferenceStyleSheet();
    1487               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1488                 :   }
    1489                 :   
    1490               0 :   NS_ASSERTION(mPrefStyleSheet, "prefstylesheet should not be null");
    1491                 :   
    1492                 :   // support default link colors: 
    1493                 :   //   this means the link colors need to be overridable, 
    1494                 :   //   which they are if we put them in the agent stylesheet,
    1495                 :   //   though if using an override sheet this will cause authors grief still
    1496                 :   //   In the agent stylesheet, they are !important when we are ignoring document colors
    1497                 :   
    1498               0 :   nscolor linkColor(mPresContext->DefaultLinkColor());
    1499               0 :   nscolor activeColor(mPresContext->DefaultActiveLinkColor());
    1500               0 :   nscolor visitedColor(mPresContext->DefaultVisitedLinkColor());
    1501                 :   
    1502               0 :   NS_NAMED_LITERAL_STRING(ruleClose, "}");
    1503               0 :   PRUint32 index = 0;
    1504               0 :   nsAutoString strColor;
    1505                 : 
    1506                 :   // insert a rule to color links: '*|*:link {color: #RRGGBB [!important];}'
    1507               0 :   ColorToString(linkColor, strColor);
    1508                 :   rv = mPrefStyleSheet->
    1509               0 :     InsertRuleInternal(NS_LITERAL_STRING("*|*:link{color:") +
    1510               0 :                        strColor + ruleClose,
    1511               0 :                        sInsertPrefSheetRulesAt, &index);
    1512               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1513                 : 
    1514                 :   // - visited links: '*|*:visited {color: #RRGGBB [!important];}'
    1515               0 :   ColorToString(visitedColor, strColor);
    1516                 :   rv = mPrefStyleSheet->
    1517               0 :     InsertRuleInternal(NS_LITERAL_STRING("*|*:visited{color:") +
    1518               0 :                        strColor + ruleClose,
    1519               0 :                        sInsertPrefSheetRulesAt, &index);
    1520               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1521                 : 
    1522                 :   // - active links: '*|*:-moz-any-link:active {color: #RRGGBB [!important];}'
    1523               0 :   ColorToString(activeColor, strColor);
    1524                 :   rv = mPrefStyleSheet->
    1525               0 :     InsertRuleInternal(NS_LITERAL_STRING("*|*:-moz-any-link:active{color:") +
    1526               0 :                        strColor + ruleClose,
    1527               0 :                        sInsertPrefSheetRulesAt, &index);
    1528               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1529                 : 
    1530                 :   bool underlineLinks =
    1531               0 :     mPresContext->GetCachedBoolPref(kPresContext_UnderlineLinks);
    1532                 : 
    1533               0 :   if (underlineLinks) {
    1534                 :     // create a rule to make underlining happen
    1535                 :     //  '*|*:-moz-any-link {text-decoration:[underline|none];}'
    1536                 :     // no need for important, we want these to be overridable
    1537                 :     // NOTE: these must go in the agent stylesheet or they cannot be
    1538                 :     //       overridden by authors
    1539                 :     rv = mPrefStyleSheet->
    1540               0 :       InsertRuleInternal(NS_LITERAL_STRING("*|*:-moz-any-link{text-decoration:underline}"),
    1541               0 :                          sInsertPrefSheetRulesAt, &index);
    1542                 :   } else {
    1543                 :     rv = mPrefStyleSheet->
    1544               0 :       InsertRuleInternal(NS_LITERAL_STRING("*|*:-moz-any-link{text-decoration:none}"),
    1545               0 :                          sInsertPrefSheetRulesAt, &index);
    1546                 :   }
    1547                 : 
    1548               0 :   return rv;          
    1549                 : }
    1550                 : 
    1551               0 : nsresult PresShell::SetPrefFocusRules(void)
    1552                 : {
    1553                 :   NS_TIME_FUNCTION_MIN(1.0);
    1554                 : 
    1555               0 :   NS_ASSERTION(mPresContext,"null prescontext not allowed");
    1556               0 :   nsresult result = NS_OK;
    1557                 : 
    1558               0 :   if (!mPresContext)
    1559               0 :     result = NS_ERROR_FAILURE;
    1560                 : 
    1561               0 :   if (NS_SUCCEEDED(result) && !mPrefStyleSheet)
    1562               0 :     result = CreatePreferenceStyleSheet();
    1563                 : 
    1564               0 :   if (NS_SUCCEEDED(result)) {
    1565               0 :     NS_ASSERTION(mPrefStyleSheet, "prefstylesheet should not be null");
    1566                 : 
    1567               0 :     if (mPresContext->GetUseFocusColors()) {
    1568               0 :       nscolor focusBackground(mPresContext->FocusBackgroundColor());
    1569               0 :       nscolor focusText(mPresContext->FocusTextColor());
    1570                 : 
    1571                 :       // insert a rule to make focus the preferred color
    1572               0 :       PRUint32 index = 0;
    1573               0 :       nsAutoString strRule, strColor;
    1574                 : 
    1575                 :       ///////////////////////////////////////////////////////////////
    1576                 :       // - focus: '*:focus
    1577               0 :       ColorToString(focusText,strColor);
    1578               0 :       strRule.AppendLiteral("*:focus,*:focus>font {color: ");
    1579               0 :       strRule.Append(strColor);
    1580               0 :       strRule.AppendLiteral(" !important; background-color: ");
    1581               0 :       ColorToString(focusBackground,strColor);
    1582               0 :       strRule.Append(strColor);
    1583               0 :       strRule.AppendLiteral(" !important; } ");
    1584                 :       // insert the rules
    1585                 :       result = mPrefStyleSheet->
    1586               0 :         InsertRuleInternal(strRule, sInsertPrefSheetRulesAt, &index);
    1587                 :     }
    1588               0 :     PRUint8 focusRingWidth = mPresContext->FocusRingWidth();
    1589               0 :     bool focusRingOnAnything = mPresContext->GetFocusRingOnAnything();
    1590               0 :     PRUint8 focusRingStyle = mPresContext->GetFocusRingStyle();
    1591                 : 
    1592               0 :     if ((NS_SUCCEEDED(result) && focusRingWidth != 1 && focusRingWidth <= 4 ) || focusRingOnAnything) {
    1593               0 :       PRUint32 index = 0;
    1594               0 :       nsAutoString strRule;
    1595               0 :       if (!focusRingOnAnything)
    1596               0 :         strRule.AppendLiteral("*|*:link:focus, *|*:visited");    // If we only want focus rings on the normal things like links
    1597               0 :       strRule.AppendLiteral(":focus {outline: ");     // For example 3px dotted WindowText (maximum 4)
    1598               0 :       strRule.AppendInt(focusRingWidth);
    1599               0 :       if (focusRingStyle == 0) // solid
    1600               0 :         strRule.AppendLiteral("px solid -moz-mac-focusring !important; -moz-outline-radius: 3px; outline-offset: 1px; } ");
    1601                 :       else // dotted
    1602               0 :         strRule.AppendLiteral("px dotted WindowText !important; } ");
    1603                 :       // insert the rules
    1604                 :       result = mPrefStyleSheet->
    1605               0 :         InsertRuleInternal(strRule, sInsertPrefSheetRulesAt, &index);
    1606               0 :       NS_ENSURE_SUCCESS(result, result);
    1607               0 :       if (focusRingWidth != 1) {
    1608                 :         // If the focus ring width is different from the default, fix buttons with rings
    1609               0 :         strRule.AssignLiteral("button::-moz-focus-inner, input[type=\"reset\"]::-moz-focus-inner,");
    1610               0 :         strRule.AppendLiteral("input[type=\"button\"]::-moz-focus-inner, ");
    1611               0 :         strRule.AppendLiteral("input[type=\"submit\"]::-moz-focus-inner { padding: 1px 2px 1px 2px; border: ");
    1612               0 :         strRule.AppendInt(focusRingWidth);
    1613               0 :         if (focusRingStyle == 0) // solid
    1614               0 :           strRule.AppendLiteral("px solid transparent !important; } ");
    1615                 :         else
    1616               0 :           strRule.AppendLiteral("px dotted transparent !important; } ");
    1617                 :         result = mPrefStyleSheet->
    1618               0 :           InsertRuleInternal(strRule, sInsertPrefSheetRulesAt, &index);
    1619               0 :         NS_ENSURE_SUCCESS(result, result);
    1620                 :           
    1621               0 :         strRule.AssignLiteral("button:focus::-moz-focus-inner, input[type=\"reset\"]:focus::-moz-focus-inner,");
    1622               0 :         strRule.AppendLiteral("input[type=\"button\"]:focus::-moz-focus-inner, input[type=\"submit\"]:focus::-moz-focus-inner {");
    1623               0 :         strRule.AppendLiteral("border-color: ButtonText !important; }");
    1624                 :         result = mPrefStyleSheet->
    1625               0 :           InsertRuleInternal(strRule, sInsertPrefSheetRulesAt, &index);
    1626                 :       }
    1627                 :     }
    1628                 :   }
    1629               0 :   return result;
    1630                 : }
    1631                 : 
    1632                 : void
    1633               0 : PresShell::AddUserSheet(nsISupports* aSheet)
    1634                 : {
    1635                 :   // Make sure this does what DocumentViewerImpl::CreateStyleSet does wrt
    1636                 :   // ordering. We want this new sheet to come after all the existing stylesheet
    1637                 :   // service sheets, but before other user sheets; see nsIStyleSheetService.idl
    1638                 :   // for the ordering.  Just remove and readd all the nsStyleSheetService
    1639                 :   // sheets.
    1640                 :   nsCOMPtr<nsIStyleSheetService> dummy =
    1641               0 :     do_GetService(NS_STYLESHEETSERVICE_CONTRACTID);
    1642                 : 
    1643               0 :   mStyleSet->BeginUpdate();
    1644                 :   
    1645               0 :   nsStyleSheetService *sheetService = nsStyleSheetService::gInstance;
    1646               0 :   nsCOMArray<nsIStyleSheet> & userSheets = *sheetService->UserStyleSheets();
    1647                 :   PRInt32 i;
    1648                 :   // Iterate forwards when removing so the searches for RemoveStyleSheet are as
    1649                 :   // short as possible.
    1650               0 :   for (i = 0; i < userSheets.Count(); ++i) {
    1651               0 :     mStyleSet->RemoveStyleSheet(nsStyleSet::eUserSheet, userSheets[i]);
    1652                 :   }
    1653                 : 
    1654                 :   // Now iterate backwards, so that the order of userSheets will be the same as
    1655                 :   // the order of sheets from it in the style set.
    1656               0 :   for (i = userSheets.Count() - 1; i >= 0; --i) {
    1657               0 :     mStyleSet->PrependStyleSheet(nsStyleSet::eUserSheet, userSheets[i]);
    1658                 :   }
    1659                 : 
    1660               0 :   mStyleSet->EndUpdate();
    1661                 : 
    1662               0 :   ReconstructStyleData();
    1663               0 : }
    1664                 : 
    1665                 : void
    1666               0 : PresShell::AddAgentSheet(nsISupports* aSheet)
    1667                 : {
    1668                 :   // Make sure this does what DocumentViewerImpl::CreateStyleSet does
    1669                 :   // wrt ordering.
    1670               0 :   nsCOMPtr<nsIStyleSheet> sheet = do_QueryInterface(aSheet);
    1671               0 :   if (!sheet) {
    1672                 :     return;
    1673                 :   }
    1674                 : 
    1675               0 :   mStyleSet->AppendStyleSheet(nsStyleSet::eAgentSheet, sheet);
    1676               0 :   ReconstructStyleData();
    1677                 : }
    1678                 : 
    1679                 : void
    1680               0 : PresShell::RemoveSheet(nsStyleSet::sheetType aType, nsISupports* aSheet)
    1681                 : {
    1682               0 :   nsCOMPtr<nsIStyleSheet> sheet = do_QueryInterface(aSheet);
    1683               0 :   if (!sheet) {
    1684                 :     return;
    1685                 :   }
    1686                 : 
    1687               0 :   mStyleSet->RemoveStyleSheet(aType, sheet);
    1688               0 :   ReconstructStyleData();
    1689                 : }
    1690                 : 
    1691                 : NS_IMETHODIMP
    1692               0 : PresShell::SetDisplaySelection(PRInt16 aToggle)
    1693                 : {
    1694               0 :   mSelection->SetDisplaySelection(aToggle);
    1695               0 :   return NS_OK;
    1696                 : }
    1697                 : 
    1698                 : NS_IMETHODIMP
    1699               0 : PresShell::GetDisplaySelection(PRInt16 *aToggle)
    1700                 : {
    1701               0 :   *aToggle = mSelection->GetDisplaySelection();
    1702               0 :   return NS_OK;
    1703                 : }
    1704                 : 
    1705                 : NS_IMETHODIMP
    1706               0 : PresShell::GetSelection(SelectionType aType, nsISelection **aSelection)
    1707                 : {
    1708               0 :   if (!aSelection || !mSelection)
    1709               0 :     return NS_ERROR_NULL_POINTER;
    1710                 : 
    1711               0 :   *aSelection = mSelection->GetSelection(aType);
    1712                 : 
    1713               0 :   if (!(*aSelection))
    1714               0 :     return NS_ERROR_INVALID_ARG;
    1715                 : 
    1716               0 :   NS_ADDREF(*aSelection);
    1717                 : 
    1718               0 :   return NS_OK;
    1719                 : }
    1720                 : 
    1721                 : nsISelection*
    1722               0 : PresShell::GetCurrentSelection(SelectionType aType)
    1723                 : {
    1724               0 :   if (!mSelection)
    1725               0 :     return nsnull;
    1726                 : 
    1727               0 :   return mSelection->GetSelection(aType);
    1728                 : }
    1729                 : 
    1730                 : NS_IMETHODIMP
    1731               0 : PresShell::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion,
    1732                 :                                    PRInt16 aFlags)
    1733                 : {
    1734               0 :   if (!mSelection)
    1735               0 :     return NS_ERROR_NULL_POINTER;
    1736                 : 
    1737               0 :   return mSelection->ScrollSelectionIntoView(aType, aRegion, aFlags);
    1738                 : }
    1739                 : 
    1740                 : NS_IMETHODIMP
    1741               0 : PresShell::RepaintSelection(SelectionType aType)
    1742                 : {
    1743               0 :   if (!mSelection)
    1744               0 :     return NS_ERROR_NULL_POINTER;
    1745                 : 
    1746               0 :   return mSelection->RepaintSelection(aType);
    1747                 : }
    1748                 : 
    1749                 : // Make shell be a document observer
    1750                 : void
    1751               0 : PresShell::BeginObservingDocument()
    1752                 : {
    1753               0 :   if (mDocument && !mIsDestroying) {
    1754               0 :     mDocument->AddObserver(this);
    1755               0 :     if (mIsDocumentGone) {
    1756                 :       NS_WARNING("Adding a presshell that was disconnected from the document "
    1757               0 :                  "as a document observer?  Sounds wrong...");
    1758               0 :       mIsDocumentGone = false;
    1759                 :     }
    1760                 :   }
    1761               0 : }
    1762                 : 
    1763                 : // Make shell stop being a document observer
    1764                 : void
    1765               0 : PresShell::EndObservingDocument()
    1766                 : {
    1767                 :   // XXXbz do we need to tell the frame constructor that the document
    1768                 :   // is gone, perhaps?  Except for printing it's NOT gone, sometimes.
    1769               0 :   mIsDocumentGone = true;
    1770               0 :   if (mDocument) {
    1771               0 :     mDocument->RemoveObserver(this);
    1772                 :   }
    1773               0 : }
    1774                 : 
    1775                 : #ifdef DEBUG_kipp
    1776                 : char* nsPresShell_ReflowStackPointerTop;
    1777                 : #endif
    1778                 : 
    1779                 : nsresult
    1780               0 : PresShell::InitialReflow(nscoord aWidth, nscoord aHeight)
    1781                 : {
    1782               0 :   if (mIsDestroying) {
    1783               0 :     return NS_OK;
    1784                 :   }
    1785                 : 
    1786               0 :   if (!mDocument) {
    1787                 :     // Nothing to do
    1788               0 :     return NS_OK;
    1789                 :   }
    1790                 : 
    1791                 :   NS_TIME_FUNCTION_WITH_DOCURL;
    1792               0 :   mozilla::TimeStamp timerStart = mozilla::TimeStamp::Now();
    1793                 : 
    1794               0 :   NS_ASSERTION(!mDidInitialReflow, "Why are we being called?");
    1795                 : 
    1796               0 :   nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
    1797               0 :   mDidInitialReflow = true;
    1798                 : 
    1799                 : #ifdef NS_DEBUG
    1800               0 :   if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
    1801               0 :     if (mDocument) {
    1802               0 :       nsIURI *uri = mDocument->GetDocumentURI();
    1803               0 :       if (uri) {
    1804               0 :         nsCAutoString url;
    1805               0 :         uri->GetSpec(url);
    1806               0 :         printf("*** PresShell::InitialReflow (this=%p, url='%s')\n", (void*)this, url.get());
    1807                 :       }
    1808                 :     }
    1809                 :   }
    1810                 : #endif
    1811                 : 
    1812               0 :   if (mCaret)
    1813               0 :     mCaret->EraseCaret();
    1814                 : 
    1815                 :   // XXX Do a full invalidate at the beginning so that invalidates along
    1816                 :   // the way don't have region accumulation issues?
    1817                 : 
    1818               0 :   mPresContext->SetVisibleArea(nsRect(0, 0, aWidth, aHeight));
    1819                 : 
    1820                 :   // Get the root frame from the frame manager
    1821                 :   // XXXbz it would be nice to move this somewhere else... like frame manager
    1822                 :   // Init(), say.  But we need to make sure our views are all set up by the
    1823                 :   // time we do this!
    1824               0 :   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
    1825               0 :   NS_ASSERTION(!rootFrame, "How did that happen, exactly?");
    1826               0 :   if (!rootFrame) {
    1827               0 :     nsAutoScriptBlocker scriptBlocker;
    1828               0 :     mFrameConstructor->BeginUpdate();
    1829               0 :     mFrameConstructor->ConstructRootFrame(&rootFrame);
    1830               0 :     mFrameConstructor->SetRootFrame(rootFrame);
    1831               0 :     mFrameConstructor->EndUpdate();
    1832                 :   }
    1833                 : 
    1834               0 :   NS_ENSURE_STATE(!mHaveShutDown);
    1835                 : 
    1836               0 :   if (!rootFrame) {
    1837               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1838                 :   }
    1839                 : 
    1840               0 :   Element *root = mDocument->GetRootElement();
    1841                 : 
    1842               0 :   if (root) {
    1843                 :     {
    1844               0 :       nsAutoCauseReflowNotifier reflowNotifier(this);
    1845               0 :       mFrameConstructor->BeginUpdate();
    1846                 : 
    1847                 :       // Have the style sheet processor construct frame for the root
    1848                 :       // content object down
    1849               0 :       mFrameConstructor->ContentInserted(nsnull, root, nsnull, false);
    1850               0 :       VERIFY_STYLE_TREE;
    1851                 : 
    1852                 :       // Something in mFrameConstructor->ContentInserted may have caused
    1853                 :       // Destroy() to get called, bug 337586.
    1854               0 :       NS_ENSURE_STATE(!mHaveShutDown);
    1855                 : 
    1856               0 :       mFrameConstructor->EndUpdate();
    1857                 :     }
    1858                 : 
    1859                 :     // nsAutoScriptBlocker going out of scope may have killed us too
    1860               0 :     NS_ENSURE_STATE(!mHaveShutDown);
    1861                 : 
    1862                 :     // Run the XBL binding constructors for any new frames we've constructed
    1863               0 :     mDocument->BindingManager()->ProcessAttachedQueue();
    1864                 : 
    1865                 :     NS_TIME_FUNCTION_MARK("XBL binding constructors fired");
    1866                 : 
    1867                 :     // Constructors may have killed us too
    1868               0 :     NS_ENSURE_STATE(!mHaveShutDown);
    1869                 : 
    1870                 :     // Now flush out pending restyles before we actually reflow, in
    1871                 :     // case XBL constructors changed styles somewhere.
    1872                 :     {
    1873               0 :       nsAutoScriptBlocker scriptBlocker;
    1874               0 :       mFrameConstructor->CreateNeededFrames();
    1875               0 :       mFrameConstructor->ProcessPendingRestyles();
    1876                 :     }
    1877                 : 
    1878                 :     // And that might have run _more_ XBL constructors
    1879               0 :     NS_ENSURE_STATE(!mHaveShutDown);
    1880                 :   }
    1881                 : 
    1882               0 :   NS_ASSERTION(rootFrame, "How did that happen?");
    1883                 : 
    1884                 :   // Note: when the frame was created above it had the NS_FRAME_IS_DIRTY bit
    1885                 :   // set, but XBL processing could have caused a reflow which clears it.
    1886               0 :   if (NS_LIKELY(rootFrame->GetStateBits() & NS_FRAME_IS_DIRTY)) {
    1887                 :     // Unset the DIRTY bits so that FrameNeedsReflow() will work right.
    1888                 :     rootFrame->RemoveStateBits(NS_FRAME_IS_DIRTY |
    1889               0 :                                NS_FRAME_HAS_DIRTY_CHILDREN);
    1890               0 :     NS_ASSERTION(!mDirtyRoots.Contains(rootFrame),
    1891                 :                  "Why is the root in mDirtyRoots already?");
    1892               0 :     FrameNeedsReflow(rootFrame, eResize, NS_FRAME_IS_DIRTY);
    1893               0 :     NS_ASSERTION(mDirtyRoots.Contains(rootFrame),
    1894                 :                  "Should be in mDirtyRoots now");
    1895               0 :     NS_ASSERTION(mReflowScheduled, "Why no reflow scheduled?");
    1896                 :   }
    1897                 : 
    1898                 :   // Restore our root scroll position now if we're getting here after EndLoad
    1899                 :   // got called, since this is our one chance to do it.  Note that we need not
    1900                 :   // have reflowed for this to work; when the scrollframe is finally reflowed
    1901                 :   // it'll pick up the position we store in it here.
    1902               0 :   if (!mDocumentLoading) {
    1903               0 :     RestoreRootScrollPosition();
    1904                 :   }
    1905                 : 
    1906                 :   // For printing, we just immediately unsuppress.
    1907               0 :   if (!mPresContext->IsPaginated()) {
    1908                 :     // Kick off a one-shot timer based off our pref value.  When this timer
    1909                 :     // fires, if painting is still locked down, then we will go ahead and
    1910                 :     // trigger a full invalidate and allow painting to proceed normally.
    1911               0 :     mPaintingSuppressed = true;
    1912                 :     // Don't suppress painting if the document isn't loading.
    1913               0 :     nsIDocument::ReadyState readyState = mDocument->GetReadyStateEnum();
    1914               0 :     if (readyState != nsIDocument::READYSTATE_COMPLETE) {
    1915               0 :       mPaintSuppressionTimer = do_CreateInstance("@mozilla.org/timer;1");
    1916                 :     }
    1917               0 :     if (!mPaintSuppressionTimer) {
    1918               0 :       mPaintingSuppressed = false;
    1919                 :     } else {
    1920                 :       // Initialize the timer.
    1921                 : 
    1922                 :       // Default to PAINTLOCK_EVENT_DELAY if we can't get the pref value.
    1923                 :       PRInt32 delay =
    1924                 :         Preferences::GetInt("nglayout.initialpaint.delay",
    1925               0 :                             PAINTLOCK_EVENT_DELAY);
    1926                 : 
    1927               0 :       mPaintSuppressionTimer->InitWithFuncCallback(sPaintSuppressionCallback,
    1928                 :                                                    this, delay, 
    1929               0 :                                                    nsITimer::TYPE_ONE_SHOT);
    1930                 :     }
    1931                 :   }
    1932                 : 
    1933               0 :   if (root && root->IsXUL()) {
    1934                 :     mozilla::Telemetry::AccumulateTimeDelta(Telemetry::XUL_INITIAL_FRAME_CONSTRUCTION,
    1935               0 :                                             timerStart);
    1936                 :   }
    1937                 : 
    1938               0 :   return NS_OK; //XXX this needs to be real. MMP
    1939                 : }
    1940                 : 
    1941                 : void
    1942               0 : PresShell::sPaintSuppressionCallback(nsITimer *aTimer, void* aPresShell)
    1943                 : {
    1944               0 :   nsRefPtr<PresShell> self = static_cast<PresShell*>(aPresShell);
    1945               0 :   if (self)
    1946               0 :     self->UnsuppressPainting();
    1947               0 : }
    1948                 : 
    1949                 : void
    1950               0 : PresShell::AsyncResizeEventCallback(nsITimer* aTimer, void* aPresShell)
    1951                 : {
    1952               0 :   static_cast<PresShell*>(aPresShell)->FireResizeEvent();
    1953               0 : }
    1954                 : 
    1955                 : nsresult
    1956               0 : PresShell::ResizeReflowOverride(nscoord aWidth, nscoord aHeight)
    1957                 : {
    1958               0 :   mViewportOverridden = true;
    1959               0 :   return ResizeReflowIgnoreOverride(aWidth, aHeight);
    1960                 : }
    1961                 : 
    1962                 : nsresult
    1963               0 : PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
    1964                 : {
    1965               0 :   if (mViewportOverridden) {
    1966                 :     // The viewport has been overridden, and this reflow request
    1967                 :     // didn't ask to ignore the override.  Pretend it didn't happen.
    1968               0 :     return NS_OK;
    1969                 :   }
    1970               0 :   return ResizeReflowIgnoreOverride(aWidth, aHeight);
    1971                 : }
    1972                 : 
    1973                 : nsresult
    1974               0 : PresShell::ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight)
    1975                 : {
    1976               0 :   NS_PRECONDITION(!mIsReflowing, "Shouldn't be in reflow here!");
    1977               0 :   NS_PRECONDITION(aWidth != NS_UNCONSTRAINEDSIZE,
    1978                 :                   "shouldn't use unconstrained widths anymore");
    1979                 :   
    1980                 :   // If we don't have a root frame yet, that means we haven't had our initial
    1981                 :   // reflow... If that's the case, and aWidth or aHeight is unconstrained,
    1982                 :   // ignore them altogether.
    1983               0 :   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
    1984                 : 
    1985               0 :   if (!rootFrame && aHeight == NS_UNCONSTRAINEDSIZE) {
    1986                 :     // We can't do the work needed for SizeToContent without a root
    1987                 :     // frame, and we want to return before setting the visible area.
    1988               0 :     return NS_ERROR_NOT_AVAILABLE;
    1989                 :   }
    1990                 : 
    1991               0 :   nsCOMPtr<nsIViewManager> viewManagerDeathGrip = mViewManager;
    1992                 :   // Take this ref after viewManager so it'll make sure to go away first
    1993               0 :   nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
    1994                 : 
    1995               0 :   if (!mIsDestroying && !mResizeEvent.IsPending() &&
    1996               0 :       !mAsyncResizeTimerIsActive) {
    1997               0 :     FireBeforeResizeEvent();
    1998                 :   }
    1999                 : 
    2000               0 :   mPresContext->SetVisibleArea(nsRect(0, 0, aWidth, aHeight));
    2001                 : 
    2002                 :   // There isn't anything useful we can do if the initial reflow hasn't happened
    2003               0 :   rootFrame = mFrameConstructor->GetRootFrame();
    2004               0 :   if (!rootFrame)
    2005               0 :     return NS_OK;
    2006                 : 
    2007               0 :   if (!GetPresContext()->SupressingResizeReflow())
    2008                 :   {
    2009                 :     // Have to make sure that the content notifications are flushed before we
    2010                 :     // start messing with the frame model; otherwise we can get content doubling.
    2011               0 :     mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
    2012                 : 
    2013                 :     // Make sure style is up to date
    2014                 :     {
    2015               0 :       nsAutoScriptBlocker scriptBlocker;
    2016               0 :       mFrameConstructor->CreateNeededFrames();
    2017               0 :       mFrameConstructor->ProcessPendingRestyles();
    2018                 :     }
    2019                 : 
    2020               0 :     rootFrame = mFrameConstructor->GetRootFrame();
    2021               0 :     if (!mIsDestroying && rootFrame) {
    2022                 :       // XXX Do a full invalidate at the beginning so that invalidates along
    2023                 :       // the way don't have region accumulation issues?
    2024                 : 
    2025                 :       {
    2026               0 :         nsAutoCauseReflowNotifier crNotifier(this);
    2027               0 :         WillDoReflow();
    2028                 : 
    2029                 :         // Kick off a top-down reflow
    2030               0 :         AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
    2031               0 :         nsIViewManager::AutoDisableRefresh refreshBlocker(mViewManager);
    2032                 : 
    2033               0 :         mDirtyRoots.RemoveElement(rootFrame);
    2034               0 :         DoReflow(rootFrame, true);
    2035                 :       }
    2036                 : 
    2037               0 :       DidDoReflow(true);
    2038                 :     }
    2039                 :   }
    2040                 : 
    2041               0 :   rootFrame = mFrameConstructor->GetRootFrame();
    2042               0 :   if (aHeight == NS_UNCONSTRAINEDSIZE && rootFrame) {
    2043                 :     mPresContext->SetVisibleArea(
    2044               0 :       nsRect(0, 0, aWidth, rootFrame->GetRect().height));
    2045                 :   }
    2046                 : 
    2047               0 :   if (!mIsDestroying && !mResizeEvent.IsPending() &&
    2048               0 :       !mAsyncResizeTimerIsActive) {
    2049               0 :     if (mInResize) {
    2050               0 :       if (!mAsyncResizeEventTimer) {
    2051               0 :         mAsyncResizeEventTimer = do_CreateInstance("@mozilla.org/timer;1");
    2052                 :       }
    2053               0 :       if (mAsyncResizeEventTimer) {
    2054               0 :         mAsyncResizeTimerIsActive = true;
    2055               0 :         mAsyncResizeEventTimer->InitWithFuncCallback(AsyncResizeEventCallback,
    2056                 :                                                      this, 15,
    2057               0 :                                                      nsITimer::TYPE_ONE_SHOT);
    2058                 :       }
    2059                 :     } else {
    2060                 :       nsRefPtr<nsRunnableMethod<PresShell> > resizeEvent =
    2061               0 :         NS_NewRunnableMethod(this, &PresShell::FireResizeEvent);
    2062               0 :       if (NS_SUCCEEDED(NS_DispatchToCurrentThread(resizeEvent))) {
    2063               0 :         mResizeEvent = resizeEvent;
    2064               0 :         mDocument->SetNeedStyleFlush();
    2065                 :       }
    2066                 :     }
    2067                 :   }
    2068                 : 
    2069               0 :   return NS_OK; //XXX this needs to be real. MMP
    2070                 : }
    2071                 : 
    2072                 : void
    2073               0 : PresShell::FireBeforeResizeEvent()
    2074                 : {
    2075               0 :   if (mIsDocumentGone)
    2076               0 :     return;
    2077                 : 
    2078                 :   // Send beforeresize event from here.
    2079               0 :   nsEvent event(true, NS_BEFORERESIZE_EVENT);
    2080                 : 
    2081               0 :   nsPIDOMWindow *window = mDocument->GetWindow();
    2082               0 :   if (window) {
    2083               0 :     nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
    2084               0 :     nsEventDispatcher::Dispatch(window, mPresContext, &event);
    2085                 :   }
    2086                 : }
    2087                 : 
    2088                 : void
    2089               0 : PresShell::FireResizeEvent()
    2090                 : {
    2091               0 :   if (mAsyncResizeTimerIsActive) {
    2092               0 :     mAsyncResizeTimerIsActive = false;
    2093               0 :     mAsyncResizeEventTimer->Cancel();
    2094                 :   }
    2095               0 :   mResizeEvent.Revoke();
    2096                 : 
    2097               0 :   if (mIsDocumentGone)
    2098               0 :     return;
    2099                 : 
    2100                 :   //Send resize event from here.
    2101               0 :   nsEvent event(true, NS_RESIZE_EVENT);
    2102               0 :   nsEventStatus status = nsEventStatus_eIgnore;
    2103                 : 
    2104               0 :   nsPIDOMWindow *window = mDocument->GetWindow();
    2105               0 :   if (window) {
    2106               0 :     nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
    2107               0 :     mInResize = true;
    2108               0 :     nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull, &status);
    2109               0 :     mInResize = false;
    2110                 :   }
    2111                 : }
    2112                 : 
    2113                 : void
    2114               0 : PresShell::SetIgnoreFrameDestruction(bool aIgnore)
    2115                 : {
    2116               0 :   if (mPresContext) {
    2117                 :     // We need to destroy the image loaders first, as they won't be
    2118                 :     // notified when frames are destroyed once this setting takes effect.
    2119                 :     // (See bug 673984)
    2120               0 :     mPresContext->DestroyImageLoaders();
    2121                 :   }
    2122               0 :   mIgnoreFrameDestruction = aIgnore;
    2123               0 : }
    2124                 : 
    2125                 : void
    2126               0 : PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
    2127                 : {
    2128                 :   NS_TIME_FUNCTION_MIN(1.0);
    2129                 : 
    2130               0 :   mPresContext->ForgetUpdatePluginGeometryFrame(aFrame);
    2131                 : 
    2132               0 :   if (!mIgnoreFrameDestruction) {
    2133               0 :     mPresContext->StopImagesFor(aFrame);
    2134                 : 
    2135               0 :     mFrameConstructor->NotifyDestroyingFrame(aFrame);
    2136                 : 
    2137               0 :     for (PRInt32 idx = mDirtyRoots.Length(); idx; ) {
    2138               0 :       --idx;
    2139               0 :       if (mDirtyRoots[idx] == aFrame) {
    2140               0 :         mDirtyRoots.RemoveElementAt(idx);
    2141                 :       }
    2142                 :     }
    2143                 : 
    2144                 :     // Remove frame properties
    2145               0 :     mPresContext->NotifyDestroyingFrame(aFrame);
    2146                 : 
    2147               0 :     if (aFrame == mCurrentEventFrame) {
    2148               0 :       mCurrentEventContent = aFrame->GetContent();
    2149               0 :       mCurrentEventFrame = nsnull;
    2150                 :     }
    2151                 : 
    2152                 :   #ifdef NS_DEBUG
    2153               0 :     if (aFrame == mDrawEventTargetFrame) {
    2154               0 :       mDrawEventTargetFrame = nsnull;
    2155                 :     }
    2156                 :   #endif
    2157                 : 
    2158               0 :     for (unsigned int i=0; i < mCurrentEventFrameStack.Length(); i++) {
    2159               0 :       if (aFrame == mCurrentEventFrameStack.ElementAt(i)) {
    2160                 :         //One of our stack frames was deleted.  Get its content so that when we
    2161                 :         //pop it we can still get its new frame from its content
    2162               0 :         nsIContent *currentEventContent = aFrame->GetContent();
    2163               0 :         mCurrentEventContentStack.ReplaceObjectAt(currentEventContent, i);
    2164               0 :         mCurrentEventFrameStack[i] = nsnull;
    2165                 :       }
    2166                 :     }
    2167                 :   
    2168               0 :     mFramesToDirty.RemoveEntry(aFrame);
    2169                 :   }
    2170               0 : }
    2171                 : 
    2172               0 : already_AddRefed<nsCaret> PresShell::GetCaret() const
    2173                 : {
    2174               0 :   nsCaret* caret = mCaret;
    2175               0 :   NS_IF_ADDREF(caret);
    2176               0 :   return caret;
    2177                 : }
    2178                 : 
    2179               0 : void PresShell::MaybeInvalidateCaretPosition()
    2180                 : {
    2181               0 :   if (mCaret) {
    2182               0 :     mCaret->InvalidateOutsideCaret();
    2183                 :   }
    2184               0 : }
    2185                 : 
    2186               0 : void PresShell::SetCaret(nsCaret *aNewCaret)
    2187                 : {
    2188               0 :   mCaret = aNewCaret;
    2189               0 : }
    2190                 : 
    2191               0 : void PresShell::RestoreCaret()
    2192                 : {
    2193               0 :   mCaret = mOriginalCaret;
    2194               0 : }
    2195                 : 
    2196               0 : NS_IMETHODIMP PresShell::SetCaretEnabled(bool aInEnable)
    2197                 : {
    2198               0 :   bool oldEnabled = mCaretEnabled;
    2199                 : 
    2200               0 :   mCaretEnabled = aInEnable;
    2201                 : 
    2202               0 :   if (mCaret && (mCaretEnabled != oldEnabled))
    2203                 :   {
    2204                 : /*  Don't change the caret's selection here! This was an evil side-effect of SetCaretEnabled()
    2205                 :     nsCOMPtr<nsIDOMSelection> domSel;
    2206                 :     if (NS_SUCCEEDED(GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel))) && domSel)
    2207                 :       mCaret->SetCaretDOMSelection(domSel);
    2208                 : */
    2209               0 :     mCaret->SetCaretVisible(mCaretEnabled);
    2210                 :   }
    2211                 : 
    2212               0 :   return NS_OK;
    2213                 : }
    2214                 : 
    2215               0 : NS_IMETHODIMP PresShell::SetCaretReadOnly(bool aReadOnly)
    2216                 : {
    2217               0 :   if (mCaret)
    2218               0 :     mCaret->SetCaretReadOnly(aReadOnly);
    2219               0 :   return NS_OK;
    2220                 : }
    2221                 : 
    2222               0 : NS_IMETHODIMP PresShell::GetCaretEnabled(bool *aOutEnabled)
    2223                 : {
    2224               0 :   NS_ENSURE_ARG_POINTER(aOutEnabled);
    2225               0 :   *aOutEnabled = mCaretEnabled;
    2226               0 :   return NS_OK;
    2227                 : }
    2228                 : 
    2229               0 : NS_IMETHODIMP PresShell::SetCaretVisibilityDuringSelection(bool aVisibility)
    2230                 : {
    2231               0 :   if (mCaret)
    2232               0 :     mCaret->SetVisibilityDuringSelection(aVisibility);
    2233               0 :   return NS_OK;
    2234                 : }
    2235                 : 
    2236               0 : NS_IMETHODIMP PresShell::GetCaretVisible(bool *aOutIsVisible)
    2237                 : {
    2238               0 :   *aOutIsVisible = false;
    2239               0 :   if (mCaret) {
    2240               0 :     nsresult rv = mCaret->GetCaretVisible(aOutIsVisible);
    2241               0 :     NS_ENSURE_SUCCESS(rv,rv);
    2242                 :   }
    2243               0 :   return NS_OK;
    2244                 : }
    2245                 : 
    2246               0 : NS_IMETHODIMP PresShell::SetSelectionFlags(PRInt16 aInEnable)
    2247                 : {
    2248               0 :   mSelectionFlags = aInEnable;
    2249               0 :   return NS_OK;
    2250                 : }
    2251                 : 
    2252               0 : NS_IMETHODIMP PresShell::GetSelectionFlags(PRInt16 *aOutEnable)
    2253                 : {
    2254               0 :   if (!aOutEnable)
    2255               0 :     return NS_ERROR_INVALID_ARG;
    2256               0 :   *aOutEnable = mSelectionFlags;
    2257               0 :   return NS_OK;
    2258                 : }
    2259                 : 
    2260                 : //implementation of nsISelectionController
    2261                 : 
    2262                 : NS_IMETHODIMP 
    2263               0 : PresShell::CharacterMove(bool aForward, bool aExtend)
    2264                 : {
    2265               0 :   return mSelection->CharacterMove(aForward, aExtend);  
    2266                 : }
    2267                 : 
    2268                 : NS_IMETHODIMP
    2269               0 : PresShell::CharacterExtendForDelete()
    2270                 : {
    2271               0 :   return mSelection->CharacterExtendForDelete();
    2272                 : }
    2273                 : 
    2274                 : NS_IMETHODIMP
    2275               0 : PresShell::CharacterExtendForBackspace()
    2276                 : {
    2277               0 :   return mSelection->CharacterExtendForBackspace();
    2278                 : }
    2279                 : 
    2280                 : NS_IMETHODIMP 
    2281               0 : PresShell::WordMove(bool aForward, bool aExtend)
    2282                 : {
    2283               0 :   nsresult result = mSelection->WordMove(aForward, aExtend);
    2284                 : // if we can't go down/up any more we must then move caret completely to
    2285                 : // end/beginning respectively.
    2286               0 :   if (NS_FAILED(result))
    2287               0 :     result = CompleteMove(aForward, aExtend);
    2288               0 :   return result;
    2289                 : }
    2290                 : 
    2291                 : NS_IMETHODIMP 
    2292               0 : PresShell::WordExtendForDelete(bool aForward)
    2293                 : {
    2294               0 :   return mSelection->WordExtendForDelete(aForward);  
    2295                 : }
    2296                 : 
    2297                 : NS_IMETHODIMP 
    2298               0 : PresShell::LineMove(bool aForward, bool aExtend)
    2299                 : {
    2300               0 :   nsresult result = mSelection->LineMove(aForward, aExtend);  
    2301                 : // if we can't go down/up any more we must then move caret completely to 
    2302                 : // end/beginning respectively.
    2303               0 :   if (NS_FAILED(result)) 
    2304               0 :     result = CompleteMove(aForward,aExtend);
    2305               0 :   return result;
    2306                 : }
    2307                 : 
    2308                 : NS_IMETHODIMP 
    2309               0 : PresShell::IntraLineMove(bool aForward, bool aExtend)
    2310                 : {
    2311               0 :   return mSelection->IntraLineMove(aForward, aExtend);  
    2312                 : }
    2313                 : 
    2314                 : 
    2315                 : 
    2316                 : NS_IMETHODIMP 
    2317               0 : PresShell::PageMove(bool aForward, bool aExtend)
    2318                 : {
    2319                 :   nsIScrollableFrame *scrollableFrame =
    2320               0 :     GetFrameToScrollAsScrollable(nsIPresShell::eVertical);
    2321               0 :   if (!scrollableFrame)
    2322               0 :     return NS_OK;
    2323                 : 
    2324               0 :   mSelection->CommonPageMove(aForward, aExtend, scrollableFrame);
    2325                 :   // After ScrollSelectionIntoView(), the pending notifications might be
    2326                 :   // flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
    2327                 :   return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
    2328                 :                                  nsISelectionController::SELECTION_FOCUS_REGION,
    2329               0 :                                  nsISelectionController::SCROLL_SYNCHRONOUS);
    2330                 : }
    2331                 : 
    2332                 : 
    2333                 : 
    2334                 : NS_IMETHODIMP 
    2335               0 : PresShell::ScrollPage(bool aForward)
    2336                 : {
    2337                 :   nsIScrollableFrame* scrollFrame =
    2338               0 :     GetFrameToScrollAsScrollable(nsIPresShell::eVertical);
    2339               0 :   if (scrollFrame) {
    2340                 :     scrollFrame->ScrollBy(nsIntPoint(0, aForward ? 1 : -1),
    2341                 :                           nsIScrollableFrame::PAGES,
    2342               0 :                           nsIScrollableFrame::SMOOTH);
    2343                 :   }
    2344               0 :   return NS_OK;
    2345                 : }
    2346                 : 
    2347                 : NS_IMETHODIMP
    2348               0 : PresShell::ScrollLine(bool aForward)
    2349                 : {
    2350                 :   nsIScrollableFrame* scrollFrame =
    2351               0 :     GetFrameToScrollAsScrollable(nsIPresShell::eVertical);
    2352               0 :   if (scrollFrame) {
    2353                 :     PRInt32 lineCount = Preferences::GetInt("toolkit.scrollbox.verticalScrollDistance",
    2354               0 :                                             NS_DEFAULT_VERTICAL_SCROLL_DISTANCE);
    2355                 :     scrollFrame->ScrollBy(nsIntPoint(0, aForward ? lineCount : -lineCount),
    2356                 :                           nsIScrollableFrame::LINES,
    2357               0 :                           nsIScrollableFrame::SMOOTH);
    2358                 :   }
    2359               0 :   return NS_OK;
    2360                 : }
    2361                 : 
    2362                 : NS_IMETHODIMP
    2363               0 : PresShell::ScrollCharacter(bool aRight)
    2364                 : {
    2365                 :   nsIScrollableFrame* scrollFrame =
    2366               0 :     GetFrameToScrollAsScrollable(nsIPresShell::eHorizontal);
    2367               0 :   if (scrollFrame) {
    2368                 :     scrollFrame->ScrollBy(nsIntPoint(aRight ? 1 : -1, 0),
    2369                 :                           nsIScrollableFrame::LINES,
    2370               0 :                           nsIScrollableFrame::SMOOTH);
    2371                 :   }
    2372               0 :   return NS_OK;
    2373                 : }
    2374                 : 
    2375                 : NS_IMETHODIMP
    2376               0 : PresShell::CompleteScroll(bool aForward)
    2377                 : {
    2378                 :   nsIScrollableFrame* scrollFrame =
    2379               0 :     GetFrameToScrollAsScrollable(nsIPresShell::eVertical);
    2380               0 :   if (scrollFrame) {
    2381                 :     scrollFrame->ScrollBy(nsIntPoint(0, aForward ? 1 : -1),
    2382                 :                           nsIScrollableFrame::WHOLE,
    2383               0 :                           nsIScrollableFrame::INSTANT);
    2384                 :   }
    2385               0 :   return NS_OK;
    2386                 : }
    2387                 : 
    2388                 : NS_IMETHODIMP
    2389               0 : PresShell::CompleteMove(bool aForward, bool aExtend)
    2390                 : {
    2391                 :   // Beware! This may flush notifications via synchronous
    2392                 :   // ScrollSelectionIntoView.
    2393               0 :   nsIContent* limiter = mSelection->GetAncestorLimiter();
    2394                 :   nsIFrame* frame = limiter ? limiter->GetPrimaryFrame()
    2395               0 :                             : FrameConstructor()->GetRootElementFrame();
    2396               0 :   if (!frame)
    2397               0 :     return NS_ERROR_FAILURE;
    2398               0 :   nsPeekOffsetStruct pos = frame->GetExtremeCaretPosition(!aForward);
    2399                 :   mSelection->HandleClick(pos.mResultContent, pos.mContentOffset,
    2400               0 :                           pos.mContentOffset, aExtend, false, aForward);
    2401               0 :   if (limiter) {
    2402                 :     // HandleClick resets ancestorLimiter, so set it again.
    2403               0 :     mSelection->SetAncestorLimiter(limiter);
    2404                 :   }
    2405                 :     
    2406                 :   // After ScrollSelectionIntoView(), the pending notifications might be
    2407                 :   // flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
    2408                 :   return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, 
    2409                 :                                  nsISelectionController::SELECTION_FOCUS_REGION,
    2410               0 :                                  nsISelectionController::SCROLL_SYNCHRONOUS);
    2411                 : }
    2412                 : 
    2413                 : NS_IMETHODIMP 
    2414               0 : PresShell::SelectAll()
    2415                 : {
    2416               0 :   return mSelection->SelectAll();
    2417                 : }
    2418                 : 
    2419                 : static void
    2420               0 : DoCheckVisibility(nsPresContext* aPresContext,
    2421                 :                   nsIContent* aNode,
    2422                 :                   PRInt16 aStartOffset,
    2423                 :                   PRInt16 aEndOffset,
    2424                 :                   bool* aRetval)
    2425                 : {
    2426               0 :   nsIFrame* frame = aNode->GetPrimaryFrame();
    2427               0 :   if (!frame) {
    2428                 :     // No frame to look at so it must not be visible.
    2429               0 :     return;
    2430                 :   }
    2431                 : 
    2432                 :   // Start process now to go through all frames to find startOffset. Then check
    2433                 :   // chars after that to see if anything until EndOffset is visible.
    2434               0 :   bool finished = false;
    2435                 :   frame->CheckVisibility(aPresContext, aStartOffset, aEndOffset, true,
    2436               0 :                          &finished, aRetval);
    2437                 :   // Don't worry about other return value.
    2438                 : }
    2439                 : 
    2440                 : NS_IMETHODIMP
    2441               0 : PresShell::CheckVisibility(nsIDOMNode *node, PRInt16 startOffset, PRInt16 EndOffset, bool *_retval)
    2442                 : {
    2443               0 :   if (!node || startOffset>EndOffset || !_retval || startOffset<0 || EndOffset<0)
    2444               0 :     return NS_ERROR_INVALID_ARG;
    2445               0 :   *_retval = false; //initialize return parameter
    2446               0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(node));
    2447               0 :   if (!content)
    2448               0 :     return NS_ERROR_FAILURE;
    2449                 : 
    2450               0 :   DoCheckVisibility(mPresContext, content, startOffset, EndOffset, _retval);
    2451               0 :   return NS_OK;
    2452                 : }
    2453                 : 
    2454                 : nsresult
    2455               0 : PresShell::CheckVisibilityContent(nsIContent* aNode, PRInt16 aStartOffset,
    2456                 :                                   PRInt16 aEndOffset, bool* aRetval)
    2457                 : {
    2458               0 :   if (!aNode || aStartOffset > aEndOffset || !aRetval ||
    2459                 :       aStartOffset < 0 || aEndOffset < 0) {
    2460               0 :     return NS_ERROR_INVALID_ARG;
    2461                 :   }
    2462                 : 
    2463               0 :   *aRetval = false;
    2464               0 :   DoCheckVisibility(mPresContext, aNode, aStartOffset, aEndOffset, aRetval);
    2465               0 :   return NS_OK;
    2466                 : }
    2467                 : 
    2468                 : //end implementations nsISelectionController
    2469                 : 
    2470                 : 
    2471                 : void
    2472               0 : PresShell::StyleChangeReflow()
    2473                 : {
    2474               0 :   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
    2475                 :   // At the moment at least, we don't have a root frame before the initial
    2476                 :   // reflow; it's safe to just ignore the request in that case
    2477               0 :   if (!rootFrame)
    2478               0 :     return;
    2479                 : 
    2480               0 :   FrameNeedsReflow(rootFrame, eStyleChange, NS_FRAME_IS_DIRTY);
    2481                 : }
    2482                 : 
    2483                 : nsIFrame*
    2484               0 : nsIPresShell::GetRootFrameExternal() const
    2485                 : {
    2486               0 :   return mFrameConstructor->GetRootFrame();
    2487                 : }
    2488                 : 
    2489                 : nsIFrame*
    2490               0 : nsIPresShell::GetRootScrollFrame() const
    2491                 : {
    2492               0 :   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
    2493                 :   // Ensure root frame is a viewport frame
    2494               0 :   if (!rootFrame || nsGkAtoms::viewportFrame != rootFrame->GetType())
    2495               0 :     return nsnull;
    2496               0 :   nsIFrame* theFrame = rootFrame->GetFirstPrincipalChild();
    2497               0 :   if (!theFrame || nsGkAtoms::scrollFrame != theFrame->GetType())
    2498               0 :     return nsnull;
    2499               0 :   return theFrame;
    2500                 : }
    2501                 : 
    2502                 : nsIScrollableFrame*
    2503               0 : nsIPresShell::GetRootScrollFrameAsScrollable() const
    2504                 : {
    2505               0 :   nsIFrame* frame = GetRootScrollFrame();
    2506               0 :   if (!frame)
    2507               0 :     return nsnull;
    2508               0 :   nsIScrollableFrame* scrollableFrame = do_QueryFrame(frame);
    2509               0 :   NS_ASSERTION(scrollableFrame,
    2510                 :                "All scroll frames must implement nsIScrollableFrame");
    2511               0 :   return scrollableFrame;
    2512                 : }
    2513                 : 
    2514                 : nsIScrollableFrame*
    2515               0 : nsIPresShell::GetRootScrollFrameAsScrollableExternal() const
    2516                 : {
    2517               0 :   return GetRootScrollFrameAsScrollable();
    2518                 : }
    2519                 : 
    2520                 : nsIPageSequenceFrame*
    2521               0 : PresShell::GetPageSequenceFrame() const
    2522                 : {
    2523               0 :   nsIFrame* frame = mFrameConstructor->GetPageSequenceFrame();
    2524               0 :   return do_QueryFrame(frame);
    2525                 : }
    2526                 : 
    2527                 : nsIFrame*
    2528               0 : PresShell::GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt)
    2529                 : {
    2530               0 :   return nsLayoutUtils::GetFrameForPoint(aFrame, aPt);
    2531                 : }
    2532                 : 
    2533                 : void
    2534               0 : PresShell::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
    2535                 : {
    2536                 : #ifdef DEBUG
    2537               0 :   mUpdateCount++;
    2538                 : #endif
    2539               0 :   mFrameConstructor->BeginUpdate();
    2540                 : 
    2541               0 :   if (aUpdateType & UPDATE_STYLE)
    2542               0 :     mStyleSet->BeginUpdate();
    2543               0 : }
    2544                 : 
    2545                 : void
    2546               0 : PresShell::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
    2547                 : {
    2548                 : #ifdef DEBUG
    2549               0 :   NS_PRECONDITION(0 != mUpdateCount, "too many EndUpdate's");
    2550               0 :   --mUpdateCount;
    2551                 : #endif
    2552                 : 
    2553               0 :   if (aUpdateType & UPDATE_STYLE) {
    2554               0 :     mStyleSet->EndUpdate();
    2555               0 :     if (mStylesHaveChanged)
    2556               0 :       ReconstructStyleData();
    2557                 :   }
    2558                 : 
    2559               0 :   mFrameConstructor->EndUpdate();
    2560               0 : }
    2561                 : 
    2562                 : void
    2563               0 : PresShell::RestoreRootScrollPosition()
    2564                 : {
    2565                 :   // Restore frame state for the root scroll frame
    2566                 :   nsCOMPtr<nsILayoutHistoryState> historyState =
    2567               0 :     mDocument->GetLayoutHistoryState();
    2568                 :   // Make sure we don't reenter reflow via the sync paint that happens while
    2569                 :   // we're scrolling to our restored position.  Entering reflow for the
    2570                 :   // scrollable frame will cause it to reenter ScrollToRestoredPosition(), and
    2571                 :   // it'll get all confused.
    2572               0 :   nsAutoScriptBlocker scriptBlocker;
    2573               0 :   ++mChangeNestCount;
    2574                 : 
    2575               0 :   if (historyState) {
    2576               0 :     nsIFrame* scrollFrame = GetRootScrollFrame();
    2577               0 :     if (scrollFrame) {
    2578               0 :       nsIScrollableFrame* scrollableFrame = do_QueryFrame(scrollFrame);
    2579               0 :       if (scrollableFrame) {
    2580                 :         mFrameConstructor->RestoreFrameStateFor(scrollFrame, historyState,
    2581               0 :                                                 nsIStatefulFrame::eDocumentScrollState);
    2582               0 :         scrollableFrame->ScrollToRestoredPosition();
    2583                 :       }
    2584                 :     }
    2585                 :   }
    2586                 : 
    2587               0 :   --mChangeNestCount;
    2588               0 : }
    2589                 : 
    2590                 : void
    2591               0 : PresShell::BeginLoad(nsIDocument *aDocument)
    2592                 : {  
    2593               0 :   mDocumentLoading = true;
    2594               0 : }
    2595                 : 
    2596                 : void
    2597               0 : PresShell::EndLoad(nsIDocument *aDocument)
    2598                 : {
    2599               0 :   NS_PRECONDITION(aDocument == mDocument, "Wrong document");
    2600                 :   
    2601               0 :   RestoreRootScrollPosition();
    2602                 :   
    2603               0 :   mDocumentLoading = false;
    2604               0 : }
    2605                 : 
    2606                 : #ifdef DEBUG
    2607                 : void
    2608               0 : PresShell::VerifyHasDirtyRootAncestor(nsIFrame* aFrame)
    2609                 : {
    2610                 :   // XXXbz due to bug 372769, can't actually assert anything here...
    2611                 :   return;
    2612                 :   
    2613                 :   // XXXbz shouldn't need this part; remove it once FrameNeedsReflow
    2614                 :   // handles the root frame correctly.
    2615                 :   if (!aFrame->GetParent()) {
    2616                 :     return;
    2617                 :   }
    2618                 :         
    2619                 :   // Make sure that there is a reflow root ancestor of |aFrame| that's
    2620                 :   // in mDirtyRoots already.
    2621                 :   while (aFrame && (aFrame->GetStateBits() & NS_FRAME_HAS_DIRTY_CHILDREN)) {
    2622                 :     if (((aFrame->GetStateBits() & NS_FRAME_REFLOW_ROOT) ||
    2623                 :          !aFrame->GetParent()) &&
    2624                 :         mDirtyRoots.Contains(aFrame)) {
    2625                 :       return;
    2626                 :     }
    2627                 : 
    2628                 :     aFrame = aFrame->GetParent();
    2629                 :   }
    2630                 :   NS_NOTREACHED("Frame has dirty bits set but isn't scheduled to be "
    2631                 :                 "reflowed?");
    2632                 : }
    2633                 : #endif
    2634                 : 
    2635                 : void
    2636               0 : PresShell::FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
    2637                 :                             nsFrameState aBitToAdd)
    2638                 : {
    2639                 : #ifdef NS_FUNCTION_TIMER
    2640                 :   NS_TIME_FUNCTION_DECLARE_DOCURL;
    2641                 :   nsCAutoString frameType__("N/A");
    2642                 :   nsIAtom *atomType__ = aFrame ? aFrame->GetType() : nsnull;
    2643                 :   if (atomType__) atomType__->ToUTF8String(frameType__);
    2644                 :   NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (document: %s, frame type: %s)", MOZ_FUNCTION_NAME,
    2645                 :                            __LINE__, docURL__.get(), frameType__.get());
    2646                 : #endif
    2647                 : 
    2648               0 :   NS_PRECONDITION(aBitToAdd == NS_FRAME_IS_DIRTY ||
    2649                 :                   aBitToAdd == NS_FRAME_HAS_DIRTY_CHILDREN,
    2650                 :                   "Unexpected bits being added");
    2651               0 :   NS_PRECONDITION(aIntrinsicDirty != eStyleChange ||
    2652                 :                   aBitToAdd == NS_FRAME_IS_DIRTY,
    2653                 :                   "bits don't correspond to style change reason");
    2654                 : 
    2655               0 :   NS_ASSERTION(!mIsReflowing, "can't mark frame dirty during reflow");
    2656                 : 
    2657                 :   // If we've not yet done the initial reflow, then don't bother
    2658                 :   // enqueuing a reflow command yet.
    2659               0 :   if (! mDidInitialReflow)
    2660               0 :     return;
    2661                 : 
    2662                 :   // If we're already destroying, don't bother with this either.
    2663               0 :   if (mIsDestroying)
    2664               0 :     return;
    2665                 : 
    2666                 : #ifdef DEBUG
    2667                 :   //printf("gShellCounter: %d\n", gShellCounter++);
    2668               0 :   if (mInVerifyReflow)
    2669               0 :     return;
    2670                 : 
    2671               0 :   if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
    2672               0 :     printf("\nPresShell@%p: frame %p needs reflow\n", (void*)this, (void*)aFrame);
    2673               0 :     if (VERIFY_REFLOW_REALLY_NOISY_RC & gVerifyReflowFlags) {
    2674               0 :       printf("Current content model:\n");
    2675               0 :       Element *rootElement = mDocument->GetRootElement();
    2676               0 :       if (rootElement) {
    2677               0 :         rootElement->List(stdout, 0);
    2678                 :       }
    2679                 :     }
    2680                 :   }  
    2681                 : #endif
    2682                 : 
    2683               0 :   nsAutoTArray<nsIFrame*, 4> subtrees;
    2684               0 :   subtrees.AppendElement(aFrame);
    2685                 : 
    2686               0 :   do {
    2687               0 :     nsIFrame *subtreeRoot = subtrees.ElementAt(subtrees.Length() - 1);
    2688               0 :     subtrees.RemoveElementAt(subtrees.Length() - 1);
    2689                 : 
    2690                 :     // Grab |wasDirty| now so we can go ahead and update the bits on
    2691                 :     // subtreeRoot.
    2692               0 :     bool wasDirty = NS_SUBTREE_DIRTY(subtreeRoot);
    2693               0 :     subtreeRoot->AddStateBits(aBitToAdd);
    2694                 : 
    2695                 :     // Now if subtreeRoot is a reflow root we can cut off this reflow at it if
    2696                 :     // the bit being added is NS_FRAME_HAS_DIRTY_CHILDREN.
    2697               0 :     bool targetFrameDirty = (aBitToAdd == NS_FRAME_IS_DIRTY);
    2698                 : 
    2699                 : #define FRAME_IS_REFLOW_ROOT(_f)                   \
    2700                 :   ((_f->GetStateBits() & NS_FRAME_REFLOW_ROOT) &&  \
    2701                 :    (_f != subtreeRoot || !targetFrameDirty))
    2702                 : 
    2703                 : 
    2704                 :     // Mark the intrinsic widths as dirty on the frame, all of its ancestors,
    2705                 :     // and all of its descendants, if needed:
    2706                 : 
    2707               0 :     if (aIntrinsicDirty != eResize) {
    2708                 :       // Mark argument and all ancestors dirty. (Unless we hit a reflow
    2709                 :       // root that should contain the reflow.  That root could be
    2710                 :       // subtreeRoot itself if it's not dirty, or it could be some
    2711                 :       // ancestor of subtreeRoot.)
    2712               0 :       for (nsIFrame *a = subtreeRoot;
    2713               0 :            a && !FRAME_IS_REFLOW_ROOT(a);
    2714                 :            a = a->GetParent())
    2715               0 :         a->MarkIntrinsicWidthsDirty();
    2716                 :     }
    2717                 : 
    2718               0 :     if (aIntrinsicDirty == eStyleChange) {
    2719                 :       // Mark all descendants dirty (using an nsTArray stack rather than
    2720                 :       // recursion).
    2721               0 :       nsAutoTArray<nsIFrame*, 32> stack;
    2722               0 :       stack.AppendElement(subtreeRoot);
    2723                 : 
    2724               0 :       do {
    2725               0 :         nsIFrame *f = stack.ElementAt(stack.Length() - 1);
    2726               0 :         stack.RemoveElementAt(stack.Length() - 1);
    2727                 : 
    2728               0 :         if (f->GetType() == nsGkAtoms::placeholderFrame) {
    2729               0 :           nsIFrame *oof = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
    2730               0 :           if (!nsLayoutUtils::IsProperAncestorFrame(subtreeRoot, oof)) {
    2731                 :             // We have another distinct subtree we need to mark.
    2732               0 :             subtrees.AppendElement(oof);
    2733                 :           }
    2734                 :         }
    2735                 : 
    2736               0 :         nsIFrame::ChildListIterator lists(f);
    2737               0 :         for (; !lists.IsDone(); lists.Next()) {
    2738               0 :           nsFrameList::Enumerator childFrames(lists.CurrentList());
    2739               0 :           for (; !childFrames.AtEnd(); childFrames.Next()) {
    2740               0 :             nsIFrame* kid = childFrames.get();
    2741               0 :             kid->MarkIntrinsicWidthsDirty();
    2742               0 :             stack.AppendElement(kid);
    2743                 :           }
    2744                 :         }
    2745               0 :       } while (stack.Length() != 0);
    2746                 :     }
    2747                 : 
    2748                 :     // Set NS_FRAME_HAS_DIRTY_CHILDREN bits (via nsIFrame::ChildIsDirty)
    2749                 :     // up the tree until we reach either a frame that's already dirty or
    2750                 :     // a reflow root.
    2751               0 :     nsIFrame *f = subtreeRoot;
    2752               0 :     for (;;) {
    2753               0 :       if (FRAME_IS_REFLOW_ROOT(f) || !f->GetParent()) {
    2754                 :         // we've hit a reflow root or the root frame
    2755               0 :         if (!wasDirty) {
    2756               0 :           mDirtyRoots.AppendElement(f);
    2757               0 :           mDocument->SetNeedLayoutFlush();
    2758                 :         }
    2759                 : #ifdef DEBUG
    2760                 :         else {
    2761               0 :           VerifyHasDirtyRootAncestor(f);
    2762                 :         }
    2763                 : #endif
    2764                 :         
    2765               0 :         break;
    2766                 :       }
    2767                 : 
    2768               0 :       nsIFrame *child = f;
    2769               0 :       f = f->GetParent();
    2770               0 :       wasDirty = NS_SUBTREE_DIRTY(f);
    2771               0 :       f->ChildIsDirty(child);
    2772               0 :       NS_ASSERTION(f->GetStateBits() & NS_FRAME_HAS_DIRTY_CHILDREN,
    2773                 :                    "ChildIsDirty didn't do its job");
    2774               0 :       if (wasDirty) {
    2775                 :         // This frame was already marked dirty.
    2776                 : #ifdef DEBUG
    2777               0 :         VerifyHasDirtyRootAncestor(f);
    2778                 : #endif
    2779               0 :         break;
    2780                 :       }
    2781                 :     }
    2782               0 :   } while (subtrees.Length() != 0);
    2783                 : 
    2784               0 :   MaybeScheduleReflow();
    2785                 : }
    2786                 : 
    2787                 : void
    2788               0 : PresShell::FrameNeedsToContinueReflow(nsIFrame *aFrame)
    2789                 : {
    2790               0 :   NS_ASSERTION(mIsReflowing, "Must be in reflow when marking path dirty.");  
    2791               0 :   NS_PRECONDITION(mCurrentReflowRoot, "Must have a current reflow root here");
    2792               0 :   NS_ASSERTION(aFrame == mCurrentReflowRoot ||
    2793                 :                nsLayoutUtils::IsProperAncestorFrame(mCurrentReflowRoot, aFrame),
    2794                 :                "Frame passed in is not the descendant of mCurrentReflowRoot");
    2795               0 :   NS_ASSERTION(aFrame->GetStateBits() & NS_FRAME_IN_REFLOW,
    2796                 :                "Frame passed in not in reflow?");
    2797                 : 
    2798               0 :   mFramesToDirty.PutEntry(aFrame);
    2799               0 : }
    2800                 : 
    2801                 : nsIScrollableFrame*
    2802               0 : nsIPresShell::GetFrameToScrollAsScrollable(
    2803                 :                 nsIPresShell::ScrollDirection aDirection)
    2804                 : {
    2805               0 :   nsIScrollableFrame* scrollFrame = nsnull;
    2806                 : 
    2807               0 :   nsCOMPtr<nsIContent> focusedContent;
    2808               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    2809               0 :   if (fm && mDocument) {
    2810               0 :     nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(mDocument->GetWindow());
    2811                 : 
    2812               0 :     nsCOMPtr<nsIDOMElement> focusedElement;
    2813               0 :     fm->GetFocusedElementForWindow(window, false, nsnull, getter_AddRefs(focusedElement));
    2814               0 :     focusedContent = do_QueryInterface(focusedElement);
    2815                 :   }
    2816               0 :   if (!focusedContent && mSelection) {
    2817                 :     nsISelection* domSelection = mSelection->
    2818               0 :       GetSelection(nsISelectionController::SELECTION_NORMAL);
    2819               0 :     if (domSelection) {
    2820               0 :       nsCOMPtr<nsIDOMNode> focusedNode;
    2821               0 :       domSelection->GetFocusNode(getter_AddRefs(focusedNode));
    2822               0 :       focusedContent = do_QueryInterface(focusedNode);
    2823                 :     }
    2824                 :   }
    2825               0 :   if (focusedContent) {
    2826               0 :     nsIFrame* startFrame = focusedContent->GetPrimaryFrame();
    2827               0 :     if (startFrame) {
    2828               0 :       scrollFrame = startFrame->GetScrollTargetFrame();
    2829               0 :       if (scrollFrame) {
    2830               0 :         startFrame = scrollFrame->GetScrolledFrame();
    2831                 :       }
    2832               0 :       if (aDirection == nsIPresShell::eEither) {
    2833                 :         scrollFrame =
    2834               0 :           nsLayoutUtils::GetNearestScrollableFrame(startFrame);
    2835                 :       } else {
    2836                 :         scrollFrame =
    2837                 :           nsLayoutUtils::GetNearestScrollableFrameForDirection(startFrame,
    2838                 :             aDirection == eVertical ? nsLayoutUtils::eVertical :
    2839               0 :                                       nsLayoutUtils::eHorizontal);
    2840                 :       }
    2841                 :     }
    2842                 :   }
    2843               0 :   if (!scrollFrame) {
    2844               0 :     scrollFrame = GetRootScrollFrameAsScrollable();
    2845                 :   }
    2846               0 :   return scrollFrame;
    2847                 : }
    2848                 : 
    2849                 : void
    2850               0 : PresShell::CancelAllPendingReflows()
    2851                 : {
    2852               0 :   mDirtyRoots.Clear();
    2853                 : 
    2854               0 :   if (mReflowScheduled) {
    2855               0 :     GetPresContext()->RefreshDriver()->RemoveLayoutFlushObserver(this);
    2856               0 :     mReflowScheduled = false;
    2857                 :   }
    2858                 : 
    2859               0 :   ASSERT_REFLOW_SCHEDULED_STATE();
    2860               0 : }
    2861                 : 
    2862                 : nsresult
    2863               0 : PresShell::RecreateFramesFor(nsIContent* aContent)
    2864                 : {
    2865                 :   NS_TIME_FUNCTION_MIN(1.0);
    2866                 : 
    2867               0 :   NS_ENSURE_TRUE(mPresContext, NS_ERROR_FAILURE);
    2868               0 :   if (!mDidInitialReflow) {
    2869                 :     // Nothing to do here.  In fact, if we proceed and aContent is the
    2870                 :     // root we will crash.
    2871               0 :     return NS_OK;
    2872                 :   }
    2873                 : 
    2874                 :   // Don't call RecreateFramesForContent since that is not exported and we want
    2875                 :   // to keep the number of entrypoints down.
    2876                 : 
    2877               0 :   NS_ASSERTION(mViewManager, "Should have view manager");
    2878                 : 
    2879                 :   // Have to make sure that the content notifications are flushed before we
    2880                 :   // start messing with the frame model; otherwise we can get content doubling.
    2881               0 :   mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
    2882                 : 
    2883               0 :   nsAutoScriptBlocker scriptBlocker;
    2884                 : 
    2885               0 :   nsStyleChangeList changeList;
    2886               0 :   changeList.AppendChange(nsnull, aContent, nsChangeHint_ReconstructFrame);
    2887                 : 
    2888                 :   // Mark ourselves as not safe to flush while we're doing frame construction.
    2889               0 :   ++mChangeNestCount;
    2890               0 :   nsresult rv = mFrameConstructor->ProcessRestyledFrames(changeList);
    2891               0 :   --mChangeNestCount;
    2892                 :   
    2893               0 :   return rv;
    2894                 : }
    2895                 : 
    2896                 : void
    2897               0 : nsIPresShell::PostRecreateFramesFor(Element* aElement)
    2898                 : {
    2899                 :   FrameConstructor()->PostRestyleEvent(aElement, nsRestyleHint(0),
    2900               0 :                                        nsChangeHint_ReconstructFrame);
    2901               0 : }
    2902                 : 
    2903                 : void
    2904               0 : nsIPresShell::RestyleForAnimation(Element* aElement, nsRestyleHint aHint)
    2905                 : {
    2906                 :   FrameConstructor()->PostAnimationRestyleEvent(aElement, aHint,
    2907               0 :                                                 NS_STYLE_HINT_NONE);
    2908               0 : }
    2909                 : 
    2910                 : void
    2911               0 : PresShell::ClearFrameRefs(nsIFrame* aFrame)
    2912                 : {
    2913               0 :   mPresContext->EventStateManager()->ClearFrameRefs(aFrame);
    2914                 : 
    2915               0 :   nsWeakFrame* weakFrame = mWeakFrames;
    2916               0 :   while (weakFrame) {
    2917               0 :     nsWeakFrame* prev = weakFrame->GetPreviousWeakFrame();
    2918               0 :     if (weakFrame->GetFrame() == aFrame) {
    2919                 :       // This removes weakFrame from mWeakFrames.
    2920               0 :       weakFrame->Clear(this);
    2921                 :     }
    2922               0 :     weakFrame = prev;
    2923                 :   }
    2924               0 : }
    2925                 : 
    2926                 : already_AddRefed<nsRenderingContext>
    2927               0 : PresShell::GetReferenceRenderingContext()
    2928                 : {
    2929                 :   NS_TIME_FUNCTION_MIN(1.0);
    2930                 : 
    2931               0 :   nsDeviceContext* devCtx = mPresContext->DeviceContext();
    2932               0 :   nsRefPtr<nsRenderingContext> rc;
    2933               0 :   if (mPresContext->IsScreen()) {
    2934               0 :     rc = new nsRenderingContext();
    2935               0 :     rc->Init(devCtx, gfxPlatform::GetPlatform()->ScreenReferenceSurface());
    2936                 :   } else {
    2937               0 :     devCtx->CreateRenderingContext(*getter_AddRefs(rc));
    2938                 :   }
    2939               0 :   return rc.forget();
    2940                 : }
    2941                 : 
    2942                 : nsresult
    2943               0 : PresShell::GoToAnchor(const nsAString& aAnchorName, bool aScroll)
    2944                 : {
    2945               0 :   if (!mDocument) {
    2946               0 :     return NS_ERROR_FAILURE;
    2947                 :   }
    2948                 :   
    2949                 :   // Hold a reference to the ESM in case event dispatch tears us down.
    2950               0 :   nsRefPtr<nsEventStateManager> esm = mPresContext->EventStateManager();
    2951                 : 
    2952               0 :   if (aAnchorName.IsEmpty()) {
    2953               0 :     NS_ASSERTION(!aScroll, "can't scroll to empty anchor name");
    2954               0 :     esm->SetContentState(nsnull, NS_EVENT_STATE_URLTARGET);
    2955               0 :     return NS_OK;
    2956                 :   }
    2957                 : 
    2958               0 :   nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
    2959               0 :   nsresult rv = NS_OK;
    2960               0 :   nsCOMPtr<nsIContent> content;
    2961                 : 
    2962                 :   // Search for an element with a matching "id" attribute
    2963               0 :   if (mDocument) {    
    2964               0 :     content = mDocument->GetElementById(aAnchorName);
    2965                 :   }
    2966                 : 
    2967                 :   // Search for an anchor element with a matching "name" attribute
    2968               0 :   if (!content && htmlDoc) {
    2969               0 :     nsCOMPtr<nsIDOMNodeList> list;
    2970                 :     // Find a matching list of named nodes
    2971               0 :     rv = htmlDoc->GetElementsByName(aAnchorName, getter_AddRefs(list));
    2972               0 :     if (NS_SUCCEEDED(rv) && list) {
    2973                 :       PRUint32 i;
    2974                 :       // Loop through the named nodes looking for the first anchor
    2975               0 :       for (i = 0; true; i++) {
    2976               0 :         nsCOMPtr<nsIDOMNode> node;
    2977               0 :         rv = list->Item(i, getter_AddRefs(node));
    2978               0 :         if (!node) {  // End of list
    2979                 :           break;
    2980                 :         }
    2981                 :         // Ensure it's an anchor element
    2982               0 :         content = do_QueryInterface(node);
    2983               0 :         if (content) {
    2984               0 :           if (content->Tag() == nsGkAtoms::a && content->IsHTML()) {
    2985                 :             break;
    2986                 :           }
    2987               0 :           content = nsnull;
    2988                 :         }
    2989                 :       }
    2990                 :     }
    2991                 :   }
    2992                 : 
    2993                 :   // Search for anchor in the HTML namespace with a matching name
    2994               0 :   if (!content && !htmlDoc)
    2995                 :   {
    2996               0 :     nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(mDocument);
    2997               0 :     nsCOMPtr<nsIDOMNodeList> list;
    2998               0 :     NS_NAMED_LITERAL_STRING(nameSpace, "http://www.w3.org/1999/xhtml");
    2999                 :     // Get the list of anchor elements
    3000               0 :     rv = doc->GetElementsByTagNameNS(nameSpace, NS_LITERAL_STRING("a"), getter_AddRefs(list));
    3001               0 :     if (NS_SUCCEEDED(rv) && list) {
    3002                 :       PRUint32 i;
    3003                 :       // Loop through the named nodes looking for the first anchor
    3004               0 :       for (i = 0; true; i++) {
    3005               0 :         nsCOMPtr<nsIDOMNode> node;
    3006               0 :         rv = list->Item(i, getter_AddRefs(node));
    3007               0 :         if (!node) { // End of list
    3008                 :           break;
    3009                 :         }
    3010                 :         // Compare the name attribute
    3011               0 :         nsCOMPtr<nsIDOMElement> element = do_QueryInterface(node);
    3012               0 :         nsAutoString value;
    3013               0 :         if (element && NS_SUCCEEDED(element->GetAttribute(NS_LITERAL_STRING("name"), value))) {
    3014               0 :           if (value.Equals(aAnchorName)) {
    3015               0 :             content = do_QueryInterface(element);
    3016                 :             break;
    3017                 :           }
    3018                 :         }
    3019                 :       }
    3020                 :     }
    3021                 :   }
    3022                 : 
    3023               0 :   esm->SetContentState(content, NS_EVENT_STATE_URLTARGET);
    3024                 : 
    3025                 : #ifdef ACCESSIBILITY
    3026               0 :   nsIContent *anchorTarget = content;
    3027                 : #endif
    3028                 : 
    3029               0 :   if (content) {
    3030               0 :     if (aScroll) {
    3031                 :       rv = ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_TOP,
    3032                 :                                  NS_PRESSHELL_SCROLL_ANYWHERE,
    3033               0 :                                  ANCHOR_SCROLL_FLAGS);
    3034               0 :       NS_ENSURE_SUCCESS(rv, rv);
    3035                 : 
    3036               0 :       nsIScrollableFrame* rootScroll = GetRootScrollFrameAsScrollable();
    3037               0 :       if (rootScroll) {
    3038               0 :         mLastAnchorScrolledTo = content;
    3039               0 :         mLastAnchorScrollPositionY = rootScroll->GetScrollPosition().y;
    3040                 :       }
    3041                 :     }
    3042                 : 
    3043                 :     // Should we select the target? This action is controlled by a
    3044                 :     // preference: the default is to not select.
    3045               0 :     bool selectAnchor = Preferences::GetBool("layout.selectanchor");
    3046                 : 
    3047                 :     // Even if select anchor pref is false, we must still move the
    3048                 :     // caret there. That way tabbing will start from the new
    3049                 :     // location
    3050               0 :     nsRefPtr<nsIDOMRange> jumpToRange = new nsRange();
    3051               0 :     while (content && content->GetFirstChild()) {
    3052               0 :       content = content->GetFirstChild();
    3053                 :     }
    3054               0 :     nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content));
    3055               0 :     NS_ASSERTION(node, "No nsIDOMNode for descendant of anchor");
    3056               0 :     jumpToRange->SelectNodeContents(node);
    3057                 :     // Select the anchor
    3058                 :     nsISelection* sel = mSelection->
    3059               0 :       GetSelection(nsISelectionController::SELECTION_NORMAL);
    3060               0 :     if (sel) {
    3061               0 :       sel->RemoveAllRanges();
    3062               0 :       sel->AddRange(jumpToRange);
    3063               0 :       if (!selectAnchor) {
    3064                 :         // Use a caret (collapsed selection) at the start of the anchor
    3065               0 :         sel->CollapseToStart();
    3066                 :       }
    3067                 :     }
    3068                 :     // Selection is at anchor.
    3069                 :     // Now focus the document itself if focus is on an element within it.
    3070               0 :     nsPIDOMWindow *win = mDocument->GetWindow();
    3071                 : 
    3072               0 :     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    3073               0 :     if (fm && win) {
    3074               0 :       nsCOMPtr<nsIDOMWindow> focusedWindow;
    3075               0 :       fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
    3076               0 :       if (SameCOMIdentity(win, focusedWindow)) {
    3077               0 :         fm->ClearFocus(focusedWindow);
    3078                 :       }
    3079                 :     }
    3080                 :   } else {
    3081               0 :     rv = NS_ERROR_FAILURE;
    3082               0 :     NS_NAMED_LITERAL_STRING(top, "top");
    3083               0 :     if (nsContentUtils::EqualsIgnoreASCIICase(aAnchorName, top)) {
    3084                 :       // Scroll to the top/left if aAnchorName is "top" and there is no element
    3085                 :       // with such a name or id.
    3086               0 :       rv = NS_OK;
    3087               0 :       nsIScrollableFrame* sf = GetRootScrollFrameAsScrollable();
    3088                 :       // Check |aScroll| after setting |rv| so we set |rv| to the same
    3089                 :       // thing whether or not |aScroll| is true.
    3090               0 :       if (aScroll && sf) {
    3091                 :         // Scroll to the top of the page
    3092               0 :         sf->ScrollTo(nsPoint(0, 0), nsIScrollableFrame::INSTANT);
    3093                 :       }
    3094                 :     }
    3095                 :   }
    3096                 : 
    3097                 : #ifdef ACCESSIBILITY
    3098               0 :   if (anchorTarget) {
    3099               0 :     nsAccessibilityService* accService = AccService();
    3100               0 :     if (accService)
    3101               0 :       accService->NotifyOfAnchorJumpTo(anchorTarget);
    3102                 :   }
    3103                 : #endif
    3104                 : 
    3105               0 :   return rv;
    3106                 : }
    3107                 : 
    3108                 : nsresult
    3109               0 : PresShell::ScrollToAnchor()
    3110                 : {
    3111               0 :   if (!mLastAnchorScrolledTo)
    3112               0 :     return NS_OK;
    3113                 : 
    3114               0 :   NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
    3115                 : 
    3116               0 :   nsIScrollableFrame* rootScroll = GetRootScrollFrameAsScrollable();
    3117               0 :   if (!rootScroll ||
    3118               0 :       mLastAnchorScrollPositionY != rootScroll->GetScrollPosition().y)
    3119               0 :     return NS_OK;
    3120                 : 
    3121                 :   nsresult rv = ScrollContentIntoView(mLastAnchorScrolledTo, NS_PRESSHELL_SCROLL_TOP,
    3122                 :                                       NS_PRESSHELL_SCROLL_ANYWHERE,
    3123               0 :                                       ANCHOR_SCROLL_FLAGS);
    3124               0 :   mLastAnchorScrolledTo = nsnull;
    3125               0 :   return rv;
    3126                 : }
    3127                 : 
    3128                 : /*
    3129                 :  * Helper (per-continuation) for ScrollContentIntoView.
    3130                 :  *
    3131                 :  * @param aContainerFrame [in] the frame which aRect is relative to
    3132                 :  * @param aFrame [in] Frame whose bounds should be unioned
    3133                 :  * @param aUseWholeLineHeightForInlines [in] if true, then for inline frames
    3134                 :  * we should include the top of the line in the added rectangle
    3135                 :  * @param aRect [inout] rect into which its bounds should be unioned
    3136                 :  * @param aHaveRect [inout] whether aRect contains data yet
    3137                 :  * @param aPrevBlock [inout] the block aLines is a line iterator for
    3138                 :  * @param aLines [inout] the line iterator we're using
    3139                 :  * @param aCurLine [inout] the line to start looking from in this iterator
    3140                 :  */
    3141                 : static void
    3142               0 : AccumulateFrameBounds(nsIFrame* aContainerFrame,
    3143                 :                       nsIFrame* aFrame,
    3144                 :                       bool aUseWholeLineHeightForInlines,
    3145                 :                       nsRect& aRect,
    3146                 :                       bool& aHaveRect,
    3147                 :                       nsIFrame*& aPrevBlock,
    3148                 :                       nsAutoLineIterator& aLines,
    3149                 :                       PRInt32& aCurLine)
    3150                 : {
    3151               0 :   nsRect frameBounds = aFrame->GetRect() +
    3152               0 :     aFrame->GetParent()->GetOffsetTo(aContainerFrame);
    3153                 : 
    3154                 :   // If this is an inline frame and either the bounds height is 0 (quirks
    3155                 :   // layout model) or aUseWholeLineHeightForInlines is set, we need to
    3156                 :   // change the top of the bounds to include the whole line.
    3157               0 :   if (frameBounds.height == 0 || aUseWholeLineHeightForInlines) {
    3158               0 :     nsIAtom* frameType = NULL;
    3159               0 :     nsIFrame *prevFrame = aFrame;
    3160               0 :     nsIFrame *f = aFrame;
    3161                 : 
    3162               0 :     while (f &&
    3163               0 :            (frameType = f->GetType()) == nsGkAtoms::inlineFrame) {
    3164               0 :       prevFrame = f;
    3165               0 :       f = prevFrame->GetParent();
    3166                 :     }
    3167                 : 
    3168               0 :     if (f != aFrame &&
    3169                 :         f &&
    3170                 :         frameType == nsGkAtoms::blockFrame) {
    3171                 :       // find the line containing aFrame and increase the top of |offset|.
    3172               0 :       if (f != aPrevBlock) {
    3173               0 :         aLines = f->GetLineIterator();
    3174               0 :         aPrevBlock = f;
    3175               0 :         aCurLine = 0;
    3176                 :       }
    3177               0 :       if (aLines) {
    3178               0 :         PRInt32 index = aLines->FindLineContaining(prevFrame, aCurLine);
    3179               0 :         if (index >= 0) {
    3180               0 :           aCurLine = index;
    3181                 :           nsIFrame *trash1;
    3182                 :           PRInt32 trash2;
    3183               0 :           nsRect lineBounds;
    3184                 :           PRUint32 trash3;
    3185                 : 
    3186               0 :           if (NS_SUCCEEDED(aLines->GetLine(index, &trash1, &trash2,
    3187                 :                                            lineBounds, &trash3))) {
    3188               0 :             lineBounds += f->GetOffsetTo(aContainerFrame);
    3189               0 :             if (lineBounds.y < frameBounds.y) {
    3190               0 :               frameBounds.height = frameBounds.YMost() - lineBounds.y;
    3191               0 :               frameBounds.y = lineBounds.y;
    3192                 :             }
    3193                 :           }
    3194                 :         }
    3195                 :       }
    3196                 :     }
    3197                 :   }
    3198                 : 
    3199               0 :   if (aHaveRect) {
    3200                 :     // We can't use nsRect::UnionRect since it drops empty rects on
    3201                 :     // the floor, and we need to include them.  (Thus we need
    3202                 :     // aHaveRect to know when to drop the initial value on the floor.)
    3203               0 :     aRect.UnionRectEdges(aRect, frameBounds);
    3204                 :   } else {
    3205               0 :     aHaveRect = true;
    3206               0 :     aRect = frameBounds;
    3207                 :   }
    3208               0 : }
    3209                 : 
    3210                 : /**
    3211                 :  * This function takes a scrollable frame, a rect in the coordinate system
    3212                 :  * of the scrolled frame, and a desired percentage-based scroll
    3213                 :  * position and attempts to scroll the rect to that position in the
    3214                 :  * scrollport.
    3215                 :  * 
    3216                 :  * This needs to work even if aRect has a width or height of zero.
    3217                 :  */
    3218               0 : static void ScrollToShowRect(nsIScrollableFrame* aScrollFrame,
    3219                 :                              const nsRect&       aRect,
    3220                 :                              PRIntn              aVPercent,
    3221                 :                              PRIntn              aHPercent,
    3222                 :                              PRUint32            aFlags)
    3223                 : {
    3224               0 :   nsPoint scrollPt = aScrollFrame->GetScrollPosition();
    3225               0 :   nsRect visibleRect(scrollPt, aScrollFrame->GetScrollPortRect().Size());
    3226               0 :   nsSize lineSize = aScrollFrame->GetLineScrollAmount();
    3227               0 :   nsPresContext::ScrollbarStyles ss = aScrollFrame->GetScrollbarStyles();
    3228                 : 
    3229               0 :   if ((aFlags & nsIPresShell::SCROLL_OVERFLOW_HIDDEN) ||
    3230                 :       ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN) {
    3231                 :     // See how the rect should be positioned vertically
    3232               0 :     if (NS_PRESSHELL_SCROLL_ANYWHERE == aVPercent ||
    3233                 :         (NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE == aVPercent &&
    3234                 :          aRect.height < lineSize.height)) {
    3235                 :       // The caller doesn't care where the frame is positioned vertically,
    3236                 :       // so long as it's fully visible
    3237               0 :       if (aRect.y < visibleRect.y) {
    3238                 :         // Scroll up so the frame's top edge is visible
    3239               0 :         scrollPt.y = aRect.y;
    3240               0 :       } else if (aRect.YMost() > visibleRect.YMost()) {
    3241                 :         // Scroll down so the frame's bottom edge is visible. Make sure the
    3242                 :         // frame's top edge is still visible
    3243               0 :         scrollPt.y += aRect.YMost() - visibleRect.YMost();
    3244               0 :         if (scrollPt.y > aRect.y) {
    3245               0 :           scrollPt.y = aRect.y;
    3246                 :         }
    3247                 :       }
    3248               0 :     } else if (NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE == aVPercent) {
    3249                 :       // Scroll only if no part of the frame is visible in this view
    3250               0 :       if (aRect.YMost() - lineSize.height < visibleRect.y) {
    3251                 :         // Scroll up so the frame's top edge is visible
    3252               0 :         scrollPt.y = aRect.y;
    3253               0 :       }  else if (aRect.y + lineSize.height > visibleRect.YMost()) {
    3254                 :         // Scroll down so the frame's bottom edge is visible. Make sure the
    3255                 :         // frame's top edge is still visible
    3256               0 :         scrollPt.y += aRect.YMost() - visibleRect.YMost();
    3257               0 :         if (scrollPt.y > aRect.y) {
    3258               0 :           scrollPt.y = aRect.y;
    3259                 :         }
    3260                 :       }
    3261                 :     } else {
    3262                 :       // Align the frame edge according to the specified percentage
    3263                 :       nscoord frameAlignY =
    3264               0 :         NSToCoordRound(aRect.y + aRect.height * (aVPercent / 100.0f));
    3265                 :       scrollPt.y =
    3266               0 :         NSToCoordRound(frameAlignY - visibleRect.height * (aVPercent / 100.0f));
    3267                 :     }
    3268                 :   }
    3269                 : 
    3270               0 :   if ((aFlags & nsIPresShell::SCROLL_OVERFLOW_HIDDEN) ||
    3271                 :       ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) {
    3272                 :     // See how the frame should be positioned horizontally
    3273               0 :     if (NS_PRESSHELL_SCROLL_ANYWHERE == aHPercent ||
    3274                 :         (NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE == aHPercent &&
    3275                 :          aRect.width < lineSize.width)) {
    3276                 :       // The caller doesn't care where the frame is positioned horizontally,
    3277                 :       // so long as it's fully visible
    3278               0 :       if (aRect.x < visibleRect.x) {
    3279                 :         // Scroll left so the frame's left edge is visible
    3280               0 :         scrollPt.x = aRect.x;
    3281               0 :       } else if (aRect.XMost() > visibleRect.XMost()) {
    3282                 :         // Scroll right so the frame's right edge is visible. Make sure the
    3283                 :         // frame's left edge is still visible
    3284               0 :         scrollPt.x += aRect.XMost() - visibleRect.XMost();
    3285               0 :         if (scrollPt.x > aRect.x) {
    3286               0 :           scrollPt.x = aRect.x;
    3287                 :         }
    3288                 :       }
    3289               0 :     } else if (NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE == aHPercent) {
    3290                 :       // Scroll only if no part of the frame is visible in this view
    3291               0 :       if (aRect.XMost() - lineSize.width < visibleRect.x) {
    3292                 :         // Scroll left so the frame's left edge is visible
    3293               0 :         scrollPt.x = aRect.x;
    3294               0 :       }  else if (aRect.x + lineSize.width > visibleRect.XMost()) {
    3295                 :         // Scroll right so the frame's right edge is visible. Make sure the
    3296                 :         // frame's left edge is still visible
    3297               0 :         scrollPt.x += aRect.XMost() - visibleRect.XMost();
    3298               0 :         if (scrollPt.x > aRect.x) {
    3299               0 :           scrollPt.x = aRect.x;
    3300                 :         }
    3301                 :       }
    3302                 :     } else {
    3303                 :       // Align the frame edge according to the specified percentage
    3304                 :       nscoord frameAlignX =
    3305               0 :         NSToCoordRound(aRect.x + (aRect.width) * (aHPercent / 100.0f));
    3306                 :       scrollPt.x =
    3307               0 :         NSToCoordRound(frameAlignX - visibleRect.width * (aHPercent / 100.0f));
    3308                 :     }
    3309                 :   }
    3310                 : 
    3311               0 :   aScrollFrame->ScrollTo(scrollPt, nsIScrollableFrame::INSTANT);
    3312               0 : }
    3313                 : 
    3314                 : nsresult
    3315               0 : PresShell::ScrollContentIntoView(nsIContent* aContent,
    3316                 :                                  PRIntn      aVPercent,
    3317                 :                                  PRIntn      aHPercent,
    3318                 :                                  PRUint32    aFlags)
    3319                 : {
    3320               0 :   nsCOMPtr<nsIContent> content = aContent; // Keep content alive while flushing.
    3321               0 :   NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER);
    3322               0 :   nsCOMPtr<nsIDocument> currentDoc = content->GetCurrentDoc();
    3323               0 :   NS_ENSURE_STATE(currentDoc);
    3324                 : 
    3325               0 :   NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
    3326                 : 
    3327               0 :   mContentToScrollTo = aContent;
    3328               0 :   mContentScrollVPosition = aVPercent;
    3329               0 :   mContentScrollHPosition = aHPercent;
    3330               0 :   mContentToScrollToFlags = aFlags;
    3331                 : 
    3332                 :   // Flush layout and attempt to scroll in the process.
    3333               0 :   currentDoc->SetNeedLayoutFlush();
    3334               0 :   currentDoc->FlushPendingNotifications(Flush_InterruptibleLayout);
    3335                 : 
    3336                 :   // If mContentToScrollTo is non-null, that means we interrupted the reflow
    3337                 :   // (or suppressed it altogether because we're suppressing interruptible
    3338                 :   // flushes right now) and won't necessarily get the position correct, but do
    3339                 :   // a best-effort scroll here.  The other option would be to do this inside
    3340                 :   // FlushPendingNotifications, but I'm not sure the repeated scrolling that
    3341                 :   // could trigger if reflows keep getting interrupted would be more desirable
    3342                 :   // than a single best-effort scroll followed by one final scroll on the first
    3343                 :   // completed reflow.
    3344               0 :   if (mContentToScrollTo) {
    3345               0 :     DoScrollContentIntoView(content, aVPercent, aHPercent, aFlags);
    3346                 :   }
    3347               0 :   return NS_OK;
    3348                 : }
    3349                 : 
    3350                 : void
    3351               0 : PresShell::DoScrollContentIntoView(nsIContent* aContent,
    3352                 :                                    PRIntn      aVPercent,
    3353                 :                                    PRIntn      aHPercent,
    3354                 :                                    PRUint32    aFlags)
    3355                 : {
    3356               0 :   NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
    3357                 : 
    3358               0 :   nsIFrame* frame = aContent->GetPrimaryFrame();
    3359               0 :   if (!frame) {
    3360               0 :     mContentToScrollTo = nsnull;
    3361               0 :     return;
    3362                 :   }
    3363                 : 
    3364               0 :   if (frame->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
    3365                 :     // The reflow flush before this scroll got interrupted, and this frame's
    3366                 :     // coords and size are all zero, and it has no content showing anyway.
    3367                 :     // Don't bother scrolling to it.  We'll try again when we finish up layout.
    3368               0 :     return;
    3369                 :   }
    3370                 : 
    3371                 :   nsIFrame* container =
    3372               0 :     nsLayoutUtils::GetClosestFrameOfType(frame, nsGkAtoms::scrollFrame);
    3373               0 :   if (!container) {
    3374                 :     // nothing can be scrolled
    3375               0 :     return;
    3376                 :   }
    3377                 : 
    3378                 :   // This is a two-step process.
    3379                 :   // Step 1: Find the bounds of the rect we want to scroll into view.  For
    3380                 :   //         example, for an inline frame we may want to scroll in the whole
    3381                 :   //         line, or we may want to scroll multiple lines into view.
    3382                 :   // Step 2: Walk container frame and its ancestors and scroll them
    3383                 :   //         appropriately.
    3384                 :   // frameBounds is relative to container. We're assuming
    3385                 :   // that scrollframes don't split so every continuation of frame will
    3386                 :   // be a descendant of container. (Things would still mostly work
    3387                 :   // even if that assumption was false.)
    3388               0 :   nsRect frameBounds;
    3389               0 :   bool haveRect = false;
    3390               0 :   bool useWholeLineHeightForInlines = aVPercent != NS_PRESSHELL_SCROLL_ANYWHERE;
    3391                 :   // Reuse the same line iterator across calls to AccumulateFrameBounds.  We set
    3392                 :   // it every time we detect a new block (stored in prevBlock).
    3393               0 :   nsIFrame* prevBlock = nsnull;
    3394               0 :   nsAutoLineIterator lines;
    3395                 :   // The last line we found a continuation on in |lines|.  We assume that later
    3396                 :   // continuations cannot come on earlier lines.
    3397               0 :   PRInt32 curLine = 0;
    3398               0 :   do {
    3399                 :     AccumulateFrameBounds(container, frame, useWholeLineHeightForInlines,
    3400               0 :                           frameBounds, haveRect, prevBlock, lines, curLine);
    3401               0 :   } while ((frame = frame->GetNextContinuation()));
    3402                 : 
    3403                 :   ScrollFrameRectIntoView(container, frameBounds, aVPercent, aHPercent,
    3404               0 :                           aFlags);
    3405                 : }
    3406                 : 
    3407                 : bool
    3408               0 : PresShell::ScrollFrameRectIntoView(nsIFrame*     aFrame,
    3409                 :                                    const nsRect& aRect,
    3410                 :                                    PRIntn        aVPercent,
    3411                 :                                    PRIntn        aHPercent,
    3412                 :                                    PRUint32      aFlags)
    3413                 : {
    3414               0 :   bool didScroll = false;
    3415                 :   // This function needs to work even if rect has a width or height of 0.
    3416               0 :   nsRect rect = aRect;
    3417               0 :   nsIFrame* container = aFrame;
    3418                 :   // Walk up the frame hierarchy scrolling the rect into view and
    3419                 :   // keeping rect relative to container
    3420               0 :   do {
    3421               0 :     nsIScrollableFrame* sf = do_QueryFrame(container);
    3422               0 :     if (sf) {
    3423               0 :       nsPoint oldPosition = sf->GetScrollPosition();
    3424               0 :       ScrollToShowRect(sf, rect - sf->GetScrolledFrame()->GetPosition(),
    3425               0 :                        aVPercent, aHPercent, aFlags);
    3426               0 :       nsPoint newPosition = sf->GetScrollPosition();
    3427                 :       // If the scroll position increased, that means our content moved up,
    3428                 :       // so our rect's offset should decrease
    3429               0 :       rect += oldPosition - newPosition;
    3430                 : 
    3431               0 :       if (oldPosition != newPosition) {
    3432               0 :         didScroll = true;
    3433                 :       }
    3434                 : 
    3435                 :       // only scroll one container when this flag is set
    3436               0 :       if (aFlags & nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY) {
    3437               0 :         break;
    3438                 :       }
    3439                 :     }
    3440               0 :     rect += container->GetPosition();
    3441               0 :     nsIFrame* parent = container->GetParent();
    3442               0 :     if (!parent && !(aFlags & nsIPresShell::SCROLL_NO_PARENT_FRAMES)) {
    3443               0 :       nsPoint extraOffset(0,0);
    3444               0 :       parent = nsLayoutUtils::GetCrossDocParentFrame(container, &extraOffset);
    3445               0 :       if (parent) {
    3446               0 :         PRInt32 APD = container->PresContext()->AppUnitsPerDevPixel();        
    3447               0 :         PRInt32 parentAPD = parent->PresContext()->AppUnitsPerDevPixel();
    3448               0 :         rect = rect.ConvertAppUnitsRoundOut(APD, parentAPD);
    3449               0 :         rect += extraOffset;
    3450                 :       }
    3451                 :     }
    3452               0 :     container = parent;
    3453                 :   } while (container);
    3454                 : 
    3455               0 :   return didScroll;
    3456                 : }
    3457                 : 
    3458                 : nsRectVisibility
    3459               0 : PresShell::GetRectVisibility(nsIFrame* aFrame,
    3460                 :                              const nsRect &aRect,
    3461                 :                              nscoord aMinTwips) const
    3462                 : {
    3463               0 :   NS_ASSERTION(aFrame->PresContext() == GetPresContext(),
    3464                 :                "prescontext mismatch?");
    3465               0 :   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
    3466               0 :   NS_ASSERTION(rootFrame,
    3467                 :                "How can someone have a frame for this presshell when there's no root?");
    3468               0 :   nsIScrollableFrame* sf = GetRootScrollFrameAsScrollable();
    3469               0 :   nsRect scrollPortRect;
    3470               0 :   if (sf) {
    3471               0 :     scrollPortRect = sf->GetScrollPortRect();
    3472               0 :     nsIFrame* f = do_QueryFrame(sf);
    3473               0 :     scrollPortRect += f->GetOffsetTo(rootFrame);
    3474                 :   } else {
    3475               0 :     scrollPortRect = nsRect(nsPoint(0,0), rootFrame->GetSize());
    3476                 :   }
    3477                 : 
    3478               0 :   nsRect r = aRect + aFrame->GetOffsetTo(rootFrame);
    3479                 :   // If aRect is entirely visible then we don't need to ensure that
    3480                 :   // at least aMinTwips of it is visible
    3481               0 :   if (scrollPortRect.Contains(r))
    3482               0 :     return nsRectVisibility_kVisible;
    3483                 : 
    3484               0 :   nsRect insetRect = scrollPortRect;
    3485               0 :   insetRect.Deflate(aMinTwips, aMinTwips);
    3486               0 :   if (r.YMost() <= insetRect.y)
    3487               0 :     return nsRectVisibility_kAboveViewport;
    3488               0 :   if (r.y >= insetRect.YMost())
    3489               0 :     return nsRectVisibility_kBelowViewport;
    3490               0 :   if (r.XMost() <= insetRect.x)
    3491               0 :     return nsRectVisibility_kLeftOfViewport;
    3492               0 :   if (r.x >= insetRect.XMost())
    3493               0 :     return nsRectVisibility_kRightOfViewport;
    3494                 : 
    3495               0 :   return nsRectVisibility_kVisible;
    3496                 : }
    3497                 : 
    3498                 : // GetLinkLocation: copy link location to clipboard
    3499               0 : nsresult PresShell::GetLinkLocation(nsIDOMNode* aNode, nsAString& aLocationString) const
    3500                 : {
    3501                 : #ifdef DEBUG_dr
    3502                 :   printf("dr :: PresShell::GetLinkLocation\n");
    3503                 : #endif
    3504                 : 
    3505               0 :   NS_ENSURE_ARG_POINTER(aNode);
    3506                 : 
    3507               0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
    3508               0 :   if (content) {
    3509               0 :     nsCOMPtr<nsIURI> hrefURI = content->GetHrefURI();
    3510               0 :     if (hrefURI) {
    3511               0 :       nsCAutoString specUTF8;
    3512               0 :       nsresult rv = hrefURI->GetSpec(specUTF8);
    3513               0 :       NS_ENSURE_SUCCESS(rv, rv);
    3514                 : 
    3515               0 :       nsAutoString anchorText;
    3516               0 :       CopyUTF8toUTF16(specUTF8, anchorText);
    3517                 : 
    3518                 :       // Remove all the '\t', '\r' and '\n' from 'anchorText'
    3519                 :       static const char strippedChars[] = "\t\r\n";
    3520               0 :       anchorText.StripChars(strippedChars);
    3521               0 :       aLocationString = anchorText;
    3522               0 :       return NS_OK;
    3523                 :     }
    3524                 :   }
    3525                 : 
    3526                 :   // if no link, fail.
    3527               0 :   return NS_ERROR_FAILURE;
    3528                 : }
    3529                 : 
    3530                 : void
    3531               0 : PresShell::ScheduleViewManagerFlush()
    3532                 : {
    3533               0 :   nsPresContext* presContext = GetPresContext();
    3534               0 :   if (presContext) {
    3535               0 :     presContext->RefreshDriver()->ScheduleViewManagerFlush();
    3536                 :   }
    3537               0 :   if (mDocument) {
    3538               0 :     mDocument->SetNeedLayoutFlush();
    3539                 :   }
    3540               0 : }
    3541                 : 
    3542                 : void
    3543               0 : PresShell::DispatchSynthMouseMove(nsGUIEvent *aEvent,
    3544                 :                                   bool aFlushOnHoverChange)
    3545                 : {
    3546               0 :   PRUint32 hoverGenerationBefore = mFrameConstructor->GetHoverGeneration();
    3547                 :   nsEventStatus status;
    3548               0 :   nsIView* targetView = nsIView::GetViewFor(aEvent->widget);
    3549               0 :   targetView->GetViewManager()->DispatchEvent(aEvent, targetView, &status);
    3550               0 :   if (aFlushOnHoverChange &&
    3551               0 :       hoverGenerationBefore != mFrameConstructor->GetHoverGeneration()) {
    3552                 :     // Flush so that the resulting reflow happens now so that our caller
    3553                 :     // can suppress any synthesized mouse moves caused by that reflow.
    3554               0 :     FlushPendingNotifications(Flush_Layout);
    3555                 :   }
    3556               0 : }
    3557                 : 
    3558                 : void
    3559               0 : PresShell::ClearMouseCaptureOnView(nsIView* aView)
    3560                 : {
    3561               0 :   if (gCaptureInfo.mContent) {
    3562               0 :     if (aView) {
    3563                 :       // if a view was specified, ensure that the captured content is within
    3564                 :       // this view.
    3565               0 :       nsIFrame* frame = gCaptureInfo.mContent->GetPrimaryFrame();
    3566               0 :       if (frame) {
    3567               0 :         nsIView* view = frame->GetClosestView();
    3568                 :         // if there is no view, capturing won't be handled any more, so
    3569                 :         // just release the capture.
    3570               0 :         if (view) {
    3571               0 :           do {
    3572               0 :             if (view == aView) {
    3573               0 :               NS_RELEASE(gCaptureInfo.mContent);
    3574                 :               // the view containing the captured content likely disappeared so
    3575                 :               // disable capture for now.
    3576               0 :               gCaptureInfo.mAllowed = false;
    3577               0 :               break;
    3578                 :             }
    3579                 : 
    3580               0 :             view = view->GetParent();
    3581                 :           } while (view);
    3582                 :           // return if the view wasn't found
    3583               0 :           return;
    3584                 :         }
    3585                 :       }
    3586                 :     }
    3587                 : 
    3588               0 :     NS_RELEASE(gCaptureInfo.mContent);
    3589                 :   }
    3590                 : 
    3591                 :   // disable mouse capture until the next mousedown as a dialog has opened
    3592                 :   // or a drag has started. Otherwise, someone could start capture during
    3593                 :   // the modal dialog or drag.
    3594               0 :   gCaptureInfo.mAllowed = false;
    3595                 : }
    3596                 : 
    3597                 : void
    3598               0 : nsIPresShell::ClearMouseCapture(nsIFrame* aFrame)
    3599                 : {
    3600               0 :   if (!gCaptureInfo.mContent) {
    3601               0 :     gCaptureInfo.mAllowed = false;
    3602               0 :     return;
    3603                 :   }
    3604                 : 
    3605                 :   // null frame argument means clear the capture
    3606               0 :   if (!aFrame) {
    3607               0 :     NS_RELEASE(gCaptureInfo.mContent);
    3608               0 :     gCaptureInfo.mAllowed = false;
    3609               0 :     return;
    3610                 :   }
    3611                 : 
    3612               0 :   nsIFrame* capturingFrame = gCaptureInfo.mContent->GetPrimaryFrame();
    3613               0 :   if (!capturingFrame) {
    3614               0 :     NS_RELEASE(gCaptureInfo.mContent);
    3615               0 :     gCaptureInfo.mAllowed = false;
    3616               0 :     return;
    3617                 :   }
    3618                 : 
    3619               0 :   if (nsLayoutUtils::IsAncestorFrameCrossDoc(aFrame, capturingFrame)) {
    3620               0 :     NS_RELEASE(gCaptureInfo.mContent);
    3621               0 :     gCaptureInfo.mAllowed = false;
    3622                 :   }
    3623                 : }
    3624                 : 
    3625                 : nsresult
    3626               0 : PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, bool aLeavingPage)
    3627                 : {
    3628                 :   NS_TIME_FUNCTION_MIN(1.0);
    3629                 : 
    3630               0 :   nsresult rv = NS_OK;
    3631                 : 
    3632               0 :   NS_PRECONDITION(nsnull != aState, "null state pointer");
    3633                 : 
    3634                 :   // We actually have to mess with the docshell here, since we want to
    3635                 :   // store the state back in it.
    3636                 :   // XXXbz this isn't really right, since this is being called in the
    3637                 :   // content viewer's Hide() method...  by that point the docshell's
    3638                 :   // state could be wrong.  We should sort out a better ownership
    3639                 :   // model for the layout history state.
    3640               0 :   nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
    3641               0 :   if (!container)
    3642               0 :     return NS_ERROR_FAILURE;
    3643                 : 
    3644               0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
    3645               0 :   if (!docShell)
    3646               0 :     return NS_ERROR_FAILURE;
    3647                 : 
    3648               0 :   nsCOMPtr<nsILayoutHistoryState> historyState;
    3649               0 :   docShell->GetLayoutHistoryState(getter_AddRefs(historyState));
    3650               0 :   if (!historyState) {
    3651                 :     // Create the document state object
    3652               0 :     rv = NS_NewLayoutHistoryState(getter_AddRefs(historyState));
    3653                 :   
    3654               0 :     if (NS_FAILED(rv)) { 
    3655               0 :       *aState = nsnull;
    3656               0 :       return rv;
    3657                 :     }    
    3658                 : 
    3659               0 :     docShell->SetLayoutHistoryState(historyState);
    3660                 :   }
    3661                 : 
    3662               0 :   *aState = historyState;
    3663               0 :   NS_IF_ADDREF(*aState);
    3664                 :   
    3665                 :   // Capture frame state for the entire frame hierarchy
    3666               0 :   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
    3667               0 :   if (!rootFrame) return NS_OK;
    3668                 :   // Capture frame state for the root scroll frame
    3669                 :   // Don't capture state when first creating doc element hierarchy
    3670                 :   // As the scroll position is 0 and this will cause us to lose
    3671                 :   // our previously saved place!
    3672               0 :   if (aLeavingPage) {
    3673               0 :     nsIFrame* scrollFrame = GetRootScrollFrame();
    3674               0 :     if (scrollFrame) {
    3675                 :       mFrameConstructor->CaptureFrameStateFor(scrollFrame, historyState,
    3676               0 :                                               nsIStatefulFrame::eDocumentScrollState);
    3677                 :     }
    3678                 :   }
    3679                 : 
    3680               0 :   mFrameConstructor->CaptureFrameState(rootFrame, historyState);  
    3681                 :  
    3682               0 :   return NS_OK;
    3683                 : }
    3684                 : 
    3685                 : void
    3686               0 : PresShell::UnsuppressAndInvalidate()
    3687                 : {
    3688                 :   // Note: We ignore the EnsureVisible check for resource documents, because
    3689                 :   // they won't have a docshell, so they'll always fail EnsureVisible.
    3690               0 :   if ((!mDocument->IsResourceDoc() && !mPresContext->EnsureVisible()) ||
    3691                 :       mHaveShutDown) {
    3692                 :     // No point; we're about to be torn down anyway.
    3693               0 :     return;
    3694                 :   }
    3695                 :   
    3696               0 :   mPaintingSuppressed = false;
    3697               0 :   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
    3698               0 :   if (rootFrame) {
    3699                 :     // let's assume that outline on a root frame is not supported
    3700               0 :     nsRect rect(nsPoint(0, 0), rootFrame->GetSize());
    3701               0 :     rootFrame->Invalidate(rect);
    3702                 : 
    3703               0 :     if (mCaretEnabled && mCaret) {
    3704               0 :       mCaret->CheckCaretDrawingState();
    3705                 :     }
    3706                 : 
    3707               0 :     nsRootPresContext* rootPC = mPresContext->GetRootPresContext();
    3708               0 :     if (rootPC) {
    3709               0 :       rootPC->RequestUpdatePluginGeometry(rootFrame);
    3710                 :     }
    3711                 :   }
    3712                 : 
    3713                 :   // now that painting is unsuppressed, focus may be set on the document
    3714               0 :   nsPIDOMWindow *win = mDocument->GetWindow();
    3715               0 :   if (win)
    3716               0 :     win->SetReadyForFocus();
    3717                 : 
    3718               0 :   if (!mHaveShutDown)
    3719               0 :     SynthesizeMouseMove(false);
    3720                 : }
    3721                 : 
    3722                 : void
    3723               0 : PresShell::UnsuppressPainting()
    3724                 : {
    3725               0 :   if (mPaintSuppressionTimer) {
    3726               0 :     mPaintSuppressionTimer->Cancel();
    3727               0 :     mPaintSuppressionTimer = nsnull;
    3728                 :   }
    3729                 : 
    3730               0 :   if (mIsDocumentGone || !mPaintingSuppressed)
    3731               0 :     return;
    3732                 : 
    3733                 :   // If we have reflows pending, just wait until we process
    3734                 :   // the reflows and get all the frames where we want them
    3735                 :   // before actually unlocking the painting.  Otherwise
    3736                 :   // go ahead and unlock now.
    3737               0 :   if (!mDirtyRoots.IsEmpty())
    3738               0 :     mShouldUnsuppressPainting = true;
    3739                 :   else
    3740               0 :     UnsuppressAndInvalidate();
    3741                 : }
    3742                 : 
    3743                 : // Post a request to handle an arbitrary callback after reflow has finished.
    3744                 : nsresult
    3745               0 : PresShell::PostReflowCallback(nsIReflowCallback* aCallback)
    3746                 : {
    3747               0 :   void* result = AllocateMisc(sizeof(nsCallbackEventRequest));
    3748               0 :   if (NS_UNLIKELY(!result)) {
    3749               0 :     return NS_ERROR_OUT_OF_MEMORY;
    3750                 :   }
    3751               0 :   nsCallbackEventRequest* request = (nsCallbackEventRequest*)result;
    3752                 : 
    3753               0 :   request->callback = aCallback;
    3754               0 :   request->next = nsnull;
    3755                 : 
    3756               0 :   if (mLastCallbackEventRequest) {
    3757               0 :     mLastCallbackEventRequest = mLastCallbackEventRequest->next = request;
    3758                 :   } else {
    3759               0 :     mFirstCallbackEventRequest = request;
    3760               0 :     mLastCallbackEventRequest = request;
    3761                 :   }
    3762                 :  
    3763               0 :   return NS_OK;
    3764                 : }
    3765                 : 
    3766                 : void
    3767               0 : PresShell::CancelReflowCallback(nsIReflowCallback* aCallback)
    3768                 : {
    3769               0 :    nsCallbackEventRequest* before = nsnull;
    3770               0 :    nsCallbackEventRequest* node = mFirstCallbackEventRequest;
    3771               0 :    while(node)
    3772                 :    {
    3773               0 :       nsIReflowCallback* callback = node->callback;
    3774                 : 
    3775               0 :       if (callback == aCallback) 
    3776                 :       {
    3777               0 :         nsCallbackEventRequest* toFree = node;
    3778               0 :         if (node == mFirstCallbackEventRequest) {
    3779               0 :           node = node->next;
    3780               0 :           mFirstCallbackEventRequest = node;
    3781               0 :           NS_ASSERTION(before == nsnull, "impossible");
    3782                 :         } else {
    3783               0 :           node = node->next;
    3784               0 :           before->next = node;
    3785                 :         }
    3786                 : 
    3787               0 :         if (toFree == mLastCallbackEventRequest) {
    3788               0 :           mLastCallbackEventRequest = before;
    3789                 :         }
    3790                 : 
    3791               0 :         FreeMisc(sizeof(nsCallbackEventRequest), toFree);
    3792                 :       } else {
    3793               0 :         before = node;
    3794               0 :         node = node->next;
    3795                 :       }
    3796                 :    }
    3797               0 : }
    3798                 : 
    3799                 : void
    3800               0 : PresShell::CancelPostedReflowCallbacks()
    3801                 : {
    3802               0 :   while (mFirstCallbackEventRequest) {
    3803               0 :     nsCallbackEventRequest* node = mFirstCallbackEventRequest;
    3804               0 :     mFirstCallbackEventRequest = node->next;
    3805               0 :     if (!mFirstCallbackEventRequest) {
    3806               0 :       mLastCallbackEventRequest = nsnull;
    3807                 :     }
    3808               0 :     nsIReflowCallback* callback = node->callback;
    3809               0 :     FreeMisc(sizeof(nsCallbackEventRequest), node);
    3810               0 :     if (callback) {
    3811               0 :       callback->ReflowCallbackCanceled();
    3812                 :     }
    3813                 :   }
    3814               0 : }
    3815                 : 
    3816                 : void
    3817               0 : PresShell::HandlePostedReflowCallbacks(bool aInterruptible)
    3818                 : {
    3819               0 :    bool shouldFlush = false;
    3820                 : 
    3821               0 :    while (mFirstCallbackEventRequest) {
    3822               0 :      nsCallbackEventRequest* node = mFirstCallbackEventRequest;
    3823               0 :      mFirstCallbackEventRequest = node->next;
    3824               0 :      if (!mFirstCallbackEventRequest) {
    3825               0 :        mLastCallbackEventRequest = nsnull;
    3826                 :      }
    3827               0 :      nsIReflowCallback* callback = node->callback;
    3828               0 :      FreeMisc(sizeof(nsCallbackEventRequest), node);
    3829               0 :      if (callback) {
    3830               0 :        if (callback->ReflowFinished()) {
    3831               0 :          shouldFlush = true;
    3832                 :        }
    3833                 :      }
    3834                 :    }
    3835                 : 
    3836                 :    mozFlushType flushType =
    3837               0 :      aInterruptible ? Flush_InterruptibleLayout : Flush_Layout;
    3838               0 :    if (shouldFlush)
    3839               0 :      FlushPendingNotifications(flushType);
    3840               0 : }
    3841                 : 
    3842                 : bool
    3843               0 : PresShell::IsSafeToFlush() const
    3844                 : {
    3845                 :   // Not safe if we are reflowing or in the middle of frame construction
    3846               0 :   bool isSafeToFlush = !mIsReflowing &&
    3847               0 :                          !mChangeNestCount;
    3848                 : 
    3849               0 :   if (isSafeToFlush) {
    3850                 :     // Not safe if we are painting
    3851               0 :     nsIViewManager* viewManager = GetViewManager();
    3852               0 :     if (viewManager) {
    3853               0 :       bool isPainting = false;
    3854               0 :       viewManager->IsPainting(isPainting);
    3855               0 :       if (isPainting) {
    3856               0 :         isSafeToFlush = false;
    3857                 :       }
    3858                 :     }
    3859                 :   }
    3860                 : 
    3861               0 :   return isSafeToFlush;
    3862                 : }
    3863                 : 
    3864                 : 
    3865                 : void
    3866               0 : PresShell::FlushPendingNotifications(mozFlushType aType)
    3867                 : {
    3868                 :   /**
    3869                 :    * VERY IMPORTANT: If you add some sort of new flushing to this
    3870                 :    * method, make sure to add the relevant SetNeedLayoutFlush or
    3871                 :    * SetNeedStyleFlush calls on the document.
    3872                 :    */
    3873                 : 
    3874                 : #ifdef NS_FUNCTION_TIMER
    3875                 :   NS_TIME_FUNCTION_DECLARE_DOCURL;
    3876                 :   static const char *flushTypeNames[] = {
    3877                 :     "Flush_Content",
    3878                 :     "Flush_ContentAndNotify",
    3879                 :     "Flush_Styles",
    3880                 :     "Flush_InterruptibleLayout",
    3881                 :     "Flush_Layout",
    3882                 :     "Flush_Display"
    3883                 :   };
    3884                 :   NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (document: %s, type: %s)", MOZ_FUNCTION_NAME,
    3885                 :                            __LINE__, docURL__.get(), flushTypeNames[aType - 1]);
    3886                 : #endif
    3887               0 :   SAMPLE_LABEL("layout", "FlushPendingNotifications");
    3888                 : 
    3889                 : #ifdef ACCESSIBILITY
    3890                 : #ifdef DEBUG
    3891               0 :   nsAccessibilityService* accService = GetAccService();
    3892               0 :   if (accService) {
    3893               0 :     NS_ASSERTION(!accService->IsProcessingRefreshDriverNotification(),
    3894                 :                  "Flush during accessible tree update!");
    3895                 :   }
    3896                 : #endif
    3897                 : #endif
    3898                 : 
    3899               0 :   NS_ASSERTION(aType >= Flush_Frames, "Why did we get called?");
    3900                 : 
    3901               0 :   bool isSafeToFlush = IsSafeToFlush();
    3902                 : 
    3903                 :   // If layout could possibly trigger scripts, then it's only safe to flush if
    3904                 :   // it's safe to run script.
    3905                 :   bool hasHadScriptObject;
    3906               0 :   if (mDocument->GetScriptHandlingObject(hasHadScriptObject) ||
    3907                 :       hasHadScriptObject) {
    3908               0 :     isSafeToFlush = isSafeToFlush && nsContentUtils::IsSafeToRunScript();
    3909                 :   }
    3910                 : 
    3911               0 :   NS_ASSERTION(!isSafeToFlush || mViewManager, "Must have view manager");
    3912                 :   // Make sure the view manager stays alive.
    3913               0 :   nsCOMPtr<nsIViewManager> viewManagerDeathGrip = mViewManager;
    3914               0 :   if (isSafeToFlush && mViewManager) {
    3915                 :     // Processing pending notifications can kill us, and some callers only
    3916                 :     // hold weak refs when calling FlushPendingNotifications().  :(
    3917               0 :     nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
    3918                 : 
    3919               0 :     if (mResizeEvent.IsPending()) {
    3920               0 :       FireResizeEvent();
    3921               0 :       if (mIsDestroying) {
    3922                 :         return;
    3923                 :       }
    3924                 :     }
    3925                 : 
    3926                 :     // We need to make sure external resource documents are flushed too (for
    3927                 :     // example, svg filters that reference a filter in an external document
    3928                 :     // need the frames in the external document to be constructed for the
    3929                 :     // filter to work). We only need external resources to be flushed when the
    3930                 :     // main document is flushing >= Flush_Frames, so we flush external
    3931                 :     // resources here instead of nsDocument::FlushPendingNotifications.
    3932               0 :     mDocument->FlushExternalResources(aType);
    3933                 : 
    3934                 :     // Force flushing of any pending content notifications that might have
    3935                 :     // queued up while our event was pending.  That will ensure that we don't
    3936                 :     // construct frames for content right now that's still waiting to be
    3937                 :     // notified on,
    3938               0 :     mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
    3939                 : 
    3940                 :     // Process pending restyles, since any flush of the presshell wants
    3941                 :     // up-to-date style data.
    3942               0 :     if (!mIsDestroying) {
    3943               0 :       mViewManager->FlushDelayedResize(false);
    3944               0 :       mPresContext->FlushPendingMediaFeatureValuesChanged();
    3945                 : 
    3946                 :       // Flush any pending update of the user font set, since that could
    3947                 :       // cause style changes (for updating ex/ch units, and to cause a
    3948                 :       // reflow).
    3949               0 :       mPresContext->FlushUserFontSet();
    3950                 : 
    3951                 :       // Flush any requested SMIL samples.
    3952               0 :       if (mDocument->HasAnimationController()) {
    3953               0 :         mDocument->GetAnimationController()->FlushResampleRequests();
    3954                 :       }
    3955                 : 
    3956                 :       // The FlushResampleRequests() above flushed style changes.
    3957               0 :       if (!mIsDestroying) {
    3958               0 :         nsAutoScriptBlocker scriptBlocker;
    3959               0 :         mFrameConstructor->CreateNeededFrames();
    3960               0 :         mFrameConstructor->ProcessPendingRestyles();
    3961                 :       }
    3962                 :     }
    3963                 : 
    3964                 :     // Dispatch any 'animationstart' events those (or earlier) restyles
    3965                 :     // queued up.
    3966               0 :     if (!mIsDestroying) {
    3967               0 :       mPresContext->AnimationManager()->DispatchEvents();
    3968                 :     }
    3969                 : 
    3970                 :     // Process whatever XBL constructors those restyles queued up.  This
    3971                 :     // ensures that onload doesn't fire too early and that we won't do extra
    3972                 :     // reflows after those constructors run.
    3973               0 :     if (!mIsDestroying) {
    3974               0 :       mDocument->BindingManager()->ProcessAttachedQueue();
    3975                 :     }
    3976                 : 
    3977                 :     // Now those constructors or events might have posted restyle
    3978                 :     // events.  At the same time, we still need up-to-date style data.
    3979                 :     // In particular, reflow depends on style being completely up to
    3980                 :     // date.  If it's not, then style context reparenting, which can
    3981                 :     // happen during reflow, might suddenly pick up the new rules and
    3982                 :     // we'll end up with frames whose style doesn't match the frame
    3983                 :     // type.
    3984               0 :     if (!mIsDestroying) {
    3985               0 :       nsAutoScriptBlocker scriptBlocker;
    3986               0 :       mFrameConstructor->CreateNeededFrames();
    3987               0 :       mFrameConstructor->ProcessPendingRestyles();
    3988                 :     }
    3989                 : 
    3990                 : 
    3991                 :     // There might be more pending constructors now, but we're not going to
    3992                 :     // worry about them.  They can't be triggered during reflow, so we should
    3993                 :     // be good.
    3994                 : 
    3995               0 :     if (aType >= (mSuppressInterruptibleReflows ? Flush_Layout : Flush_InterruptibleLayout) &&
    3996               0 :         !mIsDestroying) {
    3997               0 :       mFrameConstructor->RecalcQuotesAndCounters();
    3998               0 :       mViewManager->FlushDelayedResize(true);
    3999               0 :       if (ProcessReflowCommands(aType < Flush_Layout) && mContentToScrollTo) {
    4000                 :         // We didn't get interrupted.  Go ahead and scroll to our content
    4001                 :         DoScrollContentIntoView(mContentToScrollTo, mContentScrollVPosition,
    4002                 :                                 mContentScrollHPosition,
    4003               0 :                                 mContentToScrollToFlags);
    4004               0 :         mContentToScrollTo = nsnull;
    4005                 :       }
    4006               0 :     } else if (!mIsDestroying && mSuppressInterruptibleReflows &&
    4007                 :                aType == Flush_InterruptibleLayout) {
    4008                 :       // We suppressed this flush, but the document thinks it doesn't
    4009                 :       // need to flush anymore.  Let it know what's really going on.
    4010               0 :       mDocument->SetNeedLayoutFlush();
    4011                 :     }
    4012                 : 
    4013               0 :     if (aType >= Flush_Layout) {
    4014                 :       // Flush plugin geometry. Don't flush plugin geometry for
    4015                 :       // interruptible layouts, since WillPaint does an interruptible
    4016                 :       // layout.
    4017               0 :       nsRootPresContext* rootPresContext = mPresContext->GetRootPresContext();
    4018               0 :       if (rootPresContext) {
    4019               0 :         rootPresContext->UpdatePluginGeometry();
    4020                 :       }
    4021                 : 
    4022               0 :       if (!mIsDestroying) {
    4023               0 :         mViewManager->UpdateWidgetGeometry();
    4024                 :       }
    4025                 :     }
    4026                 :   }
    4027                 : }
    4028                 : 
    4029                 : void
    4030               0 : PresShell::CharacterDataChanged(nsIDocument *aDocument,
    4031                 :                                 nsIContent*  aContent,
    4032                 :                                 CharacterDataChangeInfo* aInfo)
    4033                 : {
    4034               0 :   NS_PRECONDITION(!mIsDocumentGone, "Unexpected CharacterDataChanged");
    4035               0 :   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
    4036                 : 
    4037               0 :   nsAutoCauseReflowNotifier crNotifier(this);
    4038                 : 
    4039               0 :   if (mCaret) {
    4040                 :     // Invalidate the caret's current location before we call into the frame
    4041                 :     // constructor. It is important to do this now, and not wait until the
    4042                 :     // resulting reflow, because this call causes continuation frames of the
    4043                 :     // text frame the caret is in to forget what part of the content they
    4044                 :     // refer to, making it hard for them to return the correct continuation
    4045                 :     // frame to the caret.
    4046               0 :     mCaret->InvalidateOutsideCaret();
    4047                 :   }
    4048                 : 
    4049                 :   // Call this here so it only happens for real content mutations and
    4050                 :   // not cases when the frame constructor calls its own methods to force
    4051                 :   // frame reconstruction.
    4052               0 :   nsIContent *container = aContent->GetParent();
    4053                 :   PRUint32 selectorFlags =
    4054               0 :     container ? (container->GetFlags() & NODE_ALL_SELECTOR_FLAGS) : 0;
    4055               0 :   if (selectorFlags != 0 && !aContent->IsRootOfAnonymousSubtree()) {
    4056               0 :     Element* element = container->AsElement();
    4057               0 :     if (aInfo->mAppend && !aContent->GetNextSibling())
    4058               0 :       mFrameConstructor->RestyleForAppend(element, aContent);
    4059                 :     else
    4060               0 :       mFrameConstructor->RestyleForInsertOrChange(element, aContent);
    4061                 :   }
    4062                 : 
    4063               0 :   mFrameConstructor->CharacterDataChanged(aContent, aInfo);
    4064               0 :   VERIFY_STYLE_TREE;
    4065               0 : }
    4066                 : 
    4067                 : void
    4068               0 : PresShell::ContentStateChanged(nsIDocument* aDocument,
    4069                 :                                nsIContent* aContent,
    4070                 :                                nsEventStates aStateMask)
    4071                 : {
    4072               0 :   NS_PRECONDITION(!mIsDocumentGone, "Unexpected ContentStateChanged");
    4073               0 :   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
    4074                 : 
    4075               0 :   if (mDidInitialReflow) {
    4076               0 :     nsAutoCauseReflowNotifier crNotifier(this);
    4077               0 :     mFrameConstructor->ContentStateChanged(aContent, aStateMask);
    4078               0 :     VERIFY_STYLE_TREE;
    4079                 :   }
    4080               0 : }
    4081                 : 
    4082                 : void
    4083               0 : PresShell::DocumentStatesChanged(nsIDocument* aDocument,
    4084                 :                                  nsEventStates aStateMask)
    4085                 : {
    4086               0 :   NS_PRECONDITION(!mIsDocumentGone, "Unexpected DocumentStatesChanged");
    4087               0 :   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
    4088                 : 
    4089               0 :   if (mDidInitialReflow &&
    4090                 :       mStyleSet->HasDocumentStateDependentStyle(mPresContext,
    4091               0 :                                                 mDocument->GetRootElement(),
    4092               0 :                                                 aStateMask)) {
    4093                 :     mFrameConstructor->PostRestyleEvent(mDocument->GetRootElement(),
    4094               0 :                                         eRestyle_Subtree, NS_STYLE_HINT_NONE);
    4095               0 :     VERIFY_STYLE_TREE;
    4096                 :   }
    4097                 : 
    4098               0 :   if (aStateMask.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) {
    4099               0 :     nsIFrame* root = mFrameConstructor->GetRootFrame();
    4100               0 :     if (root) {
    4101               0 :       root->InvalidateFrameSubtree();
    4102                 :     }
    4103                 :   }
    4104               0 : }
    4105                 : 
    4106                 : void
    4107               0 : PresShell::AttributeWillChange(nsIDocument* aDocument,
    4108                 :                                Element*     aElement,
    4109                 :                                PRInt32      aNameSpaceID,
    4110                 :                                nsIAtom*     aAttribute,
    4111                 :                                PRInt32      aModType)
    4112                 : {
    4113               0 :   NS_PRECONDITION(!mIsDocumentGone, "Unexpected AttributeWillChange");
    4114               0 :   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
    4115                 : 
    4116                 :   // XXXwaterson it might be more elegant to wait until after the
    4117                 :   // initial reflow to begin observing the document. That would
    4118                 :   // squelch any other inappropriate notifications as well.
    4119               0 :   if (mDidInitialReflow) {
    4120               0 :     nsAutoCauseReflowNotifier crNotifier(this);
    4121                 :     mFrameConstructor->AttributeWillChange(aElement, aNameSpaceID,
    4122               0 :                                            aAttribute, aModType);
    4123               0 :     VERIFY_STYLE_TREE;
    4124                 :   }
    4125               0 : }
    4126                 : 
    4127                 : void
    4128               0 : PresShell::AttributeChanged(nsIDocument* aDocument,
    4129                 :                             Element*     aElement,
    4130                 :                             PRInt32      aNameSpaceID,
    4131                 :                             nsIAtom*     aAttribute,
    4132                 :                             PRInt32      aModType)
    4133                 : {
    4134               0 :   NS_PRECONDITION(!mIsDocumentGone, "Unexpected AttributeChanged");
    4135               0 :   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
    4136                 : 
    4137                 :   // XXXwaterson it might be more elegant to wait until after the
    4138                 :   // initial reflow to begin observing the document. That would
    4139                 :   // squelch any other inappropriate notifications as well.
    4140               0 :   if (mDidInitialReflow) {
    4141               0 :     nsAutoCauseReflowNotifier crNotifier(this);
    4142                 :     mFrameConstructor->AttributeChanged(aElement, aNameSpaceID,
    4143               0 :                                         aAttribute, aModType);
    4144               0 :     VERIFY_STYLE_TREE;
    4145                 :   }
    4146               0 : }
    4147                 : 
    4148                 : void
    4149               0 : PresShell::ContentAppended(nsIDocument *aDocument,
    4150                 :                            nsIContent* aContainer,
    4151                 :                            nsIContent* aFirstNewContent,
    4152                 :                            PRInt32     aNewIndexInContainer)
    4153                 : {
    4154               0 :   NS_PRECONDITION(!mIsDocumentGone, "Unexpected ContentAppended");
    4155               0 :   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
    4156               0 :   NS_PRECONDITION(aContainer, "must have container");
    4157                 :   
    4158               0 :   if (!mDidInitialReflow) {
    4159               0 :     return;
    4160                 :   }
    4161                 :   
    4162               0 :   nsAutoCauseReflowNotifier crNotifier(this);
    4163                 : 
    4164                 :   // Call this here so it only happens for real content mutations and
    4165                 :   // not cases when the frame constructor calls its own methods to force
    4166                 :   // frame reconstruction.
    4167               0 :   mFrameConstructor->RestyleForAppend(aContainer->AsElement(), aFirstNewContent);
    4168                 : 
    4169               0 :   mFrameConstructor->ContentAppended(aContainer, aFirstNewContent, true);
    4170               0 :   VERIFY_STYLE_TREE;
    4171                 : }
    4172                 : 
    4173                 : void
    4174               0 : PresShell::ContentInserted(nsIDocument* aDocument,
    4175                 :                            nsIContent*  aContainer,
    4176                 :                            nsIContent*  aChild,
    4177                 :                            PRInt32      aIndexInContainer)
    4178                 : {
    4179               0 :   NS_PRECONDITION(!mIsDocumentGone, "Unexpected ContentInserted");
    4180               0 :   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
    4181                 : 
    4182               0 :   if (!mDidInitialReflow) {
    4183               0 :     return;
    4184                 :   }
    4185                 :   
    4186               0 :   nsAutoCauseReflowNotifier crNotifier(this);
    4187                 : 
    4188                 :   // Call this here so it only happens for real content mutations and
    4189                 :   // not cases when the frame constructor calls its own methods to force
    4190                 :   // frame reconstruction.
    4191               0 :   if (aContainer)
    4192               0 :     mFrameConstructor->RestyleForInsertOrChange(aContainer->AsElement(), aChild);
    4193                 : 
    4194               0 :   mFrameConstructor->ContentInserted(aContainer, aChild, nsnull, true);
    4195               0 :   VERIFY_STYLE_TREE;
    4196                 : }
    4197                 : 
    4198                 : void
    4199               0 : PresShell::ContentRemoved(nsIDocument *aDocument,
    4200                 :                           nsIContent* aContainer,
    4201                 :                           nsIContent* aChild,
    4202                 :                           PRInt32     aIndexInContainer,
    4203                 :                           nsIContent* aPreviousSibling)
    4204                 : {
    4205               0 :   NS_PRECONDITION(!mIsDocumentGone, "Unexpected ContentRemoved");
    4206               0 :   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
    4207                 : 
    4208                 :   // Make sure that the caret doesn't leave a turd where the child used to be.
    4209               0 :   if (mCaret) {
    4210               0 :     mCaret->InvalidateOutsideCaret();
    4211                 :   }
    4212                 : 
    4213                 :   // Notify the ESM that the content has been removed, so that
    4214                 :   // it can clean up any state related to the content.
    4215               0 :   mPresContext->EventStateManager()->ContentRemoved(aDocument, aChild);
    4216                 : 
    4217               0 :   nsAutoCauseReflowNotifier crNotifier(this);
    4218                 : 
    4219                 :   // Call this here so it only happens for real content mutations and
    4220                 :   // not cases when the frame constructor calls its own methods to force
    4221                 :   // frame reconstruction.
    4222                 :   nsIContent* oldNextSibling;
    4223               0 :   if (aContainer) {
    4224               0 :     oldNextSibling = aContainer->GetChildAt(aIndexInContainer);
    4225                 :   } else {
    4226               0 :     oldNextSibling = nsnull;
    4227                 :   }
    4228                 :   
    4229               0 :   if (aContainer)
    4230                 :     mFrameConstructor->RestyleForRemove(aContainer->AsElement(), aChild,
    4231               0 :                                         oldNextSibling);
    4232                 : 
    4233                 :   bool didReconstruct;
    4234                 :   mFrameConstructor->ContentRemoved(aContainer, aChild, oldNextSibling,
    4235                 :                                     nsCSSFrameConstructor::REMOVE_CONTENT,
    4236               0 :                                     &didReconstruct);
    4237                 : 
    4238               0 :   VERIFY_STYLE_TREE;
    4239               0 : }
    4240                 : 
    4241                 : nsresult
    4242               0 : PresShell::ReconstructFrames(void)
    4243                 : {
    4244               0 :   NS_PRECONDITION(!mFrameConstructor->GetRootFrame() || mDidInitialReflow,
    4245                 :                   "Must not have root frame before initial reflow");
    4246               0 :   if (!mDidInitialReflow) {
    4247                 :     // Nothing to do here
    4248               0 :     return NS_OK;
    4249                 :   }
    4250                 : 
    4251               0 :   nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
    4252                 : 
    4253                 :   // Have to make sure that the content notifications are flushed before we
    4254                 :   // start messing with the frame model; otherwise we can get content doubling.
    4255               0 :   mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
    4256                 : 
    4257               0 :   nsAutoCauseReflowNotifier crNotifier(this);
    4258               0 :   mFrameConstructor->BeginUpdate();
    4259               0 :   nsresult rv = mFrameConstructor->ReconstructDocElementHierarchy();
    4260               0 :   VERIFY_STYLE_TREE;
    4261               0 :   mFrameConstructor->EndUpdate();
    4262                 : 
    4263               0 :   return rv;
    4264                 : }
    4265                 : 
    4266                 : void
    4267               0 : nsIPresShell::ReconstructStyleDataInternal()
    4268                 : {
    4269               0 :   mStylesHaveChanged = false;
    4270                 : 
    4271               0 :   if (mIsDestroying) {
    4272                 :     // We don't want to mess with restyles at this point
    4273               0 :     return;
    4274                 :   }
    4275                 : 
    4276               0 :   if (mPresContext) {
    4277               0 :     mPresContext->RebuildUserFontSet();
    4278               0 :     mPresContext->AnimationManager()->KeyframesListIsDirty();
    4279                 :   }
    4280                 : 
    4281               0 :   Element* root = mDocument->GetRootElement();
    4282               0 :   if (!mDidInitialReflow) {
    4283                 :     // Nothing to do here, since we have no frames yet
    4284               0 :     return;
    4285                 :   }
    4286                 : 
    4287               0 :   if (!root) {
    4288                 :     // No content to restyle
    4289               0 :     return;
    4290                 :   }
    4291                 :   
    4292               0 :   mFrameConstructor->PostRestyleEvent(root, eRestyle_Subtree, NS_STYLE_HINT_NONE);
    4293                 : }
    4294                 : 
    4295                 : void
    4296               0 : nsIPresShell::ReconstructStyleDataExternal()
    4297                 : {
    4298               0 :   ReconstructStyleDataInternal();
    4299               0 : }
    4300                 : 
    4301                 : void
    4302               0 : PresShell::StyleSheetAdded(nsIDocument *aDocument,
    4303                 :                            nsIStyleSheet* aStyleSheet,
    4304                 :                            bool aDocumentSheet)
    4305                 : {
    4306                 :   // We only care when enabled sheets are added
    4307               0 :   NS_PRECONDITION(aStyleSheet, "Must have a style sheet!");
    4308                 : 
    4309               0 :   if (aStyleSheet->IsApplicable() && aStyleSheet->HasRules()) {
    4310               0 :     mStylesHaveChanged = true;
    4311                 :   }
    4312               0 : }
    4313                 : 
    4314                 : void 
    4315               0 : PresShell::StyleSheetRemoved(nsIDocument *aDocument,
    4316                 :                              nsIStyleSheet* aStyleSheet,
    4317                 :                              bool aDocumentSheet)
    4318                 : {
    4319                 :   // We only care when enabled sheets are removed
    4320               0 :   NS_PRECONDITION(aStyleSheet, "Must have a style sheet!");
    4321                 : 
    4322               0 :   if (aStyleSheet->IsApplicable() && aStyleSheet->HasRules()) {
    4323               0 :     mStylesHaveChanged = true;
    4324                 :   }
    4325               0 : }
    4326                 : 
    4327                 : void
    4328               0 : PresShell::StyleSheetApplicableStateChanged(nsIDocument *aDocument,
    4329                 :                                             nsIStyleSheet* aStyleSheet,
    4330                 :                                             bool aApplicable)
    4331                 : {
    4332               0 :   if (aStyleSheet->HasRules()) {
    4333               0 :     mStylesHaveChanged = true;
    4334                 :   }
    4335               0 : }
    4336                 : 
    4337                 : void
    4338               0 : PresShell::StyleRuleChanged(nsIDocument *aDocument,
    4339                 :                             nsIStyleSheet* aStyleSheet,
    4340                 :                             nsIStyleRule* aOldStyleRule,
    4341                 :                             nsIStyleRule* aNewStyleRule)
    4342                 : {
    4343               0 :   mStylesHaveChanged = true;
    4344               0 : }
    4345                 : 
    4346                 : void
    4347               0 : PresShell::StyleRuleAdded(nsIDocument *aDocument,
    4348                 :                           nsIStyleSheet* aStyleSheet,
    4349                 :                           nsIStyleRule* aStyleRule) 
    4350                 : {
    4351               0 :   mStylesHaveChanged = true;
    4352               0 : }
    4353                 : 
    4354                 : void
    4355               0 : PresShell::StyleRuleRemoved(nsIDocument *aDocument,
    4356                 :                             nsIStyleSheet* aStyleSheet,
    4357                 :                             nsIStyleRule* aStyleRule) 
    4358                 : {
    4359               0 :   mStylesHaveChanged = true;
    4360               0 : }
    4361                 : 
    4362                 : nsIFrame*
    4363               0 : PresShell::GetRealPrimaryFrameFor(nsIContent* aContent) const
    4364                 : {
    4365               0 :   if (aContent->GetDocument() != GetDocument()) {
    4366               0 :     return nsnull;
    4367                 :   }
    4368               0 :   nsIFrame *primaryFrame = aContent->GetPrimaryFrame();
    4369               0 :   if (!primaryFrame)
    4370               0 :     return nsnull;
    4371               0 :   return nsPlaceholderFrame::GetRealFrameFor(primaryFrame);
    4372                 : }
    4373                 : 
    4374                 : nsIFrame*
    4375               0 : PresShell::GetPlaceholderFrameFor(nsIFrame* aFrame) const
    4376                 : {
    4377               0 :   return mFrameConstructor->GetPlaceholderFrameFor(aFrame);
    4378                 : }
    4379                 : 
    4380                 : nsresult
    4381               0 : PresShell::RenderDocument(const nsRect& aRect, PRUint32 aFlags,
    4382                 :                           nscolor aBackgroundColor,
    4383                 :                           gfxContext* aThebesContext)
    4384                 : {
    4385                 :   NS_TIME_FUNCTION_WITH_DOCURL;
    4386                 : 
    4387               0 :   NS_ENSURE_TRUE(!(aFlags & RENDER_IS_UNTRUSTED), NS_ERROR_NOT_IMPLEMENTED);
    4388                 : 
    4389               0 :   nsRootPresContext* rootPresContext = mPresContext->GetRootPresContext();
    4390               0 :   if (rootPresContext) {
    4391               0 :     rootPresContext->FlushWillPaintObservers();
    4392               0 :     if (mIsDestroying)
    4393               0 :       return NS_OK;
    4394                 :   }
    4395                 : 
    4396               0 :   nsAutoScriptBlocker blockScripts;
    4397                 : 
    4398                 :   // Set up the rectangle as the path in aThebesContext
    4399                 :   gfxRect r(0, 0,
    4400               0 :             nsPresContext::AppUnitsToFloatCSSPixels(aRect.width),
    4401               0 :             nsPresContext::AppUnitsToFloatCSSPixels(aRect.height));
    4402               0 :   aThebesContext->NewPath();
    4403                 : #ifdef MOZ_GFX_OPTIMIZE_MOBILE
    4404                 :   aThebesContext->Rectangle(r, true);
    4405                 : #else
    4406               0 :   aThebesContext->Rectangle(r);
    4407                 : #endif
    4408                 : 
    4409               0 :   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
    4410               0 :   if (!rootFrame) {
    4411                 :     // Nothing to paint, just fill the rect
    4412               0 :     aThebesContext->SetColor(gfxRGBA(aBackgroundColor));
    4413               0 :     aThebesContext->Fill();
    4414               0 :     return NS_OK;
    4415                 :   }
    4416                 : 
    4417               0 :   gfxContextAutoSaveRestore save(aThebesContext);
    4418                 : 
    4419               0 :   gfxContext::GraphicsOperator oldOperator = aThebesContext->CurrentOperator();
    4420               0 :   if (oldOperator == gfxContext::OPERATOR_OVER) {
    4421                 :     // Clip to the destination rectangle before we push the group,
    4422                 :     // to limit the size of the temporary surface
    4423               0 :     aThebesContext->Clip();
    4424                 :   }
    4425                 : 
    4426                 :   // we want the window to be composited as a single image using
    4427                 :   // whatever operator was set; set OPERATOR_OVER here, which is
    4428                 :   // either already the case, or overrides the operator in a group.
    4429                 :   // the original operator will be present when we PopGroup.
    4430                 :   // we can avoid using a temporary surface if we're using OPERATOR_OVER
    4431                 :   // and our background color has no alpha (so we'll be compositing on top
    4432                 :   // of a fully opaque solid color region)
    4433                 :   bool needsGroup = NS_GET_A(aBackgroundColor) < 0xff ||
    4434               0 :     oldOperator != gfxContext::OPERATOR_OVER;
    4435                 : 
    4436               0 :   if (needsGroup) {
    4437                 :     aThebesContext->PushGroup(NS_GET_A(aBackgroundColor) == 0xff ?
    4438                 :                               gfxASurface::CONTENT_COLOR :
    4439               0 :                               gfxASurface::CONTENT_COLOR_ALPHA);
    4440               0 :     aThebesContext->Save();
    4441                 : 
    4442               0 :     if (oldOperator != gfxContext::OPERATOR_OVER) {
    4443                 :       // Clip now while we paint to the temporary surface. For
    4444                 :       // non-source-bounded operators (e.g., SOURCE), we need to do clip
    4445                 :       // here after we've pushed the group, so that eventually popping
    4446                 :       // the group and painting it will be able to clear the entire
    4447                 :       // destination surface.
    4448               0 :       aThebesContext->Clip();
    4449               0 :       aThebesContext->SetOperator(gfxContext::OPERATOR_OVER);
    4450                 :     }
    4451                 :   }
    4452                 : 
    4453               0 :   aThebesContext->Translate(gfxPoint(-nsPresContext::AppUnitsToFloatCSSPixels(aRect.x),
    4454               0 :                                      -nsPresContext::AppUnitsToFloatCSSPixels(aRect.y)));
    4455                 : 
    4456               0 :   nsDeviceContext* devCtx = mPresContext->DeviceContext();
    4457               0 :   gfxFloat scale = gfxFloat(devCtx->AppUnitsPerDevPixel())/nsPresContext::AppUnitsPerCSSPixel();
    4458               0 :   aThebesContext->Scale(scale, scale);
    4459                 : 
    4460                 :   // Since canvas APIs use floats to set up their matrices, we may have
    4461                 :   // some slight inaccuracy here. Adjust matrix components that are
    4462                 :   // integers up to the accuracy of floats to be those integers.
    4463               0 :   aThebesContext->NudgeCurrentMatrixToIntegers();
    4464                 : 
    4465               0 :   AutoSaveRestoreRenderingState _(this);
    4466                 : 
    4467               0 :   nsRefPtr<nsRenderingContext> rc = new nsRenderingContext();
    4468               0 :   rc->Init(devCtx, aThebesContext);
    4469                 : 
    4470               0 :   bool wouldFlushRetainedLayers = false;
    4471               0 :   PRUint32 flags = nsLayoutUtils::PAINT_IGNORE_SUPPRESSION;
    4472               0 :   if (aThebesContext->CurrentMatrix().HasNonIntegerTranslation()) {
    4473               0 :     flags |= nsLayoutUtils::PAINT_IN_TRANSFORM;
    4474                 :   }
    4475               0 :   if (!(aFlags & RENDER_ASYNC_DECODE_IMAGES)) {
    4476               0 :     flags |= nsLayoutUtils::PAINT_SYNC_DECODE_IMAGES;
    4477                 :   }
    4478               0 :   if (aFlags & RENDER_USE_WIDGET_LAYERS) {
    4479                 :     // We only support using widget layers on display root's with widgets.
    4480               0 :     nsIView* view = rootFrame->GetView();
    4481               0 :     if (view && view->GetWidget() &&
    4482               0 :         nsLayoutUtils::GetDisplayRootFrame(rootFrame) == rootFrame) {
    4483               0 :       flags |= nsLayoutUtils::PAINT_WIDGET_LAYERS;
    4484                 :     }
    4485                 :   }
    4486               0 :   if (!(aFlags & RENDER_CARET)) {
    4487               0 :     wouldFlushRetainedLayers = true;
    4488               0 :     flags |= nsLayoutUtils::PAINT_HIDE_CARET;
    4489                 :   }
    4490               0 :   if (aFlags & RENDER_IGNORE_VIEWPORT_SCROLLING) {
    4491               0 :     wouldFlushRetainedLayers = !IgnoringViewportScrolling();
    4492               0 :     mRenderFlags = ChangeFlag(mRenderFlags, true, STATE_IGNORING_VIEWPORT_SCROLLING);
    4493                 :   }
    4494               0 :   if (aFlags & RENDER_DOCUMENT_RELATIVE) {
    4495                 :     // XXX be smarter about this ... drawWindow might want a rect
    4496                 :     // that's "pretty close" to what our retained layer tree covers.
    4497                 :     // In that case, it wouldn't disturb normal rendering too much,
    4498                 :     // and we should allow it.
    4499               0 :     wouldFlushRetainedLayers = true;
    4500               0 :     flags |= nsLayoutUtils::PAINT_DOCUMENT_RELATIVE;
    4501                 :   }
    4502                 : 
    4503                 :   // Don't let drawWindow blow away our retained layer tree
    4504               0 :   if ((flags & nsLayoutUtils::PAINT_WIDGET_LAYERS) && wouldFlushRetainedLayers) {
    4505               0 :     flags &= ~nsLayoutUtils::PAINT_WIDGET_LAYERS;
    4506                 :   }
    4507                 : 
    4508               0 :   nsLayoutUtils::PaintFrame(rc, rootFrame, nsRegion(aRect),
    4509               0 :                             aBackgroundColor, flags);
    4510                 : 
    4511                 :   // if we had to use a group, paint it to the destination now
    4512               0 :   if (needsGroup) {
    4513               0 :     aThebesContext->Restore();
    4514               0 :     aThebesContext->PopGroupToSource();
    4515               0 :     aThebesContext->Paint();
    4516                 :   }
    4517                 : 
    4518               0 :   return NS_OK;
    4519                 : }
    4520                 : 
    4521                 : /*
    4522                 :  * Clip the display list aList to a range. Returns the clipped
    4523                 :  * rectangle surrounding the range.
    4524                 :  */
    4525                 : nsRect
    4526               0 : PresShell::ClipListToRange(nsDisplayListBuilder *aBuilder,
    4527                 :                            nsDisplayList* aList,
    4528                 :                            nsRange* aRange)
    4529                 : {
    4530                 :   NS_TIME_FUNCTION_WITH_DOCURL;
    4531                 : 
    4532                 :   // iterate though the display items and add up the bounding boxes of each.
    4533                 :   // This will allow the total area of the frames within the range to be
    4534                 :   // determined. To do this, remove an item from the bottom of the list, check
    4535                 :   // whether it should be part of the range, and if so, append it to the top
    4536                 :   // of the temporary list tmpList. If the item is a text frame at the end of
    4537                 :   // the selection range, wrap it in an nsDisplayClip to clip the display to
    4538                 :   // the portion of the text frame that is part of the selection. Then, append
    4539                 :   // the wrapper to the top of the list. Otherwise, just delete the item and
    4540                 :   // don't append it.
    4541               0 :   nsRect surfaceRect;
    4542               0 :   nsDisplayList tmpList;
    4543                 : 
    4544                 :   nsDisplayItem* i;
    4545               0 :   while ((i = aList->RemoveBottom())) {
    4546                 :     // itemToInsert indiciates the item that should be inserted into the
    4547                 :     // temporary list. If null, no item should be inserted.
    4548               0 :     nsDisplayItem* itemToInsert = nsnull;
    4549               0 :     nsIFrame* frame = i->GetUnderlyingFrame();
    4550               0 :     if (frame) {
    4551               0 :       nsIContent* content = frame->GetContent();
    4552               0 :       if (content) {
    4553               0 :         bool atStart = (content == aRange->GetStartParent());
    4554               0 :         bool atEnd = (content == aRange->GetEndParent());
    4555               0 :         if ((atStart || atEnd) && frame->GetType() == nsGkAtoms::textFrame) {
    4556                 :           PRInt32 frameStartOffset, frameEndOffset;
    4557               0 :           frame->GetOffsets(frameStartOffset, frameEndOffset);
    4558                 : 
    4559                 :           PRInt32 hilightStart =
    4560               0 :             atStart ? NS_MAX(aRange->StartOffset(), frameStartOffset) : frameStartOffset;
    4561                 :           PRInt32 hilightEnd =
    4562               0 :             atEnd ? NS_MIN(aRange->EndOffset(), frameEndOffset) : frameEndOffset;
    4563               0 :           if (hilightStart < hilightEnd) {
    4564                 :             // determine the location of the start and end edges of the range.
    4565               0 :             nsPoint startPoint, endPoint;
    4566               0 :             frame->GetPointFromOffset(hilightStart, &startPoint);
    4567               0 :             frame->GetPointFromOffset(hilightEnd, &endPoint);
    4568                 : 
    4569                 :             // the clip rectangle is determined by taking the the start and
    4570                 :             // end points of the range, offset from the reference frame.
    4571                 :             // Because of rtl, the end point may be to the left of the
    4572                 :             // start point, so x is set to the lowest value
    4573               0 :             nsRect textRect(aBuilder->ToReferenceFrame(frame), frame->GetSize());
    4574               0 :             nscoord x = NS_MIN(startPoint.x, endPoint.x);
    4575               0 :             textRect.x += x;
    4576               0 :             textRect.width = NS_MAX(startPoint.x, endPoint.x) - x;
    4577               0 :             surfaceRect.UnionRect(surfaceRect, textRect);
    4578                 : 
    4579                 :             // wrap the item in an nsDisplayClip so that it can be clipped to
    4580                 :             // the selection. If the allocation fails, fall through and delete
    4581                 :             // the item below.
    4582                 :             itemToInsert = new (aBuilder)
    4583               0 :                 nsDisplayClip(aBuilder, frame, i, textRect);
    4584                 :           }
    4585                 :         }
    4586                 :         // Don't try to descend into subdocuments.
    4587                 :         // If this ever changes we'd need to add handling for subdocuments with
    4588                 :         // different zoom levels.
    4589               0 :         else if (content->GetCurrentDoc() ==
    4590               0 :                    aRange->GetStartParent()->GetCurrentDoc()) {
    4591                 :           // if the node is within the range, append it to the temporary list
    4592                 :           bool before, after;
    4593                 :           nsresult rv =
    4594               0 :             nsRange::CompareNodeToRange(content, aRange, &before, &after);
    4595               0 :           if (NS_SUCCEEDED(rv) && !before && !after) {
    4596               0 :             itemToInsert = i;
    4597               0 :             surfaceRect.UnionRect(surfaceRect, i->GetBounds(aBuilder));
    4598                 :           }
    4599                 :         }
    4600                 :       }
    4601                 :     }
    4602                 : 
    4603                 :     // insert the item into the list if necessary. If the item has a child
    4604                 :     // list, insert that as well
    4605               0 :     nsDisplayList* sublist = i->GetList();
    4606               0 :     if (itemToInsert || sublist) {
    4607               0 :       tmpList.AppendToTop(itemToInsert ? itemToInsert : i);
    4608                 :       // if the item is a list, iterate over it as well
    4609               0 :       if (sublist)
    4610                 :         surfaceRect.UnionRect(surfaceRect,
    4611               0 :           ClipListToRange(aBuilder, sublist, aRange));
    4612                 :     }
    4613                 :     else {
    4614                 :       // otherwise, just delete the item and don't readd it to the list
    4615               0 :       i->~nsDisplayItem();
    4616                 :     }
    4617                 :   }
    4618                 : 
    4619                 :   // now add all the items back onto the original list again
    4620               0 :   aList->AppendToTop(&tmpList);
    4621                 : 
    4622                 :   return surfaceRect;
    4623                 : }
    4624                 : 
    4625                 : #ifdef DEBUG
    4626                 : #include <stdio.h>
    4627                 : 
    4628                 : static bool gDumpRangePaintList = false;
    4629                 : #endif
    4630                 : 
    4631                 : RangePaintInfo*
    4632               0 : PresShell::CreateRangePaintInfo(nsIDOMRange* aRange,
    4633                 :                                 nsRect& aSurfaceRect,
    4634                 :                                 bool aForPrimarySelection)
    4635                 : {
    4636                 :   NS_TIME_FUNCTION_WITH_DOCURL;
    4637                 : 
    4638               0 :   RangePaintInfo* info = nsnull;
    4639                 : 
    4640               0 :   nsRange* range = static_cast<nsRange*>(aRange);
    4641                 : 
    4642                 :   nsIFrame* ancestorFrame;
    4643               0 :   nsIFrame* rootFrame = GetRootFrame();
    4644                 : 
    4645                 :   // If the start or end of the range is the document, just use the root
    4646                 :   // frame, otherwise get the common ancestor of the two endpoints of the
    4647                 :   // range.
    4648               0 :   nsINode* startParent = range->GetStartParent();
    4649               0 :   nsINode* endParent = range->GetEndParent();
    4650               0 :   nsIDocument* doc = startParent->GetCurrentDoc();
    4651               0 :   if (startParent == doc || endParent == doc) {
    4652               0 :     ancestorFrame = rootFrame;
    4653                 :   }
    4654                 :   else {
    4655               0 :     nsINode* ancestor = nsContentUtils::GetCommonAncestor(startParent, endParent);
    4656               0 :     NS_ASSERTION(!ancestor || ancestor->IsNodeOfType(nsINode::eCONTENT),
    4657                 :                  "common ancestor is not content");
    4658               0 :     if (!ancestor || !ancestor->IsNodeOfType(nsINode::eCONTENT))
    4659               0 :       return nsnull;
    4660                 : 
    4661               0 :     nsIContent* ancestorContent = static_cast<nsIContent*>(ancestor);
    4662               0 :     ancestorFrame = ancestorContent->GetPrimaryFrame();
    4663                 : 
    4664                 :     // use the nearest ancestor frame that includes all continuations as the
    4665                 :     // root for building the display list
    4666               0 :     while (ancestorFrame &&
    4667               0 :            nsLayoutUtils::GetNextContinuationOrSpecialSibling(ancestorFrame))
    4668               0 :       ancestorFrame = ancestorFrame->GetParent();
    4669                 :   }
    4670                 : 
    4671               0 :   if (!ancestorFrame)
    4672               0 :     return nsnull;
    4673                 : 
    4674               0 :   info = new RangePaintInfo(range, ancestorFrame);
    4675                 : 
    4676               0 :   nsRect ancestorRect = ancestorFrame->GetVisualOverflowRect();
    4677                 : 
    4678                 :   // get a display list containing the range
    4679               0 :   info->mBuilder.SetIncludeAllOutOfFlows();
    4680               0 :   if (aForPrimarySelection) {
    4681               0 :     info->mBuilder.SetSelectedFramesOnly();
    4682                 :   }
    4683               0 :   info->mBuilder.EnterPresShell(ancestorFrame, ancestorRect);
    4684                 :   ancestorFrame->BuildDisplayListForStackingContext(&info->mBuilder,
    4685               0 :                                                     ancestorRect, &info->mList);
    4686                 : 
    4687                 : #ifdef DEBUG
    4688               0 :   if (gDumpRangePaintList) {
    4689               0 :     fprintf(stderr, "CreateRangePaintInfo --- before ClipListToRange:\n");
    4690               0 :     nsFrame::PrintDisplayList(&(info->mBuilder), info->mList);
    4691                 :   }
    4692                 : #endif
    4693                 : 
    4694               0 :   nsRect rangeRect = ClipListToRange(&info->mBuilder, &info->mList, range);
    4695                 : 
    4696               0 :   info->mBuilder.LeavePresShell(ancestorFrame, ancestorRect);
    4697                 : 
    4698                 : #ifdef DEBUG
    4699               0 :   if (gDumpRangePaintList) {
    4700               0 :     fprintf(stderr, "CreateRangePaintInfo --- after ClipListToRange:\n");
    4701               0 :     nsFrame::PrintDisplayList(&(info->mBuilder), info->mList);
    4702                 :   }
    4703                 : #endif
    4704                 : 
    4705                 :   // determine the offset of the reference frame for the display list
    4706                 :   // to the root frame. This will allow the coordinates used when painting
    4707                 :   // to all be offset from the same point
    4708               0 :   info->mRootOffset = ancestorFrame->GetOffsetTo(rootFrame);
    4709               0 :   rangeRect.MoveBy(info->mRootOffset);
    4710               0 :   aSurfaceRect.UnionRect(aSurfaceRect, rangeRect);
    4711                 : 
    4712               0 :   return info;
    4713                 : }
    4714                 : 
    4715                 : already_AddRefed<gfxASurface>
    4716               0 : PresShell::PaintRangePaintInfo(nsTArray<nsAutoPtr<RangePaintInfo> >* aItems,
    4717                 :                                nsISelection* aSelection,
    4718                 :                                nsIntRegion* aRegion,
    4719                 :                                nsRect aArea,
    4720                 :                                nsIntPoint& aPoint,
    4721                 :                                nsIntRect* aScreenRect)
    4722                 : {
    4723                 :   NS_TIME_FUNCTION_WITH_DOCURL;
    4724                 : 
    4725               0 :   nsPresContext* pc = GetPresContext();
    4726               0 :   if (!pc || aArea.width == 0 || aArea.height == 0)
    4727               0 :     return nsnull;
    4728                 : 
    4729               0 :   nsDeviceContext* deviceContext = pc->DeviceContext();
    4730                 : 
    4731                 :   // use the rectangle to create the surface
    4732               0 :   nsIntRect pixelArea = aArea.ToOutsidePixels(pc->AppUnitsPerDevPixel());
    4733                 : 
    4734                 :   // if the area of the image is larger than the maximum area, scale it down
    4735               0 :   float scale = 0.0;
    4736                 :   nsIntRect rootScreenRect =
    4737               0 :     GetRootFrame()->GetScreenRectInAppUnits().ToNearestPixels(
    4738               0 :       pc->AppUnitsPerDevPixel());
    4739                 : 
    4740                 :   // if the image is larger in one or both directions than half the size of
    4741                 :   // the available screen area, scale the image down to that size.
    4742               0 :   nsRect maxSize;
    4743               0 :   deviceContext->GetClientRect(maxSize);
    4744               0 :   nscoord maxWidth = pc->AppUnitsToDevPixels(maxSize.width >> 1);
    4745               0 :   nscoord maxHeight = pc->AppUnitsToDevPixels(maxSize.height >> 1);
    4746               0 :   bool resize = (pixelArea.width > maxWidth || pixelArea.height > maxHeight);
    4747               0 :   if (resize) {
    4748               0 :     scale = 1.0;
    4749                 :     // divide the maximum size by the image size in both directions. Whichever
    4750                 :     // direction produces the smallest result determines how much should be
    4751                 :     // scaled.
    4752               0 :     if (pixelArea.width > maxWidth)
    4753               0 :       scale = NS_MIN(scale, float(maxWidth) / pixelArea.width);
    4754               0 :     if (pixelArea.height > maxHeight)
    4755               0 :       scale = NS_MIN(scale, float(maxHeight) / pixelArea.height);
    4756                 : 
    4757               0 :     pixelArea.width = NSToIntFloor(float(pixelArea.width) * scale);
    4758               0 :     pixelArea.height = NSToIntFloor(float(pixelArea.height) * scale);
    4759                 : 
    4760                 :     // adjust the screen position based on the rescaled size
    4761               0 :     nscoord left = rootScreenRect.x + pixelArea.x;
    4762               0 :     nscoord top = rootScreenRect.y + pixelArea.y;
    4763               0 :     aScreenRect->x = NSToIntFloor(aPoint.x - float(aPoint.x - left) * scale);
    4764               0 :     aScreenRect->y = NSToIntFloor(aPoint.y - float(aPoint.y - top) * scale);
    4765                 :   }
    4766                 :   else {
    4767                 :     // move aScreenRect to the position of the surface in screen coordinates
    4768               0 :     aScreenRect->MoveTo(rootScreenRect.x + pixelArea.x, rootScreenRect.y + pixelArea.y);
    4769                 :   }
    4770               0 :   aScreenRect->width = pixelArea.width;
    4771               0 :   aScreenRect->height = pixelArea.height;
    4772                 : 
    4773                 :   gfxImageSurface* surface =
    4774                 :     new gfxImageSurface(gfxIntSize(pixelArea.width, pixelArea.height),
    4775               0 :                         gfxImageSurface::ImageFormatARGB32);
    4776               0 :   if (surface->CairoStatus()) {
    4777               0 :     delete surface;
    4778               0 :     return nsnull;
    4779                 :   }
    4780                 : 
    4781                 :   // clear the image
    4782               0 :   gfxContext context(surface);
    4783               0 :   context.SetOperator(gfxContext::OPERATOR_CLEAR);
    4784               0 :   context.Rectangle(gfxRect(0, 0, pixelArea.width, pixelArea.height));
    4785               0 :   context.Fill();
    4786                 : 
    4787               0 :   nsRefPtr<nsRenderingContext> rc = new nsRenderingContext();
    4788               0 :   rc->Init(deviceContext, surface);
    4789                 : 
    4790               0 :   if (aRegion) {
    4791                 :     // Convert aRegion from CSS pixels to dev pixels
    4792                 :     nsIntRegion region =
    4793               0 :       aRegion->ToAppUnits(nsPresContext::AppUnitsPerCSSPixel())
    4794               0 :         .ToOutsidePixels(pc->AppUnitsPerDevPixel());
    4795               0 :     rc->SetClip(region);
    4796                 :   }
    4797                 : 
    4798               0 :   if (resize)
    4799               0 :     rc->Scale(scale, scale);
    4800                 : 
    4801                 :   // translate so that points are relative to the surface area
    4802               0 :   rc->Translate(-aArea.TopLeft());
    4803                 : 
    4804                 :   // temporarily hide the selection so that text is drawn normally. If a
    4805                 :   // selection is being rendered, use that, otherwise use the presshell's
    4806                 :   // selection.
    4807               0 :   nsRefPtr<nsFrameSelection> frameSelection;
    4808               0 :   if (aSelection) {
    4809               0 :     nsCOMPtr<nsISelectionPrivate> selpriv = do_QueryInterface(aSelection);
    4810               0 :     selpriv->GetFrameSelection(getter_AddRefs(frameSelection));
    4811                 :   }
    4812                 :   else {
    4813               0 :     frameSelection = FrameSelection();
    4814                 :   }
    4815               0 :   PRInt16 oldDisplaySelection = frameSelection->GetDisplaySelection();
    4816               0 :   frameSelection->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);
    4817                 : 
    4818                 :   // next, paint each range in the selection
    4819               0 :   PRInt32 count = aItems->Length();
    4820               0 :   for (PRInt32 i = 0; i < count; i++) {
    4821               0 :     RangePaintInfo* rangeInfo = (*aItems)[i];
    4822                 :     // the display lists paint relative to the offset from the reference
    4823                 :     // frame, so translate the rendering context
    4824                 :     nsRenderingContext::AutoPushTranslation
    4825               0 :       translate(rc, rangeInfo->mRootOffset);
    4826                 : 
    4827               0 :     aArea.MoveBy(-rangeInfo->mRootOffset.x, -rangeInfo->mRootOffset.y);
    4828               0 :     nsRegion visible(aArea);
    4829               0 :     rangeInfo->mList.ComputeVisibilityForRoot(&rangeInfo->mBuilder, &visible);
    4830               0 :     rangeInfo->mList.PaintRoot(&rangeInfo->mBuilder, rc, nsDisplayList::PAINT_DEFAULT);
    4831               0 :     aArea.MoveBy(rangeInfo->mRootOffset.x, rangeInfo->mRootOffset.y);
    4832                 :   }
    4833                 : 
    4834                 :   // restore the old selection display state
    4835               0 :   frameSelection->SetDisplaySelection(oldDisplaySelection);
    4836                 : 
    4837               0 :   NS_ADDREF(surface);
    4838               0 :   return surface;
    4839                 : }
    4840                 : 
    4841                 : already_AddRefed<gfxASurface>
    4842               0 : PresShell::RenderNode(nsIDOMNode* aNode,
    4843                 :                       nsIntRegion* aRegion,
    4844                 :                       nsIntPoint& aPoint,
    4845                 :                       nsIntRect* aScreenRect)
    4846                 : {
    4847                 :   // area will hold the size of the surface needed to draw the node, measured
    4848                 :   // from the root frame.
    4849               0 :   nsRect area;
    4850               0 :   nsTArray<nsAutoPtr<RangePaintInfo> > rangeItems;
    4851                 : 
    4852                 :   // nothing to draw if the node isn't in a document
    4853               0 :   nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
    4854               0 :   if (!node->IsInDoc())
    4855               0 :     return nsnull;
    4856                 :   
    4857               0 :   nsRefPtr<nsRange> range = new nsRange();
    4858               0 :   if (NS_FAILED(range->SelectNode(aNode)))
    4859               0 :     return nsnull;
    4860                 : 
    4861               0 :   RangePaintInfo* info = CreateRangePaintInfo(range, area, false);
    4862               0 :   if (info && !rangeItems.AppendElement(info)) {
    4863               0 :     delete info;
    4864               0 :     return nsnull;
    4865                 :   }
    4866                 : 
    4867               0 :   if (aRegion) {
    4868                 :     // combine the area with the supplied region
    4869               0 :     nsIntRect rrectPixels = aRegion->GetBounds();
    4870                 : 
    4871               0 :     nsRect rrect = rrectPixels.ToAppUnits(nsPresContext::AppUnitsPerCSSPixel());
    4872               0 :     area.IntersectRect(area, rrect);
    4873                 :     
    4874               0 :     nsPresContext* pc = GetPresContext();
    4875               0 :     if (!pc)
    4876               0 :       return nsnull;
    4877                 : 
    4878                 :     // move the region so that it is offset from the topleft corner of the surface
    4879               0 :     aRegion->MoveBy(-pc->AppUnitsToDevPixels(area.x),
    4880               0 :                     -pc->AppUnitsToDevPixels(area.y));
    4881                 :   }
    4882                 : 
    4883                 :   return PaintRangePaintInfo(&rangeItems, nsnull, aRegion, area, aPoint,
    4884               0 :                              aScreenRect);
    4885                 : }
    4886                 : 
    4887                 : already_AddRefed<gfxASurface>
    4888               0 : PresShell::RenderSelection(nsISelection* aSelection,
    4889                 :                            nsIntPoint& aPoint,
    4890                 :                            nsIntRect* aScreenRect)
    4891                 : {
    4892                 :   // area will hold the size of the surface needed to draw the selection,
    4893                 :   // measured from the root frame.
    4894               0 :   nsRect area;
    4895               0 :   nsTArray<nsAutoPtr<RangePaintInfo> > rangeItems;
    4896                 : 
    4897                 :   // iterate over each range and collect them into the rangeItems array.
    4898                 :   // This is done so that the size of selection can be determined so as
    4899                 :   // to allocate a surface area
    4900                 :   PRInt32 numRanges;
    4901               0 :   aSelection->GetRangeCount(&numRanges);
    4902               0 :   NS_ASSERTION(numRanges > 0, "RenderSelection called with no selection");
    4903                 : 
    4904               0 :   for (PRInt32 r = 0; r < numRanges; r++)
    4905                 :   {
    4906               0 :     nsCOMPtr<nsIDOMRange> range;
    4907               0 :     aSelection->GetRangeAt(r, getter_AddRefs(range));
    4908                 : 
    4909               0 :     RangePaintInfo* info = CreateRangePaintInfo(range, area, true);
    4910               0 :     if (info && !rangeItems.AppendElement(info)) {
    4911               0 :       delete info;
    4912               0 :       return nsnull;
    4913                 :     }
    4914                 :   }
    4915                 : 
    4916                 :   return PaintRangePaintInfo(&rangeItems, aSelection, nsnull, area, aPoint,
    4917               0 :                              aScreenRect);
    4918                 : }
    4919                 : 
    4920                 : nsresult
    4921               0 : PresShell::AddPrintPreviewBackgroundItem(nsDisplayListBuilder& aBuilder,
    4922                 :                                          nsDisplayList&        aList,
    4923                 :                                          nsIFrame*             aFrame,
    4924                 :                                          const nsRect&         aBounds)
    4925                 : {
    4926                 :   return aList.AppendNewToBottom(new (&aBuilder)
    4927               0 :     nsDisplaySolidColor(&aBuilder, aFrame, aBounds, NS_RGB(115, 115, 115)));
    4928                 : }
    4929                 : 
    4930                 : static bool
    4931               0 : AddCanvasBackgroundColor(const nsDisplayList& aList, nsIFrame* aCanvasFrame,
    4932                 :                          nscolor aColor)
    4933                 : {
    4934               0 :   for (nsDisplayItem* i = aList.GetBottom(); i; i = i->GetAbove()) {
    4935               0 :     if (i->GetUnderlyingFrame() == aCanvasFrame &&
    4936               0 :         i->GetType() == nsDisplayItem::TYPE_CANVAS_BACKGROUND) {
    4937               0 :       nsDisplayCanvasBackground* bg = static_cast<nsDisplayCanvasBackground*>(i);
    4938               0 :       bg->SetExtraBackgroundColor(aColor);
    4939               0 :       return true;
    4940                 :     }
    4941               0 :     nsDisplayList* sublist = i->GetList();
    4942               0 :     if (sublist && AddCanvasBackgroundColor(*sublist, aCanvasFrame, aColor))
    4943               0 :       return true;
    4944                 :   }
    4945               0 :   return false;
    4946                 : }
    4947                 : 
    4948               0 : nsresult PresShell::AddCanvasBackgroundColorItem(nsDisplayListBuilder& aBuilder,
    4949                 :                                                  nsDisplayList&        aList,
    4950                 :                                                  nsIFrame*             aFrame,
    4951                 :                                                  const nsRect&         aBounds,
    4952                 :                                                  nscolor               aBackstopColor,
    4953                 :                                                  PRUint32              aFlags)
    4954                 : {
    4955               0 :   if (aBounds.IsEmpty()) {
    4956               0 :     return NS_OK;
    4957                 :   }
    4958                 :   // We don't want to add an item for the canvas background color if the frame
    4959                 :   // (sub)tree we are painting doesn't include any canvas frames. There isn't
    4960                 :   // an easy way to check this directly, but if we check if the root of the
    4961                 :   // (sub)tree we are painting is a canvas frame that should cover us in all
    4962                 :   // cases (it will usually be a viewport frame when we have a canvas frame in
    4963                 :   // the (sub)tree).
    4964               0 :   if (!(aFlags & nsIPresShell::FORCE_DRAW) &&
    4965               0 :       !nsCSSRendering::IsCanvasFrame(aFrame)) {
    4966               0 :     return NS_OK;
    4967                 :   }
    4968                 : 
    4969               0 :   nscolor bgcolor = NS_ComposeColors(aBackstopColor, mCanvasBackgroundColor);
    4970               0 :   if (NS_GET_A(bgcolor) == 0)
    4971               0 :     return NS_OK;
    4972                 : 
    4973                 :   // To make layers work better, we want to avoid having a big non-scrolled 
    4974                 :   // color background behind a scrolled transparent background. Instead,
    4975                 :   // we'll try to move the color background into the scrolled content
    4976                 :   // by making nsDisplayCanvasBackground paint it.
    4977               0 :   if (!aFrame->GetParent()) {
    4978                 :     nsIScrollableFrame* sf =
    4979               0 :       aFrame->PresContext()->PresShell()->GetRootScrollFrameAsScrollable();
    4980               0 :     if (sf) {
    4981               0 :       nsCanvasFrame* canvasFrame = do_QueryFrame(sf->GetScrolledFrame());
    4982               0 :       if (canvasFrame && canvasFrame->IsVisibleForPainting(&aBuilder)) {
    4983               0 :         if (AddCanvasBackgroundColor(aList, canvasFrame, bgcolor))
    4984               0 :           return NS_OK;
    4985                 :       }
    4986                 :     }
    4987                 :   }
    4988                 : 
    4989                 :   return aList.AppendNewToBottom(
    4990               0 :       new (&aBuilder) nsDisplaySolidColor(&aBuilder, aFrame, aBounds, bgcolor));
    4991                 : }
    4992                 : 
    4993               0 : static bool IsTransparentContainerElement(nsPresContext* aPresContext)
    4994                 : {
    4995               0 :   nsCOMPtr<nsISupports> container = aPresContext->GetContainerInternal();
    4996               0 :   nsCOMPtr<nsIDocShellTreeItem> docShellItem = do_QueryInterface(container);
    4997               0 :   nsCOMPtr<nsPIDOMWindow> pwin(do_GetInterface(docShellItem));
    4998               0 :   if (!pwin)
    4999               0 :     return false;
    5000                 :   nsCOMPtr<nsIContent> containerElement =
    5001               0 :     do_QueryInterface(pwin->GetFrameElementInternal());
    5002                 :   return containerElement &&
    5003               0 :          containerElement->HasAttr(kNameSpaceID_None, nsGkAtoms::transparent);
    5004                 : }
    5005                 : 
    5006               0 : nscolor PresShell::GetDefaultBackgroundColorToDraw()
    5007                 : {
    5008               0 :   if (!mPresContext || !mPresContext->GetBackgroundColorDraw()) {
    5009               0 :     return NS_RGB(255,255,255);
    5010                 :   }
    5011               0 :   return mPresContext->DefaultBackgroundColor();
    5012                 : }
    5013                 : 
    5014               0 : void PresShell::UpdateCanvasBackground()
    5015                 : {
    5016                 :   // If we have a frame tree and it has style information that
    5017                 :   // specifies the background color of the canvas, update our local
    5018                 :   // cache of that color.
    5019               0 :   nsIFrame* rootStyleFrame = FrameConstructor()->GetRootElementStyleFrame();
    5020               0 :   if (rootStyleFrame) {
    5021                 :     nsStyleContext* bgStyle =
    5022               0 :       nsCSSRendering::FindRootFrameBackground(rootStyleFrame);
    5023                 :     // XXX We should really be passing the canvasframe, not the root element
    5024                 :     // style frame but we don't have access to the canvasframe here. It isn't
    5025                 :     // a problem because only a few frames can return something other than true
    5026                 :     // and none of them would be a canvas frame or root element style frame.
    5027                 :     mCanvasBackgroundColor =
    5028                 :       nsCSSRendering::DetermineBackgroundColor(mPresContext, bgStyle,
    5029               0 :                                                rootStyleFrame);
    5030               0 :     if (GetPresContext()->IsRootContentDocument() &&
    5031               0 :         !IsTransparentContainerElement(mPresContext)) {
    5032                 :       mCanvasBackgroundColor =
    5033               0 :         NS_ComposeColors(GetDefaultBackgroundColorToDraw(), mCanvasBackgroundColor);
    5034                 :     }
    5035                 :   }
    5036                 : 
    5037                 :   // If the root element of the document (ie html) has style 'display: none'
    5038                 :   // then the document's background color does not get drawn; cache the
    5039                 :   // color we actually draw.
    5040               0 :   if (!FrameConstructor()->GetRootElementFrame()) {
    5041               0 :     mCanvasBackgroundColor = GetDefaultBackgroundColorToDraw();
    5042                 :   }
    5043               0 :   if (XRE_GetProcessType() == GeckoProcessType_Content) {
    5044               0 :     if (TabChild* tabChild = GetTabChildFrom(this)) {
    5045               0 :       tabChild->SetBackgroundColor(mCanvasBackgroundColor);
    5046                 :     }
    5047                 :   }
    5048               0 : }
    5049                 : 
    5050               0 : nscolor PresShell::ComputeBackstopColor(nsIView* aDisplayRoot)
    5051                 : {
    5052               0 :   nsIWidget* widget = aDisplayRoot->GetWidget();
    5053               0 :   if (widget && widget->GetTransparencyMode() != eTransparencyOpaque) {
    5054                 :     // Within a transparent widget, so the backstop color must be
    5055                 :     // totally transparent.
    5056               0 :     return NS_RGBA(0,0,0,0);
    5057                 :   }
    5058                 :   // Within an opaque widget (or no widget at all), so the backstop
    5059                 :   // color must be totally opaque. The user's default background
    5060                 :   // as reported by the prescontext is guaranteed to be opaque.
    5061               0 :   return GetDefaultBackgroundColorToDraw();
    5062                 : }
    5063                 : 
    5064                 : struct PaintParams {
    5065                 :   nscolor mBackgroundColor;
    5066                 : };
    5067                 : 
    5068               0 : LayerManager* PresShell::GetLayerManager()
    5069                 : {
    5070               0 :   NS_ASSERTION(mViewManager, "Should have view manager");
    5071                 : 
    5072               0 :   nsIView* rootView = mViewManager->GetRootView();
    5073               0 :   if (rootView) {
    5074               0 :     if (nsIWidget* widget = rootView->GetWidget()) {
    5075               0 :       return widget->GetLayerManager();
    5076                 :     }
    5077                 :   }
    5078               0 :   return nsnull;
    5079                 : }
    5080                 : 
    5081               0 : void PresShell::SetIgnoreViewportScrolling(bool aIgnore)
    5082                 : {
    5083               0 :   if (IgnoringViewportScrolling() == aIgnore) {
    5084               0 :     return;
    5085                 :   }
    5086               0 :   RenderingState state(this);
    5087                 :   state.mRenderFlags = ChangeFlag(state.mRenderFlags, aIgnore,
    5088               0 :                                   STATE_IGNORING_VIEWPORT_SCROLLING);
    5089               0 :   SetRenderingState(state);
    5090                 : }
    5091                 : 
    5092               0 : void PresShell::SetDisplayPort(const nsRect& aDisplayPort)
    5093                 : {
    5094               0 :   NS_ABORT_IF_FALSE(false, "SetDisplayPort is deprecated");
    5095               0 : }
    5096                 : 
    5097               0 : nsresult PresShell::SetResolution(float aXResolution, float aYResolution)
    5098                 : {
    5099               0 :   if (!(aXResolution > 0.0 && aYResolution > 0.0)) {
    5100               0 :     return NS_ERROR_ILLEGAL_VALUE;
    5101                 :   }
    5102               0 :   if (aXResolution == mXResolution && aYResolution == mYResolution) {
    5103               0 :     return NS_OK;
    5104                 :   }
    5105               0 :   RenderingState state(this);
    5106               0 :   state.mXResolution = aXResolution;
    5107               0 :   state.mYResolution = aYResolution;
    5108               0 :   SetRenderingState(state);
    5109               0 :   return NS_OK;
    5110                 :  }
    5111                 : 
    5112               0 : void PresShell::SetRenderingState(const RenderingState& aState)
    5113                 : {
    5114               0 :   if (mRenderFlags != aState.mRenderFlags) {
    5115                 :     // Rendering state changed in a way that forces us to flush any
    5116                 :     // retained layers we might already have.
    5117               0 :     LayerManager* manager = GetLayerManager();
    5118               0 :     if (manager) {
    5119               0 :       FrameLayerBuilder::InvalidateAllLayers(manager);
    5120                 :     }
    5121                 :   }
    5122                 : 
    5123               0 :   mRenderFlags = aState.mRenderFlags;
    5124               0 :   mXResolution = aState.mXResolution;
    5125               0 :   mYResolution = aState.mYResolution;
    5126               0 : }
    5127                 : 
    5128               0 : void PresShell::SynthesizeMouseMove(bool aFromScroll)
    5129                 : {
    5130               0 :   if (!sSynthMouseMove)
    5131               0 :     return;
    5132                 : 
    5133               0 :   if (mPaintingSuppressed || !mIsActive || !mPresContext) {
    5134               0 :     return;
    5135                 :   }
    5136                 : 
    5137               0 :   if (!mPresContext->IsRoot()) {
    5138               0 :     nsIPresShell* rootPresShell = GetRootPresShell();
    5139               0 :     if (rootPresShell) {
    5140               0 :       rootPresShell->SynthesizeMouseMove(aFromScroll);
    5141                 :     }
    5142               0 :     return;
    5143                 :   }
    5144                 : 
    5145               0 :   if (mMouseLocation == nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE))
    5146               0 :     return;
    5147                 : 
    5148               0 :   if (!mSynthMouseMoveEvent.IsPending()) {
    5149                 :     nsRefPtr<nsSynthMouseMoveEvent> ev =
    5150               0 :         new nsSynthMouseMoveEvent(this, aFromScroll);
    5151                 : 
    5152               0 :     if (!GetPresContext()->RefreshDriver()->AddRefreshObserver(ev,
    5153               0 :                                                                Flush_Display)) {
    5154               0 :       NS_WARNING("failed to dispatch nsSynthMouseMoveEvent");
    5155                 :       return;
    5156                 :     }
    5157                 : 
    5158               0 :     mSynthMouseMoveEvent = ev;
    5159                 :   }
    5160                 : }
    5161                 : 
    5162                 : /**
    5163                 :  * Find the first floating view with a widget in a postorder traversal of the
    5164                 :  * view tree that contains the point. Thus more deeply nested floating views
    5165                 :  * are preferred over their ancestors, and floating views earlier in the
    5166                 :  * view hierarchy (i.e., added later) are preferred over their siblings.
    5167                 :  * This is adequate for finding the "topmost" floating view under a point,
    5168                 :  * given that floating views don't supporting having a specific z-index.
    5169                 :  * 
    5170                 :  * We cannot exit early when aPt is outside the view bounds, because floating
    5171                 :  * views aren't necessarily included in their parent's bounds, so this could
    5172                 :  * traverse the entire view hierarchy --- use carefully.
    5173                 :  */
    5174               0 : static nsIView* FindFloatingViewContaining(nsIView* aView, nsPoint aPt)
    5175                 : {
    5176               0 :   if (aView->GetVisibility() == nsViewVisibility_kHide)
    5177                 :     // No need to look into descendants.
    5178               0 :     return nsnull;
    5179                 : 
    5180               0 :   nsIFrame* frame = aView->GetFrame();
    5181               0 :   if (frame) {
    5182               0 :     if (!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) ||
    5183               0 :         !frame->PresContext()->PresShell()->IsActive()) {
    5184               0 :       return nsnull;
    5185                 :     }
    5186                 :   }
    5187                 : 
    5188               0 :   for (nsIView* v = aView->GetFirstChild(); v; v = v->GetNextSibling()) {
    5189               0 :     nsIView* r = FindFloatingViewContaining(v, v->ConvertFromParentCoords(aPt));
    5190               0 :     if (r)
    5191               0 :       return r;
    5192                 :   }
    5193                 : 
    5194               0 :   if (aView->GetFloating() && aView->HasWidget() &&
    5195               0 :       aView->GetDimensions().Contains(aPt))
    5196               0 :     return aView;
    5197                 :     
    5198               0 :   return nsnull;
    5199                 : }
    5200                 : 
    5201                 : /*
    5202                 :  * This finds the first view containing the given point in a postorder
    5203                 :  * traversal of the view tree that contains the point, assuming that the
    5204                 :  * point is not in a floating view.  It assumes that only floating views
    5205                 :  * extend outside the bounds of their parents.
    5206                 :  *
    5207                 :  * This methods should only be called if FindFloatingViewContaining
    5208                 :  * returns null.
    5209                 :  */
    5210               0 : static nsIView* FindViewContaining(nsIView* aView, nsPoint aPt)
    5211                 : {
    5212               0 :   if (!aView->GetDimensions().Contains(aPt) ||
    5213               0 :       aView->GetVisibility() == nsViewVisibility_kHide) {
    5214               0 :     return nsnull;
    5215                 :   }
    5216                 : 
    5217               0 :   nsIFrame* frame = aView->GetFrame();
    5218               0 :   if (frame) {
    5219               0 :     if (!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) ||
    5220               0 :         !frame->PresContext()->PresShell()->IsActive()) {
    5221               0 :       return nsnull;
    5222                 :     }
    5223                 :   }
    5224                 : 
    5225               0 :   for (nsIView* v = aView->GetFirstChild(); v; v = v->GetNextSibling()) {
    5226               0 :     nsIView* r = FindViewContaining(v, v->ConvertFromParentCoords(aPt));
    5227               0 :     if (r)
    5228               0 :       return r;
    5229                 :   }
    5230                 : 
    5231               0 :   return aView;
    5232                 : }
    5233                 : 
    5234                 : void
    5235               0 : PresShell::ProcessSynthMouseMoveEvent(bool aFromScroll)
    5236                 : {
    5237                 :   // If drag session has started, we shouldn't synthesize mousemove event.
    5238               0 :   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
    5239               0 :   if (dragSession) {
    5240               0 :     mSynthMouseMoveEvent.Forget();
    5241                 :     return;
    5242                 :   }
    5243                 : 
    5244                 :   // allow new event to be posted while handling this one only if the
    5245                 :   // source of the event is a scroll (to prevent infinite reflow loops)
    5246               0 :   if (aFromScroll) {
    5247               0 :     mSynthMouseMoveEvent.Forget();
    5248                 :   }
    5249                 : 
    5250               0 :   nsIView* rootView = mViewManager ? mViewManager->GetRootView() : nsnull;
    5251               0 :   if (mMouseLocation == nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) ||
    5252               0 :       !rootView || !rootView->HasWidget() || !mPresContext) {
    5253               0 :     mSynthMouseMoveEvent.Forget();
    5254                 :     return;
    5255                 :   }
    5256                 : 
    5257               0 :   NS_ASSERTION(mPresContext->IsRoot(), "Only a root pres shell should be here");
    5258                 : 
    5259                 :   // Hold a ref to ourselves so DispatchEvent won't destroy us (since
    5260                 :   // we need to access members after we call DispatchEvent).
    5261               0 :   nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
    5262                 :   
    5263                 : #ifdef DEBUG_MOUSE_LOCATION
    5264                 :   printf("[ps=%p]synthesizing mouse move to (%d,%d)\n",
    5265                 :          this, mMouseLocation.x, mMouseLocation.y);
    5266                 : #endif
    5267                 : 
    5268               0 :   PRInt32 APD = mPresContext->AppUnitsPerDevPixel();
    5269                 : 
    5270                 :   // We need a widget to put in the event we are going to dispatch so we look
    5271                 :   // for a view that has a widget and the mouse location is over. We first look
    5272                 :   // for floating views, if there isn't one we use the root view. |view| holds
    5273                 :   // that view.
    5274               0 :   nsIView* view = nsnull;
    5275                 : 
    5276                 :   // The appunits per devpixel ratio of |view|.
    5277                 :   PRInt32 viewAPD;
    5278                 : 
    5279                 :   // refPoint will be mMouseLocation relative to the widget of |view|, the
    5280                 :   // widget we will put in the event we dispatch, in viewAPD appunits
    5281               0 :   nsPoint refpoint(0, 0);
    5282                 : 
    5283                 :   // We always dispatch the event to the pres shell that contains the view that
    5284                 :   // the mouse is over. pointVM is the VM of that pres shell.
    5285               0 :   nsIViewManager *pointVM = nsnull;
    5286                 : 
    5287                 :   // This could be a bit slow (traverses entire view hierarchy)
    5288                 :   // but it's OK to do it once per synthetic mouse event
    5289               0 :   view = FindFloatingViewContaining(rootView, mMouseLocation);
    5290               0 :   if (!view) {
    5291               0 :     view = rootView;
    5292               0 :     nsIView *pointView = FindViewContaining(rootView, mMouseLocation);
    5293                 :     // pointView can be null in situations related to mouse capture
    5294               0 :     pointVM = (pointView ? pointView : view)->GetViewManager();
    5295               0 :     refpoint = mMouseLocation + rootView->ViewToWidgetOffset();
    5296               0 :     viewAPD = APD;
    5297                 :   } else {
    5298               0 :     pointVM = view->GetViewManager();
    5299               0 :     nsIFrame* frame = view->GetFrame();
    5300               0 :     NS_ASSERTION(frame, "floating views can't be anonymous");
    5301               0 :     viewAPD = frame->PresContext()->AppUnitsPerDevPixel();
    5302               0 :     refpoint = mMouseLocation.ConvertAppUnits(APD, viewAPD);
    5303               0 :     refpoint -= view->GetOffsetTo(rootView);
    5304               0 :     refpoint += view->ViewToWidgetOffset();
    5305                 :   }
    5306               0 :   NS_ASSERTION(view->GetWidget(), "view should have a widget here");
    5307                 :   nsMouseEvent event(true, NS_MOUSE_MOVE, view->GetWidget(),
    5308               0 :                      nsMouseEvent::eSynthesized);
    5309               0 :   event.refPoint = refpoint.ToNearestPixels(viewAPD);
    5310               0 :   event.time = PR_IntervalNow();
    5311                 :   // XXX set event.isShift, event.isControl, event.isAlt, event.isMeta ?
    5312                 : 
    5313               0 :   nsCOMPtr<nsIPresShell> shell = pointVM->GetPresShell();
    5314               0 :   if (shell) {
    5315               0 :     shell->DispatchSynthMouseMove(&event, !aFromScroll);
    5316                 :   }
    5317                 : 
    5318               0 :   if (!aFromScroll) {
    5319               0 :     mSynthMouseMoveEvent.Forget();
    5320                 :   }
    5321                 : }
    5322                 : 
    5323                 : class nsAutoNotifyDidPaint
    5324                 : {
    5325                 : public:
    5326               0 :   nsAutoNotifyDidPaint(bool aWillSendDidPaint)
    5327               0 :     : mWillSendDidPaint(aWillSendDidPaint)
    5328                 :   {
    5329               0 :   }
    5330               0 :   ~nsAutoNotifyDidPaint()
    5331                 :   {
    5332               0 :     if (!mWillSendDidPaint && nsContentUtils::XPConnect()) {
    5333               0 :       nsContentUtils::XPConnect()->NotifyDidPaint();
    5334                 :     }
    5335               0 :   }
    5336                 : 
    5337                 : private:
    5338                 :   bool mWillSendDidPaint;
    5339                 : };
    5340                 : 
    5341                 : void
    5342               0 : PresShell::Paint(nsIView*           aViewToPaint,
    5343                 :                  nsIWidget*         aWidgetToPaint,
    5344                 :                  const nsRegion&    aDirtyRegion,
    5345                 :                  const nsIntRegion& aIntDirtyRegion,
    5346                 :                  bool               aWillSendDidPaint)
    5347                 : {
    5348                 : #ifdef NS_FUNCTION_TIMER
    5349                 :   NS_TIME_FUNCTION_DECLARE_DOCURL;
    5350                 :   const nsRect& bounds__ = aDirtyRegion.GetBounds();
    5351                 :   NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (document: %s, dirty rect: (<%f, %f>, <%f, %f>)",
    5352                 :                            MOZ_FUNCTION_NAME, __LINE__, docURL__.get(),
    5353                 :                            NSCoordToFloat(bounds__.x),
    5354                 :                            NSCoordToFloat(bounds__.y),
    5355                 :                            NSCoordToFloat(bounds__.XMost()),
    5356                 :                            NSCoordToFloat(bounds__.YMost()));
    5357                 : #endif
    5358                 : 
    5359               0 :   SAMPLE_LABEL("Paint", "PresShell::Paint");
    5360               0 :   NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
    5361               0 :   NS_ASSERTION(aViewToPaint, "null view");
    5362               0 :   NS_ASSERTION(aWidgetToPaint, "Can't paint without a widget");
    5363                 : 
    5364               0 :   nsAutoNotifyDidPaint notifyDidPaint(aWillSendDidPaint);
    5365                 : 
    5366               0 :   nsPresContext* presContext = GetPresContext();
    5367               0 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(presContext, Paint);
    5368                 : 
    5369               0 :   nsIFrame* frame = aViewToPaint->GetFrame();
    5370                 : 
    5371                 :   bool isRetainingManager;
    5372                 :   LayerManager* layerManager =
    5373               0 :     aWidgetToPaint->GetLayerManager(&isRetainingManager);
    5374               0 :   NS_ASSERTION(layerManager, "Must be in paint event");
    5375               0 :   layerManager->BeginTransaction();
    5376                 : 
    5377               0 :   if (frame && isRetainingManager) {
    5378                 :     // Try to do an empty transaction, if the frame tree does not
    5379                 :     // need to be updated. Do not try to do an empty transaction on
    5380                 :     // a non-retained layer manager (like the BasicLayerManager that
    5381                 :     // draws the window title bar on Mac), because a) it won't work
    5382                 :     // and b) below we don't want to clear NS_FRAME_UPDATE_LAYER_TREE,
    5383                 :     // that will cause us to forget to update the real layer manager!
    5384               0 :     if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) {
    5385               0 :       if (layerManager->EndEmptyTransaction()) {
    5386               0 :         frame->UpdatePaintCountForPaintedPresShells();
    5387               0 :         presContext->NotifyDidPaintForSubtree();
    5388                 :         return;
    5389                 :       }
    5390                 :     }
    5391                 : 
    5392               0 :     frame->RemoveStateBits(NS_FRAME_UPDATE_LAYER_TREE);
    5393                 :   }
    5394               0 :   if (frame) {
    5395               0 :     frame->ClearPresShellsFromLastPaint();
    5396                 :   }
    5397                 : 
    5398               0 :   nscolor bgcolor = ComputeBackstopColor(aViewToPaint);
    5399                 : 
    5400               0 :   if (frame) {
    5401                 :     // Defer invalidates that are triggered during painting, and discard
    5402                 :     // invalidates of areas that are already being repainted.
    5403                 :     // The layer system can trigger invalidates during painting
    5404                 :     // (see FrameLayerBuilder).
    5405               0 :     frame->BeginDeferringInvalidatesForDisplayRoot(aDirtyRegion);
    5406                 : 
    5407                 :     // We can paint directly into the widget using its layer manager.
    5408                 :     nsLayoutUtils::PaintFrame(nsnull, frame, aDirtyRegion, bgcolor,
    5409                 :                               nsLayoutUtils::PAINT_WIDGET_LAYERS |
    5410               0 :                               nsLayoutUtils::PAINT_EXISTING_TRANSACTION);
    5411                 : 
    5412               0 :     frame->EndDeferringInvalidatesForDisplayRoot();
    5413               0 :     presContext->NotifyDidPaintForSubtree();
    5414                 :     return;
    5415                 :   }
    5416                 : 
    5417               0 :   nsRefPtr<ColorLayer> root = layerManager->CreateColorLayer();
    5418               0 :   if (root) {
    5419               0 :     nsPresContext* pc = GetPresContext();
    5420                 :     nsIntRect bounds =
    5421               0 :       pc->GetVisibleArea().ToOutsidePixels(pc->AppUnitsPerDevPixel());
    5422               0 :     bgcolor = NS_ComposeColors(bgcolor, mCanvasBackgroundColor);
    5423               0 :     root->SetColor(bgcolor);
    5424               0 :     root->SetVisibleRegion(bounds);
    5425               0 :     layerManager->SetRoot(root);
    5426                 :   }
    5427               0 :   layerManager->EndTransaction(NULL, NULL);
    5428                 : 
    5429               0 :   presContext->NotifyDidPaintForSubtree();
    5430                 : }
    5431                 : 
    5432                 : // static
    5433                 : void
    5434               0 : nsIPresShell::SetCapturingContent(nsIContent* aContent, PRUint8 aFlags)
    5435                 : {
    5436               0 :   NS_IF_RELEASE(gCaptureInfo.mContent);
    5437                 : 
    5438                 :   // only set capturing content if allowed or the CAPTURE_IGNOREALLOWED flag
    5439                 :   // is used
    5440               0 :   if ((aFlags & CAPTURE_IGNOREALLOWED) || gCaptureInfo.mAllowed) {
    5441               0 :     if (aContent) {
    5442               0 :       NS_ADDREF(gCaptureInfo.mContent = aContent);
    5443                 :     }
    5444               0 :     gCaptureInfo.mRetargetToElement = (aFlags & CAPTURE_RETARGETTOELEMENT) != 0;
    5445               0 :     gCaptureInfo.mPreventDrag = (aFlags & CAPTURE_PREVENTDRAG) != 0;
    5446                 :   }
    5447               0 : }
    5448                 : 
    5449                 : nsIFrame*
    5450               0 : PresShell::GetCurrentEventFrame()
    5451                 : {
    5452               0 :   if (NS_UNLIKELY(mIsDestroying)) {
    5453               0 :     return nsnull;
    5454                 :   }
    5455                 :     
    5456               0 :   if (!mCurrentEventFrame && mCurrentEventContent) {
    5457                 :     // Make sure the content still has a document reference. If not,
    5458                 :     // then we assume it is no longer in the content tree and the
    5459                 :     // frame shouldn't get an event, nor should we even assume its
    5460                 :     // safe to try and find the frame.
    5461               0 :     if (mCurrentEventContent->GetDocument()) {
    5462               0 :       mCurrentEventFrame = mCurrentEventContent->GetPrimaryFrame();
    5463                 :     }
    5464                 :   }
    5465                 : 
    5466               0 :   return mCurrentEventFrame;
    5467                 : }
    5468                 : 
    5469                 : nsIFrame*
    5470               0 : PresShell::GetEventTargetFrame()
    5471                 : {
    5472               0 :   return GetCurrentEventFrame();
    5473                 : }
    5474                 : 
    5475                 : already_AddRefed<nsIContent>
    5476               0 : PresShell::GetEventTargetContent(nsEvent* aEvent)
    5477                 : {
    5478               0 :   nsIContent* content = nsnull;
    5479                 : 
    5480               0 :   if (mCurrentEventContent) {
    5481               0 :     content = mCurrentEventContent;
    5482               0 :     NS_IF_ADDREF(content);
    5483                 :   } else {
    5484               0 :     nsIFrame* currentEventFrame = GetCurrentEventFrame();
    5485               0 :     if (currentEventFrame) {
    5486               0 :       currentEventFrame->GetContentForEvent(aEvent, &content);
    5487                 :     } else {
    5488               0 :       content = nsnull;
    5489                 :     }
    5490                 :   }
    5491               0 :   return content;
    5492                 : }
    5493                 : 
    5494                 : void
    5495               0 : PresShell::PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent)
    5496                 : {
    5497               0 :   if (mCurrentEventFrame || mCurrentEventContent) {
    5498               0 :     mCurrentEventFrameStack.InsertElementAt(0, mCurrentEventFrame);
    5499               0 :     mCurrentEventContentStack.InsertObjectAt(mCurrentEventContent, 0);
    5500                 :   }
    5501               0 :   mCurrentEventFrame = aFrame;
    5502               0 :   mCurrentEventContent = aContent;
    5503               0 : }
    5504                 : 
    5505                 : void
    5506               0 : PresShell::PopCurrentEventInfo()
    5507                 : {
    5508               0 :   mCurrentEventFrame = nsnull;
    5509               0 :   mCurrentEventContent = nsnull;
    5510                 : 
    5511               0 :   if (0 != mCurrentEventFrameStack.Length()) {
    5512               0 :     mCurrentEventFrame = mCurrentEventFrameStack.ElementAt(0);
    5513               0 :     mCurrentEventFrameStack.RemoveElementAt(0);
    5514               0 :     mCurrentEventContent = mCurrentEventContentStack.ObjectAt(0);
    5515               0 :     mCurrentEventContentStack.RemoveObjectAt(0);
    5516                 :   }
    5517               0 : }
    5518                 : 
    5519               0 : bool PresShell::InZombieDocument(nsIContent *aContent)
    5520                 : {
    5521                 :   // If a content node points to a null document, or the document is not
    5522                 :   // attached to a window, then it is possibly in a zombie document,
    5523                 :   // about to be replaced by a newly loading document.
    5524                 :   // Such documents cannot handle DOM events.
    5525                 :   // It might actually be in a node not attached to any document,
    5526                 :   // in which case there is not parent presshell to retarget it to.
    5527               0 :   nsIDocument *doc = aContent->GetDocument();
    5528               0 :   return !doc || !doc->GetWindow();
    5529                 : }
    5530                 : 
    5531                 : already_AddRefed<nsPIDOMWindow>
    5532               0 : PresShell::GetRootWindow()
    5533                 : {
    5534                 :   nsCOMPtr<nsPIDOMWindow> window =
    5535               0 :     do_QueryInterface(mDocument->GetWindow());
    5536               0 :   if (window) {
    5537               0 :     nsCOMPtr<nsPIDOMWindow> rootWindow = window->GetPrivateRoot();
    5538               0 :     NS_ASSERTION(rootWindow, "nsPIDOMWindow::GetPrivateRoot() returns NULL");
    5539               0 :     return rootWindow.forget();
    5540                 :   }
    5541                 : 
    5542                 :   // If we don't have DOM window, we're zombie, we should find the root window
    5543                 :   // with our parent shell.
    5544               0 :   nsCOMPtr<nsIPresShell> parent = GetParentPresShell();
    5545               0 :   NS_ENSURE_TRUE(parent, nsnull);
    5546               0 :   return parent->GetRootWindow();
    5547                 : }
    5548                 : 
    5549                 : already_AddRefed<nsIPresShell>
    5550               0 : PresShell::GetParentPresShell()
    5551                 : {
    5552               0 :   NS_ENSURE_TRUE(mPresContext, nsnull);
    5553               0 :   nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
    5554               0 :   if (!container) {
    5555               0 :     container = do_QueryReferent(mForwardingContainer);
    5556                 :   }
    5557                 : 
    5558                 :   // Now, find the parent pres shell and send the event there
    5559               0 :   nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(container);
    5560                 :   // Might have gone away, or never been around to start with
    5561               0 :   NS_ENSURE_TRUE(treeItem, nsnull);
    5562                 : 
    5563               0 :   nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
    5564               0 :   treeItem->GetParent(getter_AddRefs(parentTreeItem));
    5565               0 :   nsCOMPtr<nsIDocShell> parentDocShell = do_QueryInterface(parentTreeItem);
    5566               0 :   NS_ENSURE_TRUE(parentDocShell && treeItem != parentTreeItem, nsnull);
    5567                 : 
    5568               0 :   nsIPresShell* parentPresShell = nsnull;
    5569               0 :   parentDocShell->GetPresShell(&parentPresShell);
    5570               0 :   return parentPresShell;
    5571                 : }
    5572                 : 
    5573                 : nsresult
    5574               0 : PresShell::RetargetEventToParent(nsGUIEvent*     aEvent,
    5575                 :                                  nsEventStatus*  aEventStatus)
    5576                 : {
    5577                 :   // Send this events straight up to the parent pres shell.
    5578                 :   // We do this for keystroke events in zombie documents or if either a frame
    5579                 :   // or a root content is not present.
    5580                 :   // That way at least the UI key bindings can work.
    5581                 : 
    5582               0 :   nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
    5583               0 :   nsCOMPtr<nsIPresShell> parentPresShell = GetParentPresShell();
    5584               0 :   NS_ENSURE_TRUE(parentPresShell, NS_ERROR_FAILURE);
    5585                 : 
    5586                 :   // Fake the event as though it's from the parent pres shell's root frame.
    5587               0 :   return parentPresShell->HandleEvent(parentPresShell->GetRootFrame(), aEvent, true, aEventStatus);
    5588                 : }
    5589                 : 
    5590                 : void
    5591               0 : PresShell::DisableNonTestMouseEvents(bool aDisable)
    5592                 : {
    5593               0 :   sDisableNonTestMouseEvents = aDisable;
    5594               0 : }
    5595                 : 
    5596                 : already_AddRefed<nsPIDOMWindow>
    5597               0 : PresShell::GetFocusedDOMWindowInOurWindow()
    5598                 : {
    5599               0 :   nsCOMPtr<nsPIDOMWindow> rootWindow = GetRootWindow();
    5600               0 :   NS_ENSURE_TRUE(rootWindow, nsnull);
    5601                 :   nsPIDOMWindow* focusedWindow;
    5602               0 :   nsFocusManager::GetFocusedDescendant(rootWindow, true, &focusedWindow);
    5603               0 :   return focusedWindow;
    5604                 : }
    5605                 : 
    5606                 : void
    5607               0 : PresShell::RecordMouseLocation(nsGUIEvent* aEvent)
    5608                 : {
    5609               0 :   if (!mPresContext)
    5610               0 :     return;
    5611                 : 
    5612               0 :   if (!mPresContext->IsRoot()) {
    5613               0 :     PresShell* rootPresShell = GetRootPresShell();
    5614               0 :     if (rootPresShell) {
    5615               0 :       rootPresShell->RecordMouseLocation(aEvent);
    5616                 :     }
    5617               0 :     return;
    5618                 :   }
    5619                 : 
    5620               0 :   if ((aEvent->message == NS_MOUSE_MOVE &&
    5621                 :        static_cast<nsMouseEvent*>(aEvent)->reason == nsMouseEvent::eReal) ||
    5622                 :       aEvent->message == NS_MOUSE_ENTER ||
    5623                 :       aEvent->message == NS_MOUSE_BUTTON_DOWN ||
    5624                 :       aEvent->message == NS_MOUSE_BUTTON_UP) {
    5625               0 :     nsIFrame* rootFrame = GetRootFrame();
    5626               0 :     if (!rootFrame) {
    5627               0 :       nsIView* rootView = mViewManager->GetRootView();
    5628                 :       mMouseLocation = nsLayoutUtils::TranslateWidgetToView(mPresContext,
    5629               0 :         aEvent->widget, aEvent->refPoint, rootView);
    5630                 :     } else {
    5631                 :       mMouseLocation =
    5632               0 :         nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, rootFrame);
    5633                 :     }
    5634                 : #ifdef DEBUG_MOUSE_LOCATION
    5635                 :     if (aEvent->message == NS_MOUSE_ENTER)
    5636                 :       printf("[ps=%p]got mouse enter for %p\n",
    5637                 :              this, aEvent->widget);
    5638                 :     printf("[ps=%p]setting mouse location to (%d,%d)\n",
    5639                 :            this, mMouseLocation.x, mMouseLocation.y);
    5640                 : #endif
    5641               0 :     if (aEvent->message == NS_MOUSE_ENTER)
    5642               0 :       SynthesizeMouseMove(false);
    5643               0 :   } else if (aEvent->message == NS_MOUSE_EXIT) {
    5644                 :     // Although we only care about the mouse moving into an area for which this
    5645                 :     // pres shell doesn't receive mouse move events, we don't check which widget
    5646                 :     // the mouse exit was for since this seems to vary by platform.  Hopefully
    5647                 :     // this won't matter at all since we'll get the mouse move or enter after
    5648                 :     // the mouse exit when the mouse moves from one of our widgets into another.
    5649               0 :     mMouseLocation = nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
    5650                 : #ifdef DEBUG_MOUSE_LOCATION
    5651                 :     printf("[ps=%p]got mouse exit for %p\n",
    5652                 :            this, aEvent->widget);
    5653                 :     printf("[ps=%p]clearing mouse location\n",
    5654                 :            this);
    5655                 : #endif
    5656                 :   }
    5657                 : }
    5658                 : 
    5659                 : #ifdef MOZ_TOUCH
    5660                 : static void
    5661                 : EvictTouchPoint(nsCOMPtr<nsIDOMTouch>& aTouch)
    5662                 : {
    5663                 :   nsIWidget *widget = nsnull;
    5664                 :   // is there an easier/better way to dig out the widget?
    5665                 :   nsCOMPtr<nsINode> node(do_QueryInterface(aTouch->GetTarget()));
    5666                 :   if (!node) {
    5667                 :     return;
    5668                 :   }
    5669                 :   nsIDocument* doc = node->GetCurrentDoc();
    5670                 :   if (!doc) {
    5671                 :     return;
    5672                 :   }
    5673                 :   nsIPresShell *presShell = doc->GetShell();
    5674                 :   if (!presShell) {
    5675                 :     return;
    5676                 :   }
    5677                 :   nsIFrame* frame = presShell->GetRootFrame();
    5678                 :   if (!frame) {
    5679                 :     return;
    5680                 :   }
    5681                 :   nsPoint *pt = new nsPoint(aTouch->mRefPoint.x, aTouch->mRefPoint.y);
    5682                 :   widget = frame->GetView()->GetNearestWidget(pt);
    5683                 :   if (!widget) {
    5684                 :     return;
    5685                 :   }
    5686                 :   nsTouchEvent event(true, NS_TOUCH_END, widget);
    5687                 :   event.isShift = false;
    5688                 :   event.isControl = false;
    5689                 :   event.isAlt = false;
    5690                 :   event.isMeta = false;
    5691                 :   event.widget = widget;
    5692                 :   event.time = PR_IntervalNow();
    5693                 :   event.touches.AppendElement(aTouch);
    5694                 : 
    5695                 :   nsEventStatus status;
    5696                 :   widget->DispatchEvent(&event, status);
    5697                 : }
    5698                 : 
    5699                 : static PLDHashOperator
    5700                 : AppendToTouchList(const PRUint32& aKey, nsCOMPtr<nsIDOMTouch>& aData, void *aTouchList)
    5701                 : {
    5702                 :   nsTArray<nsCOMPtr<nsIDOMTouch> > *touches = static_cast<nsTArray<nsCOMPtr<nsIDOMTouch> > *>(aTouchList);
    5703                 :   aData->mChanged = false;
    5704                 :   touches->AppendElement(aData);
    5705                 :   return PL_DHASH_NEXT;
    5706                 : }
    5707                 : #endif // MOZ_TOUCH
    5708                 : 
    5709                 : nsresult
    5710               0 : PresShell::HandleEvent(nsIFrame        *aFrame,
    5711                 :                        nsGUIEvent*     aEvent,
    5712                 :                        bool            aDontRetargetEvents,
    5713                 :                        nsEventStatus*  aEventStatus)
    5714                 : {
    5715               0 :   NS_ASSERTION(aFrame, "null frame");
    5716                 : 
    5717               0 :   if (mIsDestroying ||
    5718                 :       (sDisableNonTestMouseEvents && NS_IS_MOUSE_EVENT(aEvent) &&
    5719               0 :        !(aEvent->flags & NS_EVENT_FLAG_SYNTHETIC_TEST_EVENT))) {
    5720               0 :     return NS_OK;
    5721                 :   }
    5722                 : 
    5723               0 :   RecordMouseLocation(aEvent);
    5724                 : 
    5725                 : #ifdef ACCESSIBILITY
    5726               0 :   if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT) {
    5727                 :     NS_TIME_FUNCTION_MIN(1.0);
    5728                 : 
    5729                 :     // Accessibility events come through OS requests and not from scripts,
    5730                 :     // so it is safe to handle here
    5731               0 :     return HandleEventInternal(aEvent, aEventStatus);
    5732                 :   }
    5733                 : #endif
    5734                 : 
    5735               0 :   if (!nsContentUtils::IsSafeToRunScript())
    5736               0 :     return NS_OK;
    5737                 : 
    5738                 :   NS_TIME_FUNCTION_MIN(1.0);
    5739                 : 
    5740                 :   nsIContent* capturingContent =
    5741               0 :     NS_IS_MOUSE_EVENT(aEvent) ? GetCapturingContent() : nsnull;
    5742                 : 
    5743               0 :   nsCOMPtr<nsIDocument> retargetEventDoc;
    5744               0 :   if (!aDontRetargetEvents) {
    5745                 :     // key and IME related events should not cross top level window boundary.
    5746                 :     // Basically, such input events should be fired only on focused widget.
    5747                 :     // However, some IMEs might need to clean up composition after focused
    5748                 :     // window is deactivated.  And also some tests on MozMill want to test key
    5749                 :     // handling on deactivated window because MozMill window can be activated
    5750                 :     // during tests.  So, there is no merit the events should be redirected to
    5751                 :     // active window.  So, the events should be handled on the last focused
    5752                 :     // content in the last focused DOM window in same top level window.
    5753                 :     // Note, if no DOM window has been focused yet, we can discard the events.
    5754               0 :     if (NS_IsEventTargetedAtFocusedWindow(aEvent)) {
    5755               0 :       nsCOMPtr<nsPIDOMWindow> window = GetFocusedDOMWindowInOurWindow();
    5756                 :       // No DOM window in same top level window has not been focused yet,
    5757                 :       // discard the events.
    5758               0 :       if (!window) {
    5759               0 :         return NS_OK;
    5760                 :       }
    5761                 : 
    5762               0 :       retargetEventDoc = do_QueryInterface(window->GetExtantDocument());
    5763               0 :       if (!retargetEventDoc)
    5764               0 :         return NS_OK;
    5765               0 :     } else if (capturingContent) {
    5766                 :       // if the mouse is being captured then retarget the mouse event at the
    5767                 :       // document that is being captured.
    5768               0 :       retargetEventDoc = capturingContent->GetCurrentDoc();
    5769                 :     }
    5770                 : 
    5771               0 :     if (retargetEventDoc) {
    5772               0 :       nsCOMPtr<nsIPresShell> presShell = retargetEventDoc->GetShell();
    5773               0 :       if (!presShell)
    5774               0 :         return NS_OK;
    5775                 : 
    5776               0 :       if (presShell != this) {
    5777               0 :         nsIFrame* frame = presShell->GetRootFrame();
    5778               0 :         if (!frame) {
    5779               0 :           if (aEvent->message == NS_QUERY_TEXT_CONTENT ||
    5780                 :               NS_IS_CONTENT_COMMAND_EVENT(aEvent)) {
    5781               0 :             return NS_OK;
    5782                 :           }
    5783                 : 
    5784               0 :           nsIView* view = presShell->GetViewManager()->GetRootView();
    5785               0 :           while (view && !view->GetFrame()) {
    5786               0 :             view = view->GetParent();
    5787                 :           }
    5788                 : 
    5789               0 :           if (view) {
    5790               0 :             frame = view->GetFrame();
    5791                 :           }
    5792                 :         }
    5793                 : 
    5794               0 :         if (!frame)
    5795               0 :           return NS_OK;
    5796                 : 
    5797               0 :         nsCOMPtr<nsIPresShell> shell = frame->PresContext()->GetPresShell();
    5798               0 :         return shell->HandleEvent(frame, aEvent, true, aEventStatus);
    5799                 :       }
    5800                 :     }
    5801                 :   }
    5802                 : 
    5803                 :   // Check for a theme change up front, since the frame type is irrelevant
    5804               0 :   if (aEvent->message == NS_THEMECHANGED && mPresContext) {
    5805               0 :     mPresContext->ThemeChanged();
    5806               0 :     return NS_OK;
    5807                 :   }
    5808                 : 
    5809               0 :   if (aEvent->message == NS_UISTATECHANGED && mDocument) {
    5810               0 :     nsPIDOMWindow* win = mDocument->GetWindow();
    5811               0 :     if (win) {
    5812               0 :       nsUIStateChangeEvent* event = (nsUIStateChangeEvent*)aEvent;
    5813               0 :       win->SetKeyboardIndicators(event->showAccelerators, event->showFocusRings);
    5814                 :     }
    5815               0 :     return NS_OK;
    5816                 :   }
    5817                 : 
    5818                 :   // Check for a system color change up front, since the frame type is
    5819                 :   // irrelevant
    5820               0 :   if ((aEvent->message == NS_SYSCOLORCHANGED) && mPresContext &&
    5821               0 :       aFrame == mFrameConstructor->GetRootFrame()) {
    5822               0 :     *aEventStatus = nsEventStatus_eConsumeDoDefault;
    5823               0 :     mPresContext->SysColorChanged();
    5824               0 :     return NS_OK;
    5825                 :   }
    5826                 : 
    5827               0 :   if (aEvent->eventStructType == NS_KEY_EVENT &&
    5828               0 :       mDocument && mDocument->EventHandlingSuppressed()) {
    5829               0 :     if (aEvent->message == NS_KEY_DOWN) {
    5830               0 :       mNoDelayedKeyEvents = true;
    5831               0 :     } else if (!mNoDelayedKeyEvents) {
    5832                 :       nsDelayedEvent* event =
    5833               0 :         new nsDelayedKeyEvent(static_cast<nsKeyEvent*>(aEvent));
    5834               0 :       if (!mDelayedEvents.AppendElement(event)) {
    5835               0 :         delete event;
    5836                 :       }
    5837                 :     }
    5838               0 :     return NS_OK;
    5839                 :   }
    5840                 : 
    5841               0 :   nsIFrame* frame = aFrame;
    5842               0 :   bool dispatchUsingCoordinates = NS_IsEventUsingCoordinates(aEvent);
    5843               0 :   if (dispatchUsingCoordinates) {
    5844               0 :     NS_WARN_IF_FALSE(frame, "Nothing to handle this event!");
    5845               0 :     if (!frame)
    5846               0 :       return NS_OK;
    5847                 : 
    5848               0 :     nsPresContext* framePresContext = frame->PresContext();
    5849               0 :     nsPresContext* rootPresContext = framePresContext->GetRootPresContext();
    5850               0 :     NS_ASSERTION(rootPresContext == mPresContext->GetRootPresContext(),
    5851                 :                  "How did we end up outside the connected prescontext/viewmanager hierarchy?"); 
    5852                 :     // If we aren't starting our event dispatch from the root frame of the root prescontext,
    5853                 :     // then someone must be capturing the mouse. In that case we don't want to search the popup
    5854                 :     // list.
    5855               0 :     if (framePresContext == rootPresContext &&
    5856               0 :         frame == mFrameConstructor->GetRootFrame()) {
    5857                 :       nsIFrame* popupFrame =
    5858               0 :         nsLayoutUtils::GetPopupFrameForEventCoordinates(rootPresContext, aEvent);
    5859                 :       // If the popupFrame is an ancestor of the 'frame', the frame should
    5860                 :       // handle the event, otherwise, the popup should handle it.
    5861               0 :       if (popupFrame &&
    5862                 :           !nsContentUtils::ContentIsCrossDocDescendantOf(
    5863               0 :              framePresContext->GetPresShell()->GetDocument(),
    5864               0 :              popupFrame->GetContent())) {
    5865               0 :         frame = popupFrame;
    5866                 :       }
    5867                 :     }
    5868                 : 
    5869               0 :     bool captureRetarget = false;
    5870               0 :     if (capturingContent) {
    5871                 :       // If a capture is active, determine if the docshell is visible. If not,
    5872                 :       // clear the capture and target the mouse event normally instead. This
    5873                 :       // would occur if the mouse button is held down while a tab change occurs.
    5874                 :       // If the docshell is visible, look for a scrolling container.
    5875                 :       bool vis;
    5876               0 :       nsCOMPtr<nsISupports> supports = mPresContext->GetContainer();
    5877               0 :       nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(supports));
    5878               0 :       if (baseWin && NS_SUCCEEDED(baseWin->GetVisibility(&vis)) && vis) {
    5879               0 :         captureRetarget = gCaptureInfo.mRetargetToElement;
    5880               0 :         if (!captureRetarget) {
    5881                 :           // A check was already done above to ensure that capturingContent is
    5882                 :           // in this presshell.
    5883               0 :           NS_ASSERTION(capturingContent->GetCurrentDoc() == GetDocument(),
    5884                 :                        "Unexpected document");
    5885               0 :           nsIFrame* captureFrame = capturingContent->GetPrimaryFrame();
    5886               0 :           if (captureFrame) {
    5887               0 :             if (capturingContent->Tag() == nsGkAtoms::select &&
    5888               0 :                 capturingContent->IsHTML()) {
    5889                 :               // a dropdown <select> has a child in its selectPopupList and we should
    5890                 :               // capture on that instead.
    5891               0 :               nsIFrame* childFrame = captureFrame->GetChildList(nsIFrame::kSelectPopupList).FirstChild();
    5892               0 :               if (childFrame) {
    5893               0 :                 captureFrame = childFrame;
    5894                 :               }
    5895                 :             }
    5896                 : 
    5897                 :             // scrollable frames should use the scrolling container as
    5898                 :             // the root instead of the document
    5899               0 :             nsIScrollableFrame* scrollFrame = do_QueryFrame(captureFrame);
    5900               0 :             if (scrollFrame) {
    5901               0 :               frame = scrollFrame->GetScrolledFrame();
    5902                 :             }
    5903                 :           }
    5904                 :         }
    5905                 :       }
    5906                 :       else {
    5907               0 :         ClearMouseCapture(nsnull);
    5908               0 :         capturingContent = nsnull;
    5909                 :       }
    5910                 :     }
    5911                 : 
    5912                 :     bool isWindowLevelMouseExit = (aEvent->message == NS_MOUSE_EXIT) &&
    5913               0 :       (static_cast<nsMouseEvent*>(aEvent)->exit == nsMouseEvent::eTopLevel);
    5914                 : 
    5915                 :     // Get the frame at the event point. However, don't do this if we're
    5916                 :     // capturing and retargeting the event because the captured frame will
    5917                 :     // be used instead below. Also keep using the root frame if we're dealing
    5918                 :     // with a window-level mouse exit event since we want to start sending
    5919                 :     // mouse out events at the root EventStateManager.
    5920               0 :     if (!captureRetarget && !isWindowLevelMouseExit) {
    5921                 : #ifdef MOZ_TOUCH
    5922                 :       nsPoint eventPoint;
    5923                 :       if (aEvent->message == NS_TOUCH_START) {
    5924                 :         // Add any new touches to the queue
    5925                 :         nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
    5926                 :         // if there is only one touch in this touchstart event, assume that it is
    5927                 :         // the start of a new touch session and evict any old touches in the
    5928                 :         // queue
    5929                 :         if (touchEvent->touches.Length() == 1) {
    5930                 :           nsTArray<nsCOMPtr<nsIDOMTouch> > touches;
    5931                 :           gCaptureTouchList.Enumerate(&AppendToTouchList, (void *)&touches);
    5932                 :           for (PRUint32 i = 0; i < touches.Length(); ++i) {
    5933                 :             EvictTouchPoint(touches[i]);
    5934                 :           }
    5935                 :         }
    5936                 :         for (PRUint32 i = 0; i < touchEvent->touches.Length(); ++i) {
    5937                 :           nsIDOMTouch *touch = touchEvent->touches[i];
    5938                 :           nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
    5939                 :           touch->mMessage = aEvent->message;
    5940                 : 
    5941                 :           PRInt32 id = 0;
    5942                 :           touch->GetIdentifier(&id);
    5943                 :           if (!gCaptureTouchList.Get(id, nsnull)) {
    5944                 :             // This event is a new touch. Mark it as a changedTouch and
    5945                 :             // add it to the queue.
    5946                 :             touch->mChanged = true;
    5947                 :             gCaptureTouchList.Put(id, touch);
    5948                 : 
    5949                 :             eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, touch->mRefPoint, frame);
    5950                 :           } else {
    5951                 :             // This touch is an old touch, we need to ensure that is not
    5952                 :             // marked as changed and set its target correctly
    5953                 :             touch->mChanged = false;
    5954                 :             PRInt32 id;
    5955                 :             touch->GetIdentifier(&id);
    5956                 : 
    5957                 :             nsCOMPtr<nsIDOMTouch> oldTouch;
    5958                 :             gCaptureTouchList.Get(id, getter_AddRefs(oldTouch));
    5959                 :             if (oldTouch) {
    5960                 :               nsCOMPtr<nsPIDOMEventTarget> targetPtr;
    5961                 :               oldTouch->GetTarget(getter_AddRefs(targetPtr));
    5962                 :               domtouch->SetTarget(targetPtr);
    5963                 :               gCaptureTouchList.Put(id, touch);
    5964                 :             }
    5965                 :           }
    5966                 :         }
    5967                 :       } else {
    5968                 :         eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
    5969                 :       }
    5970                 : #else
    5971                 :       nsPoint eventPoint
    5972               0 :           = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
    5973                 : #endif
    5974                 :       {
    5975               0 :         bool ignoreRootScrollFrame = false;
    5976               0 :         if (aEvent->eventStructType == NS_MOUSE_EVENT) {
    5977               0 :           ignoreRootScrollFrame = static_cast<nsMouseEvent*>(aEvent)->ignoreRootScrollFrame;
    5978                 :         }
    5979                 :         nsIFrame* target = nsLayoutUtils::GetFrameForPoint(frame, eventPoint,
    5980               0 :                                                            false, ignoreRootScrollFrame);
    5981               0 :         if (target) {
    5982               0 :           frame = target;
    5983                 :         }
    5984                 :       }
    5985                 :     }
    5986                 : 
    5987                 :     // if a node is capturing the mouse, check if the event needs to be
    5988                 :     // retargeted at the capturing content instead. This will be the case when
    5989                 :     // capture retargeting is being used, no frame was found or the frame's
    5990                 :     // content is not a descendant of the capturing content.
    5991               0 :     if (capturingContent &&
    5992               0 :         (gCaptureInfo.mRetargetToElement || !frame->GetContent() ||
    5993               0 :          !nsContentUtils::ContentIsCrossDocDescendantOf(frame->GetContent(),
    5994               0 :                                                         capturingContent))) {
    5995                 :       // A check was already done above to ensure that capturingContent is
    5996                 :       // in this presshell.
    5997               0 :       NS_ASSERTION(capturingContent->GetCurrentDoc() == GetDocument(),
    5998                 :                    "Unexpected document");
    5999               0 :       nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
    6000               0 :       if (capturingFrame) {
    6001               0 :         frame = capturingFrame;
    6002                 :       }
    6003                 :     }
    6004                 : 
    6005                 :     // Suppress mouse event if it's being targeted at an element inside
    6006                 :     // a document which needs events suppressed
    6007               0 :     if (aEvent->eventStructType == NS_MOUSE_EVENT &&
    6008               0 :         frame->PresContext()->Document()->EventHandlingSuppressed()) {
    6009               0 :       if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
    6010               0 :         mNoDelayedMouseEvents = true;
    6011               0 :       } else if (!mNoDelayedMouseEvents && aEvent->message == NS_MOUSE_BUTTON_UP) {
    6012                 :         nsDelayedEvent* event =
    6013               0 :           new nsDelayedMouseEvent(static_cast<nsMouseEvent*>(aEvent));
    6014               0 :         if (!mDelayedEvents.AppendElement(event)) {
    6015               0 :           delete event;
    6016                 :         }
    6017                 :       }
    6018                 : 
    6019               0 :       return NS_OK;
    6020                 :     }
    6021                 : 
    6022                 :     PresShell* shell =
    6023               0 :         static_cast<PresShell*>(frame->PresContext()->PresShell());
    6024                 : 
    6025                 :     // Check if we have an active EventStateManager which isn't the
    6026                 :     // EventStateManager of the current PresContext.
    6027                 :     // If that is the case, and mouse is over some ancestor document,
    6028                 :     // forward event handling to the active document.
    6029                 :     // This way content can get mouse events even when
    6030                 :     // mouse is over the chrome or outside the window.
    6031                 :     //
    6032                 :     // Note, currently for backwards compatibility we don't forward mouse events
    6033                 :     // to the active document when mouse is over some subdocument.
    6034                 :     nsEventStateManager* activeESM =
    6035               0 :       nsEventStateManager::GetActiveEventStateManager();
    6036               0 :     if (activeESM && NS_IS_MOUSE_EVENT(aEvent) &&
    6037               0 :         activeESM != shell->GetPresContext()->EventStateManager() &&
    6038               0 :         static_cast<nsEventStateManager*>(activeESM)->GetPresContext()) {
    6039                 :       nsIPresShell* activeShell =
    6040               0 :         static_cast<nsEventStateManager*>(activeESM)->GetPresContext()->GetPresShell();
    6041               0 :       if (activeShell &&
    6042               0 :           nsContentUtils::ContentIsCrossDocDescendantOf(activeShell->GetDocument(),
    6043               0 :                                                         shell->GetDocument())) {
    6044               0 :         shell = static_cast<PresShell*>(activeShell);
    6045               0 :         frame = shell->GetRootFrame();
    6046                 :       }
    6047                 :     }
    6048                 : 
    6049               0 :     if (shell != this) {
    6050                 :       // Handle the event in the correct shell.
    6051                 :       // Prevent deletion until we're done with event handling (bug 336582).
    6052               0 :       nsCOMPtr<nsIPresShell> kungFuDeathGrip(shell);
    6053                 :       // We pass the subshell's root frame as the frame to start from. This is
    6054                 :       // the only correct alternative; if the event was captured then it
    6055                 :       // must have been captured by us or some ancestor shell and we
    6056                 :       // now ask the subshell to dispatch it normally.
    6057               0 :       return shell->HandlePositionedEvent(frame, aEvent, aEventStatus);
    6058                 :     }
    6059                 : 
    6060               0 :     return HandlePositionedEvent(frame, aEvent, aEventStatus);
    6061                 :   }
    6062                 :   
    6063               0 :   nsresult rv = NS_OK;
    6064                 :   
    6065               0 :   if (frame) {
    6066               0 :     PushCurrentEventInfo(nsnull, nsnull);
    6067                 : 
    6068                 :     // key and IME related events go to the focused frame in this DOM window.
    6069               0 :     if (NS_IsEventTargetedAtFocusedContent(aEvent)) {
    6070               0 :       mCurrentEventContent = nsnull;
    6071                 : 
    6072                 :       nsCOMPtr<nsPIDOMWindow> window =
    6073               0 :         do_QueryInterface(mDocument->GetWindow());
    6074               0 :       nsCOMPtr<nsPIDOMWindow> focusedWindow;
    6075                 :       nsCOMPtr<nsIContent> eventTarget =
    6076                 :         nsFocusManager::GetFocusedDescendant(window, false,
    6077               0 :                                              getter_AddRefs(focusedWindow));
    6078                 : 
    6079                 :       // otherwise, if there is no focused content or the focused content has
    6080                 :       // no frame, just use the root content. This ensures that key events
    6081                 :       // still get sent to the window properly if nothing is focused or if a
    6082                 :       // frame goes away while it is focused.
    6083               0 :       if (!eventTarget || !eventTarget->GetPrimaryFrame()) {
    6084               0 :         nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
    6085               0 :         if (htmlDoc) {
    6086               0 :           nsCOMPtr<nsIDOMHTMLElement> body;
    6087               0 :           htmlDoc->GetBody(getter_AddRefs(body));
    6088               0 :           eventTarget = do_QueryInterface(body);
    6089               0 :           if (!eventTarget) {
    6090               0 :             eventTarget = mDocument->GetRootElement();
    6091                 :           }
    6092                 :         } else {
    6093               0 :           eventTarget = mDocument->GetRootElement();
    6094                 :         }
    6095                 :       }
    6096                 : 
    6097               0 :       if (aEvent->message == NS_KEY_DOWN) {
    6098               0 :         NS_IF_RELEASE(gKeyDownTarget);
    6099               0 :         NS_IF_ADDREF(gKeyDownTarget = eventTarget);
    6100                 :       }
    6101               0 :       else if ((aEvent->message == NS_KEY_PRESS || aEvent->message == NS_KEY_UP) &&
    6102                 :                gKeyDownTarget) {
    6103                 :         // If a different element is now focused for the keypress/keyup event
    6104                 :         // than what was focused during the keydown event, check if the new
    6105                 :         // focused element is not in a chrome document any more, and if so,
    6106                 :         // retarget the event back at the keydown target. This prevents a
    6107                 :         // content area from grabbing the focus from chrome in-between key
    6108                 :         // events.
    6109               0 :         if (eventTarget &&
    6110               0 :             nsContentUtils::IsChromeDoc(gKeyDownTarget->GetCurrentDoc()) !=
    6111               0 :             nsContentUtils::IsChromeDoc(eventTarget->GetCurrentDoc())) {
    6112               0 :           eventTarget = gKeyDownTarget;
    6113                 :         }
    6114                 : 
    6115               0 :         if (aEvent->message == NS_KEY_UP) {
    6116               0 :           NS_RELEASE(gKeyDownTarget);
    6117                 :         }
    6118                 :       }
    6119                 : 
    6120               0 :       mCurrentEventFrame = nsnull;
    6121               0 :       nsIDocument* targetDoc = eventTarget ? eventTarget->OwnerDoc() : nsnull;
    6122               0 :       if (targetDoc && targetDoc != mDocument) {
    6123               0 :         PopCurrentEventInfo();
    6124               0 :         nsCOMPtr<nsIPresShell> shell = targetDoc->GetShell();
    6125               0 :         if (shell) {
    6126               0 :           rv = static_cast<PresShell*>(shell.get())->
    6127               0 :             HandleRetargetedEvent(aEvent, aEventStatus, eventTarget);
    6128                 :         }
    6129               0 :         return rv;
    6130                 :       } else {
    6131               0 :         mCurrentEventContent = eventTarget;
    6132                 :       }
    6133                 :         
    6134               0 :       if (!mCurrentEventContent || !GetCurrentEventFrame() ||
    6135               0 :           InZombieDocument(mCurrentEventContent)) {
    6136               0 :         rv = RetargetEventToParent(aEvent, aEventStatus);
    6137               0 :         PopCurrentEventInfo();
    6138               0 :         return rv;
    6139                 :       }
    6140                 :     } else {
    6141               0 :       mCurrentEventFrame = frame;
    6142                 :     }
    6143               0 :     if (GetCurrentEventFrame()) {
    6144               0 :       rv = HandleEventInternal(aEvent, aEventStatus);
    6145                 :     }
    6146                 :   
    6147                 : #ifdef NS_DEBUG
    6148               0 :     ShowEventTargetDebug();
    6149                 : #endif
    6150               0 :     PopCurrentEventInfo();
    6151                 :   } else {
    6152                 :     // Activation events need to be dispatched even if no frame was found, since
    6153                 :     // we don't want the focus to be out of sync.
    6154                 : 
    6155               0 :     if (!NS_EVENT_NEEDS_FRAME(aEvent)) {
    6156               0 :       mCurrentEventFrame = nsnull;
    6157               0 :       return HandleEventInternal(aEvent, aEventStatus);
    6158                 :     }
    6159               0 :     else if (NS_IS_KEY_EVENT(aEvent)) {
    6160                 :       // Keypress events in new blank tabs should not be completely thrown away.
    6161                 :       // Retarget them -- the parent chrome shell might make use of them.
    6162               0 :       return RetargetEventToParent(aEvent, aEventStatus);
    6163                 :     }
    6164                 :   }
    6165                 : 
    6166               0 :   return rv;
    6167                 : }
    6168                 : 
    6169                 : #ifdef NS_DEBUG
    6170                 : void
    6171               0 : PresShell::ShowEventTargetDebug()
    6172                 : {
    6173               0 :   if (nsFrame::GetShowEventTargetFrameBorder() &&
    6174               0 :       GetCurrentEventFrame()) {
    6175               0 :     if (mDrawEventTargetFrame) {
    6176                 :       mDrawEventTargetFrame->Invalidate(
    6177               0 :           nsRect(nsPoint(0, 0), mDrawEventTargetFrame->GetSize()));
    6178                 :     }
    6179                 : 
    6180               0 :     mDrawEventTargetFrame = mCurrentEventFrame;
    6181                 :     mDrawEventTargetFrame->Invalidate(
    6182               0 :         nsRect(nsPoint(0, 0), mDrawEventTargetFrame->GetSize()));
    6183                 :   }
    6184               0 : }
    6185                 : #endif
    6186                 : 
    6187                 : nsresult
    6188               0 : PresShell::HandlePositionedEvent(nsIFrame*      aTargetFrame,
    6189                 :                                  nsGUIEvent*    aEvent,
    6190                 :                                  nsEventStatus* aEventStatus)
    6191                 : {
    6192               0 :   nsresult rv = NS_OK;
    6193                 :   
    6194               0 :   PushCurrentEventInfo(nsnull, nsnull);
    6195                 :   
    6196               0 :   mCurrentEventFrame = aTargetFrame;
    6197                 : 
    6198               0 :   if (mCurrentEventFrame) {
    6199               0 :     nsCOMPtr<nsIContent> targetElement;
    6200                 :     mCurrentEventFrame->GetContentForEvent(aEvent,
    6201               0 :                                            getter_AddRefs(targetElement));
    6202                 : 
    6203                 :     // If there is no content for this frame, target it anyway.  Some
    6204                 :     // frames can be targeted but do not have content, particularly
    6205                 :     // windows with scrolling off.
    6206               0 :     if (targetElement) {
    6207                 :       // Bug 103055, bug 185889: mouse events apply to *elements*, not all
    6208                 :       // nodes.  Thus we get the nearest element parent here.
    6209                 :       // XXX we leave the frame the same even if we find an element
    6210                 :       // parent, so that the text frame will receive the event (selection
    6211                 :       // and friends are the ones who care about that anyway)
    6212                 :       //
    6213                 :       // We use weak pointers because during this tight loop, the node
    6214                 :       // will *not* go away.  And this happens on every mousemove.
    6215               0 :       while (targetElement && !targetElement->IsElement()) {
    6216               0 :         targetElement = targetElement->GetParent();
    6217                 :       }
    6218                 : 
    6219                 :       // If we found an element, target it.  Otherwise, target *nothing*.
    6220               0 :       if (!targetElement) {
    6221               0 :         mCurrentEventContent = nsnull;
    6222               0 :         mCurrentEventFrame = nsnull;
    6223               0 :       } else if (targetElement != mCurrentEventContent) {
    6224               0 :         mCurrentEventContent = targetElement;
    6225                 :       }
    6226                 :     }
    6227                 :   }
    6228                 : 
    6229               0 :   if (GetCurrentEventFrame()) {
    6230               0 :     rv = HandleEventInternal(aEvent, aEventStatus);
    6231                 :   }
    6232                 : 
    6233                 : #ifdef NS_DEBUG
    6234               0 :   ShowEventTargetDebug();
    6235                 : #endif
    6236               0 :   PopCurrentEventInfo();
    6237               0 :   return rv;
    6238                 : }
    6239                 : 
    6240                 : nsresult
    6241               0 : PresShell::HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame,
    6242                 :                                  nsIContent* aContent, nsEventStatus* aStatus)
    6243                 : {
    6244               0 :   PushCurrentEventInfo(aFrame, aContent);
    6245               0 :   nsresult rv = HandleEventInternal(aEvent, aStatus);
    6246               0 :   PopCurrentEventInfo();
    6247               0 :   return rv;
    6248                 : }
    6249                 : 
    6250                 : static inline bool
    6251               0 : IsSynthesizedMouseEvent(nsEvent* aEvent)
    6252                 : {
    6253                 :   return aEvent->eventStructType == NS_MOUSE_EVENT &&
    6254               0 :          static_cast<nsMouseEvent*>(aEvent)->reason != nsMouseEvent::eReal;
    6255                 : }
    6256                 : 
    6257               0 : static bool CanHandleContextMenuEvent(nsMouseEvent* aMouseEvent,
    6258                 :                                         nsIFrame* aFrame)
    6259                 : {
    6260                 : #if defined(XP_MACOSX) && defined(MOZ_XUL)
    6261                 :   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
    6262                 :   if (pm) {
    6263                 :     nsIFrame* popupFrame = pm->GetTopPopup(ePopupTypeMenu);
    6264                 :     if (popupFrame) {
    6265                 :       // context menus should not be opened while another menu is open on Mac,
    6266                 :       // so return false so that the event is not fired.
    6267                 :       if (aMouseEvent->context == nsMouseEvent::eContextMenuKey) {
    6268                 :         return false;
    6269                 :       } else if (aMouseEvent->widget) {
    6270                 :          nsWindowType windowType;
    6271                 :          aMouseEvent->widget->GetWindowType(windowType);
    6272                 :          if (windowType == eWindowType_popup) {
    6273                 :            for (nsIFrame* current = aFrame; current;
    6274                 :                 current = nsLayoutUtils::GetCrossDocParentFrame(current)) {
    6275                 :              if (current->GetType() == nsGkAtoms::menuPopupFrame) {
    6276                 :                return false;
    6277                 :              }
    6278                 :            }
    6279                 :          }
    6280                 :       }
    6281                 :     }
    6282                 :   }
    6283                 : #endif
    6284               0 :   return true;
    6285                 : }
    6286                 : 
    6287                 : static bool
    6288               0 : IsFullScreenAndRestrictedKeyEvent(nsIContent* aTarget, const nsEvent* aEvent)
    6289                 : {
    6290               0 :   NS_ABORT_IF_FALSE(aEvent, "Must have an event to check.");
    6291                 : 
    6292                 :   // Bail out if the event is not a key event, or the target's document is
    6293                 :   // not in DOM full screen mode, or full-screen key input is not restricted.
    6294               0 :   nsIDocument *root = nsnull;
    6295               0 :   if (!aTarget ||
    6296                 :       (aEvent->message != NS_KEY_DOWN &&
    6297                 :       aEvent->message != NS_KEY_UP &&
    6298                 :       aEvent->message != NS_KEY_PRESS) ||
    6299               0 :       !(root = nsContentUtils::GetRootDocument(aTarget->OwnerDoc())) ||
    6300               0 :       !root->IsFullScreenDoc() ||
    6301               0 :       !nsContentUtils::IsFullScreenKeyInputRestricted()) {
    6302               0 :     return false;
    6303                 :   }
    6304                 : 
    6305                 :   // We're in full-screen mode. We whitelist key codes, and we will
    6306                 :   // show a warning when keys not in this list are pressed.
    6307               0 :   const nsKeyEvent* keyEvent = static_cast<const nsKeyEvent*>(aEvent);
    6308               0 :   int key = keyEvent->keyCode ? keyEvent->keyCode : keyEvent->charCode;
    6309               0 :   switch (key) {
    6310                 :     case NS_VK_TAB:
    6311                 :     case NS_VK_SPACE:
    6312                 :     case NS_VK_PAGE_UP:
    6313                 :     case NS_VK_PAGE_DOWN:
    6314                 :     case NS_VK_END:
    6315                 :     case NS_VK_HOME:
    6316                 :     case NS_VK_LEFT:
    6317                 :     case NS_VK_UP:
    6318                 :     case NS_VK_RIGHT:
    6319                 :     case NS_VK_DOWN:
    6320                 :     case NS_VK_SHIFT:
    6321                 :     case NS_VK_CONTROL:
    6322                 :     case NS_VK_ALT:
    6323                 :     case NS_VK_META:
    6324                 : #ifdef XP_WIN
    6325                 :     case VK_VOLUME_MUTE:
    6326                 :     case VK_VOLUME_DOWN:
    6327                 :     case VK_VOLUME_UP:
    6328                 : #endif
    6329                 :       // Unrestricted key code.
    6330               0 :       return false;
    6331                 :     default:
    6332                 :       // Otherwise, fullscreen is enabled, key input is restricted, and the key
    6333                 :       // code is not an allowed key code.
    6334               0 :       return true;
    6335                 :   }
    6336                 : }
    6337                 : 
    6338                 : nsresult
    6339               0 : PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
    6340                 : {
    6341                 :   NS_TIME_FUNCTION_MIN(1.0);
    6342                 : 
    6343                 : #ifdef ACCESSIBILITY
    6344               0 :   if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT)
    6345                 :   {
    6346               0 :     nsAccessibleEvent *accEvent = static_cast<nsAccessibleEvent*>(aEvent);
    6347               0 :     accEvent->mAccessible = nsnull;
    6348                 : 
    6349                 :     nsCOMPtr<nsIAccessibilityService> accService =
    6350               0 :       do_GetService("@mozilla.org/accessibilityService;1");
    6351               0 :     if (accService) {
    6352               0 :       nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
    6353               0 :       if (!container) {
    6354                 :         // This presshell is not active. This often happens when a
    6355                 :         // preshell is being held onto for fastback.
    6356               0 :         return NS_OK;
    6357                 :       }
    6358                 : 
    6359                 :       // Accessible creation might be not safe so we make sure it's not created
    6360                 :       // at unsafe times.
    6361                 :       accEvent->mAccessible =
    6362               0 :         accService->GetRootDocumentAccessible(this, nsContentUtils::IsSafeToRunScript());
    6363                 : 
    6364               0 :       return NS_OK;
    6365                 :     }
    6366                 :   }
    6367                 : #endif
    6368                 : 
    6369               0 :   nsRefPtr<nsEventStateManager> manager = mPresContext->EventStateManager();
    6370               0 :   nsresult rv = NS_OK;
    6371                 : 
    6372               0 :   if (!NS_EVENT_NEEDS_FRAME(aEvent) || GetCurrentEventFrame()) {
    6373                 : #ifdef MOZ_TOUCH
    6374                 :     bool touchIsNew = false;
    6375                 : #endif
    6376               0 :     bool isHandlingUserInput = false;
    6377                 : 
    6378                 :     // XXX How about IME events and input events for plugins?
    6379               0 :     if (NS_IS_TRUSTED_EVENT(aEvent)) {
    6380               0 :       switch (aEvent->message) {
    6381                 :       case NS_KEY_PRESS:
    6382                 :       case NS_KEY_DOWN:
    6383                 :       case NS_KEY_UP: {
    6384                 :         nsIDocument *doc = mCurrentEventContent ?
    6385               0 :                            mCurrentEventContent->OwnerDoc() : nsnull;
    6386               0 :         nsIDocument* root = nsnull;
    6387               0 :         if (static_cast<const nsKeyEvent*>(aEvent)->keyCode == NS_VK_ESCAPE &&
    6388                 :             (root = nsContentUtils::GetRootDocument(doc)) &&
    6389               0 :             root->IsFullScreenDoc()) {
    6390                 :           // Prevent default action on ESC key press when exiting
    6391                 :           // DOM full-screen mode. This prevents the browser ESC key
    6392                 :           // handler from stopping all loads in the document, which
    6393                 :           // would cause <video> loads to stop.
    6394                 :           aEvent->flags |= (NS_EVENT_FLAG_NO_DEFAULT |
    6395               0 :                             NS_EVENT_FLAG_ONLY_CHROME_DISPATCH);
    6396                 : 
    6397               0 :           if (aEvent->message == NS_KEY_UP) {
    6398                 :            // ESC key released while in DOM full-screen mode.
    6399                 :            // Exit full-screen mode.
    6400               0 :             nsIDocument::ExitFullScreen(true);
    6401                 :           }
    6402               0 :         } else if (IsFullScreenAndRestrictedKeyEvent(mCurrentEventContent, aEvent)) {
    6403                 :           // Restricted key press while in DOM full-screen mode. Dispatch
    6404                 :           // an event to chrome so it knows to show a warning message
    6405                 :           // informing the user how to exit full-screen.
    6406                 :           nsRefPtr<nsAsyncDOMEvent> e =
    6407               0 :             new nsAsyncDOMEvent(doc, NS_LITERAL_STRING("MozShowFullScreenWarning"),
    6408               0 :                                 true, true);
    6409               0 :           e->PostDOMEvent();
    6410                 :         }
    6411                 :         // Else not full-screen mode or key code is unrestricted, fall
    6412                 :         // through to normal handling.
    6413                 :       }
    6414                 :       case NS_MOUSE_BUTTON_DOWN:
    6415                 :       case NS_MOUSE_BUTTON_UP:
    6416               0 :         isHandlingUserInput = true;
    6417               0 :         break;
    6418                 : #ifdef MOZ_TOUCH
    6419                 :       case NS_TOUCH_CANCEL:
    6420                 :       case NS_TOUCH_END: {
    6421                 :         // Remove the changed touches
    6422                 :         // need to make sure we only remove touches that are ending here
    6423                 :         nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
    6424                 :         nsTArray<nsCOMPtr<nsIDOMTouch> >  &touches = touchEvent->touches;
    6425                 :         for (PRUint32 i = 0; i < touches.Length(); ++i) {
    6426                 :           nsIDOMTouch *touch = touches[i];
    6427                 :           nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
    6428                 :           if (!touch) {
    6429                 :             continue;
    6430                 :           }
    6431                 :           touch->mMessage = aEvent->message;
    6432                 :           touch->mChanged = true;
    6433                 :           nsCOMPtr<nsIDOMTouch> oldTouch;
    6434                 : 
    6435                 :           PRInt32 id;
    6436                 :           touch->GetIdentifier(&id);
    6437                 : 
    6438                 :           gCaptureTouchList.Get(id, getter_AddRefs(oldTouch));
    6439                 :           if (!oldTouch) {
    6440                 :             continue;
    6441                 :           }
    6442                 :           nsCOMPtr<nsPIDOMEventTarget> targetPtr;
    6443                 :           oldTouch->GetTarget(getter_AddRefs(targetPtr));
    6444                 : 
    6445                 :           mCurrentEventContent = do_QueryInterface(targetPtr);
    6446                 :           domtouch->SetTarget(targetPtr);
    6447                 :           gCaptureTouchList.Remove(id);
    6448                 :         }
    6449                 :         // add any touches left in the touch list, but ensure changed=false
    6450                 :         gCaptureTouchList.Enumerate(&AppendToTouchList, (void *)&touches);
    6451                 :         break;
    6452                 :       }
    6453                 :       case NS_TOUCH_MOVE: {
    6454                 :         // Check for touches that changed. Mark them add to queue
    6455                 :         nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
    6456                 :         nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
    6457                 :         bool haveChanged = false;
    6458                 :         for (PRUint32 i = 0; i < touches.Length(); ++i) {
    6459                 :           nsIDOMTouch *touch = touches[i];
    6460                 :           nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
    6461                 :           if (!touch) {
    6462                 :             continue;
    6463                 :           }
    6464                 :           PRInt32 id;
    6465                 :           touch->GetIdentifier(&id);
    6466                 :           touch->mMessage = aEvent->message;
    6467                 : 
    6468                 :           nsCOMPtr<nsIDOMTouch> oldTouch;
    6469                 :           gCaptureTouchList.Get(id, getter_AddRefs(oldTouch));
    6470                 :           if (!oldTouch) {
    6471                 :             continue;
    6472                 :           }
    6473                 :           if(domtouch->Equals(oldTouch)) {
    6474                 :             touch->mChanged = true;
    6475                 :             haveChanged = true;
    6476                 :           }
    6477                 : 
    6478                 :           nsCOMPtr<nsPIDOMEventTarget> targetPtr;
    6479                 :           oldTouch->GetTarget(getter_AddRefs(targetPtr));
    6480                 :           domtouch->SetTarget(targetPtr);
    6481                 : 
    6482                 :           gCaptureTouchList.Put(id, touch);
    6483                 :           // if we're moving from touchstart to touchmove for this touch
    6484                 :           // we allow preventDefault to prevent mouse events
    6485                 :           if (oldTouch->mMessage != touch->mMessage) {
    6486                 :             touchIsNew = true;
    6487                 :           }
    6488                 :         }
    6489                 :         // is nothing has changed, we should just return
    6490                 :         if (!haveChanged) {
    6491                 :           if (gPreventMouseEvents) {
    6492                 :               *aStatus = nsEventStatus_eConsumeNoDefault;
    6493                 :           }
    6494                 :           return NS_OK;
    6495                 :         }
    6496                 :         break;
    6497                 :       }
    6498                 : #endif
    6499                 :       case NS_DRAGDROP_DROP:
    6500               0 :         nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
    6501               0 :         if (session) {
    6502               0 :           bool onlyChromeDrop = false;
    6503               0 :           session->GetOnlyChromeDrop(&onlyChromeDrop);
    6504               0 :           if (onlyChromeDrop) {
    6505               0 :             aEvent->flags |= NS_EVENT_FLAG_ONLY_CHROME_DISPATCH;
    6506                 :           }
    6507                 :         }
    6508                 :         break;
    6509                 :       }
    6510                 :     }
    6511                 : 
    6512               0 :     if (aEvent->message == NS_CONTEXTMENU) {
    6513               0 :       nsMouseEvent* me = static_cast<nsMouseEvent*>(aEvent);
    6514               0 :       if (!CanHandleContextMenuEvent(me, GetCurrentEventFrame())) {
    6515               0 :         return NS_OK;
    6516                 :       }
    6517               0 :       if (me->context == nsMouseEvent::eContextMenuKey &&
    6518               0 :           !AdjustContextMenuKeyEvent(me)) {
    6519               0 :         return NS_OK;
    6520                 :       }
    6521               0 :       if (me->isShift)
    6522                 :         aEvent->flags |= NS_EVENT_FLAG_ONLY_CHROME_DISPATCH |
    6523               0 :                          NS_EVENT_RETARGET_TO_NON_NATIVE_ANONYMOUS;
    6524                 :     }
    6525                 : 
    6526                 :     nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput,
    6527               0 :                                                           aEvent, mDocument);
    6528                 : 
    6529               0 :     if (NS_IS_TRUSTED_EVENT(aEvent) && aEvent->message == NS_MOUSE_MOVE) {
    6530                 :       nsIPresShell::AllowMouseCapture(
    6531               0 :         nsEventStateManager::GetActiveEventStateManager() == manager);
    6532                 :     }
    6533                 : 
    6534               0 :     nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
    6535                 : 
    6536                 :     // FIXME. If the event was reused, we need to clear the old target,
    6537                 :     // bug 329430
    6538               0 :     aEvent->target = nsnull;
    6539                 : 
    6540                 :     // 1. Give event to event manager for pre event state changes and
    6541                 :     //    generation of synthetic events.
    6542               0 :     rv = manager->PreHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aStatus);
    6543                 : 
    6544                 :     // 2. Give event to the DOM for third party and JS use.
    6545               0 :     if (GetCurrentEventFrame() && NS_SUCCEEDED(rv)) {
    6546                 :       bool wasHandlingKeyBoardEvent =
    6547               0 :         nsContentUtils::IsHandlingKeyBoardEvent();
    6548               0 :       if (aEvent->eventStructType == NS_KEY_EVENT) {
    6549               0 :         nsContentUtils::SetIsHandlingKeyBoardEvent(true);
    6550                 :       }
    6551                 :       // We want synthesized mouse moves to cause mouseover and mouseout
    6552                 :       // DOM events (PreHandleEvent above), but not mousemove DOM events.
    6553                 :       // Synthesized button up events also do not cause DOM events
    6554                 :       // because they do not have a reliable refPoint.
    6555               0 :       if (!IsSynthesizedMouseEvent(aEvent)) {
    6556               0 :         nsPresShellEventCB eventCB(this);
    6557                 : #ifdef MOZ_TOUCH
    6558                 :         if (aEvent->eventStructType == NS_TOUCH_EVENT) {
    6559                 :           DispatchTouchEvent(aEvent, aStatus, &eventCB, touchIsNew);
    6560                 :         }
    6561                 :         else if (mCurrentEventContent) {
    6562                 : #else
    6563               0 :         if (mCurrentEventContent) {
    6564                 : #endif
    6565                 :           nsEventDispatcher::Dispatch(mCurrentEventContent, mPresContext,
    6566               0 :                                       aEvent, nsnull, aStatus, &eventCB);
    6567                 :         }
    6568                 :         else {
    6569               0 :           nsCOMPtr<nsIContent> targetContent;
    6570                 :           rv = mCurrentEventFrame->GetContentForEvent(aEvent,
    6571               0 :                                                       getter_AddRefs(targetContent));
    6572               0 :           if (NS_SUCCEEDED(rv) && targetContent) {
    6573                 :             nsEventDispatcher::Dispatch(targetContent, mPresContext, aEvent,
    6574               0 :                                         nsnull, aStatus, &eventCB);
    6575               0 :           } else if (mDocument) {
    6576                 :             nsEventDispatcher::Dispatch(mDocument, mPresContext, aEvent,
    6577               0 :                                         nsnull, aStatus, nsnull);
    6578                 :           }
    6579                 :         }
    6580                 :       }
    6581                 : 
    6582               0 :       nsContentUtils::SetIsHandlingKeyBoardEvent(wasHandlingKeyBoardEvent);
    6583                 : 
    6584                 :       // 3. Give event to event manager for post event state changes and
    6585                 :       //    generation of synthetic events.
    6586               0 :       if (!mIsDestroying && NS_SUCCEEDED(rv)) {
    6587                 :         rv = manager->PostHandleEvent(mPresContext, aEvent,
    6588               0 :                                       GetCurrentEventFrame(), aStatus);
    6589                 :       }
    6590                 :     }
    6591                 : 
    6592               0 :     if (aEvent->message == NS_MOUSE_BUTTON_UP) {
    6593                 :       // reset the capturing content now that the mouse button is up
    6594               0 :       SetCapturingContent(nsnull, 0);
    6595               0 :     } else if (aEvent->message == NS_MOUSE_MOVE) {
    6596               0 :       nsIPresShell::AllowMouseCapture(false);
    6597                 :     }
    6598                 :   }
    6599               0 :   return rv;
    6600                 : }
    6601                 : 
    6602                 : void
    6603               0 : PresShell::DispatchTouchEvent(nsEvent *aEvent,
    6604                 :                               nsEventStatus* aStatus,
    6605                 :                               nsPresShellEventCB* aEventCB,
    6606                 :                               bool aTouchIsNew)
    6607                 : {
    6608               0 :   nsresult rv = NS_OK;
    6609                 :   // calling preventDefault on touchstart or the first touchmove for a
    6610                 :   // point prevents mouse events
    6611                 :   bool canPrevent = aEvent->message == NS_TOUCH_START ||
    6612               0 :               (aEvent->message == NS_TOUCH_MOVE && aTouchIsNew);
    6613               0 :   bool preventDefault = false;
    6614               0 :   nsEventStatus tmpStatus = nsEventStatus_eIgnore;
    6615               0 :   nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
    6616                 :   // touch events should fire on all targets
    6617               0 :   if (aEvent->message != NS_TOUCH_START) {
    6618               0 :     nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
    6619               0 :     for (PRUint32 i = 0; i < touches.Length(); ++i) {
    6620               0 :       nsIDOMTouch *touch = touches[i];
    6621               0 :       if (!touch || !touch->mChanged) {
    6622               0 :         continue;
    6623                 :       }
    6624                 :       // copy the event
    6625               0 :       nsCOMPtr<nsPIDOMEventTarget> targetPtr;
    6626               0 :       touch->GetTarget(getter_AddRefs(targetPtr));
    6627               0 :       if (!targetPtr) {
    6628               0 :         continue;
    6629                 :       }
    6630                 : 
    6631               0 :       nsTouchEvent newEvent(touchEvent);
    6632               0 :       newEvent.target = targetPtr;
    6633                 : 
    6634               0 :       nsCOMPtr<nsIContent> content(do_QueryInterface(targetPtr));
    6635               0 :       nsPresContext *context = nsContentUtils::GetContextForContent(content);
    6636               0 :       if (!context) {
    6637               0 :         context = mPresContext;
    6638                 :       }
    6639               0 :       tmpStatus = nsEventStatus_eIgnore;
    6640                 :       nsEventDispatcher::Dispatch(targetPtr, context,
    6641               0 :                                   &newEvent, nsnull, &tmpStatus, aEventCB);
    6642               0 :       if (nsEventStatus_eConsumeNoDefault == tmpStatus) {
    6643               0 :         preventDefault = true;
    6644                 :       }
    6645                 :     }
    6646                 :   } else {
    6647                 :     // touchevents need to have the target attribute set on each touch
    6648               0 :     nsTArray<nsCOMPtr<nsIDOMTouch> >  touches = touchEvent->touches;
    6649               0 :     for (PRUint32 i = 0; i < touches.Length(); ++i) {
    6650               0 :       nsIDOMTouch *touch = touches[i];
    6651               0 :       if (touch->mChanged) {
    6652               0 :         touch->SetTarget(mCurrentEventContent);
    6653                 :       }
    6654                 :     }
    6655                 : 
    6656               0 :     if (mCurrentEventContent) {
    6657                 :       nsEventDispatcher::Dispatch(mCurrentEventContent, mPresContext,
    6658               0 :                                   aEvent, nsnull, &tmpStatus, aEventCB);
    6659                 :     } else {
    6660               0 :       nsCOMPtr<nsIContent> targetContent;
    6661                 :       rv = mCurrentEventFrame->GetContentForEvent(aEvent,
    6662               0 :                                                   getter_AddRefs(targetContent));
    6663               0 :       if (NS_SUCCEEDED(rv) && targetContent) {
    6664                 :         nsEventDispatcher::Dispatch(targetContent, mPresContext, aEvent,
    6665               0 :                                     nsnull, &tmpStatus, aEventCB);
    6666               0 :       } else if (mDocument) {
    6667                 :         nsEventDispatcher::Dispatch(mDocument, mPresContext, aEvent,
    6668               0 :                                     nsnull, &tmpStatus, nsnull);
    6669                 :       }
    6670                 :     }
    6671               0 :     if (nsEventStatus_eConsumeNoDefault == tmpStatus) {
    6672               0 :       preventDefault = true;
    6673                 :     }
    6674                 : 
    6675               0 :     if (touchEvent->touches.Length() == 1) {
    6676               0 :       gPreventMouseEvents = false;
    6677                 :     }
    6678                 :   }
    6679                 : 
    6680                 :   // if preventDefault was called on any of the events dispatched
    6681                 :   // and this is touchstart, or the first touchmove, widget should consume
    6682                 :   // other events that would be associated with this touch session
    6683               0 :   if (preventDefault && canPrevent) {
    6684               0 :     gPreventMouseEvents = true;
    6685                 :   }
    6686                 : 
    6687               0 :   if (gPreventMouseEvents) {
    6688               0 :     *aStatus = nsEventStatus_eConsumeNoDefault;
    6689                 :   } else {
    6690               0 :     *aStatus = nsEventStatus_eIgnore;
    6691                 :   }
    6692               0 : }
    6693                 : 
    6694                 : // Dispatch event to content only (NOT full processing)
    6695                 : // See also HandleEventWithTarget which does full event processing.
    6696                 : nsresult
    6697               0 : PresShell::HandleDOMEventWithTarget(nsIContent* aTargetContent, nsEvent* aEvent,
    6698                 :                                     nsEventStatus* aStatus)
    6699                 : {
    6700               0 :   nsresult rv = NS_OK;
    6701                 : 
    6702               0 :   PushCurrentEventInfo(nsnull, aTargetContent);
    6703                 : 
    6704                 :   // Bug 41013: Check if the event should be dispatched to content.
    6705                 :   // It's possible that we are in the middle of destroying the window
    6706                 :   // and the js context is out of date. This check detects the case
    6707                 :   // that caused a crash in bug 41013, but there may be a better way
    6708                 :   // to handle this situation!
    6709               0 :   nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
    6710               0 :   if (container) {
    6711                 : 
    6712                 :     // Dispatch event to content
    6713                 :     rv = nsEventDispatcher::Dispatch(aTargetContent, mPresContext, aEvent, nsnull,
    6714               0 :                                      aStatus);
    6715                 :   }
    6716                 : 
    6717               0 :   PopCurrentEventInfo();
    6718               0 :   return rv;
    6719                 : }
    6720                 : 
    6721                 : // See the method above.
    6722                 : nsresult
    6723               0 : PresShell::HandleDOMEventWithTarget(nsIContent* aTargetContent,
    6724                 :                                     nsIDOMEvent* aEvent,
    6725                 :                                     nsEventStatus* aStatus)
    6726                 : {
    6727               0 :   nsresult rv = NS_OK;
    6728                 : 
    6729               0 :   PushCurrentEventInfo(nsnull, aTargetContent);
    6730               0 :   nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
    6731               0 :   if (container) {
    6732                 :     rv = nsEventDispatcher::DispatchDOMEvent(aTargetContent, nsnull, aEvent,
    6733               0 :                                              mPresContext, aStatus);
    6734                 :   }
    6735                 : 
    6736               0 :   PopCurrentEventInfo();
    6737               0 :   return rv;
    6738                 : }
    6739                 : 
    6740                 : bool
    6741               0 : PresShell::AdjustContextMenuKeyEvent(nsMouseEvent* aEvent)
    6742                 : {
    6743                 : #ifdef MOZ_XUL
    6744                 :   // if a menu is open, open the context menu relative to the active item on the menu. 
    6745               0 :   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
    6746               0 :   if (pm) {
    6747               0 :     nsIFrame* popupFrame = pm->GetTopPopup(ePopupTypeMenu);
    6748               0 :     if (popupFrame) {
    6749                 :       nsIFrame* itemFrame = 
    6750               0 :         (static_cast<nsMenuPopupFrame *>(popupFrame))->GetCurrentMenuItem();
    6751               0 :       if (!itemFrame)
    6752               0 :         itemFrame = popupFrame;
    6753                 : 
    6754               0 :       nsCOMPtr<nsIWidget> widget = popupFrame->GetNearestWidget();
    6755               0 :       aEvent->widget = widget;
    6756               0 :       nsIntPoint widgetPoint = widget->WidgetToScreenOffset();
    6757               0 :       aEvent->refPoint = itemFrame->GetScreenRect().BottomLeft() - widgetPoint;
    6758                 : 
    6759               0 :       mCurrentEventContent = itemFrame->GetContent();
    6760               0 :       mCurrentEventFrame = itemFrame;
    6761                 : 
    6762               0 :       return true;
    6763                 :     }
    6764                 :   }
    6765                 : #endif
    6766                 : 
    6767                 :   // If we're here because of the key-equiv for showing context menus, we
    6768                 :   // have to twiddle with the NS event to make sure the context menu comes
    6769                 :   // up in the upper left of the relevant content area before we create
    6770                 :   // the DOM event. Since we never call InitMouseEvent() on the event, 
    6771                 :   // the client X/Y will be 0,0. We can make use of that if the widget is null.
    6772                 :   // Use the root view manager's widget since it's most likely to have one,
    6773                 :   // and the coordinates returned by GetCurrentItemAndPositionForElement
    6774                 :   // are relative to the widget of the root of the root view manager.
    6775               0 :   nsRootPresContext* rootPC = mPresContext->GetRootPresContext();
    6776               0 :   aEvent->refPoint.x = 0;
    6777               0 :   aEvent->refPoint.y = 0;
    6778               0 :   if (rootPC) {
    6779               0 :     rootPC->PresShell()->GetViewManager()->
    6780               0 :       GetRootWidget(getter_AddRefs(aEvent->widget));
    6781                 : 
    6782               0 :     if (aEvent->widget) {
    6783                 :       // default the refpoint to the topleft of our document
    6784               0 :       nsPoint offset(0, 0);
    6785               0 :       nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
    6786               0 :       if (rootFrame) {
    6787               0 :         nsIView* view = rootFrame->GetClosestView(&offset);
    6788               0 :         offset += view->GetOffsetToWidget(aEvent->widget);
    6789                 :         aEvent->refPoint =
    6790               0 :           offset.ToNearestPixels(mPresContext->AppUnitsPerDevPixel());
    6791                 :       }
    6792                 :     }
    6793                 :   } else {
    6794               0 :     aEvent->widget = nsnull;
    6795                 :   }
    6796                 : 
    6797                 :   // see if we should use the caret position for the popup
    6798               0 :   nsIntPoint caretPoint;
    6799                 :   // Beware! This may flush notifications via synchronous
    6800                 :   // ScrollSelectionIntoView.
    6801               0 :   if (PrepareToUseCaretPosition(aEvent->widget, caretPoint)) {
    6802                 :     // caret position is good
    6803               0 :     aEvent->refPoint = caretPoint;
    6804               0 :     return true;
    6805                 :   }
    6806                 : 
    6807                 :   // If we're here because of the key-equiv for showing context menus, we
    6808                 :   // have to reset the event target to the currently focused element. Get it
    6809                 :   // from the focus controller.
    6810               0 :   nsCOMPtr<nsIDOMElement> currentFocus;
    6811               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    6812               0 :   if (fm)
    6813               0 :     fm->GetFocusedElement(getter_AddRefs(currentFocus));
    6814                 : 
    6815                 :   // Reset event coordinates relative to focused frame in view
    6816               0 :   if (currentFocus) {
    6817               0 :     nsCOMPtr<nsIContent> currentPointElement;
    6818                 :     GetCurrentItemAndPositionForElement(currentFocus,
    6819               0 :                                         getter_AddRefs(currentPointElement),
    6820                 :                                         aEvent->refPoint,
    6821               0 :                                         aEvent->widget);
    6822               0 :     if (currentPointElement) {
    6823               0 :       mCurrentEventContent = currentPointElement;
    6824               0 :       mCurrentEventFrame = nsnull;
    6825               0 :       GetCurrentEventFrame();
    6826                 :     }
    6827                 :   }
    6828                 : 
    6829               0 :   return true;
    6830                 : }
    6831                 : 
    6832                 : // PresShell::PrepareToUseCaretPosition
    6833                 : //
    6834                 : //    This checks to see if we should use the caret position for popup context
    6835                 : //    menus. Returns true if the caret position should be used, and the
    6836                 : //    coordinates of that position is returned in aTargetPt. This function
    6837                 : //    will also scroll the window as needed to make the caret visible.
    6838                 : //
    6839                 : //    The event widget should be the widget that generated the event, and
    6840                 : //    whose coordinate system the resulting event's refPoint should be
    6841                 : //    relative to.  The returned point is in device pixels realtive to the
    6842                 : //    widget passed in.
    6843                 : bool
    6844               0 : PresShell::PrepareToUseCaretPosition(nsIWidget* aEventWidget, nsIntPoint& aTargetPt)
    6845                 : {
    6846                 :   nsresult rv;
    6847                 : 
    6848                 :   // check caret visibility
    6849               0 :   nsRefPtr<nsCaret> caret = GetCaret();
    6850               0 :   NS_ENSURE_TRUE(caret, false);
    6851                 : 
    6852               0 :   bool caretVisible = false;
    6853               0 :   rv = caret->GetCaretVisible(&caretVisible);
    6854               0 :   if (NS_FAILED(rv) || ! caretVisible)
    6855               0 :     return false;
    6856                 : 
    6857                 :   // caret selection, this is a temporary weak reference, so no refcounting is 
    6858                 :   // needed
    6859               0 :   nsISelection* domSelection = caret->GetCaretDOMSelection();
    6860               0 :   NS_ENSURE_TRUE(domSelection, false);
    6861                 : 
    6862                 :   // since the match could be an anonymous textnode inside a
    6863                 :   // <textarea> or text <input>, we need to get the outer frame
    6864                 :   // note: frames are not refcounted
    6865               0 :   nsIFrame* frame = nsnull; // may be NULL
    6866               0 :   nsCOMPtr<nsIDOMNode> node;
    6867               0 :   rv = domSelection->GetFocusNode(getter_AddRefs(node));
    6868               0 :   NS_ENSURE_SUCCESS(rv, false);
    6869               0 :   NS_ENSURE_TRUE(node, false);
    6870               0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(node));
    6871               0 :   if (content) {
    6872               0 :     nsIContent* nonNative = content->FindFirstNonNativeAnonymous();
    6873               0 :     content = nonNative;
    6874                 :   }
    6875                 : 
    6876               0 :   if (content) {
    6877                 :     // It seems like ScrollSelectionIntoView should be enough, but it's
    6878                 :     // not. The problem is that scrolling the selection into view when it is
    6879                 :     // below the current viewport will align the top line of the frame exactly
    6880                 :     // with the bottom of the window. This is fine, BUT, the popup event causes
    6881                 :     // the control to be re-focused which does this exact call to
    6882                 :     // ScrollContentIntoView, which has a one-pixel disagreement of whether the
    6883                 :     // frame is actually in view. The result is that the frame is aligned with
    6884                 :     // the top of the window, but the menu is still at the bottom.
    6885                 :     //
    6886                 :     // Doing this call first forces the frame to be in view, eliminating the
    6887                 :     // problem. The only difference in the result is that if your cursor is in
    6888                 :     // an edit box below the current view, you'll get the edit box aligned with
    6889                 :     // the top of the window. This is arguably better behavior anyway.
    6890                 :     rv = ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
    6891                 :                                         NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
    6892               0 :                                         SCROLL_OVERFLOW_HIDDEN);
    6893               0 :     NS_ENSURE_SUCCESS(rv, false);
    6894               0 :     frame = content->GetPrimaryFrame();
    6895               0 :     NS_WARN_IF_FALSE(frame, "No frame for focused content?");
    6896                 :   }
    6897                 : 
    6898                 :   // Actually scroll the selection (ie caret) into view. Note that this must
    6899                 :   // be synchronous since we will be checking the caret position on the screen.
    6900                 :   //
    6901                 :   // Be easy about errors, and just don't scroll in those cases. Better to have
    6902                 :   // the correct menu at a weird place than the wrong menu.
    6903                 :   // After ScrollSelectionIntoView(), the pending notifications might be
    6904                 :   // flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
    6905               0 :   nsCOMPtr<nsISelectionController> selCon;
    6906               0 :   if (frame)
    6907               0 :     frame->GetSelectionController(GetPresContext(), getter_AddRefs(selCon));
    6908                 :   else
    6909               0 :     selCon = static_cast<nsISelectionController *>(this);
    6910               0 :   if (selCon) {
    6911               0 :     rv = selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
    6912                 :                                          nsISelectionController::SELECTION_FOCUS_REGION,
    6913               0 :                                          nsISelectionController::SCROLL_SYNCHRONOUS);
    6914               0 :     NS_ENSURE_SUCCESS(rv, false);
    6915                 :   }
    6916                 : 
    6917               0 :   nsPresContext* presContext = GetPresContext();
    6918                 : 
    6919                 :   // get caret position relative to the closest view
    6920               0 :   nsRect caretCoords;
    6921               0 :   nsIFrame* caretFrame = caret->GetGeometry(domSelection, &caretCoords);
    6922               0 :   if (!caretFrame)
    6923               0 :     return false;
    6924               0 :   nsPoint viewOffset;
    6925               0 :   nsIView* view = caretFrame->GetClosestView(&viewOffset);
    6926               0 :   if (!view)
    6927               0 :     return false;
    6928                 :   // and then get the caret coords relative to the event widget
    6929               0 :   if (aEventWidget) {
    6930               0 :     viewOffset += view->GetOffsetToWidget(aEventWidget);
    6931                 :   }
    6932               0 :   caretCoords.MoveBy(viewOffset);
    6933                 : 
    6934                 :   // caret coordinates are in app units, convert to pixels
    6935                 :   aTargetPt.x =
    6936               0 :     presContext->AppUnitsToDevPixels(caretCoords.x + caretCoords.width);
    6937                 :   aTargetPt.y =
    6938               0 :     presContext->AppUnitsToDevPixels(caretCoords.y + caretCoords.height);
    6939                 : 
    6940                 :   // make sure rounding doesn't return a pixel which is outside the caret
    6941                 :   // (e.g. one line lower)
    6942               0 :   aTargetPt.y -= 1;
    6943                 : 
    6944               0 :   return true;
    6945                 : }
    6946                 : 
    6947                 : void
    6948               0 : PresShell::GetCurrentItemAndPositionForElement(nsIDOMElement *aCurrentEl,
    6949                 :                                                nsIContent** aTargetToUse,
    6950                 :                                                nsIntPoint& aTargetPt,
    6951                 :                                                nsIWidget *aRootWidget)
    6952                 : {
    6953               0 :   nsCOMPtr<nsIContent> focusedContent(do_QueryInterface(aCurrentEl));
    6954                 :   ScrollContentIntoView(focusedContent, NS_PRESSHELL_SCROLL_ANYWHERE,
    6955                 :                                         NS_PRESSHELL_SCROLL_ANYWHERE,
    6956               0 :                                         SCROLL_OVERFLOW_HIDDEN);
    6957                 : 
    6958               0 :   nsPresContext* presContext = GetPresContext();
    6959                 : 
    6960               0 :   bool istree = false, checkLineHeight = true;
    6961               0 :   nscoord extraTreeY = 0;
    6962                 : 
    6963                 : #ifdef MOZ_XUL
    6964                 :   // Set the position to just underneath the current item for multi-select
    6965                 :   // lists or just underneath the selected item for single-select lists. If
    6966                 :   // the element is not a list, or there is no selection, leave the position
    6967                 :   // as is.
    6968               0 :   nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
    6969                 :   nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelect =
    6970               0 :     do_QueryInterface(aCurrentEl);
    6971               0 :   if (multiSelect) {
    6972               0 :     checkLineHeight = false;
    6973                 :     
    6974                 :     PRInt32 currentIndex;
    6975               0 :     multiSelect->GetCurrentIndex(&currentIndex);
    6976               0 :     if (currentIndex >= 0) {
    6977               0 :       nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(aCurrentEl));
    6978               0 :       if (xulElement) {
    6979               0 :         nsCOMPtr<nsIBoxObject> box;
    6980               0 :         xulElement->GetBoxObject(getter_AddRefs(box));
    6981               0 :         nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(box));
    6982                 :         // Tree view special case (tree items have no frames)
    6983                 :         // Get the focused row and add its coordinates, which are already in pixels
    6984                 :         // XXX Boris, should we create a new interface so that this doesn't
    6985                 :         // need to know about trees? Something like nsINodelessChildCreator which
    6986                 :         // could provide the current focus coordinates?
    6987               0 :         if (treeBox) {
    6988               0 :           treeBox->EnsureRowIsVisible(currentIndex);
    6989                 :           PRInt32 firstVisibleRow, rowHeight;
    6990               0 :           treeBox->GetFirstVisibleRow(&firstVisibleRow);
    6991               0 :           treeBox->GetRowHeight(&rowHeight);
    6992                 : 
    6993                 :           extraTreeY += presContext->CSSPixelsToAppUnits(
    6994               0 :                           (currentIndex - firstVisibleRow + 1) * rowHeight);
    6995               0 :           istree = true;
    6996                 : 
    6997               0 :           nsCOMPtr<nsITreeColumns> cols;
    6998               0 :           treeBox->GetColumns(getter_AddRefs(cols));
    6999               0 :           if (cols) {
    7000               0 :             nsCOMPtr<nsITreeColumn> col;
    7001               0 :             cols->GetFirstColumn(getter_AddRefs(col));
    7002               0 :             if (col) {
    7003               0 :               nsCOMPtr<nsIDOMElement> colElement;
    7004               0 :               col->GetElement(getter_AddRefs(colElement));
    7005               0 :               nsCOMPtr<nsIContent> colContent(do_QueryInterface(colElement));
    7006               0 :               if (colContent) {
    7007               0 :                 nsIFrame* frame = colContent->GetPrimaryFrame();
    7008               0 :                 if (frame) {
    7009               0 :                   extraTreeY += frame->GetSize().height;
    7010                 :                 }
    7011                 :               }
    7012                 :             }
    7013                 :           }
    7014                 :         }
    7015                 :         else {
    7016               0 :           multiSelect->GetCurrentItem(getter_AddRefs(item));
    7017                 :         }
    7018                 :       }
    7019                 :     }
    7020                 :   }
    7021                 :   else {
    7022                 :     // don't check menulists as the selected item will be inside a popup.
    7023               0 :     nsCOMPtr<nsIDOMXULMenuListElement> menulist = do_QueryInterface(aCurrentEl);
    7024               0 :     if (!menulist) {
    7025                 :       nsCOMPtr<nsIDOMXULSelectControlElement> select =
    7026               0 :         do_QueryInterface(aCurrentEl);
    7027               0 :       if (select) {
    7028               0 :         checkLineHeight = false;
    7029               0 :         select->GetSelectedItem(getter_AddRefs(item));
    7030                 :       }
    7031                 :     }
    7032                 :   }
    7033                 : 
    7034               0 :   if (item)
    7035               0 :     focusedContent = do_QueryInterface(item);
    7036                 : #endif
    7037                 : 
    7038               0 :   nsIFrame *frame = focusedContent->GetPrimaryFrame();
    7039               0 :   if (frame) {
    7040               0 :     NS_ASSERTION(frame->PresContext() == GetPresContext(),
    7041                 :       "handling event for focused content that is not in our document?");
    7042                 : 
    7043               0 :     nsPoint frameOrigin(0, 0);
    7044                 : 
    7045                 :     // Get the frame's origin within its view
    7046               0 :     nsIView *view = frame->GetClosestView(&frameOrigin);
    7047               0 :     NS_ASSERTION(view, "No view for frame");
    7048                 : 
    7049                 :     // View's origin relative the widget
    7050               0 :     if (aRootWidget) {
    7051               0 :       frameOrigin += view->GetOffsetToWidget(aRootWidget);
    7052                 :     }
    7053                 : 
    7054                 :     // Start context menu down and to the right from top left of frame
    7055                 :     // use the lineheight. This is a good distance to move the context
    7056                 :     // menu away from the top left corner of the frame. If we always 
    7057                 :     // used the frame height, the context menu could end up far away,
    7058                 :     // for example when we're focused on linked images.
    7059                 :     // On the other hand, we want to use the frame height if it's less
    7060                 :     // than the current line height, so that the context menu appears
    7061                 :     // associated with the correct frame.
    7062               0 :     nscoord extra = 0;
    7063               0 :     if (!istree) {
    7064               0 :       extra = frame->GetSize().height;
    7065               0 :       if (checkLineHeight) {
    7066                 :         nsIScrollableFrame *scrollFrame =
    7067               0 :           nsLayoutUtils::GetNearestScrollableFrame(frame);
    7068               0 :         if (scrollFrame) {
    7069               0 :           nsSize scrollAmount = scrollFrame->GetLineScrollAmount();
    7070               0 :           nsIFrame* f = do_QueryFrame(scrollFrame);
    7071               0 :           PRInt32 APD = presContext->AppUnitsPerDevPixel();
    7072               0 :           PRInt32 scrollAPD = f->PresContext()->AppUnitsPerDevPixel();
    7073               0 :           scrollAmount = scrollAmount.ConvertAppUnits(scrollAPD, APD);
    7074               0 :           if (extra > scrollAmount.height) {
    7075               0 :             extra = scrollAmount.height;
    7076                 :           }
    7077                 :         }
    7078                 :       }
    7079                 :     }
    7080                 : 
    7081               0 :     aTargetPt.x = presContext->AppUnitsToDevPixels(frameOrigin.x);
    7082                 :     aTargetPt.y = presContext->AppUnitsToDevPixels(
    7083               0 :                     frameOrigin.y + extra + extraTreeY);
    7084                 :   }
    7085                 : 
    7086               0 :   NS_IF_ADDREF(*aTargetToUse = focusedContent);
    7087               0 : }
    7088                 : 
    7089                 : bool
    7090               0 : PresShell::ShouldIgnoreInvalidation()
    7091                 : {
    7092               0 :   return mPaintingSuppressed || !mIsActive;
    7093                 : }
    7094                 : 
    7095                 : void
    7096               0 : PresShell::WillPaint(bool aWillSendDidPaint)
    7097                 : {
    7098                 :   // Don't bother doing anything if some viewmanager in our tree is painting
    7099                 :   // while we still have painting suppressed or we are not active.
    7100               0 :   if (mPaintingSuppressed || !mIsActive || !IsVisible()) {
    7101               0 :     return;
    7102                 :   }
    7103                 : 
    7104               0 :   nsRootPresContext* rootPresContext = mPresContext->GetRootPresContext();
    7105               0 :   if (!rootPresContext) {
    7106               0 :     return;
    7107                 :   }
    7108                 : 
    7109               0 :   if (!aWillSendDidPaint && rootPresContext == mPresContext) {
    7110               0 :     rootPresContext->UpdatePluginGeometry();
    7111                 :   }
    7112               0 :   rootPresContext->FlushWillPaintObservers();
    7113               0 :   if (mIsDestroying)
    7114               0 :     return;
    7115                 : 
    7116                 :   // Process reflows, if we have them, to reduce flicker due to invalidates and
    7117                 :   // reflow being interspersed.  Note that we _do_ allow this to be
    7118                 :   // interruptible; if we can't do all the reflows it's better to flicker a bit
    7119                 :   // than to freeze up.
    7120               0 :   FlushPendingNotifications(Flush_InterruptibleLayout);
    7121                 : }
    7122                 : 
    7123                 : void
    7124               0 : PresShell::DidPaint()
    7125                 : {
    7126               0 :   if (mPaintingSuppressed || !mIsActive || !IsVisible()) {
    7127               0 :     return;
    7128                 :   }
    7129                 : 
    7130               0 :   NS_ASSERTION(mPresContext->IsRoot(), "Should only call DidPaint on root presshells");
    7131                 : 
    7132               0 :   nsRootPresContext* rootPresContext = mPresContext->GetRootPresContext();
    7133                 :   // This should only be called on root presshells, but maybe if a document
    7134                 :   // tree is torn down we might not be a root presshell...
    7135               0 :   if (rootPresContext == mPresContext) {
    7136               0 :     rootPresContext->UpdatePluginGeometry();
    7137                 :   }
    7138                 : 
    7139               0 :   if (nsContentUtils::XPConnect()) {
    7140               0 :     nsContentUtils::XPConnect()->NotifyDidPaint();
    7141                 :   }
    7142                 : }
    7143                 : 
    7144                 : bool
    7145               0 : PresShell::IsVisible()
    7146                 : {
    7147               0 :   if (!mViewManager)
    7148               0 :     return false;
    7149                 : 
    7150               0 :   nsIView* view = mViewManager->GetRootView();
    7151               0 :   if (!view)
    7152               0 :     return true;
    7153                 : 
    7154                 :   // inner view of subdoc frame
    7155               0 :   view = view->GetParent();
    7156               0 :   if (!view)
    7157               0 :     return true;
    7158                 :   
    7159                 :   // subdoc view
    7160               0 :   view = view->GetParent();
    7161               0 :   if (!view)
    7162               0 :     return true;
    7163                 : 
    7164               0 :   nsIFrame* frame = view->GetFrame();
    7165               0 :   if (!frame)
    7166               0 :     return true;
    7167                 : 
    7168               0 :   return frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY);
    7169                 : }
    7170                 : 
    7171                 : nsresult
    7172               0 : PresShell::GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets)
    7173                 : {
    7174               0 :   aSheets.Clear();
    7175               0 :   PRInt32 sheetCount = mStyleSet->SheetCount(nsStyleSet::eAgentSheet);
    7176                 : 
    7177               0 :   for (PRInt32 i = 0; i < sheetCount; ++i) {
    7178               0 :     nsIStyleSheet *sheet = mStyleSet->StyleSheetAt(nsStyleSet::eAgentSheet, i);
    7179               0 :     if (!aSheets.AppendObject(sheet))
    7180               0 :       return NS_ERROR_OUT_OF_MEMORY;
    7181                 :   }
    7182                 : 
    7183               0 :   return NS_OK;
    7184                 : }
    7185                 : 
    7186                 : nsresult
    7187               0 : PresShell::SetAgentStyleSheets(const nsCOMArray<nsIStyleSheet>& aSheets)
    7188                 : {
    7189               0 :   return mStyleSet->ReplaceSheets(nsStyleSet::eAgentSheet, aSheets);
    7190                 : }
    7191                 : 
    7192                 : nsresult
    7193               0 : PresShell::AddOverrideStyleSheet(nsIStyleSheet *aSheet)
    7194                 : {
    7195               0 :   return mStyleSet->PrependStyleSheet(nsStyleSet::eOverrideSheet, aSheet);
    7196                 : }
    7197                 : 
    7198                 : nsresult
    7199               0 : PresShell::RemoveOverrideStyleSheet(nsIStyleSheet *aSheet)
    7200                 : {
    7201               0 :   return mStyleSet->RemoveStyleSheet(nsStyleSet::eOverrideSheet, aSheet);
    7202                 : }
    7203                 : 
    7204                 : static void
    7205               0 : FreezeElement(nsIContent *aContent, void * /* unused */)
    7206                 : {
    7207               0 :   nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(aContent));
    7208               0 :   if (olc) {
    7209               0 :     olc->StopPluginInstance();
    7210                 :   }
    7211               0 : }
    7212                 : 
    7213                 : static bool
    7214               0 : FreezeSubDocument(nsIDocument *aDocument, void *aData)
    7215                 : {
    7216               0 :   nsIPresShell *shell = aDocument->GetShell();
    7217               0 :   if (shell)
    7218               0 :     shell->Freeze();
    7219                 : 
    7220               0 :   return true;
    7221                 : }
    7222                 : 
    7223                 : void
    7224               0 : PresShell::Freeze()
    7225                 : {
    7226               0 :   MaybeReleaseCapturingContent();
    7227                 : 
    7228               0 :   mDocument->EnumerateFreezableElements(FreezeElement, nsnull);
    7229                 : 
    7230               0 :   if (mCaret) {
    7231               0 :     mCaret->SetCaretVisible(false);
    7232                 :   }
    7233                 : 
    7234               0 :   mPaintingSuppressed = true;
    7235                 : 
    7236               0 :   if (mDocument) {
    7237               0 :     mDocument->EnumerateSubDocuments(FreezeSubDocument, nsnull);
    7238                 :   }
    7239                 : 
    7240               0 :   nsPresContext* presContext = GetPresContext();
    7241               0 :   if (presContext &&
    7242               0 :       presContext->RefreshDriver()->PresContext() == presContext) {
    7243               0 :     presContext->RefreshDriver()->Freeze();
    7244                 :   }
    7245                 : 
    7246               0 :   if (presContext) {
    7247               0 :     nsRootPresContext* rootPresContext = presContext->GetRootPresContext();
    7248               0 :     if (rootPresContext) {
    7249                 :       rootPresContext->
    7250               0 :         RootForgetUpdatePluginGeometryFrameForPresContext(mPresContext);
    7251                 :     }
    7252                 :   }
    7253                 : 
    7254               0 :   mFrozen = true;
    7255               0 :   if (mDocument) {
    7256               0 :     UpdateImageLockingState();
    7257                 :   }
    7258               0 : }
    7259                 : 
    7260                 : void
    7261               0 : PresShell::FireOrClearDelayedEvents(bool aFireEvents)
    7262                 : {
    7263               0 :   mNoDelayedMouseEvents = false;
    7264               0 :   mNoDelayedKeyEvents = false;
    7265               0 :   if (!aFireEvents) {
    7266               0 :     mDelayedEvents.Clear();
    7267               0 :     return;
    7268                 :   }
    7269                 : 
    7270               0 :   if (mDocument) {
    7271               0 :     nsCOMPtr<nsIDocument> doc = mDocument;
    7272               0 :     while (!mIsDestroying && mDelayedEvents.Length() &&
    7273               0 :            !doc->EventHandlingSuppressed()) {
    7274               0 :       nsAutoPtr<nsDelayedEvent> ev(mDelayedEvents[0].forget());
    7275               0 :       mDelayedEvents.RemoveElementAt(0);
    7276               0 :       ev->Dispatch(this);
    7277                 :     }
    7278               0 :     if (!doc->EventHandlingSuppressed()) {
    7279               0 :       mDelayedEvents.Clear();
    7280                 :     }
    7281                 :   }
    7282                 : }
    7283                 : 
    7284                 : static void
    7285               0 : ThawElement(nsIContent *aContent, void *aShell)
    7286                 : {
    7287               0 :   nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(aContent));
    7288               0 :   if (olc) {
    7289               0 :     olc->AsyncStartPluginInstance();
    7290                 :   }
    7291               0 : }
    7292                 : 
    7293                 : static bool
    7294               0 : ThawSubDocument(nsIDocument *aDocument, void *aData)
    7295                 : {
    7296               0 :   nsIPresShell *shell = aDocument->GetShell();
    7297               0 :   if (shell)
    7298               0 :     shell->Thaw();
    7299                 : 
    7300               0 :   return true;
    7301                 : }
    7302                 : 
    7303                 : void
    7304               0 : PresShell::Thaw()
    7305                 : {
    7306               0 :   nsPresContext* presContext = GetPresContext();
    7307               0 :   if (presContext &&
    7308               0 :       presContext->RefreshDriver()->PresContext() == presContext) {
    7309               0 :     presContext->RefreshDriver()->Thaw();
    7310                 :   }
    7311                 : 
    7312               0 :   mDocument->EnumerateFreezableElements(ThawElement, this);
    7313                 : 
    7314               0 :   if (mDocument)
    7315               0 :     mDocument->EnumerateSubDocuments(ThawSubDocument, nsnull);
    7316                 : 
    7317                 :   // Get the activeness of our presshell, as this might have changed
    7318                 :   // while we were in the bfcache
    7319               0 :   QueryIsActive();
    7320                 : 
    7321                 :   // We're now unfrozen
    7322               0 :   mFrozen = false;
    7323               0 :   UpdateImageLockingState();
    7324                 : 
    7325               0 :   UnsuppressPainting();
    7326               0 : }
    7327                 : 
    7328                 : //--------------------------------------------------------
    7329                 : // Start of protected and private methods on the PresShell
    7330                 : //--------------------------------------------------------
    7331                 : 
    7332                 : void
    7333               0 : PresShell::MaybeScheduleReflow()
    7334                 : {
    7335               0 :   ASSERT_REFLOW_SCHEDULED_STATE();
    7336               0 :   if (mReflowScheduled || mIsDestroying || mIsReflowing ||
    7337               0 :       mDirtyRoots.Length() == 0)
    7338               0 :     return;
    7339                 : 
    7340               0 :   if (!mPresContext->HasPendingInterrupt() || !ScheduleReflowOffTimer()) {
    7341               0 :     ScheduleReflow();
    7342                 :   }
    7343                 : 
    7344               0 :   ASSERT_REFLOW_SCHEDULED_STATE();
    7345                 : }
    7346                 : 
    7347                 : void
    7348               0 : PresShell::ScheduleReflow()
    7349                 : {
    7350               0 :   NS_PRECONDITION(!mReflowScheduled, "Why are we trying to schedule a reflow?");
    7351               0 :   ASSERT_REFLOW_SCHEDULED_STATE();
    7352                 : 
    7353               0 :   if (GetPresContext()->RefreshDriver()->AddLayoutFlushObserver(this)) {
    7354               0 :     mReflowScheduled = true;
    7355                 :   }
    7356                 : 
    7357               0 :   ASSERT_REFLOW_SCHEDULED_STATE();
    7358               0 : }
    7359                 : 
    7360                 : nsresult
    7361               0 : PresShell::DidCauseReflow()
    7362                 : {
    7363               0 :   NS_ASSERTION(mChangeNestCount != 0, "Unexpected call to DidCauseReflow()");
    7364               0 :   --mChangeNestCount;
    7365               0 :   nsContentUtils::RemoveScriptBlocker();
    7366                 : 
    7367               0 :   return NS_OK;
    7368                 : }
    7369                 : 
    7370                 : void
    7371               0 : PresShell::WillDoReflow()
    7372                 : {
    7373                 :   // We just reflowed, tell the caret that its frame might have moved.
    7374                 :   // XXXbz that comment makes no sense
    7375               0 :   if (mCaret) {
    7376               0 :     mCaret->InvalidateOutsideCaret();
    7377                 :   }
    7378                 : 
    7379               0 :   mPresContext->FlushUserFontSet();
    7380                 : 
    7381               0 :   mFrameConstructor->BeginUpdate();
    7382               0 : }
    7383                 : 
    7384                 : void
    7385               0 : PresShell::DidDoReflow(bool aInterruptible)
    7386                 : {
    7387               0 :   mFrameConstructor->EndUpdate();
    7388                 :   
    7389               0 :   HandlePostedReflowCallbacks(aInterruptible);
    7390               0 :   if (sSynthMouseMove) {
    7391               0 :     SynthesizeMouseMove(false);
    7392                 :   }
    7393               0 :   if (mCaret) {
    7394                 :     // Update the caret's position now to account for any changes created by
    7395                 :     // the reflow.
    7396               0 :     mCaret->InvalidateOutsideCaret();
    7397               0 :     mCaret->UpdateCaretPosition();
    7398                 :   }
    7399               0 : }
    7400                 : 
    7401                 : static PLDHashOperator
    7402               0 : MarkFramesDirtyToRoot(nsPtrHashKey<nsIFrame>* p, void* closure)
    7403                 : {
    7404               0 :   nsIFrame* target = static_cast<nsIFrame*>(closure);
    7405               0 :   for (nsIFrame* f = p->GetKey(); f && !NS_SUBTREE_DIRTY(f);
    7406                 :        f = f->GetParent()) {
    7407               0 :     f->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
    7408                 : 
    7409               0 :     if (f == target) {
    7410               0 :       break;
    7411                 :     }
    7412                 :   }
    7413                 : 
    7414               0 :   return PL_DHASH_NEXT;
    7415                 : }
    7416                 : 
    7417                 : void
    7418               0 : PresShell::sReflowContinueCallback(nsITimer* aTimer, void* aPresShell)
    7419                 : {
    7420               0 :   nsRefPtr<PresShell> self = static_cast<PresShell*>(aPresShell);
    7421                 : 
    7422               0 :   NS_PRECONDITION(aTimer == self->mReflowContinueTimer, "Unexpected timer");
    7423               0 :   self->mReflowContinueTimer = nsnull;
    7424               0 :   self->ScheduleReflow();
    7425               0 : }
    7426                 : 
    7427                 : bool
    7428               0 : PresShell::ScheduleReflowOffTimer()
    7429                 : {
    7430               0 :   NS_PRECONDITION(!mReflowScheduled, "Shouldn't get here");
    7431               0 :   ASSERT_REFLOW_SCHEDULED_STATE();
    7432                 : 
    7433               0 :   if (!mReflowContinueTimer) {
    7434               0 :     mReflowContinueTimer = do_CreateInstance("@mozilla.org/timer;1");
    7435               0 :     if (!mReflowContinueTimer ||
    7436               0 :         NS_FAILED(mReflowContinueTimer->
    7437                 :                     InitWithFuncCallback(sReflowContinueCallback, this, 30,
    7438                 :                                          nsITimer::TYPE_ONE_SHOT))) {
    7439               0 :       return false;
    7440                 :     }
    7441                 :   }
    7442               0 :   return true;
    7443                 : }
    7444                 : 
    7445                 : bool
    7446               0 : PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
    7447                 : {
    7448                 :   NS_TIME_FUNCTION_WITH_DOCURL;
    7449               0 :   SAMPLE_LABEL("layout", "DoReflow");
    7450                 : 
    7451               0 :   if (mReflowContinueTimer) {
    7452               0 :     mReflowContinueTimer->Cancel();
    7453               0 :     mReflowContinueTimer = nsnull;
    7454                 :   }
    7455                 : 
    7456               0 :   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
    7457                 : 
    7458               0 :   nsRefPtr<nsRenderingContext> rcx = GetReferenceRenderingContext();
    7459               0 :   if (!rcx) {
    7460               0 :     NS_NOTREACHED("CreateRenderingContext failure");
    7461               0 :     return false;
    7462                 :   }
    7463                 : 
    7464               0 :   NS_ASSERTION(!mPresContext->mCurrentInflationContainer,
    7465                 :                "current inflation container should be null");
    7466                 :   AutoRestore<nsIFrame*> restoreInflationContainer(mPresContext->
    7467               0 :                            mCurrentInflationContainer);
    7468               0 :   for (nsIFrame *f = target->GetParent(); f; f = f->GetParent()) {
    7469               0 :     if (nsLayoutUtils::IsContainerForFontSizeInflation(f)) {
    7470               0 :       NS_ASSERTION(!(f->GetStateBits() & NS_FRAME_IN_REFLOW),
    7471                 :                    "a frame outside should not be in reflow");
    7472               0 :       mPresContext->mCurrentInflationContainer = f;
    7473               0 :       mPresContext->mCurrentInflationContainerWidth = f->GetContentRect().width;
    7474               0 :       break;
    7475                 :     }
    7476                 :   }
    7477                 : 
    7478                 : #ifdef DEBUG
    7479               0 :   mCurrentReflowRoot = target;
    7480                 : #endif
    7481                 : 
    7482               0 :   target->WillReflow(mPresContext);
    7483                 : 
    7484                 :   // If the target frame is the root of the frame hierarchy, then
    7485                 :   // use all the available space. If it's simply a `reflow root',
    7486                 :   // then use the target frame's size as the available space.
    7487               0 :   nsSize size;
    7488               0 :   if (target == rootFrame) {
    7489               0 :      size = mPresContext->GetVisibleArea().Size();
    7490                 : 
    7491                 :      // target->GetRect() has the old size of the frame,
    7492                 :      // mPresContext->GetVisibleArea() has the new size.
    7493               0 :      target->InvalidateRectDifference(mPresContext->GetVisibleArea(),
    7494               0 :                                       target->GetRect());
    7495                 :   } else {
    7496               0 :      size = target->GetSize();
    7497                 :   }
    7498                 : 
    7499               0 :   NS_ASSERTION(!target->GetNextInFlow() && !target->GetPrevInFlow(),
    7500                 :                "reflow roots should never split");
    7501                 : 
    7502                 :   // Don't pass size directly to the reflow state, since a
    7503                 :   // constrained height implies page/column breaking.
    7504               0 :   nsSize reflowSize(size.width, NS_UNCONSTRAINEDSIZE);
    7505               0 :   nsHTMLReflowState reflowState(mPresContext, target, rcx, reflowSize);
    7506                 : 
    7507               0 :   if (rootFrame == target) {
    7508                 :     // When the root frame is being reflowed with unconstrained height
    7509                 :     // (which happens when we're called from
    7510                 :     // DocumentViewerImpl::SizeToContent), we're effectively doing a
    7511                 :     // vertical resize, since it changes the meaning of percentage
    7512                 :     // heights even if no heights actually changed.  The same applies
    7513                 :     // when we reflow again after that computation.  This is an unusual
    7514                 :     // case, and isn't caught by nsHTMLReflowState::InitResizeFlags.
    7515               0 :     bool hasUnconstrainedHeight = size.height == NS_UNCONSTRAINEDSIZE;
    7516                 : 
    7517               0 :     if (hasUnconstrainedHeight || mLastRootReflowHadUnconstrainedHeight) {
    7518               0 :       reflowState.mFlags.mVResize = true;
    7519                 :     }
    7520                 : 
    7521               0 :     mLastRootReflowHadUnconstrainedHeight = hasUnconstrainedHeight;
    7522                 :   }
    7523                 : 
    7524                 :   // fix the computed height
    7525               0 :   NS_ASSERTION(reflowState.mComputedMargin == nsMargin(0, 0, 0, 0),
    7526                 :                "reflow state should not set margin for reflow roots");
    7527               0 :   if (size.height != NS_UNCONSTRAINEDSIZE) {
    7528                 :     nscoord computedHeight =
    7529               0 :       size.height - reflowState.mComputedBorderPadding.TopBottom();
    7530               0 :     computedHeight = NS_MAX(computedHeight, 0);
    7531               0 :     reflowState.SetComputedHeight(computedHeight);
    7532                 :   }
    7533               0 :   NS_ASSERTION(reflowState.ComputedWidth() ==
    7534                 :                  size.width -
    7535                 :                    reflowState.mComputedBorderPadding.LeftRight(),
    7536                 :                "reflow state computed incorrect width");
    7537                 : 
    7538               0 :   mPresContext->ReflowStarted(aInterruptible);
    7539               0 :   mIsReflowing = true;
    7540                 : 
    7541                 :   nsReflowStatus status;
    7542               0 :   nsHTMLReflowMetrics desiredSize;
    7543               0 :   target->Reflow(mPresContext, desiredSize, reflowState, status);
    7544                 : 
    7545                 :   // If an incremental reflow is initiated at a frame other than the
    7546                 :   // root frame, then its desired size had better not change!  If it's
    7547                 :   // initiated at the root, then the size better not change unless its
    7548                 :   // height was unconstrained to start with.
    7549               0 :   nsRect boundsRelativeToTarget = nsRect(0, 0, desiredSize.width, desiredSize.height);
    7550               0 :   NS_ASSERTION((target == rootFrame && size.height == NS_UNCONSTRAINEDSIZE) ||
    7551                 :                (desiredSize.width == size.width &&
    7552                 :                 desiredSize.height == size.height),
    7553                 :                "non-root frame's desired size changed during an "
    7554                 :                "incremental reflow");
    7555               0 :   NS_ASSERTION(target == rootFrame ||
    7556                 :                desiredSize.VisualOverflow().IsEqualInterior(boundsRelativeToTarget),
    7557                 :                "non-root reflow roots must not have visible overflow");
    7558               0 :   NS_ASSERTION(target == rootFrame ||
    7559                 :                desiredSize.ScrollableOverflow().IsEqualEdges(boundsRelativeToTarget),
    7560                 :                "non-root reflow roots must not have scrollable overflow");
    7561               0 :   NS_ASSERTION(status == NS_FRAME_COMPLETE,
    7562                 :                "reflow roots should never split");
    7563                 : 
    7564               0 :   target->SetSize(boundsRelativeToTarget.Size());
    7565                 : 
    7566                 :   // Always use boundsRelativeToTarget here, not desiredSize.GetVisualOverflowArea(),
    7567                 :   // because for root frames (where they could be different, since root frames
    7568                 :   // are allowed to have overflow) the root view bounds need to match the
    7569                 :   // viewport bounds; the view manager "window dimensions" code depends on it.
    7570                 :   nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, target,
    7571                 :                                              target->GetView(),
    7572               0 :                                              boundsRelativeToTarget);
    7573                 :   nsContainerFrame::SyncWindowProperties(mPresContext, target,
    7574               0 :                                          target->GetView());
    7575                 : 
    7576               0 :   target->DidReflow(mPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
    7577               0 :   if (target == rootFrame && size.height == NS_UNCONSTRAINEDSIZE) {
    7578               0 :     mPresContext->SetVisibleArea(boundsRelativeToTarget);
    7579                 :   }
    7580                 : 
    7581                 : #ifdef DEBUG
    7582               0 :   mCurrentReflowRoot = nsnull;
    7583                 : #endif
    7584                 : 
    7585               0 :   NS_ASSERTION(mPresContext->HasPendingInterrupt() ||
    7586                 :                mFramesToDirty.Count() == 0,
    7587                 :                "Why do we need to dirty anything if not interrupted?");
    7588                 : 
    7589               0 :   mIsReflowing = false;
    7590               0 :   bool interrupted = mPresContext->HasPendingInterrupt();
    7591               0 :   if (interrupted) {
    7592                 :     // Make sure target gets reflowed again.
    7593               0 :     mFramesToDirty.EnumerateEntries(&MarkFramesDirtyToRoot, target);
    7594               0 :     NS_ASSERTION(NS_SUBTREE_DIRTY(target), "Why is the target not dirty?");
    7595               0 :     mDirtyRoots.AppendElement(target);
    7596               0 :     mDocument->SetNeedLayoutFlush();
    7597                 : 
    7598                 :     // Clear mFramesToDirty after we've done the NS_SUBTREE_DIRTY(target)
    7599                 :     // assertion so that if it fails it's easier to see what's going on.
    7600                 : #ifdef NOISY_INTERRUPTIBLE_REFLOW
    7601                 :     printf("mFramesToDirty.Count() == %u\n", mFramesToDirty.Count());
    7602                 : #endif /* NOISY_INTERRUPTIBLE_REFLOW */
    7603               0 :     mFramesToDirty.Clear();
    7604                 : 
    7605                 :     // Any FlushPendingNotifications with interruptible reflows
    7606                 :     // should be suppressed now. We don't want to do extra reflow work
    7607                 :     // before our reflow event happens.
    7608               0 :     mSuppressInterruptibleReflows = true;
    7609               0 :     MaybeScheduleReflow();
    7610                 :   }
    7611                 : 
    7612               0 :   nsRootPresContext* rootPC = mPresContext->GetRootPresContext();
    7613               0 :   if (rootPC) {
    7614               0 :     rootPC->RequestUpdatePluginGeometry(target);
    7615                 :   }
    7616                 : 
    7617               0 :   return !interrupted;
    7618                 : }
    7619                 : 
    7620                 : #ifdef DEBUG
    7621                 : void
    7622               0 : PresShell::DoVerifyReflow()
    7623                 : {
    7624               0 :   if (GetVerifyReflowEnable()) {
    7625                 :     // First synchronously render what we have so far so that we can
    7626                 :     // see it.
    7627               0 :     nsIView* rootView = mViewManager->GetRootView();
    7628               0 :     mViewManager->InvalidateView(rootView);
    7629                 : 
    7630               0 :     FlushPendingNotifications(Flush_Layout);
    7631               0 :     mInVerifyReflow = true;
    7632               0 :     bool ok = VerifyIncrementalReflow();
    7633               0 :     mInVerifyReflow = false;
    7634               0 :     if (VERIFY_REFLOW_ALL & gVerifyReflowFlags) {
    7635                 :       printf("ProcessReflowCommands: finished (%s)\n",
    7636               0 :              ok ? "ok" : "failed");
    7637                 :     }
    7638                 : 
    7639               0 :     if (!mDirtyRoots.IsEmpty()) {
    7640               0 :       printf("XXX yikes! reflow commands queued during verify-reflow\n");
    7641                 :     }
    7642                 :   }
    7643               0 : }
    7644                 : #endif
    7645                 : 
    7646                 : bool
    7647               0 : PresShell::ProcessReflowCommands(bool aInterruptible)
    7648                 : {
    7649               0 :   if (mDirtyRoots.IsEmpty() && !mShouldUnsuppressPainting) {
    7650                 :     // Nothing to do; bail out
    7651               0 :     return true;
    7652                 :   }
    7653                 : 
    7654                 :   NS_TIME_FUNCTION_WITH_DOCURL;
    7655               0 :   mozilla::TimeStamp timerStart = mozilla::TimeStamp::Now();
    7656               0 :   bool interrupted = false;
    7657               0 :   if (!mDirtyRoots.IsEmpty()) {
    7658                 : 
    7659                 : #ifdef DEBUG
    7660               0 :     if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
    7661               0 :       printf("ProcessReflowCommands: begin incremental reflow\n");
    7662                 :     }
    7663                 : #endif
    7664                 : 
    7665                 :     // If reflow is interruptible, then make a note of our deadline.
    7666                 :     const PRIntervalTime deadline = aInterruptible
    7667               0 :         ? PR_IntervalNow() + PR_MicrosecondsToInterval(gMaxRCProcessingTime)
    7668               0 :         : (PRIntervalTime)0;
    7669                 : 
    7670                 :     // Scope for the reflow entry point
    7671                 :     {
    7672               0 :       nsAutoScriptBlocker scriptBlocker;
    7673               0 :       WillDoReflow();
    7674               0 :       AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
    7675               0 :       nsIViewManager::AutoDisableRefresh refreshBlocker(mViewManager);
    7676                 : 
    7677               0 :       do {
    7678                 :         // Send an incremental reflow notification to the target frame.
    7679               0 :         PRInt32 idx = mDirtyRoots.Length() - 1;
    7680               0 :         nsIFrame *target = mDirtyRoots[idx];
    7681               0 :         mDirtyRoots.RemoveElementAt(idx);
    7682                 : 
    7683               0 :         if (!NS_SUBTREE_DIRTY(target)) {
    7684                 :           // It's not dirty anymore, which probably means the notification
    7685                 :           // was posted in the middle of a reflow (perhaps with a reflow
    7686                 :           // root in the middle).  Don't do anything.
    7687               0 :           continue;
    7688                 :         }
    7689                 : 
    7690               0 :         interrupted = !DoReflow(target, aInterruptible);
    7691                 : 
    7692                 :         // Keep going until we're out of reflow commands, or we've run
    7693                 :         // past our deadline, or we're interrupted.
    7694               0 :       } while (!interrupted && !mDirtyRoots.IsEmpty() &&
    7695               0 :                (!aInterruptible || PR_IntervalNow() < deadline));
    7696                 : 
    7697               0 :       interrupted = !mDirtyRoots.IsEmpty();
    7698                 :     }
    7699                 : 
    7700                 :     // Exiting the scriptblocker might have killed us
    7701               0 :     if (!mIsDestroying) {
    7702               0 :       DidDoReflow(aInterruptible);
    7703                 :     }
    7704                 : 
    7705                 :     // DidDoReflow might have killed us
    7706               0 :     if (!mIsDestroying) {
    7707                 : #ifdef DEBUG
    7708               0 :       if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
    7709                 :         printf("\nPresShell::ProcessReflowCommands() finished: this=%p\n",
    7710               0 :                (void*)this);
    7711                 :       }
    7712               0 :       DoVerifyReflow();
    7713                 : #endif
    7714                 : 
    7715                 :       // If any new reflow commands were enqueued during the reflow, schedule
    7716                 :       // another reflow event to process them.  Note that we want to do this
    7717                 :       // after DidDoReflow(), since that method can change whether there are
    7718                 :       // dirty roots around by flushing, and there's no point in posting a
    7719                 :       // reflow event just to have the flush revoke it.
    7720               0 :       if (!mDirtyRoots.IsEmpty()) {
    7721               0 :         MaybeScheduleReflow();
    7722                 :         // And tell our document that we might need flushing
    7723               0 :         mDocument->SetNeedLayoutFlush();
    7724                 :       }
    7725                 :     }
    7726                 :   }
    7727                 : 
    7728               0 :   if (!mIsDestroying && mShouldUnsuppressPainting &&
    7729               0 :       mDirtyRoots.IsEmpty()) {
    7730                 :     // We only unlock if we're out of reflows.  It's pointless
    7731                 :     // to unlock if reflows are still pending, since reflows
    7732                 :     // are just going to thrash the frames around some more.  By
    7733                 :     // waiting we avoid an overeager "jitter" effect.
    7734               0 :     mShouldUnsuppressPainting = false;
    7735               0 :     UnsuppressAndInvalidate();
    7736                 :   }
    7737                 : 
    7738               0 :   if (mDocument->GetRootElement()) {
    7739                 :     Telemetry::ID id;
    7740               0 :     if (mDocument->GetRootElement()->IsXUL()) {
    7741                 :       id = mIsActive
    7742                 :         ? Telemetry::XUL_FOREGROUND_REFLOW_MS
    7743               0 :         : Telemetry::XUL_BACKGROUND_REFLOW_MS;
    7744                 :     } else {
    7745                 :       id = mIsActive
    7746                 :         ? Telemetry::HTML_FOREGROUND_REFLOW_MS
    7747               0 :         : Telemetry::HTML_BACKGROUND_REFLOW_MS;
    7748                 :     }
    7749               0 :     Telemetry::AccumulateTimeDelta(id, timerStart);
    7750                 :   }
    7751                 : 
    7752               0 :   return !interrupted;
    7753                 : }
    7754                 : 
    7755                 : #ifdef MOZ_XUL
    7756                 : /*
    7757                 :  * It's better to add stuff to the |DidSetStyleContext| method of the
    7758                 :  * relevant frames than adding it here.  These methods should (ideally,
    7759                 :  * anyway) go away.
    7760                 :  */
    7761                 : 
    7762                 : // Return value says whether to walk children.
    7763                 : typedef bool (* frameWalkerFn)(nsIFrame *aFrame, void *aClosure);
    7764                 :    
    7765                 : static bool
    7766               0 : ReResolveMenusAndTrees(nsIFrame *aFrame, void *aClosure)
    7767                 : {
    7768                 :   // Trees have a special style cache that needs to be flushed when
    7769                 :   // the theme changes.
    7770               0 :   nsTreeBodyFrame *treeBody = do_QueryFrame(aFrame);
    7771               0 :   if (treeBody)
    7772               0 :     treeBody->ClearStyleAndImageCaches();
    7773                 : 
    7774                 :   // We deliberately don't re-resolve style on a menu's popup
    7775                 :   // sub-content, since doing so slows menus to a crawl.  That means we
    7776                 :   // have to special-case them on a skin switch, and ensure that the
    7777                 :   // popup frames just get destroyed completely.
    7778               0 :   if (aFrame && aFrame->GetType() == nsGkAtoms::menuFrame)
    7779               0 :     (static_cast<nsMenuFrame *>(aFrame))->CloseMenu(true);
    7780               0 :   return true;
    7781                 : }
    7782                 : 
    7783                 : static bool
    7784               0 : ReframeImageBoxes(nsIFrame *aFrame, void *aClosure)
    7785                 : {
    7786               0 :   nsStyleChangeList *list = static_cast<nsStyleChangeList*>(aClosure);
    7787               0 :   if (aFrame->GetType() == nsGkAtoms::imageBoxFrame) {
    7788                 :     list->AppendChange(aFrame, aFrame->GetContent(),
    7789               0 :                        NS_STYLE_HINT_FRAMECHANGE);
    7790               0 :     return false; // don't walk descendants
    7791                 :   }
    7792               0 :   return true; // walk descendants
    7793                 : }
    7794                 : 
    7795                 : static void
    7796               0 : WalkFramesThroughPlaceholders(nsPresContext *aPresContext, nsIFrame *aFrame,
    7797                 :                               frameWalkerFn aFunc, void *aClosure)
    7798                 : {
    7799               0 :   bool walkChildren = (*aFunc)(aFrame, aClosure);
    7800               0 :   if (!walkChildren)
    7801               0 :     return;
    7802                 : 
    7803               0 :   nsIFrame::ChildListIterator lists(aFrame);
    7804               0 :   for (; !lists.IsDone(); lists.Next()) {
    7805               0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
    7806               0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
    7807               0 :       nsIFrame* child = childFrames.get();
    7808               0 :       if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
    7809                 :         // only do frames that are in flow, and recur through the
    7810                 :         // out-of-flows of placeholders.
    7811                 :         WalkFramesThroughPlaceholders(aPresContext,
    7812                 :                                       nsPlaceholderFrame::GetRealFrameFor(child),
    7813               0 :                                       aFunc, aClosure);
    7814                 :       }
    7815                 :     }
    7816                 :   }
    7817                 : }
    7818                 : #endif
    7819                 : 
    7820                 : NS_IMETHODIMP
    7821               0 : PresShell::Observe(nsISupports* aSubject, 
    7822                 :                    const char* aTopic,
    7823                 :                    const PRUnichar* aData)
    7824                 : {
    7825                 : #ifdef MOZ_XUL
    7826               0 :   if (!nsCRT::strcmp(aTopic, "chrome-flush-skin-caches")) {
    7827               0 :     nsIFrame *rootFrame = mFrameConstructor->GetRootFrame();
    7828                 :     // Need to null-check because "chrome-flush-skin-caches" can happen
    7829                 :     // at interesting times during startup.
    7830               0 :     if (rootFrame) {
    7831               0 :       NS_ASSERTION(mViewManager, "View manager must exist");
    7832                 : 
    7833               0 :       nsWeakFrame weakRoot(rootFrame);
    7834                 :       // Have to make sure that the content notifications are flushed before we
    7835                 :       // start messing with the frame model; otherwise we can get content doubling.
    7836               0 :       mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
    7837                 : 
    7838               0 :       if (weakRoot.IsAlive()) {
    7839                 :         WalkFramesThroughPlaceholders(mPresContext, rootFrame,
    7840               0 :                                       &ReResolveMenusAndTrees, nsnull);
    7841                 : 
    7842                 :         // Because "chrome:" URL equality is messy, reframe image box
    7843                 :         // frames (hack!).
    7844               0 :         nsStyleChangeList changeList;
    7845                 :         WalkFramesThroughPlaceholders(mPresContext, rootFrame,
    7846               0 :                                       ReframeImageBoxes, &changeList);
    7847                 :         // Mark ourselves as not safe to flush while we're doing frame
    7848                 :         // construction.
    7849                 :         {
    7850               0 :           nsAutoScriptBlocker scriptBlocker;
    7851               0 :           ++mChangeNestCount;
    7852               0 :           mFrameConstructor->ProcessRestyledFrames(changeList);
    7853               0 :           --mChangeNestCount;
    7854                 :         }
    7855                 :       }
    7856                 :     }
    7857               0 :     return NS_OK;
    7858                 :   }
    7859                 : #endif
    7860                 : 
    7861               0 :   if (!nsCRT::strcmp(aTopic, "agent-sheet-added") && mStyleSet) {
    7862               0 :     AddAgentSheet(aSubject);
    7863               0 :     return NS_OK;
    7864                 :   }
    7865                 : 
    7866               0 :   if (!nsCRT::strcmp(aTopic, "user-sheet-added") && mStyleSet) {
    7867               0 :     AddUserSheet(aSubject);
    7868               0 :     return NS_OK;
    7869                 :   }
    7870                 : 
    7871               0 :   if (!nsCRT::strcmp(aTopic, "agent-sheet-removed") && mStyleSet) {
    7872               0 :     RemoveSheet(nsStyleSet::eAgentSheet, aSubject);
    7873               0 :     return NS_OK;
    7874                 :   }
    7875                 : 
    7876               0 :   if (!nsCRT::strcmp(aTopic, "user-sheet-removed") && mStyleSet) {
    7877               0 :     RemoveSheet(nsStyleSet::eUserSheet, aSubject);
    7878               0 :     return NS_OK;
    7879                 :   }
    7880                 : 
    7881               0 :   NS_WARNING("unrecognized topic in PresShell::Observe");
    7882               0 :   return NS_ERROR_FAILURE;
    7883                 : }
    7884                 : 
    7885                 : bool
    7886               0 : nsIPresShell::AddRefreshObserverInternal(nsARefreshObserver* aObserver,
    7887                 :                                          mozFlushType aFlushType)
    7888                 : {
    7889               0 :   nsPresContext* presContext = GetPresContext();
    7890                 :   return presContext ? presContext->RefreshDriver()->
    7891               0 :     AddRefreshObserver(aObserver, aFlushType) : false;
    7892                 : }
    7893                 : 
    7894                 : /* virtual */ bool
    7895               0 : nsIPresShell::AddRefreshObserverExternal(nsARefreshObserver* aObserver,
    7896                 :                                          mozFlushType aFlushType)
    7897                 : {
    7898               0 :   return AddRefreshObserverInternal(aObserver, aFlushType);
    7899                 : }
    7900                 : 
    7901                 : bool
    7902               0 : nsIPresShell::RemoveRefreshObserverInternal(nsARefreshObserver* aObserver,
    7903                 :                                             mozFlushType aFlushType)
    7904                 : {
    7905               0 :   nsPresContext* presContext = GetPresContext();
    7906                 :   return presContext ? presContext->RefreshDriver()->
    7907               0 :     RemoveRefreshObserver(aObserver, aFlushType) : false;
    7908                 : }
    7909                 : 
    7910                 : /* virtual */ bool
    7911               0 : nsIPresShell::RemoveRefreshObserverExternal(nsARefreshObserver* aObserver,
    7912                 :                                             mozFlushType aFlushType)
    7913                 : {
    7914               0 :   return RemoveRefreshObserverInternal(aObserver, aFlushType);
    7915                 : }
    7916                 : 
    7917                 : //------------------------------------------------------
    7918                 : // End of protected and private methods on the PresShell
    7919                 : //------------------------------------------------------
    7920                 : 
    7921                 : // Start of DEBUG only code
    7922                 : 
    7923                 : #ifdef NS_DEBUG
    7924                 : #include "nsIURL.h"
    7925                 : #include "nsILinkHandler.h"
    7926                 : 
    7927                 : static NS_DEFINE_CID(kViewManagerCID, NS_VIEW_MANAGER_CID);
    7928                 : 
    7929                 : static void
    7930               0 : LogVerifyMessage(nsIFrame* k1, nsIFrame* k2, const char* aMsg)
    7931                 : {
    7932               0 :   nsAutoString n1, n2;
    7933               0 :   if (k1) {
    7934               0 :     k1->GetFrameName(n1);
    7935                 :   } else {
    7936               0 :     n1.Assign(NS_LITERAL_STRING("(null)"));
    7937                 :   }
    7938                 : 
    7939               0 :   if (k2) {
    7940               0 :     k2->GetFrameName(n2);
    7941                 :   } else {
    7942               0 :     n2.Assign(NS_LITERAL_STRING("(null)"));
    7943                 :   }
    7944                 : 
    7945                 :   printf("verifyreflow: %s %p != %s %p  %s\n",
    7946               0 :          NS_LossyConvertUTF16toASCII(n1).get(), (void*)k1,
    7947               0 :          NS_LossyConvertUTF16toASCII(n2).get(), (void*)k2, aMsg);
    7948               0 : }
    7949                 : 
    7950                 : static void
    7951               0 : LogVerifyMessage(nsIFrame* k1, nsIFrame* k2, const char* aMsg,
    7952                 :                  const nsRect& r1, const nsRect& r2)
    7953                 : {
    7954               0 :   printf("VerifyReflow Error:\n");
    7955               0 :   nsAutoString name;
    7956                 : 
    7957               0 :   if (k1) {
    7958               0 :     k1->GetFrameName(name);
    7959               0 :     printf("  %s %p ", NS_LossyConvertUTF16toASCII(name).get(), (void*)k1);
    7960                 :   }
    7961               0 :   printf("{%d, %d, %d, %d} != \n", r1.x, r1.y, r1.width, r1.height);
    7962                 : 
    7963               0 :   if (k2) {
    7964               0 :     k2->GetFrameName(name);
    7965               0 :     printf("  %s %p ", NS_LossyConvertUTF16toASCII(name).get(), (void*)k2);
    7966                 :   }
    7967                 :   printf("{%d, %d, %d, %d}\n  %s\n",
    7968               0 :          r2.x, r2.y, r2.width, r2.height, aMsg);
    7969               0 : }
    7970                 : 
    7971                 : static void
    7972               0 : LogVerifyMessage(nsIFrame* k1, nsIFrame* k2, const char* aMsg,
    7973                 :                  const nsIntRect& r1, const nsIntRect& r2)
    7974                 : {
    7975               0 :   printf("VerifyReflow Error:\n");
    7976               0 :   nsAutoString name;
    7977                 : 
    7978               0 :   if (k1) {
    7979               0 :     k1->GetFrameName(name);
    7980               0 :     printf("  %s %p ", NS_LossyConvertUTF16toASCII(name).get(), (void*)k1);
    7981                 :   }
    7982               0 :   printf("{%d, %d, %d, %d} != \n", r1.x, r1.y, r1.width, r1.height);
    7983                 : 
    7984               0 :   if (k2) {
    7985               0 :     k2->GetFrameName(name);
    7986               0 :     printf("  %s %p ", NS_LossyConvertUTF16toASCII(name).get(), (void*)k2);
    7987                 :   }
    7988                 :   printf("{%d, %d, %d, %d}\n  %s\n",
    7989               0 :          r2.x, r2.y, r2.width, r2.height, aMsg);
    7990               0 : }
    7991                 : 
    7992                 : static bool
    7993               0 : CompareTrees(nsPresContext* aFirstPresContext, nsIFrame* aFirstFrame, 
    7994                 :              nsPresContext* aSecondPresContext, nsIFrame* aSecondFrame)
    7995                 : {
    7996               0 :   if (!aFirstPresContext || !aFirstFrame || !aSecondPresContext || !aSecondFrame)
    7997               0 :     return true;
    7998                 :   // XXX Evil hack to reduce false positives; I can't seem to figure
    7999                 :   // out how to flush scrollbar changes correctly
    8000                 :   //if (aFirstFrame->GetType() == nsGkAtoms::scrollbarFrame)
    8001                 :   //  return true;
    8002               0 :   bool ok = true;
    8003               0 :   nsIFrame::ChildListIterator lists1(aFirstFrame);
    8004               0 :   nsIFrame::ChildListIterator lists2(aSecondFrame);
    8005               0 :   do {
    8006               0 :     const nsFrameList& kids1 = !lists1.IsDone() ? lists1.CurrentList() : nsFrameList();
    8007               0 :     const nsFrameList& kids2 = !lists2.IsDone() ? lists2.CurrentList() : nsFrameList();
    8008               0 :     PRInt32 l1 = kids1.GetLength();
    8009               0 :     PRInt32 l2 = kids2.GetLength();;
    8010               0 :     if (l1 != l2) {
    8011               0 :       ok = false;
    8012                 :       LogVerifyMessage(kids1.FirstChild(), kids2.FirstChild(),
    8013               0 :                        "child counts don't match: ");
    8014               0 :       printf("%d != %d\n", l1, l2);
    8015               0 :       if (0 == (VERIFY_REFLOW_ALL & gVerifyReflowFlags)) {
    8016                 :         break;
    8017                 :       }
    8018                 :     }
    8019                 : 
    8020               0 :     nsIntRect r1, r2;
    8021                 :     nsIView* v1, *v2;
    8022               0 :     for (nsFrameList::Enumerator e1(kids1), e2(kids2);
    8023                 :          ;
    8024               0 :          e1.Next(), e2.Next()) {
    8025               0 :       nsIFrame* k1 = e1.get();
    8026               0 :       nsIFrame* k2 = e2.get();
    8027               0 :       if (((nsnull == k1) && (nsnull != k2)) ||
    8028                 :           ((nsnull != k1) && (nsnull == k2))) {
    8029               0 :         ok = false;
    8030               0 :         LogVerifyMessage(k1, k2, "child lists are different\n");
    8031               0 :         break;
    8032                 :       }
    8033               0 :       else if (nsnull != k1) {
    8034                 :         // Verify that the frames are the same size
    8035               0 :         if (!k1->GetRect().IsEqualInterior(k2->GetRect())) {
    8036               0 :           ok = false;
    8037               0 :           LogVerifyMessage(k1, k2, "(frame rects)", k1->GetRect(), k2->GetRect());
    8038                 :         }
    8039                 : 
    8040                 :         // Make sure either both have views or neither have views; if they
    8041                 :         // do have views, make sure the views are the same size. If the
    8042                 :         // views have widgets, make sure they both do or neither does. If
    8043                 :         // they do, make sure the widgets are the same size.
    8044               0 :         v1 = k1->GetView();
    8045               0 :         v2 = k2->GetView();
    8046               0 :         if (((nsnull == v1) && (nsnull != v2)) ||
    8047                 :             ((nsnull != v1) && (nsnull == v2))) {
    8048               0 :           ok = false;
    8049               0 :           LogVerifyMessage(k1, k2, "child views are not matched\n");
    8050                 :         }
    8051               0 :         else if (nsnull != v1) {
    8052               0 :           if (!v1->GetBounds().IsEqualInterior(v2->GetBounds())) {
    8053               0 :             LogVerifyMessage(k1, k2, "(view rects)", v1->GetBounds(), v2->GetBounds());
    8054                 :           }
    8055                 : 
    8056               0 :           nsIWidget* w1 = v1->GetWidget();
    8057               0 :           nsIWidget* w2 = v2->GetWidget();
    8058               0 :           if (((nsnull == w1) && (nsnull != w2)) ||
    8059                 :               ((nsnull != w1) && (nsnull == w2))) {
    8060               0 :             ok = false;
    8061               0 :             LogVerifyMessage(k1, k2, "child widgets are not matched\n");
    8062                 :           }
    8063               0 :           else if (nsnull != w1) {
    8064               0 :             w1->GetBounds(r1);
    8065               0 :             w2->GetBounds(r2);
    8066               0 :             if (!r1.IsEqualEdges(r2)) {
    8067               0 :               LogVerifyMessage(k1, k2, "(widget rects)", r1, r2);
    8068                 :             }
    8069                 :           }
    8070                 :         }
    8071               0 :         if (!ok && (0 == (VERIFY_REFLOW_ALL & gVerifyReflowFlags))) {
    8072               0 :           break;
    8073                 :         }
    8074                 : 
    8075                 :         // XXX Should perhaps compare their float managers.
    8076                 : 
    8077                 :         // Compare the sub-trees too
    8078               0 :         if (!CompareTrees(aFirstPresContext, k1, aSecondPresContext, k2)) {
    8079               0 :           ok = false;
    8080               0 :           if (0 == (VERIFY_REFLOW_ALL & gVerifyReflowFlags)) {
    8081               0 :             break;
    8082                 :           }
    8083                 :         }
    8084                 :       }
    8085                 :       else {
    8086               0 :         break;
    8087                 :       }
    8088                 :     }
    8089               0 :     if (!ok && (0 == (VERIFY_REFLOW_ALL & gVerifyReflowFlags))) {
    8090                 :       break;
    8091                 :     }
    8092                 : 
    8093               0 :     lists1.Next();
    8094               0 :     lists2.Next();
    8095               0 :     if (lists1.IsDone() != lists2.IsDone() ||
    8096               0 :         (!lists1.IsDone() && lists1.CurrentID() != lists2.CurrentID())) {
    8097               0 :       if (0 == (VERIFY_REFLOW_ALL & gVerifyReflowFlags)) {
    8098               0 :         ok = false;
    8099                 :       }
    8100                 :       LogVerifyMessage(kids1.FirstChild(), kids2.FirstChild(),
    8101               0 :                        "child list names are not matched: ");
    8102                 :       fprintf(stdout, "%s != %s\n",
    8103               0 :               !lists1.IsDone() ? mozilla::layout::ChildListName(lists1.CurrentID()) : "(null)",
    8104               0 :               !lists2.IsDone() ? mozilla::layout::ChildListName(lists2.CurrentID()) : "(null)");
    8105                 :       break;
    8106                 :     }
    8107               0 :   } while (ok && !lists1.IsDone());
    8108                 : 
    8109               0 :   return ok;
    8110                 : }
    8111                 : #endif
    8112                 : 
    8113                 : #if 0
    8114                 : static nsIFrame*
    8115                 : FindTopFrame(nsIFrame* aRoot)
    8116                 : {
    8117                 :   if (aRoot) {
    8118                 :     nsIContent* content = aRoot->GetContent();
    8119                 :     if (content) {
    8120                 :       nsIAtom* tag;
    8121                 :       content->GetTag(tag);
    8122                 :       if (nsnull != tag) {
    8123                 :         NS_RELEASE(tag);
    8124                 :         return aRoot;
    8125                 :       }
    8126                 :     }
    8127                 : 
    8128                 :     // Try one of the children
    8129                 :     nsIFrame* kid = aRoot->GetFirstPrincipalChild();
    8130                 :     while (nsnull != kid) {
    8131                 :       nsIFrame* result = FindTopFrame(kid);
    8132                 :       if (nsnull != result) {
    8133                 :         return result;
    8134                 :       }
    8135                 :       kid = kid->GetNextSibling();
    8136                 :     }
    8137                 :   }
    8138                 :   return nsnull;
    8139                 : }
    8140                 : #endif
    8141                 : 
    8142                 : 
    8143                 : #ifdef DEBUG
    8144                 : 
    8145                 : nsStyleSet*
    8146               0 : PresShell::CloneStyleSet(nsStyleSet* aSet)
    8147                 : {
    8148               0 :   nsStyleSet *clone = new nsStyleSet();
    8149                 : 
    8150               0 :   PRInt32 i, n = aSet->SheetCount(nsStyleSet::eOverrideSheet);
    8151               0 :   for (i = 0; i < n; i++) {
    8152               0 :     nsIStyleSheet* ss = aSet->StyleSheetAt(nsStyleSet::eOverrideSheet, i);
    8153               0 :     if (ss)
    8154               0 :       clone->AppendStyleSheet(nsStyleSet::eOverrideSheet, ss);
    8155                 :   }
    8156                 : 
    8157                 :   // The document expects to insert document stylesheets itself
    8158                 : #if 0
    8159                 :   n = aSet->SheetCount(nsStyleSet::eDocSheet);
    8160                 :   for (i = 0; i < n; i++) {
    8161                 :     nsIStyleSheet* ss = aSet->StyleSheetAt(nsStyleSet::eDocSheet, i);
    8162                 :     if (ss)
    8163                 :       clone->AddDocStyleSheet(ss, mDocument);
    8164                 :   }
    8165                 : #endif
    8166                 : 
    8167               0 :   n = aSet->SheetCount(nsStyleSet::eUserSheet);
    8168               0 :   for (i = 0; i < n; i++) {
    8169               0 :     nsIStyleSheet* ss = aSet->StyleSheetAt(nsStyleSet::eUserSheet, i);
    8170               0 :     if (ss)
    8171               0 :       clone->AppendStyleSheet(nsStyleSet::eUserSheet, ss);
    8172                 :   }
    8173                 : 
    8174               0 :   n = aSet->SheetCount(nsStyleSet::eAgentSheet);
    8175               0 :   for (i = 0; i < n; i++) {
    8176               0 :     nsIStyleSheet* ss = aSet->StyleSheetAt(nsStyleSet::eAgentSheet, i);
    8177               0 :     if (ss)
    8178               0 :       clone->AppendStyleSheet(nsStyleSet::eAgentSheet, ss);
    8179                 :   }
    8180               0 :   return clone;
    8181                 : }
    8182                 : 
    8183                 : #ifdef DEBUG_Eli
    8184                 : static nsresult
    8185                 : DumpToPNG(nsIPresShell* shell, nsAString& name) {
    8186                 :   PRInt32 width=1000, height=1000;
    8187                 :   nsRect r(0, 0, shell->GetPresContext()->DevPixelsToAppUnits(width),
    8188                 :                  shell->GetPresContext()->DevPixelsToAppUnits(height));
    8189                 : 
    8190                 :   nsRefPtr<gfxImageSurface> imgSurface =
    8191                 :      new gfxImageSurface(gfxIntSize(width, height),
    8192                 :                          gfxImageSurface::ImageFormatARGB32);
    8193                 : 
    8194                 :   nsRefPtr<gfxContext> imgContext = new gfxContext(imgSurface);
    8195                 : 
    8196                 :   nsRefPtr<gfxASurface> surface = 
    8197                 :     gfxPlatform::GetPlatform()->
    8198                 :     CreateOffscreenSurface(gfxIntSize(width, height),
    8199                 :       gfxASurface::ContentFromFormat(gfxASurface::ImageFormatARGB32));
    8200                 :   NS_ENSURE_TRUE(surface, NS_ERROR_OUT_OF_MEMORY);
    8201                 : 
    8202                 :   nsRefPtr<gfxContext> context = new gfxContext(surface);
    8203                 : 
    8204                 :   shell->RenderDocument(r, 0, NS_RGB(255, 255, 0), context);
    8205                 : 
    8206                 :   imgContext->DrawSurface(surface, gfxSize(width, height));
    8207                 : 
    8208                 :   nsCOMPtr<imgIEncoder> encoder = do_CreateInstance("@mozilla.org/image/encoder;2?type=image/png");
    8209                 :   NS_ENSURE_TRUE(encoder, NS_ERROR_FAILURE);
    8210                 :   encoder->InitFromData(imgSurface->Data(), imgSurface->Stride() * height,
    8211                 :                         width, height, imgSurface->Stride(),
    8212                 :                         imgIEncoder::INPUT_FORMAT_HOSTARGB, EmptyString());
    8213                 : 
    8214                 :   // XXX not sure if this is the right way to write to a file
    8215                 :   nsCOMPtr<nsILocalFile> file = do_CreateInstance("@mozilla.org/file/local;1");
    8216                 :   NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
    8217                 :   rv = file->InitWithPath(name);
    8218                 :   NS_ENSURE_SUCCESS(rv, rv);
    8219                 : 
    8220                 :   PRUint32 length;
    8221                 :   encoder->Available(&length);
    8222                 : 
    8223                 :   nsCOMPtr<nsIOutputStream> outputStream;
    8224                 :   rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), file);
    8225                 :   NS_ENSURE_SUCCESS(rv, rv);
    8226                 : 
    8227                 :   nsCOMPtr<nsIOutputStream> bufferedOutputStream;
    8228                 :   rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
    8229                 :                                   outputStream, length);
    8230                 : 
    8231                 :   PRUint32 numWritten;
    8232                 :   rv = bufferedOutputStream->WriteFrom(encoder, length, &numWritten);
    8233                 :   NS_ENSURE_SUCCESS(rv, rv);
    8234                 : 
    8235                 :   return NS_OK;
    8236                 : }
    8237                 : #endif
    8238                 : 
    8239                 : // After an incremental reflow, we verify the correctness by doing a
    8240                 : // full reflow into a fresh frame tree.
    8241                 : bool
    8242               0 : PresShell::VerifyIncrementalReflow()
    8243                 : {
    8244               0 :    if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
    8245               0 :      printf("Building Verification Tree...\n");
    8246                 :    }
    8247                 : 
    8248                 :   // Create a presentation context to view the new frame tree
    8249                 :   nsRefPtr<nsPresContext> cx =
    8250               0 :        new nsRootPresContext(mDocument, mPresContext->IsPaginated() ?
    8251                 :                                         nsPresContext::eContext_PrintPreview :
    8252               0 :                                         nsPresContext::eContext_Galley);
    8253               0 :   NS_ENSURE_TRUE(cx, false);
    8254                 : 
    8255               0 :   nsDeviceContext *dc = mPresContext->DeviceContext();
    8256               0 :   nsresult rv = cx->Init(dc);
    8257               0 :   NS_ENSURE_SUCCESS(rv, false);
    8258                 : 
    8259                 :   // Get our scrolling preference
    8260               0 :   nsIView* rootView = mViewManager->GetRootView();
    8261               0 :   NS_ENSURE_TRUE(rootView->HasWidget(), false);
    8262               0 :   nsIWidget* parentWidget = rootView->GetWidget();
    8263                 : 
    8264                 :   // Create a new view manager.
    8265               0 :   nsCOMPtr<nsIViewManager> vm = do_CreateInstance(kViewManagerCID);
    8266               0 :   NS_ENSURE_TRUE(vm, false);
    8267               0 :   rv = vm->Init(dc);
    8268               0 :   NS_ENSURE_SUCCESS(rv, false);
    8269                 : 
    8270                 :   // Create a child window of the parent that is our "root view/window"
    8271                 :   // Create a view
    8272               0 :   nsRect tbounds = mPresContext->GetVisibleArea();
    8273               0 :   nsIView* view = vm->CreateView(tbounds, nsnull);
    8274               0 :   NS_ENSURE_TRUE(view, false);
    8275                 : 
    8276                 :   //now create the widget for the view
    8277               0 :   rv = view->CreateWidgetForParent(parentWidget, nsnull, true);
    8278               0 :   NS_ENSURE_SUCCESS(rv, false);
    8279                 : 
    8280                 :   // Setup hierarchical relationship in view manager
    8281               0 :   vm->SetRootView(view);
    8282                 : 
    8283                 :   // Make the new presentation context the same size as our
    8284                 :   // presentation context.
    8285               0 :   nsRect r = mPresContext->GetVisibleArea();
    8286               0 :   cx->SetVisibleArea(r);
    8287                 : 
    8288                 :   // Create a new presentation shell to view the document. Use the
    8289                 :   // exact same style information that this document has.
    8290               0 :   nsAutoPtr<nsStyleSet> newSet(CloneStyleSet(mStyleSet));
    8291               0 :   nsCOMPtr<nsIPresShell> sh;
    8292               0 :   rv = mDocument->CreateShell(cx, vm, newSet, getter_AddRefs(sh));
    8293               0 :   NS_ENSURE_SUCCESS(rv, false);
    8294               0 :   newSet.forget();
    8295                 :   // Note that after we create the shell, we must make sure to destroy it
    8296               0 :   sh->SetVerifyReflowEnable(false); // turn off verify reflow while we're reflowing the test frame tree
    8297               0 :   vm->SetPresShell(sh);
    8298                 :   {
    8299               0 :     nsAutoCauseReflowNotifier crNotifier(this);
    8300               0 :     sh->InitialReflow(r.width, r.height);
    8301                 :   }
    8302               0 :   mDocument->BindingManager()->ProcessAttachedQueue();
    8303               0 :   sh->FlushPendingNotifications(Flush_Layout);
    8304               0 :   sh->SetVerifyReflowEnable(true);  // turn on verify reflow again now that we're done reflowing the test frame tree
    8305                 :   // Force the non-primary presshell to unsuppress; it doesn't want to normally
    8306                 :   // because it thinks it's hidden
    8307               0 :   ((PresShell*)sh.get())->mPaintingSuppressed = false;
    8308               0 :   if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
    8309               0 :      printf("Verification Tree built, comparing...\n");
    8310                 :   }
    8311                 : 
    8312                 :   // Now that the document has been reflowed, use its frame tree to
    8313                 :   // compare against our frame tree.
    8314               0 :   nsIFrame* root1 = mFrameConstructor->GetRootFrame();
    8315               0 :   nsIFrame* root2 = sh->GetRootFrame();
    8316               0 :   bool ok = CompareTrees(mPresContext, root1, cx, root2);
    8317               0 :   if (!ok && (VERIFY_REFLOW_NOISY & gVerifyReflowFlags)) {
    8318               0 :     printf("Verify reflow failed, primary tree:\n");
    8319               0 :     root1->List(stdout, 0);
    8320               0 :     printf("Verification tree:\n");
    8321               0 :     root2->List(stdout, 0);
    8322                 :   }
    8323                 : 
    8324                 : #ifdef DEBUG_Eli
    8325                 :   // Sample code for dumping page to png
    8326                 :   // XXX Needs to be made more flexible
    8327                 :   if (!ok) {
    8328                 :     nsString stra;
    8329                 :     static int num = 0;
    8330                 :     stra.AppendLiteral("C:\\mozilla\\mozilla\\debug\\filea");
    8331                 :     stra.AppendInt(num);
    8332                 :     stra.AppendLiteral(".png");
    8333                 :     DumpToPNG(sh, stra);
    8334                 :     nsString strb;
    8335                 :     strb.AppendLiteral("C:\\mozilla\\mozilla\\debug\\fileb");
    8336                 :     strb.AppendInt(num);
    8337                 :     strb.AppendLiteral(".png");
    8338                 :     DumpToPNG(this, strb);
    8339                 :     ++num;
    8340                 :   }
    8341                 : #endif
    8342                 : 
    8343               0 :   sh->EndObservingDocument();
    8344               0 :   sh->Destroy();
    8345               0 :   if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
    8346               0 :     printf("Finished Verifying Reflow...\n");
    8347                 :   }
    8348                 : 
    8349               0 :   return ok;
    8350                 : }
    8351                 : 
    8352                 : // Layout debugging hooks
    8353                 : void
    8354               0 : PresShell::ListStyleContexts(nsIFrame *aRootFrame, FILE *out, PRInt32 aIndent)
    8355                 : {
    8356               0 :   nsStyleContext *sc = aRootFrame->GetStyleContext();
    8357               0 :   if (sc)
    8358               0 :     sc->List(out, aIndent);
    8359               0 : }
    8360                 : 
    8361                 : void
    8362               0 : PresShell::ListStyleSheets(FILE *out, PRInt32 aIndent)
    8363                 : {
    8364               0 :   PRInt32 sheetCount = mStyleSet->SheetCount(nsStyleSet::eDocSheet);
    8365               0 :   for (PRInt32 i = 0; i < sheetCount; ++i) {
    8366               0 :     mStyleSet->StyleSheetAt(nsStyleSet::eDocSheet, i)->List(out, aIndent);
    8367               0 :     fputs("\n", out);
    8368                 :   }
    8369               0 : }
    8370                 : 
    8371                 : void
    8372               0 : PresShell::VerifyStyleTree()
    8373                 : {
    8374               0 :   VERIFY_STYLE_TREE;
    8375               0 : }
    8376                 : #endif
    8377                 : 
    8378                 : //=============================================================
    8379                 : //=============================================================
    8380                 : //-- Debug Reflow Counts
    8381                 : //=============================================================
    8382                 : //=============================================================
    8383                 : #ifdef MOZ_REFLOW_PERF
    8384                 : //-------------------------------------------------------------
    8385                 : void
    8386               0 : PresShell::DumpReflows()
    8387                 : {
    8388               0 :   if (mReflowCountMgr) {
    8389               0 :     nsCAutoString uriStr;
    8390               0 :     if (mDocument) {
    8391               0 :       nsIURI *uri = mDocument->GetDocumentURI();
    8392               0 :       if (uri) {
    8393               0 :         uri->GetPath(uriStr);
    8394                 :       }
    8395                 :     }
    8396               0 :     mReflowCountMgr->DisplayTotals(uriStr.get());
    8397               0 :     mReflowCountMgr->DisplayHTMLTotals(uriStr.get());
    8398               0 :     mReflowCountMgr->DisplayDiffsInTotals("Differences");
    8399                 :   }
    8400               0 : }
    8401                 : 
    8402                 : //-------------------------------------------------------------
    8403                 : void
    8404               0 : PresShell::CountReflows(const char * aName, nsIFrame * aFrame)
    8405                 : {
    8406               0 :   if (mReflowCountMgr) {
    8407               0 :     mReflowCountMgr->Add(aName, aFrame);
    8408                 :   }
    8409               0 : }
    8410                 : 
    8411                 : //-------------------------------------------------------------
    8412                 : void
    8413               0 : PresShell::PaintCount(const char * aName,
    8414                 :                       nsRenderingContext* aRenderingContext,
    8415                 :                       nsPresContext* aPresContext,
    8416                 :                       nsIFrame * aFrame,
    8417                 :                       const nsPoint& aOffset,
    8418                 :                       PRUint32 aColor)
    8419                 : {
    8420               0 :   if (mReflowCountMgr) {
    8421                 :     mReflowCountMgr->PaintCount(aName, aRenderingContext, aPresContext,
    8422               0 :                                 aFrame, aOffset, aColor);
    8423                 :   }
    8424               0 : }
    8425                 : 
    8426                 : //-------------------------------------------------------------
    8427                 : void
    8428               0 : PresShell::SetPaintFrameCount(bool aPaintFrameCounts)
    8429                 : {
    8430               0 :   if (mReflowCountMgr) {
    8431               0 :     mReflowCountMgr->SetPaintFrameCounts(aPaintFrameCounts);
    8432                 :   }
    8433               0 : }
    8434                 : 
    8435                 : bool
    8436               0 : PresShell::IsPaintingFrameCounts()
    8437                 : {
    8438               0 :   if (mReflowCountMgr)
    8439               0 :     return mReflowCountMgr->IsPaintingFrameCounts();
    8440               0 :   return false;
    8441                 : }
    8442                 : 
    8443                 : //------------------------------------------------------------------
    8444                 : //-- Reflow Counter Classes Impls
    8445                 : //------------------------------------------------------------------
    8446                 : 
    8447                 : //------------------------------------------------------------------
    8448               0 : ReflowCounter::ReflowCounter(ReflowCountMgr * aMgr) :
    8449               0 :   mMgr(aMgr)
    8450                 : {
    8451               0 :   ClearTotals();
    8452               0 :   SetTotalsCache();
    8453               0 : }
    8454                 : 
    8455                 : //------------------------------------------------------------------
    8456               0 : ReflowCounter::~ReflowCounter()
    8457                 : {
    8458                 :   
    8459               0 : }
    8460                 : 
    8461                 : //------------------------------------------------------------------
    8462               0 : void ReflowCounter::ClearTotals()
    8463                 : {
    8464               0 :   mTotal = 0;
    8465               0 : }
    8466                 : 
    8467                 : //------------------------------------------------------------------
    8468               0 : void ReflowCounter::SetTotalsCache()
    8469                 : {
    8470               0 :   mCacheTotal = mTotal;
    8471               0 : }
    8472                 : 
    8473                 : //------------------------------------------------------------------
    8474               0 : void ReflowCounter::CalcDiffInTotals()
    8475                 : {
    8476               0 :   mCacheTotal = mTotal - mCacheTotal;
    8477               0 : }
    8478                 : 
    8479                 : //------------------------------------------------------------------
    8480               0 : void ReflowCounter::DisplayTotals(const char * aStr)
    8481                 : {
    8482               0 :   DisplayTotals(mTotal, aStr?aStr:"Totals");
    8483               0 : }
    8484                 : 
    8485                 : //------------------------------------------------------------------
    8486               0 : void ReflowCounter::DisplayDiffTotals(const char * aStr)
    8487                 : {
    8488               0 :   DisplayTotals(mCacheTotal, aStr?aStr:"Diff Totals");
    8489               0 : }
    8490                 : 
    8491                 : //------------------------------------------------------------------
    8492               0 : void ReflowCounter::DisplayHTMLTotals(const char * aStr)
    8493                 : {
    8494               0 :   DisplayHTMLTotals(mTotal, aStr?aStr:"Totals");
    8495               0 : }
    8496                 : 
    8497                 : //------------------------------------------------------------------
    8498               0 : void ReflowCounter::DisplayTotals(PRUint32 aTotal, const char * aTitle)
    8499                 : {
    8500                 :   // figure total
    8501               0 :   if (aTotal == 0) {
    8502               0 :     return;
    8503                 :   }
    8504               0 :   ReflowCounter * gTots = (ReflowCounter *)mMgr->LookUp(kGrandTotalsStr);
    8505                 : 
    8506               0 :   printf("%25s\t", aTitle);
    8507               0 :   printf("%d\t", aTotal);
    8508               0 :   if (gTots != this && aTotal > 0) {
    8509               0 :     gTots->Add(aTotal);
    8510                 :   }
    8511                 : }
    8512                 : 
    8513                 : //------------------------------------------------------------------
    8514               0 : void ReflowCounter::DisplayHTMLTotals(PRUint32 aTotal, const char * aTitle)
    8515                 : {
    8516               0 :   if (aTotal == 0) {
    8517               0 :     return;
    8518                 :   }
    8519                 : 
    8520               0 :   ReflowCounter * gTots = (ReflowCounter *)mMgr->LookUp(kGrandTotalsStr);
    8521               0 :   FILE * fd = mMgr->GetOutFile();
    8522               0 :   if (!fd) {
    8523               0 :     return;
    8524                 :   }
    8525                 : 
    8526               0 :   fprintf(fd, "<tr><td><center>%s</center></td>", aTitle);
    8527               0 :   fprintf(fd, "<td><center>%d</center></td></tr>\n", aTotal);
    8528                 : 
    8529               0 :   if (gTots != this && aTotal > 0) {
    8530               0 :     gTots->Add(aTotal);
    8531                 :   }
    8532                 : }
    8533                 : 
    8534                 : //------------------------------------------------------------------
    8535                 : //-- ReflowCountMgr
    8536                 : //------------------------------------------------------------------
    8537               0 : ReflowCountMgr::ReflowCountMgr()
    8538                 : {
    8539                 :   mCounts = PL_NewHashTable(10, PL_HashString, PL_CompareStrings, 
    8540               0 :                                 PL_CompareValues, nsnull, nsnull);
    8541                 :   mIndiFrameCounts = PL_NewHashTable(10, PL_HashString, PL_CompareStrings, 
    8542               0 :                                      PL_CompareValues, nsnull, nsnull);
    8543               0 :   mCycledOnce              = false;
    8544               0 :   mDumpFrameCounts         = false;
    8545               0 :   mDumpFrameByFrameCounts  = false;
    8546               0 :   mPaintFrameByFrameCounts = false;
    8547               0 : }
    8548                 : 
    8549                 : //------------------------------------------------------------------
    8550               0 : ReflowCountMgr::~ReflowCountMgr()
    8551                 : {
    8552               0 :   CleanUp();
    8553               0 : }
    8554                 : 
    8555                 : //------------------------------------------------------------------
    8556               0 : ReflowCounter * ReflowCountMgr::LookUp(const char * aName)
    8557                 : {
    8558               0 :   if (nsnull != mCounts) {
    8559               0 :     ReflowCounter * counter = (ReflowCounter *)PL_HashTableLookup(mCounts, aName);
    8560               0 :     return counter;
    8561                 :   }
    8562               0 :   return nsnull;
    8563                 : 
    8564                 : }
    8565                 : 
    8566                 : //------------------------------------------------------------------
    8567               0 : void ReflowCountMgr::Add(const char * aName, nsIFrame * aFrame)
    8568                 : {
    8569               0 :   NS_ASSERTION(aName != nsnull, "Name shouldn't be null!");
    8570                 : 
    8571               0 :   if (mDumpFrameCounts && nsnull != mCounts) {
    8572               0 :     ReflowCounter * counter = (ReflowCounter *)PL_HashTableLookup(mCounts, aName);
    8573               0 :     if (counter == nsnull) {
    8574               0 :       counter = new ReflowCounter(this);
    8575               0 :       char * name = NS_strdup(aName);
    8576               0 :       NS_ASSERTION(name != nsnull, "null ptr");
    8577               0 :       PL_HashTableAdd(mCounts, name, counter);
    8578                 :     }
    8579               0 :     counter->Add();
    8580                 :   }
    8581                 : 
    8582               0 :   if ((mDumpFrameByFrameCounts || mPaintFrameByFrameCounts) && 
    8583                 :       nsnull != mIndiFrameCounts && 
    8584                 :       aFrame != nsnull) {
    8585               0 :     char * key = new char[16];
    8586               0 :     sprintf(key, "%p", (void*)aFrame);
    8587               0 :     IndiReflowCounter * counter = (IndiReflowCounter *)PL_HashTableLookup(mIndiFrameCounts, key);
    8588               0 :     if (counter == nsnull) {
    8589               0 :       counter = new IndiReflowCounter(this);
    8590               0 :       counter->mFrame = aFrame;
    8591               0 :       counter->mName.AssignASCII(aName);
    8592               0 :       PL_HashTableAdd(mIndiFrameCounts, key, counter);
    8593                 :     }
    8594                 :     // this eliminates extra counts from super classes
    8595               0 :     if (counter != nsnull && counter->mName.EqualsASCII(aName)) {
    8596               0 :       counter->mCount++;
    8597               0 :       counter->mCounter.Add(1);
    8598                 :     }
    8599                 :   }
    8600               0 : }
    8601                 : 
    8602                 : //------------------------------------------------------------------
    8603               0 : void ReflowCountMgr::PaintCount(const char*     aName,
    8604                 :                                 nsRenderingContext* aRenderingContext,
    8605                 :                                 nsPresContext*  aPresContext,
    8606                 :                                 nsIFrame*       aFrame,
    8607                 :                                 const nsPoint&  aOffset,
    8608                 :                                 PRUint32        aColor)
    8609                 : {
    8610               0 :   if (mPaintFrameByFrameCounts &&
    8611                 :       nsnull != mIndiFrameCounts &&
    8612                 :       aFrame != nsnull) {
    8613               0 :     char * key = new char[16];
    8614               0 :     sprintf(key, "%p", (void*)aFrame);
    8615                 :     IndiReflowCounter * counter =
    8616               0 :       (IndiReflowCounter *)PL_HashTableLookup(mIndiFrameCounts, key);
    8617               0 :     if (counter != nsnull && counter->mName.EqualsASCII(aName)) {
    8618               0 :       aRenderingContext->PushState();
    8619               0 :       aRenderingContext->Translate(aOffset);
    8620                 :       nsFont font("Times", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
    8621                 :                   NS_FONT_WEIGHT_NORMAL, NS_FONT_STRETCH_NORMAL, 0,
    8622               0 :                   nsPresContext::CSSPixelsToAppUnits(11));
    8623                 : 
    8624               0 :       nsRefPtr<nsFontMetrics> fm;
    8625                 :       aPresContext->DeviceContext()->GetMetricsFor(font,
    8626                 :         // We have one frame, therefore we must have a root...
    8627                 :         aPresContext->GetPresShell()->GetRootFrame()->
    8628               0 :           GetStyleFont()->mLanguage,
    8629               0 :         aPresContext->GetUserFontSet(), *getter_AddRefs(fm));
    8630                 : 
    8631               0 :       aRenderingContext->SetFont(fm);
    8632                 :       char buf[16];
    8633               0 :       sprintf(buf, "%d", counter->mCount);
    8634               0 :       nscoord x = 0, y = fm->MaxAscent();
    8635               0 :       nscoord width, height = fm->MaxHeight();
    8636               0 :       aRenderingContext->SetTextRunRTL(false);
    8637               0 :       width = aRenderingContext->GetWidth(buf);
    8638                 : 
    8639                 :       PRUint32 color;
    8640                 :       PRUint32 color2;
    8641               0 :       if (aColor != 0) {
    8642               0 :         color  = aColor;
    8643               0 :         color2 = NS_RGB(0,0,0);
    8644                 :       } else {
    8645               0 :         PRUint8 rc = 0, gc = 0, bc = 0;
    8646               0 :         if (counter->mCount < 5) {
    8647               0 :           rc = 255;
    8648               0 :           gc = 255;
    8649               0 :         } else if ( counter->mCount < 11) {
    8650               0 :           gc = 255;
    8651                 :         } else {
    8652               0 :           rc = 255;
    8653                 :         }
    8654               0 :         color  = NS_RGB(rc,gc,bc);
    8655               0 :         color2 = NS_RGB(rc/2,gc/2,bc/2);
    8656                 :       }
    8657                 : 
    8658               0 :       nsRect rect(0,0, width+15, height+15);
    8659               0 :       aRenderingContext->SetColor(NS_RGB(0,0,0));
    8660               0 :       aRenderingContext->FillRect(rect);
    8661               0 :       aRenderingContext->SetColor(color2);
    8662               0 :       aRenderingContext->DrawString(buf, strlen(buf), x+15,y+15);
    8663               0 :       aRenderingContext->SetColor(color);
    8664               0 :       aRenderingContext->DrawString(buf, strlen(buf), x,y);
    8665                 : 
    8666               0 :       aRenderingContext->PopState();
    8667                 :     }
    8668                 :   }
    8669               0 : }
    8670                 : 
    8671                 : //------------------------------------------------------------------
    8672               0 : PRIntn ReflowCountMgr::RemoveItems(PLHashEntry *he, PRIntn i, void *arg)
    8673                 : {
    8674               0 :   char *str = (char *)he->key;
    8675               0 :   ReflowCounter * counter = (ReflowCounter *)he->value;
    8676               0 :   delete counter;
    8677               0 :   NS_Free(str);
    8678                 : 
    8679               0 :   return HT_ENUMERATE_REMOVE;
    8680                 : }
    8681                 : 
    8682                 : //------------------------------------------------------------------
    8683               0 : PRIntn ReflowCountMgr::RemoveIndiItems(PLHashEntry *he, PRIntn i, void *arg)
    8684                 : {
    8685               0 :   char *str = (char *)he->key;
    8686               0 :   IndiReflowCounter * counter = (IndiReflowCounter *)he->value;
    8687               0 :   delete counter;
    8688               0 :   NS_Free(str);
    8689                 : 
    8690               0 :   return HT_ENUMERATE_REMOVE;
    8691                 : }
    8692                 : 
    8693                 : //------------------------------------------------------------------
    8694               0 : void ReflowCountMgr::CleanUp()
    8695                 : {
    8696               0 :   if (nsnull != mCounts) {
    8697               0 :     PL_HashTableEnumerateEntries(mCounts, RemoveItems, nsnull);
    8698               0 :     PL_HashTableDestroy(mCounts);
    8699               0 :     mCounts = nsnull;
    8700                 :   }
    8701                 : 
    8702               0 :   if (nsnull != mIndiFrameCounts) {
    8703               0 :     PL_HashTableEnumerateEntries(mIndiFrameCounts, RemoveIndiItems, nsnull);
    8704               0 :     PL_HashTableDestroy(mIndiFrameCounts);
    8705               0 :     mIndiFrameCounts = nsnull;
    8706                 :   }
    8707               0 : }
    8708                 : 
    8709                 : //------------------------------------------------------------------
    8710               0 : PRIntn ReflowCountMgr::DoSingleTotal(PLHashEntry *he, PRIntn i, void *arg)
    8711                 : {
    8712               0 :   char *str = (char *)he->key;
    8713               0 :   ReflowCounter * counter = (ReflowCounter *)he->value;
    8714                 : 
    8715               0 :   counter->DisplayTotals(str);
    8716                 : 
    8717               0 :   return HT_ENUMERATE_NEXT;
    8718                 : }
    8719                 : 
    8720                 : //------------------------------------------------------------------
    8721               0 : void ReflowCountMgr::DoGrandTotals()
    8722                 : {
    8723               0 :   if (nsnull != mCounts) {
    8724               0 :     ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr);
    8725               0 :     if (gTots == nsnull) {
    8726               0 :       gTots = new ReflowCounter(this);
    8727               0 :       PL_HashTableAdd(mCounts, NS_strdup(kGrandTotalsStr), gTots);
    8728                 :     } else {
    8729               0 :       gTots->ClearTotals();
    8730                 :     }
    8731                 : 
    8732               0 :     printf("\t\t\t\tTotal\n");
    8733               0 :     for (PRUint32 i=0;i<78;i++) {
    8734               0 :       printf("-");
    8735                 :     }
    8736               0 :     printf("\n");
    8737               0 :     PL_HashTableEnumerateEntries(mCounts, DoSingleTotal, this);
    8738                 :   }
    8739               0 : }
    8740                 : 
    8741               0 : static void RecurseIndiTotals(nsPresContext* aPresContext, 
    8742                 :                               PLHashTable *   aHT, 
    8743                 :                               nsIFrame *      aParentFrame,
    8744                 :                               PRInt32         aLevel)
    8745                 : {
    8746               0 :   if (aParentFrame == nsnull) {
    8747               0 :     return;
    8748                 :   }
    8749                 : 
    8750                 :   char key[16];
    8751               0 :   sprintf(key, "%p", (void*)aParentFrame);
    8752               0 :   IndiReflowCounter * counter = (IndiReflowCounter *)PL_HashTableLookup(aHT, key);
    8753               0 :   if (counter) {
    8754               0 :     counter->mHasBeenOutput = true;
    8755               0 :     char * name = ToNewCString(counter->mName);
    8756               0 :     for (PRInt32 i=0;i<aLevel;i++) printf(" ");
    8757               0 :     printf("%s - %p   [%d][", name, (void*)aParentFrame, counter->mCount);
    8758               0 :     printf("%d", counter->mCounter.GetTotal());
    8759               0 :     printf("]\n");
    8760               0 :     nsMemory::Free(name);
    8761                 :   }
    8762                 : 
    8763               0 :   nsIFrame* child = aParentFrame->GetFirstPrincipalChild();
    8764               0 :   while (child) {
    8765               0 :     RecurseIndiTotals(aPresContext, aHT, child, aLevel+1);
    8766               0 :     child = child->GetNextSibling();
    8767                 :   }
    8768                 : 
    8769                 : }
    8770                 : 
    8771                 : //------------------------------------------------------------------
    8772               0 : PRIntn ReflowCountMgr::DoSingleIndi(PLHashEntry *he, PRIntn i, void *arg)
    8773                 : {
    8774               0 :   IndiReflowCounter * counter = (IndiReflowCounter *)he->value;
    8775               0 :   if (counter && !counter->mHasBeenOutput) {
    8776               0 :     char * name = ToNewCString(counter->mName);
    8777               0 :     printf("%s - %p   [%d][", name, (void*)counter->mFrame, counter->mCount);
    8778               0 :     printf("%d", counter->mCounter.GetTotal());
    8779               0 :     printf("]\n");
    8780               0 :     nsMemory::Free(name);
    8781                 :   }
    8782               0 :   return HT_ENUMERATE_NEXT;
    8783                 : }
    8784                 : 
    8785                 : //------------------------------------------------------------------
    8786               0 : void ReflowCountMgr::DoIndiTotalsTree()
    8787                 : {
    8788               0 :   if (nsnull != mCounts) {
    8789               0 :     printf("\n------------------------------------------------\n");
    8790               0 :     printf("-- Individual Frame Counts\n");
    8791               0 :     printf("------------------------------------------------\n");
    8792                 : 
    8793               0 :     if (mPresShell) {
    8794               0 :       nsIFrame * rootFrame = mPresShell->FrameManager()->GetRootFrame();
    8795               0 :       RecurseIndiTotals(mPresContext, mIndiFrameCounts, rootFrame, 0);
    8796               0 :       printf("------------------------------------------------\n");
    8797               0 :       printf("-- Individual Counts of Frames not in Root Tree\n");
    8798               0 :       printf("------------------------------------------------\n");
    8799               0 :       PL_HashTableEnumerateEntries(mIndiFrameCounts, DoSingleIndi, this);
    8800                 :     }
    8801                 :   }
    8802               0 : }
    8803                 : 
    8804                 : //------------------------------------------------------------------
    8805               0 : PRIntn ReflowCountMgr::DoSingleHTMLTotal(PLHashEntry *he, PRIntn i, void *arg)
    8806                 : {
    8807               0 :   char *str = (char *)he->key;
    8808               0 :   ReflowCounter * counter = (ReflowCounter *)he->value;
    8809                 : 
    8810               0 :   counter->DisplayHTMLTotals(str);
    8811                 : 
    8812               0 :   return HT_ENUMERATE_NEXT;
    8813                 : }
    8814                 : 
    8815                 : //------------------------------------------------------------------
    8816               0 : void ReflowCountMgr::DoGrandHTMLTotals()
    8817                 : {
    8818               0 :   if (nsnull != mCounts) {
    8819               0 :     ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr);
    8820               0 :     if (gTots == nsnull) {
    8821               0 :       gTots = new ReflowCounter(this);
    8822               0 :       PL_HashTableAdd(mCounts, NS_strdup(kGrandTotalsStr), gTots);
    8823                 :     } else {
    8824               0 :       gTots->ClearTotals();
    8825                 :     }
    8826                 : 
    8827                 :     static const char * title[] = {"Class", "Reflows"};
    8828               0 :     fprintf(mFD, "<tr>");
    8829               0 :     for (PRUint32 i=0; i < ArrayLength(title); i++) {
    8830               0 :       fprintf(mFD, "<td><center><b>%s<b></center></td>", title[i]);
    8831                 :     }
    8832               0 :     fprintf(mFD, "</tr>\n");
    8833               0 :     PL_HashTableEnumerateEntries(mCounts, DoSingleHTMLTotal, this);
    8834                 :   }
    8835               0 : }
    8836                 : 
    8837                 : //------------------------------------
    8838               0 : void ReflowCountMgr::DisplayTotals(const char * aStr)
    8839                 : {
    8840                 : #ifdef DEBUG_rods
    8841                 :   printf("%s\n", aStr?aStr:"No name");
    8842                 : #endif
    8843               0 :   if (mDumpFrameCounts) {
    8844               0 :     DoGrandTotals();
    8845                 :   }
    8846               0 :   if (mDumpFrameByFrameCounts) {
    8847               0 :     DoIndiTotalsTree();
    8848                 :   }
    8849                 : 
    8850               0 : }
    8851                 : //------------------------------------
    8852               0 : void ReflowCountMgr::DisplayHTMLTotals(const char * aStr)
    8853                 : {
    8854                 : #ifdef WIN32x // XXX NOT XP!
    8855                 :   char name[1024];
    8856                 :   
    8857                 :   char * sptr = strrchr(aStr, '/');
    8858                 :   if (sptr) {
    8859                 :     sptr++;
    8860                 :     strcpy(name, sptr);
    8861                 :     char * eptr = strrchr(name, '.');
    8862                 :     if (eptr) {
    8863                 :       *eptr = 0;
    8864                 :     }
    8865                 :     strcat(name, "_stats.html");
    8866                 :   }
    8867                 :   mFD = fopen(name, "w");
    8868                 :   if (mFD) {
    8869                 :     fprintf(mFD, "<html><head><title>Reflow Stats</title></head><body>\n");
    8870                 :     const char * title = aStr?aStr:"No name";
    8871                 :     fprintf(mFD, "<center><b>%s</b><br><table border=1 style=\"background-color:#e0e0e0\">", title);
    8872                 :     DoGrandHTMLTotals();
    8873                 :     fprintf(mFD, "</center></table>\n");
    8874                 :     fprintf(mFD, "</body></html>\n");
    8875                 :     fclose(mFD);
    8876                 :     mFD = nsnull;
    8877                 :   }
    8878                 : #endif // not XP!
    8879               0 : }
    8880                 : 
    8881                 : //------------------------------------------------------------------
    8882               0 : PRIntn ReflowCountMgr::DoClearTotals(PLHashEntry *he, PRIntn i, void *arg)
    8883                 : {
    8884               0 :   ReflowCounter * counter = (ReflowCounter *)he->value;
    8885               0 :   counter->ClearTotals();
    8886                 : 
    8887               0 :   return HT_ENUMERATE_NEXT;
    8888                 : }
    8889                 : 
    8890                 : //------------------------------------------------------------------
    8891               0 : void ReflowCountMgr::ClearTotals()
    8892                 : {
    8893               0 :   PL_HashTableEnumerateEntries(mCounts, DoClearTotals, this);
    8894               0 : }
    8895                 : 
    8896                 : //------------------------------------------------------------------
    8897               0 : void ReflowCountMgr::ClearGrandTotals()
    8898                 : {
    8899               0 :   if (nsnull != mCounts) {
    8900               0 :     ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr);
    8901               0 :     if (gTots == nsnull) {
    8902               0 :       gTots = new ReflowCounter(this);
    8903               0 :       PL_HashTableAdd(mCounts, NS_strdup(kGrandTotalsStr), gTots);
    8904                 :     } else {
    8905               0 :       gTots->ClearTotals();
    8906               0 :       gTots->SetTotalsCache();
    8907                 :     }
    8908                 :   }
    8909               0 : }
    8910                 : 
    8911                 : //------------------------------------------------------------------
    8912               0 : PRIntn ReflowCountMgr::DoDisplayDiffTotals(PLHashEntry *he, PRIntn i, void *arg)
    8913                 : {
    8914               0 :   bool cycledOnce = (arg != 0);
    8915                 : 
    8916               0 :   char *str = (char *)he->key;
    8917               0 :   ReflowCounter * counter = (ReflowCounter *)he->value;
    8918                 : 
    8919               0 :   if (cycledOnce) {
    8920               0 :     counter->CalcDiffInTotals();
    8921               0 :     counter->DisplayDiffTotals(str);
    8922                 :   }
    8923               0 :   counter->SetTotalsCache();
    8924                 : 
    8925               0 :   return HT_ENUMERATE_NEXT;
    8926                 : }
    8927                 : 
    8928                 : //------------------------------------------------------------------
    8929               0 : void ReflowCountMgr::DisplayDiffsInTotals(const char * aStr)
    8930                 : {
    8931               0 :   if (mCycledOnce) {
    8932               0 :     printf("Differences\n");
    8933               0 :     for (PRInt32 i=0;i<78;i++) {
    8934               0 :       printf("-");
    8935                 :     }
    8936               0 :     printf("\n");
    8937               0 :     ClearGrandTotals();
    8938                 :   }
    8939               0 :   PL_HashTableEnumerateEntries(mCounts, DoDisplayDiffTotals, (void *)mCycledOnce);
    8940                 : 
    8941               0 :   mCycledOnce = true;
    8942               0 : }
    8943                 : 
    8944                 : #endif // MOZ_REFLOW_PERF
    8945                 : 
    8946                 : // make a color string like #RRGGBB
    8947               0 : void ColorToString(nscolor aColor, nsAutoString &aString)
    8948                 : {
    8949                 :   char buf[8];
    8950                 : 
    8951                 :   PR_snprintf(buf, sizeof(buf), "#%02x%02x%02x",
    8952               0 :               NS_GET_R(aColor), NS_GET_G(aColor), NS_GET_B(aColor));
    8953               0 :   CopyASCIItoUTF16(buf, aString);
    8954               0 : }
    8955                 : 
    8956               0 : nsIFrame* nsIPresShell::GetAbsoluteContainingBlock(nsIFrame *aFrame)
    8957                 : {
    8958               0 :   return FrameConstructor()->GetAbsoluteContainingBlock(aFrame);
    8959                 : }
    8960                 : 
    8961                 : #ifdef ACCESSIBILITY
    8962                 : bool
    8963               0 : nsIPresShell::IsAccessibilityActive()
    8964                 : {
    8965               0 :   return GetAccService() != nsnull;
    8966                 : }
    8967                 : 
    8968                 : nsAccessibilityService*
    8969               0 : nsIPresShell::AccService()
    8970                 : {
    8971               0 :   return GetAccService();
    8972                 : }
    8973                 : #endif
    8974                 : 
    8975                 : static bool inited = false;
    8976                 : 
    8977            1404 : void nsIPresShell::InitializeStatics()
    8978                 : {
    8979            1404 :   NS_ASSERTION(!inited, "InitializeStatics called multiple times!");
    8980            1404 :   gCaptureTouchList.Init();
    8981            1404 :   inited = true;
    8982            1404 : }
    8983                 : 
    8984            1403 : void nsIPresShell::ReleaseStatics()
    8985                 : {
    8986            1403 :   NS_ASSERTION(inited, "ReleaseStatics called without Initialize!");
    8987            1403 : }
    8988                 : 
    8989                 : // Asks our docshell whether we're active.
    8990               0 : void PresShell::QueryIsActive()
    8991                 : {
    8992               0 :   nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
    8993               0 :   if (mDocument) {
    8994               0 :     nsIDocument* displayDoc = mDocument->GetDisplayDocument();
    8995               0 :     if (displayDoc) {
    8996                 :       // Ok, we're an external resource document -- we need to use our display
    8997                 :       // document's docshell to determine "IsActive" status, since we lack
    8998                 :       // a container.
    8999               0 :       NS_ABORT_IF_FALSE(!container,
    9000                 :                         "external resource doc shouldn't have "
    9001                 :                         "its own container");
    9002                 : 
    9003               0 :       nsIPresShell* displayPresShell = displayDoc->GetShell();
    9004               0 :       if (displayPresShell) {
    9005               0 :         container = displayPresShell->GetPresContext()->GetContainer();
    9006                 :       }
    9007                 :     }
    9008                 :   }
    9009                 : 
    9010               0 :   nsCOMPtr<nsIDocShell> docshell(do_QueryInterface(container));
    9011               0 :   if (docshell) {
    9012                 :     bool isActive;
    9013               0 :     nsresult rv = docshell->GetIsActive(&isActive);
    9014               0 :     if (NS_SUCCEEDED(rv))
    9015               0 :       SetIsActive(isActive);
    9016                 :   }
    9017               0 : }
    9018                 : 
    9019                 : // Helper for propagating mIsActive changes to external resources
    9020                 : static bool
    9021               0 : SetExternalResourceIsActive(nsIDocument* aDocument, void* aClosure)
    9022                 : {
    9023               0 :   nsIPresShell* shell = aDocument->GetShell();
    9024               0 :   if (shell) {
    9025               0 :     shell->SetIsActive(*static_cast<bool*>(aClosure));
    9026                 :   }
    9027               0 :   return true;
    9028                 : }
    9029                 : 
    9030                 : static void
    9031               0 : SetPluginIsActive(nsIContent* aContent, void* aClosure)
    9032                 : {
    9033               0 :   nsIFrame *frame = aContent->GetPrimaryFrame();
    9034               0 :   nsIObjectFrame *objectFrame = do_QueryFrame(frame);
    9035               0 :   if (objectFrame) {
    9036               0 :     objectFrame->SetIsDocumentActive(*static_cast<bool*>(aClosure));
    9037                 :   }
    9038               0 : }
    9039                 : 
    9040                 : nsresult
    9041               0 : PresShell::SetIsActive(bool aIsActive)
    9042                 : {
    9043               0 :   NS_PRECONDITION(mDocument, "should only be called with a document");
    9044                 : 
    9045               0 :   mIsActive = aIsActive;
    9046               0 :   nsPresContext* presContext = GetPresContext();
    9047               0 :   if (presContext &&
    9048               0 :       presContext->RefreshDriver()->PresContext() == presContext) {
    9049               0 :     presContext->RefreshDriver()->SetThrottled(!mIsActive);
    9050                 :   }
    9051                 : 
    9052                 :   // Propagate state-change to my resource documents' PresShells
    9053                 :   mDocument->EnumerateExternalResources(SetExternalResourceIsActive,
    9054               0 :                                         &aIsActive);
    9055                 :   mDocument->EnumerateFreezableElements(SetPluginIsActive,
    9056               0 :                                         &aIsActive);
    9057               0 :   nsresult rv = UpdateImageLockingState();
    9058                 : #ifdef ACCESSIBILITY
    9059               0 :   if (aIsActive) {
    9060               0 :     nsAccessibilityService* accService = AccService();
    9061               0 :     if (accService) {
    9062               0 :       accService->PresShellActivated(this);
    9063                 :     }
    9064                 :   }
    9065                 : #endif
    9066               0 :   return rv;
    9067                 : }
    9068                 : 
    9069                 : /*
    9070                 :  * Determines the current image locking state. Called when one of the
    9071                 :  * dependent factors changes.
    9072                 :  */
    9073                 : nsresult
    9074               0 : PresShell::UpdateImageLockingState()
    9075                 : {
    9076                 :   // We're locked if we're both thawed and active.
    9077               0 :   return mDocument->SetImageLockingState(!mFrozen && mIsActive);
    9078                 : }
    9079                 : 
    9080                 : PresShell*
    9081               0 : PresShell::GetRootPresShell()
    9082                 : {
    9083               0 :   if (mPresContext) {
    9084               0 :     nsPresContext* rootPresContext = mPresContext->GetRootPresContext();
    9085               0 :     if (rootPresContext) {
    9086               0 :       return static_cast<PresShell*>(rootPresContext->PresShell());
    9087                 :     }
    9088                 :   }
    9089               0 :   return nsnull;
    9090                 : }
    9091                 : 
    9092                 : void
    9093               0 : PresShell::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
    9094                 :                                size_t *aArenasSize,
    9095                 :                                size_t *aStyleSetsSize,
    9096                 :                                size_t *aTextRunsSize) const
    9097                 : {
    9098               0 :   *aArenasSize = aMallocSizeOf(this);
    9099               0 :   *aArenasSize += mStackArena.SizeOfExcludingThis(aMallocSizeOf);
    9100               0 :   *aArenasSize += mFrameArena.SizeOfExcludingThis(aMallocSizeOf);
    9101                 : 
    9102               0 :   *aStyleSetsSize = StyleSet()->SizeOfIncludingThis(aMallocSizeOf);
    9103                 : 
    9104               0 :   *aTextRunsSize = SizeOfTextRuns(aMallocSizeOf);
    9105               0 : }
    9106                 : 
    9107                 : size_t
    9108               0 : PresShell::SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf) const
    9109                 : {
    9110               0 :   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
    9111               0 :   if (!rootFrame) {
    9112               0 :     return 0;
    9113                 :   }
    9114                 : 
    9115                 :   // clear the TEXT_RUN_MEMORY_ACCOUNTED flags
    9116                 :   nsLayoutUtils::SizeOfTextRunsForFrames(rootFrame, nsnull,
    9117               0 :                                          /* clear = */true);
    9118                 : 
    9119                 :   // collect the total memory in use for textruns
    9120                 :   return nsLayoutUtils::SizeOfTextRunsForFrames(rootFrame, aMallocSizeOf,
    9121               0 :                                                 /* clear = */false);
    9122            4392 : }
    9123                 : 

Generated by: LCOV version 1.7