void
PackagedAppVerifier::ProcessResourceCache(const ResourceCacheInfo* aInfo)
{
  MOZ_RELEASE_ASSERT(NS_IsMainThread(), "ProcessResourceCache must be on main thread");

  // Queue this info since we might process it asynchronously.
  mPendingResourceCacheInfoList.insertBack(const_cast<ResourceCacheInfo*>(aInfo));

  switch (mState) {
  case STATE_UNKNOWN:
    // The first resource has to be the manifest.
    VerifyManifest(aInfo);
    break;

  case STATE_MANIFEST_VERIFYING:
    // A resource is cached in the middle of manifest verification.
    // Verify it until the manifest is verified.
    break;

  case STATE_MANIFEST_VERIFIED_OK:
    VerifyResource(aInfo);
    break;

  case STATE_MANIFEST_VERIFIED_FAILED:
    LOG(("Resource not verified because manifest verification failed."));
    FireVerifiedEvent(false, false);
    break;

  default:
    MOZ_CRASH("Unexpected PackagedAppVerifier state."); // Shouldn't get here.
    break;
  }
}
void
PackagedAppVerifier::OnManifestVerified(bool aSuccess)
{
  MOZ_RELEASE_ASSERT(NS_IsMainThread(), "OnManifestVerified must be on main thread.");

  LOG(("PackagedAppVerifier::OnManifestVerified: %d", aSuccess));

  // The listener could have been removed before we verify the resource.
  if (!mListener) {
    return;
  }

  if (!aSuccess && gDeveloperMode) {
    aSuccess = true;
    LOG(("Developer mode! Treat junk signature valid."));
  }

  // Only when the manifest verified and package has signature would we
  // regard this package is signed.
  mIsPackageSigned = aSuccess && !mSignature.IsEmpty();

  mState = aSuccess ? STATE_MANIFEST_VERIFIED_OK
                    : STATE_MANIFEST_VERIFIED_FAILED;

  // Obtain the package identifier from manifest if the package is signed.
  if (mIsPackageSigned) {
    mPackagedAppUtils->GetPackageIdentifier(mPackageIdentifer);
    LOG(("PackageIdentifer is: %s", mPackageIdentifer.get()));
  }

  // If the package is signed, add related info to the package cache.
  if (mIsPackageSigned && mPackageCacheEntry) {
    LOG(("This package is signed. Add this info to the cache channel."));
    if (mPackageCacheEntry) {
      mPackageCacheEntry->SetMetaDataElement(kSignedPakIdMetadataKey,
                                             mPackageIdentifer.get());
      mPackageCacheEntry = nullptr; // the cache entry is no longer needed.
    }
  }

  RefPtr<ResourceCacheInfo> info(mPendingResourceCacheInfoList.popFirst());
  MOZ_ASSERT(info);

  mListener->OnVerified(true, // aIsManifest.
                        info->mURI,
                        info->mCacheEntry,
                        info->mStatusCode,
                        info->mIsLastPart,
                        aSuccess);

  LOG(("Ready to verify resources that were cached during verification"));
  // Verify the resources which were cached during verification accordingly.
  for (auto i = mPendingResourceCacheInfoList.getFirst(); i; i = i->getNext()) {
    VerifyResource(i);
  }
}