security/manager/pki/src/nsASN1Tree.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 #include "nsASN1Tree.h"
     5 #include "nsIComponentManager.h"
     6 #include "nsString.h"
     7 #include "nsCRT.h"
     8 #include "nsIMutableArray.h"
     9 #include "nsArrayUtils.h"
    11 NS_IMPL_ISUPPORTS(nsNSSASN1Tree, nsIASN1Tree, nsITreeView)
    13 nsNSSASN1Tree::nsNSSASN1Tree() 
    14 :mTopNode(nullptr)
    15 {
    16 }
    18 nsNSSASN1Tree::~nsNSSASN1Tree()
    19 {
    20   ClearNodes();
    21 }
    23 void nsNSSASN1Tree::ClearNodesRecursively(myNode *n)
    24 {
    25   myNode *walk = n;
    26   while (walk) {
    27     myNode *kill = walk;
    29     if (walk->child) {
    30       ClearNodesRecursively(walk->child);
    31     }
    33     walk = walk->next;
    34     delete kill;
    35   }
    36 }
    38 void nsNSSASN1Tree::ClearNodes()
    39 {
    40   ClearNodesRecursively(mTopNode);
    41   mTopNode = nullptr;
    42 }
    44 void nsNSSASN1Tree::InitChildsRecursively(myNode *n)
    45 {
    46   if (!n->obj)
    47     return;
    49   n->seq = do_QueryInterface(n->obj);
    50   if (!n->seq)
    51     return;
    53   // If the object is a sequence, there might still be a reason
    54   // why it should not be displayed as a container.
    55   // If we decide that it has all the properties to justify
    56   // displaying as a container, we will create a new child chain.
    57   // If we decide, it does not make sense to display as a container,
    58   // we forget that it is a sequence by erasing n->seq.
    59   // That way, n->seq and n->child will be either both set or both null.
    61   bool isContainer;
    62   n->seq->GetIsValidContainer(&isContainer);
    63   if (!isContainer) {
    64     n->seq = nullptr;
    65     return;
    66   }
    68   nsCOMPtr<nsIMutableArray> asn1Objects;
    69   n->seq->GetASN1Objects(getter_AddRefs(asn1Objects));
    70   uint32_t numObjects;
    71   asn1Objects->GetLength(&numObjects);
    73   if (!numObjects) {
    74     n->seq = nullptr;
    75     return;
    76   }
    78   myNode *walk = nullptr;
    79   myNode *prev = nullptr;
    81   uint32_t i;
    82   nsCOMPtr<nsISupports> isupports;
    83   for (i=0; i<numObjects; i++) {
    84     if (0 == i) {
    85       n->child = walk = new myNode;
    86     }
    87     else {
    88       walk = new myNode;
    89     }
    91     walk->parent = n;
    92     if (prev) {
    93       prev->next = walk;
    94     }
    96     walk->obj = do_QueryElementAt(asn1Objects, i);
    98     InitChildsRecursively(walk);
   100     prev = walk;
   101   }
   102 }
   104 void nsNSSASN1Tree::InitNodes()
   105 {
   106   ClearNodes();
   108   mTopNode = new myNode;
   109   mTopNode->obj = mASN1Object;
   111   InitChildsRecursively(mTopNode);
   112 }
   114 /* void loadASN1Structure (in nsIASN1Object asn1Object); */
   115 NS_IMETHODIMP 
   116 nsNSSASN1Tree::LoadASN1Structure(nsIASN1Object *asn1Object)
   117 {
   118   //
   119   // The tree won't automatically re-draw if the contents
   120   // have been changed.  So I do a quick test here to let
   121   // me know if I should forced the tree to redraw itself
   122   // by calling RowCountChanged on it.
   123   //
   124   bool redraw = (mASN1Object && mTree);
   125   int32_t rowsToDelete = 0;
   127   if (redraw) {
   128     // This is the number of rows we will be deleting after
   129     // the contents have changed.
   130     rowsToDelete = 0-CountVisibleNodes(mTopNode);
   131   }
   133   mASN1Object = asn1Object;
   134   InitNodes();
   136   if (redraw) {
   137     // The number of rows in the new content.
   138     int32_t newRows = CountVisibleNodes(mTopNode);
   139     mTree->BeginUpdateBatch();
   140     // Erase all of the old rows.
   141     mTree->RowCountChanged(0, rowsToDelete);
   142     // Replace them with the new contents
   143     mTree->RowCountChanged(0, newRows);
   144     mTree->EndUpdateBatch();
   145   }
   147   return NS_OK;
   148 }
   150 /* readonly attribute long rowCount; */
   151 NS_IMETHODIMP 
   152 nsNSSASN1Tree::GetRowCount(int32_t *aRowCount)
   153 {
   154   if (mASN1Object) {
   155     *aRowCount = CountVisibleNodes(mTopNode);
   156   } else {
   157     *aRowCount = 0;
   158   }
   159   return NS_OK;
   160 }
   162 /* attribute nsITreeSelection selection; */
   163 NS_IMETHODIMP 
   164 nsNSSASN1Tree::GetSelection(nsITreeSelection * *aSelection)
   165 {
   166   *aSelection = mSelection;
   167   NS_IF_ADDREF(*aSelection);
   168   return NS_OK;
   169 }
   171 NS_IMETHODIMP 
   172 nsNSSASN1Tree::SetSelection(nsITreeSelection * aSelection)
   173 {
   174   mSelection = aSelection;
   175   return NS_OK;
   176 }
   178 NS_IMETHODIMP 
   179 nsNSSASN1Tree::GetRowProperties(int32_t index, nsAString& aProps)
   180 {
   181   return NS_OK;
   182 }
   184 NS_IMETHODIMP 
   185 nsNSSASN1Tree::GetCellProperties(int32_t row, nsITreeColumn* col, 
   186                                  nsAString& aProps)
   187 {
   188   return NS_OK;
   189 }
   191 NS_IMETHODIMP 
   192 nsNSSASN1Tree::GetColumnProperties(nsITreeColumn* col, nsAString& aProps)
   193 {
   194   return NS_OK;
   195 }
   197 /* boolean isContainer (in long index); */
   198 NS_IMETHODIMP 
   199 nsNSSASN1Tree::IsContainer(int32_t index, bool *_retval)
   200 {
   201   myNode *n = FindNodeFromIndex(index);
   202   if (!n)
   203     return NS_ERROR_FAILURE;
   205   *_retval = (n->seq != nullptr);
   206   return NS_OK; 
   207 }
   209 /* boolean isContainerOpen (in long index); */
   210 NS_IMETHODIMP 
   211 nsNSSASN1Tree::IsContainerOpen(int32_t index, bool *_retval)
   212 {
   213   myNode *n = FindNodeFromIndex(index);
   214   if (!n || !n->seq)
   215     return NS_ERROR_FAILURE;
   217   n->seq->GetIsExpanded(_retval);
   218   return NS_OK;
   219 }
   221 /* boolean isContainerEmpty (in long index); */
   222 NS_IMETHODIMP 
   223 nsNSSASN1Tree::IsContainerEmpty(int32_t index, bool *_retval)
   224 {
   225   *_retval = false;
   226   return NS_OK;
   227 }
   229 /* boolean isSeparator (in long index); */
   230 NS_IMETHODIMP 
   231 nsNSSASN1Tree::IsSeparator(int32_t index, bool *_retval)
   232 {
   233   *_retval = false;
   234   return NS_OK; 
   235 }
   237 /* long getLevel (in long index); */
   238 NS_IMETHODIMP 
   239 nsNSSASN1Tree::GetLevel(int32_t index, int32_t *_retval)
   240 {
   241   int32_t parentIndex;
   242   int32_t nodeLevel;
   244   myNode *n = FindNodeFromIndex(index, &parentIndex, &nodeLevel);
   245   if (!n)
   246     return NS_ERROR_FAILURE;
   248   *_retval = nodeLevel;
   249   return NS_OK; 
   250 }
   252 /* Astring getImageSrc (in long row, in nsITreeColumn col); */
   253 NS_IMETHODIMP 
   254 nsNSSASN1Tree::GetImageSrc(int32_t row, nsITreeColumn* col, 
   255                            nsAString& _retval)
   256 {
   257   return NS_OK;
   258 }
   260 /* long getProgressMode (in long row, in nsITreeColumn col); */
   261 NS_IMETHODIMP 
   262 nsNSSASN1Tree::GetProgressMode(int32_t row, nsITreeColumn* col, int32_t* _retval)
   263 {
   264   return NS_OK;
   265 }
   267 /* Astring getCellValue (in long row, in nsITreeColumn col); */
   268 NS_IMETHODIMP 
   269 nsNSSASN1Tree::GetCellValue(int32_t row, nsITreeColumn* col, 
   270                             nsAString& _retval)
   271 {
   272   return NS_OK;
   273 }
   275 /* Astring getCellText (in long row, in nsITreeColumn col); */
   276 NS_IMETHODIMP 
   277 nsNSSASN1Tree::GetCellText(int32_t row, nsITreeColumn* col, 
   278                            nsAString& _retval)
   279 {
   280   _retval.Truncate();
   282   myNode* n = FindNodeFromIndex(row);
   283   if (!n)
   284     return NS_ERROR_FAILURE;
   286   // There's only one column for ASN1 dump.
   287   return n->obj->GetDisplayName(_retval);
   288 }
   290 /* wstring getDisplayData (in unsigned long index); */
   291 NS_IMETHODIMP 
   292 nsNSSASN1Tree::GetDisplayData(uint32_t index, nsAString &_retval)
   293 {
   294   myNode *n = FindNodeFromIndex(index);
   295   if (!n)
   296     return NS_ERROR_FAILURE;
   298   n->obj->GetDisplayValue(_retval);
   299   return NS_OK;
   300 }
   302 /* void setTree (in nsITreeBoxObject tree); */
   303 NS_IMETHODIMP 
   304 nsNSSASN1Tree::SetTree(nsITreeBoxObject *tree)
   305 {
   306   mTree = tree;
   307   return NS_OK;
   308 }
   310 /* void toggleOpenState (in long index); */
   311 NS_IMETHODIMP 
   312 nsNSSASN1Tree::ToggleOpenState(int32_t index)
   313 {
   314   myNode *n = FindNodeFromIndex(index);
   315   if (!n)
   316     return NS_ERROR_FAILURE;
   318   if (!n->seq)
   319     return NS_ERROR_FAILURE;
   321   bool IsExpanded;
   322   n->seq->GetIsExpanded(&IsExpanded);
   323   int32_t rowCountChange;
   324   if (IsExpanded) {
   325     rowCountChange = -CountVisibleNodes(n->child);
   326     n->seq->SetIsExpanded(false);
   327   } else {
   328     n->seq->SetIsExpanded(true);
   329     rowCountChange = CountVisibleNodes(n->child);
   330   }
   331   if (mTree)
   332     mTree->RowCountChanged(index, rowCountChange);
   333   return NS_OK;
   334 }
   336 /* void cycleHeader (in nsITreeColumn col); */
   337 NS_IMETHODIMP 
   338 nsNSSASN1Tree::CycleHeader(nsITreeColumn* col)
   339 {
   340   return NS_OK;
   341 }
   343 /* void selectionChanged (); */
   344 NS_IMETHODIMP 
   345 nsNSSASN1Tree::SelectionChanged()
   346 {
   347   return NS_ERROR_NOT_IMPLEMENTED;
   348 }
   350 /* void cycleCell (in long row, in nsITreeColumn col); */
   351 NS_IMETHODIMP 
   352 nsNSSASN1Tree::CycleCell(int32_t row, nsITreeColumn* col)
   353 {
   354   return NS_OK;
   355 }
   357 /* boolean isEditable (in long row, in nsITreeColumn col); */
   358 NS_IMETHODIMP 
   359 nsNSSASN1Tree::IsEditable(int32_t row, nsITreeColumn* col, 
   360                           bool *_retval)
   361 {
   362   *_retval = false;
   363   return NS_OK;
   364 }
   366 /* boolean isSelectable (in long row, in nsITreeColumn col); */
   367 NS_IMETHODIMP 
   368 nsNSSASN1Tree::IsSelectable(int32_t row, nsITreeColumn* col, 
   369                             bool *_retval)
   370 {
   371   *_retval = false;
   372   return NS_OK;
   373 }
   375 /* void setCellValue (in long row, in nsITreeColumn col, in AString value); */
   376 NS_IMETHODIMP 
   377 nsNSSASN1Tree::SetCellValue(int32_t row, nsITreeColumn* col, 
   378                             const nsAString& value)
   379 {
   380   return NS_OK;
   381 }
   383 /* void setCellText (in long row, in nsITreeColumn col, in AString value); */
   384 NS_IMETHODIMP 
   385 nsNSSASN1Tree::SetCellText(int32_t row, nsITreeColumn* col, 
   386                            const nsAString& value)
   387 {
   388   return NS_OK;
   389 }
   391 /* void performAction (in wstring action); */
   392 NS_IMETHODIMP 
   393 nsNSSASN1Tree::PerformAction(const char16_t *action)
   394 {
   395   return NS_OK;
   396 }
   398 /* void performActionOnRow (in wstring action, in long row); */
   399 NS_IMETHODIMP 
   400 nsNSSASN1Tree::PerformActionOnRow(const char16_t *action, int32_t row)
   401 {
   402   return NS_OK;
   403 }
   405 /* void performActionOnCell (in wstring action, in long row, in nsITreeColumn col); */
   406 NS_IMETHODIMP 
   407 nsNSSASN1Tree::PerformActionOnCell(const char16_t *action, int32_t row, 
   408                                    nsITreeColumn* col)
   409 {
   410   return NS_OK;
   411 }
   413 //
   414 // CanDrop
   415 //
   416 NS_IMETHODIMP nsNSSASN1Tree::CanDrop(int32_t index, int32_t orientation,
   417                                      nsIDOMDataTransfer* aDataTransfer, bool *_retval)
   418 {
   419   NS_ENSURE_ARG_POINTER(_retval);
   420   *_retval = false;
   422   return NS_OK;
   423 }
   426 //
   427 // Drop
   428 //
   429 NS_IMETHODIMP nsNSSASN1Tree::Drop(int32_t row, int32_t orient, nsIDOMDataTransfer* aDataTransfer)
   430 {
   431   return NS_OK;
   432 }
   435 //
   436 // IsSorted
   437 //
   438 // ...
   439 //
   440 NS_IMETHODIMP nsNSSASN1Tree::IsSorted(bool *_retval)
   441 {
   442   *_retval = false;
   443   return NS_OK;
   444 }
   447 /* long getParentIndex (in long rowIndex); */
   448 NS_IMETHODIMP 
   449 nsNSSASN1Tree::GetParentIndex(int32_t rowIndex, int32_t *_retval)
   450 {
   451   int32_t parentIndex = -1;
   453   myNode *n = FindNodeFromIndex(rowIndex, &parentIndex);
   454   if (!n)
   455     return NS_ERROR_FAILURE;
   457   *_retval = parentIndex;
   458   return NS_OK; 
   459 }
   461 /* boolean hasNextSibling (in long rowIndex, in long afterIndex); */
   462 NS_IMETHODIMP 
   463 nsNSSASN1Tree::HasNextSibling(int32_t rowIndex, int32_t afterIndex, 
   464                               bool *_retval)
   465 {
   466   myNode *n = FindNodeFromIndex(rowIndex);
   467   if (!n)
   468     return NS_ERROR_FAILURE;
   470   if (!n->next) {
   471     *_retval = false;
   472   }
   473   else {
   474     int32_t nTotalSize = CountVisibleNodes(n);
   475     int32_t nLastChildPos = rowIndex + nTotalSize -1;
   476     int32_t nextSiblingPos = nLastChildPos +1;
   477     *_retval = (nextSiblingPos > afterIndex);
   478   }
   480   return NS_OK; 
   481 }
   483 int32_t nsNSSASN1Tree::CountVisibleNodes(myNode *n)
   484 {
   485   if (!n)
   486     return 0;
   488   myNode *walk = n;
   489   int32_t count = 0;
   491   while (walk) {
   492     ++count;
   494     if (walk->seq) {
   495       bool IsExpanded;
   496       walk->seq->GetIsExpanded(&IsExpanded);
   497       if (IsExpanded) {
   498         count += CountVisibleNodes(walk->child);
   499       }
   500     }
   502     walk = walk->next;
   503   }
   505   return count;
   506 }
   508 // Entry point for find
   509 nsNSSASN1Tree::myNode *
   510 nsNSSASN1Tree::FindNodeFromIndex(int32_t wantedIndex, 
   511                                  int32_t *optionalOutParentIndex, int32_t *optionalOutLevel)
   512 {
   513   if (0 == wantedIndex) {
   514     if (optionalOutLevel) {
   515       *optionalOutLevel = 0;
   516     }
   517     if (optionalOutParentIndex) {
   518       *optionalOutParentIndex = -1;
   519     }
   520     return mTopNode;
   521   }
   522   else {
   523     int32_t index = 0;
   524     int32_t level = 0;
   525     return FindNodeFromIndex(mTopNode, wantedIndex, index, level, 
   526                              optionalOutParentIndex, optionalOutLevel);
   527   }
   528 }
   530 // Internal recursive helper function
   531 nsNSSASN1Tree::myNode *
   532 nsNSSASN1Tree::FindNodeFromIndex(myNode *n, int32_t wantedIndex,
   533                                  int32_t &index_counter, int32_t &level_counter,
   534                                  int32_t *optionalOutParentIndex, int32_t *optionalOutLevel)
   535 {
   536   if (!n)
   537     return nullptr;
   539   myNode *walk = n;
   540   int32_t parentIndex = index_counter-1;
   542   while (walk) {
   543     if (index_counter == wantedIndex) {
   544       if (optionalOutLevel) {
   545         *optionalOutLevel = level_counter;
   546       }
   547       if (optionalOutParentIndex) {
   548         *optionalOutParentIndex = parentIndex;
   549       }
   550       return walk;
   551     }
   553     if (walk->seq) {
   554       bool IsExpanded;
   555       walk->seq->GetIsExpanded(&IsExpanded);
   556       if (IsExpanded) {
   557         ++index_counter; // set to walk->child
   559         ++level_counter;
   560         myNode *found = FindNodeFromIndex(walk->child, wantedIndex, index_counter, level_counter,
   561                                           optionalOutParentIndex, optionalOutLevel);
   562         --level_counter;
   564         if (found)
   565           return found;
   566       }
   567     }
   569     walk = walk->next;
   570     if (walk) {
   571       ++index_counter;
   572     }
   573   }
   575   return nullptr;
   576 }

mercurial