зеркало из https://github.com/mozilla/gecko-dev.git
Bug 818667 - Put HTTP cache into app jars. r=michal.novotny
This commit is contained in:
Родитель
84d274cfbc
Коммит
b8e77d1643
|
@ -77,22 +77,6 @@ AccumulateCacheHitTelemetry(Telemetry::ID deviceHistogram,
|
|||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
GetCacheSessionNameForStoragePolicy(nsCacheStoragePolicy storagePolicy,
|
||||
bool isPrivate)
|
||||
{
|
||||
MOZ_ASSERT(!isPrivate || storagePolicy == nsICache::STORE_IN_MEMORY);
|
||||
|
||||
switch (storagePolicy) {
|
||||
case nsICache::STORE_IN_MEMORY:
|
||||
return isPrivate ? "HTTP-memory-only-PB" : "HTTP-memory-only";
|
||||
case nsICache::STORE_OFFLINE:
|
||||
return "HTTP-offline";
|
||||
default:
|
||||
return "HTTP";
|
||||
}
|
||||
}
|
||||
|
||||
// Computes and returns a SHA1 hash of the input buffer. The input buffer
|
||||
// must be a null-terminated string.
|
||||
nsresult
|
||||
|
@ -2480,6 +2464,18 @@ nsHttpChannel::OnOfflineCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
|
|||
return OpenNormalCacheEntry(usingSSL);
|
||||
}
|
||||
|
||||
static void
|
||||
GetAppInfo(nsIChannel* aChannel, uint32_t* aAppId, bool* aIsInBrowser)
|
||||
{
|
||||
nsCOMPtr<nsILoadContext> loadContext;
|
||||
NS_QueryNotificationCallbacks(aChannel, loadContext);
|
||||
*aAppId = NECKO_NO_APP_ID;
|
||||
*aIsInBrowser = false;
|
||||
if (loadContext) {
|
||||
loadContext->GetAppId(aAppId);
|
||||
loadContext->GetIsInBrowserElement(aIsInBrowser);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpChannel::OpenNormalCacheEntry(bool usingSSL)
|
||||
|
@ -2488,9 +2484,14 @@ nsHttpChannel::OpenNormalCacheEntry(bool usingSSL)
|
|||
|
||||
nsresult rv;
|
||||
|
||||
uint32_t appId;
|
||||
bool isInBrowser;
|
||||
GetAppInfo(this, &appId, &isInBrowser);
|
||||
|
||||
nsCacheStoragePolicy storagePolicy = DetermineStoragePolicy();
|
||||
nsDependentCString clientID(
|
||||
GetCacheSessionNameForStoragePolicy(storagePolicy, mPrivateBrowsing));
|
||||
nsAutoCString clientID;
|
||||
nsHttpHandler::GetCacheSessionNameForStoragePolicy(storagePolicy, mPrivateBrowsing,
|
||||
appId, isInBrowser, clientID);
|
||||
|
||||
nsAutoCString cacheKey;
|
||||
GenerateCacheKey(mPostID, cacheKey);
|
||||
|
@ -5897,20 +5898,25 @@ nsHttpChannel::DoInvalidateCacheEntry(const nsCString &key)
|
|||
// The logic below deviates from the original logic in OpenCacheEntry on
|
||||
// one point by using only READ_ONLY access-policy. I think this is safe.
|
||||
|
||||
uint32_t appId;
|
||||
bool isInBrowser;
|
||||
GetAppInfo(this, &appId, &isInBrowser);
|
||||
|
||||
// First, find session holding the cache-entry - use current storage-policy
|
||||
nsCacheStoragePolicy storagePolicy = DetermineStoragePolicy();
|
||||
const char * clientID =
|
||||
GetCacheSessionNameForStoragePolicy(storagePolicy, mPrivateBrowsing);
|
||||
nsAutoCString clientID;
|
||||
nsHttpHandler::GetCacheSessionNameForStoragePolicy(storagePolicy, mPrivateBrowsing,
|
||||
appId, isInBrowser, clientID);
|
||||
|
||||
LOG(("DoInvalidateCacheEntry [channel=%p session=%s policy=%d key=%s]",
|
||||
this, clientID, int(storagePolicy), key.get()));
|
||||
this, clientID.get(), int(storagePolicy), key.get()));
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = serv->CreateSession(clientID, storagePolicy,
|
||||
rv = serv->CreateSession(clientID.get(), storagePolicy,
|
||||
nsICache::STREAM_BASED,
|
||||
getter_AddRefs(session));
|
||||
}
|
||||
|
@ -5922,7 +5928,7 @@ nsHttpChannel::DoInvalidateCacheEntry(const nsCString &key)
|
|||
}
|
||||
|
||||
LOG(("DoInvalidateCacheEntry [channel=%p session=%s policy=%d key=%s rv=%d]",
|
||||
this, clientID, int(storagePolicy), key.get(), int(rv)));
|
||||
this, clientID.get(), int(storagePolicy), key.get(), int(rv)));
|
||||
}
|
||||
|
||||
nsCacheStoragePolicy
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "nsSocketTransportService2.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "ASpdySession.h"
|
||||
#include "mozIApplicationClearPrivateDataParams.h"
|
||||
|
||||
#include "nsIXULAppInfo.h"
|
||||
|
||||
|
@ -325,6 +326,7 @@ nsHttpHandler::Init()
|
|||
mObserverService->AddObserver(this, "net:prune-dead-connections", true);
|
||||
mObserverService->AddObserver(this, "net:failed-to-process-uri-content", true);
|
||||
mObserverService->AddObserver(this, "last-pb-context-exited", true);
|
||||
mObserverService->AddObserver(this, "webapps-clear-data", true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1581,10 +1583,62 @@ nsHttpHandler::GetMisc(nsACString &value)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
nsHttpHandler::GetCacheSessionNameForStoragePolicy(
|
||||
nsCacheStoragePolicy storagePolicy,
|
||||
bool isPrivate,
|
||||
uint32_t appId,
|
||||
bool inBrowser,
|
||||
nsACString& sessionName)
|
||||
{
|
||||
MOZ_ASSERT(!isPrivate || storagePolicy == nsICache::STORE_IN_MEMORY);
|
||||
|
||||
switch (storagePolicy) {
|
||||
case nsICache::STORE_IN_MEMORY:
|
||||
sessionName.AssignASCII(isPrivate ? "HTTP-memory-only-PB" : "HTTP-memory-only");
|
||||
break;
|
||||
case nsICache::STORE_OFFLINE:
|
||||
sessionName.AssignLiteral("HTTP-offline");
|
||||
break;
|
||||
default:
|
||||
sessionName.AssignLiteral("HTTP");
|
||||
break;
|
||||
}
|
||||
if (appId != NECKO_NO_APP_ID || inBrowser) {
|
||||
sessionName.Append('~');
|
||||
sessionName.AppendInt(appId);
|
||||
sessionName.Append('~');
|
||||
sessionName.AppendInt(inBrowser);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpHandler::nsIObserver
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void
|
||||
EvictCacheSession(nsCacheStoragePolicy aPolicy,
|
||||
bool aPrivateBrowsing,
|
||||
uint32_t aAppId,
|
||||
bool aInBrowser)
|
||||
{
|
||||
nsAutoCString clientId;
|
||||
nsHttpHandler::GetCacheSessionNameForStoragePolicy(aPolicy,
|
||||
aPrivateBrowsing,
|
||||
aAppId, aInBrowser,
|
||||
clientId);
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID);
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
nsresult rv = serv->CreateSession(clientId.get(),
|
||||
nsICache::STORE_ANYWHERE,
|
||||
nsICache::STREAM_BASED,
|
||||
getter_AddRefs(session));
|
||||
if (NS_SUCCEEDED(rv) && session) {
|
||||
session->EvictEntries();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpHandler::Observe(nsISupports *subject,
|
||||
const char *topic,
|
||||
|
@ -1635,6 +1689,45 @@ nsHttpHandler::Observe(nsISupports *subject,
|
|||
else if (strcmp(topic, "last-pb-context-exited") == 0) {
|
||||
mPrivateAuthCache.ClearAll();
|
||||
}
|
||||
else if (strcmp(topic, "webapps-clear-data") == 0) {
|
||||
nsCOMPtr<mozIApplicationClearPrivateDataParams> params =
|
||||
do_QueryInterface(subject);
|
||||
if (!params) {
|
||||
NS_ERROR("'webapps-clear-data' notification's subject should be a mozIApplicationClearPrivateDataParams");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
uint32_t appId;
|
||||
bool browserOnly;
|
||||
nsresult rv = params->GetAppId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = params->GetBrowserOnly(&browserOnly);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MOZ_ASSERT(appId != NECKO_UNKNOWN_APP_ID);
|
||||
|
||||
// Now we ensure that all unique session name combinations are cleared.
|
||||
struct {
|
||||
nsCacheStoragePolicy policy;
|
||||
bool privateBrowsing;
|
||||
} policies[] = { {nsICache::STORE_OFFLINE, false},
|
||||
{nsICache::STORE_IN_MEMORY, false},
|
||||
{nsICache::STORE_IN_MEMORY, true},
|
||||
{nsICache::STORE_ON_DISK, false} };
|
||||
|
||||
for (uint32_t i = 0; i < NS_ARRAY_LENGTH(policies); i++) {
|
||||
EvictCacheSession(policies[i].policy,
|
||||
policies[i].privateBrowsing,
|
||||
appId, browserOnly);
|
||||
|
||||
if (!browserOnly) {
|
||||
EvictCacheSession(policies[i].policy,
|
||||
policies[i].privateBrowsing,
|
||||
appId, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -253,6 +253,12 @@ public:
|
|||
// returns true in between Init and Shutdown states
|
||||
bool Active() { return mHandlerActive; }
|
||||
|
||||
static void GetCacheSessionNameForStoragePolicy(
|
||||
nsCacheStoragePolicy storagePolicy,
|
||||
bool isPrivate,
|
||||
uint32_t appId,
|
||||
bool inBrowser,
|
||||
nsACString& sessionName);
|
||||
private:
|
||||
|
||||
//
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
var httpserv = null;
|
||||
var handlers_called = 0;
|
||||
|
||||
function cached_handler(metadata, response) {
|
||||
response.setHeader("Content-Type", "text/plain", false);
|
||||
response.setHeader("Cache-Control", "max-age=10000", false);
|
||||
response.setStatusLine(metadata.httpVersion, 200, "OK");
|
||||
var body = "0123456789";
|
||||
response.bodyOutputStream.write(body, body.length);
|
||||
handlers_called++;
|
||||
}
|
||||
|
||||
function makeChan(url, appId, inBrowser) {
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
||||
var chan = ios.newChannel(url, null, null).QueryInterface(Ci.nsIHttpChannel);
|
||||
chan.notificationCallbacks = {
|
||||
appId: appId,
|
||||
isInBrowserElement: inBrowser,
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Ci.nsILoadContext))
|
||||
return this;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
getInterface: function(iid) { return this.QueryInterface(iid); }
|
||||
};
|
||||
return chan;
|
||||
}
|
||||
|
||||
var firstTests = [[0, false, 1], [0, true, 1], [1, false, 1], [1, true, 1]];
|
||||
var secondTests = [[0, false, 0], [0, true, 0], [1, false, 0], [1, true, 1]];
|
||||
var thirdTests = [[0, false, 0], [0, true, 0], [1, false, 1], [1, true, 1]];
|
||||
|
||||
function run_all_tests() {
|
||||
for (let test of firstTests) {
|
||||
handlers_called = 0;
|
||||
var chan = makeChan("http://localhost:4444/cached", test[0], test[1]);
|
||||
chan.asyncOpen(new ChannelListener(doneFirstLoad, test[2]), null);
|
||||
yield;
|
||||
}
|
||||
|
||||
// We can't easily cause webapp data to be cleared from the child process, so skip
|
||||
// the rest of these tests.
|
||||
let procType = Cc["@mozilla.org/xre/runtime;1"].getService(Ci.nsIXULRuntime).processType;
|
||||
if (procType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT)
|
||||
return;
|
||||
|
||||
let subject = {
|
||||
appId: 1,
|
||||
browserOnly: true,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.mozIApplicationClearPrivateDataParams])
|
||||
};
|
||||
Services.obs.notifyObservers(subject, "webapps-clear-data", null);
|
||||
|
||||
for (let test of secondTests) {
|
||||
handlers_called = 0;
|
||||
var chan = makeChan("http://localhost:4444/cached", test[0], test[1]);
|
||||
chan.asyncOpen(new ChannelListener(doneFirstLoad, test[2]), null);
|
||||
yield;
|
||||
}
|
||||
|
||||
subject = {
|
||||
appId: 1,
|
||||
browserOnly: false,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.mozIApplicationClearPrivateDataParams])
|
||||
};
|
||||
Services.obs.notifyObservers(subject, "webapps-clear-data", null);
|
||||
|
||||
for (let test of thirdTests) {
|
||||
handlers_called = 0;
|
||||
var chan = makeChan("http://localhost:4444/cached", test[0], test[1]);
|
||||
chan.asyncOpen(new ChannelListener(doneFirstLoad, test[2]), null);
|
||||
yield;
|
||||
}
|
||||
}
|
||||
|
||||
let gTests;
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
httpserv = new HttpServer();
|
||||
httpserv.registerPathHandler("/cached", cached_handler);
|
||||
httpserv.start(4444);
|
||||
gTests = run_all_tests();
|
||||
gTests.next();
|
||||
}
|
||||
|
||||
function doneFirstLoad(req, buffer, expected) {
|
||||
// Load it again, make sure it hits the cache
|
||||
var chan = makeChan("http://localhost:4444/cached", 0, false);
|
||||
chan.asyncOpen(new ChannelListener(doneSecondLoad, expected), null);
|
||||
}
|
||||
|
||||
function doneSecondLoad(req, buffer, expected) {
|
||||
do_check_eq(handlers_called, expected);
|
||||
try {
|
||||
gTests.next();
|
||||
} catch (x) {
|
||||
do_test_finished();
|
||||
}
|
||||
}
|
|
@ -94,6 +94,7 @@ fail-if = os == "android"
|
|||
[test_bug770243.js]
|
||||
[test_doomentry.js]
|
||||
[test_cacheflags.js]
|
||||
[test_cache_jar.js]
|
||||
[test_channel_close.js]
|
||||
[test_compareURIs.js]
|
||||
[test_compressappend.js]
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
function run_test() {
|
||||
run_test_in_child("../unit/test_cache_jar.js");
|
||||
}
|
|
@ -4,6 +4,7 @@ tail =
|
|||
|
||||
[test_bug248970_cookie_wrap.js]
|
||||
[test_cacheflags_wrap.js]
|
||||
[test_cache_jar_wrap.js]
|
||||
[test_channel_close_wrap.js]
|
||||
[test_cookie_header_wrap.js]
|
||||
[test_cookiejars_wrap.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче