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 //-----------------------------------------------------------------------------