layout/xul/grid/nsGridRowLeafLayout.cpp

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

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

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

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 //
     7 // Eric Vaughan
     8 // Netscape Communications
     9 //
    10 // See documentation in associated header file
    11 //
    13 #include "nsGridRowLeafLayout.h"
    14 #include "nsGridRowGroupLayout.h"
    15 #include "nsGridRow.h"
    16 #include "nsBoxLayoutState.h"
    17 #include "nsBox.h"
    18 #include "nsIScrollableFrame.h"
    19 #include "nsBoxFrame.h"
    20 #include "nsGridLayout2.h"
    21 #include <algorithm>
    23 already_AddRefed<nsBoxLayout> NS_NewGridRowLeafLayout()
    24 {
    25   nsRefPtr<nsBoxLayout> layout = new nsGridRowLeafLayout();
    26   return layout.forget();
    27 } 
    29 nsGridRowLeafLayout::nsGridRowLeafLayout():nsGridRowLayout()
    30 {
    31 }
    33 nsGridRowLeafLayout::~nsGridRowLeafLayout()
    34 {
    35 }
    37 nsSize
    38 nsGridRowLeafLayout::GetPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState)
    39 {
    40   int32_t index = 0;
    41   nsGrid* grid = GetGrid(aBox, &index);
    42   bool isHorizontal = IsHorizontal(aBox);
    44   // If we are not in a grid. Then we just work like a box. But if we are in a grid
    45   // ask the grid for our size.
    46   if (!grid) {
    47     return nsGridRowLayout::GetPrefSize(aBox, aState); 
    48   }
    49   else {
    50     return grid->GetPrefRowSize(aState, index, isHorizontal);
    51     //AddBorderAndPadding(aBox, pref);
    52   }
    53 }
    55 nsSize
    56 nsGridRowLeafLayout::GetMinSize(nsIFrame* aBox, nsBoxLayoutState& aState)
    57 {
    58   int32_t index = 0;
    59   nsGrid* grid = GetGrid(aBox, &index);
    60   bool isHorizontal = IsHorizontal(aBox);
    62   if (!grid)
    63     return nsGridRowLayout::GetMinSize(aBox, aState); 
    64   else {
    65     nsSize minSize = grid->GetMinRowSize(aState, index, isHorizontal);
    66     AddBorderAndPadding(aBox, minSize);
    67     return minSize;
    68   }
    69 }
    71 nsSize
    72 nsGridRowLeafLayout::GetMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState)
    73 {
    74   int32_t index = 0;
    75   nsGrid* grid = GetGrid(aBox, &index);
    76   bool isHorizontal = IsHorizontal(aBox);
    78   if (!grid)
    79     return nsGridRowLayout::GetMaxSize(aBox, aState); 
    80   else {
    81     nsSize maxSize;
    82     maxSize = grid->GetMaxRowSize(aState, index, isHorizontal);
    83     AddBorderAndPadding(aBox, maxSize);
    84     return maxSize;
    85   }
    86 }
    88 /** If a child is added or removed or changes size
    89   */
    90 void
    91 nsGridRowLeafLayout::ChildAddedOrRemoved(nsIFrame* aBox, nsBoxLayoutState& aState)
    92 {
    93   int32_t index = 0;
    94   nsGrid* grid = GetGrid(aBox, &index);
    95   bool isHorizontal = IsHorizontal(aBox);
    97   if (grid)
    98     grid->CellAddedOrRemoved(aState, index, isHorizontal);
    99 }
   101 void
   102 nsGridRowLeafLayout::PopulateBoxSizes(nsIFrame* aBox, nsBoxLayoutState& aState, nsBoxSize*& aBoxSizes, nscoord& aMinSize, nscoord& aMaxSize, int32_t& aFlexes)
   103 {
   104   int32_t index = 0;
   105   nsGrid* grid = GetGrid(aBox, &index);
   106   bool isHorizontal = IsHorizontal(aBox);
   108   // Our base class SprocketLayout is giving us a chance to change the box sizes before layout
   109   // If we are a row lets change the sizes to match our columns. If we are a column then do the opposite
   110   // and make them match or rows.
   111   if (grid) {
   112     nsGridRow* column;
   113     int32_t count = grid->GetColumnCount(isHorizontal); 
   114     nsBoxSize* start = nullptr;
   115     nsBoxSize* last = nullptr;
   116     nsBoxSize* current = nullptr;
   117     nsIFrame* child = aBox->GetChildBox();
   118     for (int i=0; i < count; i++)
   119     {
   120       column = grid->GetColumnAt(i,isHorizontal); 
   122       // make sure the value was computed before we use it.
   123       // !isHorizontal is passed in to invert the behavior of these methods.
   124       nscoord pref =
   125         grid->GetPrefRowHeight(aState, i, !isHorizontal); // GetPrefColumnWidth
   126       nscoord min = 
   127         grid->GetMinRowHeight(aState, i, !isHorizontal);  // GetMinColumnWidth
   128       nscoord max = 
   129         grid->GetMaxRowHeight(aState, i, !isHorizontal);  // GetMaxColumnWidth
   130       nscoord flex =
   131         grid->GetRowFlex(aState, i, !isHorizontal);       // GetColumnFlex
   132       nscoord left  = 0;
   133       nscoord right  = 0;
   134       grid->GetRowOffsets(aState, i, left, right, !isHorizontal); // GetColumnOffsets
   135       nsIFrame* box = column->GetBox();
   136       bool collapsed = false;
   137       nscoord topMargin = column->mTopMargin;
   138       nscoord bottomMargin = column->mBottomMargin;
   140       if (box) 
   141         collapsed = box->IsCollapsed();
   143       pref = pref - (left + right);
   144       if (pref < 0)
   145         pref = 0;
   147       // if this is the first or last column. Take into account that
   148       // our row could have a border that could affect our left or right
   149       // padding from our columns. If the row has padding subtract it.
   150       // would should always be able to garentee that our margin is smaller
   151       // or equal to our left or right
   152       int32_t firstIndex = 0;
   153       int32_t lastIndex = 0;
   154       nsGridRow* firstRow = nullptr;
   155       nsGridRow* lastRow = nullptr;
   156       grid->GetFirstAndLastRow(aState, firstIndex, lastIndex, firstRow, lastRow, !isHorizontal);
   158       if (i == firstIndex || i == lastIndex) {
   159         nsMargin offset = GetTotalMargin(aBox, isHorizontal);
   161         nsMargin border(0,0,0,0);
   162         // can't call GetBorderPadding we will get into recursion
   163         aBox->GetBorder(border);
   164         offset += border;
   165         aBox->GetPadding(border);
   166         offset += border;
   168         // subtract from out left and right
   169         if (i == firstIndex) 
   170         {
   171           if (isHorizontal)
   172            left -= offset.left;
   173           else
   174            left -= offset.top;
   175         }
   177         if (i == lastIndex)
   178         {
   179           if (isHorizontal)
   180            right -= offset.right;
   181           else
   182            right -= offset.bottom;
   183         }
   184       }
   186       // initialize the box size here 
   187       max = std::max(min, max);
   188       pref = nsBox::BoundsCheck(min, pref, max);
   190       current = new (aState) nsBoxSize();
   191       current->pref = pref;
   192       current->min = min;
   193       current->max = max;
   194       current->flex = flex;
   195       current->bogus = column->mIsBogus;
   196       current->left = left + topMargin;
   197       current->right = right + bottomMargin;
   198       current->collapsed = collapsed;
   200       if (!start) {
   201         start = current;
   202         last = start;
   203       } else {
   204         last->next = current;
   205         last = current;
   206       }
   208       if (child && !column->mIsBogus)
   209         child = child->GetNextBox();
   211     }
   212     aBoxSizes = start;
   213   }
   215   nsSprocketLayout::PopulateBoxSizes(aBox, aState, aBoxSizes, aMinSize, aMaxSize, aFlexes);
   216 }
   218 void
   219 nsGridRowLeafLayout::ComputeChildSizes(nsIFrame* aBox,
   220                            nsBoxLayoutState& aState, 
   221                            nscoord& aGivenSize, 
   222                            nsBoxSize* aBoxSizes, 
   223                            nsComputedBoxSize*& aComputedBoxSizes)
   224 { 
   225   // see if we are in a scrollable frame. If we are then there could be scrollbars present
   226   // if so we need to subtract them out to make sure our columns line up.
   227   if (aBox) {
   228     bool isHorizontal = aBox->IsHorizontal();
   230     // go up the parent chain looking for scrollframes
   231     nscoord diff = 0;
   232     nsIFrame* parentBox;
   233     (void)GetParentGridPart(aBox, &parentBox);
   234     while (parentBox) {
   235       nsIFrame* scrollbox = nsGrid::GetScrollBox(parentBox);
   236       nsIScrollableFrame *scrollable = do_QueryFrame(scrollbox);
   237       if (scrollable) {
   238         // Don't call GetActualScrollbarSizes here because it's not safe
   239         // to call that while we're reflowing the contents of the scrollframe,
   240         // which we are here.
   241         nsMargin scrollbarSizes = scrollable->GetDesiredScrollbarSizes(&aState);
   242         uint32_t visible = scrollable->GetScrollbarVisibility();
   244         if (isHorizontal && (visible & nsIScrollableFrame::VERTICAL)) {
   245           diff += scrollbarSizes.left + scrollbarSizes.right;
   246         } else if (!isHorizontal && (visible & nsIScrollableFrame::HORIZONTAL)) {
   247           diff += scrollbarSizes.top + scrollbarSizes.bottom;
   248         }
   249       }
   251       (void)GetParentGridPart(parentBox, &parentBox);
   252     }
   254     if (diff > 0) {
   255       aGivenSize += diff;
   257       nsSprocketLayout::ComputeChildSizes(aBox, aState, aGivenSize, aBoxSizes, aComputedBoxSizes);
   259       aGivenSize -= diff;
   261       nsComputedBoxSize* s    = aComputedBoxSizes;
   262       nsComputedBoxSize* last = aComputedBoxSizes;
   263       while(s)
   264       {
   265         last = s;
   266         s = s->next;
   267       }
   269       if (last) 
   270         last->size -= diff;                         
   272       return;
   273     }
   274   }
   276   nsSprocketLayout::ComputeChildSizes(aBox, aState, aGivenSize, aBoxSizes, aComputedBoxSizes);
   278 }
   280 NS_IMETHODIMP
   281 nsGridRowLeafLayout::Layout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState)
   282 {
   283   return nsGridRowLayout::Layout(aBox, aBoxLayoutState);
   284 }
   286 void
   287 nsGridRowLeafLayout::DirtyRows(nsIFrame* aBox, nsBoxLayoutState& aState)
   288 {
   289   if (aBox) {
   290     // mark us dirty
   291     // XXXldb We probably don't want to walk up the ancestor chain
   292     // calling MarkIntrinsicWidthsDirty for every row.
   293     aState.PresShell()->FrameNeedsReflow(aBox, nsIPresShell::eTreeChange,
   294                                          NS_FRAME_IS_DIRTY);
   295   }
   296 }
   298 void
   299 nsGridRowLeafLayout::CountRowsColumns(nsIFrame* aBox, int32_t& aRowCount, int32_t& aComputedColumnCount)
   300 {
   301   if (aBox) {
   302     nsIFrame* child = aBox->GetChildBox();
   304     // count the children
   305     int32_t columnCount = 0;
   306     while(child) {
   307       child = child->GetNextBox();
   308       columnCount++;
   309     }
   311     // if our count is greater than the current column count
   312     if (columnCount > aComputedColumnCount) 
   313       aComputedColumnCount = columnCount;
   315     aRowCount++;
   316   }
   317 }
   319 int32_t
   320 nsGridRowLeafLayout::BuildRows(nsIFrame* aBox, nsGridRow* aRows)
   321 {
   322   if (aBox) {
   323       aRows[0].Init(aBox, false);
   324       return 1;
   325   }
   327   return 0;
   328 }

mercurial