mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 442812: Implement the application cache selection algorithm. r+sr=bz
This commit is contained in:
parent
14f256186b
commit
bec376906f
@ -316,118 +316,7 @@ PRBool
|
||||
nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI,
|
||||
nsIURI* aTargetURI)
|
||||
{
|
||||
// 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<nsIURI> sourceBaseURI = NS_GetInnermostURI(aSourceURI);
|
||||
nsCOMPtr<nsIURI> 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<nsIFileURL> sourceFileURL(do_QueryInterface(sourceBaseURI));
|
||||
nsCOMPtr<nsIFileURL> targetFileURL(do_QueryInterface(targetBaseURI));
|
||||
|
||||
if (!sourceFileURL || !targetFileURL)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIFile> 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;
|
||||
return NS_SecurityCompareURIs(aSourceURI, aTargetURI, sStrictFileOriginPolicy);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1250,6 +1250,11 @@ 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
|
||||
|
@ -59,6 +59,7 @@ REQUIRES = xpcom \
|
||||
js \
|
||||
webshell \
|
||||
necko \
|
||||
nkcache \
|
||||
mimetype \
|
||||
exthandler \
|
||||
chardet \
|
||||
|
@ -73,6 +73,7 @@
|
||||
#include "nsIOfflineCacheUpdate.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheContainer.h"
|
||||
#include "nsIApplicationCacheService.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIDOMLoadStatus.h"
|
||||
#include "nsICookieService.h"
|
||||
@ -96,6 +97,10 @@
|
||||
#include "nsPresShellIterator.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIDocumentLoader.h"
|
||||
#include "nsICachingChannel.h"
|
||||
#include "nsICacheEntryDescriptor.h"
|
||||
|
||||
PRLogModuleInfo* gContentSinkLogModuleInfo;
|
||||
|
||||
@ -847,79 +852,304 @@ nsContentSink::PrefetchHref(const nsAString &aHref,
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContentSink::GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey)
|
||||
{
|
||||
aCacheKey.Truncate();
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsICachingChannel> cachingChannel = do_QueryInterface(aChannel, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsISupports> token;
|
||||
rv = cachingChannel->GetCacheToken(getter_AddRefs(token));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsICacheEntryDescriptor> 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<nsIApplicationCacheContainer> applicationCacheDocument =
|
||||
do_QueryInterface(mDocument);
|
||||
NS_ASSERTION(applicationCacheDocument,
|
||||
"mDocument must implement nsIApplicationCacheContainer.");
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// We might decide on a new application cache...
|
||||
nsCOMPtr<nsIApplicationCache> applicationCache = aLoadApplicationCache;
|
||||
|
||||
if (applicationCache) {
|
||||
nsCAutoString groupID;
|
||||
rv = applicationCache->GetGroupID(groupID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> 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<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);
|
||||
}
|
||||
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<nsIApplicationCacheContainer> 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);
|
||||
|
||||
if (manifestSpec.IsEmpty() ||
|
||||
manifestSpec.FindChar('#') != kNotFound) {
|
||||
// Grab the application cache the document was loaded from, if any.
|
||||
nsCOMPtr<nsIApplicationCache> applicationCache;
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheContainer> 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.
|
||||
return;
|
||||
}
|
||||
|
||||
// We only care about manifests in toplevel windows.
|
||||
nsCOMPtr<nsPIDOMWindow> pwindow =
|
||||
do_QueryInterface(mDocument->GetScriptGlobalObject());
|
||||
if (!pwindow) {
|
||||
// The manifest attribute is handled differently if the document is
|
||||
// not toplevel.
|
||||
nsCOMPtr<nsIDOMWindow> window = mDocument->GetWindow();
|
||||
if (!window)
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> window =
|
||||
do_QueryInterface(pwindow->GetOuterWindow());
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> parent;
|
||||
window->GetParent(getter_AddRefs(parent));
|
||||
if (parent.get() != window.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only update if the document has permission to use offline APIs.
|
||||
if (!nsContentUtils::OfflineAppAllowed(mDocumentURI)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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<nsIApplicationCacheContainer> channelContainer =
|
||||
do_QueryInterface(mDocument->GetChannel());
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheContainer> docContainer =
|
||||
do_QueryInterface(mDocument);
|
||||
|
||||
if (channelContainer && docContainer) {
|
||||
nsCOMPtr<nsIApplicationCache> appCache;
|
||||
channelContainer->GetApplicationCache(getter_AddRefs(appCache));
|
||||
docContainer->SetApplicationCache(appCache);
|
||||
}
|
||||
PRBool isTop = (parent == window);
|
||||
|
||||
CacheSelectionAction action = CACHE_SELECTION_NONE;
|
||||
nsCOMPtr<nsIURI> manifestURI;
|
||||
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI),
|
||||
manifestSpec, mDocument,
|
||||
mDocumentURI);
|
||||
if (!manifestURI) {
|
||||
return;
|
||||
|
||||
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<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 (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Documents must list a manifest from the same origin
|
||||
nsresult rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, PR_TRUE);
|
||||
if (NS_FAILED(rv)) {
|
||||
switch (action)
|
||||
{
|
||||
case CACHE_SELECTION_NONE:
|
||||
return;
|
||||
}
|
||||
case CACHE_SELECTION_UPDATE: {
|
||||
nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
|
||||
do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
|
||||
|
||||
// Start the update
|
||||
nsCOMPtr<nsIDOMDocument> domdoc = do_QueryInterface(mDocument);
|
||||
nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
|
||||
do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
|
||||
updateService->ScheduleOnDocumentStop(manifestURI, mDocumentURI, domdoc);
|
||||
if (updateService) {
|
||||
nsCOMPtr<nsIDOMDocument> domdoc = do_QueryInterface(mDocument);
|
||||
updateService->ScheduleOnDocumentStop(manifestURI, mDocumentURI, domdoc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -76,6 +76,7 @@ class nsIContent;
|
||||
class nsIViewManager;
|
||||
class nsNodeInfoManager;
|
||||
class nsScriptLoader;
|
||||
class nsIApplicationCache;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
|
||||
@ -150,6 +151,25 @@ 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);
|
||||
|
||||
@ -171,6 +191,60 @@ 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
|
||||
|
@ -811,6 +811,16 @@ nsContentUtils::OfflineAppAllowed(nsIURI *aURI)
|
||||
return NS_OfflineAppAllowed(aURI, sPrefBranch);
|
||||
}
|
||||
|
||||
/* static */
|
||||
PRBool
|
||||
nsContentUtils::OfflineAppAllowed(nsIPrincipal *aPrincipal)
|
||||
{
|
||||
nsCOMPtr<nsIURI> codebaseURI;
|
||||
aPrincipal->GetURI(getter_AddRefs(codebaseURI));
|
||||
|
||||
return OfflineAppAllowed(codebaseURI);
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsContentUtils::Shutdown()
|
||||
|
@ -338,7 +338,11 @@ nsDOMOfflineResourceList::Add(const nsAString& aURI)
|
||||
do_CreateInstance(NS_OFFLINECACHEUPDATE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = update->Init(PR_TRUE, mManifestURI, mDocumentURI);
|
||||
nsCAutoString clientID;
|
||||
rv = appCache->GetClientID(clientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = update->InitPartial(mManifestURI, clientID, mDocumentURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = update->AddDynamicURI(requestedURI);
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "nsIStringStream.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsIFileStreams.h"
|
||||
#include "nsIFileURL.h"
|
||||
#include "nsIProtocolProxyService.h"
|
||||
#include "nsIProxyInfo.h"
|
||||
#include "nsIFileStreams.h"
|
||||
@ -1465,4 +1466,128 @@ 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<nsIURI> sourceBaseURI = NS_GetInnermostURI(aSourceURI);
|
||||
nsCOMPtr<nsIURI> 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<nsIFileURL> sourceFileURL(do_QueryInterface(sourceBaseURI));
|
||||
nsCOMPtr<nsIFileURL> targetFileURL(do_QueryInterface(targetBaseURI));
|
||||
|
||||
if (!sourceFileURL || !targetFileURL)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIFile> 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__
|
||||
|
51
netwerk/cache/src/nsDiskCacheDeviceSQL.cpp
vendored
51
netwerk/cache/src/nsDiskCacheDeviceSQL.cpp
vendored
@ -44,6 +44,8 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsString.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsCRT.h"
|
||||
@ -692,6 +694,20 @@ nsOfflineCacheDevice::~nsOfflineCacheDevice()
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
/* static */
|
||||
PRBool
|
||||
nsOfflineCacheDevice::GetStrictFileOriginPolicy()
|
||||
{
|
||||
nsCOMPtr<nsIPrefBranch> 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()
|
||||
{
|
||||
@ -1745,13 +1761,40 @@ nsOfflineCacheDevice::ChooseApplicationCache(const nsACString &key,
|
||||
rv = statement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> keyURI;
|
||||
rv = NS_NewURI(getter_AddRefs(keyURI), key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
while (hasRows) {
|
||||
nsCString clientID;
|
||||
rv = statement->GetUTF8String(0, clientID);
|
||||
PRInt32 itemType;
|
||||
rv = statement->GetInt32(1, &itemType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mActiveCaches.Contains(clientID))
|
||||
return GetApplicationCache(clientID, out);
|
||||
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<nsIURI> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = statement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
2
netwerk/cache/src/nsDiskCacheDeviceSQL.h
vendored
2
netwerk/cache/src/nsDiskCacheDeviceSQL.h
vendored
@ -184,6 +184,8 @@ private:
|
||||
nsIWeakReference *weakRef,
|
||||
void *ctx);
|
||||
|
||||
static PRBool GetStrictFileOriginPolicy();
|
||||
|
||||
PRBool Initialized() { return mDB != nsnull; }
|
||||
|
||||
nsresult InitActiveCaches();
|
||||
|
@ -115,7 +115,7 @@ interface nsIOfflineCacheUpdateObserver : nsISupports {
|
||||
* load its items one by one, sending itemCompleted() to any registered
|
||||
* observers.
|
||||
*/
|
||||
[scriptable, uuid(4b206247-82ee-46cf-a8b7-f7284e753bc2)]
|
||||
[scriptable, uuid(877261bb-b952-4d27-847e-859bdd47c0ec)]
|
||||
interface nsIOfflineCacheUpdate : nsISupports {
|
||||
/**
|
||||
* Fetch the status of the running update. This will return a value
|
||||
@ -154,21 +154,30 @@ 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, or for partial updates the
|
||||
* manifest that should own resources that are added.
|
||||
* The manifest URI to be checked.
|
||||
* @param aDocumentURI
|
||||
* The page that is requesting the update.
|
||||
*/
|
||||
void init(in boolean aPartialUpdate,
|
||||
in nsIURI aManifestURI,
|
||||
in nsIURI aDocumentURI);
|
||||
void init(in nsIURI aManifestURI, in nsIURI aDocumentURI);
|
||||
|
||||
/**
|
||||
* Add a URI to the offline cache as part of the update.
|
||||
* 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.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI to add.
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "nsICacheService.h"
|
||||
#include "nsICacheSession.h"
|
||||
#include "nsICachingChannel.h"
|
||||
#include "nsIDocumentLoader.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIDOMOfflineResourceList.h"
|
||||
#include "nsIObserverService.h"
|
||||
@ -57,6 +58,7 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsStringEnumerator.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prlog.h"
|
||||
|
||||
@ -577,6 +579,7 @@ nsOfflineManifestItem::HandleManifestLine(const nsCString::const_iterator &aBegi
|
||||
// this should have been dealt with earlier
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
case PARSE_CACHE_ENTRIES: {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), line, nsnull, mURI);
|
||||
@ -810,8 +813,7 @@ nsOfflineCacheUpdate::GetCacheKey(nsIURI *aURI, nsACString &aKey)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheUpdate::Init(PRBool aPartialUpdate,
|
||||
nsIURI *aManifestURI,
|
||||
nsOfflineCacheUpdate::Init(nsIURI *aManifestURI,
|
||||
nsIURI *aDocumentURI)
|
||||
{
|
||||
nsresult rv;
|
||||
@ -822,9 +824,9 @@ nsOfflineCacheUpdate::Init(PRBool aPartialUpdate,
|
||||
if (!service)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
LOG(("nsOfflineCacheUpdate::Init [%p, %d]", this, aPartialUpdate));
|
||||
LOG(("nsOfflineCacheUpdate::Init [%p]", this));
|
||||
|
||||
mPartialUpdate = aPartialUpdate;
|
||||
mPartialUpdate = PR_FALSE;
|
||||
|
||||
// Only http and https applications are supported.
|
||||
PRBool match;
|
||||
@ -858,20 +860,66 @@ nsOfflineCacheUpdate::Init(PRBool aPartialUpdate,
|
||||
getter_AddRefs(mPreviousApplicationCache));
|
||||
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 = 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<nsIApplicationCacheService> 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;
|
||||
}
|
||||
|
||||
@ -1610,6 +1658,7 @@ 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;
|
||||
@ -1737,7 +1786,7 @@ nsOfflineCacheUpdateService::ScheduleUpdate(nsIURI *aManifestURI,
|
||||
if (!update)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
rv = update->Init(PR_FALSE, aManifestURI, aDocumentURI);
|
||||
rv = update->Init(aManifestURI, aDocumentURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = update->Schedule();
|
||||
|
Loading…
Reference in New Issue
Block a user