layout/xul/tree/nsTreeBoxObject.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 #include "nsTreeBoxObject.h"
     7 #include "nsCOMPtr.h"
     8 #include "nsIDOMXULElement.h"
     9 #include "nsIXULTemplateBuilder.h"
    10 #include "nsTreeContentView.h"
    11 #include "nsITreeSelection.h"
    12 #include "ChildIterator.h"
    13 #include "nsContentUtils.h"
    14 #include "nsError.h"
    15 #include "nsTreeBodyFrame.h"
    17 NS_IMPL_CYCLE_COLLECTION(nsTreeBoxObject, mView)
    19 NS_IMPL_ADDREF_INHERITED(nsTreeBoxObject, nsBoxObject)
    20 NS_IMPL_RELEASE_INHERITED(nsTreeBoxObject, nsBoxObject)
    22 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsTreeBoxObject)
    23   NS_INTERFACE_MAP_ENTRY(nsITreeBoxObject)
    24 NS_INTERFACE_MAP_END_INHERITING(nsBoxObject)
    26 void
    27 nsTreeBoxObject::Clear()
    28 {
    29   ClearCachedValues();
    31   // Drop the view's ref to us.
    32   if (mView) {
    33     nsCOMPtr<nsITreeSelection> sel;
    34     mView->GetSelection(getter_AddRefs(sel));
    35     if (sel)
    36       sel->SetTree(nullptr);
    37     mView->SetTree(nullptr); // Break the circular ref between the view and us.
    38   }
    39   mView = nullptr;
    41   nsBoxObject::Clear();
    42 }
    45 nsTreeBoxObject::nsTreeBoxObject()
    46   : mTreeBody(nullptr)
    47 {
    48 }
    50 nsTreeBoxObject::~nsTreeBoxObject()
    51 {
    52   /* destructor code */
    53 }
    55 static nsIContent* FindBodyElement(nsIContent* aParent)
    56 {
    57   mozilla::dom::FlattenedChildIterator iter(aParent);
    58   for (nsIContent* content = iter.GetNextChild(); content; content = iter.GetNextChild()) {
    59     nsINodeInfo *ni = content->NodeInfo();
    60     if (ni->Equals(nsGkAtoms::treechildren, kNameSpaceID_XUL)) {
    61       return content;
    62     } else if (ni->Equals(nsGkAtoms::tree, kNameSpaceID_XUL)) {
    63       // There are nesting tree elements. Only the innermost should
    64       // find the treechilren.
    65       return nullptr;
    66     } else if (content->IsElement() &&
    67                !ni->Equals(nsGkAtoms::_template, kNameSpaceID_XUL)) {
    68       nsIContent* result = FindBodyElement(content);
    69       if (result)
    70         return result;
    71     }
    72   }
    74   return nullptr;
    75 }
    77 nsTreeBodyFrame*
    78 nsTreeBoxObject::GetTreeBody(bool aFlushLayout)
    79 {
    80   // Make sure our frames are up to date, and layout as needed.  We
    81   // have to do this before checking for our cached mTreeBody, since
    82   // it might go away on style flush, and in any case if aFlushLayout
    83   // is true we need to make sure to flush no matter what.
    84   // XXXbz except that flushing style when we were not asked to flush
    85   // layout here breaks things.  See bug 585123.
    86   nsIFrame* frame;
    87   if (aFlushLayout) {
    88     frame = GetFrame(aFlushLayout);
    89     if (!frame)
    90       return nullptr;
    91   }
    93   if (mTreeBody) {
    94     // Have one cached already.
    95     return mTreeBody;
    96   }
    98   if (!aFlushLayout) {
    99     frame = GetFrame(aFlushLayout);
   100     if (!frame)
   101       return nullptr;
   102   }
   104   // Iterate over our content model children looking for the body.
   105   nsCOMPtr<nsIContent> content = FindBodyElement(frame->GetContent());
   106   if (!content)
   107     return nullptr;
   109   frame = content->GetPrimaryFrame();
   110   if (!frame)
   111      return nullptr;
   113   // Make sure that the treebodyframe has a pointer to |this|.
   114   nsTreeBodyFrame *treeBody = do_QueryFrame(frame);
   115   NS_ENSURE_TRUE(treeBody && treeBody->GetTreeBoxObject() == this, nullptr);
   117   mTreeBody = treeBody;
   118   return mTreeBody;
   119 }
   121 NS_IMETHODIMP nsTreeBoxObject::GetView(nsITreeView * *aView)
   122 {
   123   if (!mTreeBody) {
   124     if (!GetTreeBody()) {
   125       // Don't return an uninitialised view
   126       *aView = nullptr;
   127       return NS_OK;
   128     }
   130     if (mView)
   131       // Our new frame needs to initialise itself
   132       return mTreeBody->GetView(aView);
   133   }
   134   if (!mView) {
   135     nsCOMPtr<nsIDOMXULElement> xulele = do_QueryInterface(mContent);
   136     if (xulele) {
   137       // See if there is a XUL tree builder associated with the element
   138       nsCOMPtr<nsIXULTemplateBuilder> builder;
   139       xulele->GetBuilder(getter_AddRefs(builder));
   140       mView = do_QueryInterface(builder);
   142       if (!mView) {
   143         // No tree builder, create a tree content view.
   144         nsresult rv = NS_NewTreeContentView(getter_AddRefs(mView));
   145         NS_ENSURE_SUCCESS(rv, rv);
   146       }
   148       // Initialise the frame and view
   149       mTreeBody->SetView(mView);
   150     }
   151   }
   152   NS_IF_ADDREF(*aView = mView);
   153   return NS_OK;
   154 }
   156 static bool
   157 CanTrustView(nsISupports* aValue)
   158 {
   159   // Untrusted content is only allowed to specify known-good views
   160   if (nsContentUtils::IsCallerChrome())
   161     return true;
   162   nsCOMPtr<nsINativeTreeView> nativeTreeView = do_QueryInterface(aValue);
   163   if (!nativeTreeView || NS_FAILED(nativeTreeView->EnsureNative())) {
   164     // XXX ERRMSG need a good error here for developers
   165     return false;
   166   }
   167   return true;
   168 }
   170 NS_IMETHODIMP nsTreeBoxObject::SetView(nsITreeView * aView)
   171 {
   172   if (!CanTrustView(aView))
   173     return NS_ERROR_DOM_SECURITY_ERR;
   175   mView = aView;
   176   nsTreeBodyFrame* body = GetTreeBody();
   177   if (body)
   178     body->SetView(aView);
   180   return NS_OK;
   181 }
   183 NS_IMETHODIMP nsTreeBoxObject::GetFocused(bool* aFocused)
   184 {
   185   *aFocused = false;
   186   nsTreeBodyFrame* body = GetTreeBody();
   187   if (body)
   188     return body->GetFocused(aFocused);
   189   return NS_OK;
   190 }
   192 NS_IMETHODIMP nsTreeBoxObject::SetFocused(bool aFocused)
   193 {
   194   nsTreeBodyFrame* body = GetTreeBody();
   195   if (body)
   196     return body->SetFocused(aFocused);
   197   return NS_OK;
   198 }
   200 NS_IMETHODIMP nsTreeBoxObject::GetTreeBody(nsIDOMElement** aElement)
   201 {
   202   *aElement = nullptr;
   203   nsTreeBodyFrame* body = GetTreeBody();
   204   if (body) 
   205     return body->GetTreeBody(aElement);
   206   return NS_OK;
   207 }
   209 NS_IMETHODIMP nsTreeBoxObject::GetColumns(nsITreeColumns** aColumns)
   210 {
   211   *aColumns = nullptr;
   212   nsTreeBodyFrame* body = GetTreeBody();
   213   if (body) 
   214     *aColumns = body->Columns().take();
   215   return NS_OK;
   216 }
   218 NS_IMETHODIMP nsTreeBoxObject::GetRowHeight(int32_t* aRowHeight)
   219 {
   220   *aRowHeight = 0;
   221   nsTreeBodyFrame* body = GetTreeBody();
   222   if (body) 
   223     return body->GetRowHeight(aRowHeight);
   224   return NS_OK;
   225 }
   227 NS_IMETHODIMP nsTreeBoxObject::GetRowWidth(int32_t *aRowWidth)
   228 {
   229   *aRowWidth = 0;
   230   nsTreeBodyFrame* body = GetTreeBody();
   231   if (body) 
   232     return body->GetRowWidth(aRowWidth);
   233   return NS_OK;
   234 }
   236 NS_IMETHODIMP nsTreeBoxObject::GetFirstVisibleRow(int32_t *aFirstVisibleRow)
   237 {
   238   *aFirstVisibleRow = 0;
   239   nsTreeBodyFrame* body = GetTreeBody();
   240   if (body)
   241     *aFirstVisibleRow = body->FirstVisibleRow();
   242   return NS_OK;
   243 }
   245 NS_IMETHODIMP nsTreeBoxObject::GetLastVisibleRow(int32_t *aLastVisibleRow)
   246 {
   247   *aLastVisibleRow = 0;
   248   nsTreeBodyFrame* body = GetTreeBody();
   249   if (body)
   250     *aLastVisibleRow = body->LastVisibleRow();
   251   return NS_OK;
   252 }
   254 NS_IMETHODIMP nsTreeBoxObject::GetHorizontalPosition(int32_t *aHorizontalPosition)
   255 {
   256   *aHorizontalPosition = 0;
   257   nsTreeBodyFrame* body = GetTreeBody();
   258   if (body)
   259     return body->GetHorizontalPosition(aHorizontalPosition);
   260   return NS_OK;
   261 }
   263 NS_IMETHODIMP nsTreeBoxObject::GetPageLength(int32_t *aPageLength)
   264 {
   265   *aPageLength = 0;
   266   nsTreeBodyFrame* body = GetTreeBody();
   267   if (body)
   268     *aPageLength = body->PageLength();
   269   return NS_OK;
   270 }
   272 NS_IMETHODIMP nsTreeBoxObject::GetSelectionRegion(nsIScriptableRegion **aRegion)
   273 {
   274  *aRegion = nullptr;
   275   nsTreeBodyFrame* body = GetTreeBody();
   276   if (body)
   277     return body->GetSelectionRegion(aRegion);
   278   return NS_OK;
   279 }
   281 NS_IMETHODIMP
   282 nsTreeBoxObject::EnsureRowIsVisible(int32_t aRow)
   283 {
   284   nsTreeBodyFrame* body = GetTreeBody();
   285   if (body)
   286     return body->EnsureRowIsVisible(aRow);
   287   return NS_OK;
   288 }
   290 NS_IMETHODIMP 
   291 nsTreeBoxObject::EnsureCellIsVisible(int32_t aRow, nsITreeColumn* aCol)
   292 {
   293   nsTreeBodyFrame* body = GetTreeBody();
   294   if (body)
   295     return body->EnsureCellIsVisible(aRow, aCol);
   296   return NS_OK;
   297     return NS_ERROR_NOT_IMPLEMENTED;
   298 }
   300 NS_IMETHODIMP
   301 nsTreeBoxObject::ScrollToRow(int32_t aRow)
   302 {
   303   nsTreeBodyFrame* body = GetTreeBody(true);
   304   if (body)
   305     return body->ScrollToRow(aRow);
   306   return NS_OK;
   307 }
   309 NS_IMETHODIMP
   310 nsTreeBoxObject::ScrollByLines(int32_t aNumLines)
   311 {
   312   nsTreeBodyFrame* body = GetTreeBody();
   313   if (body)
   314     return body->ScrollByLines(aNumLines);
   315   return NS_OK;
   316 }
   318 NS_IMETHODIMP
   319 nsTreeBoxObject::ScrollByPages(int32_t aNumPages)
   320 {
   321   nsTreeBodyFrame* body = GetTreeBody();
   322   if (body)
   323     return body->ScrollByPages(aNumPages);
   324   return NS_OK;
   325 }
   327 NS_IMETHODIMP 
   328 nsTreeBoxObject::ScrollToCell(int32_t aRow, nsITreeColumn* aCol)
   329 {
   330   nsTreeBodyFrame* body = GetTreeBody();
   331   if (body)
   332     return body->ScrollToCell(aRow, aCol);
   333   return NS_OK;
   334 }
   336 NS_IMETHODIMP 
   337 nsTreeBoxObject::ScrollToColumn(nsITreeColumn* aCol)
   338 {
   339   nsTreeBodyFrame* body = GetTreeBody();
   340   if (body)
   341     return body->ScrollToColumn(aCol);
   342   return NS_OK;
   343 }
   345 NS_IMETHODIMP 
   346 nsTreeBoxObject::ScrollToHorizontalPosition(int32_t aHorizontalPosition)
   347 {
   348   nsTreeBodyFrame* body = GetTreeBody();
   349   if (body)
   350     return body->ScrollToHorizontalPosition(aHorizontalPosition);
   351   return NS_OK;
   352 }
   354 NS_IMETHODIMP nsTreeBoxObject::Invalidate()
   355 {
   356   nsTreeBodyFrame* body = GetTreeBody();
   357   if (body)
   358     return body->Invalidate();
   359   return NS_OK;
   360 }
   362 NS_IMETHODIMP nsTreeBoxObject::InvalidateColumn(nsITreeColumn* aCol)
   363 {
   364   nsTreeBodyFrame* body = GetTreeBody();
   365   if (body)
   366     return body->InvalidateColumn(aCol);
   367   return NS_OK;
   368 }
   370 NS_IMETHODIMP nsTreeBoxObject::InvalidateRow(int32_t aIndex)
   371 {
   372   nsTreeBodyFrame* body = GetTreeBody();
   373   if (body)
   374     return body->InvalidateRow(aIndex);
   375   return NS_OK;
   376 }
   378 NS_IMETHODIMP nsTreeBoxObject::InvalidateCell(int32_t aRow, nsITreeColumn* aCol)
   379 {
   380   nsTreeBodyFrame* body = GetTreeBody();
   381   if (body)
   382     return body->InvalidateCell(aRow, aCol);
   383   return NS_OK;
   384 }
   386 NS_IMETHODIMP nsTreeBoxObject::InvalidateRange(int32_t aStart, int32_t aEnd)
   387 {
   388   nsTreeBodyFrame* body = GetTreeBody();
   389   if (body)
   390     return body->InvalidateRange(aStart, aEnd);
   391   return NS_OK;
   392 }
   394 NS_IMETHODIMP nsTreeBoxObject::InvalidateColumnRange(int32_t aStart, int32_t aEnd, nsITreeColumn* aCol)
   395 {
   396   nsTreeBodyFrame* body = GetTreeBody();
   397   if (body)
   398     return body->InvalidateColumnRange(aStart, aEnd, aCol);
   399   return NS_OK;
   400 }
   402 NS_IMETHODIMP nsTreeBoxObject::GetRowAt(int32_t x, int32_t y, int32_t *aRow)
   403 {
   404   *aRow = 0;
   405   nsTreeBodyFrame* body = GetTreeBody();
   406   if (body)
   407     return body->GetRowAt(x, y, aRow);
   408   return NS_OK;
   409 }
   411 NS_IMETHODIMP nsTreeBoxObject::GetCellAt(int32_t aX, int32_t aY, int32_t *aRow, nsITreeColumn** aCol,
   412                                          nsACString& aChildElt)
   413 {
   414   *aRow = 0;
   415   *aCol = nullptr;
   416   nsTreeBodyFrame* body = GetTreeBody();
   417   if (body)
   418     return body->GetCellAt(aX, aY, aRow, aCol, aChildElt);
   419   return NS_OK;
   420 }
   422 NS_IMETHODIMP
   423 nsTreeBoxObject::GetCoordsForCellItem(int32_t aRow, nsITreeColumn* aCol, const nsACString& aElement, 
   424                                       int32_t *aX, int32_t *aY, int32_t *aWidth, int32_t *aHeight)
   425 {
   426   *aX = *aY = *aWidth = *aHeight = 0;
   427   nsTreeBodyFrame* body = GetTreeBody();
   428   if (body)
   429     return body->GetCoordsForCellItem(aRow, aCol, aElement, aX, aY, aWidth, aHeight);
   430   return NS_OK;
   431 }
   433 NS_IMETHODIMP
   434 nsTreeBoxObject::IsCellCropped(int32_t aRow, nsITreeColumn* aCol, bool *aIsCropped)
   435 {  
   436   *aIsCropped = false;
   437   nsTreeBodyFrame* body = GetTreeBody();
   438   if (body)
   439     return body->IsCellCropped(aRow, aCol, aIsCropped);
   440   return NS_OK;
   441 }
   443 NS_IMETHODIMP nsTreeBoxObject::RowCountChanged(int32_t aIndex, int32_t aDelta)
   444 {
   445   nsTreeBodyFrame* body = GetTreeBody();
   446   if (body)
   447     return body->RowCountChanged(aIndex, aDelta);
   448   return NS_OK;
   449 }
   451 NS_IMETHODIMP nsTreeBoxObject::BeginUpdateBatch()
   452 {
   453   nsTreeBodyFrame* body = GetTreeBody();
   454   if (body)
   455     return body->BeginUpdateBatch();
   456   return NS_OK;
   457 }
   459 NS_IMETHODIMP nsTreeBoxObject::EndUpdateBatch()
   460 {
   461   nsTreeBodyFrame* body = GetTreeBody();
   462   if (body)
   463     return body->EndUpdateBatch();
   464   return NS_OK;
   465 }
   467 NS_IMETHODIMP nsTreeBoxObject::ClearStyleAndImageCaches()
   468 {
   469   nsTreeBodyFrame* body = GetTreeBody();
   470   if (body)
   471     return body->ClearStyleAndImageCaches();
   472   return NS_OK;
   473 }
   475 void
   476 nsTreeBoxObject::ClearCachedValues()
   477 {
   478   mTreeBody = nullptr;
   479 }    
   481 // Creation Routine ///////////////////////////////////////////////////////////////////////
   483 nsresult
   484 NS_NewTreeBoxObject(nsIBoxObject** aResult)
   485 {
   486   *aResult = new nsTreeBoxObject;
   487   if (!*aResult)
   488     return NS_ERROR_OUT_OF_MEMORY;
   489   NS_ADDREF(*aResult);
   490   return NS_OK;
   491 }

mercurial