Example #1
0
// 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;
}