Bug 458861. Validate TrueType headers before activating downloaded font. r=roc, sr...
[wine-gecko.git] / xpinstall / src / nsXPInstallManager.cpp
blob16207bb2bc6fc09db902ae76de710f5a508553c2
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is Mozilla Communicator client code, released
15 * March 31, 1998.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Daniel Veditz <dveditz@netscape.com>
24 * Dave Townsend <dtownsend@oxymoronical.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "nscore.h"
41 #include "prprf.h"
42 #include "plstr.h"
43 #include "nsInt64.h"
45 #include "nsISupports.h"
46 #include "nsIServiceManager.h"
48 #include "nsIURL.h"
49 #include "nsIFileURL.h"
50 #include "nsIJAR.h"
52 #include "nsITransport.h"
53 #include "nsIOutputStream.h"
54 #include "nsNetUtil.h"
55 #include "nsIInputStream.h"
56 #include "nsIFileStreams.h"
57 #include "nsIStreamListener.h"
58 #include "nsICryptoHash.h"
60 #include "nsIExtensionManager.h"
61 #include "nsSoftwareUpdateIIDs.h"
63 #include "nsIStringEnumerator.h"
64 #include "nsXPITriggerInfo.h"
65 #include "nsXPInstallManager.h"
66 #include "nsInstallTrigger.h"
67 #include "nsIWindowWatcher.h"
68 #include "nsIAuthPrompt.h"
69 #include "nsIWindowMediator.h"
70 #include "nsIDOMWindowInternal.h"
71 #include "nsDirectoryService.h"
72 #include "nsDirectoryServiceDefs.h"
73 #include "nsAppDirectoryServiceDefs.h"
75 #include "nsReadableUtils.h"
76 #include "nsIPromptService.h"
77 #include "nsIScriptGlobalObject.h"
78 #include "nsXPCOM.h"
79 #include "nsISupportsPrimitives.h"
80 #include "nsIObserverService.h"
82 #include "nsISSLStatusProvider.h"
83 #include "nsISSLStatus.h"
84 #include "nsIX509Cert.h"
86 #include "nsIPrefService.h"
87 #include "nsIPrefBranch.h"
89 #include "CertReader.h"
91 #include "nsEmbedCID.h"
93 #define PREF_XPINSTALL_ENABLED "xpinstall.enabled"
94 #define PREF_XPINSTALL_CONFIRM_DLG "xpinstall.dialog.confirm"
95 #define PREF_XPINSTALL_STATUS_DLG_SKIN "xpinstall.dialog.progress.skin"
96 #define PREF_XPINSTALL_STATUS_DLG_CHROME "xpinstall.dialog.progress.chrome"
97 #define PREF_XPINSTALL_STATUS_DLG_TYPE_SKIN "xpinstall.dialog.progress.type.skin"
98 #define PREF_XPINSTALL_STATUS_DLG_TYPE_CHROME "xpinstall.dialog.progress.type.chrome"
100 static NS_DEFINE_IID(kZipReaderCID, NS_ZIPREADER_CID);
103 nsXPInstallManager::nsXPInstallManager()
104 : mTriggers(0), mItem(0), mNextItem(0), mChromeType(NOT_CHROME),
105 mContentLength(0), mDialogOpen(PR_FALSE), mCancelled(PR_FALSE),
106 mNeedsShutdown(PR_FALSE), mFromChrome(PR_FALSE)
108 // we need to own ourself because we have a longer
109 // lifetime than the scriptlet that created us.
110 NS_ADDREF_THIS();
114 nsXPInstallManager::~nsXPInstallManager()
116 NS_ASSERTION(!mTriggers, "Shutdown not called, triggers still alive");
120 NS_INTERFACE_MAP_BEGIN(nsXPInstallManager)
121 NS_INTERFACE_MAP_ENTRY(nsIXPIDialogService)
122 NS_INTERFACE_MAP_ENTRY(nsIXPInstallManager)
123 NS_INTERFACE_MAP_ENTRY(nsIObserver)
124 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
125 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
126 NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink)
127 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
128 NS_INTERFACE_MAP_ENTRY(nsPICertNotification)
129 NS_INTERFACE_MAP_ENTRY(nsIBadCertListener2)
130 NS_INTERFACE_MAP_ENTRY(nsISSLErrorListener)
131 NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
132 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
133 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISupportsWeakReference)
134 NS_INTERFACE_MAP_END
136 NS_IMPL_ADDREF(nsXPInstallManager)
137 NS_IMPL_RELEASE(nsXPInstallManager)
139 NS_IMETHODIMP
140 nsXPInstallManager::InitManagerFromChrome(const PRUnichar **aURLs,
141 PRUint32 aURLCount,
142 nsIXPIProgressDialog* aListener)
144 return InitManagerWithHashes(aURLs, nsnull, aURLCount, aListener);
147 NS_IMETHODIMP
148 nsXPInstallManager::InitManagerWithHashes(const PRUnichar **aURLs,
149 const char **aHashes,
150 PRUint32 aURLCount,
151 nsIXPIProgressDialog* aListener)
153 // If Software Installation is not enabled, we don't want to proceed with
154 // update.
155 PRBool xpinstallEnabled = PR_TRUE;
156 nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID));
157 if (pref)
158 pref->GetBoolPref(PREF_XPINSTALL_ENABLED, &xpinstallEnabled);
160 if (!xpinstallEnabled)
161 return NS_OK;
163 mTriggers = new nsXPITriggerInfo();
164 if (!mTriggers)
165 return NS_ERROR_OUT_OF_MEMORY;
167 mNeedsShutdown = PR_TRUE;
169 for (PRUint32 i = 0; i < aURLCount; ++i)
171 nsXPITriggerItem* item = new nsXPITriggerItem(0, aURLs[i], nsnull,
172 aHashes ? aHashes[i] : nsnull);
173 if (!item)
175 delete mTriggers; // nsXPITriggerInfo frees any alloc'ed nsXPITriggerItems
176 mTriggers = nsnull;
177 Shutdown();
178 return NS_ERROR_OUT_OF_MEMORY;
180 mTriggers->Add(item);
183 mFromChrome = PR_TRUE;
185 nsresult rv = Observe(aListener, XPI_PROGRESS_TOPIC, NS_LITERAL_STRING("open").get());
186 if (NS_FAILED(rv))
187 Shutdown();
188 return rv;
191 NS_IMETHODIMP
192 nsXPInstallManager::InitManagerWithInstallInfo(nsIXPIInstallInfo* aInstallInfo)
194 nsXPITriggerInfo* triggers;
195 nsresult rv = aInstallInfo->GetTriggerInfo(&triggers);
196 NS_ENSURE_SUCCESS(rv, rv);
198 nsCOMPtr<nsIDOMWindowInternal> win;
199 rv = aInstallInfo->GetOriginatingWindow(getter_AddRefs(win));
200 if (NS_SUCCEEDED(rv))
202 PRUint32 type;
203 rv = aInstallInfo->GetChromeType(&type);
204 if (NS_SUCCEEDED(rv))
206 // Passing ownership onto InitManager which will free when necessary
207 aInstallInfo->SetTriggerInfo(nsnull);
208 return InitManager(win, triggers, type);
212 NS_RELEASE_THIS();
213 return rv;
216 NS_IMETHODIMP
217 nsXPInstallManager::InitManager(nsIDOMWindowInternal* aParentWindow, nsXPITriggerInfo* aTriggers, PRUint32 aChromeType)
219 if ( !aTriggers || aTriggers->Size() == 0 )
221 NS_WARNING("XPInstallManager called with no trigger info!");
222 delete aTriggers;
223 NS_RELEASE_THIS();
224 return NS_ERROR_INVALID_POINTER;
227 nsresult rv = NS_OK;
229 mNeedsShutdown = PR_TRUE;
230 mTriggers = aTriggers;
231 mChromeType = aChromeType;
233 mParentWindow = aParentWindow;
235 // Start downloading initial chunks looking for signatures,
236 mOutstandingCertLoads = mTriggers->Size();
238 nsXPITriggerItem *item = mTriggers->Get(--mOutstandingCertLoads);
240 nsCOMPtr<nsIURI> uri;
241 NS_NewURI(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(item->mURL));
242 nsCOMPtr<nsIStreamListener> listener = new CertReader(uri, nsnull, this);
243 if (listener)
244 rv = NS_OpenURI(listener, nsnull, uri);
245 else
246 rv = NS_ERROR_OUT_OF_MEMORY;
248 if (NS_FAILED(rv)) {
249 Shutdown();
251 return rv;
255 nsresult
256 nsXPInstallManager::InitManagerInternal()
258 nsresult rv;
259 PRBool OKtoInstall = PR_FALSE; // initialize to secure state
261 //-----------------------------------------------------
262 // *** Do not return early after this point ***
264 // We have to clean up the triggers in case of error
265 //-----------------------------------------------------
267 // --- use embedding dialogs if any registered
268 nsCOMPtr<nsIXPIDialogService> dlgSvc(do_CreateInstance(NS_XPIDIALOGSERVICE_CONTRACTID));
269 if ( !dlgSvc )
270 dlgSvc = this; // provide our own dialogs
272 // --- prepare dialog params
273 PRUint32 numTriggers = mTriggers->Size();
274 PRUint32 numStrings = 4 * numTriggers;
275 const PRUnichar** packageList =
276 (const PRUnichar**)malloc( sizeof(PRUnichar*) * numStrings );
278 if ( packageList )
280 // populate the list. The list doesn't own the strings
281 for ( PRUint32 i=0, j=0; i < numTriggers; i++ )
283 nsXPITriggerItem *item = mTriggers->Get(i);
284 packageList[j++] = item->mName.get();
285 packageList[j++] = item->GetSafeURLString();
286 packageList[j++] = item->mIconURL.get();
287 packageList[j++] = item->mCertName.get();
290 //-----------------------------------------------------
291 // Get permission to install
292 //-----------------------------------------------------
294 #ifdef ENABLE_SKIN_SIMPLE_INSTALLATION_UI
295 if ( mChromeType == CHROME_SKIN )
297 // We may want to enable the simple installation UI once
298 // bug 343037 is fixed
300 // skins get a simpler/friendlier dialog
301 // XXX currently not embeddable
302 OKtoInstall = ConfirmChromeInstall( mParentWindow, packageList );
304 else
306 #endif
307 rv = dlgSvc->ConfirmInstall( mParentWindow,
308 packageList,
309 numStrings,
310 &OKtoInstall );
311 if (NS_FAILED(rv))
312 OKtoInstall = PR_FALSE;
313 #ifdef ENABLE_SKIN_SIMPLE_INSTALLATION_UI
315 #endif
317 if (OKtoInstall)
319 //-----------------------------------------------------
320 // Open the progress dialog
321 //-----------------------------------------------------
323 rv = dlgSvc->OpenProgressDialog( packageList, numStrings, this );
326 else
327 rv = NS_ERROR_OUT_OF_MEMORY;
329 //-----------------------------------------------------
330 // cleanup and signal callbacks if there were errors
331 //-----------------------------------------------------
333 if (packageList)
334 free(packageList);
336 PRInt32 cbstatus = 0; // callback status
337 if (NS_FAILED(rv))
338 cbstatus = nsInstall::UNEXPECTED_ERROR;
339 else if (!OKtoInstall)
340 cbstatus = nsInstall::USER_CANCELLED;
342 if ( cbstatus != 0 )
344 // --- must shutdown if not continuing
345 Shutdown( cbstatus );
348 return rv;
352 NS_IMETHODIMP
353 nsXPInstallManager::ConfirmInstall(nsIDOMWindow *aParent, const PRUnichar **aPackageList, PRUint32 aCount, PRBool *aRetval)
355 *aRetval = PR_FALSE;
357 nsCOMPtr<nsIDOMWindowInternal> parentWindow( do_QueryInterface(aParent) );
358 nsCOMPtr<nsIDialogParamBlock> params;
359 nsresult rv = LoadParams( aCount, aPackageList, getter_AddRefs(params) );
361 if ( NS_SUCCEEDED(rv) && parentWindow && params)
363 nsCOMPtr<nsIDOMWindow> newWindow;
365 nsCOMPtr<nsISupportsInterfacePointer> ifptr =
366 do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
367 NS_ENSURE_SUCCESS(rv, rv);
369 ifptr->SetData(params);
370 ifptr->SetDataIID(&NS_GET_IID(nsIDialogParamBlock));
372 char* confirmDialogURL;
373 nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
374 if (!pref)
375 return rv;
377 rv = pref->GetCharPref(PREF_XPINSTALL_CONFIRM_DLG, &confirmDialogURL);
378 NS_ASSERTION(NS_SUCCEEDED(rv), "Can't invoke XPInstall FE without a FE URL! Set xpinstall.dialog.confirm");
379 if (NS_FAILED(rv))
380 return rv;
382 rv = parentWindow->OpenDialog(NS_ConvertASCIItoUTF16(confirmDialogURL),
383 NS_LITERAL_STRING("_blank"),
384 NS_LITERAL_STRING("chrome,centerscreen,modal,titlebar"),
385 ifptr,
386 getter_AddRefs(newWindow));
388 if (NS_SUCCEEDED(rv))
390 //Now get which button was pressed from the ParamBlock
391 PRInt32 buttonPressed = 0;
392 params->GetInt( 0, &buttonPressed );
393 *aRetval = buttonPressed ? PR_FALSE : PR_TRUE;
397 return rv;
400 #ifdef ENABLE_SKIN_SIMPLE_INSTALLATION_UI
401 PRBool nsXPInstallManager::ConfirmChromeInstall(nsIDOMWindowInternal* aParentWindow, const PRUnichar **aPackage)
403 // get the dialog strings
404 nsXPIDLString applyNowText;
405 nsXPIDLString confirmText;
406 nsCOMPtr<nsIStringBundleService> bundleSvc =
407 do_GetService(NS_STRINGBUNDLE_CONTRACTID);
408 if (!bundleSvc)
409 return PR_FALSE;
411 nsCOMPtr<nsIStringBundle> xpiBundle;
412 bundleSvc->CreateBundle( XPINSTALL_BUNDLE_URL,
413 getter_AddRefs(xpiBundle) );
414 if (!xpiBundle)
415 return PR_FALSE;
417 const PRUnichar *formatStrings[2] = { aPackage[0], aPackage[1] };
418 if ( mChromeType == CHROME_LOCALE )
420 xpiBundle->GetStringFromName(
421 NS_LITERAL_STRING("ApplyNowLocale").get(),
422 getter_Copies(applyNowText));
423 xpiBundle->FormatStringFromName(
424 NS_LITERAL_STRING("ConfirmLocale").get(),
425 formatStrings,
427 getter_Copies(confirmText));
429 else
431 xpiBundle->GetStringFromName(
432 NS_LITERAL_STRING("ApplyNowSkin").get(),
433 getter_Copies(applyNowText));
434 xpiBundle->FormatStringFromName(
435 NS_LITERAL_STRING("ConfirmSkin").get(),
436 formatStrings,
438 getter_Copies(confirmText));
441 if (confirmText.IsEmpty())
442 return PR_FALSE;
444 // confirmation dialog
445 PRBool bInstall = PR_FALSE;
446 nsCOMPtr<nsIPromptService> dlgService(do_GetService(NS_PROMPTSERVICE_CONTRACTID));
447 if (dlgService)
449 dlgService->Confirm(
450 aParentWindow,
451 nsnull,
452 confirmText,
453 &bInstall );
456 return bInstall;
458 #endif
460 NS_IMETHODIMP
461 nsXPInstallManager::OpenProgressDialog(const PRUnichar **aPackageList, PRUint32 aCount, nsIObserver *aObserver)
463 // --- convert parameters into nsISupportArray members
464 nsCOMPtr<nsIDialogParamBlock> list;
465 nsresult rv = LoadParams( aCount, aPackageList, getter_AddRefs(list) );
466 if (NS_FAILED(rv))
467 return rv;
469 nsCOMPtr<nsISupportsInterfacePointer> listwrap(do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID));
470 if (listwrap) {
471 listwrap->SetData(list);
472 listwrap->SetDataIID(&NS_GET_IID(nsIDialogParamBlock));
475 nsCOMPtr<nsISupportsInterfacePointer> callbackwrap(do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID));
476 if (callbackwrap) {
477 callbackwrap->SetData(aObserver);
478 callbackwrap->SetDataIID(&NS_GET_IID(nsIObserver));
481 nsCOMPtr<nsISupportsArray> params(do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID));
483 if ( !params || !listwrap || !callbackwrap )
484 return NS_ERROR_FAILURE;
486 params->AppendElement(listwrap);
487 params->AppendElement(callbackwrap);
489 // --- open the window
490 nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
491 if (!wwatch)
492 return rv;
494 char *statusDialogURL, *statusDialogType;
495 nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
496 if (!pref)
497 return rv;
498 const char* statusDlg = mChromeType == CHROME_SKIN ? PREF_XPINSTALL_STATUS_DLG_SKIN
499 : PREF_XPINSTALL_STATUS_DLG_CHROME;
500 rv = pref->GetCharPref(statusDlg, &statusDialogURL);
501 NS_ASSERTION(NS_SUCCEEDED(rv), "Can't invoke XPInstall FE without a FE URL! Set xpinstall.dialog.status");
502 if (NS_FAILED(rv))
503 return rv;
505 const char* statusType = mChromeType == CHROME_SKIN ? PREF_XPINSTALL_STATUS_DLG_TYPE_SKIN
506 : PREF_XPINSTALL_STATUS_DLG_TYPE_CHROME;
507 rv = pref->GetCharPref(statusType, &statusDialogType);
508 nsAutoString type;
509 type.AssignWithConversion(statusDialogType);
510 if (NS_SUCCEEDED(rv) && !type.IsEmpty()) {
511 nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
513 nsCOMPtr<nsIDOMWindowInternal> recentWindow;
514 wm->GetMostRecentWindow(type.get(), getter_AddRefs(recentWindow));
515 if (recentWindow) {
516 nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
517 os->NotifyObservers(params, "xpinstall-download-started", nsnull);
519 recentWindow->Focus();
520 return NS_OK;
524 nsCOMPtr<nsIDOMWindow> newWindow;
525 rv = wwatch->OpenWindow(0,
526 statusDialogURL,
527 "_blank",
528 "chrome,centerscreen,titlebar,dialog=no,resizable",
529 params,
530 getter_AddRefs(newWindow));
532 return rv;
536 NS_IMETHODIMP nsXPInstallManager::Observe( nsISupports *aSubject,
537 const char *aTopic,
538 const PRUnichar *aData )
540 nsresult rv = NS_ERROR_ILLEGAL_VALUE;
542 if ( !aTopic || !aData )
543 return rv;
545 nsDependentCString topic( aTopic );
546 if ( topic.Equals( XPI_PROGRESS_TOPIC ) )
548 //------------------------------------------------------
549 // Communication from the XPInstall Progress Dialog
550 //------------------------------------------------------
552 nsDependentString data( aData );
554 if ( data.Equals( NS_LITERAL_STRING("open") ) )
556 // -- The dialog has been opened
557 if (mDialogOpen)
558 return NS_OK; // We've already been opened, nothing more to do
560 mDialogOpen = PR_TRUE;
561 rv = NS_OK;
563 nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
564 if (os)
566 os->AddObserver(this, NS_IOSERVICE_GOING_OFFLINE_TOPIC, PR_TRUE);
567 os->AddObserver(this, "quit-application", PR_TRUE);
570 mDlg = do_QueryInterface(aSubject);
572 // -- get the ball rolling
573 DownloadNext();
576 else if ( data.Equals( NS_LITERAL_STRING("cancel") ) )
578 // -- The dialog/user wants us to cancel the download
579 mCancelled = PR_TRUE;
580 if ( !mDialogOpen )
582 // if we've never been opened then we can shutdown right here,
583 // otherwise we need to let mCancelled get discovered elsewhere
584 Shutdown();
586 rv = NS_OK;
589 else if ( topic.Equals( NS_IOSERVICE_GOING_OFFLINE_TOPIC ) ||
590 topic.Equals( "quit-application" ) )
592 mCancelled = PR_TRUE;
593 rv = NS_OK;
596 return rv;
600 ///////////////////////////////////////////////////////////////////////////////////////////////
601 // Function name : VerifySigning
602 // Description : Verify that the entire zip file is signed by the certificate displayed to
603 // the user during download
604 // Return type : PRInt32
605 // Argument : nsIZipReader* hZip - the zip reader
606 // Argument : nsIPrincipal* aPrincipal - a principal, if any, displayed to the user
607 // during download. Would have been retrieved from the first file in the zip
608 ///////////////////////////////////////////////////////////////////////////////////////////////
610 static nsresult
611 VerifySigning(nsIZipReader* hZip, nsIPrincipal* aPrincipal)
613 // If we didn't detect a principal from the zip file during download then
614 // we didn't suggest it was signed to the user, so just carry on.
615 if (!aPrincipal)
616 return NS_OK;
618 PRBool hasCert;
619 aPrincipal->GetHasCertificate(&hasCert);
620 if (!hasCert)
621 return NS_ERROR_FAILURE;
623 nsCOMPtr<nsIJAR> jar(do_QueryInterface(hZip));
624 if (!jar)
625 return NS_ERROR_FAILURE;
627 // See if the archive is signed at all first
628 nsCOMPtr<nsIPrincipal> principal;
629 nsresult rv = jar->GetCertificatePrincipal(nsnull, getter_AddRefs(principal));
630 if (NS_FAILED(rv) || !principal)
631 return NS_ERROR_FAILURE;
633 PRUint32 entryCount = 0;
635 // first verify all files in the jar are also in the manifest.
636 nsCOMPtr<nsIUTF8StringEnumerator> entries;
637 rv = hZip->FindEntries(nsnull, getter_AddRefs(entries));
638 if (NS_FAILED(rv))
639 return rv;
641 PRBool more;
642 nsCAutoString name;
643 while (NS_SUCCEEDED(entries->HasMore(&more)) && more)
645 rv = entries->GetNext(name);
646 if (NS_FAILED(rv)) return rv;
648 // Do not verify the directory entries or
649 // entries which are in the meta-inf directory
650 if ((name.Last() == '/') ||
651 (PL_strncasecmp("META-INF/", name.get(), 9) == 0))
652 continue;
654 // Count the entries to be verified
655 entryCount++;
657 // Each entry must be signed
658 rv = jar->GetCertificatePrincipal(name.get(), getter_AddRefs(principal));
659 if (NS_FAILED(rv) || !principal) return NS_ERROR_FAILURE;
661 PRBool equal;
662 rv = principal->Equals(aPrincipal, &equal);
663 if (NS_FAILED(rv) || !equal) return NS_ERROR_FAILURE;
666 // next verify all files in the manifest are in the archive.
667 PRUint32 manifestEntryCount;
668 rv = jar->GetManifestEntriesCount(&manifestEntryCount);
669 if (NS_FAILED(rv))
670 return rv;
672 if (entryCount != manifestEntryCount)
673 return NS_ERROR_FAILURE; // some files were deleted from archive
675 return NS_OK;
679 ///////////////////////////////////////////////////////////////////////////////////////////////
680 // Function name : OpenAndValidateArchive
681 // Description : Opens install archive and validates contents
682 // Return type : PRInt32
683 // Argument : nsIZipReader* hZip - the zip reader
684 // Argument : nsIFile* jarFile - the .xpi file
685 // Argument : nsIPrincipal* aPrincipal - a principal, if any, displayed to the user
686 // regarding the cert used to sign this install
687 ///////////////////////////////////////////////////////////////////////////////////////////////
689 static PRInt32
690 OpenAndValidateArchive(nsIZipReader* hZip, nsIFile* jarFile, nsIPrincipal* aPrincipal)
692 if (!jarFile)
693 return nsInstall::DOWNLOAD_ERROR;
695 nsCOMPtr<nsIFile> jFile;
696 nsresult rv =jarFile->Clone(getter_AddRefs(jFile));
697 if (NS_SUCCEEDED(rv))
698 rv = hZip->Open(jFile);
700 if (NS_FAILED(rv))
701 return nsInstall::CANT_READ_ARCHIVE;
703 // CRC check the integrity of all items in this archive
704 rv = hZip->Test(nsnull);
705 if (NS_FAILED(rv))
707 NS_WARNING("CRC check of archive failed!");
708 return nsInstall::CANT_READ_ARCHIVE;
711 rv = VerifySigning(hZip, aPrincipal);
712 if (NS_FAILED(rv))
714 NS_WARNING("Signing check of archive failed!");
715 return nsInstall::INVALID_SIGNATURE;
718 if (NS_FAILED(hZip->Test("install.rdf")))
720 NS_WARNING("Archive did not contain an install manifest!");
721 return nsInstall::NO_INSTALL_SCRIPT;
724 return nsInstall::SUCCESS;
728 nsresult nsXPInstallManager::InstallItems()
730 nsresult rv;
731 nsCOMPtr<nsIZipReader> hZip = do_CreateInstance(kZipReaderCID, &rv);
732 NS_ENSURE_SUCCESS(rv, rv);
733 nsCOMPtr<nsIExtensionManager> em = do_GetService("@mozilla.org/extensions/manager;1", &rv);
734 NS_ENSURE_SUCCESS(rv, rv);
736 // can't cancel from here on cause we can't undo installs in a multitrigger
737 for (PRUint32 i = 0; i < mTriggers->Size(); ++i)
739 mItem = (nsXPITriggerItem*)mTriggers->Get(i);
740 if ( !mItem || !mItem->mFile )
742 // notification for these errors already handled
743 continue;
746 // If there was hash info in the trigger, but
747 // there wasn't a hash object created, then the
748 // algorithm used isn't known.
750 if (mItem->mHashFound && !mItem->mHasher)
752 // report failure
753 mTriggers->SendStatus( mItem->mURL.get(), nsInstall::INVALID_HASH_TYPE );
754 if (mDlg)
755 mDlg->OnStateChange( i, nsIXPIProgressDialog::INSTALL_DONE,
756 nsInstall::INVALID_HASH_TYPE );
757 continue;
760 // Don't install if we can't verify the hash (if specified)
761 if (mItem->mHasher && !VerifyHash(mItem))
763 // report failure
764 mTriggers->SendStatus( mItem->mURL.get(), nsInstall::INVALID_HASH );
765 if (mDlg)
766 mDlg->OnStateChange( i, nsIXPIProgressDialog::INSTALL_DONE,
767 nsInstall::INVALID_HASH );
768 continue;
771 if (mDlg)
772 mDlg->OnStateChange( i, nsIXPIProgressDialog::INSTALL_START, 0 );
774 PRInt32 finalStatus = OpenAndValidateArchive( hZip,
775 mItem->mFile,
776 mItem->mPrincipal);
777 hZip->Close();
779 if (finalStatus == nsInstall::SUCCESS)
781 rv = em->InstallItemFromFile( mItem->mFile,
782 NS_INSTALL_LOCATION_APPPROFILE);
783 if (NS_FAILED(rv))
784 finalStatus = nsInstall::EXECUTION_ERROR;
787 mTriggers->SendStatus( mItem->mURL.get(), finalStatus );
788 if (mDlg)
789 mDlg->OnStateChange( i, nsIXPIProgressDialog::INSTALL_DONE,
790 finalStatus );
792 return NS_OK;
795 NS_IMETHODIMP nsXPInstallManager::DownloadNext()
797 nsresult rv;
798 mContentLength = 0;
800 if (mCancelled)
802 // Don't download any more if we were cancelled
803 Shutdown();
804 return NS_OK;
807 if ( mNextItem < mTriggers->Size() )
809 //-------------------------------------------------
810 // There are items to download, get the next one
811 //-------------------------------------------------
812 mItem = (nsXPITriggerItem*)mTriggers->Get(mNextItem++);
814 NS_ASSERTION( mItem, "bogus Trigger slipped through" );
815 NS_ASSERTION( !mItem->mURL.IsEmpty(), "bogus trigger");
816 if ( !mItem || mItem->mURL.IsEmpty() )
818 // serious problem with trigger! Can't notify anyone of the
819 // error without the URL, just try to carry on.
820 return DownloadNext();
823 // --- Tell the dialog we're starting a download
824 if (mDlg)
825 mDlg->OnStateChange( mNextItem-1, nsIXPIProgressDialog::DOWNLOAD_START, 0 );
827 if ( mItem->IsFileURL() && mChromeType == NOT_CHROME )
829 //--------------------------------------------------
830 // Already local, we can open it where it is
831 //--------------------------------------------------
832 nsCOMPtr<nsIURI> pURL;
833 rv = NS_NewURI(getter_AddRefs(pURL), mItem->mURL);
835 if (NS_SUCCEEDED(rv))
837 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(pURL,&rv);
838 if (fileURL)
840 nsCOMPtr<nsIFile> localFile;
841 rv = fileURL->GetFile(getter_AddRefs(localFile));
842 if (NS_SUCCEEDED(rv))
844 mItem->mFile = do_QueryInterface(localFile,&rv);
849 if ( NS_FAILED(rv) || !mItem->mFile )
851 // send error status back
852 if (mDlg)
853 mDlg->OnStateChange( mNextItem-1,
854 nsIXPIProgressDialog::INSTALL_DONE,
855 nsInstall::UNEXPECTED_ERROR );
856 mTriggers->SendStatus( mItem->mURL.get(),
857 nsInstall::UNEXPECTED_ERROR );
858 mItem->mFile = 0;
860 else if (mDlg)
862 mDlg->OnStateChange( mNextItem-1,
863 nsIXPIProgressDialog::DOWNLOAD_DONE, 0);
866 // --- on to the next one
867 return DownloadNext();
869 else
871 //--------------------------------------------------
872 // We have one to download
873 //--------------------------------------------------
874 rv = GetDestinationFile(mItem->mURL, getter_AddRefs(mItem->mFile));
875 if (NS_SUCCEEDED(rv))
877 nsCOMPtr<nsIURI> pURL;
878 rv = NS_NewURI(getter_AddRefs(pURL), mItem->mURL);
879 if (NS_SUCCEEDED(rv))
881 nsCOMPtr<nsIChannel> channel;
883 rv = NS_NewChannel(getter_AddRefs(channel), pURL, nsnull, nsnull, this);
884 if (NS_SUCCEEDED(rv))
886 rv = channel->AsyncOpen(this, nsnull);
891 if (NS_FAILED(rv))
893 // announce failure
894 if (mDlg)
895 mDlg->OnStateChange( mNextItem-1,
896 nsIXPIProgressDialog::INSTALL_DONE,
897 nsInstall::DOWNLOAD_ERROR );
898 mTriggers->SendStatus( mItem->mURL.get(),
899 nsInstall::DOWNLOAD_ERROR );
900 mItem->mFile = 0;
902 // We won't get Necko callbacks so start the next one now
903 return DownloadNext();
907 else
909 //------------------------------------------------------
910 // all downloaded, install them
911 //------------------------------------------------------
912 InstallItems();
913 Shutdown();
916 return rv;
920 //-------------------------------------------------------------------
921 // VerifyHash
923 // Returns true if the file hash matches the expected value (or if
924 // the item has no hash value). False if we can't verify the hash
925 // for any reason
927 PRBool nsXPInstallManager::VerifyHash(nsXPITriggerItem* aItem)
929 NS_ASSERTION(aItem, "Null nsXPITriggerItem passed to VerifyHash");
931 nsresult rv;
932 if (!aItem->mHasher)
933 return PR_FALSE;
935 nsCOMPtr<nsIInputStream> stream;
936 rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), aItem->mFile);
937 if (NS_FAILED(rv)) return PR_FALSE;
939 rv = aItem->mHasher->UpdateFromStream(stream, PR_UINT32_MAX);
940 if (NS_FAILED(rv)) return PR_FALSE;
942 nsCAutoString binaryHash;
943 rv = aItem->mHasher->Finish(PR_FALSE, binaryHash);
944 if (NS_FAILED(rv)) return PR_FALSE;
946 char* hash = nsnull;
947 for (PRUint32 i=0; i < binaryHash.Length(); ++i)
949 hash = PR_sprintf_append(hash,"%.2x", (PRUint8)binaryHash[i]);
952 PRBool result = aItem->mHash.EqualsIgnoreCase(hash);
954 PR_smprintf_free(hash);
955 return result;
959 void nsXPInstallManager::Shutdown(PRInt32 status)
961 if (mDlg)
963 // tell the dialog it can go away
964 mDlg->OnStateChange(0, nsIXPIProgressDialog::DIALOG_CLOSE, 0 );
965 mDlg = nsnull;
968 if (mNeedsShutdown)
970 mNeedsShutdown = PR_FALSE;
972 // Send remaining status notifications if we were cancelled early
973 nsXPITriggerItem* item;
974 while ( mNextItem < mTriggers->Size() )
976 item = (nsXPITriggerItem*)mTriggers->Get(mNextItem++);
977 if ( item && !item->mURL.IsEmpty() )
979 mTriggers->SendStatus( item->mURL.get(), status );
983 // Clean up downloaded files (regular install only, not chrome installs)
984 for (PRUint32 i = 0; i < mTriggers->Size(); i++ )
986 item = static_cast<nsXPITriggerItem*>(mTriggers->Get(i));
987 if ( item && item->mFile && !item->IsFileURL() )
988 item->mFile->Remove(PR_FALSE);
991 nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
992 if (os)
994 os->RemoveObserver(this, NS_IOSERVICE_GOING_OFFLINE_TOPIC);
995 os->RemoveObserver(this, "quit-application");
998 if (mTriggers)
1000 delete mTriggers;
1001 mTriggers = nsnull;
1004 NS_RELEASE_THIS();
1008 NS_IMETHODIMP
1009 nsXPInstallManager::LoadParams(PRUint32 aCount, const PRUnichar** aPackageList, nsIDialogParamBlock** aParams)
1011 nsresult rv;
1012 nsCOMPtr<nsIDialogParamBlock> paramBlock = do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID, &rv);
1013 if (NS_SUCCEEDED(rv))
1015 // set OK and Cancel buttons
1016 paramBlock->SetInt( 0, 2 );
1017 // pass in number of strings
1018 paramBlock->SetInt( 1, aCount );
1019 // add strings
1020 paramBlock->SetNumberStrings( aCount );
1021 for (PRUint32 i = 0; i < aCount; i++)
1022 paramBlock->SetString( i, aPackageList[i] );
1025 NS_IF_ADDREF(*aParams = paramBlock);
1026 return rv;
1030 NS_IMETHODIMP
1031 nsXPInstallManager::GetDestinationFile(nsString& url, nsILocalFile* *file)
1033 NS_ENSURE_ARG_POINTER(file);
1034 nsresult rv;
1036 nsCOMPtr<nsIProperties> directoryService =
1037 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
1038 NS_ENSURE_SUCCESS(rv, rv);
1040 nsCOMPtr<nsILocalFile> temp;
1041 rv = directoryService->Get(NS_OS_TEMP_DIR,
1042 NS_GET_IID(nsIFile),
1043 getter_AddRefs(temp));
1044 NS_ENSURE_SUCCESS(rv, rv);
1046 temp->AppendNative(NS_LITERAL_CSTRING("tmp.xpi"));
1047 temp->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
1048 *file = temp;
1049 NS_IF_ADDREF(*file);
1051 return NS_OK;
1054 nsresult
1055 nsXPInstallManager::CheckCert(nsIChannel* aChannel)
1057 nsCOMPtr<nsIURI> uri;
1058 nsresult rv = aChannel->GetOriginalURI(getter_AddRefs(uri));
1059 NS_ENSURE_SUCCESS(rv, rv);
1060 nsCAutoString scheme;
1061 rv = uri->GetScheme(scheme);
1062 NS_ENSURE_SUCCESS(rv, rv);
1063 if (!scheme.Equals(NS_LITERAL_CSTRING("https")))
1064 return NS_OK;
1066 nsCOMPtr<nsISupports> security;
1067 rv = aChannel->GetSecurityInfo(getter_AddRefs(security));
1068 NS_ENSURE_SUCCESS(rv, rv);
1069 nsCOMPtr<nsISSLStatusProvider> statusProvider(do_QueryInterface(security));
1070 NS_ENSURE_TRUE(statusProvider, NS_ERROR_FAILURE);
1072 rv = statusProvider->GetSSLStatus(getter_AddRefs(security));
1073 NS_ENSURE_SUCCESS(rv, rv);
1074 nsCOMPtr<nsISSLStatus> status(do_QueryInterface(security));
1075 NS_ENSURE_TRUE(status, NS_ERROR_FAILURE);
1076 nsCOMPtr<nsIX509Cert> cert;
1077 rv = status->GetServerCert(getter_AddRefs(cert));
1078 NS_ENSURE_SUCCESS(rv, rv);
1080 nsCOMPtr<nsIX509Cert> issuer;
1081 rv = cert->GetIssuer(getter_AddRefs(issuer));
1082 NS_ENSURE_SUCCESS(rv, rv);
1083 PRBool equal;
1084 while (issuer && NS_SUCCEEDED(cert->Equals(issuer, &equal)) && !equal) {
1085 cert = issuer;
1086 rv = cert->GetIssuer(getter_AddRefs(issuer));
1087 NS_ENSURE_SUCCESS(rv, rv);
1090 if (issuer) {
1091 nsAutoString tokenName;
1092 rv = issuer->GetTokenName(tokenName);
1093 NS_ENSURE_SUCCESS(rv ,rv);
1094 if (tokenName.Equals(NS_LITERAL_STRING("Builtin Object Token")))
1095 return NS_OK;
1097 return NS_ERROR_FAILURE;
1100 NS_IMETHODIMP
1101 nsXPInstallManager::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
1103 nsresult rv = NS_ERROR_FAILURE;
1105 // If we are dealing with a HTTP request, then treat HTTP error pages as
1106 // download failures.
1107 nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(request);
1108 if (httpChan) {
1109 // If we were chrome lauched check the certificate on the request
1110 if (mFromChrome && NS_FAILED(CheckCert(httpChan))) {
1111 request->Cancel(NS_BINDING_ABORTED);
1112 return NS_OK;
1114 PRBool succeeded;
1115 if (NS_SUCCEEDED(httpChan->GetRequestSucceeded(&succeeded)) && !succeeded) {
1116 // HTTP response is not a 2xx!
1117 request->Cancel(NS_BINDING_ABORTED);
1118 return NS_OK;
1122 NS_ASSERTION( mItem && mItem->mFile, "XPIMgr::OnStartRequest bad state");
1123 if ( mItem && mItem->mFile )
1125 NS_ASSERTION( !mItem->mOutStream, "Received double OnStartRequest from Necko");
1127 rv = NS_NewLocalFileOutputStream(getter_AddRefs(mItem->mOutStream),
1128 mItem->mFile,
1129 PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
1130 0600);
1132 return rv;
1136 NS_IMETHODIMP
1137 nsXPInstallManager::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
1138 nsresult status)
1140 nsresult rv;
1142 switch( status )
1145 case NS_BINDING_SUCCEEDED:
1146 rv = NS_OK;
1147 break;
1149 case NS_BINDING_FAILED:
1150 case NS_BINDING_ABORTED:
1151 rv = status;
1152 // XXX need to note failure, both to send back status
1153 // to the callback, and also so we don't try to install
1154 // this probably corrupt file.
1155 break;
1157 default:
1158 rv = NS_ERROR_ILLEGAL_VALUE;
1161 NS_ASSERTION( mItem, "Bad state in XPIManager");
1162 NS_ASSERTION( mItem->mOutStream, "XPIManager: output stream doesn't exist");
1163 if ( mItem && mItem->mOutStream )
1165 mItem->mOutStream->Close();
1166 mItem->mOutStream = nsnull;
1169 if (NS_FAILED(rv) || mCancelled)
1171 // Download error!
1172 // -- first clean up partially downloaded file
1173 if ( mItem->mFile )
1175 PRBool flagExists;
1176 nsresult rv2 ;
1177 rv2 = mItem->mFile->Exists(&flagExists);
1178 if (NS_SUCCEEDED(rv2) && flagExists)
1179 mItem->mFile->Remove(PR_FALSE);
1181 mItem->mFile = 0;
1184 // -- then notify interested parties
1185 PRInt32 errorcode = mCancelled ? nsInstall::USER_CANCELLED
1186 : nsInstall::DOWNLOAD_ERROR;
1187 if (mDlg)
1188 mDlg->OnStateChange( mNextItem-1,
1189 nsIXPIProgressDialog::INSTALL_DONE,
1190 errorcode );
1191 mTriggers->SendStatus( mItem->mURL.get(), errorcode );
1193 else if (mDlg)
1195 mDlg->OnStateChange( mNextItem-1, nsIXPIProgressDialog::DOWNLOAD_DONE, 0);
1198 DownloadNext();
1199 return rv;
1203 NS_IMETHODIMP
1204 nsXPInstallManager::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
1205 nsIInputStream *pIStream,
1206 PRUint32 sourceOffset,
1207 PRUint32 length)
1209 #define XPI_ODA_BUFFER_SIZE 8*1024
1210 PRUint32 amt = PR_MIN(XPI_ODA_BUFFER_SIZE, length);
1211 nsresult err;
1212 char buffer[XPI_ODA_BUFFER_SIZE];
1213 PRUint32 writeCount;
1215 if (mCancelled)
1217 // We must cancel this download in progress. We may get extra
1218 // OnData calls if they were already queued so beware
1219 request->Cancel(NS_BINDING_ABORTED);
1220 return NS_ERROR_FAILURE;
1225 err = pIStream->Read(buffer, amt, &amt);
1227 if (amt == 0) break;
1228 if (NS_FAILED(err)) return err;
1230 err = mItem->mOutStream->Write( buffer, amt, &writeCount);
1231 if (NS_FAILED(err) || writeCount != amt)
1233 return NS_ERROR_FAILURE;
1235 length -= amt;
1237 amt = PR_MIN(XPI_ODA_BUFFER_SIZE, length);
1239 } while (length > 0);
1241 return NS_OK;
1245 NS_IMETHODIMP
1246 nsXPInstallManager::OnProgress(nsIRequest* request, nsISupports *ctxt, PRUint64 aProgress, PRUint64 aProgressMax)
1248 nsresult rv = NS_OK;
1250 if (mDlg && !mCancelled)
1252 if (mContentLength < 1) {
1253 nsCOMPtr<nsIChannel> channel = do_QueryInterface(request,&rv);
1254 NS_ASSERTION(channel, "should have a channel");
1255 if (NS_FAILED(rv)) return rv;
1256 rv = channel->GetContentLength(&mContentLength);
1257 if (NS_FAILED(rv)) return rv;
1259 // XXX once channels support that, use 64-bit contentlength
1260 rv = mDlg->OnProgress( mNextItem-1, aProgress, nsUint64(mContentLength) );
1263 return rv;
1266 NS_IMETHODIMP
1267 nsXPInstallManager::OnStatus(nsIRequest* request, nsISupports *ctxt,
1268 nsresult aStatus, const PRUnichar *aStatusArg)
1270 // don't need to do anything
1271 return NS_OK;
1274 // nsIInterfaceRequestor method
1275 NS_IMETHODIMP
1276 nsXPInstallManager::GetInterface(const nsIID & eventSinkIID, void* *_retval)
1278 if (eventSinkIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
1279 *_retval = nsnull;
1281 nsresult rv;
1282 nsCOMPtr<nsIWindowWatcher> ww(do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
1283 NS_ENSURE_SUCCESS(rv, rv);
1285 nsCOMPtr<nsIAuthPrompt> prompt;
1286 rv = ww->GetNewAuthPrompter(nsnull, getter_AddRefs(prompt));
1287 NS_ENSURE_SUCCESS(rv, rv);
1289 nsIAuthPrompt *p = prompt.get();
1290 NS_ADDREF(p);
1291 *_retval = p;
1292 return NS_OK;
1294 else if (eventSinkIID.Equals(NS_GET_IID(nsIBadCertListener2))) {
1295 // If we aren't chrome triggered fall back to the default dialogs
1296 if (!mFromChrome)
1297 return NS_ERROR_NO_INTERFACE;
1299 return QueryInterface(eventSinkIID, (void**)_retval);
1302 // nsIChannelEventSink method
1303 NS_IMETHODIMP
1304 nsXPInstallManager::OnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel, PRUint32 flags)
1306 // Chrome triggered installs need to have their certificates checked
1307 if (mFromChrome)
1308 return CheckCert(oldChannel);
1309 return NS_OK;
1312 // nsIBadCertListener2 methods
1313 NS_IMETHODIMP
1314 nsXPInstallManager::NotifyCertProblem(nsIInterfaceRequestor *socketInfo,
1315 nsISSLStatus *status,
1316 const nsACString &targetSite,
1317 PRBool *_retval)
1319 *_retval = PR_TRUE;
1320 return NS_OK;
1323 // nsISSLErrorListener methods
1324 NS_IMETHODIMP
1325 nsXPInstallManager::NotifySSLError(nsIInterfaceRequestor *socketInfo,
1326 PRInt32 error,
1327 const nsACString &targetSite,
1328 PRBool *_retval)
1330 *_retval = PR_TRUE;
1331 return NS_OK;
1334 NS_IMETHODIMP
1335 nsXPInstallManager::OnCertAvailable(nsIURI *aURI,
1336 nsISupports* context,
1337 nsresult aStatus,
1338 nsIPrincipal *aPrincipal)
1340 if (NS_FAILED(aStatus) && aStatus != NS_BINDING_ABORTED) {
1341 // Check for a bad status. The only acceptable failure status code we accept
1342 // is NS_BINDING_ABORTED. For all others we want to ensure that the
1343 // nsIPrincipal is nsnull.
1345 NS_ASSERTION(aPrincipal == nsnull, "There has been an error, but we have a principal!");
1346 aPrincipal = nsnull;
1349 // get the current one and assign the cert name
1350 nsXPITriggerItem *item = mTriggers->Get(mOutstandingCertLoads);
1351 item->SetPrincipal(aPrincipal);
1353 if (mOutstandingCertLoads == 0) {
1354 InitManagerInternal();
1355 return NS_OK;
1358 // get the next one to load. If there is any failure, we just go on to the
1359 // next trigger. When all triggers items are handled, we call into InitManagerInternal
1361 item = mTriggers->Get(--mOutstandingCertLoads);
1363 nsCOMPtr<nsIURI> uri;
1364 NS_NewURI(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(item->mURL.get()).get());
1366 if (!uri || mChromeType != NOT_CHROME)
1367 return OnCertAvailable(uri, context, NS_ERROR_FAILURE, nsnull);
1369 nsIStreamListener* listener = new CertReader(uri, nsnull, this);
1370 if (!listener)
1371 return OnCertAvailable(uri, context, NS_ERROR_FAILURE, nsnull);
1373 NS_ADDREF(listener);
1374 nsresult rv = NS_OpenURI(listener, nsnull, uri);
1376 NS_ASSERTION(NS_SUCCEEDED(rv), "OpenURI failed");
1377 NS_RELEASE(listener);
1379 if (NS_FAILED(rv))
1380 return OnCertAvailable(uri, context, NS_ERROR_FAILURE, nsnull);
1382 return NS_OK;