mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 1187159 - Pass principal and flags from the requesting channel to the packaged app channel r=honzab
This commit is contained in:
parent
bc5665176b
commit
1e73e39a9d
@ -5,7 +5,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsIPrincipal;
|
||||
interface nsILoadContextInfo;
|
||||
interface nsICacheEntryOpenCallback;
|
||||
|
||||
@ -16,27 +16,35 @@ interface nsICacheEntryOpenCallback;
|
||||
/**
|
||||
* nsIPackagedAppService
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(77f9a34d-d082-43f1-9f83-e852d0173cd5)]
|
||||
[scriptable, builtinclass, uuid(f35e5229-d08a-46eb-a574-2db4e22aee98)]
|
||||
interface nsIPackagedAppService : nsISupports
|
||||
{
|
||||
/**
|
||||
* @aURI is a URL to a packaged resource
|
||||
* - format: package_url + PACKAGED_APP_TOKEN + resource_path
|
||||
* - example: http://test.com/path/to/package!//resource.html
|
||||
* @aCallback is an object implementing nsICacheEntryOpenCallback
|
||||
* - this is the target of the async result of the operation
|
||||
* - aCallback->OnCacheEntryCheck() is called to verify the entry is valid
|
||||
* - aCallback->OnCacheEntryAvailable() is called with a pointer to the
|
||||
* @param aPrincipal
|
||||
* the principal associated to the URL of a packaged resource
|
||||
* URL format: package_url + PACKAGED_APP_TOKEN + resource_path
|
||||
* example: http://test.com/path/to/package!//resource.html
|
||||
* @param aFlags
|
||||
* the load flags used for downloading the package
|
||||
* @param aCallback
|
||||
* an object implementing nsICacheEntryOpenCallback
|
||||
* this is the target of the async result of the operation
|
||||
* aCallback->OnCacheEntryCheck() is called to verify the entry is valid
|
||||
* aCallback->OnCacheEntryAvailable() is called with a pointer to the
|
||||
* the cached entry, if one exists, or an error code otherwise
|
||||
* - aCallback is kept alive using an nsCOMPtr until OnCacheEntryAvailable
|
||||
* aCallback is kept alive using an nsCOMPtr until OnCacheEntryAvailable
|
||||
* is called
|
||||
* @aInfo is an object used to determine the cache jar this resource goes in.
|
||||
* - usually created by calling GetLoadContextInfo(requestingChannel)
|
||||
* @param aInfo
|
||||
* an object used to determine the cache jar this resource goes in.
|
||||
* usually created by calling GetLoadContextInfo(requestingChannel)
|
||||
*
|
||||
* Calling this method will either download the package containing the given
|
||||
* resource URI, store it in the cache and pass the cache entry to aCallback,
|
||||
* or if that resource has already been downloaded it will be served from
|
||||
* the cache.
|
||||
*/
|
||||
void requestURI(in nsIURI aURI, in nsILoadContextInfo aInfo, in nsICacheEntryOpenCallback aCallback);
|
||||
void getResource(in nsIPrincipal aPrincipal,
|
||||
in uint32_t aFlags,
|
||||
in nsILoadContextInfo aInfo,
|
||||
in nsICacheEntryOpenCallback aCallback);
|
||||
};
|
||||
|
@ -605,23 +605,30 @@ PackagedAppService::GetPackageURI(nsIURI *aURI, nsIURI **aPackageURI)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PackagedAppService::RequestURI(nsIURI *aURI,
|
||||
PackagedAppService::GetResource(nsIPrincipal *aPrincipal,
|
||||
uint32_t aLoadFlags,
|
||||
nsILoadContextInfo *aInfo,
|
||||
nsICacheEntryOpenCallback *aCallback)
|
||||
{
|
||||
// Check arguments are not null
|
||||
if (!aURI || !aCallback || !aInfo) {
|
||||
if (!aPrincipal || !aCallback || !aInfo) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
||||
nsresult rv;
|
||||
LogURI("PackagedAppService::RequestURI", this, aURI, aInfo);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
LogURI("PackagedAppService::GetResource", this, uri, aInfo);
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread(), "mDownloadingPackages hashtable is not thread safe");
|
||||
|
||||
nsCOMPtr<nsIURI> packageURI;
|
||||
rv = GetPackageURI(aURI, getter_AddRefs(packageURI));
|
||||
rv = GetPackageURI(uri, getter_AddRefs(packageURI));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -643,22 +650,15 @@ PackagedAppService::RequestURI(nsIURI *aURI,
|
||||
// downloaded, we will add the callback to the package's queue, and it will
|
||||
// be called once the file is processed and saved in the cache.
|
||||
|
||||
downloader->AddCallback(aURI, aCallback);
|
||||
downloader->AddCallback(uri, aCallback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We need to set this flag, because the package metadata
|
||||
// needs to have a separate entry for anonymous channels.
|
||||
uint32_t extra_flags = 0;
|
||||
if (aInfo->IsAnonymous()) {
|
||||
extra_flags = nsIRequest::LOAD_ANONYMOUS;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewChannel(
|
||||
getter_AddRefs(channel), packageURI, nsContentUtils::GetSystemPrincipal(),
|
||||
getter_AddRefs(channel), packageURI, aPrincipal,
|
||||
nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_OTHER, nullptr, nullptr,
|
||||
nsIRequest::LOAD_NORMAL | extra_flags);
|
||||
aLoadFlags);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
@ -678,7 +678,7 @@ PackagedAppService::RequestURI(nsIURI *aURI,
|
||||
return rv;
|
||||
}
|
||||
|
||||
downloader->AddCallback(aURI, aCallback);
|
||||
downloader->AddCallback(uri, aCallback);
|
||||
|
||||
nsCOMPtr<nsIStreamConverterService> streamconv =
|
||||
do_GetService("@mozilla.org/streamConverters;1", &rv);
|
||||
|
@ -23,10 +23,7 @@ class nsHttpResponseHead;
|
||||
// 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 requestURI(aURI, aInfo, aCallback)
|
||||
// aURI is the subresource uri - http://domain.com/path/package!//resource.html
|
||||
// aInfo is a nsILoadContextInfo used to pick the cache jar the resource goes into
|
||||
// aCallback is the target of the async call to requestURI
|
||||
// Downloading the package is triggered by calling getResource()
|
||||
class PackagedAppService final
|
||||
: public nsIPackagedAppService
|
||||
{
|
||||
|
@ -5197,6 +5197,10 @@ nsHttpChannel::BeginConnect()
|
||||
// If this is a packaged app resource, the content will be fetched
|
||||
// by the packaged app service into the cache, and the cache entry will
|
||||
// be passed to OnCacheEntryAvailable.
|
||||
|
||||
// Pass the original load flags to the packaged app request.
|
||||
uint32_t loadFlags = mLoadFlags;
|
||||
|
||||
mLoadFlags |= LOAD_ONLY_FROM_CACHE;
|
||||
mLoadFlags |= LOAD_FROM_CACHE;
|
||||
mLoadFlags &= ~VALIDATE_ALWAYS;
|
||||
@ -5207,7 +5211,8 @@ nsHttpChannel::BeginConnect()
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = pas->RequestURI(mURI, GetLoadContextInfo(this), this);
|
||||
nsCOMPtr<nsIPrincipal> principal = GetURIPrincipal();
|
||||
rv = pas->GetResource(principal, loadFlags, GetLoadContextInfo(this), this);
|
||||
if (NS_FAILED(rv)) {
|
||||
AsyncAbort(rv);
|
||||
}
|
||||
|
@ -7,14 +7,14 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// test_bad_args
|
||||
// - checks that calls to nsIPackagedAppService::requestURI do not accept a null argument
|
||||
// - checks that calls to nsIPackagedAppService::GetResource do not accept a null argument
|
||||
// test_callback_gets_called
|
||||
// - checks the regular use case -> requesting a resource should asynchronously return an entry
|
||||
// test_same_content
|
||||
// - makes another request for the same file, and checks that the same content is returned
|
||||
// test_request_number
|
||||
// - this test does not make a request, but checks that the package has only
|
||||
// been requested once. The entry returned by the call to requestURI in
|
||||
// been requested once. The entry returned by the call to getResource in
|
||||
// test_same_content should be returned from the cache.
|
||||
//
|
||||
// test_package_does_not_exist
|
||||
@ -59,6 +59,13 @@ function packagedAppContentHandler(metadata, response)
|
||||
response.bodyOutputStream.write(body, body.length);
|
||||
}
|
||||
|
||||
function getPrincipal(url) {
|
||||
let uri = createURI(url);
|
||||
return Components.classes["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Ci.nsIScriptSecurityManager)
|
||||
.getNoAppCodebasePrincipal(uri);
|
||||
}
|
||||
|
||||
// The package content
|
||||
// getData formats it as described at http://www.w3.org/TR/web-packaging/#streamable-package-format
|
||||
var testData = {
|
||||
@ -92,7 +99,7 @@ XPCOMUtils.defineLazyGetter(this, "uri", function() {
|
||||
var httpserver = null;
|
||||
// The packaged app service initialized in run_test
|
||||
var paservice = null;
|
||||
// This variable is set before requestURI is called. The listener uses this variable
|
||||
// This variable is set before getResource is called. The listener uses this variable
|
||||
// to check the correct resource path for the returned entry
|
||||
var packagePath = null;
|
||||
|
||||
@ -170,10 +177,10 @@ var cacheListener = new packagedResourceListener(testData.content[0].data);
|
||||
|
||||
// These calls should fail, since one of the arguments is invalid or null
|
||||
function test_bad_args() {
|
||||
Assert.throws(() => { paservice.requestURI(createURI("http://test.com"), LoadContextInfo.default, cacheListener); }, "url's with no !// aren't allowed");
|
||||
Assert.throws(() => { paservice.requestURI(createURI("http://test.com/package!//test"), LoadContextInfo.default, null); }, "should have a callback");
|
||||
Assert.throws(() => { paservice.requestURI(null, LoadContextInfo.default, cacheListener); }, "should have a URI");
|
||||
Assert.throws(() => { paservice.requestURI(createURI("http://test.com/package!//test"), null, cacheListener); }, "should have a LoadContextInfo");
|
||||
Assert.throws(() => { paservice.getResource(getPrincipal("http://test.com"), 0, LoadContextInfo.default, cacheListener); }, "url's with no !// aren't allowed");
|
||||
Assert.throws(() => { paservice.getResource(getPrincipal("http://test.com/package!//test"), 0, LoadContextInfo.default, null); }, "should have a callback");
|
||||
Assert.throws(() => { paservice.getResource(null, 0, LoadContextInfo.default, cacheListener); }, "should have a URI");
|
||||
Assert.throws(() => { paservice.getResource(getPrincipal("http://test.com/package!//test"), null, cacheListener); }, "should have a LoadContextInfo");
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
@ -182,13 +189,13 @@ function test_bad_args() {
|
||||
// This tests that the callback gets called, and the cacheListener gets the proper content.
|
||||
function test_callback_gets_called() {
|
||||
packagePath = "/package";
|
||||
paservice.requestURI(createURI(uri + packagePath + "!//index.html"), LoadContextInfo.default, cacheListener);
|
||||
paservice.getResource(getPrincipal(uri + packagePath + "!//index.html"), 0, LoadContextInfo.default, cacheListener);
|
||||
}
|
||||
|
||||
// Tests that requesting the same resource returns the same content
|
||||
function test_same_content() {
|
||||
packagePath = "/package";
|
||||
paservice.requestURI(createURI(uri + packagePath + "!//index.html"), LoadContextInfo.default, cacheListener);
|
||||
paservice.getResource(getPrincipal(uri + packagePath + "!//index.html"), 0, LoadContextInfo.default, cacheListener);
|
||||
}
|
||||
|
||||
// Check the content handler has been called the expected number of times.
|
||||
@ -200,7 +207,7 @@ function test_request_number() {
|
||||
// This tests that new content is returned if the package has been updated
|
||||
function test_updated_package() {
|
||||
packagePath = "/package";
|
||||
paservice.requestURI(createURI(uri + packagePath + "!//index.html"), LoadContextInfo.default,
|
||||
paservice.getResource(getPrincipal(uri + packagePath + "!//index.html"), 0, LoadContextInfo.default,
|
||||
new packagedResourceListener(testData.content[0].data.replace(/\.\.\./g, 'xxx')));
|
||||
}
|
||||
|
||||
@ -224,13 +231,13 @@ var listener404 = {
|
||||
// Tests that an error is returned for a non existing package
|
||||
function test_package_does_not_exist() {
|
||||
packagePath = "/package_non_existent";
|
||||
paservice.requestURI(createURI(uri + packagePath + "!//index.html"), LoadContextInfo.default, listener404);
|
||||
paservice.getResource(getPrincipal(uri + packagePath + "!//index.html"), 0, LoadContextInfo.default, listener404);
|
||||
}
|
||||
|
||||
// Tests that an error is returned for a non existing resource in a package
|
||||
function test_file_does_not_exist() {
|
||||
packagePath = "/package"; // This package exists
|
||||
paservice.requestURI(createURI(uri + packagePath + "!//file_non_existent.html"), LoadContextInfo.default, listener404);
|
||||
paservice.getResource(getPrincipal(uri + packagePath + "!//file_non_existent.html"), 0, LoadContextInfo.default, listener404);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -271,13 +278,13 @@ function packagedAppBadContentHandler(metadata, response)
|
||||
// Checks that the resource with the proper headers inside the bad package is still returned
|
||||
function test_bad_package() {
|
||||
packagePath = "/badPackage";
|
||||
paservice.requestURI(createURI(uri + packagePath + "!//index.html"), LoadContextInfo.default, cacheListener);
|
||||
paservice.getResource(getPrincipal(uri + packagePath + "!//index.html"), 0, LoadContextInfo.default, cacheListener);
|
||||
}
|
||||
|
||||
// Checks that the request for a non-existent resource doesn't hang for a bad package
|
||||
function test_bad_package_404() {
|
||||
packagePath = "/badPackage";
|
||||
paservice.requestURI(createURI(uri + packagePath + "!//file_non_existent.html"), LoadContextInfo.default, listener404);
|
||||
paservice.getResource(getPrincipal(uri + packagePath + "!//file_non_existent.html"), 0, LoadContextInfo.default, listener404);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user