// Called on the worker thread. bool BackgroundFileSaver::CheckCompletion() { nsresult rv; MOZ_ASSERT(!mAsyncCopyContext, "Should not be copying when checking completion conditions."); bool failed = true; { MutexAutoLock lock(mLock); if (mComplete) { return true; } // If an error occurred, we don't need to do the checks in this code block, // and the operation can be completed immediately with a failure code. if (NS_SUCCEEDED(mStatus)) { failed = false; // We did not incur in an error, so we must determine if we can stop now. // If the Finish method has not been called, we can just continue now. if (!mFinishRequested) { return false; } // We can only stop when all the operations requested by the control // thread have been processed. First, we check whether we have processed // the first SetTarget call, if any. Then, we check whether we have // processed any rename requested by subsequent SetTarget calls. if ((mInitialTarget && !mActualTarget) || (mRenamedTarget && mRenamedTarget != mActualTarget)) { return false; } // If we still have data to write to the output file, allow the copy // operation to resume. The Available getter may return an error if one // of the pipe's streams has been already closed. uint64_t available; rv = mPipeInputStream->Available(&available); if (NS_SUCCEEDED(rv) && available != 0) { return false; } } mComplete = true; } // Ensure we notify completion now that the operation finished. // Do a best-effort attempt to remove the file if required. if (failed && mActualTarget && !mActualTargetKeepPartial) { (void)mActualTarget->Remove(false); } // Finish computing the hash if (!failed && mDigestContext) { nsNSSShutDownPreventionLock lock; if (!isAlreadyShutDown()) { Digest d; rv = d.End(SEC_OID_SHA256, mDigestContext); if (NS_SUCCEEDED(rv)) { MutexAutoLock lock(mLock); mSha256 = nsDependentCSubstring(char_ptr_cast(d.get().data), d.get().len); } } } // Compute the signature of the binary. ExtractSignatureInfo doesn't do // anything on non-Windows platforms except return an empty nsIArray. if (!failed && mActualTarget) { nsString filePath; mActualTarget->GetTarget(filePath); nsresult rv = ExtractSignatureInfo(filePath); if (NS_FAILED(rv)) { LOG(("Unable to extract signature information [this = %p].", this)); } else { LOG(("Signature extraction success! [this = %p]", this)); } } // Post an event to notify that the operation completed. if (NS_FAILED(mControlThread->Dispatch(NewRunnableMethod(this, &BackgroundFileSaver::NotifySaveComplete), NS_DISPATCH_NORMAL))) { NS_WARNING("Unable to post completion event to the control thread."); } return true; }
// Called on the worker thread. bool BackgroundFileSaver::CheckCompletion() { nsresult rv; MOZ_ASSERT(!mAsyncCopyContext, "Should not be copying when checking completion conditions."); bool failed = true; { MutexAutoLock lock(mLock); if (mComplete) { return true; } // If an error occurred, we don't need to do the checks in this code block, // and the operation can be completed immediately with a failure code. if (NS_SUCCEEDED(mStatus)) { failed = false; // On success, if there is a pending rename operation, we must process it // before finishing. Otherwise, we can finish now if requested. if ((mAssignedTarget && mAssignedTarget != mActualTarget) || !mFinishRequested) { return false; } // If completion was requested, but we still have data to write to the // output file, allow the copy operation to resume. The Available getter // may return an error if one of the pipe's streams has been already closed. uint64_t available; rv = mPipeInputStream->Available(&available); if (NS_SUCCEEDED(rv) && available != 0) { return false; } } mComplete = true; } // Ensure we notify completion now that the operation finished. // Do a best-effort attempt to remove the file if required. if (failed && mActualTarget && !mActualTargetKeepPartial) { (void)mActualTarget->Remove(false); } // Finish computing the hash if (!failed && mDigestContext) { nsNSSShutDownPreventionLock lock; if (!isAlreadyShutDown()) { Digest d; rv = d.End(SEC_OID_SHA256, mDigestContext); if (NS_SUCCEEDED(rv)) { MutexAutoLock lock(mLock); mSha256 = nsDependentCSubstring(char_ptr_cast(d.get().data), d.get().len); } } } // Post an event to notify that the operation completed. nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &BackgroundFileSaver::NotifySaveComplete); if (!event || NS_FAILED(mControlThread->Dispatch(event, NS_DISPATCH_NORMAL))) { NS_WARNING("Unable to post completion event to the control thread."); } return true; }