зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1196021 - Pass requesting channel to PackagedAppService::GetResource r=ckerschb
This commit is contained in:
Родитель
ac53c9a29f
Коммит
7833654240
|
@ -5,10 +5,8 @@
|
|||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIPrincipal;
|
||||
interface nsILoadContextInfo;
|
||||
interface nsIChannel;
|
||||
interface nsICacheEntryOpenCallback;
|
||||
interface nsILoadInfo;
|
||||
|
||||
%{C++
|
||||
#define PACKAGED_APP_TOKEN "!//"
|
||||
|
@ -17,16 +15,16 @@ interface nsILoadInfo;
|
|||
/**
|
||||
* nsIPackagedAppService
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(b36efde7-6596-4082-a5fc-fc223148489f)]
|
||||
[scriptable, builtinclass, uuid(9c96c638-e80c-4dce-abec-c96fdb7a25d8)]
|
||||
interface nsIPackagedAppService : nsISupports
|
||||
{
|
||||
/**
|
||||
* @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 aChannel
|
||||
* this param is passed to the packaged app service in order to provide
|
||||
* info about the requesting channel, which wants to access the contents
|
||||
* of a packaged app resource. Its URI has the following format:
|
||||
* http://domain.com/path/to/package.pak!//path/to/subresource.html
|
||||
*
|
||||
* @param aCallback
|
||||
* an object implementing nsICacheEntryOpenCallback
|
||||
* this is the target of the async result of the operation
|
||||
|
@ -35,18 +33,12 @@ interface nsIPackagedAppService : nsISupports
|
|||
* the cached entry, if one exists, or an error code otherwise
|
||||
* aCallback is kept alive using an nsCOMPtr until OnCacheEntryAvailable
|
||||
* is called
|
||||
* @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 getResource(in nsIPrincipal aPrincipal,
|
||||
in nsILoadInfo aLoadInfo,
|
||||
in uint32_t aFlags,
|
||||
in nsILoadContextInfo aInfo,
|
||||
void getResource(in nsIChannel aChannel,
|
||||
in nsICacheEntryOpenCallback aCallback);
|
||||
};
|
||||
|
|
|
@ -690,29 +690,55 @@ PackagedAppService::GetPackageURI(nsIURI *aURI, nsIURI **aPackageURI)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PackagedAppService::GetResource(nsIPrincipal *aPrincipal,
|
||||
nsILoadInfo *aLoadInfo,
|
||||
uint32_t aLoadFlags,
|
||||
nsILoadContextInfo *aInfo,
|
||||
PackagedAppService::GetResource(nsIChannel *aChannel,
|
||||
nsICacheEntryOpenCallback *aCallback)
|
||||
{
|
||||
// Check arguments are not null
|
||||
if (!aPrincipal || !aLoadInfo || !aCallback || !aInfo) {
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread(), "mDownloadingPackages hashtable is not thread safe");
|
||||
LOG(("[%p] PackagedAppService::GetResource(aChannel: %p, aCallback: %p)\n",
|
||||
this, aChannel, aCallback));
|
||||
|
||||
if (!aChannel || !aCallback) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsIScriptSecurityManager *securityManager =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
if (!securityManager) {
|
||||
LOG(("[%p] > No securityManager\n", this));
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
rv = securityManager->GetChannelURIPrincipal(aChannel, getter_AddRefs(principal));
|
||||
if (NS_FAILED(rv) || !principal) {
|
||||
LOG(("[%p] > Error getting principal rv=%X principal=%p\n",
|
||||
this, rv, principal.get()));
|
||||
return NS_FAILED(rv) ? rv : NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
nsCOMPtr<nsILoadContextInfo> loadContextInfo = GetLoadContextInfo(aChannel);
|
||||
if (!loadContextInfo) {
|
||||
LOG(("[%p] > Channel has no loadContextInfo\n", this));
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsLoadFlags loadFlags = 0;
|
||||
rv = aChannel->GetLoadFlags(&loadFlags);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("[%p] > Error calling GetLoadFlags rv=%X\n", this, rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
LogURI("PackagedAppService::GetResource", this, uri, aInfo);
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread(), "mDownloadingPackages hashtable is not thread safe");
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = principal->GetURI(getter_AddRefs(uri));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
LOG(("[%p] > Error calling GetURI rv=%X\n", this, rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
LogURI("PackagedAppService::GetResource", this, uri, loadContextInfo);
|
||||
nsCOMPtr<nsIURI> packageURI;
|
||||
rv = GetPackageURI(uri, getter_AddRefs(packageURI));
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -720,7 +746,7 @@ PackagedAppService::GetResource(nsIPrincipal *aPrincipal,
|
|||
}
|
||||
|
||||
nsAutoCString key;
|
||||
CacheFileUtils::AppendKeyPrefix(aInfo, key);
|
||||
CacheFileUtils::AppendKeyPrefix(loadContextInfo, key);
|
||||
|
||||
{
|
||||
nsAutoCString spec;
|
||||
|
@ -743,8 +769,8 @@ PackagedAppService::GetResource(nsIPrincipal *aPrincipal,
|
|||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewChannelInternal(
|
||||
getter_AddRefs(channel), packageURI,
|
||||
aLoadInfo,
|
||||
nullptr, nullptr, aLoadFlags);
|
||||
loadInfo,
|
||||
nullptr, nullptr, loadFlags);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -759,7 +785,7 @@ PackagedAppService::GetResource(nsIPrincipal *aPrincipal,
|
|||
}
|
||||
|
||||
downloader = new PackagedAppDownloader();
|
||||
rv = downloader->Init(aInfo, key);
|
||||
rv = downloader->Init(loadContextInfo, key);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -785,7 +811,7 @@ PackagedAppService::GetResource(nsIPrincipal *aPrincipal,
|
|||
nsRefPtr<PackagedAppChannelListener> listener =
|
||||
new PackagedAppChannelListener(downloader, mimeConverter);
|
||||
|
||||
if (aLoadInfo->GetEnforceSecurity()) {
|
||||
if (loadInfo && loadInfo->GetEnforceSecurity()) {
|
||||
return channel->AsyncOpen2(listener);
|
||||
}
|
||||
|
||||
|
|
|
@ -5206,12 +5206,6 @@ nsHttpChannel::BeginConnect()
|
|||
// 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;
|
||||
nsCOMPtr<nsIPackagedAppService> pas =
|
||||
do_GetService("@mozilla.org/network/packaged-app-service;1", &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -5219,12 +5213,18 @@ nsHttpChannel::BeginConnect()
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = GetURIPrincipal();
|
||||
nsCOMPtr<nsILoadContextInfo> loadContextInfo = GetLoadContextInfo(this);
|
||||
rv = pas->GetResource(principal, mLoadInfo, loadFlags, loadContextInfo, this);
|
||||
rv = pas->GetResource(this, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
AsyncAbort(rv);
|
||||
}
|
||||
|
||||
// We need to alter the flags so the cache entry returned by the
|
||||
// packaged app service is always accepted. Revalidation is handled
|
||||
// by the service.
|
||||
mLoadFlags |= LOAD_ONLY_FROM_CACHE;
|
||||
mLoadFlags |= LOAD_FROM_CACHE;
|
||||
mLoadFlags &= ~VALIDATE_ALWAYS;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,16 +60,24 @@ function packagedAppContentHandler(metadata, response)
|
|||
response.bodyOutputStream.write(body, body.length);
|
||||
}
|
||||
|
||||
function getPrincipal(url) {
|
||||
function getChannelForURL(url) {
|
||||
let uri = createURI(url);
|
||||
let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Ci.nsIScriptSecurityManager);
|
||||
let uri = createURI(url);
|
||||
return ssm.createCodebasePrincipal(uri, {});
|
||||
}
|
||||
let principal = ssm.createCodebasePrincipal(uri, {});
|
||||
let tmpChannel =
|
||||
NetUtil.newChannel({
|
||||
uri: url,
|
||||
loadingPrincipal: principal,
|
||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER
|
||||
});
|
||||
|
||||
function getLoadInfo(url) {
|
||||
let tmpChannel = NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
|
||||
return tmpChannel.loadInfo;
|
||||
tmpChannel.notificationCallbacks =
|
||||
new LoadContextCallback(principal.appId,
|
||||
principal.isInBrowserElement,
|
||||
false,
|
||||
false);
|
||||
return tmpChannel;
|
||||
}
|
||||
|
||||
// The package content
|
||||
|
@ -135,6 +143,15 @@ function run_test()
|
|||
add_test(test_bad_package);
|
||||
add_test(test_bad_package_404);
|
||||
|
||||
// Channels created by addons could have no load info.
|
||||
// In debug mode this triggers an assertion, but we still want to test that
|
||||
// it works in optimized mode. See bug 1196021 comment 17
|
||||
if (Components.classes["@mozilla.org/xpcom/debug;1"]
|
||||
.getService(Components.interfaces.nsIDebug2)
|
||||
.isDebugBuild == false) {
|
||||
add_test(test_channel_no_loadinfo);
|
||||
}
|
||||
|
||||
// run tests
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -185,13 +202,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() {
|
||||
let principal = getPrincipal("http://test.com/package!//test");
|
||||
let loadInfo = getLoadInfo("http://test.com/package!//test");
|
||||
Assert.throws(() => { paservice.getResource(getPrincipal("http://test.com"), loadInfo, 0, LoadContextInfo.default, cacheListener); }, "url's with no !// aren't allowed");
|
||||
Assert.throws(() => { paservice.getResource(principal, loadInfo, 0, LoadContextInfo.default, null); }, "should have a callback");
|
||||
Assert.throws(() => { paservice.getResource(null, loadInfo, 0, LoadContextInfo.default, cacheListener); }, "should have a principal");
|
||||
Assert.throws(() => { paservice.getResource(principal, loadInfo, 0, null, cacheListener); }, "should have a LoadContextInfo");
|
||||
Assert.throws(() => { paservice.getResource(principal, null, 0, LoadContextInfo.default, cacheListener); }, "should have a LoadInfo");
|
||||
Assert.throws(() => { paservice.getResource(getChannelForURL("http://test.com"), cacheListener); }, "url's with no !// aren't allowed");
|
||||
Assert.throws(() => { paservice.getResource(getChannelForURL("http://test.com/package!//test"), null); }, "should have a callback");
|
||||
Assert.throws(() => { paservice.getResource(null, cacheListener); }, "should have a channel");
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
@ -201,14 +215,14 @@ function test_bad_args() {
|
|||
function test_callback_gets_called() {
|
||||
packagePath = "/package";
|
||||
let url = uri + packagePath + "!//index.html";
|
||||
paservice.getResource(getPrincipal(url), getLoadInfo(url), 0, LoadContextInfo.default, cacheListener);
|
||||
paservice.getResource(getChannelForURL(url), cacheListener);
|
||||
}
|
||||
|
||||
// Tests that requesting the same resource returns the same content
|
||||
function test_same_content() {
|
||||
packagePath = "/package";
|
||||
let url = uri + packagePath + "!//index.html";
|
||||
paservice.getResource(getPrincipal(url), getLoadInfo(url), 0, LoadContextInfo.default, cacheListener);
|
||||
paservice.getResource(getChannelForURL(url), cacheListener);
|
||||
}
|
||||
|
||||
// Check the content handler has been called the expected number of times.
|
||||
|
@ -221,8 +235,8 @@ function test_request_number() {
|
|||
function test_updated_package() {
|
||||
packagePath = "/package";
|
||||
let url = uri + packagePath + "!//index.html";
|
||||
paservice.getResource(getPrincipal(url), getLoadInfo(url), 0, LoadContextInfo.default,
|
||||
new packagedResourceListener(testData.content[0].data.replace(/\.\.\./g, 'xxx')));
|
||||
paservice.getResource(getChannelForURL(url),
|
||||
new packagedResourceListener(testData.content[0].data.replace(/\.\.\./g, 'xxx')));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -246,14 +260,14 @@ var listener404 = {
|
|||
function test_package_does_not_exist() {
|
||||
packagePath = "/package_non_existent";
|
||||
let url = uri + packagePath + "!//index.html";
|
||||
paservice.getResource(getPrincipal(url), getLoadInfo(url), 0, LoadContextInfo.default, listener404);
|
||||
paservice.getResource(getChannelForURL(url), 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
|
||||
let url = uri + packagePath + "!//file_non_existent.html";
|
||||
paservice.getResource(getPrincipal(url), getLoadInfo(url), 0, LoadContextInfo.default, listener404);
|
||||
paservice.getResource(getChannelForURL(url), listener404);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -295,14 +309,23 @@ function packagedAppBadContentHandler(metadata, response)
|
|||
function test_bad_package() {
|
||||
packagePath = "/badPackage";
|
||||
let url = uri + packagePath + "!//index.html";
|
||||
paservice.getResource(getPrincipal(url), getLoadInfo(url), 0, LoadContextInfo.default, cacheListener);
|
||||
paservice.getResource(getChannelForURL(url), cacheListener);
|
||||
}
|
||||
|
||||
// Checks that the request for a non-existent resource doesn't hang for a bad package
|
||||
function test_bad_package_404() {
|
||||
packagePath = "/badPackage";
|
||||
let url = uri + packagePath + "!//file_non_existent.html";
|
||||
paservice.getResource(getPrincipal(url), getLoadInfo(url), 0, LoadContextInfo.default, listener404);
|
||||
paservice.getResource(getChannelForURL(url), listener404);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// NOTE: This test only runs in NON-DEBUG mode.
|
||||
function test_channel_no_loadinfo() {
|
||||
packagePath = "/package";
|
||||
let url = uri + packagePath + "!//index.html";
|
||||
let channel = getChannelForURL(url);
|
||||
channel.loadInfo = null;
|
||||
paservice.getResource(channel, cacheListener);
|
||||
}
|
||||
|
|
|
@ -12,16 +12,24 @@ function packagedAppContentHandler(metadata, response)
|
|||
gRequestNo++;
|
||||
}
|
||||
|
||||
function getPrincipal(url) {
|
||||
function getChannelForURL(url) {
|
||||
let uri = createURI(url);
|
||||
let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Ci.nsIScriptSecurityManager);
|
||||
let uri = createURI(url);
|
||||
return ssm.createCodebasePrincipal(uri, {});
|
||||
}
|
||||
let principal = ssm.createCodebasePrincipal(uri, {});
|
||||
let tmpChannel =
|
||||
NetUtil.newChannel({
|
||||
uri: url,
|
||||
loadingPrincipal: principal,
|
||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER
|
||||
});
|
||||
|
||||
function getLoadInfo(url) {
|
||||
let tmpChannel = NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
|
||||
return tmpChannel.loadInfo;
|
||||
tmpChannel.notificationCallbacks =
|
||||
new LoadContextCallback(principal.appId,
|
||||
principal.isInBrowserElement,
|
||||
false,
|
||||
false);
|
||||
return tmpChannel;
|
||||
}
|
||||
|
||||
var subresourcePaths = [
|
||||
|
@ -126,8 +134,7 @@ function test_paths() {
|
|||
packagePath = "/package/" + i;
|
||||
dump("Iteration " + i + "\n");
|
||||
let url = uri + packagePath + "!//" + subresourcePaths[i][1];
|
||||
paservice.getResource(getPrincipal(url), getLoadInfo(url), 0,
|
||||
LoadContextInfo.default,
|
||||
paservice.getResource(getChannelForURL(url),
|
||||
new packagedResourceListener(subresourcePaths[i][1], content));
|
||||
yield undefined;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче