security/manager/pki/src/nsASN1Tree.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:46b19724c66a
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"
10
11 NS_IMPL_ISUPPORTS(nsNSSASN1Tree, nsIASN1Tree, nsITreeView)
12
13 nsNSSASN1Tree::nsNSSASN1Tree()
14 :mTopNode(nullptr)
15 {
16 }
17
18 nsNSSASN1Tree::~nsNSSASN1Tree()
19 {
20 ClearNodes();
21 }
22
23 void nsNSSASN1Tree::ClearNodesRecursively(myNode *n)
24 {
25 myNode *walk = n;
26 while (walk) {
27 myNode *kill = walk;
28
29 if (walk->child) {
30 ClearNodesRecursively(walk->child);
31 }
32
33 walk = walk->next;
34 delete kill;
35 }
36 }
37
38 void nsNSSASN1Tree::ClearNodes()
39 {
40 ClearNodesRecursively(mTopNode);
41 mTopNode = nullptr;
42 }
43
44 void nsNSSASN1Tree::InitChildsRecursively(myNode *n)
45 {
46 if (!n->obj)
47 return;
48
49 n->seq = do_QueryInterface(n->obj);
50 if (!n->seq)
51 return;
52
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.
60
61 bool isContainer;
62 n->seq->GetIsValidContainer(&isContainer);
63 if (!isContainer) {
64 n->seq = nullptr;
65 return;
66 }
67
68 nsCOMPtr<nsIMutableArray> asn1Objects;
69 n->seq->GetASN1Objects(getter_AddRefs(asn1Objects));
70 uint32_t numObjects;
71 asn1Objects->GetLength(&numObjects);
72
73 if (!numObjects) {
74 n->seq = nullptr;
75 return;
76 }
77
78 myNode *walk = nullptr;
79 myNode *prev = nullptr;
80
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 }
90
91 walk->parent = n;
92 if (prev) {
93 prev->next = walk;
94 }
95
96 walk->obj = do_QueryElementAt(asn1Objects, i);
97
98 InitChildsRecursively(walk);
99
100 prev = walk;
101 }
102 }
103
104 void nsNSSASN1Tree::InitNodes()
105 {
106 ClearNodes();
107
108 mTopNode = new myNode;
109 mTopNode->obj = mASN1Object;
110
111 InitChildsRecursively(mTopNode);
112 }
113
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;
126
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 }
132
133 mASN1Object = asn1Object;
134 InitNodes();
135
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 }
146
147 return NS_OK;
148 }
149
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 }
161
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 }
170
171 NS_IMETHODIMP
172 nsNSSASN1Tree::SetSelection(nsITreeSelection * aSelection)
173 {
174 mSelection = aSelection;
175 return NS_OK;
176 }
177
178 NS_IMETHODIMP
179 nsNSSASN1Tree::GetRowProperties(int32_t index, nsAString& aProps)
180 {
181 return NS_OK;
182 }
183
184 NS_IMETHODIMP
185 nsNSSASN1Tree::GetCellProperties(int32_t row, nsITreeColumn* col,
186 nsAString& aProps)
187 {
188 return NS_OK;
189 }
190
191 NS_IMETHODIMP
192 nsNSSASN1Tree::GetColumnProperties(nsITreeColumn* col, nsAString& aProps)
193 {
194 return NS_OK;
195 }
196
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;
204
205 *_retval = (n->seq != nullptr);
206 return NS_OK;
207 }
208
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;
216
217 n->seq->GetIsExpanded(_retval);
218 return NS_OK;
219 }
220
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 }
228
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 }
236
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;
243
244 myNode *n = FindNodeFromIndex(index, &parentIndex, &nodeLevel);
245 if (!n)
246 return NS_ERROR_FAILURE;
247
248 *_retval = nodeLevel;
249 return NS_OK;
250 }
251
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 }
259
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 }
266
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 }
274
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();
281
282 myNode* n = FindNodeFromIndex(row);
283 if (!n)
284 return NS_ERROR_FAILURE;
285
286 // There's only one column for ASN1 dump.
287 return n->obj->GetDisplayName(_retval);
288 }
289
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;
297
298 n->obj->GetDisplayValue(_retval);
299 return NS_OK;
300 }
301
302 /* void setTree (in nsITreeBoxObject tree); */
303 NS_IMETHODIMP
304 nsNSSASN1Tree::SetTree(nsITreeBoxObject *tree)
305 {
306 mTree = tree;
307 return NS_OK;
308 }
309
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;
317
318 if (!n->seq)
319 return NS_ERROR_FAILURE;
320
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 }
335
336 /* void cycleHeader (in nsITreeColumn col); */
337 NS_IMETHODIMP
338 nsNSSASN1Tree::CycleHeader(nsITreeColumn* col)
339 {
340 return NS_OK;
341 }
342
343 /* void selectionChanged (); */
344 NS_IMETHODIMP
345 nsNSSASN1Tree::SelectionChanged()
346 {
347 return NS_ERROR_NOT_IMPLEMENTED;
348 }
349
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 }
356
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 }
365
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 }
374
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 }
382
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 }
390
391 /* void performAction (in wstring action); */
392 NS_IMETHODIMP
393 nsNSSASN1Tree::PerformAction(const char16_t *action)
394 {
395 return NS_OK;
396 }
397
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 }
404
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 }
412
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;
421
422 return NS_OK;
423 }
424
425
426 //
427 // Drop
428 //
429 NS_IMETHODIMP nsNSSASN1Tree::Drop(int32_t row, int32_t orient, nsIDOMDataTransfer* aDataTransfer)
430 {
431 return NS_OK;
432 }
433
434
435 //
436 // IsSorted
437 //
438 // ...
439 //
440 NS_IMETHODIMP nsNSSASN1Tree::IsSorted(bool *_retval)
441 {
442 *_retval = false;
443 return NS_OK;
444 }
445
446
447 /* long getParentIndex (in long rowIndex); */
448 NS_IMETHODIMP
449 nsNSSASN1Tree::GetParentIndex(int32_t rowIndex, int32_t *_retval)
450 {
451 int32_t parentIndex = -1;
452
453 myNode *n = FindNodeFromIndex(rowIndex, &parentIndex);
454 if (!n)
455 return NS_ERROR_FAILURE;
456
457 *_retval = parentIndex;
458 return NS_OK;
459 }
460
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;
469
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 }
479
480 return NS_OK;
481 }
482
483 int32_t nsNSSASN1Tree::CountVisibleNodes(myNode *n)
484 {
485 if (!n)
486 return 0;
487
488 myNode *walk = n;
489 int32_t count = 0;
490
491 while (walk) {
492 ++count;
493
494 if (walk->seq) {
495 bool IsExpanded;
496 walk->seq->GetIsExpanded(&IsExpanded);
497 if (IsExpanded) {
498 count += CountVisibleNodes(walk->child);
499 }
500 }
501
502 walk = walk->next;
503 }
504
505 return count;
506 }
507
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 }
529
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;
538
539 myNode *walk = n;
540 int32_t parentIndex = index_counter-1;
541
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 }
552
553 if (walk->seq) {
554 bool IsExpanded;
555 walk->seq->GetIsExpanded(&IsExpanded);
556 if (IsExpanded) {
557 ++index_counter; // set to walk->child
558
559 ++level_counter;
560 myNode *found = FindNodeFromIndex(walk->child, wantedIndex, index_counter, level_counter,
561 optionalOutParentIndex, optionalOutLevel);
562 --level_counter;
563
564 if (found)
565 return found;
566 }
567 }
568
569 walk = walk->next;
570 if (walk) {
571 ++index_counter;
572 }
573 }
574
575 return nullptr;
576 }
577

mercurial