зеркало из https://github.com/mozilla/gecko-dev.git
273 строки
11 KiB
C++
273 строки
11 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set sw=2 ts=8 et tw=80 : */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef mozilla_net_PackagedAppService_h
|
|
#define mozilla_net_PackagedAppService_h
|
|
|
|
#include "nsIPackagedAppService.h"
|
|
#include "nsILoadContextInfo.h"
|
|
#include "nsICacheStorage.h"
|
|
#include "PackagedAppVerifier.h"
|
|
#include "nsIMultiPartChannel.h"
|
|
#include "PackagedAppVerifier.h"
|
|
#include "nsIPackagedAppChannelListener.h"
|
|
|
|
namespace mozilla {
|
|
namespace net {
|
|
|
|
class nsHttpResponseHead;
|
|
|
|
// This service is used to download packages from the web.
|
|
// Individual resources in the package are saved in the browser cache. It also
|
|
// provides an interface to asynchronously request resources from packages,
|
|
// which are either returned from the cache if they exist and are valid,
|
|
// or downloads the package.
|
|
// The package format is defined at:
|
|
// https://w3ctag.github.io/packaging-on-the-web/#streamable-package-format
|
|
// Downloading the package is triggered by calling getResource()
|
|
class PackagedAppService final
|
|
: public nsIPackagedAppService
|
|
{
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
|
NS_DECL_NSIPACKAGEDAPPSERVICE
|
|
|
|
PackagedAppService();
|
|
|
|
private:
|
|
~PackagedAppService();
|
|
|
|
// Called by PackageAppDownloader once the download has finished
|
|
// (or encountered an error) to remove the package from mDownloadingPackages
|
|
// Should be called on the main thread.
|
|
nsresult NotifyPackageDownloaded(nsCString aKey);
|
|
|
|
// Extract the URI of a package from the given packaged resource URI.
|
|
static nsresult GetPackageURI(nsIURI *aUri, nsIURI **aPackageURI);
|
|
|
|
// This class is used to write data into the cache entry corresponding to the
|
|
// packaged resource being downloaded.
|
|
// The PackagedAppDownloader will hold a ref to a CacheEntryWriter that
|
|
// corresponds to the entry that is currently being downloaded.
|
|
class CacheEntryWriter final
|
|
: public nsIStreamListener
|
|
{
|
|
public:
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSISTREAMLISTENER
|
|
NS_DECL_NSIREQUESTOBSERVER
|
|
|
|
// If successful, calling this static method will create a new
|
|
// CacheEntryWriter and will create the cache entry associated to the
|
|
// resource.
|
|
static nsresult Create(nsIURI*, nsICacheStorage*, CacheEntryWriter**);
|
|
|
|
nsCOMPtr<nsICacheEntry> mEntry;
|
|
|
|
// Called by PackagedAppDownloader to write data to the cache entry.
|
|
NS_METHOD ConsumeData(const char *aBuf,
|
|
uint32_t aCount,
|
|
uint32_t *aWriteCount);
|
|
|
|
private:
|
|
CacheEntryWriter() { }
|
|
~CacheEntryWriter() { }
|
|
|
|
// Copy the security-info metadata from the channel to the cache entry
|
|
// so packaged resources can be accessed over https.
|
|
nsresult CopySecurityInfo(nsIChannel *aChannel);
|
|
|
|
// Copy headers that apply to all resources in the package
|
|
static nsresult CopyHeadersFromChannel(nsIChannel *aChannel,
|
|
nsHttpResponseHead *aHead);
|
|
|
|
// We write the data we read from the network into this stream which goes
|
|
// to the cache entry.
|
|
nsCOMPtr<nsIOutputStream> mOutputStream;
|
|
};
|
|
|
|
// This class is used to download a packaged app. It acts as a listener
|
|
// for the nsMultiMixedConv object that parses the package.
|
|
// There is an OnStartRequest, OnDataAvailable*, OnStopRequest sequence called
|
|
// for each resource
|
|
// The PackagedAppService holds a hash-table of the PackagedAppDownloaders
|
|
// that are in progress to coalesce same loads.
|
|
// Once the downloading is completed, it should call
|
|
// NotifyPackageDownloaded(packageURI), so the service releases the ref.
|
|
class PackagedAppDownloader final
|
|
: public nsIStreamListener
|
|
, public nsIPackagedAppVerifierListener
|
|
{
|
|
public:
|
|
typedef PackagedAppVerifier::ResourceCacheInfo ResourceCacheInfo;
|
|
|
|
private:
|
|
enum EErrorType {
|
|
ERROR_MANIFEST_VERIFIED_FAILED,
|
|
ERROR_RESOURCE_VERIFIED_FAILED,
|
|
ERROR_GET_INSTALLER_FAILED,
|
|
ERROR_INSTALL_RESOURCE_FAILED,
|
|
};
|
|
|
|
public:
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSISTREAMLISTENER
|
|
NS_DECL_NSIREQUESTOBSERVER
|
|
NS_DECL_NSIPACKAGEDAPPVERIFIERLISTENER
|
|
|
|
// Initializes mCacheStorage and saves aKey as mPackageKey which is later
|
|
// used to remove this object from PackagedAppService::mDownloadingPackages
|
|
// - aKey is a string which uniquely identifies this package within the
|
|
// packagedAppService
|
|
nsresult Init(nsILoadContextInfo* aInfo, const nsCString &aKey,
|
|
const nsACString& aPackageOrigin);
|
|
// Registers a callback which gets called when the given nsIURI is downloaded
|
|
// aURI is the full URI of a subresource, composed of packageURI + !// + subresourcePath
|
|
// aRequester is the outer channel who makes the request for aURI.
|
|
nsresult AddCallback(nsIURI *aURI,
|
|
nsICacheEntryOpenCallback *aCallback,
|
|
nsIChannel* aRequester);
|
|
|
|
// Remove the callback from the resource callback list.
|
|
nsresult RemoveCallbacks(nsICacheEntryOpenCallback* aCallback);
|
|
|
|
// Called by PackagedAppChannelListener to note the fact that the package
|
|
// is coming from the cache, and no subresources are to be expected as only
|
|
// package metadata is saved in the cache.
|
|
void SetIsFromCache(bool aFromCache) { mIsFromCache = aFromCache; }
|
|
|
|
// Notify the observers who are interested in knowing a signed packaged content
|
|
// is about to load from either HTTP or cache..
|
|
void NotifyOnStartSignedPackageRequest(const nsACString& PackageOrigin);
|
|
|
|
private:
|
|
~PackagedAppDownloader() { }
|
|
|
|
// Static method used to write data into the cache entry or discard
|
|
// if there's no writer. Used as a writer function of
|
|
// nsIInputStream::ReadSegments.
|
|
static NS_METHOD ConsumeData(nsIInputStream *aStream,
|
|
void *aClosure,
|
|
const char *aFromRawSegment,
|
|
uint32_t aToOffset,
|
|
uint32_t aCount,
|
|
uint32_t *aWriteCount);
|
|
|
|
//---------------------------------------------------------------
|
|
// For PackagedAppVerifierListener.
|
|
//---------------------------------------------------------------
|
|
virtual void OnManifestVerified(const ResourceCacheInfo* aInfo, bool aSuccess);
|
|
virtual void OnResourceVerified(const ResourceCacheInfo* aInfo, bool aSuccess);
|
|
|
|
// Handle all kinds of error during package downloading.
|
|
void OnError(EErrorType aError);
|
|
|
|
// Called when the last part is complete or the resource is from cache.
|
|
void FinalizeDownload(nsresult aStatusCode);
|
|
|
|
// Get the signature from the multipart channel.
|
|
nsCString GetSignatureFromChannel(nsIMultiPartChannel* aChannel);
|
|
|
|
// Start off a resource hash computation and feed the HTTP response header.
|
|
nsresult BeginHashComputation(nsIURI* aURI, nsIRequest* aRequest);
|
|
|
|
// Ensure a packaged app verifier is created.
|
|
void EnsureVerifier(nsIRequest *aRequest);
|
|
|
|
// Handle all tasks about app installation like permission and system message
|
|
// registration.
|
|
void InstallSignedPackagedApp(const ResourceCacheInfo* aInfo);
|
|
|
|
// Calls all the callbacks registered for the given URI.
|
|
// aURI is the full URI of a subresource, composed of packageURI + !// + subresourcePath
|
|
// It passes the cache entry and the result when calling OnCacheEntryAvailable
|
|
nsresult CallCallbacks(nsIURI *aURI, nsICacheEntry *aEntry, nsresult aResult);
|
|
// Clears all the callbacks for this package
|
|
// This would get called at the end of downloading the package and would
|
|
// cause us to call OnCacheEntryAvailable with a null entry. This would be
|
|
// equivalent to a 404 when loading from the net.
|
|
nsresult ClearCallbacks(nsresult aResult);
|
|
// Returns a URI with the subresource's full URI
|
|
// The request must be QIable to nsIResponseHeadProvider since it looks
|
|
// at the Content-Location header to compute the full path.
|
|
static nsresult GetSubresourceURI(nsIRequest * aRequest, nsIURI **aResult);
|
|
// Used to write data into the cache entry of the resource currently being
|
|
// downloaded. It is kept alive until the downloader receives OnStopRequest
|
|
RefPtr<CacheEntryWriter> mWriter;
|
|
// Cached value of nsICacheStorage
|
|
nsCOMPtr<nsICacheStorage> mCacheStorage;
|
|
// A hastable containing all the consumers which requested a resource and need
|
|
// to be notified once it is inserted into the cache.
|
|
// The key is a subresource URI - http://example.com/package.pak!//res.html
|
|
// Should only be used on the main thread.
|
|
nsClassHashtable<nsCStringHashKey, nsCOMArray<nsICacheEntryOpenCallback>> mCallbacks;
|
|
// The key with which this package is inserted in
|
|
// PackagedAppService::mDownloadingPackages
|
|
nsCString mPackageKey;
|
|
|
|
// Whether the package is from the cache
|
|
bool mIsFromCache;
|
|
|
|
// Deal with verification and delegate callbacks to the downloader.
|
|
RefPtr<PackagedAppVerifier> mVerifier;
|
|
|
|
// The outer channels which have issued the request to the downloader.
|
|
nsCOMArray<nsIPackagedAppChannelListener> mRequesters;
|
|
|
|
// The package origin without signed package origin identifier.
|
|
// If you need the origin with the signity taken into account, use
|
|
// PackagedAppVerifier::GetPackageOrigin().
|
|
nsCString mPackageOrigin;
|
|
|
|
//The app id of the package loaded from the LoadContextInfo
|
|
uint32_t mAppId;
|
|
|
|
// A flag to indicate if we are processing the first request.
|
|
bool mProcessingFirstRequest;
|
|
|
|
// A in-memory copy of the manifest content.
|
|
nsCString mManifestContent;
|
|
};
|
|
|
|
// Intercepts OnStartRequest, OnDataAvailable*, OnStopRequest method calls
|
|
// and forwards them to the listener.
|
|
// The target is a `mListener` which converts the package to individual
|
|
// resources and serves them to mDownloader.
|
|
// This class is able to perform conditional actions based on whether the
|
|
// underlying nsIHttpChannel is served from the cache.
|
|
// As this object serves as a listener for the channel, it is kept alive until
|
|
// calling OnStopRequest is completed.
|
|
class PackagedAppChannelListener final
|
|
: public nsIStreamListener
|
|
{
|
|
public:
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSISTREAMLISTENER
|
|
NS_DECL_NSIREQUESTOBSERVER
|
|
|
|
PackagedAppChannelListener(PackagedAppDownloader *aDownloader,
|
|
nsIStreamListener *aListener)
|
|
: mDownloader(aDownloader)
|
|
, mListener(aListener)
|
|
{
|
|
}
|
|
private:
|
|
~PackagedAppChannelListener() { }
|
|
|
|
RefPtr<PackagedAppDownloader> mDownloader;
|
|
nsCOMPtr<nsIStreamListener> mListener; // nsMultiMixedConv
|
|
};
|
|
|
|
// A hashtable of packages that are currently being downloaded.
|
|
// The key is a string formed by concatenating LoadContextInfo and package URI
|
|
// Should only be used on the main thread.
|
|
nsRefPtrHashtable<nsCStringHashKey, PackagedAppDownloader> mDownloadingPackages;
|
|
};
|
|
|
|
|
|
} // namespace net
|
|
} // namespace mozilla
|
|
|
|
#endif // mozilla_net_PackagedAppService_h
|