diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index 02879a4e470..b16afdc9e64 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -316,7 +316,118 @@ PRBool nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI, nsIURI* aTargetURI) { - return NS_SecurityCompareURIs(aSourceURI, aTargetURI, sStrictFileOriginPolicy); + // Note that this is not an Equals() test on purpose -- for URIs that don't + // support host/port, we want equality to basically be object identity, for + // security purposes. Otherwise, for example, two javascript: URIs that + // are otherwise unrelated could end up "same origin", which would be + // unfortunate. + if (aSourceURI && aSourceURI == aTargetURI) + { + return PR_TRUE; + } + + if (!aTargetURI || !aSourceURI) + { + return PR_FALSE; + } + + // If either URI is a nested URI, get the base URI + nsCOMPtr sourceBaseURI = NS_GetInnermostURI(aSourceURI); + nsCOMPtr targetBaseURI = NS_GetInnermostURI(aTargetURI); + + if (!sourceBaseURI || !targetBaseURI) + return PR_FALSE; + + // Compare schemes + nsCAutoString targetScheme; + PRBool sameScheme = PR_FALSE; + if (NS_FAILED( targetBaseURI->GetScheme(targetScheme) ) || + NS_FAILED( sourceBaseURI->SchemeIs(targetScheme.get(), &sameScheme) ) || + !sameScheme) + { + // Not same-origin if schemes differ + return PR_FALSE; + } + + // special handling for file: URIs + if (targetScheme.EqualsLiteral("file")) + { + // in traditional unsafe behavior all files are the same origin + if (!sStrictFileOriginPolicy) + return PR_TRUE; + + nsCOMPtr sourceFileURL(do_QueryInterface(sourceBaseURI)); + nsCOMPtr targetFileURL(do_QueryInterface(targetBaseURI)); + + if (!sourceFileURL || !targetFileURL) + return PR_FALSE; + + nsCOMPtr sourceFile, targetFile; + + sourceFileURL->GetFile(getter_AddRefs(sourceFile)); + targetFileURL->GetFile(getter_AddRefs(targetFile)); + + if (!sourceFile || !targetFile) + return PR_FALSE; + + // Otherwise they had better match + PRBool filesAreEqual = PR_FALSE; + nsresult rv = sourceFile->Equals(targetFile, &filesAreEqual); + return NS_SUCCEEDED(rv) && filesAreEqual; + } + + // Special handling for mailnews schemes + if (targetScheme.EqualsLiteral("imap") || + targetScheme.EqualsLiteral("mailbox") || + targetScheme.EqualsLiteral("news")) + { + // Each message is a distinct trust domain; use the + // whole spec for comparison + nsCAutoString targetSpec; + nsCAutoString sourceSpec; + return ( NS_SUCCEEDED( targetBaseURI->GetSpec(targetSpec) ) && + NS_SUCCEEDED( sourceBaseURI->GetSpec(sourceSpec) ) && + targetSpec.Equals(sourceSpec) ); + } + + // Compare hosts + nsCAutoString targetHost; + nsCAutoString sourceHost; + if (NS_FAILED( targetBaseURI->GetHost(targetHost) ) || + NS_FAILED( sourceBaseURI->GetHost(sourceHost) ) || + !targetHost.Equals(sourceHost, nsCaseInsensitiveCStringComparator())) + { + // Not same-origin if hosts differ + return PR_FALSE; + } + + // Compare ports + PRInt32 targetPort; + nsresult rv = targetBaseURI->GetPort(&targetPort); + PRInt32 sourcePort; + if (NS_SUCCEEDED(rv)) + rv = sourceBaseURI->GetPort(&sourcePort); + PRBool result = NS_SUCCEEDED(rv) && targetPort == sourcePort; + // If the port comparison failed, see if either URL has a + // port of -1. If so, replace -1 with the default port + // for that scheme. + if (NS_SUCCEEDED(rv) && !result && + (sourcePort == -1 || targetPort == -1)) + { + NS_ENSURE_TRUE(sIOService, PR_FALSE); + + PRInt32 defaultPort = NS_GetDefaultPort(targetScheme.get()); + if (defaultPort == -1) + return PR_FALSE; // No default port for this scheme + + if (sourcePort == -1) + sourcePort = defaultPort; + else if (targetPort == -1) + targetPort = defaultPort; + result = targetPort == sourcePort; + } + + return result; } NS_IMETHODIMP diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 6abb6d26510..9438c691090 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1244,11 +1244,6 @@ public: */ static PRBool OfflineAppAllowed(nsIURI *aURI); - /** - * Check whether an application should be allowed to use offline APIs. - */ - static PRBool OfflineAppAllowed(nsIPrincipal *aPrincipal); - /** * Increases the count of blockers preventing scripts from running. * NOTE: You might want to use nsAutoScriptBlocker rather than calling diff --git a/content/base/src/Makefile.in b/content/base/src/Makefile.in index 907b53cded3..68f24a71a6d 100644 --- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -59,7 +59,6 @@ REQUIRES = xpcom \ js \ webshell \ necko \ - nkcache \ mimetype \ exthandler \ chardet \ diff --git a/content/base/src/nsContentSink.cpp b/content/base/src/nsContentSink.cpp index 15b315b8af6..d19006ed338 100644 --- a/content/base/src/nsContentSink.cpp +++ b/content/base/src/nsContentSink.cpp @@ -73,7 +73,6 @@ #include "nsIOfflineCacheUpdate.h" #include "nsIApplicationCache.h" #include "nsIApplicationCacheContainer.h" -#include "nsIApplicationCacheService.h" #include "nsIScriptSecurityManager.h" #include "nsIDOMLoadStatus.h" #include "nsICookieService.h" @@ -97,10 +96,6 @@ #include "nsPresShellIterator.h" #include "nsPIDOMWindow.h" #include "mozAutoDocUpdate.h" -#include "nsIWebNavigation.h" -#include "nsIDocumentLoader.h" -#include "nsICachingChannel.h" -#include "nsICacheEntryDescriptor.h" PRLogModuleInfo* gContentSinkLogModuleInfo; @@ -852,304 +847,79 @@ nsContentSink::PrefetchHref(const nsAString &aHref, } } -nsresult -nsContentSink::GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey) -{ - aCacheKey.Truncate(); - - nsresult rv; - nsCOMPtr cachingChannel = do_QueryInterface(aChannel, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr token; - rv = cachingChannel->GetCacheToken(getter_AddRefs(token)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr descriptor = do_QueryInterface(token, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - rv = descriptor->GetKey(aCacheKey); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -nsresult -nsContentSink::SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache, - nsIURI *aManifestURI, - PRBool aIsTopDocument, - PRBool aFetchedWithHTTPGetOrEquiv, - CacheSelectionAction *aAction) -{ - *aAction = CACHE_SELECTION_NONE; - - nsCOMPtr applicationCacheDocument = - do_QueryInterface(mDocument); - NS_ASSERTION(applicationCacheDocument, - "mDocument must implement nsIApplicationCacheContainer."); - - nsresult rv; - - // We might decide on a new application cache... - nsCOMPtr applicationCache = aLoadApplicationCache; - - if (applicationCache) { - nsCAutoString groupID; - rv = applicationCache->GetGroupID(groupID); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr groupURI; - rv = NS_NewURI(getter_AddRefs(groupURI), groupID); - NS_ENSURE_SUCCESS(rv, rv); - - PRBool equal = PR_FALSE; - rv = groupURI->Equals(aManifestURI, &equal); - 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). - - nsCAutoString cachekey; - rv = GetChannelCacheKey(mDocument->GetChannel(), cachekey); - NS_ENSURE_SUCCESS(rv, rv); - - rv = applicationCache->MarkEntry(cachekey, - nsIApplicationCache::ITEM_FOREIGN); - NS_ENSURE_SUCCESS(rv, rv); - - if (aIsTopDocument) { - *aAction = CACHE_SELECTION_RELOAD; - } - - return NS_OK; - } - - 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); - NS_ENSURE_SUCCESS(rv, rv); - - *aAction = CACHE_SELECTION_UPDATE; - } - } - else { - // The document was not loaded from an application cache - // Here we know the manifest has the same origin as the - // document. There is call to CheckMayLoad() on it above. - - 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 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); - } - 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); - } - } - - return NS_OK; -} - -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 applicationCacheDocument = - do_QueryInterface(mDocument); - NS_ASSERTION(applicationCacheDocument, - "mDocument must implement nsIApplicationCacheContainer."); - - rv = applicationCacheDocument->SetApplicationCache(aLoadApplicationCache); - 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); - - rv = NS_NewURI(aManifestURI, groupID); - NS_ENSURE_SUCCESS(rv, rv); - - *aAction = CACHE_SELECTION_UPDATE; - - return NS_OK; -} - void nsContentSink::ProcessOfflineManifest(nsIContent *aElement) { - // Only check the manifest for root document nodes. - if (aElement != mDocument->GetRootContent()) { - return; - } - - nsresult rv; - // Check for a manifest= attribute. nsAutoString manifestSpec; aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::manifest, manifestSpec); - // Grab the application cache the document was loaded from, if any. - nsCOMPtr applicationCache; - - nsCOMPtr applicationCacheChannel = - do_QueryInterface(mDocument->GetChannel()); - if (applicationCacheChannel) { - rv = applicationCacheChannel->GetApplicationCache( - getter_AddRefs(applicationCache)); - if (NS_FAILED(rv)) { - return; - } - } - - if (manifestSpec.IsEmpty() && !applicationCache) { - // Not loaded from an application cache, and no manifest - // attribute. Nothing to do here. + if (manifestSpec.IsEmpty() || + manifestSpec.FindChar('#') != kNotFound) { return; } - // The manifest attribute is handled differently if the document is - // not toplevel. - nsCOMPtr window = mDocument->GetWindow(); - if (!window) + // We only care about manifests in toplevel windows. + nsCOMPtr pwindow = + do_QueryInterface(mDocument->GetScriptGlobalObject()); + if (!pwindow) { return; + } + + nsCOMPtr window = + do_QueryInterface(pwindow->GetOuterWindow()); + if (!window) { + return; + } + nsCOMPtr parent; window->GetParent(getter_AddRefs(parent)); - PRBool isTop = (parent == window); - - CacheSelectionAction action = CACHE_SELECTION_NONE; - nsCOMPtr manifestURI; - - if (manifestSpec.IsEmpty()) { - rv = SelectDocAppCacheNoManifest(applicationCache, - isTop, - getter_AddRefs(manifestURI), - &action); - if (NS_FAILED(rv)) { - return; - } - } - else { - nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI), - manifestSpec, mDocument, - mDocumentURI); - if (!manifestURI) { - return; - } - - // Documents must list a manifest from the same origin - rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, PR_TRUE); - if (NS_FAILED(rv)) { - return; - } - - // Only continue if the document has permission to use offline APIs. - if (!nsContentUtils::OfflineAppAllowed(mDocument->NodePrincipal())) { - return; - } - - PRBool fetchedWithHTTPGetOrEquiv = PR_FALSE; - nsCOMPtr 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 (NS_FAILED(rv)) { - return; - } - } - - switch (action) - { - case CACHE_SELECTION_NONE: + if (parent.get() != window.get()) { return; - case CACHE_SELECTION_UPDATE: { - nsCOMPtr updateService = - do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID); + } - if (updateService) { - nsCOMPtr domdoc = do_QueryInterface(mDocument); - updateService->ScheduleOnDocumentStop(manifestURI, mDocumentURI, domdoc); - } - break; + // Only update if the document has permission to use offline APIs. + if (!nsContentUtils::OfflineAppAllowed(mDocumentURI)) { + return; } - 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 webNav = do_QueryInterface(mDocShell); - webNav->Stop(nsIWebNavigation::STOP_ALL); - webNav->Reload(nsIWebNavigation::LOAD_FLAGS_NONE); - break; + // XXX: at this point in the spec there is an algorithm for + // confirming whether the cache that was selected at load time was + // the proper application cache for this document. This will + // be implemented in a separate patch; For now just assume that we + // chose an acceptable application cache. + + nsCOMPtr channelContainer = + do_QueryInterface(mDocument->GetChannel()); + + nsCOMPtr docContainer = + do_QueryInterface(mDocument); + + if (channelContainer && docContainer) { + nsCOMPtr appCache; + channelContainer->GetApplicationCache(getter_AddRefs(appCache)); + docContainer->SetApplicationCache(appCache); } + + nsCOMPtr manifestURI; + nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI), + manifestSpec, mDocument, + mDocumentURI); + if (!manifestURI) { + return; } + + // Documents must list a manifest from the same origin + nsresult rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, PR_TRUE); + if (NS_FAILED(rv)) { + return; + } + + // Start the update + nsCOMPtr domdoc = do_QueryInterface(mDocument); + nsCOMPtr updateService = + do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID); + updateService->ScheduleOnDocumentStop(manifestURI, mDocumentURI, domdoc); } void diff --git a/content/base/src/nsContentSink.h b/content/base/src/nsContentSink.h index 3a61d3236ea..a7e29c08556 100644 --- a/content/base/src/nsContentSink.h +++ b/content/base/src/nsContentSink.h @@ -76,7 +76,6 @@ class nsIContent; class nsIViewManager; class nsNodeInfoManager; class nsScriptLoader; -class nsIApplicationCache; #ifdef NS_DEBUG @@ -151,25 +150,6 @@ protected: nsContentSink(); virtual ~nsContentSink(); - enum CacheSelectionAction { - // There is no offline cache manifest specified by the document, - // or the document was loaded from a cache other than the one it - // specifies via its manifest attribute and IS NOT a top-level - // document, or an error occurred during the cache selection - // algorithm. - CACHE_SELECTION_NONE = 0, - - // The offline cache manifest must be updated. - CACHE_SELECTION_UPDATE = 1, - - // The document was loaded from a cache other than the one it - // specifies via its manifest attribute and IS a top-level - // 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 - }; - nsresult Init(nsIDocument* aDoc, nsIURI* aURI, nsISupports* aContainer, nsIChannel* aChannel); @@ -191,60 +171,6 @@ protected: void PrefetchHref(const nsAString &aHref, nsIContent *aSource, PRBool aExplicit); - - // Gets the cache key (used to identify items in a cache) of the channel. - nsresult GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey); - - // There is an offline cache manifest attribute specified and the - // document is allowed to use the offline cache. Process the cache - // selection algorithm for this document and the manifest. Result is - // an action that must be taken on the manifest, see - // CacheSelectionAction enum above. - // - // @param aLoadApplicationCache - // The application cache from which the load originated, if - // 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 - // Out parameter, returns the action that should be performed - // by the calling function. - nsresult SelectDocAppCache(nsIApplicationCache *aLoadApplicationCache, - nsIURI *aManifestURI, - PRBool aIsTopDocument, - PRBool aFetchedWithHTTPGetOrEquiv, - CacheSelectionAction *aAction); - - // There is no offline cache manifest attribute specified. Process - // the cache selection algorithm w/o the manifest. Result is an - // action that must be taken, see CacheSelectionAction enum - // above. In case the offline cache manifest has to be updated the - // manifest URI is returned in aManifestURI. - // - // @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. - // @param aAction - // Out parameter, returns the action that should be performed - // by the calling function. - nsresult SelectDocAppCacheNoManifest(nsIApplicationCache *aLoadApplicationCache, - PRBool aIsTopDocument, - nsIURI **aManifestURI, - CacheSelectionAction *aAction); - - // Searches for the offline cache manifest attribute and calls one - // of the above defined methods to select the document's application - // cache, let it be associated with the document and eventually - // schedule the cache update process. void ProcessOfflineManifest(nsIContent *aElement); // Tries to scroll to the URI's named anchor. Once we've successfully diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 6b777b4ffff..e9deebec33c 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -807,16 +807,6 @@ nsContentUtils::OfflineAppAllowed(nsIURI *aURI) return NS_OfflineAppAllowed(aURI, sPrefBranch); } -/* static */ -PRBool -nsContentUtils::OfflineAppAllowed(nsIPrincipal *aPrincipal) -{ - nsCOMPtr codebaseURI; - aPrincipal->GetURI(getter_AddRefs(codebaseURI)); - - return OfflineAppAllowed(codebaseURI); -} - // static void nsContentUtils::Shutdown() diff --git a/dom/src/offline/nsDOMOfflineResourceList.cpp b/dom/src/offline/nsDOMOfflineResourceList.cpp index 291ec716cc4..b431eeba73a 100644 --- a/dom/src/offline/nsDOMOfflineResourceList.cpp +++ b/dom/src/offline/nsDOMOfflineResourceList.cpp @@ -339,11 +339,7 @@ nsDOMOfflineResourceList::Add(const nsAString& aURI) do_CreateInstance(NS_OFFLINECACHEUPDATE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); - nsCAutoString clientID; - rv = appCache->GetClientID(clientID); - NS_ENSURE_SUCCESS(rv, rv); - - rv = update->InitPartial(mManifestURI, clientID, mDocumentURI); + rv = update->Init(PR_TRUE, mManifestURI, mDocumentURI); NS_ENSURE_SUCCESS(rv, rv); rv = update->AddDynamicURI(requestedURI); diff --git a/netwerk/base/public/nsNetUtil.h b/netwerk/base/public/nsNetUtil.h index ad69da89d6d..e3d75404fd9 100644 --- a/netwerk/base/public/nsNetUtil.h +++ b/netwerk/base/public/nsNetUtil.h @@ -74,7 +74,6 @@ #include "nsIStringStream.h" #include "nsILocalFile.h" #include "nsIFileStreams.h" -#include "nsIFileURL.h" #include "nsIProtocolProxyService.h" #include "nsIProxyInfo.h" #include "nsIFileStreams.h" @@ -1466,128 +1465,4 @@ NS_OfflineAppAllowed(nsIURI *aURI, nsIPrefBranch *aPrefBranch = nsnull) return allowed; } -inline PRBool -NS_SecurityCompareURIs(nsIURI* aSourceURI, - nsIURI* aTargetURI, - PRBool aStrictFileOriginPolicy) -{ - // Note that this is not an Equals() test on purpose -- for URIs that don't - // support host/port, we want equality to basically be object identity, for - // security purposes. Otherwise, for example, two javascript: URIs that - // are otherwise unrelated could end up "same origin", which would be - // unfortunate. - if (aSourceURI && aSourceURI == aTargetURI) - { - return PR_TRUE; - } - - if (!aTargetURI || !aSourceURI) - { - return PR_FALSE; - } - - // If either URI is a nested URI, get the base URI - nsCOMPtr sourceBaseURI = NS_GetInnermostURI(aSourceURI); - nsCOMPtr targetBaseURI = NS_GetInnermostURI(aTargetURI); - - if (!sourceBaseURI || !targetBaseURI) - return PR_FALSE; - - // Compare schemes - nsCAutoString targetScheme; - PRBool sameScheme = PR_FALSE; - if (NS_FAILED( targetBaseURI->GetScheme(targetScheme) ) || - NS_FAILED( sourceBaseURI->SchemeIs(targetScheme.get(), &sameScheme) ) || - !sameScheme) - { - // Not same-origin if schemes differ - return PR_FALSE; - } - - // special handling for file: URIs - if (targetScheme.EqualsLiteral("file")) - { - // in traditional unsafe behavior all files are the same origin - if (!aStrictFileOriginPolicy) - return PR_TRUE; - - nsCOMPtr sourceFileURL(do_QueryInterface(sourceBaseURI)); - nsCOMPtr targetFileURL(do_QueryInterface(targetBaseURI)); - - if (!sourceFileURL || !targetFileURL) - return PR_FALSE; - - nsCOMPtr sourceFile, targetFile; - - sourceFileURL->GetFile(getter_AddRefs(sourceFile)); - targetFileURL->GetFile(getter_AddRefs(targetFile)); - - if (!sourceFile || !targetFile) - return PR_FALSE; - - // Otherwise they had better match - PRBool filesAreEqual = PR_FALSE; - nsresult rv = sourceFile->Equals(targetFile, &filesAreEqual); - return NS_SUCCEEDED(rv) && filesAreEqual; - } - - // Special handling for mailnews schemes - if (targetScheme.EqualsLiteral("imap") || - targetScheme.EqualsLiteral("mailbox") || - targetScheme.EqualsLiteral("news")) - { - // Each message is a distinct trust domain; use the - // whole spec for comparison - nsCAutoString targetSpec; - nsCAutoString sourceSpec; - return ( NS_SUCCEEDED( targetBaseURI->GetSpec(targetSpec) ) && - NS_SUCCEEDED( sourceBaseURI->GetSpec(sourceSpec) ) && - targetSpec.Equals(sourceSpec) ); - } - - // Compare hosts - nsCAutoString targetHost; - nsCAutoString sourceHost; - if (NS_FAILED( targetBaseURI->GetAsciiHost(targetHost) ) || - NS_FAILED( sourceBaseURI->GetAsciiHost(sourceHost) )) - { - return PR_FALSE; - } - -#ifdef MOZILLA_INTERNAL_API - if (!targetHost.Equals(sourceHost, nsCaseInsensitiveCStringComparator() )) -#else - if (!targetHost.Equals(sourceHost, CaseInsensitiveCompare)) -#endif - { - return PR_FALSE; - } - - // Compare ports - PRInt32 targetPort; - nsresult rv = targetBaseURI->GetPort(&targetPort); - PRInt32 sourcePort; - if (NS_SUCCEEDED(rv)) - rv = sourceBaseURI->GetPort(&sourcePort); - PRBool result = NS_SUCCEEDED(rv) && targetPort == sourcePort; - // If the port comparison failed, see if either URL has a - // port of -1. If so, replace -1 with the default port - // for that scheme. - if (NS_SUCCEEDED(rv) && !result && - (sourcePort == -1 || targetPort == -1)) - { - PRInt32 defaultPort = NS_GetDefaultPort(targetScheme.get()); - if (defaultPort == -1) - return PR_FALSE; // No default port for this scheme - - if (sourcePort == -1) - sourcePort = defaultPort; - else if (targetPort == -1) - targetPort = defaultPort; - result = targetPort == sourcePort; - } - - return result; -} - #endif // !nsNetUtil_h__ diff --git a/netwerk/cache/src/nsDiskCacheDeviceSQL.cpp b/netwerk/cache/src/nsDiskCacheDeviceSQL.cpp index d53bed6a28f..beb1c716ea2 100644 --- a/netwerk/cache/src/nsDiskCacheDeviceSQL.cpp +++ b/netwerk/cache/src/nsDiskCacheDeviceSQL.cpp @@ -44,8 +44,6 @@ #include "nsNetUtil.h" #include "nsAutoPtr.h" #include "nsEscape.h" -#include "nsIPrefBranch.h" -#include "nsIPrefService.h" #include "nsString.h" #include "nsPrintfCString.h" #include "nsCRT.h" @@ -694,20 +692,6 @@ nsOfflineCacheDevice::~nsOfflineCacheDevice() Shutdown(); } -/* static */ -PRBool -nsOfflineCacheDevice::GetStrictFileOriginPolicy() -{ - nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); - - PRBool retval; - if (prefs && NS_SUCCEEDED(prefs->GetBoolPref("security.fileuri.strict_origin_policy", &retval))) - return retval; - - // As default value use true (be more strict) - return PR_TRUE; -} - PRUint32 nsOfflineCacheDevice::CacheSize() { @@ -1761,40 +1745,13 @@ nsOfflineCacheDevice::ChooseApplicationCache(const nsACString &key, rv = statement->ExecuteStep(&hasRows); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr keyURI; - rv = NS_NewURI(getter_AddRefs(keyURI), key); - NS_ENSURE_SUCCESS(rv, rv); - while (hasRows) { - PRInt32 itemType; - rv = statement->GetInt32(1, &itemType); + nsCString clientID; + rv = statement->GetUTF8String(0, clientID); NS_ENSURE_SUCCESS(rv, rv); - if (!(itemType & nsIApplicationCache::ITEM_FOREIGN)) { - nsCAutoString clientID; - rv = statement->GetUTF8String(0, clientID); - NS_ENSURE_SUCCESS(rv, rv); - - if (mActiveCaches.Contains(clientID)) { - nsCAutoString groupID; - rv = GetGroupForCache(clientID, groupID); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr groupURI; - rv = NS_NewURI(getter_AddRefs(groupURI), groupID); - if (NS_SUCCEEDED(rv)) { - // When we are choosing an initial cache to load the top - // level document from, the URL of that document must have - // the same origin as the manifest, according to the spec. - // The following check is here because explicit, fallback - // and dynamic entries might have origin different from the - // manifest origin. XXX: dynamic shouldn't? - if (NS_SecurityCompareURIs(keyURI, groupURI, - GetStrictFileOriginPolicy())) - return GetApplicationCache(clientID, out); - } - } - } + if (mActiveCaches.Contains(clientID)) + return GetApplicationCache(clientID, out); rv = statement->ExecuteStep(&hasRows); NS_ENSURE_SUCCESS(rv, rv); diff --git a/netwerk/cache/src/nsDiskCacheDeviceSQL.h b/netwerk/cache/src/nsDiskCacheDeviceSQL.h index ffd569976fe..af10e516e87 100644 --- a/netwerk/cache/src/nsDiskCacheDeviceSQL.h +++ b/netwerk/cache/src/nsDiskCacheDeviceSQL.h @@ -184,8 +184,6 @@ private: nsIWeakReference *weakRef, void *ctx); - static PRBool GetStrictFileOriginPolicy(); - PRBool Initialized() { return mDB != nsnull; } nsresult InitActiveCaches(); diff --git a/uriloader/prefetch/nsIOfflineCacheUpdate.idl b/uriloader/prefetch/nsIOfflineCacheUpdate.idl index a32dd54fb93..ba1797b99a6 100644 --- a/uriloader/prefetch/nsIOfflineCacheUpdate.idl +++ b/uriloader/prefetch/nsIOfflineCacheUpdate.idl @@ -115,7 +115,7 @@ interface nsIOfflineCacheUpdateObserver : nsISupports { * load its items one by one, sending itemCompleted() to any registered * observers. */ -[scriptable, uuid(877261bb-b952-4d27-847e-859bdd47c0ec)] +[scriptable, uuid(4b206247-82ee-46cf-a8b7-f7284e753bc2)] interface nsIOfflineCacheUpdate : nsISupports { /** * Fetch the status of the running update. This will return a value @@ -154,30 +154,21 @@ interface nsIOfflineCacheUpdate : nsISupports { /** * Initialize the update. * + * @param aPartialUpdate + * TRUE if the update should just update the URIs given to it, + * FALSE if all URLs for the owner domain should be added. * @param aManifestURI - * The manifest URI to be checked. + * The manifest URI to be checked, or for partial updates the + * manifest that should own resources that are added. * @param aDocumentURI * The page that is requesting the update. */ - void init(in nsIURI aManifestURI, in nsIURI aDocumentURI); + void init(in boolean aPartialUpdate, + in nsIURI aManifestURI, + in nsIURI aDocumentURI); /** - * Initialize the update for partial processing. - * - * @param aManifestURI - * The manifest URI of the related cache. - * @param aClientID - * Client ID of the cache to store resource to. This ClientID - * must be ID of cache in the cache group identified by - * the manifest URI passed in the first parameter. - * @param aDocumentURI - * The page that is requesting the update. May be null - * when this information is unknown. - */ - void initPartial(in nsIURI aManifestURI, in ACString aClientID, in nsIURI aDocumentURI); - - /** - * Add a dynamic URI to the offline cache as part of the update. + * Add a URI to the offline cache as part of the update. * * @param aURI * The URI to add. diff --git a/uriloader/prefetch/nsOfflineCacheUpdate.cpp b/uriloader/prefetch/nsOfflineCacheUpdate.cpp index 0e79c9ea64d..ae81301325b 100644 --- a/uriloader/prefetch/nsOfflineCacheUpdate.cpp +++ b/uriloader/prefetch/nsOfflineCacheUpdate.cpp @@ -46,7 +46,6 @@ #include "nsICacheService.h" #include "nsICacheSession.h" #include "nsICachingChannel.h" -#include "nsIDocumentLoader.h" #include "nsIDOMWindow.h" #include "nsIDOMOfflineResourceList.h" #include "nsIObserverService.h" @@ -58,7 +57,6 @@ #include "nsNetUtil.h" #include "nsServiceManagerUtils.h" #include "nsStreamUtils.h" -#include "nsStringEnumerator.h" #include "nsThreadUtils.h" #include "prlog.h" @@ -579,7 +577,6 @@ nsOfflineManifestItem::HandleManifestLine(const nsCString::const_iterator &aBegi // this should have been dealt with earlier return NS_ERROR_FAILURE; } - case PARSE_CACHE_ENTRIES: { nsCOMPtr uri; rv = NS_NewURI(getter_AddRefs(uri), line, nsnull, mURI); @@ -813,7 +810,8 @@ nsOfflineCacheUpdate::GetCacheKey(nsIURI *aURI, nsACString &aKey) } nsresult -nsOfflineCacheUpdate::Init(nsIURI *aManifestURI, +nsOfflineCacheUpdate::Init(PRBool aPartialUpdate, + nsIURI *aManifestURI, nsIURI *aDocumentURI) { nsresult rv; @@ -824,9 +822,9 @@ nsOfflineCacheUpdate::Init(nsIURI *aManifestURI, if (!service) return NS_ERROR_FAILURE; - LOG(("nsOfflineCacheUpdate::Init [%p]", this)); + LOG(("nsOfflineCacheUpdate::Init [%p, %d]", this, aPartialUpdate)); - mPartialUpdate = PR_FALSE; + mPartialUpdate = aPartialUpdate; // Only http and https applications are supported. PRBool match; @@ -860,66 +858,20 @@ nsOfflineCacheUpdate::Init(nsIURI *aManifestURI, getter_AddRefs(mPreviousApplicationCache)); NS_ENSURE_SUCCESS(rv, rv); - rv = cacheService->CreateApplicationCache(manifestSpec, - getter_AddRefs(mApplicationCache)); - NS_ENSURE_SUCCESS(rv, rv); + // Partial updates to existing application caches don't need a new cache. + if (aPartialUpdate && mPreviousApplicationCache) { + mApplicationCache = mPreviousApplicationCache; + } else { + rv = cacheService->CreateApplicationCache(manifestSpec, + getter_AddRefs(mApplicationCache)); + NS_ENSURE_SUCCESS(rv, rv); + } rv = mApplicationCache->GetClientID(mClientID); NS_ENSURE_SUCCESS(rv, rv); mState = STATE_INITIALIZED; - return NS_OK; -} -nsresult -nsOfflineCacheUpdate::InitPartial(nsIURI *aManifestURI, - const nsACString& clientID, - nsIURI *aDocumentURI) -{ - nsresult rv; - - // Make sure the service has been initialized - nsOfflineCacheUpdateService* service = - nsOfflineCacheUpdateService::EnsureService(); - if (!service) - return NS_ERROR_FAILURE; - - LOG(("nsOfflineCacheUpdate::InitPartial [%p]", this)); - - mPartialUpdate = PR_TRUE; - mClientID = clientID; - mDocumentURI = aDocumentURI; - - mManifestURI = aManifestURI; - rv = mManifestURI->GetAsciiHost(mUpdateDomain); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr cacheService = - do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - rv = cacheService->GetApplicationCache(mClientID, - getter_AddRefs(mApplicationCache)); - NS_ENSURE_SUCCESS(rv, rv); - - if (!mApplicationCache) { - nsCAutoString manifestSpec; - rv = GetCacheKey(mManifestURI, manifestSpec); - NS_ENSURE_SUCCESS(rv, rv); - - rv = cacheService->CreateApplicationCache - (manifestSpec, getter_AddRefs(mApplicationCache)); - NS_ENSURE_SUCCESS(rv, rv); - } - - nsCAutoString groupID; - rv = mApplicationCache->GetGroupID(groupID); - NS_ENSURE_SUCCESS(rv, rv); - - rv = NS_NewURI(getter_AddRefs(mManifestURI), groupID); - NS_ENSURE_SUCCESS(rv, rv); - - mState = STATE_INITIALIZED; return NS_OK; } @@ -1658,7 +1610,6 @@ nsOfflineCacheUpdateService::ScheduleOnDocumentStop(nsIURI *aManifestURI, LOG(("nsOfflineCacheUpdateService::ScheduleOnDocumentStop [%p, manifestURI=%p, documentURI=%p doc=%p]", this, aManifestURI, aDocumentURI, aDocument)); - // Proceed with cache update PendingUpdate *update = new PendingUpdate(); update->mManifestURI = aManifestURI; update->mDocumentURI = aDocumentURI; @@ -1786,7 +1737,7 @@ nsOfflineCacheUpdateService::ScheduleUpdate(nsIURI *aManifestURI, if (!update) return NS_ERROR_OUT_OF_MEMORY; - rv = update->Init(aManifestURI, aDocumentURI); + rv = update->Init(PR_FALSE, aManifestURI, aDocumentURI); NS_ENSURE_SUCCESS(rv, rv); rv = update->Schedule();