Bug 460353: app caches should be per iframe, not per toplevel browsing context. r=dcamp, r+sr=jst

This commit is contained in:
Honza Bambas 2008-11-05 16:01:07 -08:00
parent 19d2223559
commit c16599cc1d
17 changed files with 312 additions and 208 deletions

View File

@ -1241,14 +1241,14 @@ public:
static nsIAtom* IsNamedItem(nsIContent* aContent);
/**
* Get the application manifest URI for this context. The manifest URI
* Get the application manifest URI for this document. The manifest URI
* is specified in the manifest= attribute of the root element of the
* toplevel window.
* document.
*
* @param aWindow The context to check.
* @param aDocument The document that lists the manifest.
* @param aURI The manifest URI.
*/
static void GetOfflineAppManifest(nsIDOMWindow *aWindow, nsIURI **aURI);
static void GetOfflineAppManifest(nsIDocument *aDocument, nsIURI **aURI);
/**
* Check whether an application should be allowed to use offline APIs.

View File

@ -878,10 +878,11 @@ nsContentSink::GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey)
nsresult
nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
nsIURI *aManifestURI,
PRBool aIsTopDocument,
PRBool aFetchedWithHTTPGetOrEquiv,
CacheSelectionAction *aAction)
{
nsresult rv;
*aAction = CACHE_SELECTION_NONE;
nsCOMPtr<nsIApplicationCacheContainer> applicationCacheDocument =
@ -889,14 +890,9 @@ nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
NS_ASSERTION(applicationCacheDocument,
"mDocument must implement nsIApplicationCacheContainer.");
nsresult rv;
// We might decide on a new application cache...
nsCOMPtr<nsIApplicationCache> applicationCache = aLoadApplicationCache;
if (applicationCache) {
if (aLoadApplicationCache) {
nsCAutoString groupID;
rv = applicationCache->GetGroupID(groupID);
rv = aLoadApplicationCache->GetGroupID(groupID);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> groupURI;
@ -908,34 +904,37 @@ nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
NS_ENSURE_SUCCESS(rv, rv);
if (!equal) {
// This is a foreign entry, mark it as such. If this is a
// toplevel load, force a reload to avoid loading the foreign
// entry. The next attempt will not choose this cache entry
// (because it has been marked foreign).
// This is a foreign entry, mark it as such and force a reload to avoid
// loading the foreign entry. The next attempt will not choose this
// cache entry (because it has been marked foreign).
nsCAutoString cachekey;
rv = GetChannelCacheKey(mDocument->GetChannel(), cachekey);
NS_ENSURE_SUCCESS(rv, rv);
rv = applicationCache->MarkEntry(cachekey,
nsIApplicationCache::ITEM_FOREIGN);
rv = aLoadApplicationCache->MarkEntry(cachekey,
nsIApplicationCache::ITEM_FOREIGN);
NS_ENSURE_SUCCESS(rv, rv);
if (aIsTopDocument) {
*aAction = CACHE_SELECTION_RELOAD;
}
return NS_OK;
*aAction = CACHE_SELECTION_RELOAD;
}
else {
// The http manifest attribute URI is equal to the manifest URI of
// the cache the document was loaded from - associate the document with
// that cache and invoke the cache update process.
#ifdef NS_DEBUG
nsCAutoString docURISpec, clientID;
mDocumentURI->GetAsciiSpec(docURISpec);
aLoadApplicationCache->GetClientID(clientID);
SINK_TRACE(gContentSinkLogModuleInfo, SINK_TRACE_CALLS,
("Selection: assigning app cache %s to document %s", clientID.get(), docURISpec.get()));
#endif
if (aIsTopDocument) {
// This is a top level document and the http manifest attribute
// URI is equal to the manifest URI of the cache the document
// was loaded from - associate the document with that cache and
// invoke the cache update process.
rv = applicationCacheDocument->SetApplicationCache(applicationCache);
rv = applicationCacheDocument->SetApplicationCache(aLoadApplicationCache);
NS_ENSURE_SUCCESS(rv, rv);
// Document will be added as implicit entry to the cache as part of
// the update process.
*aAction = CACHE_SELECTION_UPDATE;
}
}
@ -947,51 +946,12 @@ nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
if (!aFetchedWithHTTPGetOrEquiv) {
// The document was not loaded using HTTP GET or equivalent
// method. The spec says to run the cache selection algorithm w/o
// the manifest specified but we can just do return NS_OK here.
return NS_OK;
}
// If there is an existing application cache for this manifest,
// associate it with the document.
nsCAutoString manifestURISpec;
rv = aManifestURI->GetAsciiSpec(manifestURISpec);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIApplicationCacheService> appCacheService =
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
if (!appCacheService) {
// No application cache service, nothing to do here.
return NS_OK;
}
rv = appCacheService->GetActiveCache(manifestURISpec,
getter_AddRefs(applicationCache));
NS_ENSURE_SUCCESS(rv, rv);
if (applicationCache) {
rv = applicationCacheDocument->SetApplicationCache(applicationCache);
NS_ENSURE_SUCCESS(rv, rv);
// the manifest specified.
*aAction = CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST;
}
else {
// XXX bug 443023: if there is already a scheduled update or
// update in progress we have to add this document as
// an implicit entry.
}
// Always do an update in this case
*aAction = CACHE_SELECTION_UPDATE;
}
if (applicationCache) {
// We are now associated with an application cache. This item
// should be marked as an implicit entry.
nsCAutoString cachekey;
rv = GetChannelCacheKey(mDocument->GetChannel(), cachekey);
if (NS_SUCCEEDED(rv)) {
rv = applicationCache->MarkEntry(cachekey,
nsIApplicationCache::ITEM_IMPLICIT);
NS_ENSURE_SUCCESS(rv, rv);
// Always do an update in this case
*aAction = CACHE_SELECTION_UPDATE;
}
}
@ -1000,39 +960,44 @@ nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
nsresult
nsContentSink::SelectDocAppCacheNoManifest(nsIApplicationCache *aLoadApplicationCache,
PRBool aIsTopDocument,
nsIURI **aManifestURI,
CacheSelectionAction *aAction)
{
*aManifestURI = nsnull;
*aAction = CACHE_SELECTION_NONE;
if (!aIsTopDocument || !aLoadApplicationCache) {
return NS_OK;
}
nsresult rv;
// The document was loaded from an application cache, use that
// application cache as the document's application cache.
nsCOMPtr<nsIApplicationCacheContainer> applicationCacheDocument =
do_QueryInterface(mDocument);
NS_ASSERTION(applicationCacheDocument,
"mDocument must implement nsIApplicationCacheContainer.");
if (aLoadApplicationCache) {
// The document was loaded from an application cache, use that
// application cache as the document's application cache.
nsCOMPtr<nsIApplicationCacheContainer> applicationCacheDocument =
do_QueryInterface(mDocument);
NS_ASSERTION(applicationCacheDocument,
"mDocument must implement nsIApplicationCacheContainer.");
rv = applicationCacheDocument->SetApplicationCache(aLoadApplicationCache);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef NS_DEBUG
nsCAutoString docURISpec, clientID;
mDocumentURI->GetAsciiSpec(docURISpec);
aLoadApplicationCache->GetClientID(clientID);
SINK_TRACE(gContentSinkLogModuleInfo, SINK_TRACE_CALLS,
("Selection, no manifest: assigning app cache %s to document %s", clientID.get(), docURISpec.get()));
#endif
// Return the uri and invoke the update process for the selected
// application cache.
nsCAutoString groupID;
rv = aLoadApplicationCache->GetGroupID(groupID);
NS_ENSURE_SUCCESS(rv, rv);
rv = applicationCacheDocument->SetApplicationCache(aLoadApplicationCache);
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewURI(aManifestURI, groupID);
NS_ENSURE_SUCCESS(rv, rv);
// Return the uri and invoke the update process for the selected
// application cache.
nsCAutoString groupID;
rv = aLoadApplicationCache->GetGroupID(groupID);
NS_ENSURE_SUCCESS(rv, rv);
*aAction = CACHE_SELECTION_UPDATE;
rv = NS_NewURI(aManifestURI, groupID);
NS_ENSURE_SUCCESS(rv, rv);
*aAction = CACHE_SELECTION_UPDATE;
}
return NS_OK;
}
@ -1070,26 +1035,11 @@ nsContentSink::ProcessOfflineManifest(nsIContent *aElement)
return;
}
// The manifest attribute is handled differently if the document is
// not toplevel.
nsCOMPtr<nsIDOMWindow> window = mDocument->GetWindow();
if (!window)
return;
nsCOMPtr<nsIDOMWindow> parent;
window->GetParent(getter_AddRefs(parent));
PRBool isTop = (parent == window);
CacheSelectionAction action = CACHE_SELECTION_NONE;
nsCOMPtr<nsIURI> manifestURI;
if (manifestSpec.IsEmpty()) {
rv = SelectDocAppCacheNoManifest(applicationCache,
isTop,
getter_AddRefs(manifestURI),
&action);
if (NS_FAILED(rv)) {
return;
}
action = CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST;
}
else {
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI),
@ -1102,25 +1052,35 @@ nsContentSink::ProcessOfflineManifest(nsIContent *aElement)
// Documents must list a manifest from the same origin
rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, PR_TRUE);
if (NS_FAILED(rv)) {
return;
action = CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST;
}
else {
// Only continue if the document has permission to use offline APIs.
if (!nsContentUtils::OfflineAppAllowed(mDocument->NodePrincipal())) {
return;
}
// Only continue if the document has permission to use offline APIs.
if (!nsContentUtils::OfflineAppAllowed(mDocument->NodePrincipal())) {
return;
PRBool fetchedWithHTTPGetOrEquiv = PR_FALSE;
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mDocument->GetChannel()));
if (httpChannel) {
nsCAutoString method;
rv = httpChannel->GetRequestMethod(method);
if (NS_SUCCEEDED(rv))
fetchedWithHTTPGetOrEquiv = method.Equals("GET");
}
rv = SelectDocAppCache(applicationCache, manifestURI,
fetchedWithHTTPGetOrEquiv, &action);
if (NS_FAILED(rv)) {
return;
}
}
}
PRBool fetchedWithHTTPGetOrEquiv = PR_FALSE;
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mDocument->GetChannel()));
if (httpChannel) {
nsCAutoString method;
rv = httpChannel->GetRequestMethod(method);
if (NS_SUCCEEDED(rv))
fetchedWithHTTPGetOrEquiv = method.Equals("GET");
}
rv = SelectDocAppCache(applicationCache, manifestURI, isTop,
fetchedWithHTTPGetOrEquiv, &action);
if (action == CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST) {
rv = SelectDocAppCacheNoManifest(applicationCache,
getter_AddRefs(manifestURI),
&action);
if (NS_FAILED(rv)) {
return;
}
@ -1129,7 +1089,7 @@ nsContentSink::ProcessOfflineManifest(nsIContent *aElement)
switch (action)
{
case CACHE_SELECTION_NONE:
return;
break;
case CACHE_SELECTION_UPDATE: {
nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
@ -1143,13 +1103,16 @@ nsContentSink::ProcessOfflineManifest(nsIContent *aElement)
case CACHE_SELECTION_RELOAD: {
// This situation occurs only for toplevel documents, see bottom
// of SelectDocAppCache method.
NS_ASSERTION(isTop, "Should only reload toplevel documents!");
nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(mDocShell);
webNav->Stop(nsIWebNavigation::STOP_ALL);
webNav->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
break;
}
default:
NS_ASSERTION(PR_FALSE,
"Cache selection algorithm didn't decide on proper action");
break;
}
}

View File

@ -167,7 +167,10 @@ protected:
// document. In this case, the document is marked as foreign in
// the cache it was loaded from and must be reloaded from the
// correct cache (the one it specifies).
CACHE_SELECTION_RELOAD = 2
CACHE_SELECTION_RELOAD = 2,
// Some conditions require we must reselect the cache without the manifest
CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST = 3
};
nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
@ -206,8 +209,6 @@ protected:
// any.
// @param aManifestURI
// The manifest URI listed in the document.
// @param aIsTopDocument
// TRUE if this is a toplevel document.
// @param aFetchedWithHTTPGetOrEquiv
// TRUE if this was fetched using the HTTP GET method.
// @param aAction
@ -215,7 +216,6 @@ protected:
// by the calling function.
nsresult SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache,
nsIURI *aManifestURI,
PRBool aIsTopDocument,
PRBool aFetchedWithHTTPGetOrEquiv,
CacheSelectionAction *aAction);
@ -228,8 +228,6 @@ protected:
// @param aLoadApplicationCache
// The application cache from which the load originated, if
// any.
// @param aIsTopDocument
// TRUE if this is a toplevel document.
// @param aManifestURI
// Out parameter, returns the manifest URI of the cache that
// was selected.
@ -237,7 +235,6 @@ protected:
// Out parameter, returns the action that should be performed
// by the calling function.
nsresult SelectDocAppCacheNoManifest(nsIApplicationCache *aLoadApplicationCache,
PRBool aIsTopDocument,
nsIURI **aManifestURI,
CacheSelectionAction *aAction);

View File

@ -798,22 +798,9 @@ nsContentUtils::IsHTMLWhitespace(PRUnichar aChar)
/* static */
void
nsContentUtils::GetOfflineAppManifest(nsIDOMWindow *aWindow, nsIURI **aURI)
nsContentUtils::GetOfflineAppManifest(nsIDocument *aDocument, nsIURI **aURI)
{
nsCOMPtr<nsIDOMWindow> top;
aWindow->GetTop(getter_AddRefs(top));
if (!top) {
return;
}
nsCOMPtr<nsIDOMDocument> topDOMDocument;
top->GetDocument(getter_AddRefs(topDOMDocument));
nsCOMPtr<nsIDocument> topDoc = do_QueryInterface(topDOMDocument);
if (!topDoc) {
return;
}
nsCOMPtr<nsIContent> docElement = topDoc->GetRootContent();
nsCOMPtr<nsIContent> docElement = aDocument->GetRootContent();
if (!docElement) {
return;
}
@ -828,7 +815,7 @@ nsContentUtils::GetOfflineAppManifest(nsIDOMWindow *aWindow, nsIURI **aURI)
}
nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec,
topDoc, topDoc->GetBaseURI());
aDocument, aDocument->GetBaseURI());
}
/* static */

View File

@ -468,17 +468,10 @@ NS_IMETHODIMP nsDocShell::GetInterface(const nsIID & aIID, void **aSink)
else if (aIID.Equals(NS_GET_IID(nsIApplicationCacheContainer))) {
*aSink = nsnull;
// Return the toplevel document as an
// nsIApplicationCacheContainer.
nsCOMPtr<nsIDocShellTreeItem> rootItem;
GetSameTypeRootTreeItem(getter_AddRefs(rootItem));
nsCOMPtr<nsIDocShell> rootDocShell = do_QueryInterface(rootItem);
if (!rootDocShell)
return NS_ERROR_NO_INTERFACE;
// Return application cache associated with this docshell, if any
nsCOMPtr<nsIContentViewer> contentViewer;
rootDocShell->GetContentViewer(getter_AddRefs(contentViewer));
GetContentViewer(getter_AddRefs(contentViewer));
if (!contentViewer)
return NS_ERROR_NO_INTERFACE;
@ -488,6 +481,11 @@ NS_IMETHODIMP nsDocShell::GetInterface(const nsIID & aIID, void **aSink)
if (!domDoc)
return NS_ERROR_NO_INTERFACE;
#if defined(PR_LOGGING) && defined(DEBUG)
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsDocShell[%p]: returning app cache container %p",
this, domDoc.get()));
#endif
return domDoc->QueryInterface(aIID, aSink);
}
else if (aIID.Equals(NS_GET_IID(nsIPrompt)) &&
@ -5115,7 +5113,7 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
if (result == NS_ERROR_NOT_IMPLEMENTED) {
// when there is no GlobalHistory3, or it doesn't implement
// AddToplevelRedirect, we fall back to GlobalHistory2. Just notify
// that the redirecting page was a redirect so it will be link colored
// that the redirecting page was a rePdirect so it will be link colored
// but not visible.
nsCOMPtr<nsIURI> oldURI;
aOldChannel->GetURI(getter_AddRefs(oldURI));
@ -7338,15 +7336,6 @@ nsDocShell::GetInheritedPrincipal(PRBool aConsiderCurrentDocument)
PRBool
nsDocShell::ShouldCheckAppCache(nsIURI *aURI)
{
// Toplevel document loads in domains with the offline-app
// permission should check for an associated application
// cache.
nsCOMPtr<nsIDocShellTreeItem> root;
GetSameTypeRootTreeItem(getter_AddRefs(root));
if (root != this) {
return PR_FALSE;
}
nsCOMPtr<nsIOfflineCacheUpdateService> offlineService =
do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
if (!offlineService) {
@ -7420,16 +7409,12 @@ nsDocShell::DoURILoad(nsIURI * aURI,
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
do_QueryInterface(channel);
if (appCacheChannel) {
// Toplevel document loads should not inherit application
// caches
nsCOMPtr<nsIDocShellTreeItem> root;
GetSameTypeRootTreeItem(getter_AddRefs(root));
if (root == this) {
appCacheChannel->SetInheritApplicationCache(PR_FALSE);
// And loads with the correct permissions should check
// for a matching application cache.
appCacheChannel->SetChooseApplicationCache(ShouldCheckAppCache(aURI));
}
// Any document load should not inherit application cache.
appCacheChannel->SetInheritApplicationCache(PR_FALSE);
// Loads with the correct permissions should check for a matching
// application cache.
appCacheChannel->SetChooseApplicationCache(ShouldCheckAppCache(aURI));
}
// Make sure to give the caller a channel if we managed to create one

View File

@ -2861,19 +2861,14 @@ nsGlobalWindow::GetApplicationCache(nsIDOMOfflineResourceList **aApplicationCach
nsresult rv = webNav->GetCurrentURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
nsCOMPtr<nsIURI> manifestURI;
nsContentUtils::GetOfflineAppManifest(GetOuterWindowInternal(),
getter_AddRefs(manifestURI));
PRBool isToplevel;
nsCOMPtr<nsIDOMWindow> parentWindow;
GetParent(getter_AddRefs(parentWindow));
isToplevel = (parentWindow.get() == static_cast<nsIDOMWindow*>(GetOuterWindowInternal()));
nsContentUtils::GetOfflineAppManifest(doc, getter_AddRefs(manifestURI));
nsDOMOfflineResourceList* applicationCache =
new nsDOMOfflineResourceList(isToplevel, manifestURI, uri, this);
new nsDOMOfflineResourceList(manifestURI, uri, this);
if (!applicationCache)
if (!applicationCache)
return NS_ERROR_OUT_OF_MEMORY;
mApplicationCache = applicationCache;

View File

@ -154,12 +154,10 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMOfflineResourceList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMOfflineResourceList)
nsDOMOfflineResourceList::nsDOMOfflineResourceList(PRBool aToplevel,
nsIURI *aManifestURI,
nsDOMOfflineResourceList::nsDOMOfflineResourceList(nsIURI *aManifestURI,
nsIURI *aDocumentURI,
nsIDOMWindow *aWindow)
: mInitialized(PR_FALSE)
, mToplevel(aToplevel)
, mManifestURI(aManifestURI)
, mDocumentURI(aDocumentURI)
, mCachedKeys(nsnull)
@ -536,10 +534,6 @@ nsDOMOfflineResourceList::SwapCache()
return NS_ERROR_DOM_SECURITY_ERR;
}
if (!mToplevel) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
nsCOMPtr<nsIApplicationCacheService> serv =
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
@ -893,11 +887,6 @@ nsDOMOfflineResourceList::SendEvent(const nsAString &aEventName,
nsIDOMEventListener *aListener,
const nsCOMArray<nsIDOMEventListener> &aListeners)
{
// Only toplevel windows get application cache events.
if (!mToplevel) {
return NS_OK;
}
if (!aListener && aListeners.Count() == 0) {
return NS_OK;
}

View File

@ -76,8 +76,7 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMOfflineResourceList,
nsIDOMOfflineResourceList)
nsDOMOfflineResourceList(PRBool aToplevel,
nsIURI* aManifestURI,
nsDOMOfflineResourceList(nsIURI* aManifestURI,
nsIURI* aDocumentURI,
nsIDOMWindow* aWindow);
virtual ~nsDOMOfflineResourceList();
@ -109,7 +108,6 @@ private:
void ClearCachedKeys();
PRBool mInitialized;
PRBool mToplevel;
nsCOMPtr<nsIURI> mManifestURI;
// AsciiSpec of mManifestURI

View File

@ -0,0 +1,9 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Bug 460353, iframe with no manifest reference</title>
</head>
<body onload="parent.frameOnLoad('noman', applicationCache.status);">
This is an iframe without a manifest reference
</body>
</html>

View File

@ -0,0 +1,37 @@
<html xmlns="http://www.w3.org/1999/xhtml" manifest="updating.cacheManifest">
<head>
<title>Bug 460353, iframe with a different manifest reference</title>
<script type="text/javascript">
applicationCache.onerror = function() {
parent.frameOnUpdate("diff", false);
}
applicationCache.oncached = function() {
parent.frameOnUpdate("diff", true, applicationCache.status);
/* This code tries to figure out what cache is really
associated to this document, but hangs on getter2.getInterface
from for now unknown reasons. Commenting this out.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var Ci = Components.interfaces;
var getter1 = window.QueryInterface(Ci.nsIInterfaceRequestor);
var webnav = getter1.getInterface(Ci.nsIWebNavigation);
var getter2 = webnav.QueryInterface(Ci.nsIInterfaceRequestor);
var cacheCont = getter2.getInterface(Ci.nsIApplicationCacheContainer);
var cache = cacheCont.applicationCache;
dump(cache.groupID);
*/
}
</script>
</head>
<body onload="parent.frameOnLoad('diff', applicationCache.status);">
This is an iframe with a different manifest reference
</body>
</html>

View File

@ -0,0 +1,21 @@
<html xmlns="http://www.w3.org/1999/xhtml" manifest="simpleManifest.cacheManifest">
<head>
<title>Bug 460353, iframe with a different manifest reference</title>
<script type="text/javascript">
applicationCache.onerror = function() {
parent.frameOnUpdate("same", false);
}
applicationCache.oncached = function() {
parent.frameOnUpdate("same", true, applicationCache.status);
}
</script>
</head>
<body onload="parent.frameOnLoad('same', applicationCache.status);">
This is an iframe with the same manifest reference
</body>
</html>

View File

@ -63,6 +63,10 @@ _TEST_FILES = \
445544_part2.html \
445544.cacheManifest \
445544.cacheManifest^headers^ \
test_bug460353.html \
460353_iframe_nomanifest.html \
460353_iframe_ownmanifest.html \
460353_iframe_samemanifest.html \
test_obsolete.html \
obsolete.html \
badManifestMagic.cacheManifest \

View File

@ -17,7 +17,7 @@ function manifestUpdated()
var foreign2cache = appCacheService.chooseApplicationCache(
"http://localhost:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html");
OfflineTest.ok(foreign2cache, "Foreign 2 cache present, choosed for foreign2.html");
OfflineTest.ok(foreign2cache, "Foreign 2 cache present, chosen for foreign2.html");
OfflineTest.is(foreign2cache.groupID, "http://localhost:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest")
var foreign1cache = appCacheService.getActiveCache(
@ -44,7 +44,7 @@ function onLoaded()
foreign1cache = appCacheService.chooseApplicationCache(
"http://localhost:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html");
OfflineTest.ok(!foreign1cache, "foreign2.html not choosed from foreign1 cache");
OfflineTest.ok(!foreign1cache, "foreign2.html not chosen from foreign1 cache");
try
{

View File

@ -0,0 +1,113 @@
<html xmlns="http://www.w3.org/1999/xhtml" manifest="http://localhost:8888/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest">
<head>
<title>Bug 460353</title>
<!--
This test checks that each iframe creates its own
scope. Actually, we just check that it loads and updates
its associated cache. There is no check that the cache is the
expected one, there is no API to gain that information.
-->
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="text/javascript">
var result = new Array();
var expectedUpdates = 2;
init();
function init()
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var Cc = Components.classes;
var Ci = Components.interfaces;
var pm = Cc["@mozilla.org/permissionmanager;1"]
.getService(Ci.nsIPermissionManager);
var uri = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI(window.location.href, null, null);
pm.add(uri, "offline-app", Ci.nsIPermissionManager.ALLOW_ACTION);
}
function frameOnLoad(frameid, status)
{
var obj = new Object();
result[frameid] = obj;
result[frameid].load = true;
result[frameid].cacheStatus = status;
}
function frameOnUpdate(frameid, ok, status)
{
result[frameid].update = true;
result[frameid].updateOK = ok;
result[frameid].cacheStatus = status;
if (!(--expectedUpdates))
finish();
}
function finish()
{
SimpleTest.ok(result["same"].load || false, "Frame with the same manifest loads");
SimpleTest.ok(result["same"].update || false, "Frame with the same manifest cache update notification");
SimpleTest.ok(result["same"].updateOK || false, "Frame with the same manifest cache update passed OK");
SimpleTest.is(result["same"].cacheStatus || -1, 1, "Frame with the same manifest cache status was IDLE");
SimpleTest.ok(result["diff"].load || false, "Frame with different manifest loads");
SimpleTest.ok(result["diff"].update || false, "Frame with different manifest cache update notification");
SimpleTest.ok(result["diff"].updateOK || false, "Frame with different manifest cache update passed OK");
SimpleTest.is(result["diff"].cacheStatus || -1, 1, "Frame with different manifest cache status was IDLE");
SimpleTest.ok(result["noman"].load || false, "Frame with no manifest loads");
SimpleTest.ok(result["noman"].update == undefined, "Frame with no manifest cache update didn't notify");
SimpleTest.ok(result["noman"].updateOK == undefined, "Frame with no manifest cache update didn't pass");
SimpleTest.is(result["noman"].cacheStatus || -1, -1, "Frame with no manifest cache status was undefined");
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var Cc = Components.classes;
var Ci = Components.interfaces;
var pm = Cc["@mozilla.org/permissionmanager;1"]
.getService(Ci.nsIPermissionManager);
var uri = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI(window.location.href, null, null);
pm.remove(uri.host, "offline-app");
cleanCache("http://localhost:8888/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest");
cleanCache("http://localhost:8888/tests/dom/tests/mochitest/ajax/offline/updating.cacheManifest");
SimpleTest.finish();
}
function cleanCache(manifestURL)
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var Cc = Components.classes;
var Ci = Components.interfaces;
var serv = Cc["@mozilla.org/network/application-cache-service;1"]
.getService(Ci.nsIApplicationCacheService);
var cache = serv.getActiveCache(manifestURL);
if (cache)
cache.discard();
}
SimpleTest.waitForExplicitFinish();
</script>
<body>
<iframe src="460353_iframe_nomanifest.html"></iframe>
<iframe src="460353_iframe_ownmanifest.html"></iframe>
<iframe src="460353_iframe_samemanifest.html"></iframe>
</body>
</html>

View File

@ -121,7 +121,7 @@ function finalize()
OfflineTest.is(gGotExplicitVersion, 1, "Explicit entry loaded");
OfflineTest.todo(gGotImplicitVersion == 1, "Bug 461325 - Implicit entry loaded");
OfflineTest.is(gGotDynamicVersion, 1, "Dynamic entry loaded");
OfflineTest.todo(gGotOnError, "Got onerror event invoked by implicit page load in offline mode");
OfflineTest.ok(gGotOnError, "Got onerror event invoked by implicit page load in offline mode");
OfflineTest.teardown();
OfflineTest.finish();

View File

@ -1881,7 +1881,7 @@ nsOfflineCacheDevice::AddNamespace(const nsCString &clientID,
rv = ns->GetItemType(&itemType);
NS_ENSURE_SUCCESS(rv, rv);
LOG(("nsOfflineCacheDevice::AddNamespace [cid=%s, ns=%s, type=%d]",
LOG(("nsOfflineCacheDevice::AddNamespace [cid=%s, ns=%s, data=%s, type=%d]",
PromiseFlatCString(clientID).get(),
namespaceSpec.get(), data.get(), itemType));

View File

@ -1720,6 +1720,8 @@ nsOfflineCacheUpdate::AssociateDocument(nsIDOMDocument *aDocument)
NS_ENSURE_SUCCESS(rv, rv);
if (!existingCache) {
LOG(("Update %p: associating app cache %s to document %p", this, mClientID.get(), aDocument));
rv = container->SetApplicationCache(mApplicationCache);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -2241,8 +2243,10 @@ nsOfflineCacheUpdateService::Schedule(nsIURI *aManifestURI,
PRBool equals;
rv = manifestURI->Equals(aManifestURI, &equals);
if (equals) {
if (aDocument)
if (aDocument) {
LOG(("Document %p added to update %p", aDocument, update.get()));
update->AddDocument(aDocument);
}
NS_ADDREF(*aUpdate = update);
return NS_OK;
}
@ -2258,8 +2262,10 @@ nsOfflineCacheUpdateService::Schedule(nsIURI *aManifestURI,
rv = update->Init(aManifestURI, aDocumentURI);
NS_ENSURE_SUCCESS(rv, rv);
if (aDocument)
if (aDocument) {
LOG(("First document %p added to update %p", aDocument, update.get()));
update->AddDocument(aDocument);
}
rv = update->Schedule();
NS_ENSURE_SUCCESS(rv, rv);