Bug 1605894 reduce the proliferation of DefaultLoopbackTone to only AudioStreamFlowin...
[gecko.git] / security / manager / ssl / nsCertTree.cpp
blob0448cf4566514fdb123dbb4316dc013a1fdd0516
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/. */
5 #include "nsCertTree.h"
7 #include "ScopedNSSTypes.h"
8 #include "mozilla/Logging.h"
9 #include "mozilla/Maybe.h"
10 #include "mozilla/intl/AppDateTimeFormat.h"
11 #include "nsArray.h"
12 #include "nsArrayUtils.h"
13 #include "nsHashKeys.h"
14 #include "nsISupportsPrimitives.h"
15 #include "nsIX509CertDB.h"
16 #include "nsIX509Cert.h"
17 #include "nsIX509CertValidity.h"
18 #include "nsNSSCertHelper.h"
19 #include "nsNSSCertificate.h"
20 #include "nsComponentManagerUtils.h"
21 #include "nsNSSCertificateDB.h"
22 #include "nsNSSHelper.h"
23 #include "nsReadableUtils.h"
24 #include "nsTHashtable.h"
25 #include "nsUnicharUtils.h"
26 #include "nsXPCOMCID.h"
27 #include "nsString.h"
28 #include "nsTreeColumns.h"
29 #include "mozpkix/pkixtypes.h"
31 using namespace mozilla;
33 extern LazyLogModule gPIPNSSLog;
35 // treeArrayElStr
37 // structure used to hold map of tree. Each thread (an organization
38 // field from a cert) has an element in the array. The numChildren field
39 // stores the number of certs corresponding to that thread.
40 struct treeArrayElStr {
41 nsString orgName; /* heading for thread */
42 bool open; /* toggle open state for thread */
43 int32_t certIndex; /* index into cert array for 1st cert */
44 int32_t numChildren; /* number of chidren (certs) for thread */
47 CompareCacheHashEntryPtr::CompareCacheHashEntryPtr() {
48 entry = new CompareCacheHashEntry;
51 CompareCacheHashEntryPtr::~CompareCacheHashEntryPtr() { delete entry; }
53 CompareCacheHashEntry::CompareCacheHashEntry() : key(nullptr), mCritInit() {
54 for (int i = 0; i < max_criterions; ++i) {
55 mCritInit[i] = false;
56 mCrit[i].SetIsVoid(true);
60 static bool CompareCacheMatchEntry(const PLDHashEntryHdr* hdr,
61 const void* key) {
62 const CompareCacheHashEntryPtr* entryPtr =
63 static_cast<const CompareCacheHashEntryPtr*>(hdr);
64 return entryPtr->entry->key == key;
67 static void CompareCacheInitEntry(PLDHashEntryHdr* hdr, const void* key) {
68 new (hdr) CompareCacheHashEntryPtr();
69 CompareCacheHashEntryPtr* entryPtr =
70 static_cast<CompareCacheHashEntryPtr*>(hdr);
71 entryPtr->entry->key = (void*)key;
74 static void CompareCacheClearEntry(PLDHashTable* table, PLDHashEntryHdr* hdr) {
75 CompareCacheHashEntryPtr* entryPtr =
76 static_cast<CompareCacheHashEntryPtr*>(hdr);
77 entryPtr->~CompareCacheHashEntryPtr();
80 static const PLDHashTableOps gMapOps = {
81 PLDHashTable::HashVoidPtrKeyStub, CompareCacheMatchEntry,
82 PLDHashTable::MoveEntryStub, CompareCacheClearEntry, CompareCacheInitEntry};
84 NS_IMPL_ISUPPORTS(nsCertTreeDispInfo, nsICertTreeItem)
86 nsCertTreeDispInfo::~nsCertTreeDispInfo() = default;
88 NS_IMETHODIMP
89 nsCertTreeDispInfo::GetCert(nsIX509Cert** aCert) {
90 NS_ENSURE_ARG(aCert);
91 nsCOMPtr<nsIX509Cert> cert = mCert;
92 cert.forget(aCert);
93 return NS_OK;
96 NS_IMPL_ISUPPORTS(nsCertTree, nsICertTree, nsITreeView)
98 nsCertTree::nsCertTree()
99 : mTreeArray(nullptr),
100 mNumOrgs(0),
101 mNumRows(0),
102 mCompareCache(&gMapOps, sizeof(CompareCacheHashEntryPtr),
103 kInitialCacheLength) {
104 mCellText = nullptr;
107 void nsCertTree::ClearCompareHash() {
108 mCompareCache.ClearAndPrepareForLength(kInitialCacheLength);
111 nsCertTree::~nsCertTree() { delete[] mTreeArray; }
113 void nsCertTree::FreeCertArray() { mDispInfo.Clear(); }
115 CompareCacheHashEntry* nsCertTree::getCacheEntry(void* cache, void* aCert) {
116 PLDHashTable& aCompareCache = *static_cast<PLDHashTable*>(cache);
117 auto entryPtr = static_cast<CompareCacheHashEntryPtr*>(
118 aCompareCache.Add(aCert, fallible));
119 return entryPtr ? entryPtr->entry : nullptr;
122 void nsCertTree::RemoveCacheEntry(void* key) { mCompareCache.Remove(key); }
124 // CountOrganizations
126 // Count the number of different organizations encountered in the cert
127 // list.
128 int32_t nsCertTree::CountOrganizations() {
129 uint32_t i, certCount;
130 certCount = mDispInfo.Length();
131 if (certCount == 0) return 0;
132 nsCOMPtr<nsIX509Cert> orgCert = mDispInfo.ElementAt(0)->mCert;
133 nsCOMPtr<nsIX509Cert> nextCert = nullptr;
134 int32_t orgCount = 1;
135 for (i = 1; i < certCount; i++) {
136 nextCert = mDispInfo.SafeElementAt(i, nullptr)->mCert;
137 // XXX we assume issuer org is always criterion 1
138 if (CmpBy(&mCompareCache, orgCert, nextCert, sort_IssuerOrg, sort_None,
139 sort_None) != 0) {
140 orgCert = nextCert;
141 orgCount++;
144 return orgCount;
147 // GetThreadDescAtIndex
149 // If the row at index is an organization thread, return the collection
150 // associated with that thread. Otherwise, return null.
151 treeArrayEl* nsCertTree::GetThreadDescAtIndex(int32_t index) {
152 int i, idx = 0;
153 if (index < 0) return nullptr;
154 for (i = 0; i < mNumOrgs; i++) {
155 if (index == idx) {
156 return &mTreeArray[i];
158 if (mTreeArray[i].open) {
159 idx += mTreeArray[i].numChildren;
161 idx++;
162 if (idx > index) break;
164 return nullptr;
167 // GetCertAtIndex
169 // If the row at index is a cert, return that cert. Otherwise, return null.
170 already_AddRefed<nsIX509Cert> nsCertTree::GetCertAtIndex(
171 int32_t index, int32_t* outAbsoluteCertOffset) {
172 RefPtr<nsCertTreeDispInfo> certdi(
173 GetDispInfoAtIndex(index, outAbsoluteCertOffset));
174 if (!certdi) return nullptr;
176 nsCOMPtr<nsIX509Cert> ret = certdi->mCert;
177 return ret.forget();
180 // If the row at index is a cert, return that cert. Otherwise, return null.
181 already_AddRefed<nsCertTreeDispInfo> nsCertTree::GetDispInfoAtIndex(
182 int32_t index, int32_t* outAbsoluteCertOffset) {
183 int i, idx = 0, cIndex = 0, nc;
184 if (index < 0) return nullptr;
185 // Loop over the threads
186 for (i = 0; i < mNumOrgs; i++) {
187 if (index == idx) return nullptr; // index is for thread
188 idx++; // get past the thread
189 nc = (mTreeArray[i].open) ? mTreeArray[i].numChildren : 0;
190 if (index < idx + nc) { // cert is within range of this thread
191 int32_t certIndex = cIndex + index - idx;
192 if (outAbsoluteCertOffset) *outAbsoluteCertOffset = certIndex;
193 RefPtr<nsCertTreeDispInfo> certdi(
194 mDispInfo.SafeElementAt(certIndex, nullptr));
195 if (certdi) {
196 return certdi.forget();
198 break;
200 if (mTreeArray[i].open) idx += mTreeArray[i].numChildren;
201 cIndex += mTreeArray[i].numChildren;
202 if (idx > index) break;
204 return nullptr;
207 nsCertTree::nsCertCompareFunc nsCertTree::GetCompareFuncFromCertType(
208 uint32_t aType) {
209 switch (aType) {
210 case nsIX509Cert::ANY_CERT:
211 case nsIX509Cert::USER_CERT:
212 return CmpUserCert;
213 case nsIX509Cert::EMAIL_CERT:
214 return CmpEmailCert;
215 case nsIX509Cert::CA_CERT:
216 default:
217 return CmpCACert;
221 nsresult nsCertTree::GetCertsByTypeFromCertList(
222 const nsTArray<RefPtr<nsIX509Cert>>& aCertList, uint32_t aWantedType,
223 nsCertCompareFunc aCertCmpFn, void* aCertCmpFnArg) {
224 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("GetCertsByTypeFromCertList"));
226 nsTHashtable<nsCStringHashKey> allHostPortOverrideKeys;
228 if (aWantedType == nsIX509Cert::SERVER_CERT) {
229 return NS_ERROR_INVALID_ARG;
232 int count = 0;
233 for (const auto& cert : aCertList) {
234 bool wantThisCert = (aWantedType == nsIX509Cert::ANY_CERT);
236 if (!wantThisCert) {
237 uint32_t thisCertType;
238 nsresult rv = cert->GetCertType(&thisCertType);
239 if (NS_FAILED(rv)) {
240 return rv;
242 if (thisCertType == aWantedType) {
243 wantThisCert = true;
247 if (wantThisCert) {
248 int InsertPosition = 0;
249 for (; InsertPosition < count; ++InsertPosition) {
250 nsCOMPtr<nsIX509Cert> otherCert = nullptr;
251 RefPtr<nsCertTreeDispInfo> elem(
252 mDispInfo.SafeElementAt(InsertPosition, nullptr));
253 if (elem) {
254 otherCert = elem->mCert;
256 if ((*aCertCmpFn)(aCertCmpFnArg, cert, otherCert) < 0) {
257 break;
260 nsCertTreeDispInfo* certdi = new nsCertTreeDispInfo(cert);
261 mDispInfo.InsertElementAt(InsertPosition, certdi);
262 ++count;
263 ++InsertPosition;
267 return NS_OK;
270 // LoadCerts
272 // Load all of the certificates in the DB for this type. Sort them
273 // by token, organization, then common name.
274 NS_IMETHODIMP
275 nsCertTree::LoadCertsFromCache(const nsTArray<RefPtr<nsIX509Cert>>& aCache,
276 uint32_t aType) {
277 if (mTreeArray) {
278 FreeCertArray();
279 delete[] mTreeArray;
280 mTreeArray = nullptr;
281 mNumRows = 0;
283 ClearCompareHash();
285 nsresult rv = GetCertsByTypeFromCertList(
286 aCache, aType, GetCompareFuncFromCertType(aType), &mCompareCache);
287 if (NS_FAILED(rv)) {
288 return rv;
290 return UpdateUIContents();
293 nsresult nsCertTree::UpdateUIContents() {
294 uint32_t count = mDispInfo.Length();
295 mNumOrgs = CountOrganizations();
296 mTreeArray = new treeArrayEl[mNumOrgs];
298 mCellText = nsArrayBase::Create();
300 if (count) {
301 uint32_t j = 0;
302 nsCOMPtr<nsIX509Cert> orgCert = mDispInfo.ElementAt(j)->mCert;
303 for (int32_t i = 0; i < mNumOrgs; i++) {
304 nsString& orgNameRef = mTreeArray[i].orgName;
305 if (!orgCert) {
306 GetPIPNSSBundleString("CertOrgUnknown", orgNameRef);
307 } else {
308 orgCert->GetIssuerOrganization(orgNameRef);
309 if (orgNameRef.IsEmpty()) orgCert->GetCommonName(orgNameRef);
311 mTreeArray[i].open = true;
312 mTreeArray[i].certIndex = j;
313 mTreeArray[i].numChildren = 1;
314 if (++j >= count) break;
315 nsCOMPtr<nsIX509Cert> nextCert =
316 mDispInfo.SafeElementAt(j, nullptr)->mCert;
317 while (0 == CmpBy(&mCompareCache, orgCert, nextCert, sort_IssuerOrg,
318 sort_None, sort_None)) {
319 mTreeArray[i].numChildren++;
320 if (++j >= count) break;
321 nextCert = mDispInfo.SafeElementAt(j, nullptr)->mCert;
323 orgCert = nextCert;
326 if (mTree) {
327 mTree->BeginUpdateBatch();
328 mTree->RowCountChanged(0, -mNumRows);
330 mNumRows = count + mNumOrgs;
331 if (mTree) mTree->EndUpdateBatch();
332 return NS_OK;
335 NS_IMETHODIMP
336 nsCertTree::DeleteEntryObject(uint32_t index) {
337 if (!mTreeArray) {
338 return NS_ERROR_FAILURE;
341 nsCOMPtr<nsIX509CertDB> certdb =
342 do_GetService("@mozilla.org/security/x509certdb;1");
343 if (!certdb) {
344 return NS_ERROR_FAILURE;
347 int i;
348 uint32_t idx = 0, cIndex = 0, nc;
349 // Loop over the threads
350 for (i = 0; i < mNumOrgs; i++) {
351 if (index == idx) return NS_OK; // index is for thread
352 idx++; // get past the thread
353 nc = (mTreeArray[i].open) ? mTreeArray[i].numChildren : 0;
354 if (index < idx + nc) { // cert is within range of this thread
355 int32_t certIndex = cIndex + index - idx;
357 RefPtr<nsCertTreeDispInfo> certdi(
358 mDispInfo.SafeElementAt(certIndex, nullptr));
359 if (certdi) {
360 nsCOMPtr<nsIX509Cert> cert = certdi->mCert;
361 RemoveCacheEntry(cert);
362 certdb->DeleteCertificate(cert);
365 mDispInfo.RemoveElementAt(certIndex);
367 delete[] mTreeArray;
368 mTreeArray = nullptr;
369 return UpdateUIContents();
371 if (mTreeArray[i].open) idx += mTreeArray[i].numChildren;
372 cIndex += mTreeArray[i].numChildren;
373 if (idx > index) break;
375 return NS_ERROR_FAILURE;
378 //////////////////////////////////////////////////////////////////////////////
380 // Begin nsITreeView methods
382 /////////////////////////////////////////////////////////////////////////////
384 NS_IMETHODIMP
385 nsCertTree::GetCert(uint32_t aIndex, nsIX509Cert** _cert) {
386 NS_ENSURE_ARG(_cert);
387 *_cert = GetCertAtIndex(aIndex).take();
388 return NS_OK;
391 NS_IMETHODIMP
392 nsCertTree::GetTreeItem(uint32_t aIndex, nsICertTreeItem** _treeitem) {
393 NS_ENSURE_ARG(_treeitem);
395 RefPtr<nsCertTreeDispInfo> certdi(GetDispInfoAtIndex(aIndex));
396 if (!certdi) return NS_ERROR_FAILURE;
398 *_treeitem = certdi;
399 NS_IF_ADDREF(*_treeitem);
400 return NS_OK;
403 NS_IMETHODIMP
404 nsCertTree::GetRowCount(int32_t* aRowCount) {
405 if (!mTreeArray) return NS_ERROR_NOT_INITIALIZED;
406 uint32_t count = 0;
407 for (int32_t i = 0; i < mNumOrgs; i++) {
408 if (mTreeArray[i].open) {
409 count += mTreeArray[i].numChildren;
411 count++;
413 *aRowCount = count;
414 return NS_OK;
417 NS_IMETHODIMP
418 nsCertTree::GetSelection(nsITreeSelection** aSelection) {
419 *aSelection = mSelection;
420 NS_IF_ADDREF(*aSelection);
421 return NS_OK;
424 NS_IMETHODIMP
425 nsCertTree::SetSelection(nsITreeSelection* aSelection) {
426 mSelection = aSelection;
427 return NS_OK;
430 NS_IMETHODIMP
431 nsCertTree::GetRowProperties(int32_t index, nsAString& aProps) { return NS_OK; }
433 NS_IMETHODIMP
434 nsCertTree::GetCellProperties(int32_t row, nsTreeColumn* col,
435 nsAString& aProps) {
436 return NS_OK;
439 NS_IMETHODIMP
440 nsCertTree::GetColumnProperties(nsTreeColumn* col, nsAString& aProps) {
441 return NS_OK;
443 NS_IMETHODIMP
444 nsCertTree::IsContainer(int32_t index, bool* _retval) {
445 if (!mTreeArray) return NS_ERROR_NOT_INITIALIZED;
446 treeArrayEl* el = GetThreadDescAtIndex(index);
447 if (el) {
448 *_retval = true;
449 } else {
450 *_retval = false;
452 return NS_OK;
455 NS_IMETHODIMP
456 nsCertTree::IsContainerOpen(int32_t index, bool* _retval) {
457 if (!mTreeArray) return NS_ERROR_NOT_INITIALIZED;
458 treeArrayEl* el = GetThreadDescAtIndex(index);
459 if (el && el->open) {
460 *_retval = true;
461 } else {
462 *_retval = false;
464 return NS_OK;
467 NS_IMETHODIMP
468 nsCertTree::IsContainerEmpty(int32_t index, bool* _retval) {
469 *_retval = !mTreeArray;
470 return NS_OK;
473 NS_IMETHODIMP
474 nsCertTree::IsSeparator(int32_t index, bool* _retval) {
475 *_retval = false;
476 return NS_OK;
479 NS_IMETHODIMP
480 nsCertTree::GetParentIndex(int32_t rowIndex, int32_t* _retval) {
481 if (!mTreeArray) return NS_ERROR_NOT_INITIALIZED;
482 int i, idx = 0;
483 for (i = 0; i < mNumOrgs && idx < rowIndex; i++, idx++) {
484 if (mTreeArray[i].open) {
485 if (rowIndex <= idx + mTreeArray[i].numChildren) {
486 *_retval = idx;
487 return NS_OK;
489 idx += mTreeArray[i].numChildren;
492 *_retval = -1;
493 return NS_OK;
496 NS_IMETHODIMP
497 nsCertTree::HasNextSibling(int32_t rowIndex, int32_t afterIndex,
498 bool* _retval) {
499 if (!mTreeArray) return NS_ERROR_NOT_INITIALIZED;
501 int i, idx = 0;
502 for (i = 0; i < mNumOrgs && idx <= rowIndex; i++, idx++) {
503 if (mTreeArray[i].open) {
504 idx += mTreeArray[i].numChildren;
505 if (afterIndex <= idx) {
506 *_retval = afterIndex < idx;
507 return NS_OK;
511 *_retval = false;
512 return NS_OK;
515 NS_IMETHODIMP
516 nsCertTree::GetLevel(int32_t index, int32_t* _retval) {
517 if (!mTreeArray) return NS_ERROR_NOT_INITIALIZED;
518 treeArrayEl* el = GetThreadDescAtIndex(index);
519 if (el) {
520 *_retval = 0;
521 } else {
522 *_retval = 1;
524 return NS_OK;
527 NS_IMETHODIMP
528 nsCertTree::GetImageSrc(int32_t row, nsTreeColumn* col, nsAString& _retval) {
529 _retval.Truncate();
530 return NS_OK;
533 NS_IMETHODIMP
534 nsCertTree::GetCellValue(int32_t row, nsTreeColumn* col, nsAString& _retval) {
535 _retval.Truncate();
536 return NS_OK;
539 static void PRTimeToLocalDateString(PRTime time, nsAString& result) {
540 PRExplodedTime explodedTime;
541 PR_ExplodeTime(time, PR_LocalTimeParameters, &explodedTime);
542 intl::DateTimeFormat::StyleBag style;
543 style.date = Some(intl::DateTimeFormat::Style::Long);
544 style.time = Nothing();
545 Unused << intl::AppDateTimeFormat::Format(style, &explodedTime, result);
548 NS_IMETHODIMP
549 nsCertTree::GetCellText(int32_t row, nsTreeColumn* col, nsAString& _retval) {
550 if (!mTreeArray) return NS_ERROR_NOT_INITIALIZED;
552 nsresult rv = NS_OK;
553 _retval.Truncate();
555 const nsAString& colID = col->GetId();
557 treeArrayEl* el = GetThreadDescAtIndex(row);
558 if (el) {
559 if (u"certcol"_ns.Equals(colID))
560 _retval.Assign(el->orgName);
561 else
562 _retval.Truncate();
563 return NS_OK;
566 int32_t absoluteCertOffset;
567 RefPtr<nsCertTreeDispInfo> certdi(
568 GetDispInfoAtIndex(row, &absoluteCertOffset));
569 if (!certdi) return NS_ERROR_FAILURE;
571 nsCOMPtr<nsIX509Cert> cert = certdi->mCert;
573 int32_t colIndex = col->Index();
574 uint32_t arrayIndex = absoluteCertOffset + colIndex * (mNumRows - mNumOrgs);
575 uint32_t arrayLength = 0;
576 if (mCellText) {
577 mCellText->GetLength(&arrayLength);
579 if (arrayIndex < arrayLength) {
580 nsCOMPtr<nsISupportsString> myString(
581 do_QueryElementAt(mCellText, arrayIndex));
582 if (myString) {
583 myString->GetData(_retval);
584 return NS_OK;
588 if (u"certcol"_ns.Equals(colID)) {
589 if (!cert) {
590 rv = GetPIPNSSBundleString("CertNotStored", _retval);
591 } else {
592 rv = cert->GetDisplayName(_retval);
594 } else if (u"tokencol"_ns.Equals(colID) && cert) {
595 rv = cert->GetTokenName(_retval);
596 } else if (u"emailcol"_ns.Equals(colID) && cert) {
597 rv = cert->GetEmailAddress(_retval);
598 } else if (u"issuedcol"_ns.Equals(colID) && cert) {
599 nsCOMPtr<nsIX509CertValidity> validity;
601 rv = cert->GetValidity(getter_AddRefs(validity));
602 if (NS_SUCCEEDED(rv)) {
603 PRTime notBefore;
604 rv = validity->GetNotBefore(&notBefore);
605 if (NS_SUCCEEDED(rv)) {
606 PRTimeToLocalDateString(notBefore, _retval);
609 } else if (u"expiredcol"_ns.Equals(colID) && cert) {
610 nsCOMPtr<nsIX509CertValidity> validity;
612 rv = cert->GetValidity(getter_AddRefs(validity));
613 if (NS_SUCCEEDED(rv)) {
614 PRTime notAfter;
615 rv = validity->GetNotAfter(&notAfter);
616 if (NS_SUCCEEDED(rv)) {
617 PRTimeToLocalDateString(notAfter, _retval);
620 } else if (u"serialnumcol"_ns.Equals(colID) && cert) {
621 rv = cert->GetSerialNumber(_retval);
622 } else {
623 return NS_ERROR_FAILURE;
625 if (mCellText) {
626 nsCOMPtr<nsISupportsString> text(
627 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv));
628 NS_ENSURE_SUCCESS(rv, rv);
629 text->SetData(_retval);
630 mCellText->ReplaceElementAt(text, arrayIndex);
632 return rv;
635 NS_IMETHODIMP
636 nsCertTree::SetTree(mozilla::dom::XULTreeElement* tree) {
637 mTree = tree;
638 return NS_OK;
641 NS_IMETHODIMP
642 nsCertTree::ToggleOpenState(int32_t index) {
643 if (!mTreeArray) return NS_ERROR_NOT_INITIALIZED;
644 treeArrayEl* el = GetThreadDescAtIndex(index);
645 if (el) {
646 el->open = !el->open;
647 int32_t newChildren = (el->open) ? el->numChildren : -el->numChildren;
648 if (mTree) {
649 mTree->RowCountChanged(index + 1, newChildren);
650 mTree->InvalidateRow(index);
653 return NS_OK;
656 NS_IMETHODIMP
657 nsCertTree::CycleHeader(nsTreeColumn* col) { return NS_OK; }
659 NS_IMETHODIMP
660 nsCertTree::SelectionChangedXPCOM() { return NS_ERROR_NOT_IMPLEMENTED; }
662 NS_IMETHODIMP
663 nsCertTree::CycleCell(int32_t row, nsTreeColumn* col) { return NS_OK; }
665 NS_IMETHODIMP
666 nsCertTree::IsEditable(int32_t row, nsTreeColumn* col, bool* _retval) {
667 *_retval = false;
668 return NS_OK;
671 NS_IMETHODIMP
672 nsCertTree::SetCellValue(int32_t row, nsTreeColumn* col,
673 const nsAString& value) {
674 return NS_OK;
677 NS_IMETHODIMP
678 nsCertTree::SetCellText(int32_t row, nsTreeColumn* col,
679 const nsAString& value) {
680 return NS_OK;
684 // CanDrop
686 NS_IMETHODIMP nsCertTree::CanDrop(int32_t index, int32_t orientation,
687 mozilla::dom::DataTransfer* aDataTransfer,
688 bool* _retval) {
689 NS_ENSURE_ARG_POINTER(_retval);
690 *_retval = false;
692 return NS_OK;
696 // Drop
698 NS_IMETHODIMP nsCertTree::Drop(int32_t row, int32_t orient,
699 mozilla::dom::DataTransfer* aDataTransfer) {
700 return NS_OK;
704 // IsSorted
706 // ...
708 NS_IMETHODIMP nsCertTree::IsSorted(bool* _retval) {
709 *_retval = false;
710 return NS_OK;
713 #define RETURN_NOTHING
715 void nsCertTree::CmpInitCriterion(nsIX509Cert* cert,
716 CompareCacheHashEntry* entry,
717 sortCriterion crit, int32_t level) {
718 NS_ENSURE_TRUE(cert && entry, RETURN_NOTHING);
720 entry->mCritInit[level] = true;
721 nsString& str = entry->mCrit[level];
723 switch (crit) {
724 case sort_IssuerOrg:
725 cert->GetIssuerOrganization(str);
726 if (str.IsEmpty()) cert->GetCommonName(str);
727 break;
728 case sort_Org:
729 cert->GetOrganization(str);
730 break;
731 case sort_Token:
732 cert->GetTokenName(str);
733 break;
734 case sort_CommonName:
735 cert->GetCommonName(str);
736 break;
737 case sort_IssuedDateDescending: {
738 nsresult rv;
739 nsCOMPtr<nsIX509CertValidity> validity;
740 PRTime notBefore;
742 rv = cert->GetValidity(getter_AddRefs(validity));
743 if (NS_SUCCEEDED(rv)) {
744 rv = validity->GetNotBefore(&notBefore);
747 if (NS_SUCCEEDED(rv)) {
748 PRExplodedTime explodedTime;
749 PR_ExplodeTime(notBefore, PR_GMTParameters, &explodedTime);
750 char datebuf[20]; // 4 + 2 + 2 + 2 + 2 + 2 + 1 = 15
751 if (0 != PR_FormatTime(datebuf, sizeof(datebuf), "%Y%m%d%H%M%S",
752 &explodedTime)) {
753 str = NS_ConvertASCIItoUTF16(nsDependentCString(datebuf));
756 } break;
757 case sort_Email:
758 cert->GetEmailAddress(str);
759 break;
760 case sort_None:
761 default:
762 break;
766 int32_t nsCertTree::CmpByCrit(nsIX509Cert* a, CompareCacheHashEntry* ace,
767 nsIX509Cert* b, CompareCacheHashEntry* bce,
768 sortCriterion crit, int32_t level) {
769 NS_ENSURE_TRUE(a && ace && b && bce, 0);
771 if (!ace->mCritInit[level]) {
772 CmpInitCriterion(a, ace, crit, level);
775 if (!bce->mCritInit[level]) {
776 CmpInitCriterion(b, bce, crit, level);
779 nsString& str_a = ace->mCrit[level];
780 nsString& str_b = bce->mCrit[level];
782 int32_t result;
783 if (!str_a.IsVoid() && !str_b.IsVoid())
784 result = Compare(str_a, str_b, nsCaseInsensitiveStringComparator);
785 else
786 result = str_a.IsVoid() ? (str_b.IsVoid() ? 0 : -1) : 1;
788 if (sort_IssuedDateDescending == crit) result *= -1; // reverse compare order
790 return result;
793 int32_t nsCertTree::CmpBy(void* cache, nsIX509Cert* a, nsIX509Cert* b,
794 sortCriterion c0, sortCriterion c1,
795 sortCriterion c2) {
796 // This will be called when comparing items for display sorting.
797 // Some items might have no cert associated, so either a or b is null.
798 // We want all those orphans show at the top of the list,
799 // so we treat a null cert as "smaller" by returning -1.
800 // We don't try to sort within the group of no-cert entries,
801 // so we treat them as equal wrt sort order.
803 if (!a && !b) return 0;
805 if (!a) return -1;
807 if (!b) return 1;
809 NS_ENSURE_TRUE(cache && a && b, 0);
811 CompareCacheHashEntry* ace = getCacheEntry(cache, a);
812 CompareCacheHashEntry* bce = getCacheEntry(cache, b);
814 int32_t cmp;
815 cmp = CmpByCrit(a, ace, b, bce, c0, 0);
816 if (cmp != 0) return cmp;
818 if (c1 != sort_None) {
819 cmp = CmpByCrit(a, ace, b, bce, c1, 1);
820 if (cmp != 0) return cmp;
822 if (c2 != sort_None) {
823 return CmpByCrit(a, ace, b, bce, c2, 2);
827 return cmp;
830 int32_t nsCertTree::CmpCACert(void* cache, nsIX509Cert* a, nsIX509Cert* b) {
831 // XXX we assume issuer org is always criterion 1
832 return CmpBy(cache, a, b, sort_IssuerOrg, sort_Org, sort_Token);
835 int32_t nsCertTree::CmpUserCert(void* cache, nsIX509Cert* a, nsIX509Cert* b) {
836 // XXX we assume issuer org is always criterion 1
837 return CmpBy(cache, a, b, sort_IssuerOrg, sort_Token,
838 sort_IssuedDateDescending);
841 int32_t nsCertTree::CmpEmailCert(void* cache, nsIX509Cert* a, nsIX509Cert* b) {
842 // XXX we assume issuer org is always criterion 1
843 return CmpBy(cache, a, b, sort_IssuerOrg, sort_Email, sort_CommonName);