Пример #1
0
    void Print(const char* aName, LogLevel aLevel, const char* aFmt, va_list aArgs)
    {
        const size_t kBuffSize = 1024;
        char buff[kBuffSize];

        char* buffToWrite = buff;

        // For backwards compat we need to use the NSPR format string versions
        // of sprintf and friends and then hand off to printf.
        va_list argsCopy;
        va_copy(argsCopy, aArgs);
        size_t charsWritten = PR_vsnprintf(buff, kBuffSize, aFmt, argsCopy);
        va_end(argsCopy);

        if (charsWritten == kBuffSize - 1) {
            // We may have maxed out, allocate a buffer instead.
            buffToWrite = PR_vsmprintf(aFmt, aArgs);
            charsWritten = strlen(buffToWrite);
        }

        // Determine if a newline needs to be appended to the message.
        const char* newline = "";
        if (charsWritten == 0 || buffToWrite[charsWritten - 1] != '\n') {
            newline = "\n";
        }

        FILE* out = mOutFile ? mOutFile : stderr;

        // This differs from the NSPR format in that we do not output the
        // opaque system specific thread pointer (ie pthread_t) cast
        // to a long. The address of the current PR_Thread continues to be
        // prefixed.
        //
        // Additionally we prefix the output with the abbreviated log level
        // and the module name.
        PRThread *currentThread = PR_GetCurrentThread();
        const char *currentThreadName = (mMainThread == currentThread)
                                        ? "Main Thread"
                                        : PR_GetThreadName(currentThread);

        char noNameThread[40];
        if (!currentThreadName) {
            snprintf_literal(noNameThread, "Unnamed thread %p", currentThread);
            currentThreadName = noNameThread;
        }

        if (!mAddTimestamp) {
            fprintf_stderr(out,
                           "[%s]: %s/%s %s%s",
                           currentThreadName, ToLogStr(aLevel),
                           aName, buffToWrite, newline);
        } else {
            PRExplodedTime now;
            PR_ExplodeTime(PR_Now(), PR_GMTParameters, &now);
            fprintf_stderr(
                out,
                "%04d-%02d-%02d %02d:%02d:%02d.%06d UTC - [%s]: %s/%s %s%s",
                now.tm_year, now.tm_month + 1, now.tm_mday,
                now.tm_hour, now.tm_min, now.tm_sec, now.tm_usec,
                currentThreadName, ToLogStr(aLevel),
                aName, buffToWrite, newline);
        }

        if (mIsSync) {
            fflush(out);
        }

        if (buffToWrite != buff) {
            PR_smprintf_free(buffToWrite);
        }
    }
Пример #2
0
NS_IMETHODIMP
nsAboutBloat::NewChannel(nsIURI *aURI, nsIChannel **result)
{
    NS_ENSURE_ARG_POINTER(aURI);
    nsresult rv;
    nsAutoCString path;
    rv = aURI->GetPath(path);
    if (NS_FAILED(rv)) return rv;

    nsTraceRefcntImpl::StatisticsType statType = nsTraceRefcntImpl::ALL_STATS;
    bool clear = false;
    bool leaks = false;

    int32_t pos = path.Find("?");
    if (pos > 0) {
        nsAutoCString param;
        (void)path.Right(param, path.Length() - (pos+1));
        if (param.EqualsLiteral("new"))
            statType = nsTraceRefcntImpl::NEW_STATS;
        else if (param.EqualsLiteral("clear"))
            clear = true;
        else if (param.EqualsLiteral("leaks"))
            leaks = true;
    }

    nsCOMPtr<nsIInputStream> inStr;
    if (clear) {
        nsTraceRefcntImpl::ResetStatistics();

        rv = NS_NewCStringInputStream(getter_AddRefs(inStr),
            NS_LITERAL_CSTRING("Bloat statistics cleared."));
        if (NS_FAILED(rv)) return rv;
    }
    else if (leaks) {
        // dump the current set of leaks.
        GC_gcollect();
    	
        rv = NS_NewCStringInputStream(getter_AddRefs(inStr),
            NS_LITERAL_CSTRING("Memory leaks dumped."));
        if (NS_FAILED(rv)) return rv;
    }
    else {
        nsCOMPtr<nsIFile> file;
        rv = NS_GetSpecialDirectory(NS_OS_CURRENT_PROCESS_DIR, 
                                    getter_AddRefs(file));       
        if (NS_FAILED(rv)) return rv;

        rv = file->AppendNative(NS_LITERAL_CSTRING("bloatlogs"));
        if (NS_FAILED(rv)) return rv;

        bool exists;
        rv = file->Exists(&exists);
        if (NS_FAILED(rv)) return rv;

        if (!exists) {
            // On all the platforms that I know use permissions,
            // directories need to have the executable flag set
            // if you want to do anything inside the directory.
            rv = file->Create(nsIFile::DIRECTORY_TYPE, 0755);
            if (NS_FAILED(rv)) return rv;
        }

        nsAutoCString dumpFileName;
        if (statType == nsTraceRefcntImpl::ALL_STATS)
            dumpFileName.AssignLiteral("all-");
        else
            dumpFileName.AssignLiteral("new-");
        PRExplodedTime expTime;
        PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &expTime);
        char time[128];
        PR_FormatTimeUSEnglish(time, 128, "%Y-%m-%d-%H%M%S.txt", &expTime);
        dumpFileName += time;
        rv = file->AppendNative(dumpFileName);
        if (NS_FAILED(rv)) return rv;

        FILE* out;
        rv = file->OpenANSIFileDesc("w", &out);
        if (NS_FAILED(rv)) return rv;

        rv = nsTraceRefcntImpl::DumpStatistics(statType, out);
        ::fclose(out);
        if (NS_FAILED(rv)) return rv;

        rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), file);
        if (NS_FAILED(rv)) return rv;
    }

    nsIChannel* channel;
    rv = NS_NewInputStreamChannel(&channel, aURI, inStr,
                                  NS_LITERAL_CSTRING("text/plain"),
                                  NS_LITERAL_CSTRING("utf-8"));
    if (NS_FAILED(rv)) return rv;

    *result = channel;
    return rv;
}
Пример #3
0
// Set rcvDate to true to get the Received: date instead of the Date: date.
nsresult nsMsgGroupView::GetAgeBucketValue(nsIMsgDBHdr *aMsgHdr, PRUint32 * aAgeBucket, bool rcvDate)
{
  NS_ENSURE_ARG_POINTER(aMsgHdr);
  NS_ENSURE_ARG_POINTER(aAgeBucket);

  PRTime dateOfMsg;
  nsresult rv;
  if (!rcvDate)
    rv = aMsgHdr->GetDate(&dateOfMsg);
  else
  {
    PRUint32 rcvDateSecs;
    rv = aMsgHdr->GetUint32Property("dateReceived", &rcvDateSecs);
    Seconds2PRTime(rcvDateSecs, &dateOfMsg);
  }
  NS_ENSURE_SUCCESS(rv, rv);

  PRTime currentTime = PR_Now();
  PRExplodedTime currentExplodedTime;
  PR_ExplodeTime(currentTime, PR_LocalTimeParameters, &currentExplodedTime);
  PRExplodedTime explodedMsgTime;
  PR_ExplodeTime(dateOfMsg, PR_LocalTimeParameters, &explodedMsgTime);

  if (m_lastCurExplodedTime.tm_mday &&
     m_lastCurExplodedTime.tm_mday != currentExplodedTime.tm_mday)
    m_dayChanged = true; // this will cause us to rebuild the view.

  m_lastCurExplodedTime = currentExplodedTime;
  if (currentExplodedTime.tm_year == explodedMsgTime.tm_year &&
      currentExplodedTime.tm_month == explodedMsgTime.tm_month &&
      currentExplodedTime.tm_mday == explodedMsgTime.tm_mday)
  {
    // same day...
    *aAgeBucket = 1;
  }
  // figure out how many days ago this msg arrived
  else if (LL_CMP(currentTime, >, dateOfMsg))
  {
    // some constants for calculation
    static PRInt64 microSecondsPerSecond;
    static PRInt64 microSecondsPerDay;
    static PRInt64 secondsPerDay;
    static PRInt64 microSecondsPer6Days;
    static PRInt64 microSecondsPer13Days;

    static bool bGotConstants = false;
    if ( !bGotConstants )
    {
      // seeds
      LL_I2L  ( microSecondsPerSecond,  PR_USEC_PER_SEC );
      LL_UI2L ( secondsPerDay,          60 * 60 * 24 );

      // derivees
      LL_MUL( microSecondsPerDay,   secondsPerDay,      microSecondsPerSecond );
      LL_MUL( microSecondsPer6Days, microSecondsPerDay, 6 );
      LL_MUL( microSecondsPer13Days, microSecondsPerDay, 13 );
      bGotConstants = true;
    }

    // setting the time variables to local time
    PRInt64 GMTLocalTimeShift;
    LL_ADD( GMTLocalTimeShift, currentExplodedTime.tm_params.tp_gmt_offset, currentExplodedTime.tm_params.tp_dst_offset );
    LL_MUL( GMTLocalTimeShift, GMTLocalTimeShift, microSecondsPerSecond );
    LL_ADD( currentTime, currentTime, GMTLocalTimeShift );
    LL_ADD( dateOfMsg, dateOfMsg, GMTLocalTimeShift );

    // the most recent midnight, counting from current time
    PRInt64 todaysMicroSeconds, mostRecentMidnight;
    LL_MOD( todaysMicroSeconds, currentTime, microSecondsPerDay );
    LL_SUB( mostRecentMidnight, currentTime, todaysMicroSeconds );
    PRInt64 yesterday;
    LL_SUB( yesterday, mostRecentMidnight, microSecondsPerDay );
    // most recent midnight minus 6 days
    PRInt64 mostRecentWeek;
    LL_SUB( mostRecentWeek, mostRecentMidnight, microSecondsPer6Days );

    // was the message sent yesterday?
    if ( LL_CMP( dateOfMsg, >=, yesterday ) ) // yes ....
      *aAgeBucket = 2;
    else if ( LL_CMP(dateOfMsg, >=, mostRecentWeek) )
      *aAgeBucket = 3;
    else
    {
Пример #4
0
/*
 * Create a DER-encoded OCSP request (for the certificate whose nickname
 * is "name") and dump it out.
 */
static SECStatus
create_request (FILE *out_file, CERTCertDBHandle *handle, CERTCertificate *cert,
		PRBool add_service_locator, PRBool add_acceptable_responses)
{
    CERTCertList *certs = NULL;
    CERTCertificate *myCert = NULL;
    CERTOCSPRequest *request = NULL;
    int64 now = PR_Now();
    SECItem *encoding = NULL;
    SECStatus rv = SECFailure;

    if (handle == NULL || cert == NULL)
	return rv;

    myCert = CERT_DupCertificate(cert);
    if (myCert == NULL)
        goto loser;

    /*
     * We need to create a list of one.
     */
    certs = CERT_NewCertList();
    if (certs == NULL)
	goto loser;

    if (CERT_AddCertToListTail (certs, myCert) != SECSuccess)
	goto loser;

    /*
     * Now that cert is included in the list, we need to be careful
     * that we do not try to destroy it twice.  This will prevent that.
     */
    myCert = NULL;

    request = CERT_CreateOCSPRequest (certs, now, add_service_locator, NULL);
    if (request == NULL)
	goto loser;

    if (add_acceptable_responses) {
	rv = CERT_AddOCSPAcceptableResponses(request,
					     SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
	if (rv != SECSuccess)
	    goto loser;
    }

    encoding = CERT_EncodeOCSPRequest (NULL, request, NULL);
    if (encoding == NULL)
	goto loser;

    MAKE_FILE_BINARY(out_file);
    if (fwrite (encoding->data, encoding->len, 1, out_file) != 1)
	goto loser;

    rv = SECSuccess;

loser:
    if (encoding != NULL)
	SECITEM_FreeItem(encoding, PR_TRUE);
    if (request != NULL)
	CERT_DestroyOCSPRequest(request);
    if (certs != NULL)
	CERT_DestroyCertList (certs);
    if (myCert != NULL)
	CERT_DestroyCertificate(myCert);

    return rv;
}
Пример #5
0
int
main (int argc, char **argv)
{
    int		 retval;
    PRFileDesc	*in_file;
    FILE	*out_file;	/* not PRFileDesc until SECU accepts it */
    int		 crequest, dresponse;
    int		 prequest, presponse;
    int		 ccert, vcert;
    const char	*db_dir, *date_str, *cert_usage_str, *name;
    const char	*responder_name, *responder_url, *signer_name;
    PRBool	 add_acceptable_responses, add_service_locator;
    SECItem	*data = NULL;
    PLOptState	*optstate;
    SECStatus	 rv;
    CERTCertDBHandle *handle = NULL;
    SECCertUsage cert_usage;
    int64	 verify_time;
    CERTCertificate *cert = NULL;
    PRBool ascii = PR_FALSE;

    retval = -1;		/* what we return/exit with on error */

    program_name = PL_strrchr(argv[0], '/');
    program_name = program_name ? (program_name + 1) : argv[0];

    in_file = PR_STDIN;
    out_file = stdout;

    crequest = 0;
    dresponse = 0;
    prequest = 0;
    presponse = 0;
    ccert = 0;
    vcert = 0;

    db_dir = NULL;
    date_str = NULL;
    cert_usage_str = NULL;
    name = NULL;
    responder_name = NULL;
    responder_url = NULL;
    signer_name = NULL;

    add_acceptable_responses = PR_FALSE;
    add_service_locator = PR_FALSE;

    optstate = PL_CreateOptState (argc, argv, "AHLPR:S:V:d:l:pr:s:t:u:w:");
    if (optstate == NULL) {
	SECU_PrintError (program_name, "PL_CreateOptState failed");
	return retval;
    }

    while (PL_GetNextOpt (optstate) == PL_OPT_OK) {
	switch (optstate->option) {
	  case '?':
	    short_usage (program_name);
	    return retval;

	  case 'A':
	    add_acceptable_responses = PR_TRUE;
	    break;

	  case 'H':
	    long_usage (program_name);
	    return retval;

	  case 'L':
	    add_service_locator = PR_TRUE;
	    break;

	  case 'P':
	    presponse = 1;
	    break;

	  case 'R':
	    dresponse = 1;
	    name = optstate->value;
	    break;

	  case 'S':
	    ccert = 1;
	    name = optstate->value;
	    break;

	  case 'V':
	    vcert = 1;
	    name = optstate->value;
	    break;

	  case 'a':
	    ascii = PR_TRUE;
	    break;

	  case 'd':
	    db_dir = optstate->value;
	    break;

	  case 'l':
	    responder_url = optstate->value;
	    break;

	  case 'p':
	    prequest = 1;
	    break;

	  case 'r':
	    crequest = 1;
	    name = optstate->value;
	    break;

	  case 's':
	    signer_name = optstate->value;
	    break;

	  case 't':
	    responder_name = optstate->value;
	    break;

	  case 'u':
	    cert_usage_str = optstate->value;
	    break;

	  case 'w':
	    date_str = optstate->value;
	    break;
	}
    }

    PL_DestroyOptState(optstate);

    if ((crequest + dresponse + prequest + presponse + ccert + vcert) != 1) {
	PR_fprintf (PR_STDERR, "%s: must specify exactly one command\n\n",
		    program_name);
	short_usage (program_name);
	return retval;
    }

    if (vcert) {
	if (cert_usage_str == NULL) {
	    PR_fprintf (PR_STDERR, "%s: verification requires cert usage\n\n",
			program_name);
	    short_usage (program_name);
	    return retval;
	}

	rv = cert_usage_from_char (cert_usage_str, &cert_usage);
	if (rv != SECSuccess) {
	    PR_fprintf (PR_STDERR, "%s: invalid cert usage (\"%s\")\n\n",
			program_name, cert_usage_str);
	    long_usage (program_name);
	    return retval;
	}
    }

    if (ccert + vcert) {
	if (responder_url != NULL || responder_name != NULL) {
	    /*
	     * To do a full status check, both the URL and the cert name
	     * of the responder must be specified if either one is.
	     */
	    if (responder_url == NULL || responder_name == NULL) {
		if (responder_url == NULL)
		    PR_fprintf (PR_STDERR,
				"%s: must also specify responder location\n\n",
				program_name);
		else
		    PR_fprintf (PR_STDERR,
				"%s: must also specify responder name\n\n",
				program_name);
		short_usage (program_name);
		return retval;
	    }
	}

	if (date_str != NULL) {
	    rv = DER_AsciiToTime (&verify_time, (char *) date_str);
	    if (rv != SECSuccess) {
		SECU_PrintError (program_name, "error converting time string");
		PR_fprintf (PR_STDERR, "\n");
		long_usage (program_name);
		return retval;
	    }
	} else {
	    verify_time = PR_Now();
	}
    }

    retval = -2;		/* errors change from usage to runtime */

    /*
     * Initialize the NSPR and Security libraries.
     */
    PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
    db_dir = SECU_ConfigDirectory (db_dir);
    rv = NSS_Init (db_dir);
    if (rv != SECSuccess) {
	SECU_PrintError (program_name, "NSS_Init failed");
	goto prdone;
    }
    SECU_RegisterDynamicOids();

    if (prequest + presponse) {
	MAKE_FILE_BINARY(stdin);
	data = read_file_into_item (in_file, siBuffer);
	if (data == NULL) {
	    SECU_PrintError (program_name, "problem reading input");
	    goto nssdone;
	}
    }

    if (crequest + dresponse + presponse + ccert + vcert) {
	handle = CERT_GetDefaultCertDB();
	if (handle == NULL) {
	    SECU_PrintError (program_name, "problem getting certdb handle");
	    goto nssdone;
	}

	/*
	 * It would be fine to do the enable for all of these commands,
	 * but this way we check that everything but an overall verify
	 * can be done without it.  That is, that the individual pieces
	 * work on their own.
	 */
	if (vcert) {
	    rv = CERT_EnableOCSPChecking (handle);
	    if (rv != SECSuccess) {
		SECU_PrintError (program_name, "error enabling OCSP checking");
		goto nssdone;
	    }
	}

	if ((ccert + vcert) && (responder_name != NULL)) {
	    rv = CERT_SetOCSPDefaultResponder (handle, responder_url,
					       responder_name);
	    if (rv != SECSuccess) {
		SECU_PrintError (program_name,
				 "error setting default responder");
		goto nssdone;
	    }

	    rv = CERT_EnableOCSPDefaultResponder (handle);
	    if (rv != SECSuccess) {
		SECU_PrintError (program_name,
				 "error enabling default responder");
		goto nssdone;
	    }
	}
    }

#define NOTYET(opt)							\
	{								\
	    PR_fprintf (PR_STDERR, "%s not yet working\n", opt);	\
	    exit (-1);							\
	}

    if (name) {
        cert = find_certificate(handle, name, ascii);
    }

    if (crequest) {
	if (signer_name != NULL) {
	    NOTYET("-s");
	}
	rv = create_request (out_file, handle, cert, add_service_locator,
			     add_acceptable_responses);
    } else if (dresponse) {
	if (signer_name != NULL) {
	    NOTYET("-s");
	}
	rv = dump_response (out_file, handle, cert, responder_url);
    } else if (prequest) {
	rv = print_request (out_file, data);
    } else if (presponse) {
	rv = print_response (out_file, data, handle);
    } else if (ccert) {
	if (signer_name != NULL) {
	    NOTYET("-s");
	}
	rv = get_cert_status (out_file, handle, cert, name, verify_time);
    } else if (vcert) {
	if (signer_name != NULL) {
	    NOTYET("-s");
	}
	rv = verify_cert (out_file, handle, cert, name, cert_usage, verify_time);
    }

    if (rv != SECSuccess)
	SECU_PrintError (program_name, "error performing requested operation");
    else
	retval = 0;

nssdone:
    if (cert) {
        CERT_DestroyCertificate(cert);
    }

    if (data != NULL) {
	SECITEM_FreeItem (data, PR_TRUE);
    }

    if (handle != NULL) {
 	CERT_DisableOCSPDefaultResponder(handle);        
 	CERT_DisableOCSPChecking (handle);
    }

    if (NSS_Shutdown () != SECSuccess) {
	retval = 1;
    }

prdone:
    PR_Cleanup ();
    return retval;
}
Пример #6
0
static PRTime Now(void)
{
    return PR_Now();
}
Пример #7
0
/*
 * Find a user certificate that matchs the given criteria.
 *
 *      "handle" - database to search
 *      "nickname" - nickname to match
 *      "usage" - certificate usage to match
 *      "validOnly" - only return certs that are curently valid
 *      "proto_win" - window handle passed to pkcs11
 */
CERTCertificate *
CERT_FindUserCertByUsage(CERTCertDBHandle *handle,
                         const char *nickname,
                         SECCertUsage usage,
                         PRBool validOnly,
                         void *proto_win)
{
    CERTCertificate *cert = NULL;
    CERTCertList *certList = NULL;
    SECStatus rv;
    PRTime time;

    time = PR_Now();

    /* use the pk11 call so that we pick up any certs on tokens,
     * which may require login
     */
    /* XXX - why is this restricted? */
    if (proto_win != NULL) {
        cert = PK11_FindCertFromNickname(nickname, proto_win);
    }

    /* sigh, There are still problems find smart cards from the temp
     * db. This will get smart cards working again. The real fix
     * is to make sure we can search the temp db by their token nickname.
     */
    if (cert == NULL) {
        cert = CERT_FindCertByNickname(handle, nickname);
    }

    if (cert != NULL) {
        unsigned int requiredKeyUsage;
        unsigned int requiredCertType;

        rv = CERT_KeyUsageAndTypeForCertUsage(usage, PR_FALSE,
                                              &requiredKeyUsage, &requiredCertType);
        if (rv != SECSuccess) {
            /* drop the extra reference */
            CERT_DestroyCertificate(cert);
            cert = NULL;
            goto loser;
        }
        /* If we already found the right cert, just return it */
        if ((!validOnly || CERT_CheckCertValidTimes(cert, time, PR_FALSE) == secCertTimeValid) &&
            (CERT_CheckKeyUsage(cert, requiredKeyUsage) == SECSuccess) &&
            (cert->nsCertType & requiredCertType) &&
            CERT_IsUserCert(cert)) {
            return (cert);
        }

        /* collect certs for this nickname, sorting them into the list */
        certList = CERT_CreateSubjectCertList(certList, handle,
                                              &cert->derSubject, time, validOnly);

        CERT_FilterCertListForUserCerts(certList);

        /* drop the extra reference */
        CERT_DestroyCertificate(cert);
        cert = NULL;
    }

    if (certList == NULL) {
        goto loser;
    }

    /* remove certs with incorrect usage */
    rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);

    if (rv != SECSuccess) {
        goto loser;
    }

    if (!CERT_LIST_END(CERT_LIST_HEAD(certList), certList)) {
        cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert);
    }

loser:
    if (certList != NULL) {
        CERT_DestroyCertList(certList);
    }

    return (cert);
}
Пример #8
0
NS_IMETHODIMP
nsLoadCollector::OnStateChange(nsIWebProgress *webProgress,
                               nsIRequest *request,
                               PRUint32 flags,
                               nsresult status)
{
  NS_ASSERTION(flags & STATE_IS_DOCUMENT,
               "incorrect state change notification");

#ifdef PR_LOGGING
  if (MS_LOG_ENABLED()) {
    nsCString name;
    request->GetName(name);

    MS_LOG(("LoadCollector: progress = %p, request = %p [%s], flags = %x, status = %x",
            webProgress, request, name.get(), flags, status));
  }
#endif

  nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
  if (!channel) {
    // We don't care about non-channel requests
    return NS_OK;
  }

  nsresult rv;
  if (flags & STATE_START) {
    RequestEntry entry;
    NS_ASSERTION(!mRequestMap.Get(request, &entry), "duplicate STATE_START");

    nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(webProgress);
    nsCOMPtr<nsIDOMWindow> window = do_GetInterface(docShell);
    if (!window) {
      // We don't really care about windowless loads
      return NS_OK;
    }

    rv = nsMetricsUtils::NewPropertyBag(getter_AddRefs(entry.properties));
    NS_ENSURE_SUCCESS(rv, rv);
    nsIWritablePropertyBag2 *props = entry.properties;

    rv = props->SetPropertyAsUint32(NS_LITERAL_STRING("window"),
                                    nsMetricsService::GetWindowID(window));
    NS_ENSURE_SUCCESS(rv, rv);

    if (flags & STATE_RESTORING) {
      rv = props->SetPropertyAsBool(NS_LITERAL_STRING("bfCacheHit"), PR_TRUE);
      NS_ENSURE_SUCCESS(rv, rv);
    }

    nsString origin;
    PRUint32 loadType;
    docShell->GetLoadType(&loadType);

    switch (loadType) {
    case LOAD_NORMAL:
    case LOAD_NORMAL_REPLACE:
    case LOAD_BYPASS_HISTORY:
      origin = NS_LITERAL_STRING("typed");
      break;
    case LOAD_NORMAL_EXTERNAL:
      origin = NS_LITERAL_STRING("external");
      break;
    case LOAD_HISTORY:
      origin = NS_LITERAL_STRING("session-history");
      break;
    case LOAD_RELOAD_NORMAL:
    case LOAD_RELOAD_BYPASS_CACHE:
    case LOAD_RELOAD_BYPASS_PROXY:
    case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
    case LOAD_RELOAD_CHARSET_CHANGE:
      origin = NS_LITERAL_STRING("reload");
      break;
    case LOAD_LINK:
      origin = NS_LITERAL_STRING("link");
      break;
    case LOAD_REFRESH:
      origin = NS_LITERAL_STRING("refresh");
      break;
    default:
      break;
    }
    if (!origin.IsEmpty()) {
      rv = props->SetPropertyAsAString(NS_LITERAL_STRING("origin"), origin);
      NS_ENSURE_SUCCESS(rv, rv);
    }
    entry.startTime = PR_Now();
    NS_ENSURE_TRUE(mRequestMap.Put(request, entry), NS_ERROR_OUT_OF_MEMORY);
  } else if (flags & STATE_STOP) {
    RequestEntry entry;
    if (mRequestMap.Get(request, &entry)) {
      mRequestMap.Remove(request);

      // Log a <document action="load"> event
      nsIWritablePropertyBag2 *props = entry.properties;
      rv = props->SetPropertyAsACString(NS_LITERAL_STRING("action"),
                                        NS_LITERAL_CSTRING("load"));
      NS_ENSURE_SUCCESS(rv, rv);
      
      // Compute the load time now that we have the end time.
      PRInt64 loadTime = (PR_Now() - entry.startTime) / PR_USEC_PER_MSEC;
      rv = props->SetPropertyAsUint64(NS_LITERAL_STRING("loadtime"), loadTime);
      NS_ENSURE_SUCCESS(rv, rv);

      MemUsage mu;
      if (GetMemUsage(&mu)) {
        rv = props->SetPropertyAsUint64(NS_LITERAL_STRING("memtotal"), mu.total);
        NS_ENSURE_SUCCESS(rv, rv);
        rv = props->SetPropertyAsUint64(NS_LITERAL_STRING("memresident"), mu.resident);
        NS_ENSURE_SUCCESS(rv, rv);
      }

      // Look up the document id, or assign a new one
      nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(webProgress);
      nsCOMPtr<nsIDOMWindow> window = do_GetInterface(docShell);
      if (!window) {
        MS_LOG(("Couldn't get window"));
        return NS_ERROR_UNEXPECTED;
      }

      nsCOMPtr<nsIDOMDocument> domDoc;
      window->GetDocument(getter_AddRefs(domDoc));
      nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
      if (!doc) {
        MS_LOG(("Couldn't get document"));
        return NS_ERROR_UNEXPECTED;
      }

      nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(docShell);
      NS_ENSURE_STATE(item);
      PRBool subframe = nsMetricsUtils::IsSubframe(item);
      if (subframe) {
        rv = props->SetPropertyAsBool(NS_LITERAL_STRING("subframe"), PR_TRUE);
        NS_ENSURE_SUCCESS(rv, rv);
      }

      nsMetricsService *ms = nsMetricsService::get();
      DocumentEntry docEntry;
      if (!mDocumentMap.Get(doc, &docEntry)) {
        docEntry.docID = mNextDocID++;
        docEntry.subframe = subframe;

        if (!ms->WindowMap().Get(window, &docEntry.windowID)) {
          MS_LOG(("Window not in the window map"));
          return NS_ERROR_UNEXPECTED;
        }

        NS_ENSURE_TRUE(mDocumentMap.Put(doc, docEntry),
                       NS_ERROR_OUT_OF_MEMORY);
      }
      doc->AddObserver(this);  // set up to log the document destroy

      rv = props->SetPropertyAsUint32(NS_LITERAL_STRING("docid"),
                                      docEntry.docID);
      NS_ENSURE_SUCCESS(rv, rv);

      // If this was a load of a chrome document, hash the URL of the document
      // so it can be identified.

      nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
      if (channel) {
        nsCOMPtr<nsIURI> uri;
        channel->GetURI(getter_AddRefs(uri));
        if (uri) {
          PRBool isChrome = PR_FALSE;
          uri->SchemeIs("chrome", &isChrome);
          if (isChrome) {
            nsCString spec;
            uri->GetSpec(spec);

            nsCString hashedSpec;
            rv = ms->HashUTF8(spec, hashedSpec);
            NS_ENSURE_SUCCESS(rv, rv);

            rv = props->SetPropertyAsACString(NS_LITERAL_STRING("urlhash"),
                                              hashedSpec);
            NS_ENSURE_SUCCESS(rv, rv);
          }
        }
      }

      rv = ms->LogEvent(NS_LITERAL_STRING("document"), props);
      NS_ENSURE_SUCCESS(rv, rv);
    } else {
      NS_WARNING("STATE_STOP without STATE_START");
    }
  }

  return NS_OK;
}
Пример #9
0
int
main(int argc, char **argv)
{
    SECStatus rv;
    int retval = -1;
    CERTCertDBHandle *certHandle = NULL;
    CERTCertificate *caCert = NULL, *cert = NULL;
    CERTOCSPCertID *cid = NULL;
    PLArenaPool *arena = NULL;
    PRTime now = PR_Now();
    
    SECItem *encoded = NULL;
    CERTOCSPResponse *decoded = NULL;

    SECItem *encodedRev = NULL;
    CERTOCSPResponse *decodedRev = NULL;
    
    SECItem *encodedFail = NULL;
    CERTOCSPResponse *decodedFail = NULL;

    CERTCertificate *obtainedSignerCert = NULL;

    if (argc != 4 && argc != 6) {
        return Usage();
    }

    if (argc == 6) {
        if (!strcmp(argv[4], "-p")) {
            pwdata.source = PW_PLAINTEXT;
            pwdata.data = PORT_Strdup(argv[5]);
        }
        else if (!strcmp(argv[4], "-f")) {
            pwdata.source = PW_FROMFILE;
            pwdata.data = PORT_Strdup(argv[5]);
        }
        else
            return Usage();
    }

    PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
    /*rv = NSS_Init(SECU_ConfigDirectory(NULL));*/
    rv = NSS_Init(argv[1]);
    if (rv != SECSuccess) {
	SECU_PrintPRandOSError(argv[0]);
	goto loser;
    }

    PK11_SetPasswordFunc(SECU_GetModulePassword);

    certHandle = CERT_GetDefaultCertDB();
    if (!certHandle)
	goto loser;

    if (!getCaAndSubjectCert(certHandle, argv[2], argv[3], &caCert, &cert))
        goto loser;

    cid = CERT_CreateOCSPCertID(cert, now);

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    encoded = encode(arena, cid, caCert);
    PORT_Assert(encoded);
    decoded = CERT_DecodeOCSPResponse(encoded);
    PORT_CheckSuccess(CERT_GetOCSPResponseStatus(decoded));

    PORT_CheckSuccess(CERT_VerifyOCSPResponseSignature(decoded, certHandle, &pwdata,
                                                        &obtainedSignerCert, caCert));
    PORT_CheckSuccess(CERT_GetOCSPStatusForCertID(certHandle, decoded, cid,
                                                   obtainedSignerCert, now));
    CERT_DestroyCertificate(obtainedSignerCert);

    encodedRev = encodeRevoked(arena, cid, caCert);
    PORT_Assert(encodedRev);
    decodedRev = CERT_DecodeOCSPResponse(encodedRev);
    PORT_CheckSuccess(CERT_GetOCSPResponseStatus(decodedRev));

    PORT_CheckSuccess(CERT_VerifyOCSPResponseSignature(decodedRev, certHandle, &pwdata,
                                                        &obtainedSignerCert, caCert));
#ifdef DEBUG
    {
        SECStatus rv = CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid,
                                                   obtainedSignerCert, now);
        PORT_Assert(rv == SECFailure);
        PORT_Assert(PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE);
    }
#else
    (void)CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid,
                                      obtainedSignerCert, now);
#endif
    CERT_DestroyCertificate(obtainedSignerCert);
    
    encodedFail = CERT_CreateEncodedOCSPErrorResponse(
        arena, SEC_ERROR_OCSP_TRY_SERVER_LATER);
    PORT_Assert(encodedFail);
    decodedFail = CERT_DecodeOCSPResponse(encodedFail);
#ifdef DEBUG
    {
        SECStatus rv = CERT_GetOCSPResponseStatus(decodedFail);
        PORT_Assert(rv == SECFailure);
        PORT_Assert(PORT_GetError() == SEC_ERROR_OCSP_TRY_SERVER_LATER);
    }
#else
    (void)CERT_GetOCSPResponseStatus(decodedFail);
#endif
    retval = 0;
loser:
    if (retval != 0)
        SECU_PrintError(argv[0], "tests failed");
    
    if (cid)
        CERT_DestroyOCSPCertID(cid);
    if (cert)
        CERT_DestroyCertificate(cert);
    if (caCert)
        CERT_DestroyCertificate(caCert);
    if (arena)
        PORT_FreeArena(arena, PR_FALSE);
    if (decoded)
        CERT_DestroyOCSPResponse(decoded);
    if (decodedRev)
        CERT_DestroyOCSPResponse(decodedRev);
    if (decodedFail)
        CERT_DestroyOCSPResponse(decodedFail);
    if (pwdata.data) {
        PORT_Free(pwdata.data);
    }
    
    if (NSS_Shutdown() != SECSuccess) {
        SECU_PrintError(argv[0], "NSS shutdown:");
        if (retval == 0)
            retval = -2;
    }

    return retval;
}
Пример #10
0
Файл: crlutil.c Проект: ekr/nss
static CERTSignedCrl *
CreateNewCrl(PLArenaPool *arena, CERTCertDBHandle *certHandle,
             CERTCertificate *cert)
{
    CERTSignedCrl *signCrl = NULL;
    void *dummy = NULL;
    SECStatus rv;
    void *mark = NULL;

    /* if the CERTSignedCrl structure changes, this function will need to be
       updated as well */
    if (!cert || !arena) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        SECU_PrintError(progName, "invalid args for function "
                                  "CreateNewCrl\n");
        return NULL;
    }

    mark = PORT_ArenaMark(arena);

    signCrl = PORT_ArenaZNew(arena, CERTSignedCrl);
    if (signCrl == NULL) {
        SECU_PrintError(progName, "fail to allocate memory\n");
        return NULL;
    }

    dummy = SEC_ASN1EncodeInteger(arena, &signCrl->crl.version,
                                  SEC_CRL_VERSION_2);
    /* set crl->version */
    if (!dummy) {
        SECU_PrintError(progName, "fail to create crl version data "
                                  "container\n");
        goto loser;
    }

    /* copy SECItem name from cert */
    rv = SECITEM_CopyItem(arena, &signCrl->crl.derName, &cert->derSubject);
    if (rv != SECSuccess) {
        SECU_PrintError(progName, "fail to duplicate der name from "
                                  "certificate.\n");
        goto loser;
    }

    /* copy CERTName name structure from cert issuer */
    rv = CERT_CopyName(arena, &signCrl->crl.name, &cert->subject);
    if (rv != SECSuccess) {
        SECU_PrintError(progName, "fail to duplicate RD name from "
                                  "certificate.\n");
        goto loser;
    }

    rv = DER_EncodeTimeChoice(arena, &signCrl->crl.lastUpdate, PR_Now());
    if (rv != SECSuccess) {
        SECU_PrintError(progName, "fail to encode current time\n");
        goto loser;
    }

    /* set fields */
    signCrl->arena = arena;
    signCrl->dbhandle = certHandle;
    signCrl->crl.arena = arena;

    return signCrl;

loser:
    PORT_ArenaRelease(arena, mark);
    return NULL;
}
/*
 * Check the user's password. Log into the card if it's correct.
 * succeed if the user is already logged in.
 */
static SECStatus
pk11_CheckPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
			char *pw, PRBool alreadyLocked, PRBool contextSpecific)
{
    int len = 0;
    CK_RV crv;
    SECStatus rv;
    int64 currtime = PR_Now();
    PRBool mustRetry;
    int retry = 0;

    if (slot->protectedAuthPath) {
	len = 0;
	pw = NULL;
    } else if (pw == NULL) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    } else {
	len = PORT_Strlen(pw);
    }

    do {
	if (!alreadyLocked) PK11_EnterSlotMonitor(slot);
	crv = PK11_GETTAB(slot)->C_Login(session,
		contextSpecific ? CKU_CONTEXT_SPECIFIC : CKU_USER,
						(unsigned char *)pw,len);
	slot->lastLoginCheck = 0;
	mustRetry = PR_FALSE;
	if (!alreadyLocked) PK11_ExitSlotMonitor(slot);
	switch (crv) {
	/* if we're already logged in, we're good to go */
	case CKR_OK:
		/* TODO If it was for CKU_CONTEXT_SPECIFIC should we do this */
	    slot->authTransact = PK11_Global.transaction;
	    /* Fall through */
	case CKR_USER_ALREADY_LOGGED_IN:
	    slot->authTime = currtime;
	    rv = SECSuccess;
	    break;
	case CKR_PIN_INCORRECT:
	    PORT_SetError(SEC_ERROR_BAD_PASSWORD);
	    rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
	    break;
	/* someone called reset while we fetched the password, try again once
	 * if the token is still there. */
	case CKR_SESSION_HANDLE_INVALID:
	case CKR_SESSION_CLOSED:
	    if (session != slot->session) {
		/* don't bother retrying, we were in a middle of an operation,
		 * which is now lost. Just fail. */
	        PORT_SetError(PK11_MapError(crv));
	        rv = SECFailure; 
		break;
	    }
	    if (retry++ == 0) {
		rv = PK11_InitToken(slot,PR_FALSE);
		if (rv == SECSuccess) {
		    if (slot->session != CK_INVALID_SESSION) {
			session = slot->session; /* we should have 
						  * a new session now */
			mustRetry = PR_TRUE;
		    } else {
			PORT_SetError(PK11_MapError(crv));
			rv = SECFailure;
		    }
		}
		break;
	    }
	    /* Fall through */
	default:
	    PORT_SetError(PK11_MapError(crv));
	    rv = SECFailure; /* some failure we can't fix by retrying */
	}
    } while (mustRetry);
    return rv;
}
Пример #12
0
Файл: crlutil.c Проект: ekr/nss
static CERTSignedCrl *
CreateModifiedCRLCopy(PLArenaPool *arena, CERTCertDBHandle *certHandle,
                      CERTCertificate **cert, char *certNickName,
                      PRFileDesc *inFile, PRInt32 decodeOptions,
                      PRInt32 importOptions)
{
    SECItem crlDER = { 0, NULL, 0 };
    CERTSignedCrl *signCrl = NULL;
    CERTSignedCrl *modCrl = NULL;
    PLArenaPool *modArena = NULL;
    SECStatus rv = SECSuccess;

    if (!arena || !certHandle || !certNickName) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        SECU_PrintError(progName, "CreateModifiedCRLCopy: invalid args\n");
        return NULL;
    }

    modArena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    if (!modArena) {
        SECU_PrintError(progName, "fail to allocate memory\n");
        return NULL;
    }

    if (inFile != NULL) {
        rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
        if (rv != SECSuccess) {
            SECU_PrintError(progName, "unable to read input file");
            PORT_FreeArena(modArena, PR_FALSE);
            goto loser;
        }

        decodeOptions |= CRL_DECODE_DONT_COPY_DER;

        modCrl = CERT_DecodeDERCrlWithFlags(modArena, &crlDER, SEC_CRL_TYPE,
                                            decodeOptions);
        if (!modCrl) {
            SECU_PrintError(progName, "fail to decode CRL");
            goto loser;
        }

        if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)) {
            /* If caCert is a v2 certificate, make sure that it
             * can be used for crl signing purpose */
            *cert = FindSigningCert(certHandle, modCrl, NULL);
            if (!*cert) {
                goto loser;
            }

            rv = CERT_VerifySignedData(&modCrl->signatureWrap, *cert,
                                       PR_Now(), NULL);
            if (rv != SECSuccess) {
                SECU_PrintError(progName, "fail to verify signed data\n");
                goto loser;
            }
        }
    } else {
        modCrl = FindCRL(certHandle, certNickName, SEC_CRL_TYPE);
        if (!modCrl) {
            SECU_PrintError(progName, "fail to find crl %s in database\n",
                            certNickName);
            goto loser;
        }
    }

    signCrl = PORT_ArenaZNew(arena, CERTSignedCrl);
    if (signCrl == NULL) {
        SECU_PrintError(progName, "fail to allocate memory\n");
        goto loser;
    }

    rv = SECU_CopyCRL(arena, &signCrl->crl, &modCrl->crl);
    if (rv != SECSuccess) {
        SECU_PrintError(progName, "unable to dublicate crl for "
                                  "modification.");
        goto loser;
    }

    /* Make sure the update time is current. It can be modified later
     * by "update <time>" command from crl generation script */
    rv = DER_EncodeTimeChoice(arena, &signCrl->crl.lastUpdate, PR_Now());
    if (rv != SECSuccess) {
        SECU_PrintError(progName, "fail to encode current time\n");
        goto loser;
    }

    signCrl->arena = arena;

loser:
    if (crlDER.data) {
        SECITEM_FreeItem(&crlDER, PR_FALSE);
    }
    if (modCrl)
        SEC_DestroyCrl(modCrl);
    if (rv != SECSuccess && signCrl) {
        SEC_DestroyCrl(signCrl);
        signCrl = NULL;
    }
    return signCrl;
}
NS_IMETHODIMP
nsDownload::OnStateChange(nsIWebProgress* aWebProgress,
                          nsIRequest* aRequest, PRUint32 aStateFlags,
                          nsresult aStatus)
{
    // Record the start time only if it hasn't been set.
    if (LL_IS_ZERO(mStartTime) && (aStateFlags & STATE_START))
        SetStartTime(PR_Now());

    // When we break the ref cycle with mPersist, we don't want to lose
    // access to out member vars!
    nsRefPtr<nsDownload> kungFuDeathGrip(this);

    // We need to update mDownloadState before updating the dialog, because
    // that will close and call CancelDownload if it was the last open window.
    nsresult rv = NS_OK;
    if (aStateFlags & STATE_STOP) {
        if (mDownloadState == DOWNLOADING || mDownloadState == NOTSTARTED) {
            mDownloadState = FINISHED;

            // Set file size at the end of a transfer (for unknown transfer amounts)
            if (mMaxBytes == -1)
                mMaxBytes = mCurrBytes;

            // Files less than 1Kb shouldn't show up as 0Kb.
            if (mMaxBytes < 1024) {
                mCurrBytes = 1024;
                mMaxBytes  = 1024;
            }

            mPercentComplete = 100;

            // Play a sound or show an alert when the download finishes
            PRBool playSound = PR_FALSE;
            PRBool showAlert = PR_FALSE;
            nsXPIDLCString soundStr;

            nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1");

            if (prefs) {
                nsCOMPtr<nsIPrefBranch> prefBranch;
                prefs->GetBranch(nsnull, getter_AddRefs(prefBranch));
                if (prefBranch) {
                    rv = prefBranch->GetBoolPref("browser.download.finished_download_sound", &playSound);
                    if (NS_SUCCEEDED(rv) && playSound)
                        prefBranch->GetCharPref("browser.download.finished_sound_url", getter_Copies(soundStr));
                    rv = prefBranch->GetBoolPref("browser.download.finished_download_alert", &showAlert);
                    if (NS_FAILED(rv))
                        showAlert = PR_FALSE;
                }
            }

            if (!soundStr.IsEmpty()) {
                if (!mDownloadManager->mSoundInterface) {
                    mDownloadManager->mSoundInterface = do_CreateInstance("@mozilla.org/sound;1");
                }
                if (mDownloadManager->mSoundInterface) {
                    nsCOMPtr<nsIURI> soundURI;

                    NS_NewURI(getter_AddRefs(soundURI), soundStr);
                    nsCOMPtr<nsIURL> soundURL(do_QueryInterface(soundURI));
                    if (soundURL)
                        mDownloadManager->mSoundInterface->Play(soundURL);
                    else
                        mDownloadManager->mSoundInterface->Beep();
                }
            }
            if (showAlert)
                DisplayDownloadFinishedAlert();

            nsCAutoString path;
            rv = GetFilePathUTF8(mTarget, path);
            // can't do an early return; have to break reference cycle below
            if (NS_SUCCEEDED(rv)) {
                mDownloadManager->DownloadEnded(path, nsnull);
            }
        }

        // break the cycle we created in AddDownload
        mCancelable = nsnull;
        // and the one with the progress dialog
        if (mDialog) {
            mDialog->SetObserver(nsnull);
            mDialog = nsnull;
        }
    }

    if (mDownloadManager->MustUpdateUI()) {
        nsCOMPtr<nsIDownloadProgressListener> internalListener;
        mDownloadManager->GetInternalListener(getter_AddRefs(internalListener));
        if (internalListener)
            internalListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus, this);
    }

    if (mDialogListener) {
        mDialogListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus, this);
        if (aStateFlags & STATE_STOP) {
            // Break this cycle, too
            mDialogListener = nsnull;
        }
    }

    return rv;
}
NS_IMETHODIMP
nsDownload::OnProgressChange64(nsIWebProgress *aWebProgress,
                               nsIRequest *aRequest,
                               PRInt64 aCurSelfProgress,
                               PRInt64 aMaxSelfProgress,
                               PRInt64 aCurTotalProgress,
                               PRInt64 aMaxTotalProgress)
{
    if (!mRequest)
        mRequest = aRequest; // used for pause/resume

    // Filter notifications since they come in so frequently, but we want to
    // process the last notification.
    PRTime now = PR_Now();
    nsInt64 delta = now - mLastUpdate;
    if (delta < gInterval && aCurTotalProgress != aMaxTotalProgress)
        return NS_OK;

    mLastUpdate = now;

    if (mDownloadState == NOTSTARTED) {
        nsCAutoString path;
        nsresult rv = GetFilePathUTF8(mTarget, path);
        if (NS_FAILED(rv)) return rv;

        mDownloadState = DOWNLOADING;
        mDownloadManager->DownloadStarted(path);
    }

    // Calculate the speed using the elapsed delta time and bytes downloaded
    // during that time for more accuracy.
    double elapsedSecs = double(delta) / PR_USEC_PER_SEC;
    if (elapsedSecs > 0) {
        nsUint64 curTotalProgress = (PRUint64)aCurTotalProgress;
        nsUint64 diffBytes = curTotalProgress - nsUint64(mCurrBytes);
        double speed = double(diffBytes) / elapsedSecs;
        if (LL_IS_ZERO(mCurrBytes))
            mSpeed = speed;
        else {
            // Calculate 'smoothed average' of 10 readings.
            mSpeed = mSpeed * 0.9 + speed * 0.1;
        }
    }

    if (aMaxTotalProgress > 0)
        mPercentComplete = aCurTotalProgress * 100 / aMaxTotalProgress;
    else
        mPercentComplete = -1;

    mCurrBytes = aCurTotalProgress;
    mMaxBytes = aMaxTotalProgress;

    if (mDownloadManager->MustUpdateUI()) {
        nsCOMPtr<nsIDownloadProgressListener> internalListener;
        mDownloadManager->GetInternalListener(getter_AddRefs(internalListener));
        if (internalListener) {
            internalListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress,
                                               aCurTotalProgress, aMaxTotalProgress, this);
        }
    }

    if (mDialogListener) {
        mDialogListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress,
                                          aCurTotalProgress, aMaxTotalProgress, this);
    }

    return NS_OK;
}
Пример #15
0
// called on the socket thread
nsresult
nsHttpTransaction::HandleContent(char *buf,
                                 PRUint32 count,
                                 PRUint32 *contentRead,
                                 PRUint32 *contentRemaining)
{
    nsresult rv;

    LOG(("nsHttpTransaction::HandleContent [this=%x count=%u]\n", this, count));

    *contentRead = 0;
    *contentRemaining = 0;

    NS_ASSERTION(mConnection, "no connection");

    if (!mDidContentStart) {
        rv = HandleContentStart();
        if (NS_FAILED(rv)) return rv;
        // Do not write content to the pipe if we haven't started streaming yet
        if (!mDidContentStart)
            return NS_OK;
    }

    if (mChunkedDecoder) {
        // give the buf over to the chunked decoder so it can reformat the
        // data and tell us how much is really there.
        rv = mChunkedDecoder->HandleChunkedContent(buf, count, contentRead, contentRemaining);
        if (NS_FAILED(rv)) return rv;
    }
    else if (mContentLength >= nsInt64(0)) {
        // HTTP/1.0 servers have been known to send erroneous Content-Length
        // headers. So, unless the connection is persistent, we must make
        // allowances for a possibly invalid Content-Length header. Thus, if
        // NOT persistent, we simply accept everything in |buf|.
        if (mConnection->IsPersistent()) {
            nsInt64 remaining = mContentLength - mContentRead;
            nsInt64 count64 = count;
            *contentRead = PR_MIN(count64, remaining);
            *contentRemaining = count - *contentRead;
        }
        else {
            *contentRead = count;
            // mContentLength might need to be increased...
            nsInt64 position = mContentRead + nsInt64(count);
            if (position > mContentLength) {
                mContentLength = position;
                //mResponseHead->SetContentLength(mContentLength);
            }
        }
    }
    else {
        // when we are just waiting for the server to close the connection...
        // (no explicit content-length given)
        *contentRead = count;
    }

    if (*contentRead) {
        // update count of content bytes read and report progress...
        mContentRead += *contentRead;
        /* when uncommenting, take care of 64-bit integers w/ PR_MAX...
        if (mProgressSink)
            mProgressSink->OnProgress(nsnull, nsnull, mContentRead, PR_MAX(0, mContentLength));
        */
    }

    LOG(("nsHttpTransaction::HandleContent [this=%x count=%u read=%u mContentRead=%lld mContentLength=%lld]\n",
        this, count, *contentRead, mContentRead.mValue, mContentLength.mValue));

    // check for end-of-file
    if ((mContentRead == mContentLength) ||
        (mChunkedDecoder && mChunkedDecoder->ReachedEOF())) {
        // the transaction is done with a complete response.
        mTransactionDone = PR_TRUE;
        mResponseIsComplete = PR_TRUE;

        // report the entire response has arrived
        if (mActivityDistributor)
            mActivityDistributor->ObserveActivity(
                mChannel,
                NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
                NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_COMPLETE,
                PR_Now(),
                static_cast<PRUint64>(mContentRead.mValue),
                EmptyCString());
    }

    return NS_OK;
}
Пример #16
0
nsresult
nsMimeBaseEmitter::GenerateDateString(const char * dateString,
                                      nsACString &formattedDate,
                                      bool showDateForToday)
{
  nsresult rv = NS_OK;

  if (!mDateFormatter) {
    mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  /**
   * See if the user wants to have the date displayed in the senders
   * timezone (including the timezone offset).
   * We also evaluate the pref original_date which was introduced
   * as makeshift in bug 118899.
   */
  bool displaySenderTimezone = false;
  bool displayOriginalDate = false;

  nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIPrefBranch> dateFormatPrefs;
  rv = prefs->GetBranch("mailnews.display.", getter_AddRefs(dateFormatPrefs));
  NS_ENSURE_SUCCESS(rv, rv);

  dateFormatPrefs->GetBoolPref("date_senders_timezone", &displaySenderTimezone);
  dateFormatPrefs->GetBoolPref("original_date", &displayOriginalDate);
  // migrate old pref to date_senders_timezone
  if (displayOriginalDate && !displaySenderTimezone)
    dateFormatPrefs->SetBoolPref("date_senders_timezone", true);

  PRExplodedTime explodedMsgTime;
  // XXX Casting PRStatus to nsresult
  rv = static_cast<nsresult>(
    PR_ParseTimeStringToExplodedTime(dateString, false, &explodedMsgTime));
  /**
   * To determine the date format to use, comparison of current and message
   * time has to be made. If displaying in local time, both timestamps have
   * to be in local time. If displaying in senders time zone, leave the compare
   * time in that time zone.
   * Otherwise in TZ+0100 on 2009-03-12 a message from 2009-03-11T20:49-0700
   * would be displayed as "20:49 -0700" though it in fact is not from the
   * same day.
   */
  PRExplodedTime explodedCompTime;
  if (displaySenderTimezone)
    explodedCompTime = explodedMsgTime;
  else
    PR_ExplodeTime(PR_ImplodeTime(&explodedMsgTime), PR_LocalTimeParameters, &explodedCompTime);

  PRExplodedTime explodedCurrentTime;
  PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &explodedCurrentTime);

  // If we want short dates, check if the message is from today, and if so
  // only show the time (e.g. 3:15 pm).
  nsDateFormatSelector dateFormat = kDateFormatShort;
  if (!showDateForToday &&
      explodedCurrentTime.tm_year == explodedCompTime.tm_year &&
      explodedCurrentTime.tm_month == explodedCompTime.tm_month &&
      explodedCurrentTime.tm_mday == explodedCompTime.tm_mday)
  {
    // same day...
    dateFormat = kDateFormatNone;
  }

  nsAutoString formattedDateString;
  if (NS_SUCCEEDED(rv))
  {
    rv = mDateFormatter->FormatPRExplodedTime(nullptr /* nsILocale* locale */,
                                              dateFormat,
                                              kTimeFormatNoSeconds,
                                              &explodedCompTime,
                                              formattedDateString);

    if (NS_SUCCEEDED(rv))
    {
      if (displaySenderTimezone)
      {
        // offset of local time from UTC in minutes
        int32_t senderoffset = (explodedMsgTime.tm_params.tp_gmt_offset +
                                explodedMsgTime.tm_params.tp_dst_offset) / 60;
        // append offset to date string
        char16_t *tzstring =
          nsTextFormatter::smprintf(MOZ_UTF16(" %+05d"),
                                    (senderoffset / 60 * 100) +
                                    (senderoffset % 60));
        formattedDateString.Append(tzstring);
        nsTextFormatter::smprintf_free(tzstring);
      }

      CopyUTF16toUTF8(formattedDateString, formattedDate);
    }
  }

  return rv;
}
Пример #17
0
nsresult
nsHttpTransaction::ProcessData(char *buf, PRUint32 count, PRUint32 *countRead)
{
    nsresult rv;

    LOG(("nsHttpTransaction::ProcessData [this=%x count=%u]\n", this, count));

    *countRead = 0;

    // we may not have read all of the headers yet...
    if (!mHaveAllHeaders) {
        PRUint32 bytesConsumed = 0;

        rv = ParseHead(buf, count, &bytesConsumed);
        if (NS_FAILED(rv)) return rv;

        count -= bytesConsumed;

        // if buf has some content in it, shift bytes to top of buf.
        if (count && bytesConsumed)
            memmove(buf, buf + bytesConsumed, count);

        // report the completed response header
        if (mActivityDistributor && mResponseHead && mHaveAllHeaders) {
            nsCAutoString completeResponseHeaders;
            mResponseHead->Flatten(completeResponseHeaders, PR_FALSE);
            completeResponseHeaders.AppendLiteral("\r\n");
            mActivityDistributor->ObserveActivity(
                mChannel,
                NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
                NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_HEADER,
                PR_Now(), LL_ZERO,
                completeResponseHeaders);
        }
    }

    // even though count may be 0, we still want to call HandleContent
    // so it can complete the transaction if this is a "no-content" response.
    if (mHaveAllHeaders) {
        PRUint32 countRemaining = 0;
        //
        // buf layout:
        // 
        // +--------------------------------------+----------------+-----+
        // |              countRead               | countRemaining |     |
        // +--------------------------------------+----------------+-----+
        //
        // count          : bytes read from the socket
        // countRead      : bytes corresponding to this transaction
        // countRemaining : bytes corresponding to next pipelined transaction
        //
        // NOTE:
        // count > countRead + countRemaining <==> chunked transfer encoding
        //
        rv = HandleContent(buf, count, countRead, &countRemaining);
        if (NS_FAILED(rv)) return rv;
        // we may have read more than our share, in which case we must give
        // the excess bytes back to the connection
        if (mResponseIsComplete && countRemaining) {
            NS_ASSERTION(mConnection, "no connection");
            mConnection->PushBack(buf + *countRead, countRemaining);
        }
    }

    return NS_OK;
}
Пример #18
0
void
nsCacheEntry::TouchMetaData()
{
    mLastModified = SecondsFromPRTime(PR_Now());
    MarkMetaDataDirty();
}
Пример #19
0
static PKIX_Error *
testDefaultCertStore(PKIX_ValidateParams *valParams, char *crlDir)
{
        PKIX_PL_String *dirString = NULL;
        PKIX_CertStore *certStore = NULL;
        PKIX_ProcessingParams *procParams = NULL;
        PKIX_PL_Date *validity = NULL; 
        PKIX_List *revCheckers = NULL;
        PKIX_RevocationChecker *ocspChecker = NULL;

        PKIX_TEST_STD_VARS();

        subTest("PKIX_PL_CollectionCertStoreContext_Create");

        /* Create CollectionCertStore */

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
                (PKIX_ESCASCII, crlDir, 0, &dirString, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
                (dirString, &certStore, plContext));

        /* Create CertStore */

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams
                (valParams, &procParams, plContext));

        subTest("PKIX_ProcessingParams_AddCertStore");
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertStore
                (procParams, certStore, plContext));

        subTest("PKIX_ProcessingParams_SetRevocationEnabled");

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled
                (procParams, PKIX_TRUE, plContext));

        /* create current Date */
        PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Date_CreateFromPRTime
                (PR_Now(), &validity, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));

        /* create revChecker */
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_OcspChecker_Initialize
                (validity,
                NULL,        /* pwArg */
                NULL,        /* Use default responder */
                &ocspChecker,
                plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                (revCheckers, (PKIX_PL_Object *)ocspChecker, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers
                (procParams, revCheckers, plContext));

cleanup:

        PKIX_TEST_DECREF_AC(dirString);
        PKIX_TEST_DECREF_AC(procParams);
        PKIX_TEST_DECREF_AC(certStore);
        PKIX_TEST_DECREF_AC(revCheckers);
        PKIX_TEST_DECREF_AC(ocspChecker);

        PKIX_TEST_RETURN();

        return (0);
}
void
MediaEngineWebRTCVideoSource::SnapshotImpl() {

    MOZ_ASSERT(NS_IsMainThread());

    idl::CameraSize size;
    size.width = mCapability.width;
    size.height = mCapability.height;

    idl::CameraPosition cameraPosition;
    cameraPosition.latitude = NAN;
    cameraPosition.longitude = NAN;
    cameraPosition.altitude = NAN;
    cameraPosition.timestamp = NAN;

    mNativeCameraControl->TakePicture(size, 0, NS_LITERAL_STRING("jpeg"), cameraPosition, PR_Now() / 1000000, this, this);
}
Пример #21
0
/*
 * Find all user certificates that match the given criteria.
 *
 *      "handle" - database to search
 *      "usage" - certificate usage to match
 *      "oneCertPerName" - if set then only return the "best" cert per
 *                      name
 *      "validOnly" - only return certs that are curently valid
 *      "proto_win" - window handle passed to pkcs11
 */
CERTCertList *
CERT_FindUserCertsByUsage(CERTCertDBHandle *handle,
                          SECCertUsage usage,
                          PRBool oneCertPerName,
                          PRBool validOnly,
                          void *proto_win)
{
    CERTCertNicknames *nicknames = NULL;
    char **nnptr;
    int nn;
    CERTCertificate *cert = NULL;
    CERTCertList *certList = NULL;
    SECStatus rv;
    PRTime time;
    CERTCertListNode *node = NULL;
    CERTCertListNode *freenode = NULL;
    int n;

    time = PR_Now();

    nicknames = CERT_GetCertNicknames(handle, SEC_CERT_NICKNAMES_USER,
                                      proto_win);

    if ((nicknames == NULL) || (nicknames->numnicknames == 0)) {
        goto loser;
    }

    nnptr = nicknames->nicknames;
    nn = nicknames->numnicknames;

    while (nn > 0) {
        cert = NULL;
        /* use the pk11 call so that we pick up any certs on tokens,
         * which may require login
         */
        if (proto_win != NULL) {
            cert = PK11_FindCertFromNickname(*nnptr, proto_win);
        }

        /* Sigh, It turns out if the cert is already in the temp db, because
         * it's in the perm db, then the nickname lookup doesn't work.
         * since we already have the cert here, though, than we can just call
         * CERT_CreateSubjectCertList directly. For those cases where we didn't
         * find the cert in pkcs #11 (because we didn't have a password arg,
         * or because the nickname is for a peer, server, or CA cert, then we
         * go look the cert up.
         */
        if (cert == NULL) {
            cert = CERT_FindCertByNickname(handle, *nnptr);
        }

        if (cert != NULL) {
            /* collect certs for this nickname, sorting them into the list */
            certList = CERT_CreateSubjectCertList(certList, handle,
                                                  &cert->derSubject, time, validOnly);

            CERT_FilterCertListForUserCerts(certList);

            /* drop the extra reference */
            CERT_DestroyCertificate(cert);
        }

        nnptr++;
        nn--;
    }

    /* remove certs with incorrect usage */
    rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);

    if (rv != SECSuccess) {
        goto loser;
    }

    /* remove any extra certs for each name */
    if (oneCertPerName) {
        PRBool *flags;

        nn = nicknames->numnicknames;
        nnptr = nicknames->nicknames;

        if (!certList) {
            goto loser;
        }

        flags = (PRBool *)PORT_ZAlloc(sizeof(PRBool) * nn);
        if (flags == NULL) {
            goto loser;
        }

        node = CERT_LIST_HEAD(certList);

        /* treverse all certs in the list */
        while (!CERT_LIST_END(node, certList)) {

            /* find matching nickname index */
            for (n = 0; n < nn; n++) {
                if (CERT_MatchNickname(nnptr[n], node->cert->nickname)) {
                    /* We found a match.  If this is the first one, then
                     * set the flag and move on to the next cert.  If this
                     * is not the first one then delete it from the list.
                     */
                    if (flags[n]) {
                        /* We have already seen a cert with this nickname,
                         * so delete this one.
                         */
                        freenode = node;
                        node = CERT_LIST_NEXT(node);
                        CERT_RemoveCertListNode(freenode);
                    } else {
                        /* keep the first cert for each nickname, but set the
                         * flag so we know to delete any others with the same
                         * nickname.
                         */
                        flags[n] = PR_TRUE;
                        node = CERT_LIST_NEXT(node);
                    }
                    break;
                }
            }
            if (n == nn) {
                /* if we get here it means that we didn't find a matching
                 * nickname, which should not happen.
                 */
                PORT_Assert(0);
                node = CERT_LIST_NEXT(node);
            }
        }
        PORT_Free(flags);
    }

    goto done;

loser:
    if (certList != NULL) {
        CERT_DestroyCertList(certList);
        certList = NULL;
    }

done:
    if (nicknames != NULL) {
        CERT_FreeNicknames(nicknames);
    }

    return (certList);
}
Пример #22
0
nsresult
nsHttpTransaction::Init(PRUint8 caps,
                        nsHttpConnectionInfo *cinfo,
                        nsHttpRequestHead *requestHead,
                        nsIInputStream *requestBody,
                        PRBool requestBodyHasHeaders,
                        nsIEventTarget *target,
                        nsIInterfaceRequestor *callbacks,
                        nsITransportEventSink *eventsink,
                        nsIAsyncInputStream **responseBody)
{
    nsresult rv;

    LOG(("nsHttpTransaction::Init [this=%x caps=%x]\n", this, caps));

    NS_ASSERTION(cinfo, "ouch");
    NS_ASSERTION(requestHead, "ouch");
    NS_ASSERTION(target, "ouch");

    mActivityDistributor = do_GetService(NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID, &rv);
    if (NS_FAILED(rv)) return rv;

    PRBool activityDistributorActive;
    rv = mActivityDistributor->GetIsActive(&activityDistributorActive);
    if (NS_SUCCEEDED(rv) && activityDistributorActive) {
        // there are some observers registered at activity distributor, gather
        // nsISupports for the channel that called Init()
        mChannel = do_QueryInterface(eventsink);
        LOG(("nsHttpTransaction::Init() " \
             "mActivityDistributor is active " \
             "this=%x", this));
    } else {
        // there is no observer, so don't use it
        activityDistributorActive = PR_FALSE;
        mActivityDistributor = nsnull;
    }

    // create transport event sink proxy. it coalesces all events if and only 
    // if the activity observer is not active. when the observer is active
    // we need not to coalesce any events to get all expected notifications
    // of the transaction state, necessary for correct debugging and logging.
    rv = net_NewTransportEventSinkProxy(getter_AddRefs(mTransportSink),
                                        eventsink, target,
                                        !activityDistributorActive);
    if (NS_FAILED(rv)) return rv;

    NS_ADDREF(mConnInfo = cinfo);
    mCallbacks = callbacks;
    mConsumerTarget = target;
    mCaps = caps;

    if (requestHead->Method() == nsHttp::Head)
        mNoContent = PR_TRUE;

    // Make sure that there is "Content-Length: 0" header in the requestHead
    // in case of POST and PUT methods when there is no requestBody and
    // requestHead doesn't contain "Transfer-Encoding" header.
    //
    // RFC1945 section 7.2.2:
    //   HTTP/1.0 requests containing an entity body must include a valid
    //   Content-Length header field.
    //
    // RFC2616 section 4.4:
    //   For compatibility with HTTP/1.0 applications, HTTP/1.1 requests
    //   containing a message-body MUST include a valid Content-Length header
    //   field unless the server is known to be HTTP/1.1 compliant.
    if ((requestHead->Method() == nsHttp::Post || requestHead->Method() == nsHttp::Put) &&
        !requestBody && !requestHead->PeekHeader(nsHttp::Transfer_Encoding)) {
        requestHead->SetHeader(nsHttp::Content_Length, NS_LITERAL_CSTRING("0"));
    }

    // grab a weak reference to the request head
    mRequestHead = requestHead;

    // make sure we eliminate any proxy specific headers from 
    // the request if we are talking HTTPS via a SSL tunnel.
    PRBool pruneProxyHeaders = cinfo->UsingSSL() &&
                               cinfo->UsingHttpProxy();
    mReqHeaderBuf.Truncate();
    requestHead->Flatten(mReqHeaderBuf, pruneProxyHeaders);

#if defined(PR_LOGGING)
    if (LOG3_ENABLED()) {
        LOG3(("http request [\n"));
        LogHeaders(mReqHeaderBuf.get());
        LOG3(("]\n"));
    }
#endif

    // If the request body does not include headers or if there is no request
    // body, then we must add the header/body separator manually.
    if (!requestBodyHasHeaders || !requestBody)
        mReqHeaderBuf.AppendLiteral("\r\n");

    // report the request header
    if (mActivityDistributor)
        mActivityDistributor->ObserveActivity(
            mChannel,
            NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
            NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER,
            PR_Now(), LL_ZERO,
            mReqHeaderBuf);

    // Create a string stream for the request header buf (the stream holds
    // a non-owning reference to the request header data, so we MUST keep
    // mReqHeaderBuf around).
    nsCOMPtr<nsIInputStream> headers;
    rv = NS_NewByteInputStream(getter_AddRefs(headers),
                               mReqHeaderBuf.get(),
                               mReqHeaderBuf.Length());
    if (NS_FAILED(rv)) return rv;

    if (requestBody) {
        mHasRequestBody = PR_TRUE;

        // wrap the headers and request body in a multiplexed input stream.
        nsCOMPtr<nsIMultiplexInputStream> multi =
            do_CreateInstance(kMultiplexInputStream, &rv);
        if (NS_FAILED(rv)) return rv;

        rv = multi->AppendStream(headers);
        if (NS_FAILED(rv)) return rv;

        rv = multi->AppendStream(requestBody);
        if (NS_FAILED(rv)) return rv;

        // wrap the multiplexed input stream with a buffered input stream, so
        // that we write data in the largest chunks possible.  this is actually
        // necessary to workaround some common server bugs (see bug 137155).
        rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream), multi,
                                       NET_DEFAULT_SEGMENT_SIZE);
        if (NS_FAILED(rv)) return rv;
    }
    else
        mRequestStream = headers;

    rv = mRequestStream->Available(&mRequestSize);
    if (NS_FAILED(rv)) return rv;

    // create pipe for response stream
    rv = NS_NewPipe2(getter_AddRefs(mPipeIn),
                     getter_AddRefs(mPipeOut),
                     PR_TRUE, PR_TRUE,
                     NS_HTTP_SEGMENT_SIZE,
                     NS_HTTP_SEGMENT_COUNT,
                     nsIOService::gBufferCache);
    if (NS_FAILED(rv)) return rv;

    NS_ADDREF(*responseBody = mPipeIn);
    return NS_OK;
}
Пример #23
0
/*
 * Create a DER-encoded OCSP request (for the certificate whose nickname is
 * "cert_name"), then get and dump a corresponding response.  The responder
 * location is either specified explicitly (as "responder_url") or found
 * via the AuthorityInfoAccess URL in the cert.
 */
static SECStatus
dump_response (FILE *out_file, CERTCertDBHandle *handle, CERTCertificate *cert,
	       const char *responder_url)
{
    CERTCertList *certs = NULL;
    CERTCertificate *myCert = NULL;
    char *loc = NULL;
    int64 now = PR_Now();
    SECItem *response = NULL;
    SECStatus rv = SECFailure;
    PRBool includeServiceLocator;

    if (handle == NULL || cert == NULL)
	return rv;

    myCert = CERT_DupCertificate(cert);
    if (myCert == NULL)
        goto loser;

    if (responder_url != NULL) {
	loc = (char *) responder_url;
	includeServiceLocator = PR_TRUE;
    } else {
	loc = CERT_GetOCSPAuthorityInfoAccessLocation (cert);
	if (loc == NULL)
	    goto loser;
	includeServiceLocator = PR_FALSE;
    }

    /*
     * We need to create a list of one.
     */
    certs = CERT_NewCertList();
    if (certs == NULL)
	goto loser;

    if (CERT_AddCertToListTail (certs, myCert) != SECSuccess)
	goto loser;

    /*
     * Now that cert is included in the list, we need to be careful
     * that we do not try to destroy it twice.  This will prevent that.
     */
    myCert = NULL;

    response = CERT_GetEncodedOCSPResponse (NULL, certs, loc, now,
					    includeServiceLocator,
					    NULL, NULL, NULL);
    if (response == NULL)
	goto loser;

    MAKE_FILE_BINARY(out_file);
    if (fwrite (response->data, response->len, 1, out_file) != 1)
	goto loser;

    rv = SECSuccess;

loser:
    if (response != NULL)
	SECITEM_FreeItem (response, PR_TRUE);
    if (certs != NULL)
	CERT_DestroyCertList (certs);
    if (myCert != NULL)
	CERT_DestroyCertificate(myCert);
    if (loc != NULL && loc != responder_url)
	PORT_Free (loc);

    return rv;
}
Пример #24
0
void
nsHttpTransaction::OnTransportStatus(nsresult status, PRUint64 progress)
{
    LOG(("nsHttpTransaction::OnSocketStatus [this=%x status=%x progress=%llu]\n",
        this, status, progress));

    if (!mTransportSink)
        return;
    
    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");

    // Need to do this before the STATUS_RECEIVING_FROM check below, to make
    // sure that the activity distributor gets told about all status events.
    if (mActivityDistributor) {
        // upon STATUS_WAITING_FOR; report request body sent
        if ((mHasRequestBody) &&
            (status == nsISocketTransport::STATUS_WAITING_FOR))
            mActivityDistributor->ObserveActivity(
                mChannel,
                NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
                NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_BODY_SENT,
                PR_Now(), LL_ZERO, EmptyCString());

        // report the status and progress
        mActivityDistributor->ObserveActivity(
            mChannel,
            NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT,
            static_cast<PRUint32>(status),
            PR_Now(),
            progress,
            EmptyCString());
    }

    // nsHttpChannel synthesizes progress events in OnDataAvailable
    if (status == nsISocketTransport::STATUS_RECEIVING_FROM)
        return;

    PRUint64 progressMax;

    if (status == nsISocketTransport::STATUS_SENDING_TO) {
        // suppress progress when only writing request headers
        if (!mHasRequestBody)
            return;

        nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mRequestStream);
        NS_ASSERTION(seekable, "Request stream isn't seekable?!?");

        PRInt64 prog = 0;
        seekable->Tell(&prog);
        progress = prog;

        // when uploading, we include the request headers in the progress
        // notifications.
        progressMax = mRequestSize; // XXX mRequestSize is 32-bit!
    }
    else {
        progress = LL_ZERO;
        progressMax = 0;
    }

    mTransportSink->OnTransportStatus(nsnull, status, progress, progressMax);
}
Пример #25
0
nsresult
nsDOMWorkerTimeout::Init(JSContext* aCx, PRUint32 aArgc, jsval* aArgv,
                         PRBool aIsInterval)
{
  NS_ASSERTION(aCx, "Null pointer!");
  NS_ASSERTION(aArgv, "Null pointer!");

  JSAutoRequest ar(aCx);

  if (!aArgc) {
    JS_ReportError(aCx, "Function %s requires at least 1 parameter",
                   aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
    return NS_ERROR_INVALID_ARG;
  }

  PRUint32 interval;
  if (aArgc > 1) {
    if (!JS_ValueToECMAUint32(aCx, aArgv[1], (uint32*)&interval)) {
      JS_ReportError(aCx, "Second argument to %s must be a millisecond value",
                     aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
      return NS_ERROR_INVALID_ARG;
    }
  }
  else {
    // If no interval was specified, treat this like a timeout, to avoid
    // setting an interval of 0 milliseconds.
    interval = 0;
    aIsInterval = PR_FALSE;
  }

  mInterval = interval;

  mIsInterval = aIsInterval;

  mTargetTime = PR_Now() + interval * (PRTime)PR_USEC_PER_MSEC;

  nsresult rv;
  switch (JS_TypeOfValue(aCx, aArgv[0])) {
    case JSTYPE_FUNCTION:
      mCallback = new FunctionCallback(aArgc, aArgv, &rv);
      NS_ENSURE_TRUE(mCallback, NS_ERROR_OUT_OF_MEMORY);
      NS_ENSURE_SUCCESS(rv, rv);

      break;

    case JSTYPE_STRING:
    case JSTYPE_OBJECT:
      mCallback = new ExpressionCallback(aArgc, aArgv, aCx, &rv);
      NS_ENSURE_TRUE(mCallback, NS_ERROR_OUT_OF_MEMORY);
      NS_ENSURE_SUCCESS(rv, rv);
      break;

    default:
      JS_ReportError(aCx, "useless %s call (missing quotes around argument?)",
                     aIsInterval ? kSetIntervalStr : kSetTimeoutStr);

      // Return an error that nsGlobalWindow can recognize and turn into NS_OK.
      return NS_ERROR_INVALID_ARG;
  }

  nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  nsIEventTarget* target =
    static_cast<nsIEventTarget*>(nsDOMThreadService::get());

  rv = timer->SetTarget(target);
  NS_ENSURE_SUCCESS(rv, rv);

  mTimer.swap(timer);
  return NS_OK;
}
Пример #26
0
void
nsHttpTransaction::Close(nsresult reason)
{
    LOG(("nsHttpTransaction::Close [this=%x reason=%x]\n", this, reason));

    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");

    if (mClosed) {
        LOG(("  already closed\n"));
        return;
    }

    if (mActivityDistributor) {
        // report the reponse is complete if not already reported
        if (!mResponseIsComplete)
            mActivityDistributor->ObserveActivity(
                mChannel,
                NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
                NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_COMPLETE,
                PR_Now(),
                static_cast<PRUint64>(mContentRead.mValue),
                EmptyCString());

        // report that this transaction is closing
        mActivityDistributor->ObserveActivity(
            mChannel,
            NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
            NS_HTTP_ACTIVITY_SUBTYPE_TRANSACTION_CLOSE,
            PR_Now(), LL_ZERO, EmptyCString());
    }

    // we must no longer reference the connection!  find out if the 
    // connection was being reused before letting it go.
    PRBool connReused = PR_FALSE;
    if (mConnection)
        connReused = mConnection->IsReused();
    mConnected = PR_FALSE;

    //
    // if the connection was reset or closed before we wrote any part of the
    // request or if we wrote the request but didn't receive any part of the
    // response and the connection was being reused, then we can (and really
    // should) assume that we wrote to a stale connection and we must therefore
    // repeat the request over a new connection.
    //
    // NOTE: the conditions under which we will automatically retry the HTTP
    // request have to be carefully selected to avoid duplication of the
    // request from the point-of-view of the server.  such duplication could
    // have dire consequences including repeated purchases, etc.
    //
    // NOTE: because of the way SSL proxy CONNECT is implemented, it is
    // possible that the transaction may have received data without having
    // sent any data.  for this reason, mSendData == FALSE does not imply
    // mReceivedData == FALSE.  (see bug 203057 for more info.)
    //
    if (reason == NS_ERROR_NET_RESET || reason == NS_OK) {
        if (!mReceivedData && (!mSentData || connReused)) {
            // if restarting fails, then we must proceed to close the pipe,
            // which will notify the channel that the transaction failed.
            if (NS_SUCCEEDED(Restart()))
                return;
        }
    }

    PRBool relConn = PR_TRUE;
    if (NS_SUCCEEDED(reason)) {
        // the server has not sent the final \r\n terminating the header
        // section, and there may still be a header line unparsed.  let's make
        // sure we parse the remaining header line, and then hopefully, the
        // response will be usable (see bug 88792).  related to that, we may
        // also have an empty response containing no headers.  we should treat
        // that as an empty HTTP/0.9 response (see bug 300613).
        if (!mHaveAllHeaders) {
            char data = '\n';
            PRUint32 unused;
            ParseHead(&data, 1, &unused);
        }

        // honor the sticky connection flag...
        if (mCaps & NS_HTTP_STICKY_CONNECTION)
            relConn = PR_FALSE;
    }
    if (relConn && mConnection)
        NS_RELEASE(mConnection);

    mStatus = reason;
    mTransactionDone = PR_TRUE; // forcibly flag the transaction as complete
    mClosed = PR_TRUE;

    // release some resources that we no longer need
    mRequestStream = nsnull;
    mReqHeaderBuf.Truncate();
    mLineBuf.Truncate();
    if (mChunkedDecoder) {
        delete mChunkedDecoder;
        mChunkedDecoder = nsnull;
    }

    // closing this pipe triggers the channel's OnStopRequest method.
    mPipeOut->CloseWithStatus(reason);
}
Пример #27
0
void
LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion)
{
  PROFILER_LABEL("LayerManagerComposite", "Render",
    js::ProfileEntry::Category::GRAPHICS);

  if (mDestroyed) {
    NS_WARNING("Call on destroyed layer manager");
    return;
  }

  // At this time, it doesn't really matter if these preferences change
  // during the execution of the function; we should be safe in all
  // permutations. However, may as well just get the values onces and
  // then use them, just in case the consistency becomes important in
  // the future.
  bool invertVal = gfxPrefs::LayersEffectInvert();
  bool grayscaleVal = gfxPrefs::LayersEffectGrayscale();
  float contrastVal = gfxPrefs::LayersEffectContrast();
  bool haveLayerEffects = (invertVal || grayscaleVal || contrastVal != 0.0);

  // Set LayerScope begin/end frame
  LayerScopeAutoFrame frame(PR_Now());

  // Dump to console
  if (gfxPrefs::LayersDump()) {
    this->Dump();
  } else if (profiler_feature_active("layersdump")) {
    std::stringstream ss;
    Dump(ss);
    profiler_log(ss.str().c_str());
  }

  // Dump to LayerScope Viewer
  if (LayerScope::CheckSendable()) {
    // Create a LayersPacket, dump Layers into it and transfer the
    // packet('s ownership) to LayerScope.
    auto packet = MakeUnique<layerscope::Packet>();
    layerscope::LayersPacket* layersPacket = packet->mutable_layers();
    this->Dump(layersPacket);
    LayerScope::SendLayerDump(Move(packet));
  }

  /** Our more efficient but less powerful alter ego, if one is available. */
  RefPtr<Composer2D> composer2D;
  composer2D = mCompositor->GetWidget()->GetComposer2D();

  // We can't use composert2D if we have layer effects
  if (!mTarget && !haveLayerEffects &&
      gfxPrefs::Composer2DCompositionEnabled() &&
      composer2D && composer2D->HasHwc() && composer2D->TryRenderWithHwc(mRoot,
          mCompositor->GetWidget(), mGeometryChanged))
  {
    LayerScope::SetHWComposed();
    if (mFPS) {
      double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
      if (gfxPrefs::LayersDrawFPS()) {
        printf_stderr("HWComposer: FPS is %g\n", fps);
      }
    }
    mCompositor->EndFrameForExternalComposition(Matrix());
    mLastFrameMissedHWC = false;
    return;
  } else if (!mTarget && !haveLayerEffects) {
    mLastFrameMissedHWC = !!composer2D;
  }

  {
    PROFILER_LABEL("LayerManagerComposite", "PreRender",
      js::ProfileEntry::Category::GRAPHICS);

    if (!mCompositor->GetWidget()->PreRender(this)) {
      return;
    }
  }

  ParentLayerIntRect clipRect;
  Rect bounds(mRenderBounds.x, mRenderBounds.y, mRenderBounds.width, mRenderBounds.height);
  Rect actualBounds;

  CompositorBench(mCompositor, bounds);

  if (mRoot->GetClipRect()) {
    clipRect = *mRoot->GetClipRect();
    Rect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
    mCompositor->BeginFrame(aInvalidRegion, &rect, bounds, nullptr, &actualBounds);
  } else {
    gfx::Rect rect;
    mCompositor->BeginFrame(aInvalidRegion, nullptr, bounds, &rect, &actualBounds);
    clipRect = ParentLayerIntRect(rect.x, rect.y, rect.width, rect.height);
  }

  if (actualBounds.IsEmpty()) {
    mCompositor->GetWidget()->PostRender(this);
    return;
  }

  // Allow widget to render a custom background.
  mCompositor->GetWidget()->DrawWindowUnderlay(this, IntRect(actualBounds.x,
                                                               actualBounds.y,
                                                               actualBounds.width,
                                                               actualBounds.height));

  RefPtr<CompositingRenderTarget> previousTarget;
  if (haveLayerEffects) {
    previousTarget = PushGroupForLayerEffects();
  } else {
    mTwoPassTmpTarget = nullptr;
  }

  // Render our layers.
  RootLayer()->Prepare(ViewAs<RenderTargetPixel>(clipRect, PixelCastJustification::RenderTargetIsParentLayerForRoot));
  RootLayer()->RenderLayer(ParentLayerIntRect::ToUntyped(clipRect));

  if (!mRegionToClear.IsEmpty()) {
    nsIntRegionRectIterator iter(mRegionToClear);
    const IntRect *r;
    while ((r = iter.Next())) {
      mCompositor->ClearRect(Rect(r->x, r->y, r->width, r->height));
    }
  }

  if (mTwoPassTmpTarget) {
    MOZ_ASSERT(haveLayerEffects);
    PopGroupForLayerEffects(previousTarget, ParentLayerIntRect::ToUntyped(clipRect),
                            grayscaleVal, invertVal, contrastVal);
  }

  // Allow widget to render a custom foreground.
  mCompositor->GetWidget()->DrawWindowOverlay(this, IntRect(actualBounds.x,
                                                              actualBounds.y,
                                                              actualBounds.width,
                                                              actualBounds.height));

  // Debugging
  RenderDebugOverlay(actualBounds);

  {
    PROFILER_LABEL("LayerManagerComposite", "EndFrame",
      js::ProfileEntry::Category::GRAPHICS);

    mCompositor->EndFrame();
    mCompositor->SetDispAcquireFence(mRoot,
                                     mCompositor->GetWidget()); // Call after EndFrame()
  }

  if (composer2D) {
    composer2D->Render(mCompositor->GetWidget());
  }

  mCompositor->GetWidget()->PostRender(this);

  RecordFrame();
}
Пример #28
0
nsresult
nsHttpTransaction::ParseHead(char *buf,
                             PRUint32 count,
                             PRUint32 *countRead)
{
    nsresult rv;
    PRUint32 len;
    char *eol;

    LOG(("nsHttpTransaction::ParseHead [count=%u]\n", count));

    *countRead = 0;

    NS_PRECONDITION(!mHaveAllHeaders, "oops");
        
    // allocate the response head object if necessary
    if (!mResponseHead) {
        mResponseHead = new nsHttpResponseHead();
        if (!mResponseHead)
            return NS_ERROR_OUT_OF_MEMORY;

        // report that we have a least some of the response
        if (mActivityDistributor)
            mActivityDistributor->ObserveActivity(
                mChannel,
                NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
                NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_START,
                PR_Now(), LL_ZERO, EmptyCString());
    }

    // if we don't have a status line and the line buf is empty, then
    // this must be the first time we've been called.
    if (!mHaveStatusLine && mLineBuf.IsEmpty()) {
        // tolerate some junk before the status line
        char *p = LocateHttpStart(buf, PR_MIN(count, 8));
        if (!p) {
            // Treat any 0.9 style response of a put as a failure.
            if (mRequestHead->Method() == nsHttp::Put)
                return NS_ERROR_ABORT;

            mResponseHead->ParseStatusLine("");
            mHaveStatusLine = PR_TRUE;
            mHaveAllHeaders = PR_TRUE;
            return NS_OK;
        }
        if (p > buf) {
            // skip over the junk
            *countRead = p - buf;
            buf = p;
        }
    }
    // otherwise we can assume that we don't have a HTTP/0.9 response.

    while ((eol = static_cast<char *>(memchr(buf, '\n', count - *countRead))) != nsnull) {
        // found line in range [buf:eol]
        len = eol - buf + 1;

        *countRead += len;

        // actually, the line is in the range [buf:eol-1]
        if ((eol > buf) && (*(eol-1) == '\r'))
            len--;

        buf[len-1] = '\n';
        rv = ParseLineSegment(buf, len);
        if (NS_FAILED(rv))
            return rv;

        if (mHaveAllHeaders)
            return NS_OK;

        // skip over line
        buf = eol + 1;
    }

    // do something about a partial header line
    if (!mHaveAllHeaders && (len = count - *countRead)) {
        *countRead = count;
        // ignore a trailing carriage return, and don't bother calling
        // ParseLineSegment if buf only contains a carriage return.
        if ((buf[len-1] == '\r') && (--len == 0))
            return NS_OK;
        rv = ParseLineSegment(buf, len);
        if (NS_FAILED(rv))
            return rv;
    }
    return NS_OK;
}
Пример #29
0
/* Called by clients.
 *
 *      struct {
 *         opaque identity<0..2^16-1>;
 *         uint32 obfuscated_ticket_age;
 *     } PskIdentity;
 *
 *     opaque PskBinderEntry<32..255>;
 *
 *     struct {
 *         select (Handshake.msg_type) {
 *             case client_hello:
 *                 PskIdentity identities<6..2^16-1>;
 *                 PskBinderEntry binders<33..2^16-1>;
 *
 *             case server_hello:
 *                 uint16 selected_identity;
 *         };
 *
 *     } PreSharedKeyExtension;

 * Presently the only way to get a PSK is by resumption, so this is
 * really a ticket label and there will be at most one.
 */
PRInt32
tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
                                PRBool append,
                                PRUint32 maxBytes)
{
    PRInt32 extension_length;
    PRInt32 identities_length;
    PRInt32 binders_length;
    NewSessionTicket *session_ticket;

    /* We only set statelessResume on the client in TLS 1.3 code. */
    if (!ss->statelessResume)
        return 0;

    PORT_Assert(ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3);

    /* The length computations are simplified by the fact that there
     * is just one ticket at most. */
    session_ticket = &ss->sec.ci.sid->u.ssl3.locked.sessionTicket;
    identities_length =
        2 +                              /* vector length */
        2 + session_ticket->ticket.len + /* identity length + ticket len */
        4;                               /* obfuscated_ticket_age */
    binders_length =
        2 + /* vector length */
        1 + tls13_GetHashSizeForHash(
                tls13_GetHashForCipherSuite(ss->sec.ci.sid->u.ssl3.cipherSuite));
    extension_length =
        2 + 2 + /* Type + length */
        identities_length + binders_length;

    if (maxBytes < (PRUint32)extension_length) {
        PORT_Assert(0);
        return 0;
    }

    if (append) {
        SECStatus rv;
        PRTime age;
        unsigned int prefixLength;
        PRUint8 binder[TLS13_MAX_FINISHED_SIZE];
        unsigned int binderLen;

        /* extension_type */
        rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_pre_shared_key_xtn, 2);
        if (rv != SECSuccess)
            goto loser;
        rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2);
        if (rv != SECSuccess)
            goto loser;
        rv = ssl3_ExtAppendHandshakeNumber(ss, identities_length - 2, 2);
        if (rv != SECSuccess)
            goto loser;
        rv = ssl3_ExtAppendHandshakeVariable(ss, session_ticket->ticket.data,
                                             session_ticket->ticket.len, 2);
        if (rv != SECSuccess)
            goto loser;

        /* Obfuscated age. */
        age = PR_Now() - session_ticket->received_timestamp;
        age /= PR_USEC_PER_MSEC;
        age += session_ticket->ticket_age_add;
        rv = ssl3_ExtAppendHandshakeNumber(ss, age, 4);
        if (rv != SECSuccess)
            goto loser;

        /* Now the binders. */
        prefixLength = ss->ssl3.hs.messages.len;
        rv = tls13_ComputePskBinder(CONST_CAST(sslSocket, ss), PR_TRUE,
                                    prefixLength, binder, &binderLen,
                                    sizeof(binder));
        if (rv != SECSuccess)
            goto loser;
        PORT_Assert(binderLen == tls13_GetHashSize(ss));
        rv = ssl3_ExtAppendHandshakeNumber(ss, binders_length - 2, 2);
        if (rv != SECSuccess)
            goto loser;
        rv = ssl3_ExtAppendHandshakeVariable(ss,
                                             binder, binderLen, 1);
        if (rv != SECSuccess)
            goto loser;

        PRINT_BUF(50, (ss, "Sending PreSharedKey value",
                       session_ticket->ticket.data,
                       session_ticket->ticket.len));

        xtnData->sentSessionTicketInClientHello = PR_TRUE;
        xtnData->advertised[xtnData->numAdvertised++] =
            ssl_tls13_pre_shared_key_xtn;
    }
    return extension_length;

loser:
    xtnData->ticketTimestampVerified = PR_FALSE;
    return -1;
}
Пример #30
0
NS_IMETHODIMP
nsAppStartup::Quit(PRUint32 aMode)
{
  PRUint32 ferocity = (aMode & 0xF);

  // Quit the application. We will asynchronously call the appshell's
  // Exit() method via nsAppExitEvent to allow one last pass
  // through any events in the queue. This guarantees a tidy cleanup.
  nsresult rv = NS_OK;
  PRBool postedExitEvent = PR_FALSE;

  if (mShuttingDown)
    return NS_OK;

  // If we're considering quitting, we will only do so if:
  if (ferocity == eConsiderQuit) {
    if (mConsiderQuitStopper == 0) {
      // there are no windows...
      ferocity = eAttemptQuit;
    }
#ifdef XP_MACOSX
    else if (mConsiderQuitStopper == 1) {
      // ... or there is only a hiddenWindow left, and it's useless:
      nsCOMPtr<nsIAppShellService> appShell
        (do_GetService(NS_APPSHELLSERVICE_CONTRACTID));

      // Failure shouldn't be fatal, but will abort quit attempt:
      if (!appShell)
        return NS_OK;

      PRBool usefulHiddenWindow;
      appShell->GetApplicationProvidedHiddenWindow(&usefulHiddenWindow);
      nsCOMPtr<nsIXULWindow> hiddenWindow;
      appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
      // If the one window is useful, we won't quit:
      if (!hiddenWindow || usefulHiddenWindow)
        return NS_OK;

      ferocity = eAttemptQuit;
    }
#endif
  }

  nsCOMPtr<nsIObserverService> obsService;
  if (ferocity == eAttemptQuit || ferocity == eForceQuit) {

    nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
    nsCOMPtr<nsIWindowMediator> mediator (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
    if (mediator) {
      mediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
      if (windowEnumerator) {
        PRBool more;
        while (windowEnumerator->HasMoreElements(&more), more) {
          nsCOMPtr<nsISupports> window;
          windowEnumerator->GetNext(getter_AddRefs(window));
          nsCOMPtr<nsPIDOMWindow> domWindow(do_QueryInterface(window));
          if (domWindow) {
            if (!domWindow->CanClose())
              return NS_OK;
          }
        }
      }
    }

    mShuttingDown = PR_TRUE;
    if (!mRestart) {
      mRestart = (aMode & eRestart) != 0;
      gRestartMode = (aMode & 0xF0);
    }

    if (mRestart) {
      // Firefox-restarts reuse the process. Process start-time isn't a useful indicator of startup time
      PR_SetEnv(PR_smprintf("MOZ_APP_RESTART=%lld", (PRInt64) PR_Now() / PR_USEC_PER_MSEC));
    }

    obsService = mozilla::services::GetObserverService();

    if (!mAttemptingQuit) {
      mAttemptingQuit = PR_TRUE;
#ifdef XP_MACOSX
      // now even the Mac wants to quit when the last window is closed
      ExitLastWindowClosingSurvivalArea();
#endif
      if (obsService)
        obsService->NotifyObservers(nsnull, "quit-application-granted", nsnull);
    }

    /* Enumerate through each open window and close it. It's important to do
       this before we forcequit because this can control whether we really quit
       at all. e.g. if one of these windows has an unload handler that
       opens a new window. Ugh. I know. */
    CloseAllWindows();

    if (mediator) {
      if (ferocity == eAttemptQuit) {
        ferocity = eForceQuit; // assume success

        /* Were we able to immediately close all windows? if not, eAttemptQuit
           failed. This could happen for a variety of reasons; in fact it's
           very likely. Perhaps we're being called from JS and the window->Close
           method hasn't had a chance to wrap itself up yet. So give up.
           We'll return (with eConsiderQuit) as the remaining windows are
           closed. */
        mediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
        if (windowEnumerator) {
          PRBool more;
          while (windowEnumerator->HasMoreElements(&more), more) {
            /* we can't quit immediately. we'll try again as the last window
               finally closes. */
            ferocity = eAttemptQuit;
            nsCOMPtr<nsISupports> window;
            windowEnumerator->GetNext(getter_AddRefs(window));
            nsCOMPtr<nsIDOMWindowInternal> domWindow(do_QueryInterface(window));
            if (domWindow) {
              PRBool closed = PR_FALSE;
              domWindow->GetClosed(&closed);
              if (!closed) {
                rv = NS_ERROR_FAILURE;
                break;
              }
            }
          }
        }
      }
    }
  }

  if (ferocity == eForceQuit) {
    // do it!

    // No chance of the shutdown being cancelled from here on; tell people
    // we're shutting down for sure while all services are still available.
    if (obsService) {
      NS_NAMED_LITERAL_STRING(shutdownStr, "shutdown");
      NS_NAMED_LITERAL_STRING(restartStr, "restart");
      obsService->NotifyObservers(nsnull, "quit-application",
        mRestart ? restartStr.get() : shutdownStr.get());
    }

    if (!mRunning) {
      postedExitEvent = PR_TRUE;
    }
    else {
      // no matter what, make sure we send the exit event.  If
      // worst comes to worst, we'll do a leaky shutdown but we WILL
      // shut down. Well, assuming that all *this* stuff works ;-).
      nsCOMPtr<nsIRunnable> event = new nsAppExitEvent(this);
      rv = NS_DispatchToCurrentThread(event);
      if (NS_SUCCEEDED(rv)) {
        postedExitEvent = PR_TRUE;
      }
      else {
        NS_WARNING("failed to dispatch nsAppExitEvent");
      }
    }
  }

  // turn off the reentrancy check flag, but not if we have
  // more asynchronous work to do still.
  if (!postedExitEvent)
    mShuttingDown = PR_FALSE;
  return rv;
}