mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 460353: app caches should be per iframe, not per toplevel browsing context. r=dcamp, r+sr=jst
This commit is contained in:
parent
19d2223559
commit
c16599cc1d
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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 \
|
||||
|
@ -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
|
||||
{
|
||||
|
113
dom/tests/mochitest/ajax/offline/test_bug460353.html
Normal file
113
dom/tests/mochitest/ajax/offline/test_bug460353.html
Normal 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>
|
@ -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();
|
||||
|
2
netwerk/cache/src/nsDiskCacheDeviceSQL.cpp
vendored
2
netwerk/cache/src/nsDiskCacheDeviceSQL.cpp
vendored
@ -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));
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user