зеркало из https://github.com/mozilla/gecko-dev.git
Bug 751754 - Allow separation between the update-available and start-download states in appcache, r=jduell
This commit is contained in:
Родитель
1d591da571
Коммит
edba2799c8
|
@ -47,6 +47,7 @@ MOCHITEST_FILES = \
|
|||
overlap.cacheManifest \
|
||||
overlap.cacheManifest^headers^ \
|
||||
test_updatingManifest.html \
|
||||
test_updateCheck.html \
|
||||
445544_part1.html \
|
||||
445544_part2.html \
|
||||
445544.cacheManifest \
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml" manifest="http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/updatingManifest.sjs">
|
||||
<head>
|
||||
<title>Cache update test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/*
|
||||
* The test is checking nsIOfflineCacheUpdateService.checkForUpdate API:
|
||||
* - cache a manifest
|
||||
* - check for an update of it, expected is "no update avail"
|
||||
* - modify the manifest on the server
|
||||
* - check for an update again, expected is "update avail"
|
||||
* - check for an update ones again, expected is "update avail" (secondary check to probe
|
||||
* we didn't screw state of the manifest in the current cache with the first check)
|
||||
* - cache the modified manifest, new version is now in the cache
|
||||
* - last check for an update, expected is "no update avail" again
|
||||
*/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var manifest = "http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/updatingManifest.sjs";
|
||||
var manifestURI = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService)
|
||||
.newURI(manifest, null, null);
|
||||
var updateService = Cc['@mozilla.org/offlinecacheupdate-service;1']
|
||||
.getService(Ci.nsIOfflineCacheUpdateService);
|
||||
|
||||
function manifestCached()
|
||||
{
|
||||
// Run first check for an update
|
||||
updateService.checkForUpdate(manifestURI, 0, false, {
|
||||
observe: function(subject, topic, data) {
|
||||
OfflineTest.is(topic, "offline-cache-update-unavailable", "No update avail");
|
||||
|
||||
// Change the manifest content
|
||||
OfflineTest.setSJSState(manifest, "second");
|
||||
|
||||
// Check we now get notification on update ready
|
||||
updateService.checkForUpdate(manifestURI, 0, false, {
|
||||
observe: function(subject, topic, data) {
|
||||
OfflineTest.is(topic, "offline-cache-update-available", "Update avail (1)");
|
||||
|
||||
// Do the check again. We must get the same result. Double check is here
|
||||
// to make sure we don't overwrite any data in the cache by the check it self.
|
||||
updateService.checkForUpdate(manifestURI, 0, false, {
|
||||
observe: function(subject, topic, data) {
|
||||
OfflineTest.is(topic, "offline-cache-update-available", "Update avail (2)");
|
||||
|
||||
// Update the manifest, invokes manifestUpdated()
|
||||
applicationCache.onupdateready = OfflineTest.priv(manifestUpdated);
|
||||
applicationCache.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function manifestUpdated()
|
||||
{
|
||||
// Check for an update after manifest has been updated
|
||||
updateService.checkForUpdate(manifestURI, 0, false, {
|
||||
observe: function(subject, topic, data) {
|
||||
OfflineTest.is(topic, "offline-cache-update-unavailable", "No update avail (2)");
|
||||
|
||||
OfflineTest.teardown();
|
||||
OfflineTest.finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (OfflineTest.setup()) {
|
||||
applicationCache.onerror = OfflineTest.failEvent;
|
||||
applicationCache.oncached = OfflineTest.priv(manifestCached);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -15,7 +15,7 @@ interface nsILoadContext;
|
|||
* The application cache service manages the set of application cache
|
||||
* groups.
|
||||
*/
|
||||
[scriptable, uuid(1750F671-0170-4d3f-A836-455501141E32)]
|
||||
[scriptable, uuid(9b5b2cde-d5dd-48d3-87f8-8e8b776952a8)]
|
||||
interface nsIApplicationCacheService : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -25,6 +25,13 @@ interface nsIApplicationCacheService : nsISupports
|
|||
ACString buildGroupID(in nsIURI aManifestURL,
|
||||
in nsILoadContext aLoadContext);
|
||||
|
||||
/**
|
||||
* Same as buildGroupID method, just doesn't require load context.
|
||||
*/
|
||||
ACString buildGroupIDForApp(in nsIURI aManifestURL,
|
||||
in unsigned long aAppID,
|
||||
in boolean aInBrowser);
|
||||
|
||||
/**
|
||||
* Create a new, empty application cache for the given cache
|
||||
* group.
|
||||
|
|
|
@ -30,9 +30,35 @@ NS_IMETHODIMP
|
|||
nsApplicationCacheService::BuildGroupID(nsIURI *aManifestURL,
|
||||
nsILoadContext *aLoadContext,
|
||||
nsACString &_result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
uint32_t appId = NECKO_NO_APP_ID;
|
||||
bool isInBrowserElement = false;
|
||||
|
||||
if (aLoadContext) {
|
||||
rv = aLoadContext->GetAppId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aLoadContext->GetIsInBrowserElement(&isInBrowserElement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = nsOfflineCacheDevice::BuildApplicationCacheGroupID(
|
||||
aManifestURL, appId, isInBrowserElement, _result);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationCacheService::BuildGroupIDForApp(nsIURI *aManifestURL,
|
||||
uint32_t aAppId,
|
||||
bool aIsInBrowser,
|
||||
nsACString &_result)
|
||||
{
|
||||
nsresult rv = nsOfflineCacheDevice::BuildApplicationCacheGroupID(
|
||||
aManifestURL, aLoadContext, _result);
|
||||
aManifestURL, aAppId, aIsInBrowser, _result);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -21,10 +21,6 @@ public:
|
|||
static void AppClearDataObserverInit();
|
||||
|
||||
private:
|
||||
nsresult GetJARIdentifier(nsIURI *aURI,
|
||||
nsILoadContext *aLoadContext,
|
||||
nsACString &_result);
|
||||
|
||||
nsRefPtr<nsCacheService> mCacheService;
|
||||
};
|
||||
|
||||
|
|
|
@ -1259,26 +1259,15 @@ AppendJARIdentifier(nsACString &_result, int32_t appId, bool isInBrowserElement)
|
|||
|
||||
nsresult
|
||||
GetJARIdentifier(nsIURI *aURI,
|
||||
nsILoadContext *aLoadContext,
|
||||
uint32_t appId, bool isInBrowserElement,
|
||||
nsACString &_result)
|
||||
{
|
||||
_result.Truncate();
|
||||
|
||||
if (!aLoadContext)
|
||||
return NS_OK;
|
||||
|
||||
// These lines are here for compatibility only. We must not fill the
|
||||
// JAR identifier when this is no-app context, otherwise web content
|
||||
// offline application cache loads would not be satisfied (cache would
|
||||
// not be found).
|
||||
bool isInBrowserElement;
|
||||
nsresult rv = aLoadContext->GetIsInBrowserElement(&isInBrowserElement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t appId;
|
||||
rv = aLoadContext->GetAppId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!isInBrowserElement && appId == NECKO_NO_APP_ID)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -1291,7 +1280,7 @@ GetJARIdentifier(nsIURI *aURI,
|
|||
// static
|
||||
nsresult
|
||||
nsOfflineCacheDevice::BuildApplicationCacheGroupID(nsIURI *aManifestURL,
|
||||
nsILoadContext *aLoadContext,
|
||||
uint32_t appId, bool isInBrowserElement,
|
||||
nsACString &_result)
|
||||
{
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
|
@ -1305,7 +1294,7 @@ nsOfflineCacheDevice::BuildApplicationCacheGroupID(nsIURI *aManifestURL,
|
|||
_result.Assign(manifestSpec);
|
||||
|
||||
nsAutoCString jarid;
|
||||
rv = GetJARIdentifier(aManifestURL, aLoadContext, jarid);
|
||||
rv = GetJARIdentifier(aManifestURL, appId, isInBrowserElement, jarid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Include JAR ID, i.e. the extended origin if present.
|
||||
|
@ -2442,11 +2431,24 @@ nsOfflineCacheDevice::CanUseCache(nsIURI *keyURI,
|
|||
GetStrictFileOriginPolicy()))
|
||||
return false;
|
||||
|
||||
// Get extended origin attributes
|
||||
uint32_t appId = NECKO_NO_APP_ID;
|
||||
bool isInBrowserElement = false;
|
||||
|
||||
if (loadContext) {
|
||||
rv = loadContext->GetAppId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
rv = loadContext->GetIsInBrowserElement(&isInBrowserElement);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
|
||||
// Check the groupID we found is equal to groupID based
|
||||
// on the load context demanding load from app cache.
|
||||
// This is check of extended origin.
|
||||
nsAutoCString demandedGroupID;
|
||||
rv = BuildApplicationCacheGroupID(groupURI, loadContext, demandedGroupID);
|
||||
rv = BuildApplicationCacheGroupID(groupURI, appId, isInBrowserElement,
|
||||
demandedGroupID);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (groupID != demandedGroupID)
|
||||
|
|
|
@ -133,7 +133,7 @@ public:
|
|||
nsresult EvictUnownedEntries(const char *clientID);
|
||||
|
||||
static nsresult BuildApplicationCacheGroupID(nsIURI *aManifestURL,
|
||||
nsILoadContext *aLoadContext,
|
||||
uint32_t appId, bool isInBrowserElement,
|
||||
nsACString &_result);
|
||||
|
||||
nsresult ActivateCache(const nsCSubstring &group,
|
||||
|
|
|
@ -2540,6 +2540,11 @@ nsHttpChannel::OpenOfflineCacheEntryForWriting()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mLoadFlags & INHIBIT_CACHING) {
|
||||
// respect demand not to cache
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mRequestHead.Method() != nsHttp::Get) {
|
||||
// only cache complete documents offline
|
||||
return NS_OK;
|
||||
|
|
|
@ -240,6 +240,17 @@ OfflineCacheUpdateChild::InitPartial(nsIURI *aManifestURI,
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
OfflineCacheUpdateChild::InitForUpdateCheck(nsIURI *aManifestURI,
|
||||
uint32_t aAppID,
|
||||
bool aInBrowser,
|
||||
nsIObserver *aObserver)
|
||||
{
|
||||
NS_NOTREACHED("Not expected to do only update checks"
|
||||
" from the child process");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
OfflineCacheUpdateChild::GetUpdateDomain(nsACString &aUpdateDomain)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace docshell {
|
|||
NS_IMETHOD GetManifestURI(nsIURI **aManifestURI) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetManifestURI(aManifestURI); } \
|
||||
NS_IMETHOD GetSucceeded(bool *aSucceeded) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetSucceeded(aSucceeded); } \
|
||||
NS_IMETHOD InitPartial(nsIURI *aManifestURI, const nsACString & aClientID, nsIURI *aDocumentURI) { return !_to ? NS_ERROR_NULL_POINTER : _to->InitPartial(aManifestURI, aClientID, aDocumentURI); } \
|
||||
NS_IMETHOD InitForUpdateCheck(nsIURI *aManifestURI, uint32_t aAppID, bool aInBrowser, nsIObserver *aObserver) { return !_to ? NS_ERROR_NULL_POINTER : _to->InitForUpdateCheck(aManifestURI, aAppID, aInBrowser, aObserver); } \
|
||||
NS_IMETHOD AddDynamicURI(nsIURI *aURI) { return !_to ? NS_ERROR_NULL_POINTER : _to->AddDynamicURI(aURI); } \
|
||||
NS_IMETHOD AddObserver(nsIOfflineCacheUpdateObserver *aObserver, bool aHoldWeak) { return !_to ? NS_ERROR_NULL_POINTER : _to->AddObserver(aObserver, aHoldWeak); } \
|
||||
NS_IMETHOD RemoveObserver(nsIOfflineCacheUpdateObserver *aObserver) { return !_to ? NS_ERROR_NULL_POINTER : _to->RemoveObserver(aObserver); } \
|
||||
|
|
|
@ -16,6 +16,7 @@ interface nsIPrefBranch;
|
|||
interface nsIApplicationCache;
|
||||
interface nsIFile;
|
||||
interface nsILoadContext;
|
||||
interface nsIObserver;
|
||||
|
||||
[scriptable, uuid(47360d57-8ef4-4a5d-8865-1a27a739ad1a)]
|
||||
interface nsIOfflineCacheUpdateObserver : nsISupports {
|
||||
|
@ -63,7 +64,7 @@ interface nsIOfflineCacheUpdateObserver : nsISupports {
|
|||
* load its items one by one, sending itemCompleted() to any registered
|
||||
* observers.
|
||||
*/
|
||||
[scriptable, uuid(D47966B2-1EBC-45c5-8639-2937ED200281)]
|
||||
[scriptable, uuid(91d356fa-4eaf-4de2-9870-bb92854cccfe)]
|
||||
interface nsIOfflineCacheUpdate : nsISupports {
|
||||
/**
|
||||
* Fetch the status of the running update. This will return a value
|
||||
|
@ -126,6 +127,29 @@ interface nsIOfflineCacheUpdate : nsISupports {
|
|||
*/
|
||||
void initPartial(in nsIURI aManifestURI, in ACString aClientID, in nsIURI aDocumentURI);
|
||||
|
||||
/**
|
||||
* Initialize the update to only check whether there is an update
|
||||
* to the manifest available (if it has actually changed on the server).
|
||||
*
|
||||
* @param aManifestURI
|
||||
* The manifest URI of the related cache.
|
||||
* @param aAppID
|
||||
* Local ID of an app (optional) to check the cache update for.
|
||||
* @param aInBrowser
|
||||
* Whether to check for a cache populated from browser element.
|
||||
* @param aObserver
|
||||
* nsIObserver implementation that receives the result.
|
||||
* When aTopic == "offline-cache-update-available" there is an update to
|
||||
* to download. Update of the app cache will lead to a new version
|
||||
* download.
|
||||
* When aTopic == "offline-cache-update-unavailable" then there is no
|
||||
* update available (the manifest has not changed on the server).
|
||||
*/
|
||||
void initForUpdateCheck(in nsIURI aManifestURI,
|
||||
in unsigned long aAppID,
|
||||
in boolean aInBrowser,
|
||||
in nsIObserver aObserver);
|
||||
|
||||
/**
|
||||
* Add a dynamic URI to the offline cache as part of the update.
|
||||
*
|
||||
|
@ -166,7 +190,7 @@ interface nsIOfflineCacheUpdate : nsISupports {
|
|||
readonly attribute uint64_t byteProgress;
|
||||
};
|
||||
|
||||
[scriptable, uuid(dc5de18c-197c-41d2-9584-dd7ac7494611)]
|
||||
[scriptable, uuid(9ff7f81f-114a-4876-ad1b-f3910418e4a6)]
|
||||
interface nsIOfflineCacheUpdateService : nsISupports {
|
||||
/**
|
||||
* Constants for the offline-app permission.
|
||||
|
@ -213,6 +237,22 @@ interface nsIOfflineCacheUpdateService : nsISupports {
|
|||
in nsIURI aDocumentURI,
|
||||
in nsIDOMDocument aDocument);
|
||||
|
||||
/**
|
||||
* Schedule a check to see if an update is available.
|
||||
*
|
||||
* This will not update or make any changes to the appcache.
|
||||
* It only notifies the observer to indicate whether the manifest has
|
||||
* changed on the server (or not): a changed manifest means that an
|
||||
* update is available.
|
||||
*
|
||||
* For arguments see nsIOfflineCacheUpdate.initForUpdateCheck() method
|
||||
* description.
|
||||
*/
|
||||
void checkForUpdate(in nsIURI aManifestURI,
|
||||
in unsigned long aAppID,
|
||||
in boolean aInBrowser,
|
||||
in nsIObserver aObserver);
|
||||
|
||||
/**
|
||||
* Checks whether a principal should have access to the offline
|
||||
* cache.
|
||||
|
|
|
@ -332,12 +332,21 @@ nsOfflineCacheUpdateItem::OpenChannel(nsOfflineCacheUpdate *aUpdate)
|
|||
nsresult rv = nsOfflineCacheUpdate::GetCacheKey(mURI, mCacheKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t flags = nsIRequest::LOAD_BACKGROUND |
|
||||
nsICachingChannel::LOAD_ONLY_IF_MODIFIED |
|
||||
nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE;
|
||||
|
||||
if (mApplicationCache == mPreviousApplicationCache) {
|
||||
// Same app cache to read from and to write to is used during
|
||||
// an only-update-check procedure. Here we protect the existing
|
||||
// cache from being modified.
|
||||
flags |= nsIRequest::INHIBIT_CACHING;
|
||||
}
|
||||
|
||||
rv = NS_NewChannel(getter_AddRefs(mChannel),
|
||||
mURI,
|
||||
nullptr, nullptr, this,
|
||||
nsIRequest::LOAD_BACKGROUND |
|
||||
nsICachingChannel::LOAD_ONLY_IF_MODIFIED |
|
||||
nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE);
|
||||
flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
|
||||
|
@ -350,7 +359,7 @@ nsOfflineCacheUpdateItem::OpenChannel(nsOfflineCacheUpdate *aUpdate)
|
|||
rv = appCacheChannel->SetApplicationCache(mPreviousApplicationCache);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Set the new application cache as the targer for write.
|
||||
// Set the new application cache as the target for write.
|
||||
rv = appCacheChannel->SetApplicationCacheForWrite(mApplicationCache);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -1159,6 +1168,7 @@ nsOfflineCacheUpdate::nsOfflineCacheUpdate()
|
|||
, mOwner(nullptr)
|
||||
, mAddedItems(false)
|
||||
, mPartialUpdate(false)
|
||||
, mOnlyCheckUpdate(false)
|
||||
, mSucceeded(true)
|
||||
, mObsolete(false)
|
||||
, mItemsInProgress(0)
|
||||
|
@ -1190,24 +1200,10 @@ nsOfflineCacheUpdate::GetCacheKey(nsIURI *aURI, nsACString &aKey)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheUpdate::Init(nsIURI *aManifestURI,
|
||||
nsIURI *aDocumentURI,
|
||||
nsIDOMDocument *aDocument,
|
||||
nsIFile *aCustomProfileDir,
|
||||
nsILoadContext *aLoadContext)
|
||||
nsOfflineCacheUpdate::InitInternal(nsIURI *aManifestURI)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Make sure the service has been initialized
|
||||
nsOfflineCacheUpdateService* service =
|
||||
nsOfflineCacheUpdateService::EnsureService();
|
||||
if (!service)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
LOG(("nsOfflineCacheUpdate::Init [%p]", this));
|
||||
|
||||
mPartialUpdate = false;
|
||||
|
||||
// Only http and https applications are supported.
|
||||
bool match;
|
||||
rv = aManifestURI->SchemeIs("http", &match);
|
||||
|
@ -1225,6 +1221,31 @@ nsOfflineCacheUpdate::Init(nsIURI *aManifestURI,
|
|||
rv = mManifestURI->GetAsciiHost(mUpdateDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mPartialUpdate = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheUpdate::Init(nsIURI *aManifestURI,
|
||||
nsIURI *aDocumentURI,
|
||||
nsIDOMDocument *aDocument,
|
||||
nsIFile *aCustomProfileDir,
|
||||
nsILoadContext *aLoadContext)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Make sure the service has been initialized
|
||||
nsOfflineCacheUpdateService* service =
|
||||
nsOfflineCacheUpdateService::EnsureService();
|
||||
if (!service)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
LOG(("nsOfflineCacheUpdate::Init [%p]", this));
|
||||
|
||||
rv = InitInternal(aManifestURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheService> cacheService =
|
||||
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1277,6 +1298,58 @@ nsOfflineCacheUpdate::Init(nsIURI *aManifestURI,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheUpdate::InitForUpdateCheck(nsIURI *aManifestURI,
|
||||
uint32_t aAppID,
|
||||
bool aInBrowser,
|
||||
nsIObserver *aObserver)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Make sure the service has been initialized
|
||||
nsOfflineCacheUpdateService* service =
|
||||
nsOfflineCacheUpdateService::EnsureService();
|
||||
if (!service)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
LOG(("nsOfflineCacheUpdate::InitForUpdateCheck [%p]", this));
|
||||
|
||||
rv = InitInternal(aManifestURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheService> cacheService =
|
||||
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = cacheService->BuildGroupIDForApp(aManifestURI,
|
||||
aAppID, aInBrowser,
|
||||
mGroupID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = cacheService->GetActiveCache(mGroupID,
|
||||
getter_AddRefs(mPreviousApplicationCache));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// To load the manifest properly using current app cache to satisfy and
|
||||
// also to compare the cached content hash value we have to set 'some'
|
||||
// app cache to write to on the channel. Otherwise the cached version will
|
||||
// be used and no actual network request will be made. We use the same
|
||||
// app cache here. OpenChannel prevents caching in this case using
|
||||
// INHIBIT_CACHING load flag.
|
||||
mApplicationCache = mPreviousApplicationCache;
|
||||
|
||||
rv = nsOfflineCacheUpdateService::OfflineAppPinnedForURI(aManifestURI,
|
||||
NULL,
|
||||
&mPinned);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mUpdateAvailableObserver = aObserver;
|
||||
mOnlyCheckUpdate = true;
|
||||
|
||||
mState = STATE_INITIALIZED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheUpdate::InitPartial(nsIURI *aManifestURI,
|
||||
const nsACString& clientID,
|
||||
|
@ -1388,6 +1461,35 @@ nsOfflineCacheUpdate::HandleManifest(bool *aDoUpdate)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsOfflineCacheUpdate::CheckUpdateAvailability()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
bool succeeded;
|
||||
rv = mManifestItem->GetRequestSucceeded(&succeeded);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (!succeeded || !mManifestItem->ParseSucceeded()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mPinned) {
|
||||
uint16_t status;
|
||||
rv = mManifestItem->GetStatus(&status);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
// Treat these as there would be an update available,
|
||||
// since this is indication of demand to remove this
|
||||
// offline cache.
|
||||
if (status == 404 || status == 410) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return mManifestItem->NeedsUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
nsOfflineCacheUpdate::LoadCompleted(nsOfflineCacheUpdateItem *aItem)
|
||||
{
|
||||
|
@ -1411,6 +1513,12 @@ nsOfflineCacheUpdate::LoadCompleted(nsOfflineCacheUpdateItem *aItem)
|
|||
if (mState == STATE_CHECKING) {
|
||||
// Manifest load finished.
|
||||
|
||||
if (mOnlyCheckUpdate) {
|
||||
Finish();
|
||||
NotifyUpdateAvailability(CheckUpdateAvailability());
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mManifestItem,
|
||||
"Must have a manifest item in STATE_CHECKING.");
|
||||
NS_ASSERTION(mManifestItem == aItem,
|
||||
|
@ -1831,6 +1939,24 @@ nsOfflineCacheUpdate::NotifyState(uint32_t state)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsOfflineCacheUpdate::NotifyUpdateAvailability(bool updateAvailable)
|
||||
{
|
||||
if (!mUpdateAvailableObserver)
|
||||
return;
|
||||
|
||||
LOG(("nsOfflineCacheUpdate::NotifyUpdateAvailability [this=%p, avail=%d]",
|
||||
this, updateAvailable));
|
||||
|
||||
const char* topic = updateAvailable
|
||||
? "offline-cache-update-available"
|
||||
: "offline-cache-update-unavailable";
|
||||
|
||||
nsCOMPtr<nsIObserver> observer;
|
||||
observer.swap(mUpdateAvailableObserver);
|
||||
observer->Observe(mManifestURI, topic, nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
nsOfflineCacheUpdate::AssociateDocuments(nsIApplicationCache* cache)
|
||||
{
|
||||
|
@ -1934,7 +2060,7 @@ nsOfflineCacheUpdate::FinishNoNotify()
|
|||
|
||||
mState = STATE_FINISHED;
|
||||
|
||||
if (!mPartialUpdate) {
|
||||
if (!mPartialUpdate && !mOnlyCheckUpdate) {
|
||||
if (mSucceeded) {
|
||||
nsIArray *namespaces = mManifestItem->GetNamespaces();
|
||||
nsresult rv = mApplicationCache->AddNamespaces(namespaces);
|
||||
|
@ -2080,7 +2206,7 @@ nsOfflineCacheUpdate::GetStatus(uint16_t *aStatus)
|
|||
NS_IMETHODIMP
|
||||
nsOfflineCacheUpdate::GetPartial(bool *aPartial)
|
||||
{
|
||||
*aPartial = mPartialUpdate;
|
||||
*aPartial = mPartialUpdate || mOnlyCheckUpdate;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -218,6 +218,7 @@ protected:
|
|||
void OnByteProgress(uint64_t byteIncrement);
|
||||
|
||||
private:
|
||||
nsresult InitInternal(nsIURI *aManifestURI);
|
||||
nsresult HandleManifest(bool *aDoUpdate);
|
||||
nsresult AddURI(nsIURI *aURI, uint32_t aItemType);
|
||||
|
||||
|
@ -230,6 +231,8 @@ private:
|
|||
nsTArray<nsCString>* namespaceFilter = nullptr);
|
||||
nsresult ScheduleImplicit();
|
||||
void AssociateDocuments(nsIApplicationCache* cache);
|
||||
bool CheckUpdateAvailability();
|
||||
void NotifyUpdateAvailability(bool updateAvailable);
|
||||
|
||||
void GatherObservers(nsCOMArray<nsIOfflineCacheUpdateObserver> &aObservers);
|
||||
void NotifyState(uint32_t state);
|
||||
|
@ -252,6 +255,7 @@ private:
|
|||
|
||||
bool mAddedItems;
|
||||
bool mPartialUpdate;
|
||||
bool mOnlyCheckUpdate;
|
||||
bool mSucceeded;
|
||||
bool mObsolete;
|
||||
|
||||
|
@ -261,6 +265,7 @@ private:
|
|||
nsCOMPtr<nsIURI> mDocumentURI;
|
||||
nsCOMPtr<nsIFile> mCustomProfileDir;
|
||||
nsCOMPtr<nsILoadContext> mLoadContext;
|
||||
nsCOMPtr<nsIObserver> mUpdateAvailableObserver;
|
||||
|
||||
nsCOMPtr<nsIApplicationCache> mApplicationCache;
|
||||
nsCOMPtr<nsIApplicationCache> mPreviousApplicationCache;
|
||||
|
|
|
@ -499,6 +499,29 @@ nsOfflineCacheUpdateService::ScheduleCustomProfileUpdate(nsIURI *aManifestURI,
|
|||
return Schedule(aManifestURI, aDocumentURI, nullptr, nullptr, aProfileDir, aUpdate);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsOfflineCacheUpdateService::CheckForUpdate(nsIURI *aManifestURI,
|
||||
uint32_t aAppID,
|
||||
bool aInBrowser,
|
||||
nsIObserver *aObserver)
|
||||
{
|
||||
if (GeckoProcessType_Default != XRE_GetProcessType()) {
|
||||
// Not intended to support this on child processes
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIOfflineCacheUpdate> update = new OfflineCacheUpdateGlue();
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = update->InitForUpdateCheck(aManifestURI, aAppID, aInBrowser, aObserver);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = update->Schedule();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsOfflineCacheUpdateService::nsIObserver
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
Загрузка…
Ссылка в новой задаче