michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsDiskCache.h" michael@0: #include "nsDiskCacheDeviceSQL.h" michael@0: #include "nsCacheService.h" michael@0: #include "nsApplicationCacheService.h" michael@0: #include "nsCRT.h" michael@0: #include "nsNetUtil.h" michael@0: #include "nsIObserverService.h" michael@0: #include "nsILoadContextInfo.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID); michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsApplicationCacheService michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: NS_IMPL_ISUPPORTS(nsApplicationCacheService, nsIApplicationCacheService) michael@0: michael@0: nsApplicationCacheService::nsApplicationCacheService() michael@0: { michael@0: nsCOMPtr serv = do_GetService(kCacheServiceCID); michael@0: mCacheService = nsCacheService::GlobalInstance(); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsApplicationCacheService::BuildGroupID(nsIURI *aManifestURL, michael@0: nsILoadContextInfo *aLoadContextInfo, michael@0: nsACString &_result) michael@0: { michael@0: nsresult rv; michael@0: michael@0: uint32_t appId = NECKO_NO_APP_ID; michael@0: bool isInBrowserElement = false; michael@0: michael@0: if (aLoadContextInfo) { michael@0: appId = aLoadContextInfo->AppId(); michael@0: isInBrowserElement = aLoadContextInfo->IsInBrowserElement(); michael@0: } michael@0: michael@0: rv = nsOfflineCacheDevice::BuildApplicationCacheGroupID( michael@0: aManifestURL, appId, isInBrowserElement, _result); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsApplicationCacheService::BuildGroupIDForApp(nsIURI *aManifestURL, michael@0: uint32_t aAppId, michael@0: bool aIsInBrowser, michael@0: nsACString &_result) michael@0: { michael@0: nsresult rv = nsOfflineCacheDevice::BuildApplicationCacheGroupID( michael@0: aManifestURL, aAppId, aIsInBrowser, _result); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsApplicationCacheService::CreateApplicationCache(const nsACString &group, michael@0: nsIApplicationCache **out) michael@0: { michael@0: if (!mCacheService) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: nsRefPtr device; michael@0: nsresult rv = mCacheService->GetOfflineDevice(getter_AddRefs(device)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: return device->CreateApplicationCache(group, out); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsApplicationCacheService::CreateCustomApplicationCache(const nsACString & group, michael@0: nsIFile *profileDir, michael@0: int32_t quota, michael@0: nsIApplicationCache **out) michael@0: { michael@0: if (!mCacheService) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: nsRefPtr device; michael@0: nsresult rv = mCacheService->GetCustomOfflineDevice(profileDir, michael@0: quota, michael@0: getter_AddRefs(device)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: return device->CreateApplicationCache(group, out); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsApplicationCacheService::GetApplicationCache(const nsACString &clientID, michael@0: nsIApplicationCache **out) michael@0: { michael@0: if (!mCacheService) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: nsRefPtr device; michael@0: nsresult rv = mCacheService->GetOfflineDevice(getter_AddRefs(device)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: return device->GetApplicationCache(clientID, out); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsApplicationCacheService::GetActiveCache(const nsACString &group, michael@0: nsIApplicationCache **out) michael@0: { michael@0: if (!mCacheService) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: nsRefPtr device; michael@0: nsresult rv = mCacheService->GetOfflineDevice(getter_AddRefs(device)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: return device->GetActiveCache(group, out); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsApplicationCacheService::DeactivateGroup(const nsACString &group) michael@0: { michael@0: if (!mCacheService) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: nsRefPtr device; michael@0: nsresult rv = mCacheService->GetOfflineDevice(getter_AddRefs(device)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: return device->DeactivateGroup(group); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsApplicationCacheService::ChooseApplicationCache(const nsACString &key, michael@0: nsILoadContextInfo *aLoadContextInfo, michael@0: nsIApplicationCache **out) michael@0: { michael@0: if (!mCacheService) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: nsRefPtr device; michael@0: nsresult rv = mCacheService->GetOfflineDevice(getter_AddRefs(device)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: return device->ChooseApplicationCache(key, aLoadContextInfo, out); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsApplicationCacheService::CacheOpportunistically(nsIApplicationCache* cache, michael@0: const nsACString &key) michael@0: { michael@0: if (!mCacheService) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: nsRefPtr device; michael@0: nsresult rv = mCacheService->GetOfflineDevice(getter_AddRefs(device)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: return device->CacheOpportunistically(cache, key); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsApplicationCacheService::DiscardByAppId(int32_t appID, bool isInBrowser) michael@0: { michael@0: if (!mCacheService) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: nsRefPtr device; michael@0: nsresult rv = mCacheService->GetOfflineDevice(getter_AddRefs(device)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: return device->DiscardByAppId(appID, isInBrowser); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsApplicationCacheService::GetGroups(uint32_t *count, michael@0: char ***keys) michael@0: { michael@0: if (!mCacheService) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: nsRefPtr device; michael@0: nsresult rv = mCacheService->GetOfflineDevice(getter_AddRefs(device)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: return device->GetGroups(count, keys); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsApplicationCacheService::GetGroupsTimeOrdered(uint32_t *count, michael@0: char ***keys) michael@0: { michael@0: if (!mCacheService) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: nsRefPtr device; michael@0: nsresult rv = mCacheService->GetOfflineDevice(getter_AddRefs(device)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: return device->GetGroupsTimeOrdered(count, keys); michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // AppCacheClearDataObserver: handles clearing appcache data for app uninstall michael@0: // and clearing user data events. michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: namespace { michael@0: michael@0: class AppCacheClearDataObserver MOZ_FINAL : public nsIObserver { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: michael@0: // nsIObserver implementation. michael@0: NS_IMETHODIMP michael@0: Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData) michael@0: { michael@0: MOZ_ASSERT(!nsCRT::strcmp(aTopic, TOPIC_WEB_APP_CLEAR_DATA)); michael@0: michael@0: uint32_t appId = NECKO_UNKNOWN_APP_ID; michael@0: bool browserOnly = false; michael@0: nsresult rv = NS_GetAppInfoFromClearDataNotification(aSubject, &appId, michael@0: &browserOnly); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr cacheService = michael@0: do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: return cacheService->DiscardByAppId(appId, browserOnly); michael@0: } michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(AppCacheClearDataObserver, nsIObserver) michael@0: michael@0: } // anonymous namespace michael@0: michael@0: // Instantiates and registers AppCacheClearDataObserver for notifications michael@0: void michael@0: nsApplicationCacheService::AppClearDataObserverInit() michael@0: { michael@0: nsCOMPtr observerService = michael@0: do_GetService("@mozilla.org/observer-service;1"); michael@0: if (observerService) { michael@0: nsRefPtr obs michael@0: = new AppCacheClearDataObserver(); michael@0: observerService->AddObserver(obs, TOPIC_WEB_APP_CLEAR_DATA, michael@0: /*holdsWeak=*/ false); michael@0: } michael@0: } michael@0: