Bug 1216062 - Notify OnStartSignedPackagedRequest with package identifier. r=valentin.
authorHenry <hchang@mozilla.com>
Mon, 19 Oct 2015 03:33:00 +0200
changeset 303542 921efb579415a7dc78bcdde4c9d51c3221e66890
parent 303541 5e890d7ad1744e38b0d9de03696dfe09631c12ec
child 303543 26c7f2d75c75769c2e615ccb3708809fc3faf46f
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvalentin
bugs1216062
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1216062 - Notify OnStartSignedPackagedRequest with package identifier. r=valentin.
netwerk/base/nsIPackagedAppVerifier.idl
netwerk/protocol/http/PackagedAppService.cpp
netwerk/protocol/http/PackagedAppVerifier.cpp
netwerk/protocol/http/PackagedAppVerifier.h
netwerk/test/unit/test_packaged_app_verifier.js
--- a/netwerk/base/nsIPackagedAppVerifier.idl
+++ b/netwerk/base/nsIPackagedAppVerifier.idl
@@ -12,21 +12,22 @@ interface nsIPackagedAppVerifierListener
 
 /**
  * nsIPackagedAppVerifier
  *
  * It inherits nsIStreamListener and all the data will be fed by
  * onStartRequest/onDataAvailable/onStopRequest.
  *
  */
-[scriptable, uuid(16419a80-4cc3-11e5-b970-0800200c9a66)]
+[scriptable, uuid(fbb28ef8-d3d0-4a2b-af98-8010163a2bfb)]
 interface nsIPackagedAppVerifier : nsIStreamListener
 {
-  // The package origin of either a signed or unsigned package.
-  readonly attribute ACString packageOrigin;
+  // The package identifier of the signed package. For a unsigned package, this
+  // attribute is empty.
+  readonly attribute ACString packageIdentifier;
 
   // Whether this package is signed.
   readonly attribute boolean isPackageSigned;
 
   /**
    * @param aListener
    *    an object implementing nsIPackagedAppVerifierListener as the bridge that
    *    the client gets callback from the package verifier. The callback might be
@@ -44,17 +45,16 @@ interface nsIPackagedAppVerifier : nsISt
    * @param aPackageCacheEntry
    *    the cache entry of the package itself (not the resource's cache).
    *    It will be used to store any necessary information like the signed
    *    package origin.
    *
    * The verifier init function.
    */
   void init(in nsIPackagedAppVerifierListener aListener,
-            in ACString aPackageOrigin,
             in ACString aSignature,
             in nsICacheEntry aPackageCacheEntry);
 
   /**
    * @param aUri
    *    the URI of the resource.
    *
    * @param aCacheEntry
--- a/netwerk/protocol/http/PackagedAppService.cpp
+++ b/netwerk/protocol/http/PackagedAppService.cpp
@@ -357,29 +357,29 @@ PackagedAppService::PackagedAppChannelLi
 
   mDownloader->SetIsFromCache(isFromCache);
   LOG(("[%p] Downloader isFromCache: %d\n", mDownloader.get(), isFromCache));
 
   // If the package is loaded from cache, check the meta data in the cache
   // to know if it's a signed package. Notify requesters if it's signed.
   if (isFromCache) {
     bool isPackageSigned = false;
-    nsCString signedPackageOrigin;
+    nsCString signedPackageId;
     nsCOMPtr<nsICacheEntry> packageCacheEntry = GetPackageCacheEntry(aRequest);
     if (packageCacheEntry) {
-      const char* key = PackagedAppVerifier::kSignedPakOriginMetadataKey;
+      const char* key = PackagedAppVerifier::kSignedPakIdMetadataKey;
       nsXPIDLCString value;
       nsresult rv = packageCacheEntry->GetMetaDataElement(key,
                                                           getter_Copies(value));
       isPackageSigned = (NS_SUCCEEDED(rv) && !value.IsEmpty());
-      signedPackageOrigin = value;
+      signedPackageId = value;
     }
     if (isPackageSigned) {
       LOG(("The cached package is signed. Notify the requesters."));
-      mDownloader->NotifyOnStartSignedPackageRequest(signedPackageOrigin);
+      mDownloader->NotifyOnStartSignedPackageRequest(signedPackageId);
     }
   }
 
   // XXX: This is the place to suspend the channel, doom existing cache entries
   // for previous resources, and then resume the channel.
   return mListener->OnStartRequest(aRequest, aContext);
 }
 
@@ -442,17 +442,16 @@ PackagedAppService::PackagedAppDownloade
 
   LOG(("Creating PackagedAppVerifier."));
 
   nsCOMPtr<nsIMultiPartChannel> multiChannel(do_QueryInterface(aRequest));
   nsCString signature = GetSignatureFromChannel(multiChannel);
   nsCOMPtr<nsICacheEntry> packageCacheEntry = GetPackageCacheEntry(aRequest);
 
   mVerifier = new PackagedAppVerifier(this,
-                                      mPackageOrigin,
                                       signature,
                                       packageCacheEntry);
 }
 
 NS_IMETHODIMP
 PackagedAppService::PackagedAppDownloader::OnStartRequest(nsIRequest *aRequest,
                                                           nsISupports *aContext)
 {
@@ -764,17 +763,17 @@ PackagedAppService::PackagedAppDownloade
       // right now, directly.  See also the CallCallbacks method bellow.
       LOG(("[%p]    > already downloaded\n", this));
 
       // This is the case where a package downloader is still running and we
       // peek data from it.
       if (mVerifier && mVerifier->GetIsPackageSigned()) {
         // TODO: Bug 1178526 will deal with the package identifier things.
         //       For now we just use the origin as the identifier.
-        listener->OnStartSignedPackageRequest(mVerifier->GetPackageOrigin());
+        listener->OnStartSignedPackageRequest(mVerifier->GetPackageIdentifier());
         listener = nullptr; // So that the request will not be added to the queue.
       }
       mCacheStorage->AsyncOpenURI(aURI, EmptyCString(),
                                   nsICacheStorage::OPEN_READONLY, aCallback);
     } else {
       LOG(("[%p]    > adding to array\n", this));
       // Add this resource to the callback array
       array->AppendObject(aCallback);
@@ -898,17 +897,34 @@ PackagedAppService::PackagedAppDownloade
     LOG(("Notifying %p OnStartSignedPackageRequest. New origin: %s", requester.get(),
           nsCString(aPackageOrigin).get()));
     requester->OnStartSignedPackageRequest(aPackageOrigin);
   }
 
   mRequesters.Clear();
 }
 
-void PackagedAppService::PackagedAppDownloader::InstallSignedPackagedApp(const ResourceCacheInfo* aInfo)
+static bool
+AddPackageIdToOrigin(nsACString& aOrigin, const nsACString& aPackageId)
+{
+  nsAutoCString originNoSuffix;
+  mozilla::OriginAttributes attrs;
+  if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
+    return false;
+  }
+
+  attrs.mSignedPkg = NS_ConvertUTF8toUTF16(aPackageId);
+  nsAutoCString suffixWithPackageId;
+  attrs.CreateSuffix(suffixWithPackageId);
+  aOrigin = originNoSuffix + suffixWithPackageId;
+  return true;
+}
+
+void
+PackagedAppService::PackagedAppDownloader::InstallSignedPackagedApp(const ResourceCacheInfo* aInfo)
 {
   // TODO: Bug 1178533 to register permissions, system messages etc on navigation to
   //       signed packages.
   LOG(("Install this packaged app."));
   bool isSuccess = false;
 
   nsCOMPtr<nsIInstallPackagedWebapp> installer =
     do_GetService("@mozilla.org/newapps/installpackagedwebapp;1");
@@ -916,23 +932,24 @@ void PackagedAppService::PackagedAppDown
   if (!installer) {
     LOG(("InstallSignedPackagedApp: fail to get InstallPackagedWebapp service"));
     return OnError(ERROR_GET_INSTALLER_FAILED);
   }
 
   nsCString manifestURL;
   aInfo->mURI->GetAsciiSpec(manifestURL);
 
-  // Use the origin stored in the verifier since the signed packaged app would
-  // have a specifi package identifer defined in the manifest file.
-  nsCString packageOrigin;
-  mVerifier->GetPackageOrigin(packageOrigin);
+
+  nsCString originWithPackageId = mPackageOrigin;
+  if (!AddPackageIdToOrigin(originWithPackageId, mVerifier->GetPackageIdentifier())) {
+    NS_WARNING("mPackageOrigin is malformed.");
+  }
 
   installer->InstallPackagedWebapp(mManifestContent.get(),
-                                   packageOrigin.get(),
+                                   originWithPackageId.get(),
                                    manifestURL.get(),
                                    &isSuccess);
   if (!isSuccess) {
     LOG(("InstallSignedPackagedApp: failed to install permissions"));
     return OnError(ERROR_INSTALL_RESOURCE_FAILED);
   }
 
   LOG(("InstallSignedPackagedApp: success."));
@@ -985,19 +1002,17 @@ PackagedAppService::PackagedAppDownloade
   bool isPackagedSigned;
   mVerifier->GetIsPackageSigned(&isPackagedSigned);
   if (!isPackagedSigned) {
     // A verified but unsigned manifest means this package has no signature.
     LOG(("No signature in the package. Just run normally."));
     return;
   }
 
-  nsCString packageOrigin;
-  mVerifier->GetPackageOrigin(packageOrigin);
-  NotifyOnStartSignedPackageRequest(packageOrigin);
+  NotifyOnStartSignedPackageRequest(mVerifier->GetPackageIdentifier());
   InstallSignedPackagedApp(aInfo);
 }
 
 void
 PackagedAppService::PackagedAppDownloader::OnResourceVerified(const ResourceCacheInfo* aInfo,
                                                               bool aSuccess)
 {
   if (!aSuccess) {
@@ -1005,17 +1020,17 @@ PackagedAppService::PackagedAppDownloade
   }
 
   // If this package is signed and there is any pending requests, we just notify
   // right now no matter if this is the requested resource. Doing this can
   // have the potential process switch be done as early as possible.
   if (mVerifier->GetIsPackageSigned()) {
     // TODO: Bug 1178526 will deal with the package identifier things.
     //       For now we just use the origin as the identifier.
-    NotifyOnStartSignedPackageRequest(mVerifier->GetPackageOrigin());
+    NotifyOnStartSignedPackageRequest(mVerifier->GetPackageIdentifier());
   }
 
   // Serve this resource to all listeners.
   CallCallbacks(aInfo->mURI, aInfo->mCacheEntry, aInfo->mStatusCode);
 
   if (aInfo->mIsLastPart) {
     LOG(("This is the last part. FinalizeDownload (%d)", aInfo->mStatusCode));
     FinalizeDownload(aInfo->mStatusCode);
--- a/netwerk/protocol/http/PackagedAppVerifier.cpp
+++ b/netwerk/protocol/http/PackagedAppVerifier.cpp
@@ -28,65 +28,63 @@ namespace mozilla {
 namespace net {
 
 ///////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS(PackagedAppVerifier, nsIPackagedAppVerifier, nsIVerificationCallback)
 
 NS_IMPL_ISUPPORTS(PackagedAppVerifier::ResourceCacheInfo, nsISupports)
 
-const char* PackagedAppVerifier::kSignedPakOriginMetadataKey = "signed-pak-origin";
+const char* PackagedAppVerifier::kSignedPakIdMetadataKey = "package-id";
 
 PackagedAppVerifier::PackagedAppVerifier()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread(),
                      "PackagedAppVerifier::OnResourceVerified must be on main thread");
 
-  Init(nullptr, EmptyCString(), EmptyCString(), nullptr);
+  Init(nullptr, EmptyCString(), nullptr);
 }
 
 PackagedAppVerifier::PackagedAppVerifier(nsIPackagedAppVerifierListener* aListener,
-                                         const nsACString& aPackageOrigin,
                                          const nsACString& aSignature,
                                          nsICacheEntry* aPackageCacheEntry)
 {
-  Init(aListener, aPackageOrigin, aSignature, aPackageCacheEntry);
+  Init(aListener, aSignature, aPackageCacheEntry);
 }
 
 PackagedAppVerifier::~PackagedAppVerifier()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread(), "mPendingResourceCacheInfoList is not thread safe.");
   while (auto i = mPendingResourceCacheInfoList.popFirst()) {
     // This seems to be the only way that we can manually delete a
     // nsISupports instance with no warning.
     RefPtr<ResourceCacheInfo> deleter(i);
   }
 }
 
 NS_IMETHODIMP PackagedAppVerifier::Init(nsIPackagedAppVerifierListener* aListener,
-                                        const nsACString& aPackageOrigin,
                                         const nsACString& aSignature,
                                         nsICacheEntry* aPackageCacheEntry)
 {
   static bool onceThru = false;
   if (!onceThru) {
     Preferences::AddBoolVarCache(&gDeveloperMode,
                                  "network.http.packaged-apps-developer-mode", false);
     Preferences::AddBoolVarCache(&gSignedAppEnabled,
                                  "network.http.packaged-signed-apps-enabled", false);
     onceThru = true;
   }
 
   mListener = aListener;
   mState = STATE_UNKNOWN;
-  mPackageOrigin = aPackageOrigin;
   mSignature = aSignature;
   mIsPackageSigned = false;
   mPackageCacheEntry = aPackageCacheEntry;
   mIsFirstResource = true;
+  mManifest = EmptyCString();
 
   nsresult rv;
   mPackagedAppUtils = do_CreateInstance(NS_PACKAGEDAPPUTILS_CONTRACTID, &rv);
   if (NS_FAILED(rv)) {
     LOG(("create packaged app utils failed"));
     return rv;
   }
 
@@ -266,22 +264,16 @@ PackagedAppVerifier::VerifyManifest(cons
   if (!aInfo->mURI) { // Broken last part.
     FireVerifiedEvent(false, false);
     mState = STATE_MANIFEST_VERIFIED_FAILED;
     return;
   }
 
   mState = STATE_MANIFEST_VERIFYING;
 
-  if (gDeveloperMode) {
-    LOG(("Developer mode! Bypass verification."));
-    FireVerifiedEvent(true, true);
-    return;
-  }
-
   if (mSignature.IsEmpty()) {
     LOG(("No signature. No need to do verification."));
     FireVerifiedEvent(true, true);
     return;
   }
 
   LOG(("Signature: length = %u\n%s", mSignature.Length(), mSignature.get()));
   LOG(("Manifest: length = %u\n%s", mManifest.Length(), mManifest.get()));
@@ -347,31 +339,40 @@ PackagedAppVerifier::OnManifestVerified(
 
   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;
 
-  // TODO: Update mPackageOrigin.
+  // 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(kSignedPakOriginMetadataKey,
-                                             mPackageOrigin.get());
+      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.
@@ -427,19 +428,19 @@ PackagedAppVerifier::WouldVerify() const
   return gSignedAppEnabled && !mSignature.IsEmpty();
 }
 
 //---------------------------------------------------------------
 // nsIPackagedAppVerifier.
 //---------------------------------------------------------------
 
 NS_IMETHODIMP
-PackagedAppVerifier::GetPackageOrigin(nsACString& aPackageOrigin)
+PackagedAppVerifier::GetPackageIdentifier(nsACString& aPackageIdentifier)
 {
-  aPackageOrigin = mPackageOrigin;
+  aPackageIdentifier = mPackageIdentifer;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PackagedAppVerifier::GetIsPackageSigned(bool* aIsPackagedSigned)
 {
   *aIsPackagedSigned = mIsPackageSigned;
   return NS_OK;
--- a/netwerk/protocol/http/PackagedAppVerifier.h
+++ b/netwerk/protocol/http/PackagedAppVerifier.h
@@ -88,40 +88,39 @@ public:
   private:
     virtual ~ResourceCacheInfo() { }
   };
 
 public:
   PackagedAppVerifier();
 
   PackagedAppVerifier(nsIPackagedAppVerifierListener* aListener,
-                      const nsACString& aPackageOrigin,
                       const nsACString& aSignature,
                       nsICacheEntry* aPackageCacheEntry);
 
   // A internal used function to let the verifier know there's a broken
   // last part.
   void SetHasBrokenLastPart(nsresult aStatusCode);
 
   // Used to explicitly clear the listener to avoid circula reference.
   void ClearListener() { mListener = nullptr; }
 
   bool GetIsPackageSigned() const
   {
     return mIsPackageSigned;
   }
 
-  const nsACString& GetPackageOrigin() const
+  const nsACString& GetPackageIdentifier() const
   {
-    return mPackageOrigin;
+    return mPackageIdentifer;
   }
 
   bool WouldVerify() const;
 
-  static const char* kSignedPakOriginMetadataKey;
+  static const char* kSignedPakIdMetadataKey;
 
 private:
   virtual ~PackagedAppVerifier();
 
   // Called when a resource is already fully written in the cache. This resource
   // will be processed and is guaranteed to be called back in either:
   //
   // 1) PackagedAppVerifierListener::OnManifestVerified:
@@ -188,14 +187,16 @@ private:
   // This will help to verify manifests and resource integrity
   nsCOMPtr<nsIPackagedAppUtils> mPackagedAppUtils;
 
   // A list of pending resource that is downloaded but not verified yet.
   mozilla::LinkedList<ResourceCacheInfo> mPendingResourceCacheInfoList;
 
   // A place to store the computed hashes of each resource.
   nsClassHashtable<nsCStringHashKey, nsCString> mResourceHashStore;
+
+  nsCString mPackageIdentifer;
 }; // class PackagedAppVerifier
 
 } // namespace net
 } // namespace mozilla
 
 #endif // mozilla_net_PackagedAppVerifier_h
--- a/netwerk/test/unit/test_packaged_app_verifier.js
+++ b/netwerk/test/unit/test_packaged_app_verifier.js
@@ -33,29 +33,30 @@ var gCacheStorageService = Cc["@mozilla.
                              .getService(Ci.nsICacheStorageService);;
 
 var gLoadContextInfoFactory =
   Cu.import("resource://gre/modules/LoadContextInfo.jsm", {}).LoadContextInfo;
 
 const kUriIdx                 = 0;
 const kStatusCodeIdx          = 1;
 const kVerificationSuccessIdx = 2;
+const kContentIdx             = 3;
 
 function enable_developer_mode()
 {
   gPrefs.setBoolPref("network.http.packaged-apps-developer-mode", true);
 }
 
 function reset_developer_mode()
 {
   gPrefs.clearUserPref("network.http.packaged-apps-developer-mode");
 }
 
 function createVerifierListener(aExpecetedCallbacks,
-                                aExpectedOrigin,
+                                aExpectedPackageId,
                                 aExpectedIsSigned,
                                 aPackageCacheEntry) {
   let cnt = 0;
 
   return {
     onVerified: function(aIsManifest,
                          aUri,
                          aCacheEntry,
@@ -72,43 +73,58 @@ function createVerifierListener(aExpecet
       equal(aIsManifest, isManifest, 'is manifest');
       equal(aUri.asciiSpec, expectedCallback[kUriIdx], 'URL');
       equal(aStatusCode, expectedCallback[kStatusCodeIdx], 'status code');
       equal(aIsLastPart, isLastPart, 'is lastPart');
       equal(aVerificationSuccess, expectedCallback[kVerificationSuccessIdx], 'verification result');
 
       if (isManifest) {
         // Check if the verifier got the right package info.
-        equal(gVerifier.packageOrigin, aExpectedOrigin, 'package origin');
+        equal(gVerifier.packageIdentifier, aExpectedPackageId, 'package identifier');
         equal(gVerifier.isPackageSigned, aExpectedIsSigned, 'is package signed');
 
         // Check if the verifier wrote the signed package origin to the cache.
         ok(!!aPackageCacheEntry, aPackageCacheEntry.key);
-        let signePakOriginInCache = aPackageCacheEntry.getMetaDataElement('signed-pak-origin');
-        equal(signePakOriginInCache,
-              (aExpectedIsSigned ? aExpectedOrigin : ''),
-              'signed-pak-origin in cache');
+        let signePakIdInCache = aPackageCacheEntry.getMetaDataElement('package-id');
+        equal(signePakIdInCache,
+              (aExpectedIsSigned ? aExpectedPackageId : ''),
+              'package-id in cache');
       }
 
       if (isLastPart) {
         reset_developer_mode();
         run_next_test();
       }
     },
   };
 };
 
-function feedResources(aExpectedCallbacks) {
+function feedData(aString) {
+  let stringStream = Cc["@mozilla.org/io/string-input-stream;1"].
+                           createInstance(Ci.nsIStringInputStream);
+  stringStream.setData(aString, aString.length);
+  gVerifier.onDataAvailable(null, null, stringStream, 0, aString.length);
+}
+
+function feedResources(aExpectedCallbacks, aSignature) {
   for (let i = 0; i < aExpectedCallbacks.length; i++) {
     let expectedCallback = aExpectedCallbacks[i];
     let isLastPart = (i === aExpectedCallbacks.length - 1);
 
+    // Start request.
     let uri = gIoService.newURI(expectedCallback[kUriIdx], null, null);
     gVerifier.onStartRequest(null, uri);
 
+    // Feed data at once.
+    let contentString = expectedCallback[kContentIdx];
+    if (contentString !== undefined) {
+      feedData(contentString);
+    }
+
+    // Stop request.
     let info = gVerifier.createResourceCacheInfo(uri,
                                                  null,
                                                  expectedCallback[kStatusCodeIdx],
                                                  isLastPart);
 
     gVerifier.onStopRequest(null, info, expectedCallback[kStatusCodeIdx]);
   }
 }
@@ -143,58 +159,65 @@ function test_no_signature(aDeveloperMod
 
   // We only require the package URL to be different in each test case.
   let packageUriString = kOrigin + '/pak' + (aDeveloperMode ? '-dev' : '');
 
   let packageCacheEntry =
     createPackageCache(packageUriString, gLoadContextInfoFactory.default);
 
   let verifierListener = createVerifierListener(expectedCallbacks,
-                                                kOrigin,
+                                                '',
                                                 isPackageSigned,
                                                 packageCacheEntry);
 
-  gVerifier.init(verifierListener, kOrigin, '', packageCacheEntry);
+  gVerifier.init(verifierListener, '', packageCacheEntry);
 
-  feedResources(expectedCallbacks);
+  feedResources(expectedCallbacks, '');
 }
 
 function test_invalid_signature(aDeveloperMode) {
   const kOrigin = 'http://bar.com';
 
   aDeveloperMode = !!aDeveloperMode;
 
   // Since we haven't implemented signature verification, the verification always
   // fails if the signature exists.
 
   let verificationResult = aDeveloperMode; // Verification always success in developer mode.
   let isPackageSigned = aDeveloperMode;   // Package is always considered as signed in developer mode.
 
+  const kPackagedId = '611FC2FE-491D-4A47-B3B3-43FBDF6F404F';
+  const kManifestContent = 'Content-Location: manifest.webapp\r\n' +
+                           'Content-Type: application/x-web-app-manifest+json\r\n' +
+                           '\r\n' +
+                           '{ "package-identifier": "' + kPackagedId + '" }';
+
   const expectedCallbacks = [
-  // URL                      statusCode   verificationResult
-    [kOrigin + '/manifest',   Cr.NS_OK,    verificationResult],
+  // URL                      statusCode   verificationResult     content
+    [kOrigin + '/manifest',   Cr.NS_OK,    verificationResult,    kManifestContent],
     [kOrigin + '/1.html',     Cr.NS_OK,    verificationResult],
     [kOrigin + '/2.js',       Cr.NS_OK,    verificationResult],
     [kOrigin + '/3.jpg',      Cr.NS_OK,    verificationResult],
     [kOrigin + '/4.html',     Cr.NS_OK,    verificationResult],
     [kOrigin + '/5.css',      Cr.NS_OK,    verificationResult],
   ];
 
   let packageUriString = kOrigin + '/pak' + (aDeveloperMode ? '-dev' : '');
   let packageCacheEntry =
     createPackageCache(packageUriString, gLoadContextInfoFactory.private);
 
   let verifierListener = createVerifierListener(expectedCallbacks,
-                                                kOrigin,
+                                                aDeveloperMode ? kPackagedId : '',
                                                 isPackageSigned,
                                                 packageCacheEntry);
 
-  gVerifier.init(verifierListener, kOrigin, 'invalid signature', packageCacheEntry);
+  let signature = 'manifest-signature: 11111111111111111111111';
+  gVerifier.init(verifierListener, signature, packageCacheEntry);
 
-  feedResources(expectedCallbacks);
+  feedResources(expectedCallbacks, signature);
 }
 
 function test_no_signature_developer_mode()
 {
   enable_developer_mode()
   test_no_signature(true);
 }
 
@@ -213,9 +236,9 @@ function run_test()
   add_test(test_invalid_signature);
 
   // Test cases in developer mode.
   add_test(test_no_signature_developer_mode);
   add_test(test_invalid_signature_developer_mode);
 
   // run tests
   run_next_test();
-}
+}
\ No newline at end of file