diff --git a/dom/tests/mochitest/ajax/offline/Makefile.in b/dom/tests/mochitest/ajax/offline/Makefile.in
index 3241c94427f4..69ed8da21136 100644
--- a/dom/tests/mochitest/ajax/offline/Makefile.in
+++ b/dom/tests/mochitest/ajax/offline/Makefile.in
@@ -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 \
diff --git a/dom/tests/mochitest/ajax/offline/test_updateCheck.html b/dom/tests/mochitest/ajax/offline/test_updateCheck.html
new file mode 100644
index 000000000000..a1f27e3ef8c1
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_updateCheck.html
@@ -0,0 +1,86 @@
+
+
+Cache update test
+
+
+
+
+
+
+
+
+
+
diff --git a/netwerk/base/public/nsIApplicationCacheService.idl b/netwerk/base/public/nsIApplicationCacheService.idl
index 5bdcef4f3919..bc00394873ad 100644
--- a/netwerk/base/public/nsIApplicationCacheService.idl
+++ b/netwerk/base/public/nsIApplicationCacheService.idl
@@ -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.
diff --git a/netwerk/cache/nsApplicationCacheService.cpp b/netwerk/cache/nsApplicationCacheService.cpp
index 89e3ebb71e23..f56a965fa850 100644
--- a/netwerk/cache/nsApplicationCacheService.cpp
+++ b/netwerk/cache/nsApplicationCacheService.cpp
@@ -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;
diff --git a/netwerk/cache/nsApplicationCacheService.h b/netwerk/cache/nsApplicationCacheService.h
index 4580f5cbb18b..9a9586cd467c 100644
--- a/netwerk/cache/nsApplicationCacheService.h
+++ b/netwerk/cache/nsApplicationCacheService.h
@@ -21,10 +21,6 @@ public:
static void AppClearDataObserverInit();
private:
- nsresult GetJARIdentifier(nsIURI *aURI,
- nsILoadContext *aLoadContext,
- nsACString &_result);
-
nsRefPtr mCacheService;
};
diff --git a/netwerk/cache/nsDiskCacheDeviceSQL.cpp b/netwerk/cache/nsDiskCacheDeviceSQL.cpp
index fa4cb9ee6068..a092a5600762 100644
--- a/netwerk/cache/nsDiskCacheDeviceSQL.cpp
+++ b/netwerk/cache/nsDiskCacheDeviceSQL.cpp
@@ -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 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)
diff --git a/netwerk/cache/nsDiskCacheDeviceSQL.h b/netwerk/cache/nsDiskCacheDeviceSQL.h
index 5dbb49bfbf0f..d8fcbdb9f0a5 100644
--- a/netwerk/cache/nsDiskCacheDeviceSQL.h
+++ b/netwerk/cache/nsDiskCacheDeviceSQL.h
@@ -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,
diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp
index 91258ff6d24a..83e5334900f4 100644
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -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;
diff --git a/uriloader/prefetch/OfflineCacheUpdateChild.cpp b/uriloader/prefetch/OfflineCacheUpdateChild.cpp
index 4cd775737fe9..2c14966a1eaa 100644
--- a/uriloader/prefetch/OfflineCacheUpdateChild.cpp
+++ b/uriloader/prefetch/OfflineCacheUpdateChild.cpp
@@ -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)
{
diff --git a/uriloader/prefetch/OfflineCacheUpdateGlue.h b/uriloader/prefetch/OfflineCacheUpdateGlue.h
index a36959e6796d..ac6dabbbb828 100644
--- a/uriloader/prefetch/OfflineCacheUpdateGlue.h
+++ b/uriloader/prefetch/OfflineCacheUpdateGlue.h
@@ -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); } \
diff --git a/uriloader/prefetch/nsIOfflineCacheUpdate.idl b/uriloader/prefetch/nsIOfflineCacheUpdate.idl
index 4b38f67da1ce..6b70422272d4 100644
--- a/uriloader/prefetch/nsIOfflineCacheUpdate.idl
+++ b/uriloader/prefetch/nsIOfflineCacheUpdate.idl
@@ -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.
diff --git a/uriloader/prefetch/nsOfflineCacheUpdate.cpp b/uriloader/prefetch/nsOfflineCacheUpdate.cpp
index 92c5ed79978a..38ca26fbff58 100644
--- a/uriloader/prefetch/nsOfflineCacheUpdate.cpp
+++ b/uriloader/prefetch/nsOfflineCacheUpdate.cpp
@@ -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 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 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 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 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;
}
diff --git a/uriloader/prefetch/nsOfflineCacheUpdate.h b/uriloader/prefetch/nsOfflineCacheUpdate.h
index 7aac16c1b0f9..375371e77d7a 100644
--- a/uriloader/prefetch/nsOfflineCacheUpdate.h
+++ b/uriloader/prefetch/nsOfflineCacheUpdate.h
@@ -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* namespaceFilter = nullptr);
nsresult ScheduleImplicit();
void AssociateDocuments(nsIApplicationCache* cache);
+ bool CheckUpdateAvailability();
+ void NotifyUpdateAvailability(bool updateAvailable);
void GatherObservers(nsCOMArray &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 mDocumentURI;
nsCOMPtr mCustomProfileDir;
nsCOMPtr mLoadContext;
+ nsCOMPtr mUpdateAvailableObserver;
nsCOMPtr mApplicationCache;
nsCOMPtr mPreviousApplicationCache;
diff --git a/uriloader/prefetch/nsOfflineCacheUpdateService.cpp b/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
index a653a544807a..2ca3b18c001a 100644
--- a/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
+++ b/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
@@ -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 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
//-----------------------------------------------------------------------------