NS_IMETHODIMP nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aContext) { nsresult rv = NS_OK; if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) { NS_ASSERTION(mRequests.Count() == 0, "Only our initial stream should be unknown!"); TrackRequest(request); } if (mHaveFiredOnStartRequest) { return NS_OK; } mHaveFiredOnStartRequest = PR_TRUE; nsCOMPtr<nsIChannel> channel = do_QueryInterface(request); NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE); // deal with 404 (Not Found) HTTP response, // just return, this causes the request to be ignored. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (httpChannel) { PRUint32 responseCode = 0; rv = httpChannel->GetResponseStatus(&responseCode); if (NS_FAILED(rv)) { // NPP_Notify() will be called from OnStopRequest // in nsNPAPIPluginStreamListener::CleanUpStream // return error will cancel this request // ...and we also need to tell the plugin that mRequestFailed = PR_TRUE; return NS_ERROR_FAILURE; } if (responseCode > 206) { // not normal PRBool bWantsAllNetworkStreams = PR_FALSE; mPluginInstance->GetValueFromPlugin(NPPVpluginWantsAllNetworkStreams, (void*)&bWantsAllNetworkStreams); if (!bWantsAllNetworkStreams) { mRequestFailed = PR_TRUE; return NS_ERROR_FAILURE; } } } // do a little sanity check to make sure our frame isn't gone // by getting the tag type and checking for an error, we can determine if // the frame is gone if (mOwner) { nsCOMPtr<nsIPluginTagInfo> pti = do_QueryInterface(mOwner); NS_ENSURE_TRUE(pti, NS_ERROR_FAILURE); nsPluginTagType tagType; if (NS_FAILED(pti->GetTagType(&tagType))) return NS_ERROR_FAILURE; // something happened to our object frame, so bail! } // Get the notification callbacks from the channel and save it as // week ref we'll use it in nsPluginStreamInfo::RequestRead() when // we'll create channel for byte range request. nsCOMPtr<nsIInterfaceRequestor> callbacks; channel->GetNotificationCallbacks(getter_AddRefs(callbacks)); if (callbacks) mWeakPtrChannelCallbacks = do_GetWeakReference(callbacks); nsCOMPtr<nsILoadGroup> loadGroup; channel->GetLoadGroup(getter_AddRefs(loadGroup)); if (loadGroup) mWeakPtrChannelLoadGroup = do_GetWeakReference(loadGroup); PRInt32 length; rv = channel->GetContentLength(&length); // it's possible for the server to not send a Content-Length. // we should still work in this case. if (NS_FAILED(rv) || length == -1) { // check out if this is file channel nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(channel); if (fileChannel) { // file does not exist mRequestFailed = PR_TRUE; return NS_ERROR_FAILURE; } mLength = 0; } else { mLength = length; } nsCAutoString aContentType; // XXX but we already got the type above! rv = channel->GetContentType(aContentType); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIURI> aURL; rv = channel->GetURI(getter_AddRefs(aURL)); if (NS_FAILED(rv)) return rv; aURL->GetSpec(mURLSpec); if (!aContentType.IsEmpty()) mContentType = aContentType; #ifdef PLUGIN_LOGGING PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NOISY, ("nsPluginStreamListenerPeer::OnStartRequest this=%p request=%p mime=%s, url=%s\n", this, request, aContentType.get(), mURLSpec.get())); PR_LogFlush(); #endif NPWindow* window = nsnull; // if we don't have an nsNPAPIPluginInstance (mPluginInstance), it means // we weren't able to load a plugin previously because we // didn't have the mimetype. Now that we do (aContentType), // we'll try again with SetUpPluginInstance() // which is called by InstantiateEmbeddedPlugin() // NOTE: we don't want to try again if we didn't get the MIME type this time if (!mPluginInstance && mOwner && !aContentType.IsEmpty()) { nsCOMPtr<nsIPluginInstance> pluginInstCOMPtr; mOwner->GetInstance(getter_AddRefs(pluginInstCOMPtr)); mPluginInstance = static_cast<nsNPAPIPluginInstance*>(pluginInstCOMPtr.get()); mOwner->GetWindow(window); if (!mPluginInstance && window) { nsRefPtr<nsPluginHost> pluginHost = dont_AddRef(nsPluginHost::GetInst()); // determine if we need to try embedded again. FullPage takes a different code path PRInt32 mode; mOwner->GetMode(&mode); if (mode == NP_EMBED) { // Make sure to not allow new streams to be opened here; we've // already got a stream for this data; we just need a properly // set up plugin instance. rv = pluginHost->DoInstantiateEmbeddedPlugin(aContentType.get(), aURL, mOwner, PR_FALSE); } else { rv = pluginHost->SetUpPluginInstance(aContentType.get(), aURL, mOwner); } if (NS_OK == rv) { mOwner->GetInstance(getter_AddRefs(pluginInstCOMPtr)); mPluginInstance = static_cast<nsNPAPIPluginInstance*>(pluginInstCOMPtr.get()); if (mPluginInstance) { mPluginInstance->Start(); mOwner->CreateWidget(); // If we've got a native window, the let the plugin know about it. nsCOMPtr<nsIPluginInstanceOwner_MOZILLA_2_0_BRANCH> owner = do_QueryInterface(mOwner); if (owner) owner->SetWindow(); } } } } // Set up the stream listener... rv = SetUpStreamListener(request, aURL); if (NS_FAILED(rv)) return rv; return rv; }
NS_IMETHODIMP nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aContext) { nsresult rv = NS_OK; AUTO_PROFILER_LABEL("nsPluginStreamListenerPeer::OnStartRequest", OTHER); if (mRequests.IndexOfObject(request) == -1) { NS_ASSERTION(mRequests.Count() == 0, "Only our initial stream should be unknown!"); TrackRequest(request); } if (mHaveFiredOnStartRequest) { return NS_OK; } mHaveFiredOnStartRequest = true; nsCOMPtr<nsIChannel> channel = do_QueryInterface(request); NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE); // deal with 404 (Not Found) HTTP response, // just return, this causes the request to be ignored. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (httpChannel) { uint32_t responseCode = 0; rv = httpChannel->GetResponseStatus(&responseCode); if (NS_FAILED(rv)) { // NPP_Notify() will be called from OnStopRequest // in nsNPAPIPluginStreamListener::CleanUpStream // return error will cancel this request // ...and we also need to tell the plugin that mRequestFailed = true; return NS_ERROR_FAILURE; } if (responseCode > 206) { // not normal uint32_t wantsAllNetworkStreams = 0; // We don't always have an instance here already, but if we do, check // to see if it wants all streams. if (mPluginInstance) { rv = mPluginInstance->GetValueFromPlugin(NPPVpluginWantsAllNetworkStreams, &wantsAllNetworkStreams); // If the call returned an error code make sure we still use our default value. if (NS_FAILED(rv)) { wantsAllNetworkStreams = 0; } } if (!wantsAllNetworkStreams) { mRequestFailed = true; return NS_ERROR_FAILURE; } } } nsAutoCString contentType; rv = channel->GetContentType(contentType); if (NS_FAILED(rv)) return rv; // Check ShouldProcess with content policy RefPtr<nsPluginInstanceOwner> owner; if (mPluginInstance) { owner = mPluginInstance->GetOwner(); } nsCOMPtr<nsIDOMElement> element; nsCOMPtr<nsIDocument> doc; if (owner) { owner->GetDOMElement(getter_AddRefs(element)); owner->GetDocument(getter_AddRefs(doc)); } nsCOMPtr<nsIPrincipal> principal = doc ? doc->NodePrincipal() : nullptr; int16_t shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_OBJECT_SUBREQUEST, mURL, principal, // loading principal principal, // triggering principal element, contentType, nullptr, &shouldLoad); if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) { mRequestFailed = true; return NS_ERROR_CONTENT_BLOCKED; } // Get the notification callbacks from the channel and save it as // week ref we'll use it in nsPluginStreamInfo::RequestRead() when // we'll create channel for byte range request. nsCOMPtr<nsIInterfaceRequestor> callbacks; channel->GetNotificationCallbacks(getter_AddRefs(callbacks)); if (callbacks) mWeakPtrChannelCallbacks = do_GetWeakReference(callbacks); nsCOMPtr<nsILoadGroup> loadGroup; channel->GetLoadGroup(getter_AddRefs(loadGroup)); if (loadGroup) mWeakPtrChannelLoadGroup = do_GetWeakReference(loadGroup); int64_t length; rv = channel->GetContentLength(&length); // it's possible for the server to not send a Content-Length. // we should still work in this case. if (NS_FAILED(rv) || length < 0 || length > UINT32_MAX) { // check out if this is file channel nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(channel); if (fileChannel) { // file does not exist mRequestFailed = true; return NS_ERROR_FAILURE; } mLength = 0; } else { mLength = uint32_t(length); } nsCOMPtr<nsIURI> aURL; rv = channel->GetURI(getter_AddRefs(aURL)); if (NS_FAILED(rv)) return rv; aURL->GetSpec(mURLSpec); if (!contentType.IsEmpty()) mContentType = contentType; #ifdef PLUGIN_LOGGING MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NOISY, ("nsPluginStreamListenerPeer::OnStartRequest this=%p request=%p mime=%s, url=%s\n", this, request, contentType.get(), mURLSpec.get())); PR_LogFlush(); #endif // Set up the stream listener... rv = SetUpStreamListener(request, aURL); if (NS_FAILED(rv)) { return rv; } return rv; }
NS_IMETHODIMP nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aContext) { nsresult rv = NS_OK; PROFILER_LABEL("nsPluginStreamListenerPeer", "OnStartRequest"); if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) { NS_ASSERTION(mRequests.Count() == 0, "Only our initial stream should be unknown!"); TrackRequest(request); } if (mHaveFiredOnStartRequest) { return NS_OK; } mHaveFiredOnStartRequest = true; nsCOMPtr<nsIChannel> channel = do_QueryInterface(request); NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE); // deal with 404 (Not Found) HTTP response, // just return, this causes the request to be ignored. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (httpChannel) { uint32_t responseCode = 0; rv = httpChannel->GetResponseStatus(&responseCode); if (NS_FAILED(rv)) { // NPP_Notify() will be called from OnStopRequest // in nsNPAPIPluginStreamListener::CleanUpStream // return error will cancel this request // ...and we also need to tell the plugin that mRequestFailed = true; return NS_ERROR_FAILURE; } if (responseCode > 206) { // not normal uint32_t wantsAllNetworkStreams = 0; // We don't always have an instance here already, but if we do, check // to see if it wants all streams. if (mPluginInstance) { rv = mPluginInstance->GetValueFromPlugin(NPPVpluginWantsAllNetworkStreams, &wantsAllNetworkStreams); // If the call returned an error code make sure we still use our default value. if (NS_FAILED(rv)) { wantsAllNetworkStreams = 0; } } if (!wantsAllNetworkStreams) { mRequestFailed = true; return NS_ERROR_FAILURE; } } } // Get the notification callbacks from the channel and save it as // week ref we'll use it in nsPluginStreamInfo::RequestRead() when // we'll create channel for byte range request. nsCOMPtr<nsIInterfaceRequestor> callbacks; channel->GetNotificationCallbacks(getter_AddRefs(callbacks)); if (callbacks) mWeakPtrChannelCallbacks = do_GetWeakReference(callbacks); nsCOMPtr<nsILoadGroup> loadGroup; channel->GetLoadGroup(getter_AddRefs(loadGroup)); if (loadGroup) mWeakPtrChannelLoadGroup = do_GetWeakReference(loadGroup); int64_t length; rv = channel->GetContentLength(&length); // it's possible for the server to not send a Content-Length. // we should still work in this case. if (NS_FAILED(rv) || length < 0 || length > UINT32_MAX) { // check out if this is file channel nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(channel); if (fileChannel) { // file does not exist mRequestFailed = true; return NS_ERROR_FAILURE; } mLength = 0; } else { mLength = uint32_t(length); } nsAutoCString aContentType; // XXX but we already got the type above! rv = channel->GetContentType(aContentType); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIURI> aURL; rv = channel->GetURI(getter_AddRefs(aURL)); if (NS_FAILED(rv)) return rv; aURL->GetSpec(mURLSpec); if (!aContentType.IsEmpty()) mContentType = aContentType; #ifdef PLUGIN_LOGGING PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NOISY, ("nsPluginStreamListenerPeer::OnStartRequest this=%p request=%p mime=%s, url=%s\n", this, request, aContentType.get(), mURLSpec.get())); PR_LogFlush(); #endif // Set up the stream listener... rv = SetUpStreamListener(request, aURL); if (NS_FAILED(rv)) return rv; return rv; }
PR_IMPLEMENT(void) PR_LogPrint(const char *fmt, ...) { va_list ap; char line[LINE_BUF_SIZE]; char *line_long = NULL; PRUint32 nb_tid = 0, nb; PRThread *me; PRExplodedTime now; if (!_pr_initialized) _PR_ImplicitInitialization(); if (!logFile) { return; } if (outputTimeStamp) { PR_ExplodeTime(PR_Now(), PR_GMTParameters, &now); nb_tid = PR_snprintf(line, sizeof(line)-1, "%04d-%02d-%02d %02d:%02d:%02d.%06d UTC - ", now.tm_year, now.tm_month + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, now.tm_usec); } me = PR_GetCurrentThread(); nb_tid += PR_snprintf(line+nb_tid, sizeof(line)-nb_tid-1, "%ld[%p]: ", #if defined(_PR_BTHREADS) me, me); #else me ? me->id : 0L, me); #endif va_start(ap, fmt); nb = nb_tid + PR_vsnprintf(line+nb_tid, sizeof(line)-nb_tid-1, fmt, ap); va_end(ap); /* * Check if we might have run out of buffer space (in case we have a * long line), and malloc a buffer just this once. */ if (nb == sizeof(line)-2) { va_start(ap, fmt); line_long = PR_vsmprintf(fmt, ap); va_end(ap); /* If this failed, we'll fall back to writing the truncated line. */ } if (line_long) { nb = strlen(line_long); _PR_LOCK_LOG(); if (logBuf != 0) { _PUT_LOG(logFile, logBuf, logp - logBuf); logp = logBuf; } /* * Write out the thread id (with an optional timestamp) and the * malloc'ed buffer. */ _PUT_LOG(logFile, line, nb_tid); _PUT_LOG(logFile, line_long, nb); /* Ensure there is a trailing newline. */ if (!nb || (line_long[nb-1] != '\n')) { char eol[2]; eol[0] = '\n'; eol[1] = '\0'; _PUT_LOG(logFile, eol, 1); } _PR_UNLOCK_LOG(); PR_smprintf_free(line_long); } else { /* Ensure there is a trailing newline. */ if (nb && (line[nb-1] != '\n')) { line[nb++] = '\n'; line[nb] = '\0'; } _PR_LOCK_LOG(); if (logBuf == 0) { _PUT_LOG(logFile, line, nb); } else { /* If nb can't fit into logBuf, write out logBuf first. */ if (logp + nb > logEndp) { _PUT_LOG(logFile, logBuf, logp - logBuf); logp = logBuf; } /* nb is guaranteed to fit into logBuf. */ memcpy(logp, line, nb); logp += nb; } _PR_UNLOCK_LOG(); } PR_LogFlush(); }
NS_IMETHODIMP nsDebugImpl::Break(const char *aFile, PRInt32 aLine) { #ifndef TEMP_MAC_HACK // Write out the assertion message to the debug log InitLog(); PR_LOG(gDebugLog, PR_LOG_ERROR, ("###!!! Break: at file %s, line %d", aFile, aLine)); PR_LogFlush(); fprintf(stderr, "Break: at file %s, line %d\n",aFile, aLine); fflush(stderr); fflush(stderr); #if defined(_WIN32) #ifdef _M_IX86 ::DebugBreak(); #endif #elif defined(XP_UNIX) && !defined(UNIX_CRASH_ON_ASSERT) fprintf(stderr, "\07"); char *assertBehavior = getenv("XPCOM_DEBUG_BREAK"); if (!assertBehavior) { // the default; nothing else to do ; } else if ( strcmp(assertBehavior, "suspend")== 0 ) { // the suspend case is first because we wanna send the signal before // other threads have had a chance to get too far from the state that // caused this assertion (in case they happen to have been involved). // fprintf(stderr, "Suspending process; attach with the debugger.\n"); kill(0, SIGSTOP); } else if ( strcmp(assertBehavior, "warn")==0 ) { // same as default; nothing else to do (see "suspend" case comment for // why this compare isn't done as part of the default case) // ; } else if ( strcmp(assertBehavior,"stack")==0 ) { // walk the stack // nsTraceRefcntImpl::WalkTheStack(stderr); } else if ( strcmp(assertBehavior,"abort")==0 ) { // same as UNIX_CRASH_ON_ASSERT // Abort(aFile, aLine); } else if ( strcmp(assertBehavior,"trap")==0 ) { DebugBreak(); } else { fprintf(stderr, "unrecognized value of XPCOM_DEBUG_BREAK env var!\n"); } fflush(stderr); // this shouldn't really be necessary, i don't think, // but maybe there's some lame stdio that buffers stderr #elif defined(XP_BEOS) { #ifdef UNIX_CRASH_ON_ASSERT char buf[2000]; sprintf(buf, "Break: at file %s, line %d", aFile, aLine); DEBUGGER(buf); #endif } #else Abort(aFile, aLine); #endif #endif // TEMP_MAC_HACK return NS_OK; }
NS_IMETHODIMP nsDebugImpl::Assertion(const char *aStr, const char *aExpr, const char *aFile, PRInt32 aLine) { InitLog(); char buf[1000]; PR_snprintf(buf, sizeof(buf), "###!!! ASSERTION: %s: '%s', file %s, line %d", aStr, aExpr, aFile, aLine); // Write out the assertion message to the debug log PR_LOG(gDebugLog, PR_LOG_ERROR, ("%s", buf)); PR_LogFlush(); // And write it out to the stderr fprintf(stderr, "%s\n", buf); fflush(stderr); #if defined(_WIN32) char* assertBehavior = getenv("XPCOM_DEBUG_BREAK"); if (assertBehavior && strcmp(assertBehavior, "warn") == 0) return NS_OK; if(!InDebugger()) { DWORD code = IDRETRY; /* Create the debug dialog out of process to avoid the crashes caused by * Windows events leaking into our event loop from an in process dialog. * We do this by launching windbgdlg.exe (built in xpcom/windbgdlg). * See http://bugzilla.mozilla.org/show_bug.cgi?id=54792 */ PROCESS_INFORMATION pi; STARTUPINFO si; char executable[MAX_PATH]; char* pName; memset(&pi, 0, sizeof(pi)); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.wShowWindow = SW_SHOW; if(GetModuleFileName(GetModuleHandle(XPCOM_DLL), executable, MAX_PATH) && NULL != (pName = strrchr(executable, '\\')) && NULL != strcpy(pName+1, "windbgdlg.exe") && #ifdef DEBUG_jband (printf("Launching %s\n", executable), PR_TRUE) && #endif CreateProcess(executable, buf, NULL, NULL, PR_FALSE, DETACHED_PROCESS | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi) && WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, INFINITE) && GetExitCodeProcess(pi.hProcess, &code)) { CloseHandle(pi.hProcess); } switch(code) { case IDABORT: //This should exit us raise(SIGABRT); //If we are ignored exit this way.. _exit(3); break; case IDIGNORE: return NS_OK; // Fall Through } } #endif #if defined(XP_OS2) char* assertBehavior = getenv("XPCOM_DEBUG_BREAK"); if (assertBehavior && strcmp(assertBehavior, "warn") == 0) return NS_OK; char msg[1200]; PR_snprintf(msg, sizeof(msg), "%s\n\nClick Cancel to Debug Application.\n" "Click Enter to continue running the Application.", buf); ULONG code = MBID_ERROR; code = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, msg, "nsDebug::Assertion", 0, MB_ERROR | MB_ENTERCANCEL); /* It is possible that we are executing on a thread that doesn't have a * message queue. In that case, the message won't appear, and code will * be 0xFFFF. We'll give the user a chance to debug it by calling * Break() * Actually, that's a really bad idea since this happens a lot with threadsafe * assertions and since it means that you can't actually run the debug build * outside a debugger without it crashing constantly. */ if(( code == MBID_ENTER ) || (code == MBID_ERROR)) { return NS_OK; // If Retry, Fall Through } #endif Break(aFile, aLine); return NS_OK; }