nsIURIKey key(aURI);
nsXULPrototypeCache::StartFastLoad(nsIURI* aURI){    nsresult rv;    nsCAutoString path;    aURI->GetPath(path);    if (!StringEndsWith(path, NS_LITERAL_CSTRING(".xul")))        return NS_ERROR_NOT_AVAILABLE;    nsIURIKey key(aURI);    // Test gFastLoadFile to decide whether this is the first nsXULDocument    // participating in FastLoad.  If gFastLoadFile is non-null, this document    // must not be first, but it can join the FastLoad process.  Examples of    // multiple master documents participating include hiddenWindow.xul and    // navigator.xul on the Mac, and multiple-app-component (e.g., mailnews    // and browser) startup due to command-line arguments.    //    // XXXbe we should attempt to update the FastLoad file after startup!    //    // XXXbe we do not yet use nsFastLoadPtrs, but once we do, we must keep    // the FastLoad input stream open for the life of the app.    if (gFastLoadService && gFastLoadFile) {        mFastLoadURITable.Put(&key, aURI);        return NS_OK;    }    // Use a local to refer to the service till we're sure we succeeded, then    // commit to gFastLoadService.  Same for gFastLoadFile, which is used to    // delete the FastLoad file on abort.    nsCOMPtr<nsIFastLoadService> fastLoadService(do_GetFastLoadService());    if (! fastLoadService)        return NS_ERROR_FAILURE;    nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));    if (prefs) {        prefs->GetBoolPref(kDisableXULFastLoadPref, &gDisableXULFastLoad);        prefs->GetBoolPref(kChecksumXULFastLoadFilePref, &gChecksumXULFastLoadFile);        prefs->RegisterCallback(kDisableXULFastLoadPref,                                FastLoadPrefChangedCallback,                                nsnull);        prefs->RegisterCallback(kChecksumXULFastLoadFilePref,                                FastLoadPrefChangedCallback,                                nsnull);        if (gDisableXULFastLoad)            return NS_ERROR_NOT_AVAILABLE;    }    // Get the chrome directory to validate against the one stored in the    // FastLoad file, or to store there if we're generating a new file.    nsCOMPtr<nsIFile> chromeDir;    rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR, getter_AddRefs(chromeDir));    if (NS_FAILED(rv))        return rv;    nsCAutoString chromePath;    rv = chromeDir->GetNativePath(chromePath);    if (NS_FAILED(rv))        return rv;    nsCOMPtr<nsIFile> file;    rv = fastLoadService->NewFastLoadFile(XUL_FASTLOAD_FILE_BASENAME,                                          getter_AddRefs(file));    if (NS_FAILED(rv))        return rv;    // Give the FastLoad service an object by which it can get or create a    // file output stream given an input stream on the same file.    nsXULFastLoadFileIO* xio = new nsXULFastLoadFileIO(file);    nsCOMPtr<nsIFastLoadFileIO> io = NS_STATIC_CAST(nsIFastLoadFileIO*, xio);    if (! io)        return NS_ERROR_OUT_OF_MEMORY;    fastLoadService->SetFileIO(io);    nsCOMPtr<nsIXULChromeRegistry> chromeReg(do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv));    if (NS_FAILED(rv))        return rv;    // XXXbe we assume the first package's locale is the same as the locale of    // all subsequent packages of FastLoaded chrome URIs....    nsCAutoString package;    rv = aURI->GetHost(package);    if (NS_FAILED(rv))        return rv;    nsCAutoString locale;    rv = chromeReg->GetSelectedLocale(package, locale);    if (NS_FAILED(rv))        return rv;    // Try to read an existent FastLoad file.    PRBool exists = PR_FALSE;    if (NS_SUCCEEDED(file->Exists(&exists)) && exists) {        nsCOMPtr<nsIInputStream> input;        rv = io->GetInputStream(getter_AddRefs(input));        if (NS_FAILED(rv))            return rv;        nsCOMPtr<nsIObjectInputStream> objectInput;        rv = fastLoadService->NewInputStream(input, getter_AddRefs(objectInput));        if (NS_SUCCEEDED(rv)) {            if (gChecksumXULFastLoadFile) {                nsCOMPtr<nsIFastLoadReadControl>                    readControl(do_QueryInterface(objectInput));                if (readControl) {                    // Verify checksum, using the fastLoadService's checksum                    // cache to avoid computing more than once per session.                    PRUint32 checksum;                    rv = readControl->GetChecksum(&checksum);                    if (NS_SUCCEEDED(rv)) {                        PRUint32 verified;                        rv = fastLoadService->ComputeChecksum(file,                                                               readControl,                                                               &verified);                        if (NS_SUCCEEDED(rv) && verified != checksum) {#ifdef DEBUG                            printf("bad FastLoad file checksum\n");#endif                            rv = NS_ERROR_FAILURE;                        }                    }                }            }            if (NS_SUCCEEDED(rv)) {                // Get the XUL fastload file version number, which should be                // decremented whenever the XUL-specific file format changes                // (see public/nsIXULPrototypeCache.h for the #define).                PRUint32 version;                rv = objectInput->Read32(&version);                if (NS_SUCCEEDED(rv)) {                    if (version != XUL_FASTLOAD_FILE_VERSION) {#ifdef DEBUG                        printf("bad FastLoad file version\n");#endif                        rv = NS_ERROR_UNEXPECTED;                    } else {                        nsCAutoString fileChromePath, fileLocale;                        rv = objectInput->ReadCString(fileChromePath);                        rv |= objectInput->ReadCString(fileLocale);                        if (NS_SUCCEEDED(rv) &&                            (!fileChromePath.Equals(chromePath) ||                             !fileLocale.Equals(locale))) {                            rv = NS_ERROR_UNEXPECTED;                        }                    }                }            }        }        if (NS_SUCCEEDED(rv)) {            fastLoadService->SetInputStream(objectInput);        } else {            // NB: we must close before attempting to remove, for non-Unix OSes            // that can't do open-unlink.            if (objectInput)                objectInput->Close();            else                input->Close();            xio->mInputStream = nsnull;#ifdef DEBUG            file->MoveToNative(nsnull, NS_LITERAL_CSTRING("Invalid.mfasl"));#else            file->Remove(PR_FALSE);#endif            exists = PR_FALSE;        }    }    // FastLoad file not found, or invalid: write a new one.    if (! exists) {        nsCOMPtr<nsIOutputStream> output;        rv = io->GetOutputStream(getter_AddRefs(output));        if (NS_FAILED(rv))            return rv;        nsCOMPtr<nsIObjectOutputStream> objectOutput;        rv = fastLoadService->NewOutputStream(output,                                              getter_AddRefs(objectOutput));        if (NS_SUCCEEDED(rv)) {            rv = objectOutput->Write32(XUL_FASTLOAD_FILE_VERSION);            rv |= objectOutput->WriteStringZ(chromePath.get());            rv |= objectOutput->WriteStringZ(locale.get());        }        // Remove here even though some errors above will lead to a FastLoad        // file invalidation.  Other errors (failure to note the dependency on        // installed-chrome.txt, e.g.) will not cause invalidation, and we may        // as well tidy up now.        if (NS_FAILED(rv)) {            if (objectOutput)                objectOutput->Close();            else                output->Close();            xio->mOutputStream = nsnull;            file->Remove(PR_FALSE);            return NS_ERROR_FAILURE;        }        fastLoadService->SetOutputStream(objectOutput);    }    // Success!  Insert this URI into the mFastLoadURITable    // and commit locals to globals.    mFastLoadURITable.Put(&key, aURI);    NS_ADDREF(gFastLoadService = fastLoadService);    NS_ADDREF(gFastLoadFile = file);    return NS_OK;}