2015-10-13 06:45:30 +03:00
/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2004-10-20 09:00:23 +04:00
/* vim:set ts=2 sw=2 sts=2 et cin: */
2012-05-21 15:12:37 +04:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2.0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/. */
2004-10-20 09:00:23 +04:00
2016-08-15 11:09:06 +03:00
# include <inttypes.h>
2013-12-09 06:52:54 +04:00
# include "mozilla/ArrayUtils.h"
2012-06-06 07:18:25 +04:00
# include "mozilla/Attributes.h"
2016-08-15 09:43:21 +03:00
# include "mozilla/Sprintf.h"
2017-02-18 19:35:50 +03:00
# include "mozilla/ThreadLocal.h"
2015-10-29 23:07:44 +03:00
2004-10-20 09:00:23 +04:00
# include "nsCache.h"
# include "nsDiskCache.h"
# include "nsDiskCacheDeviceSQL.h"
2007-05-15 00:09:20 +04:00
# include "nsCacheService.h"
2010-10-20 21:12:32 +04:00
# include "nsApplicationCache.h"
2019-02-07 06:49:00 +03:00
# include "../cache2/CacheHashUtils.h"
2004-10-20 09:00:23 +04:00
2008-09-30 22:34:23 +04:00
# include "nsNetCID.h"
2004-10-20 09:00:23 +04:00
# include "nsNetUtil.h"
2015-07-07 05:17:00 +03:00
# include "nsIURI.h"
2004-10-20 09:00:23 +04:00
# include "nsAutoPtr.h"
2008-08-27 03:09:02 +04:00
# include "nsEscape.h"
2008-08-28 05:15:32 +04:00
# include "nsIPrefBranch.h"
# include "nsIPrefService.h"
2004-10-20 09:00:23 +04:00
# include "nsString.h"
# include "nsPrintfCString.h"
# include "nsCRT.h"
2008-09-30 22:34:23 +04:00
# include "nsArrayUtils.h"
# include "nsIArray.h"
2007-07-08 01:14:56 +04:00
# include "nsIVariant.h"
2013-09-20 13:11:25 +04:00
# include "nsILoadContextInfo.h"
2010-08-24 05:06:23 +04:00
# include "nsThreadUtils.h"
2013-01-30 01:05:43 +04:00
# include "nsISerializable.h"
2016-01-09 04:20:50 +03:00
# include "nsIInputStream.h"
# include "nsIOutputStream.h"
2013-01-30 01:05:43 +04:00
# include "nsSerializationHelper.h"
2017-12-07 06:36:57 +03:00
# include "nsMemory.h"
2004-10-20 09:00:23 +04:00
# include "mozIStorageService.h"
# include "mozIStorageStatement.h"
2007-05-15 00:09:20 +04:00
# include "mozIStorageFunction.h"
# include "mozStorageHelper.h"
2004-10-20 09:00:23 +04:00
# include "nsICacheVisitor.h"
# include "nsISeekableStream.h"
2011-10-30 18:39:53 +04:00
# include "mozilla/Telemetry.h"
2010-05-20 03:22:19 +04:00
2012-06-29 02:27:03 +04:00
# include "mozilla/storage.h"
2016-01-18 22:20:08 +03:00
# include "nsVariant.h"
# include "mozilla/BasePrincipal.h"
2012-06-29 02:27:03 +04:00
2011-10-11 09:50:08 +04:00
using namespace mozilla ;
2012-06-29 02:27:03 +04:00
using namespace mozilla : : storage ;
2017-01-12 19:38:48 +03:00
using mozilla : : OriginAttributes ;
2011-10-11 09:50:08 +04:00
2007-05-15 00:09:20 +04:00
static const char OFFLINE_CACHE_DEVICE_ID [ ] = { " offline " } ;
2004-10-20 09:00:23 +04:00
# define LOG(args) CACHE_LOG_DEBUG(args)
2012-08-22 19:56:38 +04:00
static uint32_t gNextTemporaryClientID = 0 ;
2004-10-20 09:00:23 +04:00
/*****************************************************************************
* helpers
*/
static nsresult EnsureDir ( nsIFile * dir ) {
2011-09-29 10:19:26 +04:00
bool exists ;
2004-10-20 09:00:23 +04:00
nsresult rv = dir - > Exists ( & exists ) ;
if ( NS_SUCCEEDED ( rv ) & & ! exists )
rv = dir - > Create ( nsIFile : : DIRECTORY_TYPE , 0700 ) ;
return rv ;
}
static bool DecomposeCacheEntryKey ( const nsCString * fullKey , const char * * cid ,
const char * * key , nsCString & buf ) {
buf = * fullKey ;
2012-08-22 19:56:38 +04:00
int32_t colon = buf . FindChar ( ' : ' ) ;
2004-10-20 09:00:23 +04:00
if ( colon = = kNotFound ) {
NS_ERROR ( " Invalid key " ) ;
2011-10-17 18:59:28 +04:00
return false ;
2004-10-20 09:00:23 +04:00
}
buf . SetCharAt ( ' \0 ' , colon ) ;
* cid = buf . get ( ) ;
* key = buf . get ( ) + colon + 1 ;
2011-10-17 18:59:28 +04:00
return true ;
2004-10-20 09:00:23 +04:00
}
2004-10-28 02:19:32 +04:00
class AutoResetStatement {
public :
2014-08-05 17:20:24 +04:00
explicit AutoResetStatement ( mozIStorageStatement * s ) : mStatement ( s ) { }
2004-10-28 02:19:32 +04:00
~ AutoResetStatement ( ) { mStatement - > Reset ( ) ; }
2014-12-25 23:18:38 +03:00
mozIStorageStatement * operator - > ( ) MOZ_NO_ADDREF_RELEASE_ON_RETURN {
return mStatement ;
}
2018-11-30 13:46:48 +03:00
2004-10-28 02:19:32 +04:00
private :
mozIStorageStatement * mStatement ;
} ;
2007-05-15 00:09:20 +04:00
class EvictionObserver {
public :
2007-07-26 04:47:33 +04:00
EvictionObserver ( mozIStorageConnection * db ,
nsOfflineCacheEvictionFunction * evictionFunction )
: mDB ( db ) , mEvictionFunction ( evictionFunction ) {
2017-02-18 19:35:50 +03:00
mEvictionFunction - > Init ( ) ;
2007-05-15 00:09:20 +04:00
mDB - > ExecuteSimpleSQL (
2012-06-29 02:27:03 +04:00
NS_LITERAL_CSTRING ( " CREATE TEMP TRIGGER cache_on_delete BEFORE DELETE "
2007-05-15 00:09:20 +04:00
" ON moz_cache FOR EACH ROW BEGIN SELECT "
" cache_eviction_observer( "
2012-06-29 02:27:03 +04:00
" OLD.ClientID, OLD.key, OLD.generation); "
2007-05-15 00:09:20 +04:00
" END; " ) ) ;
}
~ EvictionObserver ( ) {
mDB - > ExecuteSimpleSQL ( NS_LITERAL_CSTRING ( " DROP TRIGGER cache_on_delete; " ) ) ;
2007-07-26 04:47:33 +04:00
mEvictionFunction - > Reset ( ) ;
2007-05-15 00:09:20 +04:00
}
2007-07-26 04:47:33 +04:00
void Apply ( ) { return mEvictionFunction - > Apply ( ) ; }
2007-05-15 00:09:20 +04:00
private :
mozIStorageConnection * mDB ;
2015-10-18 08:24:48 +03:00
RefPtr < nsOfflineCacheEvictionFunction > mEvictionFunction ;
2007-05-15 00:09:20 +04:00
} ;
2004-10-20 09:00:23 +04:00
2012-09-28 23:55:23 +04:00
# define DCACHE_HASH_MAX INT64_MAX
2004-10-20 09:00:23 +04:00
# define DCACHE_HASH_BITS 64
/**
2007-05-15 00:09:20 +04:00
* nsOfflineCache : : Hash ( const char * key )
2004-10-20 09:00:23 +04:00
*
2007-05-15 00:09:20 +04:00
* This algorithm of this method implies nsOfflineCacheRecords will be stored
2004-10-20 09:00:23 +04:00
* in a certain order on disk . If the algorithm changes , existing cache
* map files may become invalid , and therefore the kCurrentVersion needs
* to be revised .
*/
static uint64_t DCacheHash ( const char * key ) {
2009-03-27 20:58:06 +03:00
// initval 0x7416f295 was chosen randomly
2019-02-07 06:49:00 +03:00
return ( uint64_t ( CacheHash : : Hash ( key , strlen ( key ) , 0 ) ) < < 32 ) |
CacheHash : : Hash ( key , strlen ( key ) , 0x7416f295 ) ;
2004-10-20 09:00:23 +04:00
}
2007-05-15 00:09:20 +04:00
/******************************************************************************
* nsOfflineCacheEvictionFunction
*/
2004-10-20 09:00:23 +04:00
2014-04-27 11:06:00 +04:00
NS_IMPL_ISUPPORTS ( nsOfflineCacheEvictionFunction , mozIStorageFunction )
2007-05-15 00:09:20 +04:00
// helper function for directly exposing the same data file binding
// path algorithm used in nsOfflineCacheBinding::Create
2007-07-25 10:31:27 +04:00
static nsresult GetCacheDataFile ( nsIFile * cacheDir , const char * key ,
2007-05-15 00:09:20 +04:00
int generation , nsCOMPtr < nsIFile > & file ) {
cacheDir - > Clone ( getter_AddRefs ( file ) ) ;
if ( ! file ) return NS_ERROR_OUT_OF_MEMORY ;
2004-10-20 09:00:23 +04:00
2012-08-22 19:56:38 +04:00
uint64_t hash = DCacheHash ( key ) ;
2007-05-15 00:09:20 +04:00
2012-08-22 19:56:38 +04:00
uint32_t dir1 = ( uint32_t ) ( hash & 0x0F ) ;
uint32_t dir2 = ( uint32_t ) ( ( hash & 0xF0 ) > > 4 ) ;
2007-05-15 00:09:20 +04:00
hash > > = 8 ;
file - > AppendNative ( nsPrintfCString ( " %X " , dir1 ) ) ;
file - > AppendNative ( nsPrintfCString ( " %X " , dir2 ) ) ;
char leaf [ 64 ] ;
2016-08-15 11:09:06 +03:00
SprintfLiteral ( leaf , " %014 " PRIX64 " -%X " , hash , generation ) ;
2007-05-15 00:09:20 +04:00
return file - > AppendNative ( nsDependentCString ( leaf ) ) ;
}
2017-02-18 19:35:50 +03:00
namespace appcachedetail {
typedef nsCOMArray < nsIFile > FileArray ;
static MOZ_THREAD_LOCAL ( FileArray * ) tlsEvictionItems ;
} // namespace appcachedetail
2007-05-15 00:09:20 +04:00
NS_IMETHODIMP
2007-07-08 01:14:56 +04:00
nsOfflineCacheEvictionFunction : : OnFunctionCall ( mozIStorageValueArray * values ,
nsIVariant * * _retval ) {
2007-07-26 04:47:33 +04:00
LOG ( ( " nsOfflineCacheEvictionFunction::OnFunctionCall \n " ) ) ;
2012-07-30 18:20:58 +04:00
* _retval = nullptr ;
2007-05-15 00:09:20 +04:00
2012-08-22 19:56:38 +04:00
uint32_t numEntries ;
2007-05-15 00:09:20 +04:00
nsresult rv = values - > GetNumEntries ( & numEntries ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-06-29 02:27:03 +04:00
NS_ASSERTION ( numEntries = = 3 , " unexpected number of arguments " ) ;
2004-10-20 09:00:23 +04:00
2012-08-22 19:56:38 +04:00
uint32_t valueLen ;
2012-06-29 02:27:03 +04:00
const char * clientID = values - > AsSharedUTF8String ( 0 , & valueLen ) ;
const char * key = values - > AsSharedUTF8String ( 1 , & valueLen ) ;
2012-09-02 06:35:17 +04:00
nsAutoCString fullKey ( clientID ) ;
2014-05-22 07:48:51 +04:00
fullKey . Append ( ' : ' ) ;
2012-06-29 02:27:03 +04:00
fullKey . Append ( key ) ;
int generation = values - > AsInt32 ( 2 ) ;
// If the key is currently locked, refuse to delete this row.
if ( mDevice - > IsLocked ( fullKey ) ) {
2018-06-26 14:50:57 +03:00
// This code thought it was performing the equivalent of invoking the SQL
// "RAISE(IGNORE)" function. It was not. Please see bug 1470961 and any
// follow-ups to understand the plan for correcting this bug.
2012-06-29 02:27:03 +04:00
return NS_OK ;
}
2007-05-15 00:09:20 +04:00
nsCOMPtr < nsIFile > file ;
2007-07-25 10:31:27 +04:00
rv = GetCacheDataFile ( mDevice - > CacheDirectory ( ) , key , generation , file ) ;
2007-05-15 00:09:20 +04:00
if ( NS_FAILED ( rv ) ) {
2016-12-16 06:16:31 +03:00
LOG ( ( " GetCacheDataFile [key=%s generation=%d] failed [rv=% " PRIx32 " ]! \n " ,
key , generation , static_cast < uint32_t > ( rv ) ) ) ;
2007-05-15 00:09:20 +04:00
return rv ;
2004-10-20 09:00:23 +04:00
}
2007-05-15 00:09:20 +04:00
2017-02-18 19:35:50 +03:00
appcachedetail : : FileArray * items = appcachedetail : : tlsEvictionItems . get ( ) ;
MOZ_ASSERT ( items ) ;
if ( items ) {
items - > AppendObject ( file ) ;
}
2007-07-26 04:47:33 +04:00
return NS_OK ;
}
2017-02-18 19:35:50 +03:00
nsOfflineCacheEvictionFunction : : nsOfflineCacheEvictionFunction (
nsOfflineCacheDevice * device )
: mDevice ( device ) {
mTLSInited = appcachedetail : : tlsEvictionItems . init ( ) ;
}
void nsOfflineCacheEvictionFunction : : Init ( ) {
if ( mTLSInited ) {
appcachedetail : : tlsEvictionItems . set ( new appcachedetail : : FileArray ( ) ) ;
}
}
void nsOfflineCacheEvictionFunction : : Reset ( ) {
if ( ! mTLSInited ) {
return ;
}
appcachedetail : : FileArray * items = appcachedetail : : tlsEvictionItems . get ( ) ;
if ( ! items ) {
return ;
}
appcachedetail : : tlsEvictionItems . set ( nullptr ) ;
delete items ;
}
2007-07-26 04:47:33 +04:00
void nsOfflineCacheEvictionFunction : : Apply ( ) {
LOG ( ( " nsOfflineCacheEvictionFunction::Apply \n " ) ) ;
2017-02-18 19:35:50 +03:00
if ( ! mTLSInited ) {
return ;
}
appcachedetail : : FileArray * pitems = appcachedetail : : tlsEvictionItems . get ( ) ;
if ( ! pitems ) {
return ;
}
appcachedetail : : FileArray items ;
items . SwapElements ( * pitems ) ;
for ( int32_t i = 0 ; i < items . Count ( ) ; i + + ) {
2015-06-04 01:25:57 +03:00
if ( MOZ_LOG_TEST ( gCacheLog , LogLevel : : Debug ) ) {
2017-12-15 14:21:19 +03:00
LOG ( ( " removing %s \n " , items [ i ] - > HumanReadablePath ( ) . get ( ) ) ) ;
2015-05-07 22:52:45 +03:00
}
2007-05-15 00:09:20 +04:00
2017-02-18 19:35:50 +03:00
items [ i ] - > Remove ( false ) ;
2007-07-26 04:47:33 +04:00
}
2004-10-20 09:00:23 +04:00
}
2016-04-26 03:23:21 +03:00
class nsOfflineCacheDiscardCache : public Runnable {
2012-07-11 10:16:00 +04:00
public :
2017-06-12 22:34:10 +03:00
nsOfflineCacheDiscardCache ( nsOfflineCacheDevice * device , nsCString & group ,
nsCString & clientID )
: mozilla : : Runnable ( " nsOfflineCacheDiscardCache " ) ,
mDevice ( device ) ,
2012-07-11 10:16:00 +04:00
mGroup ( group ) ,
mClientID ( clientID ) { }
2016-08-08 05:18:10 +03:00
NS_IMETHOD Run ( ) override {
2012-07-11 10:16:00 +04:00
if ( mDevice - > IsActiveCache ( mGroup , mClientID ) ) {
mDevice - > DeactivateGroup ( mGroup ) ;
}
return mDevice - > EvictEntries ( mClientID . get ( ) ) ;
}
private :
2015-10-18 08:24:48 +03:00
RefPtr < nsOfflineCacheDevice > mDevice ;
2012-07-11 10:16:00 +04:00
nsCString mGroup ;
nsCString mClientID ;
} ;
2004-10-20 09:00:23 +04:00
/******************************************************************************
2007-05-15 00:09:20 +04:00
* nsOfflineCacheDeviceInfo
2004-10-20 09:00:23 +04:00
*/
2015-03-21 19:28:04 +03:00
class nsOfflineCacheDeviceInfo final : public nsICacheDeviceInfo {
2004-10-20 09:00:23 +04:00
public :
NS_DECL_ISUPPORTS
NS_DECL_NSICACHEDEVICEINFO
2014-08-05 17:20:24 +04:00
explicit nsOfflineCacheDeviceInfo ( nsOfflineCacheDevice * device )
2004-10-20 09:00:23 +04:00
: mDevice ( device ) { }
2007-05-15 00:09:20 +04:00
2004-10-20 09:00:23 +04:00
private :
2018-04-30 19:46:04 +03:00
~ nsOfflineCacheDeviceInfo ( ) = default ;
2014-06-24 20:36:44 +04:00
2007-05-15 00:09:20 +04:00
nsOfflineCacheDevice * mDevice ;
2004-10-20 09:00:23 +04:00
} ;
2014-04-27 11:06:00 +04:00
NS_IMPL_ISUPPORTS ( nsOfflineCacheDeviceInfo , nsICacheDeviceInfo )
2004-10-20 09:00:23 +04:00
NS_IMETHODIMP
2017-10-29 14:19:48 +03:00
nsOfflineCacheDeviceInfo : : GetDescription ( nsACString & aDescription ) {
aDescription . AssignLiteral ( " Offline cache device " ) ;
return NS_OK ;
2004-10-20 09:00:23 +04:00
}
NS_IMETHODIMP
2017-10-29 14:19:48 +03:00
nsOfflineCacheDeviceInfo : : GetUsageReport ( nsACString & aUsageReport ) {
2012-09-02 06:35:17 +04:00
nsAutoCString buffer ;
2010-07-03 00:56:09 +04:00
buffer . AssignLiteral (
" <tr> \n "
" <th>Cache Directory:</th> \n "
" <td> " ) ;
2012-06-06 06:08:30 +04:00
nsIFile * cacheDir = mDevice - > CacheDirectory ( ) ;
2004-10-20 09:00:23 +04:00
if ( ! cacheDir ) return NS_OK ;
nsAutoString path ;
nsresult rv = cacheDir - > GetPath ( path ) ;
if ( NS_SUCCEEDED ( rv ) )
AppendUTF16toUTF8 ( path , buffer ) ;
else
buffer . AppendLiteral ( " directory unavailable " ) ;
2017-07-06 15:00:35 +03:00
2010-07-03 00:56:09 +04:00
buffer . AppendLiteral (
" </td> \n "
" </tr> \n " ) ;
2004-10-20 09:00:23 +04:00
2017-10-29 14:19:48 +03:00
aUsageReport . Assign ( buffer ) ;
2004-10-20 09:00:23 +04:00
return NS_OK ;
}
NS_IMETHODIMP
2012-08-22 19:56:38 +04:00
nsOfflineCacheDeviceInfo : : GetEntryCount ( uint32_t * aEntryCount ) {
2004-10-20 09:00:23 +04:00
* aEntryCount = mDevice - > EntryCount ( ) ;
return NS_OK ;
}
NS_IMETHODIMP
2012-08-22 19:56:38 +04:00
nsOfflineCacheDeviceInfo : : GetTotalSize ( uint32_t * aTotalSize ) {
2004-10-20 09:00:23 +04:00
* aTotalSize = mDevice - > CacheSize ( ) ;
return NS_OK ;
}
NS_IMETHODIMP
2012-08-22 19:56:38 +04:00
nsOfflineCacheDeviceInfo : : GetMaximumSize ( uint32_t * aMaximumSize ) {
2004-10-20 09:00:23 +04:00
* aMaximumSize = mDevice - > CacheCapacity ( ) ;
return NS_OK ;
}
/******************************************************************************
2007-05-15 00:09:20 +04:00
* nsOfflineCacheBinding
2004-10-20 09:00:23 +04:00
*/
2015-03-21 19:28:04 +03:00
class nsOfflineCacheBinding final : public nsISupports {
2018-04-30 19:46:04 +03:00
~ nsOfflineCacheBinding ( ) = default ;
2014-06-24 20:36:44 +04:00
2004-10-20 09:00:23 +04:00
public :
2013-07-19 06:24:13 +04:00
NS_DECL_THREADSAFE_ISUPPORTS
2004-10-20 09:00:23 +04:00
2007-07-25 10:31:27 +04:00
static nsOfflineCacheBinding * Create ( nsIFile * cacheDir , const nsCString * key ,
int generation ) ;
2004-10-20 09:00:23 +04:00
2012-07-17 04:38:47 +04:00
enum { FLAG_NEW_ENTRY = 1 } ;
2004-10-20 09:00:23 +04:00
nsCOMPtr < nsIFile > mDataFile ;
int mGeneration ;
2012-07-17 04:38:47 +04:00
int mFlags ;
bool IsNewEntry ( ) { return mFlags & FLAG_NEW_ENTRY ; }
void MarkNewEntry ( ) { mFlags | = FLAG_NEW_ENTRY ; }
void ClearNewEntry ( ) { mFlags & = ~ FLAG_NEW_ENTRY ; }
2004-10-20 09:00:23 +04:00
} ;
2013-07-19 06:24:13 +04:00
NS_IMPL_ISUPPORTS0 ( nsOfflineCacheBinding )
2004-10-20 09:00:23 +04:00
2007-05-15 00:09:20 +04:00
nsOfflineCacheBinding * nsOfflineCacheBinding : : Create ( nsIFile * cacheDir ,
2007-07-25 10:31:27 +04:00
const nsCString * fullKey ,
2007-05-15 00:09:20 +04:00
int generation ) {
2004-10-20 09:00:23 +04:00
nsCOMPtr < nsIFile > file ;
cacheDir - > Clone ( getter_AddRefs ( file ) ) ;
2012-07-30 18:20:58 +04:00
if ( ! file ) return nullptr ;
2004-10-20 09:00:23 +04:00
2012-09-02 06:35:17 +04:00
nsAutoCString keyBuf ;
2007-07-25 10:31:27 +04:00
const char * cid , * key ;
if ( ! DecomposeCacheEntryKey ( fullKey , & cid , & key , keyBuf ) ) return nullptr ;
2012-08-22 19:56:38 +04:00
uint64_t hash = DCacheHash ( key ) ;
2004-10-20 09:00:23 +04:00
2012-08-22 19:56:38 +04:00
uint32_t dir1 = ( uint32_t ) ( hash & 0x0F ) ;
uint32_t dir2 = ( uint32_t ) ( ( hash & 0xF0 ) > > 4 ) ;
2004-10-20 09:00:23 +04:00
hash > > = 8 ;
// XXX we might want to create these directories up-front
file - > AppendNative ( nsPrintfCString ( " %X " , dir1 ) ) ;
2016-08-18 06:30:12 +03:00
Unused < < file - > Create ( nsIFile : : DIRECTORY_TYPE , 00700 ) ;
2004-10-20 09:00:23 +04:00
file - > AppendNative ( nsPrintfCString ( " %X " , dir2 ) ) ;
2016-08-18 06:30:12 +03:00
Unused < < file - > Create ( nsIFile : : DIRECTORY_TYPE , 00700 ) ;
2004-10-20 09:00:23 +04:00
nsresult rv ;
char leaf [ 64 ] ;
if ( generation = = - 1 ) {
file - > AppendNative ( NS_LITERAL_CSTRING ( " placeholder " ) ) ;
for ( generation = 0 ; ; + + generation ) {
2016-08-15 09:44:00 +03:00
SprintfLiteral ( leaf , " %014 " PRIX64 " -%X " , hash , generation ) ;
2004-10-20 09:00:23 +04:00
rv = file - > SetNativeLeafName ( nsDependentCString ( leaf ) ) ;
if ( NS_FAILED ( rv ) ) return nullptr ;
rv = file - > Create ( nsIFile : : NORMAL_FILE_TYPE , 00600 ) ;
if ( NS_FAILED ( rv ) & & rv ! = NS_ERROR_FILE_ALREADY_EXISTS ) return nullptr ;
if ( NS_SUCCEEDED ( rv ) ) break ;
}
} else {
2016-08-15 09:44:00 +03:00
SprintfLiteral ( leaf , " %014 " PRIX64 " -%X " , hash , generation ) ;
2004-10-20 09:00:23 +04:00
rv = file - > AppendNative ( nsDependentCString ( leaf ) ) ;
if ( NS_FAILED ( rv ) ) return nullptr ;
}
2007-05-15 00:09:20 +04:00
nsOfflineCacheBinding * binding = new nsOfflineCacheBinding ;
2012-07-30 18:20:58 +04:00
if ( ! binding ) return nullptr ;
2004-10-20 09:00:23 +04:00
binding - > mDataFile . swap ( file ) ;
binding - > mGeneration = generation ;
2012-07-17 04:38:47 +04:00
binding - > mFlags = 0 ;
2004-10-20 09:00:23 +04:00
return binding ;
}
/******************************************************************************
2007-05-15 00:09:20 +04:00
* nsOfflineCacheRecord
2004-10-20 09:00:23 +04:00
*/
2007-05-15 00:09:20 +04:00
struct nsOfflineCacheRecord {
2004-10-20 09:00:23 +04:00
const char * clientID ;
const char * key ;
2012-08-22 19:56:38 +04:00
const uint8_t * metaData ;
uint32_t metaDataLen ;
int32_t generation ;
int32_t dataSize ;
int32_t fetchCount ;
int64_t lastFetched ;
int64_t lastModified ;
int64_t expirationTime ;
2004-10-20 09:00:23 +04:00
} ;
2007-05-15 00:09:20 +04:00
static nsCacheEntry * CreateCacheEntry ( nsOfflineCacheDevice * device ,
2004-10-20 09:00:23 +04:00
const nsCString * fullKey ,
2007-05-15 00:09:20 +04:00
const nsOfflineCacheRecord & rec ) {
2004-10-20 09:00:23 +04:00
nsCacheEntry * entry ;
2012-06-29 02:27:03 +04:00
if ( device - > IsLocked ( * fullKey ) ) {
2012-07-30 18:20:58 +04:00
return nullptr ;
2012-06-29 02:27:03 +04:00
}
2017-07-06 15:00:35 +03:00
2004-10-20 09:00:23 +04:00
nsresult rv = nsCacheEntry : : Create ( fullKey - > get ( ) , // XXX enable sharing
nsICache : : STREAM_BASED ,
2007-05-15 00:09:20 +04:00
nsICache : : STORE_OFFLINE , device , & entry ) ;
2004-10-20 09:00:23 +04:00
if ( NS_FAILED ( rv ) ) return nullptr ;
2012-08-22 19:56:38 +04:00
entry - > SetFetchCount ( ( uint32_t ) rec . fetchCount ) ;
2004-10-20 09:00:23 +04:00
entry - > SetLastFetched ( SecondsFromPRTime ( rec . lastFetched ) ) ;
entry - > SetLastModified ( SecondsFromPRTime ( rec . lastModified ) ) ;
entry - > SetExpirationTime ( SecondsFromPRTime ( rec . expirationTime ) ) ;
2012-08-22 19:56:38 +04:00
entry - > SetDataSize ( ( uint32_t ) rec . dataSize ) ;
2004-10-20 09:00:23 +04:00
entry - > UnflattenMetaData ( ( const char * ) rec . metaData , rec . metaDataLen ) ;
2013-01-30 01:05:43 +04:00
// Restore security info, if present
const char * info = entry - > GetMetaDataElement ( " security-info " ) ;
if ( info ) {
nsCOMPtr < nsISupports > infoObj ;
rv =
NS_DeserializeObject ( nsDependentCString ( info ) , getter_AddRefs ( infoObj ) ) ;
if ( NS_FAILED ( rv ) ) {
delete entry ;
return nullptr ;
}
entry - > SetSecurityInfo ( infoObj ) ;
}
2004-10-20 09:00:23 +04:00
// create a binding object for this entry
2007-05-15 00:09:20 +04:00
nsOfflineCacheBinding * binding = nsOfflineCacheBinding : : Create (
device - > CacheDirectory ( ) , fullKey , rec . generation ) ;
2004-10-20 09:00:23 +04:00
if ( ! binding ) {
delete entry ;
2012-07-30 18:20:58 +04:00
return nullptr ;
2004-10-20 09:00:23 +04:00
}
entry - > SetData ( binding ) ;
return entry ;
}
/******************************************************************************
2007-05-15 00:09:20 +04:00
* nsOfflineCacheEntryInfo
2004-10-20 09:00:23 +04:00
*/
2015-03-21 19:28:04 +03:00
class nsOfflineCacheEntryInfo final : public nsICacheEntryInfo {
2018-04-30 19:46:04 +03:00
~ nsOfflineCacheEntryInfo ( ) = default ;
2014-06-24 20:36:44 +04:00
2004-10-20 09:00:23 +04:00
public :
NS_DECL_ISUPPORTS
NS_DECL_NSICACHEENTRYINFO
2007-05-15 00:09:20 +04:00
nsOfflineCacheRecord * mRec ;
2004-10-20 09:00:23 +04:00
} ;
2014-04-27 11:06:00 +04:00
NS_IMPL_ISUPPORTS ( nsOfflineCacheEntryInfo , nsICacheEntryInfo )
2004-10-20 09:00:23 +04:00
NS_IMETHODIMP
2017-10-29 14:19:48 +03:00
nsOfflineCacheEntryInfo : : GetClientID ( nsACString & aClientID ) {
aClientID . Assign ( mRec - > clientID ) ;
return NS_OK ;
2004-10-20 09:00:23 +04:00
}
NS_IMETHODIMP
2017-10-29 14:19:48 +03:00
nsOfflineCacheEntryInfo : : GetDeviceID ( nsACString & aDeviceID ) {
aDeviceID . Assign ( OFFLINE_CACHE_DEVICE_ID ) ;
return NS_OK ;
2004-10-20 09:00:23 +04:00
}
NS_IMETHODIMP
2007-05-15 00:09:20 +04:00
nsOfflineCacheEntryInfo : : GetKey ( nsACString & clientKey ) {
2005-01-13 06:25:28 +03:00
clientKey . Assign ( mRec - > key ) ;
return NS_OK ;
2004-10-20 09:00:23 +04:00
}
NS_IMETHODIMP
2012-08-22 19:56:38 +04:00
nsOfflineCacheEntryInfo : : GetFetchCount ( int32_t * aFetchCount ) {
2004-10-20 09:00:23 +04:00
* aFetchCount = mRec - > fetchCount ;
return NS_OK ;
}
NS_IMETHODIMP
2012-08-22 19:56:38 +04:00
nsOfflineCacheEntryInfo : : GetLastFetched ( uint32_t * aLastFetched ) {
2004-10-20 09:00:23 +04:00
* aLastFetched = SecondsFromPRTime ( mRec - > lastFetched ) ;
return NS_OK ;
}
NS_IMETHODIMP
2012-08-22 19:56:38 +04:00
nsOfflineCacheEntryInfo : : GetLastModified ( uint32_t * aLastModified ) {
2004-10-20 09:00:23 +04:00
* aLastModified = SecondsFromPRTime ( mRec - > lastModified ) ;
return NS_OK ;
}
NS_IMETHODIMP
2012-08-22 19:56:38 +04:00
nsOfflineCacheEntryInfo : : GetExpirationTime ( uint32_t * aExpirationTime ) {
2004-10-20 09:00:23 +04:00
* aExpirationTime = SecondsFromPRTime ( mRec - > expirationTime ) ;
return NS_OK ;
}
NS_IMETHODIMP
2011-09-29 10:19:26 +04:00
nsOfflineCacheEntryInfo : : IsStreamBased ( bool * aStreamBased ) {
2011-10-17 18:59:28 +04:00
* aStreamBased = true ;
2004-10-20 09:00:23 +04:00
return NS_OK ;
}
2007-05-15 00:09:20 +04:00
NS_IMETHODIMP
2012-08-22 19:56:38 +04:00
nsOfflineCacheEntryInfo : : GetDataSize ( uint32_t * aDataSize ) {
2004-10-20 09:00:23 +04:00
* aDataSize = mRec - > dataSize ;
return NS_OK ;
}
2008-09-30 22:34:23 +04:00
/******************************************************************************
* nsApplicationCacheNamespace
*/
2014-04-27 11:06:00 +04:00
NS_IMPL_ISUPPORTS ( nsApplicationCacheNamespace , nsIApplicationCacheNamespace )
2008-09-30 22:34:23 +04:00
NS_IMETHODIMP
2012-08-22 19:56:38 +04:00
nsApplicationCacheNamespace : : Init ( uint32_t itemType ,
2008-09-30 22:34:23 +04:00
const nsACString & namespaceSpec ,
const nsACString & data ) {
mItemType = itemType ;
mNamespaceSpec = namespaceSpec ;
mData = data ;
return NS_OK ;
}
NS_IMETHODIMP
2012-08-22 19:56:38 +04:00
nsApplicationCacheNamespace : : GetItemType ( uint32_t * out ) {
2008-09-30 22:34:23 +04:00
* out = mItemType ;
return NS_OK ;
}
NS_IMETHODIMP
nsApplicationCacheNamespace : : GetNamespaceSpec ( nsACString & out ) {
out = mNamespaceSpec ;
return NS_OK ;
}
NS_IMETHODIMP
nsApplicationCacheNamespace : : GetData ( nsACString & out ) {
out = mData ;
return NS_OK ;
}
2008-08-27 03:09:02 +04:00
/******************************************************************************
* nsApplicationCache
*/
2014-04-27 11:06:00 +04:00
NS_IMPL_ISUPPORTS ( nsApplicationCache , nsIApplicationCache ,
nsISupportsWeakReference )
2008-08-27 03:09:02 +04:00
2010-10-20 21:12:32 +04:00
nsApplicationCache : : nsApplicationCache ( ) : mDevice ( nullptr ) , mValid ( true ) { }
2008-08-27 03:09:02 +04:00
nsApplicationCache : : nsApplicationCache ( nsOfflineCacheDevice * device ,
const nsACString & group ,
const nsACString & clientID )
: mDevice ( device ) , mGroup ( group ) , mClientID ( clientID ) , mValid ( true ) { }
nsApplicationCache : : ~ nsApplicationCache ( ) {
2010-10-20 21:12:32 +04:00
if ( ! mDevice ) return ;
2013-08-15 14:42:02 +04:00
{
MutexAutoLock lock ( mDevice - > mLock ) ;
mDevice - > mCaches . Remove ( mClientID ) ;
}
2008-08-27 03:09:02 +04:00
// If this isn't an active cache anymore, it can be destroyed.
if ( mValid & & ! mDevice - > IsActiveCache ( mGroup , mClientID ) ) Discard ( ) ;
}
2010-10-20 21:12:32 +04:00
void nsApplicationCache : : MarkInvalid ( ) { mValid = false ; }
NS_IMETHODIMP
nsApplicationCache : : InitAsHandle ( const nsACString & groupId ,
const nsACString & clientId ) {
NS_ENSURE_FALSE ( mDevice , NS_ERROR_ALREADY_INITIALIZED ) ;
NS_ENSURE_TRUE ( mGroup . IsEmpty ( ) , NS_ERROR_ALREADY_INITIALIZED ) ;
mGroup = groupId ;
mClientID = clientId ;
return NS_OK ;
}
2012-07-31 10:36:00 +04:00
NS_IMETHODIMP
nsApplicationCache : : GetManifestURI ( nsIURI * * out ) {
nsCOMPtr < nsIURI > uri ;
nsresult rv = NS_NewURI ( getter_AddRefs ( uri ) , mGroup ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2018-07-23 14:28:47 +03:00
rv = NS_GetURIWithNewRef ( uri , EmptyCString ( ) , out ) ;
2012-07-31 10:36:00 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
return NS_OK ;
}
2008-08-27 03:09:02 +04:00
NS_IMETHODIMP
nsApplicationCache : : GetGroupID ( nsACString & out ) {
out = mGroup ;
return NS_OK ;
}
NS_IMETHODIMP
nsApplicationCache : : GetClientID ( nsACString & out ) {
out = mClientID ;
return NS_OK ;
}
2012-06-04 18:12:24 +04:00
NS_IMETHODIMP
2012-07-11 22:20:17 +04:00
nsApplicationCache : : GetProfileDirectory ( nsIFile * * out ) {
2012-06-04 18:12:24 +04:00
if ( mDevice - > BaseDirectory ( ) )
NS_ADDREF ( * out = mDevice - > BaseDirectory ( ) ) ;
else
2012-07-30 18:20:58 +04:00
* out = nullptr ;
2012-06-04 18:12:24 +04:00
return NS_OK ;
}
2008-08-27 03:09:02 +04:00
NS_IMETHODIMP
2011-09-29 10:19:26 +04:00
nsApplicationCache : : GetActive ( bool * out ) {
2010-10-20 21:12:32 +04:00
NS_ENSURE_TRUE ( mDevice , NS_ERROR_NOT_AVAILABLE ) ;
2008-08-27 03:09:02 +04:00
* out = mDevice - > IsActiveCache ( mGroup , mClientID ) ;
return NS_OK ;
}
NS_IMETHODIMP
nsApplicationCache : : Activate ( ) {
NS_ENSURE_TRUE ( mValid , NS_ERROR_NOT_AVAILABLE ) ;
2010-10-20 21:12:32 +04:00
NS_ENSURE_TRUE ( mDevice , NS_ERROR_NOT_AVAILABLE ) ;
2008-08-27 03:09:02 +04:00
mDevice - > ActivateCache ( mGroup , mClientID ) ;
2012-07-11 22:20:17 +04:00
if ( mDevice - > AutoShutdown ( this ) ) mDevice = nullptr ;
2008-08-27 03:09:02 +04:00
return NS_OK ;
}
NS_IMETHODIMP
nsApplicationCache : : Discard ( ) {
NS_ENSURE_TRUE ( mValid , NS_ERROR_NOT_AVAILABLE ) ;
2010-10-20 21:12:32 +04:00
NS_ENSURE_TRUE ( mDevice , NS_ERROR_NOT_AVAILABLE ) ;
2008-08-27 03:09:02 +04:00
2011-10-17 18:59:28 +04:00
mValid = false ;
2008-08-27 03:09:02 +04:00
2015-03-17 19:29:17 +03:00
nsCOMPtr < nsIRunnable > ev =
2012-07-11 10:16:00 +04:00
new nsOfflineCacheDiscardCache ( mDevice , mGroup , mClientID ) ;
nsresult rv = nsCacheService : : DispatchToCacheIOThread ( ev ) ;
return rv ;
2008-08-27 03:09:02 +04:00
}
NS_IMETHODIMP
nsApplicationCache : : MarkEntry ( const nsACString & key , uint32_t typeBits ) {
NS_ENSURE_TRUE ( mValid , NS_ERROR_NOT_AVAILABLE ) ;
2010-10-20 21:12:32 +04:00
NS_ENSURE_TRUE ( mDevice , NS_ERROR_NOT_AVAILABLE ) ;
2008-08-27 03:09:02 +04:00
return mDevice - > MarkEntry ( mClientID , key , typeBits ) ;
}
NS_IMETHODIMP
nsApplicationCache : : UnmarkEntry ( const nsACString & key , uint32_t typeBits ) {
NS_ENSURE_TRUE ( mValid , NS_ERROR_NOT_AVAILABLE ) ;
2010-10-20 21:12:32 +04:00
NS_ENSURE_TRUE ( mDevice , NS_ERROR_NOT_AVAILABLE ) ;
2008-08-27 03:09:02 +04:00
return mDevice - > UnmarkEntry ( mClientID , key , typeBits ) ;
}
NS_IMETHODIMP
nsApplicationCache : : GetTypes ( const nsACString & key , uint32_t * typeBits ) {
NS_ENSURE_TRUE ( mValid , NS_ERROR_NOT_AVAILABLE ) ;
2010-10-20 21:12:32 +04:00
NS_ENSURE_TRUE ( mDevice , NS_ERROR_NOT_AVAILABLE ) ;
2008-08-27 03:09:02 +04:00
return mDevice - > GetTypes ( mClientID , key , typeBits ) ;
}
NS_IMETHODIMP
2012-08-22 19:56:38 +04:00
nsApplicationCache : : GatherEntries ( uint32_t typeBits , uint32_t * count ,
2008-08-27 03:09:02 +04:00
char * * * keys ) {
NS_ENSURE_TRUE ( mValid , NS_ERROR_NOT_AVAILABLE ) ;
2010-10-20 21:12:32 +04:00
NS_ENSURE_TRUE ( mDevice , NS_ERROR_NOT_AVAILABLE ) ;
2008-08-27 03:09:02 +04:00
return mDevice - > GatherEntries ( mClientID , typeBits , count , keys ) ;
}
2008-09-30 22:34:23 +04:00
NS_IMETHODIMP
nsApplicationCache : : AddNamespaces ( nsIArray * namespaces ) {
NS_ENSURE_TRUE ( mValid , NS_ERROR_NOT_AVAILABLE ) ;
2010-10-20 21:12:32 +04:00
NS_ENSURE_TRUE ( mDevice , NS_ERROR_NOT_AVAILABLE ) ;
2008-09-30 22:34:23 +04:00
if ( ! namespaces ) return NS_OK ;
2011-10-17 18:59:28 +04:00
mozStorageTransaction transaction ( mDevice - > mDB , false ) ;
2008-09-30 22:34:23 +04:00
2012-08-22 19:56:38 +04:00
uint32_t length ;
2008-09-30 22:34:23 +04:00
nsresult rv = namespaces - > GetLength ( & length ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-08-22 19:56:38 +04:00
for ( uint32_t i = 0 ; i < length ; i + + ) {
2008-09-30 22:34:23 +04:00
nsCOMPtr < nsIApplicationCacheNamespace > ns =
do_QueryElementAt ( namespaces , i ) ;
if ( ns ) {
rv = mDevice - > AddNamespace ( mClientID , ns ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
}
rv = transaction . Commit ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
return NS_OK ;
}
NS_IMETHODIMP
nsApplicationCache : : GetMatchingNamespace ( const nsACString & key ,
nsIApplicationCacheNamespace * * out )
{
NS_ENSURE_TRUE ( mValid , NS_ERROR_NOT_AVAILABLE ) ;
2010-10-20 21:12:32 +04:00
NS_ENSURE_TRUE ( mDevice , NS_ERROR_NOT_AVAILABLE ) ;
2008-09-30 22:34:23 +04:00
return mDevice - > GetMatchingNamespace ( mClientID , key , out ) ;
}
2009-02-22 22:09:10 +03:00
NS_IMETHODIMP
2012-08-22 19:56:38 +04:00
nsApplicationCache : : GetUsage ( uint32_t * usage ) {
2009-02-22 22:09:10 +03:00
NS_ENSURE_TRUE ( mValid , NS_ERROR_NOT_AVAILABLE ) ;
2010-10-20 21:12:32 +04:00
NS_ENSURE_TRUE ( mDevice , NS_ERROR_NOT_AVAILABLE ) ;
2009-02-22 22:09:10 +03:00
return mDevice - > GetUsage ( mClientID , usage ) ;
}
2010-08-24 05:06:23 +04:00
/******************************************************************************
* nsCloseDBEvent
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-04-26 03:23:21 +03:00
class nsCloseDBEvent : public Runnable {
2010-08-24 05:06:23 +04:00
public :
2017-06-12 22:34:10 +03:00
explicit nsCloseDBEvent ( mozIStorageConnection * aDB )
: mozilla : : Runnable ( " nsCloseDBEvent " ) {
2010-08-24 05:06:23 +04:00
mDB = aDB ;
}
2016-08-08 05:18:10 +03:00
NS_IMETHOD Run ( ) override {
2010-08-24 05:06:23 +04:00
mDB - > Close ( ) ;
return NS_OK ;
}
protected :
2018-04-30 19:46:04 +03:00
virtual ~ nsCloseDBEvent ( ) = default ;
2010-08-24 05:06:23 +04:00
private :
nsCOMPtr < mozIStorageConnection > mDB ;
} ;
2004-10-20 09:00:23 +04:00
/******************************************************************************
2007-05-15 00:09:20 +04:00
* nsOfflineCacheDevice
2004-10-20 09:00:23 +04:00
*/
2013-07-19 06:24:13 +04:00
NS_IMPL_ISUPPORTS0 ( nsOfflineCacheDevice )
2008-08-27 03:09:02 +04:00
2007-05-15 00:09:20 +04:00
nsOfflineCacheDevice : : nsOfflineCacheDevice ( )
2012-07-30 18:20:58 +04:00
: mDB ( nullptr ) ,
2004-10-20 09:00:23 +04:00
mCacheCapacity ( 0 ) ,
mDeltaCounter ( 0 ) ,
2012-07-11 22:20:17 +04:00
mAutoShutdown ( false ) ,
2013-08-15 14:42:02 +04:00
mLock ( " nsOfflineCacheDevice.lock " ) ,
2014-08-06 17:31:21 +04:00
mActiveCaches ( 4 ) ,
mLockedEntries ( 32 ) { }
2004-10-20 09:00:23 +04:00
2008-08-28 05:15:32 +04:00
/* static */
bool nsOfflineCacheDevice : : GetStrictFileOriginPolicy ( ) {
nsCOMPtr < nsIPrefBranch > prefs = do_GetService ( NS_PREFSERVICE_CONTRACTID ) ;
2011-09-29 10:19:26 +04:00
bool retval ;
2008-08-28 05:15:32 +04:00
if ( prefs & & NS_SUCCEEDED ( prefs - > GetBoolPref (
" security.fileuri.strict_origin_policy " , & retval ) ) )
return retval ;
// As default value use true (be more strict)
2011-10-17 18:59:28 +04:00
return true ;
2008-08-28 05:15:32 +04:00
}
2007-05-15 00:09:20 +04:00
uint32_t nsOfflineCacheDevice : : CacheSize ( ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , 0 ) ;
2004-10-28 02:19:32 +04:00
AutoResetStatement statement ( mStatement_CacheSize ) ;
2011-09-29 10:19:26 +04:00
bool hasRows ;
2004-10-28 02:19:32 +04:00
nsresult rv = statement - > ExecuteStep ( & hasRows ) ;
2004-10-20 09:00:23 +04:00
NS_ENSURE_TRUE ( NS_SUCCEEDED ( rv ) & & hasRows , 0 ) ;
2017-07-06 15:00:35 +03:00
2012-08-22 19:56:38 +04:00
return ( uint32_t ) statement - > AsInt32 ( 0 ) ;
2004-10-20 09:00:23 +04:00
}
2007-05-15 00:09:20 +04:00
uint32_t nsOfflineCacheDevice : : EntryCount ( ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , 0 ) ;
2004-10-28 02:19:32 +04:00
AutoResetStatement statement ( mStatement_EntryCount ) ;
2004-10-20 09:00:23 +04:00
2011-09-29 10:19:26 +04:00
bool hasRows ;
2004-10-28 02:19:32 +04:00
nsresult rv = statement - > ExecuteStep ( & hasRows ) ;
2004-10-20 09:00:23 +04:00
NS_ENSURE_TRUE ( NS_SUCCEEDED ( rv ) & & hasRows , 0 ) ;
2012-08-22 19:56:38 +04:00
return ( uint32_t ) statement - > AsInt32 ( 0 ) ;
2004-10-20 09:00:23 +04:00
}
2007-05-15 00:09:20 +04:00
nsresult nsOfflineCacheDevice : : UpdateEntry ( nsCacheEntry * entry ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2004-10-20 09:00:23 +04:00
// Decompose the key into "ClientID" and "Key"
2012-09-02 06:35:17 +04:00
nsAutoCString keyBuf ;
2004-10-20 09:00:23 +04:00
const char * cid , * key ;
2012-07-17 04:38:47 +04:00
2004-10-20 09:00:23 +04:00
if ( ! DecomposeCacheEntryKey ( entry - > Key ( ) , & cid , & key , keyBuf ) )
return NS_ERROR_UNEXPECTED ;
2013-01-30 01:05:43 +04:00
// Store security info, if it is serializable
nsCOMPtr < nsISupports > infoObj = entry - > SecurityInfo ( ) ;
nsCOMPtr < nsISerializable > serializable = do_QueryInterface ( infoObj ) ;
if ( infoObj & & ! serializable ) return NS_ERROR_UNEXPECTED ;
if ( serializable ) {
nsCString info ;
nsresult rv = NS_SerializeToString ( serializable , info ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = entry - > SetMetaDataElement ( " security-info " , info . get ( ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
2004-10-20 09:00:23 +04:00
nsCString metaDataBuf ;
2012-08-22 19:56:38 +04:00
uint32_t mdSize = entry - > MetaDataSize ( ) ;
2015-01-28 12:00:40 +03:00
if ( ! metaDataBuf . SetLength ( mdSize , fallible ) ) return NS_ERROR_OUT_OF_MEMORY ;
2004-10-20 09:00:23 +04:00
char * md = metaDataBuf . BeginWriting ( ) ;
entry - > FlattenMetaData ( md , mdSize ) ;
2007-05-15 00:09:20 +04:00
nsOfflineCacheRecord rec ;
2012-08-22 19:56:38 +04:00
rec . metaData = ( const uint8_t * ) md ;
2004-10-20 09:00:23 +04:00
rec . metaDataLen = mdSize ;
rec . dataSize = entry - > DataSize ( ) ;
rec . fetchCount = entry - > FetchCount ( ) ;
rec . lastFetched = PRTimeFromSeconds ( entry - > LastFetched ( ) ) ;
rec . lastModified = PRTimeFromSeconds ( entry - > LastModified ( ) ) ;
rec . expirationTime = PRTimeFromSeconds ( entry - > ExpirationTime ( ) ) ;
2004-10-28 02:19:32 +04:00
AutoResetStatement statement ( mStatement_UpdateEntry ) ;
2004-10-20 09:00:23 +04:00
2004-10-28 02:19:32 +04:00
nsresult rv ;
2012-07-27 18:03:08 +04:00
rv = statement - > BindBlobByIndex ( 0 , rec . metaData , rec . metaDataLen ) ;
nsresult tmp = statement - > BindInt32ByIndex ( 1 , rec . dataSize ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindInt32ByIndex ( 2 , rec . fetchCount ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindInt64ByIndex ( 3 , rec . lastFetched ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindInt64ByIndex ( 4 , rec . lastModified ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindInt64ByIndex ( 5 , rec . expirationTime ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindUTF8StringByIndex ( 6 , nsDependentCString ( cid ) ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindUTF8StringByIndex ( 7 , nsDependentCString ( key ) ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
2004-10-20 09:00:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-09-29 10:19:26 +04:00
bool hasRows ;
2004-10-20 09:00:23 +04:00
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
NS_ASSERTION ( ! hasRows , " UPDATE should not result in output " ) ;
return rv ;
}
2012-08-22 19:56:38 +04:00
nsresult nsOfflineCacheDevice : : UpdateEntrySize ( nsCacheEntry * entry ,
uint32_t newSize ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2004-10-20 09:00:23 +04:00
// Decompose the key into "ClientID" and "Key"
2012-09-02 06:35:17 +04:00
nsAutoCString keyBuf ;
2004-10-20 09:00:23 +04:00
const char * cid , * key ;
if ( ! DecomposeCacheEntryKey ( entry - > Key ( ) , & cid , & key , keyBuf ) )
return NS_ERROR_UNEXPECTED ;
2004-10-28 02:19:32 +04:00
AutoResetStatement statement ( mStatement_UpdateEntrySize ) ;
2004-10-20 09:00:23 +04:00
2012-07-27 18:03:08 +04:00
nsresult rv = statement - > BindInt32ByIndex ( 0 , newSize ) ;
nsresult tmp = statement - > BindUTF8StringByIndex ( 1 , nsDependentCString ( cid ) ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindUTF8StringByIndex ( 2 , nsDependentCString ( key ) ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
2004-10-20 09:00:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-09-29 10:19:26 +04:00
bool hasRows ;
2004-10-20 09:00:23 +04:00
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
NS_ASSERTION ( ! hasRows , " UPDATE should not result in output " ) ;
return rv ;
}
2011-09-29 10:19:26 +04:00
nsresult nsOfflineCacheDevice : : DeleteEntry ( nsCacheEntry * entry ,
bool deleteData ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2004-10-20 09:00:23 +04:00
if ( deleteData ) {
nsresult rv = DeleteData ( entry ) ;
if ( NS_FAILED ( rv ) ) return rv ;
}
// Decompose the key into "ClientID" and "Key"
2012-09-02 06:35:17 +04:00
nsAutoCString keyBuf ;
2004-10-20 09:00:23 +04:00
const char * cid , * key ;
if ( ! DecomposeCacheEntryKey ( entry - > Key ( ) , & cid , & key , keyBuf ) )
return NS_ERROR_UNEXPECTED ;
2004-10-28 02:19:32 +04:00
AutoResetStatement statement ( mStatement_DeleteEntry ) ;
2004-10-20 09:00:23 +04:00
2012-07-27 18:03:08 +04:00
nsresult rv = statement - > BindUTF8StringByIndex ( 0 , nsDependentCString ( cid ) ) ;
nsresult rv2 = statement - > BindUTF8StringByIndex ( 1 , nsDependentCString ( key ) ) ;
2004-10-20 09:00:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-07-27 18:03:08 +04:00
NS_ENSURE_SUCCESS ( rv2 , rv2 ) ;
2004-10-20 09:00:23 +04:00
2011-09-29 10:19:26 +04:00
bool hasRows ;
2004-10-20 09:00:23 +04:00
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
NS_ASSERTION ( ! hasRows , " DELETE should not result in output " ) ;
return rv ;
}
2007-05-15 00:09:20 +04:00
nsresult nsOfflineCacheDevice : : DeleteData ( nsCacheEntry * entry ) {
nsOfflineCacheBinding * binding = ( nsOfflineCacheBinding * ) entry - > Data ( ) ;
2004-10-20 09:00:23 +04:00
NS_ENSURE_STATE ( binding ) ;
2011-10-17 18:59:28 +04:00
return binding - > mDataFile - > Remove ( false ) ;
2004-10-20 09:00:23 +04:00
}
/**
* nsCacheDevice implementation
*/
2011-10-11 09:50:08 +04:00
// This struct is local to nsOfflineCacheDevice::Init, but ISO C++98 doesn't
// allow a template (mozilla::ArrayLength) to be instantiated based on a local
// type. Boo-urns!
struct StatementSql {
nsCOMPtr < mozIStorageStatement > & statement ;
const char * sql ;
StatementSql ( nsCOMPtr < mozIStorageStatement > & aStatement , const char * aSql )
: statement ( aStatement ) , sql ( aSql ) { }
} ;
2007-05-15 00:09:20 +04:00
nsresult nsOfflineCacheDevice : : Init ( ) {
2013-04-10 04:21:07 +04:00
MOZ_ASSERT ( false , " Need to be initialized with sqlite " ) ;
return NS_ERROR_NOT_IMPLEMENTED ;
}
nsresult nsOfflineCacheDevice : : InitWithSqlite ( mozIStorageService * ss ) {
2004-10-20 09:00:23 +04:00
NS_ENSURE_TRUE ( ! mDB , NS_ERROR_ALREADY_INITIALIZED ) ;
// SetCacheParentDirectory must have been called
NS_ENSURE_TRUE ( mCacheDirectory , NS_ERROR_UNEXPECTED ) ;
// make sure the cache directory exists
nsresult rv = EnsureDir ( mCacheDirectory ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
// build path to index file
2017-07-06 15:00:35 +03:00
nsCOMPtr < nsIFile > indexFile ;
2004-10-20 09:00:23 +04:00
rv = mCacheDirectory - > Clone ( getter_AddRefs ( indexFile ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2007-05-15 00:09:20 +04:00
rv = indexFile - > AppendNative ( NS_LITERAL_CSTRING ( " index.sqlite " ) ) ;
2004-10-20 09:00:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2013-04-10 04:21:07 +04:00
MOZ_ASSERT ( ss ,
" nsOfflineCacheDevice::InitWithSqlite called before "
" nsCacheService::Init() ? " ) ;
NS_ENSURE_TRUE ( ss , NS_ERROR_UNEXPECTED ) ;
2004-10-20 09:00:23 +04:00
rv = ss - > OpenDatabase ( indexFile , getter_AddRefs ( mDB ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2017-06-01 23:43:44 +03:00
mInitEventTarget = GetCurrentThreadEventTarget ( ) ;
2010-08-24 05:06:23 +04:00
2004-10-20 09:00:23 +04:00
mDB - > ExecuteSimpleSQL ( NS_LITERAL_CSTRING ( " PRAGMA synchronous = OFF; " ) ) ;
// XXX ... other initialization steps
// XXX in the future we may wish to verify the schema for moz_cache
// perhaps using "PRAGMA table_info" ?
// build the table
//
// "Generation" is the data file generation number.
//
2008-08-27 03:09:02 +04:00
rv = mDB - > ExecuteSimpleSQL (
NS_LITERAL_CSTRING ( " CREATE TABLE IF NOT EXISTS moz_cache ( \n "
2004-10-20 09:00:23 +04:00
" ClientID TEXT, \n "
" Key TEXT, \n "
" MetaData BLOB, \n "
" Generation INTEGER, \n "
" DataSize INTEGER, \n "
" FetchCount INTEGER, \n "
" LastFetched INTEGER, \n "
" LastModified INTEGER, \n "
2008-08-27 03:09:02 +04:00
" ExpirationTime INTEGER, \n "
" ItemType INTEGER DEFAULT 0 \n "
2004-10-20 09:00:23 +04:00
" ); \n " ) ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2004-10-20 09:00:23 +04:00
2008-08-27 03:09:02 +04:00
// Databases from 1.9.0 don't have the ItemType column. Add the column
// here, but don't worry about failures (the column probably already exists)
2007-05-15 00:09:20 +04:00
mDB - > ExecuteSimpleSQL ( NS_LITERAL_CSTRING (
2008-08-27 03:09:02 +04:00
" ALTER TABLE moz_cache ADD ItemType INTEGER DEFAULT 0 " ) ) ;
// Create the table for storing cache groups. All actions on
// moz_cache_groups use the GroupID, so use it as the primary key.
rv = mDB - > ExecuteSimpleSQL (
NS_LITERAL_CSTRING ( " CREATE TABLE IF NOT EXISTS moz_cache_groups ( \n "
" GroupID TEXT PRIMARY KEY, \n "
" ActiveClientID TEXT \n "
2007-05-15 00:09:20 +04:00
" ); \n " ) ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2007-05-15 00:09:20 +04:00
2008-09-30 22:34:23 +04:00
mDB - > ExecuteSimpleSQL (
NS_LITERAL_CSTRING ( " ALTER TABLE moz_cache_groups "
" ADD ActivateTimeStamp INTEGER DEFAULT 0 " ) ) ;
// ClientID: clientID joining moz_cache and moz_cache_namespaces
// tables.
// Data: Data associated with this namespace (e.g. a fallback URI
// for fallback entries).
// ItemType: the type of namespace.
rv =
mDB - > ExecuteSimpleSQL ( NS_LITERAL_CSTRING ( " CREATE TABLE IF NOT EXISTS "
" moz_cache_namespaces ( \n "
" ClientID TEXT, \n "
" NameSpace TEXT, \n "
" Data TEXT, \n "
" ItemType INTEGER \n "
" ); \n " ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2008-08-27 03:09:02 +04:00
// Databases from 1.9.0 have a moz_cache_index that should be dropped
rv = mDB - > ExecuteSimpleSQL (
NS_LITERAL_CSTRING ( " DROP INDEX IF EXISTS moz_cache_index " ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
// Key/ClientID pairs should be unique in the database. All queries
// against moz_cache use the Key (which is also the most unique), so
// use it as the primary key for this index.
rv = mDB - > ExecuteSimpleSQL (
NS_LITERAL_CSTRING ( " CREATE UNIQUE INDEX IF NOT EXISTS "
" moz_cache_key_clientid_index "
" ON moz_cache (Key, ClientID); " ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2004-10-20 09:00:23 +04:00
2008-09-30 22:34:23 +04:00
// Used for ClientID lookups and to keep ClientID/NameSpace pairs unique.
rv = mDB - > ExecuteSimpleSQL (
NS_LITERAL_CSTRING ( " CREATE UNIQUE INDEX IF NOT EXISTS "
" moz_cache_namespaces_clientid_index "
" ON moz_cache_namespaces (ClientID, NameSpace); " ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
// Used for namespace lookups.
rv = mDB - > ExecuteSimpleSQL (
NS_LITERAL_CSTRING ( " CREATE INDEX IF NOT EXISTS "
" moz_cache_namespaces_namespace_index "
" ON moz_cache_namespaces (NameSpace); " ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2007-07-26 04:47:33 +04:00
mEvictionFunction = new nsOfflineCacheEvictionFunction ( this ) ;
if ( ! mEvictionFunction ) return NS_ERROR_OUT_OF_MEMORY ;
2007-05-15 00:09:20 +04:00
2012-06-29 02:27:03 +04:00
rv = mDB - > CreateFunction ( NS_LITERAL_CSTRING ( " cache_eviction_observer " ) , 3 ,
mEvictionFunction ) ;
2007-05-15 00:09:20 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2004-10-20 09:00:23 +04:00
2004-10-28 02:19:32 +04:00
// create all (most) of our statements up front
2011-10-11 09:50:08 +04:00
StatementSql prepared [ ] = {
2018-10-12 23:48:24 +03:00
// clang-format off
2007-05-15 11:53:42 +04:00
StatementSql ( mStatement_CacheSize , " SELECT Sum(DataSize) from moz_cache; " ) ,
2009-02-22 22:09:10 +03:00
StatementSql ( mStatement_ApplicationCacheSize , " SELECT Sum(DataSize) from moz_cache WHERE ClientID = ?; " ) ,
2007-05-15 11:53:42 +04:00
StatementSql ( mStatement_EntryCount , " SELECT count(*) from moz_cache; " ) ,
2012-06-29 02:26:55 +04:00
StatementSql ( mStatement_UpdateEntry , " UPDATE moz_cache SET MetaData = ?, DataSize = ?, FetchCount = ?, LastFetched = ?, LastModified = ?, ExpirationTime = ? WHERE ClientID = ? AND Key = ?; " ) ,
2007-05-15 11:53:42 +04:00
StatementSql ( mStatement_UpdateEntrySize , " UPDATE moz_cache SET DataSize = ? WHERE ClientID = ? AND Key = ?; " ) ,
StatementSql ( mStatement_DeleteEntry , " DELETE FROM moz_cache WHERE ClientID = ? AND Key = ?; " ) ,
2012-06-29 02:26:55 +04:00
StatementSql ( mStatement_FindEntry , " SELECT MetaData, Generation, DataSize, FetchCount, LastFetched, LastModified, ExpirationTime, ItemType FROM moz_cache WHERE ClientID = ? AND Key = ?; " ) ,
StatementSql ( mStatement_BindEntry , " INSERT INTO moz_cache (ClientID, Key, MetaData, Generation, DataSize, FetchCount, LastFetched, LastModified, ExpirationTime) VALUES(?,?,?,?,?,?,?,?,?); " ) ,
2008-08-27 03:09:02 +04:00
StatementSql ( mStatement_MarkEntry , " UPDATE moz_cache SET ItemType = (ItemType | ?) WHERE ClientID = ? AND Key = ?; " ) ,
StatementSql ( mStatement_UnmarkEntry , " UPDATE moz_cache SET ItemType = (ItemType & ~?) WHERE ClientID = ? AND Key = ?; " ) ,
StatementSql ( mStatement_GetTypes , " SELECT ItemType FROM moz_cache WHERE ClientID = ? AND Key = ?; " ) ,
StatementSql ( mStatement_CleanupUnmarked , " DELETE FROM moz_cache WHERE ClientID = ? AND Key = ? AND ItemType = 0; " ) ,
StatementSql ( mStatement_GatherEntries , " SELECT Key FROM moz_cache WHERE ClientID = ? AND (ItemType & ?) > 0; " ) ,
2008-09-30 22:34:23 +04:00
StatementSql ( mStatement_ActivateClient , " INSERT OR REPLACE INTO moz_cache_groups (GroupID, ActiveClientID, ActivateTimeStamp) VALUES (?, ?, ?); " ) ,
2008-08-27 03:09:02 +04:00
StatementSql ( mStatement_DeactivateGroup , " DELETE FROM moz_cache_groups WHERE GroupID = ?; " ) ,
2018-02-10 03:19:31 +03:00
StatementSql ( mStatement_FindClient , " /* do not warn (bug 1293375) */ SELECT ClientID, ItemType FROM moz_cache WHERE Key = ? ORDER BY LastFetched DESC, LastModified DESC; " ) ,
2008-09-30 22:34:23 +04:00
// Search for namespaces that match the URI. Use the <= operator
// to ensure that we use the index on moz_cache_namespaces.
2018-02-10 03:19:31 +03:00
StatementSql ( mStatement_FindClientByNamespace , " /* do not warn (bug 1293375) */ SELECT ns.ClientID, ns.ItemType FROM "
2008-09-30 22:34:23 +04:00
" moz_cache_namespaces AS ns JOIN moz_cache_groups AS groups "
" ON ns.ClientID = groups.ActiveClientID "
" WHERE ns.NameSpace <= ?1 AND ?1 GLOB ns.NameSpace || '*' "
" ORDER BY ns.NameSpace DESC, groups.ActivateTimeStamp DESC; " ) ,
2009-02-10 09:40:40 +03:00
StatementSql ( mStatement_FindNamespaceEntry , " SELECT NameSpace, Data, ItemType FROM moz_cache_namespaces "
2008-09-30 22:34:23 +04:00
" WHERE ClientID = ?1 "
" AND NameSpace <= ?2 AND ?2 GLOB NameSpace || '*' "
2009-02-10 09:40:40 +03:00
" ORDER BY NameSpace DESC; " ) ,
2008-09-30 22:34:23 +04:00
StatementSql ( mStatement_InsertNamespaceEntry , " INSERT INTO moz_cache_namespaces (ClientID, NameSpace, Data, ItemType) VALUES(?, ?, ?, ?); " ) ,
2012-10-03 04:39:09 +04:00
StatementSql ( mStatement_EnumerateApps , " SELECT GroupID, ActiveClientID FROM moz_cache_groups WHERE GroupID LIKE ?1; " ) ,
2012-03-31 04:52:06 +04:00
StatementSql ( mStatement_EnumerateGroups , " SELECT GroupID, ActiveClientID FROM moz_cache_groups; " ) ,
StatementSql ( mStatement_EnumerateGroupsTimeOrder , " SELECT GroupID, ActiveClientID FROM moz_cache_groups ORDER BY ActivateTimeStamp; " )
2018-10-12 23:48:24 +03:00
// clang-format on
2004-10-28 02:19:32 +04:00
} ;
2012-08-22 19:56:38 +04:00
for ( uint32_t i = 0 ; NS_SUCCEEDED ( rv ) & & i < ArrayLength ( prepared ) ; + + i ) {
2008-08-27 03:09:02 +04:00
LOG ( ( " Creating statement: %s \n " , prepared [ i ] . sql ) ) ;
rv = mDB - > CreateStatement ( nsDependentCString ( prepared [ i ] . sql ) ,
getter_AddRefs ( prepared [ i ] . statement ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2004-10-28 02:19:32 +04:00
}
2008-08-27 03:09:02 +04:00
rv = InitActiveCaches ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2008-08-25 08:51:19 +04:00
2008-08-27 03:09:02 +04:00
return NS_OK ;
}
2012-07-31 10:36:00 +04:00
namespace {
2017-06-20 12:19:52 +03:00
nsresult GetGroupForCache ( const nsACString & clientID , nsCString & group ) {
2012-07-31 10:36:00 +04:00
group . Assign ( clientID ) ;
group . Truncate ( group . FindChar ( ' | ' ) ) ;
NS_UnescapeURL ( group ) ;
return NS_OK ;
}
2015-07-13 18:25:42 +03:00
} // namespace
2012-07-31 10:36:00 +04:00
// static
nsresult nsOfflineCacheDevice : : BuildApplicationCacheGroupID (
2016-01-18 22:20:08 +03:00
nsIURI * aManifestURL , nsACString const & aOriginSuffix ,
2012-07-31 10:36:00 +04:00
nsACString & _result ) {
nsCOMPtr < nsIURI > newURI ;
2018-07-23 14:28:47 +03:00
nsresult rv =
NS_GetURIWithNewRef ( aManifestURL , EmptyCString ( ) , getter_AddRefs ( newURI ) ) ;
2012-07-31 10:36:00 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
nsAutoCString manifestSpec ;
rv = newURI - > GetAsciiSpec ( manifestSpec ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
_result . Assign ( manifestSpec ) ;
2016-01-18 22:20:08 +03:00
_result . Append ( ' # ' ) ;
_result . Append ( aOriginSuffix ) ;
2012-07-31 10:36:00 +04:00
return NS_OK ;
}
2008-08-27 03:09:02 +04:00
nsresult nsOfflineCacheDevice : : InitActiveCaches ( ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2013-08-15 14:42:02 +04:00
MutexAutoLock lock ( mLock ) ;
2009-02-22 22:09:10 +03:00
AutoResetStatement statement ( mStatement_EnumerateGroups ) ;
2008-08-27 03:09:02 +04:00
2011-09-29 10:19:26 +04:00
bool hasRows ;
2012-05-18 21:30:49 +04:00
nsresult rv = statement - > ExecuteStep ( & hasRows ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
while ( hasRows ) {
2012-09-02 06:35:17 +04:00
nsAutoCString group ;
2008-08-27 03:09:02 +04:00
statement - > GetUTF8String ( 0 , group ) ;
nsCString clientID ;
statement - > GetUTF8String ( 1 , clientID ) ;
2011-11-09 00:22:15 +04:00
mActiveCaches . PutEntry ( clientID ) ;
2008-08-27 03:09:02 +04:00
mActiveCachesByGroup . Put ( group , new nsCString ( clientID ) ) ;
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
2007-07-26 04:47:33 +04:00
2004-10-20 09:00:23 +04:00
return NS_OK ;
}
2007-05-15 00:09:20 +04:00
nsresult nsOfflineCacheDevice : : Shutdown ( ) {
2004-10-20 09:00:23 +04:00
NS_ENSURE_TRUE ( mDB , NS_ERROR_NOT_INITIALIZED ) ;
2013-08-15 14:42:02 +04:00
{
MutexAutoLock lock ( mLock ) ;
2015-11-20 02:31:28 +03:00
for ( auto iter = mCaches . Iter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
nsCOMPtr < nsIApplicationCache > obj = do_QueryReferent ( iter . UserData ( ) ) ;
if ( obj ) {
auto appCache = static_cast < nsApplicationCache * > ( obj . get ( ) ) ;
appCache - > MarkInvalid ( ) ;
}
}
2013-08-15 14:42:02 +04:00
}
2008-08-27 03:09:02 +04:00
2010-08-24 05:06:23 +04:00
{
2008-08-27 03:09:02 +04:00
EvictionObserver evictionObserver ( mDB , mEvictionFunction ) ;
// Delete all rows whose clientID is not an active clientID.
2008-09-30 22:34:23 +04:00
nsresult rv = mDB - > ExecuteSimpleSQL ( NS_LITERAL_CSTRING (
" DELETE FROM moz_cache WHERE rowid IN "
" (SELECT moz_cache.rowid FROM "
" moz_cache LEFT OUTER JOIN moz_cache_groups ON "
" (moz_cache.ClientID = moz_cache_groups.ActiveClientID) "
" WHERE moz_cache_groups.GroupID ISNULL) " ) ) ;
2008-08-27 03:09:02 +04:00
if ( NS_FAILED ( rv ) )
NS_WARNING ( " Failed to clean up unused application caches. " ) ;
else
evictionObserver . Apply ( ) ;
2018-11-30 13:46:48 +03:00
2008-09-30 22:34:23 +04:00
// Delete all namespaces whose clientID is not an active clientID.
rv = mDB - > ExecuteSimpleSQL ( NS_LITERAL_CSTRING (
" DELETE FROM moz_cache_namespaces WHERE rowid IN "
" (SELECT moz_cache_namespaces.rowid FROM "
" moz_cache_namespaces LEFT OUTER JOIN moz_cache_groups ON "
" (moz_cache_namespaces.ClientID = "
" moz_cache_groups.ActiveClientID) "
" WHERE moz_cache_groups.GroupID ISNULL) " ) ) ;
2018-11-30 13:46:48 +03:00
2008-09-30 22:34:23 +04:00
if ( NS_FAILED ( rv ) ) NS_WARNING ( " Failed to clean up namespaces. " ) ;
2018-11-30 13:46:48 +03:00
2016-11-08 06:34:06 +03:00
mEvictionFunction = nullptr ;
2018-11-30 13:46:48 +03:00
2012-07-30 18:20:58 +04:00
mStatement_CacheSize = nullptr ;
mStatement_ApplicationCacheSize = nullptr ;
mStatement_EntryCount = nullptr ;
mStatement_UpdateEntry = nullptr ;
mStatement_UpdateEntrySize = nullptr ;
mStatement_DeleteEntry = nullptr ;
mStatement_FindEntry = nullptr ;
mStatement_BindEntry = nullptr ;
mStatement_ClearDomain = nullptr ;
mStatement_MarkEntry = nullptr ;
mStatement_UnmarkEntry = nullptr ;
mStatement_GetTypes = nullptr ;
mStatement_FindNamespaceEntry = nullptr ;
mStatement_InsertNamespaceEntry = nullptr ;
mStatement_CleanupUnmarked = nullptr ;
mStatement_GatherEntries = nullptr ;
mStatement_ActivateClient = nullptr ;
mStatement_DeactivateGroup = nullptr ;
mStatement_FindClient = nullptr ;
mStatement_FindClientByNamespace = nullptr ;
2012-10-03 04:39:09 +04:00
mStatement_EnumerateApps = nullptr ;
2012-07-30 18:20:58 +04:00
mStatement_EnumerateGroups = nullptr ;
mStatement_EnumerateGroupsTimeOrder = nullptr ;
2010-08-24 05:06:23 +04:00
}
// Close Database on the correct thread
2011-09-29 10:19:26 +04:00
bool isOnCurrentThread = true ;
2017-06-01 23:43:44 +03:00
if ( mInitEventTarget )
isOnCurrentThread = mInitEventTarget - > IsOnCurrentThread ( ) ;
2010-08-24 05:06:23 +04:00
if ( ! isOnCurrentThread ) {
nsCOMPtr < nsIRunnable > ev = new nsCloseDBEvent ( mDB ) ;
if ( ev ) {
2017-06-01 23:43:44 +03:00
mInitEventTarget - > Dispatch ( ev , NS_DISPATCH_NORMAL ) ;
2010-08-24 05:06:23 +04:00
}
} else {
mDB - > Close ( ) ;
}
2012-07-30 18:20:58 +04:00
mDB = nullptr ;
2017-06-01 23:43:44 +03:00
mInitEventTarget = nullptr ;
2010-08-24 05:06:23 +04:00
2004-10-20 09:00:23 +04:00
return NS_OK ;
}
2007-05-15 00:09:20 +04:00
const char * nsOfflineCacheDevice : : GetDeviceID ( ) {
return OFFLINE_CACHE_DEVICE_ID ;
2004-10-20 09:00:23 +04:00
}
2011-09-29 10:19:26 +04:00
nsCacheEntry * nsOfflineCacheDevice : : FindEntry ( nsCString * fullKey ,
bool * collision ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , nullptr ) ;
2012-08-23 21:23:03 +04:00
mozilla : : Telemetry : : AutoTimer < mozilla : : Telemetry : : CACHE_OFFLINE_SEARCH_2 >
timer ;
2007-05-15 00:09:20 +04:00
LOG ( ( " nsOfflineCacheDevice::FindEntry [key=%s] \n " , fullKey - > get ( ) ) ) ;
2004-10-20 09:00:23 +04:00
// SELECT * FROM moz_cache WHERE key = ?
// Decompose the key into "ClientID" and "Key"
2012-09-02 06:35:17 +04:00
nsAutoCString keyBuf ;
2004-10-20 09:00:23 +04:00
const char * cid , * key ;
if ( ! DecomposeCacheEntryKey ( fullKey , & cid , & key , keyBuf ) ) return nullptr ;
2004-10-28 02:19:32 +04:00
AutoResetStatement statement ( mStatement_FindEntry ) ;
2004-10-20 09:00:23 +04:00
2012-07-27 18:03:08 +04:00
nsresult rv = statement - > BindUTF8StringByIndex ( 0 , nsDependentCString ( cid ) ) ;
nsresult rv2 = statement - > BindUTF8StringByIndex ( 1 , nsDependentCString ( key ) ) ;
2012-07-30 18:20:58 +04:00
NS_ENSURE_SUCCESS ( rv , nullptr ) ;
2012-07-30 18:28:15 +04:00
NS_ENSURE_SUCCESS ( rv2 , nullptr ) ;
2004-10-20 09:00:23 +04:00
2011-09-29 10:19:26 +04:00
bool hasRows ;
2004-10-20 09:00:23 +04:00
rv = statement - > ExecuteStep ( & hasRows ) ;
2012-07-30 18:20:58 +04:00
if ( NS_FAILED ( rv ) | | ! hasRows ) return nullptr ; // entry not found
2004-10-20 09:00:23 +04:00
2007-05-15 00:09:20 +04:00
nsOfflineCacheRecord rec ;
statement - > GetSharedBlob ( 0 , & rec . metaDataLen ,
2012-08-22 19:56:38 +04:00
( const uint8_t * * ) & rec . metaData ) ;
2004-10-20 09:00:23 +04:00
rec . generation = statement - > AsInt32 ( 1 ) ;
2012-06-29 02:26:55 +04:00
rec . dataSize = statement - > AsInt32 ( 2 ) ;
rec . fetchCount = statement - > AsInt32 ( 3 ) ;
rec . lastFetched = statement - > AsInt64 ( 4 ) ;
rec . lastModified = statement - > AsInt64 ( 5 ) ;
rec . expirationTime = statement - > AsInt64 ( 6 ) ;
2016-12-16 06:16:31 +03:00
LOG ( ( " entry: [%u %d %d %d % " PRId64 " % " PRId64 " % " PRId64 " ] \n " ,
2004-10-20 09:00:23 +04:00
rec . metaDataLen , rec . generation , rec . dataSize , rec . fetchCount ,
rec . lastFetched , rec . lastModified , rec . expirationTime ) ) ;
2007-05-15 00:09:20 +04:00
nsCacheEntry * entry = CreateCacheEntry ( this , fullKey , rec ) ;
2004-10-20 09:00:23 +04:00
2007-05-15 00:09:20 +04:00
if ( entry ) {
// make sure that the data file exists
nsOfflineCacheBinding * binding = ( nsOfflineCacheBinding * ) entry - > Data ( ) ;
2011-09-29 10:19:26 +04:00
bool isFile ;
2007-05-15 00:09:20 +04:00
rv = binding - > mDataFile - > IsFile ( & isFile ) ;
if ( NS_FAILED ( rv ) | | ! isFile ) {
2011-10-17 18:59:28 +04:00
DeleteEntry ( entry , false ) ;
2007-05-15 00:09:20 +04:00
delete entry ;
2012-07-30 18:20:58 +04:00
return nullptr ;
2007-05-15 00:09:20 +04:00
}
2012-06-29 02:27:03 +04:00
// lock the entry
Lock ( * fullKey ) ;
2007-05-15 00:09:20 +04:00
}
return entry ;
2004-10-20 09:00:23 +04:00
}
2007-05-15 00:09:20 +04:00
nsresult nsOfflineCacheDevice : : DeactivateEntry ( nsCacheEntry * entry ) {
LOG ( ( " nsOfflineCacheDevice::DeactivateEntry [key=%s] \n " ,
entry - > Key ( ) - > get ( ) ) ) ;
2004-10-20 09:00:23 +04:00
// This method is called to inform us that the nsCacheEntry object is going
// away. We should persist anything that needs to be persisted, or if the
// entry is doomed, we can go ahead and clear its storage.
if ( entry - > IsDoomed ( ) ) {
// remove corresponding row and file if they exist
// the row should have been removed in DoomEntry... we could assert that
// that happened. otherwise, all we have to do here is delete the file
// on disk.
DeleteData ( entry ) ;
2012-07-17 04:38:47 +04:00
} else if ( ( ( nsOfflineCacheBinding * ) entry - > Data ( ) ) - > IsNewEntry ( ) ) {
2004-10-20 09:00:23 +04:00
// UPDATE the database row
2012-07-17 04:38:47 +04:00
// Only new entries are updated, since offline cache is updated in
// transactions. New entries are those who is returned from
// BindEntry().
2004-10-20 09:00:23 +04:00
2012-07-17 04:38:47 +04:00
LOG ( ( " nsOfflineCacheDevice::DeactivateEntry updating new entry \n " ) ) ;
2004-10-20 09:00:23 +04:00
UpdateEntry ( entry ) ;
2012-07-17 04:38:47 +04:00
} else {
LOG (
( " nsOfflineCacheDevice::DeactivateEntry "
" skipping update since entry is not dirty \n " ) ) ;
2004-10-20 09:00:23 +04:00
}
2012-06-29 02:27:03 +04:00
// Unlock the entry
Unlock ( * entry - > Key ( ) ) ;
2004-10-20 09:00:23 +04:00
delete entry ;
2007-05-15 00:09:20 +04:00
2004-10-20 09:00:23 +04:00
return NS_OK ;
}
2007-05-15 00:09:20 +04:00
nsresult nsOfflineCacheDevice : : BindEntry ( nsCacheEntry * entry ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2007-05-15 00:09:20 +04:00
LOG ( ( " nsOfflineCacheDevice::BindEntry [key=%s] \n " , entry - > Key ( ) - > get ( ) ) ) ;
2004-10-20 09:00:23 +04:00
NS_ENSURE_STATE ( ! entry - > Data ( ) ) ;
// This method is called to inform us that we have a new entry. The entry
// may collide with an existing entry in our DB, but if that happens we can
// assume that the entry is not being used.
// INSERT the database row
// XXX Assumption: if the row already exists, then FindEntry would have
// returned it. if that entry was doomed, then DoomEntry would have removed
// it from the table. so, we should always have to insert at this point.
// Decompose the key into "ClientID" and "Key"
2012-09-02 06:35:17 +04:00
nsAutoCString keyBuf ;
2004-10-20 09:00:23 +04:00
const char * cid , * key ;
if ( ! DecomposeCacheEntryKey ( entry - > Key ( ) , & cid , & key , keyBuf ) )
return NS_ERROR_UNEXPECTED ;
// create binding, pick best generation number
2015-10-18 08:24:48 +03:00
RefPtr < nsOfflineCacheBinding > binding =
2007-07-25 10:31:27 +04:00
nsOfflineCacheBinding : : Create ( mCacheDirectory , entry - > Key ( ) , - 1 ) ;
2004-10-20 09:00:23 +04:00
if ( ! binding ) return NS_ERROR_OUT_OF_MEMORY ;
2012-07-17 04:38:47 +04:00
binding - > MarkNewEntry ( ) ;
2004-10-20 09:00:23 +04:00
2007-05-15 00:09:20 +04:00
nsOfflineCacheRecord rec ;
2004-10-20 09:00:23 +04:00
rec . clientID = cid ;
rec . key = key ;
2013-09-19 23:28:26 +04:00
rec . metaData = nullptr ; // don't write any metadata now.
2004-10-20 09:00:23 +04:00
rec . metaDataLen = 0 ;
rec . generation = binding - > mGeneration ;
rec . dataSize = 0 ;
rec . fetchCount = entry - > FetchCount ( ) ;
rec . lastFetched = PRTimeFromSeconds ( entry - > LastFetched ( ) ) ;
rec . lastModified = PRTimeFromSeconds ( entry - > LastModified ( ) ) ;
rec . expirationTime = PRTimeFromSeconds ( entry - > ExpirationTime ( ) ) ;
2004-10-28 02:19:32 +04:00
AutoResetStatement statement ( mStatement_BindEntry ) ;
2004-10-20 09:00:23 +04:00
2012-07-27 18:03:08 +04:00
nsresult rv =
statement - > BindUTF8StringByIndex ( 0 , nsDependentCString ( rec . clientID ) ) ;
nsresult tmp =
statement - > BindUTF8StringByIndex ( 1 , nsDependentCString ( rec . key ) ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindBlobByIndex ( 2 , rec . metaData , rec . metaDataLen ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindInt32ByIndex ( 3 , rec . generation ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindInt32ByIndex ( 4 , rec . dataSize ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindInt32ByIndex ( 5 , rec . fetchCount ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindInt64ByIndex ( 6 , rec . lastFetched ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindInt64ByIndex ( 7 , rec . lastModified ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
tmp = statement - > BindInt64ByIndex ( 8 , rec . expirationTime ) ;
if ( NS_FAILED ( tmp ) ) {
rv = tmp ;
}
2004-10-20 09:00:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2017-07-06 15:00:35 +03:00
2011-09-29 10:19:26 +04:00
bool hasRows ;
2004-10-20 09:00:23 +04:00
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
NS_ASSERTION ( ! hasRows , " INSERT should not result in output " ) ;
entry - > SetData ( binding ) ;
2012-06-29 02:27:03 +04:00
// lock the entry
Lock ( * entry - > Key ( ) ) ;
2004-10-20 09:00:23 +04:00
return NS_OK ;
}
2007-05-15 00:09:20 +04:00
void nsOfflineCacheDevice : : DoomEntry ( nsCacheEntry * entry ) {
LOG ( ( " nsOfflineCacheDevice::DoomEntry [key=%s] \n " , entry - > Key ( ) - > get ( ) ) ) ;
2004-10-20 09:00:23 +04:00
// This method is called to inform us that we should mark the entry to be
// deleted when it is no longer in use.
// We can go ahead and delete the corresponding row in our table,
// but we must not delete the file on disk until we are deactivated.
2012-06-29 02:27:03 +04:00
// In another word, the file should be deleted if the entry had been
// deactivated.
2017-07-06 15:00:35 +03:00
2012-06-29 02:27:03 +04:00
DeleteEntry ( entry , ! entry - > IsActive ( ) ) ;
2004-10-20 09:00:23 +04:00
}
2007-05-15 00:09:20 +04:00
nsresult nsOfflineCacheDevice : : OpenInputStreamForEntry (
nsCacheEntry * entry , nsCacheAccessMode mode , uint32_t offset ,
nsIInputStream * * result ) {
LOG ( ( " nsOfflineCacheDevice::OpenInputStreamForEntry [key=%s] \n " ,
entry - > Key ( ) - > get ( ) ) ) ;
2004-10-20 09:00:23 +04:00
2012-07-30 18:20:58 +04:00
* result = nullptr ;
2004-10-20 09:00:23 +04:00
2011-02-12 16:06:02 +03:00
NS_ENSURE_TRUE ( ! offset | | ( offset < entry - > DataSize ( ) ) , NS_ERROR_INVALID_ARG ) ;
2004-10-20 09:00:23 +04:00
// return an input stream to the entry's data file. the stream
// may be read on a background thread.
2007-05-15 00:09:20 +04:00
nsOfflineCacheBinding * binding = ( nsOfflineCacheBinding * ) entry - > Data ( ) ;
2004-10-20 09:00:23 +04:00
NS_ENSURE_STATE ( binding ) ;
nsCOMPtr < nsIInputStream > in ;
NS_NewLocalFileInputStream ( getter_AddRefs ( in ) , binding - > mDataFile , PR_RDONLY ) ;
if ( ! in ) return NS_ERROR_UNEXPECTED ;
// respect |offset| param
if ( offset ! = 0 ) {
nsCOMPtr < nsISeekableStream > seekable = do_QueryInterface ( in ) ;
NS_ENSURE_TRUE ( seekable , NS_ERROR_UNEXPECTED ) ;
seekable - > Seek ( nsISeekableStream : : NS_SEEK_SET , offset ) ;
}
in . swap ( * result ) ;
return NS_OK ;
}
2007-05-15 00:09:20 +04:00
nsresult nsOfflineCacheDevice : : OpenOutputStreamForEntry (
nsCacheEntry * entry , nsCacheAccessMode mode , uint32_t offset ,
nsIOutputStream * * result ) {
LOG ( ( " nsOfflineCacheDevice::OpenOutputStreamForEntry [key=%s] \n " ,
entry - > Key ( ) - > get ( ) ) ) ;
2004-10-20 09:00:23 +04:00
2012-07-30 18:20:58 +04:00
* result = nullptr ;
2004-10-20 09:00:23 +04:00
NS_ENSURE_TRUE ( offset < = entry - > DataSize ( ) , NS_ERROR_INVALID_ARG ) ;
// return an output stream to the entry's data file. we can assume
// that the output stream will only be used on the main thread.
2007-05-15 00:09:20 +04:00
nsOfflineCacheBinding * binding = ( nsOfflineCacheBinding * ) entry - > Data ( ) ;
2004-10-20 09:00:23 +04:00
NS_ENSURE_STATE ( binding ) ;
nsCOMPtr < nsIOutputStream > out ;
NS_NewLocalFileOutputStream ( getter_AddRefs ( out ) , binding - > mDataFile ,
PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE , 00600 ) ;
if ( ! out ) return NS_ERROR_UNEXPECTED ;
// respect |offset| param
nsCOMPtr < nsISeekableStream > seekable = do_QueryInterface ( out ) ;
NS_ENSURE_TRUE ( seekable , NS_ERROR_UNEXPECTED ) ;
if ( offset ! = 0 ) seekable - > Seek ( nsISeekableStream : : NS_SEEK_SET , offset ) ;
// truncate the file at the given offset
seekable - > SetEOF ( ) ;
nsCOMPtr < nsIOutputStream > bufferedOut ;
2017-10-24 15:38:23 +03:00
nsresult rv = NS_NewBufferedOutputStream ( getter_AddRefs ( bufferedOut ) ,
out . forget ( ) , 16 * 1024 ) ;
2012-10-16 12:38:20 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2004-10-20 09:00:23 +04:00
2017-10-24 15:38:23 +03:00
bufferedOut . forget ( result ) ;
2004-10-20 09:00:23 +04:00
return NS_OK ;
}
2007-05-15 00:09:20 +04:00
nsresult nsOfflineCacheDevice : : GetFileForEntry ( nsCacheEntry * entry ,
nsIFile * * result ) {
LOG ( ( " nsOfflineCacheDevice::GetFileForEntry [key=%s] \n " ,
entry - > Key ( ) - > get ( ) ) ) ;
2004-10-20 09:00:23 +04:00
2007-05-15 00:09:20 +04:00
nsOfflineCacheBinding * binding = ( nsOfflineCacheBinding * ) entry - > Data ( ) ;
2004-10-20 09:00:23 +04:00
NS_ENSURE_STATE ( binding ) ;
NS_IF_ADDREF ( * result = binding - > mDataFile ) ;
return NS_OK ;
}
2012-08-22 19:56:38 +04:00
nsresult nsOfflineCacheDevice : : OnDataSizeChange ( nsCacheEntry * entry ,
int32_t deltaSize ) {
2007-05-15 00:09:20 +04:00
LOG ( ( " nsOfflineCacheDevice::OnDataSizeChange [key=%s delta=%d] \n " ,
2004-10-20 09:00:23 +04:00
entry - > Key ( ) - > get ( ) , deltaSize ) ) ;
2012-08-22 19:56:38 +04:00
const int32_t DELTA_THRESHOLD = 1 < < 14 ; // 16k
2007-05-15 00:09:20 +04:00
2004-10-20 09:00:23 +04:00
// called to notify us of an impending change in the total size of the
2007-05-15 00:09:20 +04:00
// specified entry.
2004-10-20 09:00:23 +04:00
2012-08-22 19:56:38 +04:00
uint32_t oldSize = entry - > DataSize ( ) ;
NS_ASSERTION ( deltaSize > = 0 | | int32_t ( oldSize ) + deltaSize > = 0 , " oops " ) ;
uint32_t newSize = int32_t ( oldSize ) + deltaSize ;
2004-10-20 09:00:23 +04:00
UpdateEntrySize ( entry , newSize ) ;
mDeltaCounter + = deltaSize ; // this may go negative
if ( mDeltaCounter > = DELTA_THRESHOLD ) {
2007-05-15 00:09:20 +04:00
if ( CacheSize ( ) > mCacheCapacity ) {
// the entry will overrun the cache capacity, doom the entry
// and abort
2008-09-15 17:34:46 +04:00
# ifdef DEBUG
nsresult rv =
# endif
nsCacheService : : DoomEntry ( entry ) ;
2007-05-15 00:09:20 +04:00
NS_ASSERTION ( NS_SUCCEEDED ( rv ) , " DoomEntry() failed. " ) ;
return NS_ERROR_ABORT ;
}
2004-10-20 09:00:23 +04:00
mDeltaCounter = 0 ; // reset counter
}
return NS_OK ;
}
2007-05-15 00:09:20 +04:00
nsresult nsOfflineCacheDevice : : Visit ( nsICacheVisitor * visitor ) {
2004-10-20 09:00:23 +04:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2007-05-15 00:09:20 +04:00
// called to enumerate the offline cache.
2004-10-20 09:00:23 +04:00
nsCOMPtr < nsICacheDeviceInfo > deviceInfo = new nsOfflineCacheDeviceInfo ( this ) ;
2011-09-29 10:19:26 +04:00
bool keepGoing ;
2007-05-15 00:09:20 +04:00
nsresult rv =
visitor - > VisitDevice ( OFFLINE_CACHE_DEVICE_ID , deviceInfo , & keepGoing ) ;
2004-10-20 09:00:23 +04:00
if ( NS_FAILED ( rv ) ) return rv ;
2017-07-06 15:00:35 +03:00
2004-10-20 09:00:23 +04:00
if ( ! keepGoing ) return NS_OK ;
// SELECT * from moz_cache;
2007-05-15 00:09:20 +04:00
nsOfflineCacheRecord rec ;
2015-10-18 08:24:48 +03:00
RefPtr < nsOfflineCacheEntryInfo > info = new nsOfflineCacheEntryInfo ;
2004-10-20 09:00:23 +04:00
if ( ! info ) return NS_ERROR_OUT_OF_MEMORY ;
info - > mRec = & rec ;
2004-10-28 02:19:32 +04:00
// XXX may want to list columns explicitly
2004-10-20 09:00:23 +04:00
nsCOMPtr < mozIStorageStatement > statement ;
rv = mDB - > CreateStatement ( NS_LITERAL_CSTRING ( " SELECT * FROM moz_cache; " ) ,
getter_AddRefs ( statement ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-09-29 10:19:26 +04:00
bool hasRows ;
2004-10-20 09:00:23 +04:00
for ( ; ; ) {
rv = statement - > ExecuteStep ( & hasRows ) ;
if ( NS_FAILED ( rv ) | | ! hasRows ) break ;
2013-09-19 23:28:26 +04:00
statement - > GetSharedUTF8String ( 0 , nullptr , & rec . clientID ) ;
statement - > GetSharedUTF8String ( 1 , nullptr , & rec . key ) ;
2007-05-15 00:09:20 +04:00
statement - > GetSharedBlob ( 2 , & rec . metaDataLen ,
2012-08-22 19:56:38 +04:00
( const uint8_t * * ) & rec . metaData ) ;
2004-10-20 09:00:23 +04:00
rec . generation = statement - > AsInt32 ( 3 ) ;
2012-06-29 02:26:55 +04:00
rec . dataSize = statement - > AsInt32 ( 4 ) ;
rec . fetchCount = statement - > AsInt32 ( 5 ) ;
rec . lastFetched = statement - > AsInt64 ( 6 ) ;
rec . lastModified = statement - > AsInt64 ( 7 ) ;
rec . expirationTime = statement - > AsInt64 ( 8 ) ;
2004-10-20 09:00:23 +04:00
2011-09-29 10:19:26 +04:00
bool keepGoing ;
2007-05-15 00:09:20 +04:00
rv = visitor - > VisitEntry ( OFFLINE_CACHE_DEVICE_ID , info , & keepGoing ) ;
2004-10-20 09:00:23 +04:00
if ( NS_FAILED ( rv ) | | ! keepGoing ) break ;
}
2012-07-30 18:20:58 +04:00
info - > mRec = nullptr ;
2004-10-20 09:00:23 +04:00
return NS_OK ;
}
2012-04-01 02:18:08 +04:00
nsresult nsOfflineCacheDevice : : EvictEntries ( const char * clientID ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2012-04-01 02:18:08 +04:00
LOG ( ( " nsOfflineCacheDevice::EvictEntries [cid=%s] \n " ,
clientID ? clientID : " " ) ) ;
2004-10-20 09:00:23 +04:00
2012-03-31 04:52:07 +04:00
// called to evict all entries matching the given clientID.
2004-10-20 09:00:23 +04:00
2012-04-01 02:18:08 +04:00
// need trigger to fire user defined function after a row is deleted
// so we can delete the corresponding data file.
EvictionObserver evictionObserver ( mDB , mEvictionFunction ) ;
2012-03-31 04:52:07 +04:00
nsCOMPtr < mozIStorageStatement > statement ;
2012-04-01 02:18:08 +04:00
nsresult rv ;
if ( clientID ) {
2012-06-29 02:26:55 +04:00
rv = mDB - > CreateStatement (
NS_LITERAL_CSTRING ( " DELETE FROM moz_cache WHERE ClientID=?; " ) ,
2012-04-01 02:18:08 +04:00
getter_AddRefs ( statement ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2008-08-27 03:09:02 +04:00
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 0 , nsDependentCString ( clientID ) ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-31 04:52:06 +04:00
2012-04-01 02:18:08 +04:00
rv = statement - > Execute ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-31 04:52:06 +04:00
2012-04-01 02:18:08 +04:00
rv = mDB - > CreateStatement (
NS_LITERAL_CSTRING (
" DELETE FROM moz_cache_groups WHERE ActiveClientID=?; " ) ,
getter_AddRefs ( statement ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-31 04:52:06 +04:00
2012-04-01 02:18:08 +04:00
rv = statement - > BindUTF8StringByIndex ( 0 , nsDependentCString ( clientID ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2004-10-20 09:00:23 +04:00
2012-04-01 02:18:08 +04:00
rv = statement - > Execute ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2015-10-15 10:56:00 +03:00
// TODO - Should update internal hashtables.
// Low priority, since this API is not widely used.
2012-04-01 02:18:08 +04:00
} else {
2012-06-29 02:26:55 +04:00
rv = mDB - > CreateStatement ( NS_LITERAL_CSTRING ( " DELETE FROM moz_cache; " ) ,
2012-04-01 02:18:08 +04:00
getter_AddRefs ( statement ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-31 04:52:06 +04:00
2012-04-01 02:18:08 +04:00
rv = statement - > Execute ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-31 04:52:06 +04:00
2012-04-01 02:18:08 +04:00
rv = mDB - > CreateStatement (
NS_LITERAL_CSTRING ( " DELETE FROM moz_cache_groups; " ) ,
getter_AddRefs ( statement ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-31 04:52:07 +04:00
2012-04-01 02:18:08 +04:00
rv = statement - > Execute ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2015-10-15 10:56:00 +03:00
MutexAutoLock lock ( mLock ) ;
mCaches . Clear ( ) ;
mActiveCaches . Clear ( ) ;
mActiveCachesByGroup . Clear ( ) ;
2012-03-31 04:52:06 +04:00
}
2008-08-27 03:09:02 +04:00
evictionObserver . Apply ( ) ;
2012-07-30 18:20:58 +04:00
statement = nullptr ;
2012-04-01 02:18:08 +04:00
// Also evict any namespaces associated with this clientID.
if ( clientID ) {
rv = mDB - > CreateStatement (
NS_LITERAL_CSTRING ( " DELETE FROM moz_cache_namespaces WHERE ClientID=? " ) ,
getter_AddRefs ( statement ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2008-09-30 22:34:23 +04:00
2012-04-01 02:18:08 +04:00
rv = statement - > BindUTF8StringByIndex ( 0 , nsDependentCString ( clientID ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
} else {
rv = mDB - > CreateStatement (
NS_LITERAL_CSTRING ( " DELETE FROM moz_cache_namespaces; " ) ,
getter_AddRefs ( statement ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
2008-09-30 22:34:23 +04:00
2012-04-01 02:18:08 +04:00
rv = statement - > Execute ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2008-09-30 22:34:23 +04:00
2008-08-27 03:09:02 +04:00
return NS_OK ;
}
nsresult nsOfflineCacheDevice : : MarkEntry ( const nsCString & clientID ,
const nsACString & key ,
2012-08-22 19:56:38 +04:00
uint32_t typeBits ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2008-08-27 03:09:02 +04:00
LOG ( ( " nsOfflineCacheDevice::MarkEntry [cid=%s, key=%s, typeBits=%d] \n " ,
clientID . get ( ) , PromiseFlatCString ( key ) . get ( ) , typeBits ) ) ;
AutoResetStatement statement ( mStatement_MarkEntry ) ;
2011-03-31 21:19:31 +04:00
nsresult rv = statement - > BindInt32ByIndex ( 0 , typeBits ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 1 , clientID ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 2 , key ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = statement - > Execute ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
return NS_OK ;
}
nsresult nsOfflineCacheDevice : : UnmarkEntry ( const nsCString & clientID ,
const nsACString & key ,
2012-08-22 19:56:38 +04:00
uint32_t typeBits ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2008-08-27 03:09:02 +04:00
LOG ( ( " nsOfflineCacheDevice::UnmarkEntry [cid=%s, key=%s, typeBits=%d] \n " ,
clientID . get ( ) , PromiseFlatCString ( key ) . get ( ) , typeBits ) ) ;
AutoResetStatement statement ( mStatement_UnmarkEntry ) ;
2011-03-31 21:19:31 +04:00
nsresult rv = statement - > BindInt32ByIndex ( 0 , typeBits ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 1 , clientID ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 2 , key ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = statement - > Execute ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
// Remove the entry if it is now empty.
EvictionObserver evictionObserver ( mDB , mEvictionFunction ) ;
AutoResetStatement cleanupStatement ( mStatement_CleanupUnmarked ) ;
2011-03-31 21:19:31 +04:00
rv = cleanupStatement - > BindUTF8StringByIndex ( 0 , clientID ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = cleanupStatement - > BindUTF8StringByIndex ( 1 , key ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = cleanupStatement - > Execute ( ) ;
2004-10-20 09:00:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2007-07-26 04:47:33 +04:00
evictionObserver . Apply ( ) ;
2004-10-20 09:00:23 +04:00
return NS_OK ;
}
2008-09-30 22:34:23 +04:00
nsresult nsOfflineCacheDevice : : GetMatchingNamespace (
const nsCString & clientID , const nsACString & key ,
nsIApplicationCacheNamespace * * out ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2008-09-30 22:34:23 +04:00
LOG ( ( " nsOfflineCacheDevice::GetMatchingNamespace [cid=%s, key=%s] \n " ,
clientID . get ( ) , PromiseFlatCString ( key ) . get ( ) ) ) ;
nsresult rv ;
AutoResetStatement statement ( mStatement_FindNamespaceEntry ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 0 , clientID ) ;
2008-09-30 22:34:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 1 , key ) ;
2008-09-30 22:34:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-09-29 10:19:26 +04:00
bool hasRows ;
2008-09-30 22:34:23 +04:00
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-07-30 18:20:58 +04:00
* out = nullptr ;
2008-09-30 22:34:23 +04:00
2011-09-29 10:19:26 +04:00
bool found = false ;
2009-02-22 22:09:10 +03:00
nsCString nsSpec ;
2012-08-22 19:56:38 +04:00
int32_t nsType = 0 ;
2009-02-22 22:09:10 +03:00
nsCString nsData ;
while ( hasRows ) {
2012-08-22 19:56:38 +04:00
int32_t itemType ;
2009-02-22 22:09:10 +03:00
rv = statement - > GetInt32 ( 2 , & itemType ) ;
2008-09-30 22:34:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2009-02-22 22:09:10 +03:00
if ( ! found | | itemType > nsType ) {
nsType = itemType ;
2008-09-30 22:34:23 +04:00
2009-02-22 22:09:10 +03:00
rv = statement - > GetUTF8String ( 0 , nsSpec ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = statement - > GetUTF8String ( 1 , nsData ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-10-17 18:59:28 +04:00
found = true ;
2009-02-22 22:09:10 +03:00
}
rv = statement - > ExecuteStep ( & hasRows ) ;
2008-09-30 22:34:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2009-02-22 22:09:10 +03:00
}
2008-09-30 22:34:23 +04:00
2009-02-22 22:09:10 +03:00
if ( found ) {
2008-09-30 22:34:23 +04:00
nsCOMPtr < nsIApplicationCacheNamespace > ns =
new nsApplicationCacheNamespace ( ) ;
if ( ! ns ) return NS_ERROR_OUT_OF_MEMORY ;
2009-02-22 22:09:10 +03:00
rv = ns - > Init ( nsType , nsSpec , nsData ) ;
2008-09-30 22:34:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
ns . swap ( * out ) ;
}
return NS_OK ;
}
nsresult nsOfflineCacheDevice : : CacheOpportunistically ( const nsCString & clientID ,
const nsACString & key ) {
// XXX: We should also be propagating this cache entry to other matching
// caches. See bug 444807.
return MarkEntry ( clientID , key , nsIApplicationCache : : ITEM_OPPORTUNISTIC ) ;
}
2008-08-27 03:09:02 +04:00
nsresult nsOfflineCacheDevice : : GetTypes ( const nsCString & clientID ,
const nsACString & key ,
2012-08-22 19:56:38 +04:00
uint32_t * typeBits ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2008-08-27 03:09:02 +04:00
LOG ( ( " nsOfflineCacheDevice::GetTypes [cid=%s, key=%s] \n " , clientID . get ( ) ,
PromiseFlatCString ( key ) . get ( ) ) ) ;
AutoResetStatement statement ( mStatement_GetTypes ) ;
2011-03-31 21:19:31 +04:00
nsresult rv = statement - > BindUTF8StringByIndex ( 0 , clientID ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 1 , key ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-09-29 10:19:26 +04:00
bool hasRows ;
2008-08-27 03:09:02 +04:00
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
if ( ! hasRows ) return NS_ERROR_CACHE_KEY_NOT_FOUND ;
* typeBits = statement - > AsInt32 ( 0 ) ;
return NS_OK ;
}
nsresult nsOfflineCacheDevice : : GatherEntries ( const nsCString & clientID ,
2012-08-22 19:56:38 +04:00
uint32_t typeBits , uint32_t * count ,
2008-08-27 03:09:02 +04:00
char * * * keys ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2008-08-27 03:09:02 +04:00
LOG ( ( " nsOfflineCacheDevice::GatherEntries [cid=%s, typeBits=%X] \n " ,
clientID . get ( ) , typeBits ) ) ;
AutoResetStatement statement ( mStatement_GatherEntries ) ;
2011-03-31 21:19:31 +04:00
nsresult rv = statement - > BindUTF8StringByIndex ( 0 , clientID ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindInt32ByIndex ( 1 , typeBits ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
return RunSimpleQuery ( mStatement_GatherEntries , 0 , count , keys ) ;
}
2008-09-30 22:34:23 +04:00
nsresult nsOfflineCacheDevice : : AddNamespace ( const nsCString & clientID ,
nsIApplicationCacheNamespace * ns ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2008-09-30 22:34:23 +04:00
nsCString namespaceSpec ;
nsresult rv = ns - > GetNamespaceSpec ( namespaceSpec ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
nsCString data ;
rv = ns - > GetData ( data ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-08-22 19:56:38 +04:00
uint32_t itemType ;
2008-09-30 22:34:23 +04:00
rv = ns - > GetItemType ( & itemType ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2008-11-06 03:01:07 +03:00
LOG ( ( " nsOfflineCacheDevice::AddNamespace [cid=%s, ns=%s, data=%s, type=%d] " ,
2011-06-17 00:25:20 +04:00
clientID . get ( ) , namespaceSpec . get ( ) , data . get ( ) , itemType ) ) ;
2008-09-30 22:34:23 +04:00
AutoResetStatement statement ( mStatement_InsertNamespaceEntry ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 0 , clientID ) ;
2008-09-30 22:34:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 1 , namespaceSpec ) ;
2008-09-30 22:34:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 2 , data ) ;
2008-09-30 22:34:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindInt32ByIndex ( 3 , itemType ) ;
2008-09-30 22:34:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = statement - > Execute ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
return NS_OK ;
}
2009-02-22 22:09:10 +03:00
nsresult nsOfflineCacheDevice : : GetUsage ( const nsACString & clientID ,
2012-08-22 19:56:38 +04:00
uint32_t * usage ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2009-02-22 22:09:10 +03:00
LOG ( ( " nsOfflineCacheDevice::GetUsage [cid=%s] \n " ,
PromiseFlatCString ( clientID ) . get ( ) ) ) ;
* usage = 0 ;
AutoResetStatement statement ( mStatement_ApplicationCacheSize ) ;
2011-03-31 21:19:31 +04:00
nsresult rv = statement - > BindUTF8StringByIndex ( 0 , clientID ) ;
2009-02-22 22:09:10 +03:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-09-29 10:19:26 +04:00
bool hasRows ;
2009-02-22 22:09:10 +03:00
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
if ( ! hasRows ) return NS_OK ;
2012-08-22 19:56:38 +04:00
* usage = static_cast < uint32_t > ( statement - > AsInt32 ( 0 ) ) ;
2009-02-22 22:09:10 +03:00
return NS_OK ;
}
2012-08-22 19:56:38 +04:00
nsresult nsOfflineCacheDevice : : GetGroups ( uint32_t * count , char * * * keys ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2009-02-22 22:09:10 +03:00
LOG ( ( " nsOfflineCacheDevice::GetGroups " ) ) ;
return RunSimpleQuery ( mStatement_EnumerateGroups , 0 , count , keys ) ;
}
2012-08-22 19:56:38 +04:00
nsresult nsOfflineCacheDevice : : GetGroupsTimeOrdered ( uint32_t * count ,
2012-03-31 04:52:06 +04:00
char * * * keys ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2012-03-31 04:52:06 +04:00
LOG ( ( " nsOfflineCacheDevice::GetGroupsTimeOrder " ) ) ;
return RunSimpleQuery ( mStatement_EnumerateGroupsTimeOrder , 0 , count , keys ) ;
}
2012-06-29 02:27:03 +04:00
bool nsOfflineCacheDevice : : IsLocked ( const nsACString & key ) {
2013-08-15 14:42:02 +04:00
MutexAutoLock lock ( mLock ) ;
2012-06-29 02:27:03 +04:00
return mLockedEntries . GetEntry ( key ) ;
}
void nsOfflineCacheDevice : : Lock ( const nsACString & key ) {
2013-08-15 14:42:02 +04:00
MutexAutoLock lock ( mLock ) ;
2012-06-29 02:27:03 +04:00
mLockedEntries . PutEntry ( key ) ;
}
void nsOfflineCacheDevice : : Unlock ( const nsACString & key ) {
2013-08-15 14:42:02 +04:00
MutexAutoLock lock ( mLock ) ;
2012-06-29 02:27:03 +04:00
mLockedEntries . RemoveEntry ( key ) ;
}
2007-07-25 09:35:39 +04:00
nsresult nsOfflineCacheDevice : : RunSimpleQuery ( mozIStorageStatement * statement ,
2012-08-22 19:56:38 +04:00
uint32_t resultIndex ,
uint32_t * count , char * * * values ) {
2011-09-29 10:19:26 +04:00
bool hasRows ;
2007-07-25 09:35:39 +04:00
nsresult rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
nsTArray < nsCString > valArray ;
while ( hasRows ) {
2012-08-22 19:56:38 +04:00
uint32_t length ;
2007-07-25 09:35:39 +04:00
valArray . AppendElement ( nsDependentCString (
statement - > AsSharedUTF8String ( resultIndex , & length ) ) ) ;
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
* count = valArray . Length ( ) ;
2015-04-01 08:29:55 +03:00
char * * ret = static_cast < char * * > ( moz_xmalloc ( * count * sizeof ( char * ) ) ) ;
2007-07-25 09:35:39 +04:00
2012-08-22 19:56:38 +04:00
for ( uint32_t i = 0 ; i < * count ; i + + ) {
2018-08-28 08:58:54 +03:00
ret [ i ] = NS_xstrdup ( valArray [ i ] . get ( ) ) ;
2007-07-25 09:35:39 +04:00
}
* values = ret ;
return NS_OK ;
}
2008-08-27 03:09:02 +04:00
nsresult nsOfflineCacheDevice : : CreateApplicationCache (
const nsACString & group , nsIApplicationCache * * out ) {
2012-07-30 18:20:58 +04:00
* out = nullptr ;
2007-05-15 00:09:20 +04:00
2008-08-27 03:09:02 +04:00
nsCString clientID ;
// Some characters are special in the clientID. Escape the groupID
// before putting it in to the client key.
if ( ! NS_Escape ( nsCString ( group ) , clientID , url_Path ) ) {
return NS_ERROR_OUT_OF_MEMORY ;
}
2004-10-20 09:00:23 +04:00
2008-08-27 03:09:02 +04:00
PRTime now = PR_Now ( ) ;
2007-05-15 00:09:20 +04:00
2008-08-27 03:09:02 +04:00
// Include the timestamp to guarantee uniqueness across runs, and
// the gNextTemporaryClientID for uniqueness within a second.
2016-12-14 19:32:21 +03:00
clientID . Append ( nsPrintfCString ( " |%016 " PRId64 " |%d " , now / PR_USEC_PER_SEC ,
2008-08-27 03:09:02 +04:00
gNextTemporaryClientID + + ) ) ;
2007-05-15 00:09:20 +04:00
2008-08-27 03:09:02 +04:00
nsCOMPtr < nsIApplicationCache > cache =
new nsApplicationCache ( this , group , clientID ) ;
if ( ! cache ) return NS_ERROR_OUT_OF_MEMORY ;
2008-08-25 10:11:31 +04:00
2018-10-31 23:39:03 +03:00
nsWeakPtr weak = do_GetWeakReference ( cache ) ;
2008-08-27 03:09:02 +04:00
if ( ! weak ) return NS_ERROR_OUT_OF_MEMORY ;
2007-05-15 00:09:20 +04:00
2013-08-15 14:42:02 +04:00
MutexAutoLock lock ( mLock ) ;
2008-08-27 03:09:02 +04:00
mCaches . Put ( clientID , weak ) ;
2007-05-15 00:09:20 +04:00
2008-08-27 03:09:02 +04:00
cache . swap ( * out ) ;
2007-05-15 00:09:20 +04:00
2008-08-27 03:09:02 +04:00
return NS_OK ;
2008-08-25 10:11:31 +04:00
}
2007-05-15 00:09:20 +04:00
2008-08-27 03:09:02 +04:00
nsresult nsOfflineCacheDevice : : GetApplicationCache ( const nsACString & clientID ,
nsIApplicationCache * * out ) {
2013-08-15 14:42:02 +04:00
MutexAutoLock lock ( mLock ) ;
return GetApplicationCache_Unlocked ( clientID , out ) ;
}
nsresult nsOfflineCacheDevice : : GetApplicationCache_Unlocked (
const nsACString & clientID , nsIApplicationCache * * out ) {
2012-07-30 18:20:58 +04:00
* out = nullptr ;
2007-05-15 00:09:20 +04:00
2008-08-27 03:09:02 +04:00
nsCOMPtr < nsIApplicationCache > cache ;
2007-05-15 00:09:20 +04:00
2008-08-27 03:09:02 +04:00
nsWeakPtr weak ;
if ( mCaches . Get ( clientID , getter_AddRefs ( weak ) ) )
cache = do_QueryReferent ( weak ) ;
2008-08-20 09:53:20 +04:00
2008-08-27 03:09:02 +04:00
if ( ! cache ) {
nsCString group ;
nsresult rv = GetGroupForCache ( clientID , group ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2007-05-15 00:09:20 +04:00
2008-08-27 03:09:02 +04:00
if ( group . IsEmpty ( ) ) {
return NS_OK ;
}
2007-05-15 00:09:20 +04:00
2008-08-27 03:09:02 +04:00
cache = new nsApplicationCache ( this , group , clientID ) ;
weak = do_GetWeakReference ( cache ) ;
if ( ! weak ) return NS_ERROR_OUT_OF_MEMORY ;
2008-08-25 10:11:31 +04:00
2008-08-27 03:09:02 +04:00
mCaches . Put ( clientID , weak ) ;
}
2007-05-15 00:09:20 +04:00
2008-08-27 03:09:02 +04:00
cache . swap ( * out ) ;
2008-08-20 09:53:20 +04:00
2008-08-27 03:09:02 +04:00
return NS_OK ;
2008-08-20 09:53:20 +04:00
}
2008-08-27 03:09:02 +04:00
nsresult nsOfflineCacheDevice : : GetActiveCache ( const nsACString & group ,
nsIApplicationCache * * out ) {
2012-07-30 18:20:58 +04:00
* out = nullptr ;
2008-08-20 09:53:20 +04:00
2013-08-15 14:42:02 +04:00
MutexAutoLock lock ( mLock ) ;
2008-08-27 03:09:02 +04:00
nsCString * clientID ;
if ( mActiveCachesByGroup . Get ( group , & clientID ) )
2013-08-15 14:42:02 +04:00
return GetApplicationCache_Unlocked ( * clientID , out ) ;
2008-08-25 10:11:31 +04:00
2008-08-27 03:09:02 +04:00
return NS_OK ;
2008-08-25 10:11:31 +04:00
}
2008-11-04 21:59:12 +03:00
nsresult nsOfflineCacheDevice : : DeactivateGroup ( const nsACString & group ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2012-07-30 18:20:58 +04:00
nsCString * active = nullptr ;
2008-11-04 21:59:12 +03:00
AutoResetStatement statement ( mStatement_DeactivateGroup ) ;
2011-03-31 21:19:31 +04:00
nsresult rv = statement - > BindUTF8StringByIndex ( 0 , group ) ;
2008-11-04 21:59:12 +03:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = statement - > Execute ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2013-08-15 14:42:02 +04:00
MutexAutoLock lock ( mLock ) ;
2008-11-04 21:59:12 +03:00
if ( mActiveCachesByGroup . Get ( group , & active ) ) {
2011-11-09 00:22:15 +04:00
mActiveCaches . RemoveEntry ( * active ) ;
2008-11-04 21:59:12 +03:00
mActiveCachesByGroup . Remove ( group ) ;
2012-07-30 18:20:58 +04:00
active = nullptr ;
2008-11-04 21:59:12 +03:00
}
return NS_OK ;
}
2016-01-18 22:20:08 +03:00
nsresult nsOfflineCacheDevice : : Evict ( nsILoadContextInfo * aInfo ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2016-01-18 22:20:08 +03:00
NS_ENSURE_ARG ( aInfo ) ;
2012-10-03 04:39:09 +04:00
nsresult rv ;
2016-01-18 22:20:08 +03:00
mozilla : : OriginAttributes const * oa = aInfo - > OriginAttributesPtr ( ) ;
2016-11-20 00:53:32 +03:00
if ( oa - > mInIsolatedMozBrowser = = false ) {
2016-01-18 22:20:08 +03:00
nsCOMPtr < nsICacheService > serv = do_GetService ( kCacheServiceCID , & rv ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
return nsCacheService : : GlobalInstance ( ) - > EvictEntriesInternal (
nsICache : : STORE_OFFLINE ) ;
}
2015-10-11 19:13:09 +03:00
2016-01-18 22:20:08 +03:00
nsAutoCString jaridsuffix ;
2012-10-03 04:39:09 +04:00
jaridsuffix . Append ( ' % ' ) ;
2015-10-11 19:13:09 +03:00
2016-01-18 22:20:08 +03:00
nsAutoCString suffix ;
oa - > CreateSuffix ( suffix ) ;
jaridsuffix . Append ( ' # ' ) ;
jaridsuffix . Append ( suffix ) ;
AutoResetStatement statement ( mStatement_EnumerateApps ) ;
rv = statement - > BindUTF8StringByIndex ( 0 , jaridsuffix ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2015-10-11 19:13:09 +03:00
2016-01-18 22:20:08 +03:00
bool hasRows ;
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-10-03 04:39:09 +04:00
2016-01-18 22:20:08 +03:00
while ( hasRows ) {
nsAutoCString group ;
rv = statement - > GetUTF8String ( 0 , group ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
nsCString clientID ;
rv = statement - > GetUTF8String ( 1 , clientID ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
nsCOMPtr < nsIRunnable > ev =
new nsOfflineCacheDiscardCache ( this , group , clientID ) ;
rv = nsCacheService : : DispatchToCacheIOThread ( ev ) ;
2012-10-03 04:39:09 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2013-09-20 13:11:25 +04:00
rv = statement - > ExecuteStep ( & hasRows ) ;
2012-10-03 04:39:09 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2016-01-18 22:20:08 +03:00
}
2012-10-03 04:39:09 +04:00
2016-01-18 22:20:08 +03:00
return NS_OK ;
}
2012-10-03 04:39:09 +04:00
2016-01-18 22:20:08 +03:00
namespace { // anon
2012-10-03 04:39:09 +04:00
2016-01-18 22:20:08 +03:00
class OriginMatch final : public mozIStorageFunction {
2018-04-30 19:46:04 +03:00
~ OriginMatch ( ) = default ;
2016-01-18 22:20:08 +03:00
mozilla : : OriginAttributesPattern const mPattern ;
2013-09-20 13:11:25 +04:00
2016-01-18 22:20:08 +03:00
NS_DECL_ISUPPORTS
NS_DECL_MOZISTORAGEFUNCTION
explicit OriginMatch ( mozilla : : OriginAttributesPattern const & aPattern )
: mPattern ( aPattern ) { }
} ;
2013-09-20 13:11:25 +04:00
2016-01-18 22:20:08 +03:00
NS_IMPL_ISUPPORTS ( OriginMatch , mozIStorageFunction )
NS_IMETHODIMP
OriginMatch : : OnFunctionCall ( mozIStorageValueArray * aFunctionArguments ,
nsIVariant * * aResult ) {
nsresult rv ;
nsAutoCString groupId ;
rv = aFunctionArguments - > GetUTF8String ( 0 , groupId ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
int32_t hash = groupId . Find ( NS_LITERAL_CSTRING ( " # " ) ) ;
if ( hash = = kNotFound ) {
// Just ignore...
return NS_OK ;
2012-10-03 04:39:09 +04:00
}
2016-01-18 22:20:08 +03:00
+ + hash ;
nsDependentCSubstring suffix ( groupId . BeginReading ( ) + hash ,
groupId . Length ( ) - hash ) ;
2017-01-12 19:38:48 +03:00
mozilla : : OriginAttributes oa ;
2016-01-18 22:20:08 +03:00
bool ok = oa . PopulateFromSuffix ( suffix ) ;
NS_ENSURE_TRUE ( ok , NS_ERROR_UNEXPECTED ) ;
bool match = mPattern . Matches ( oa ) ;
RefPtr < nsVariant > outVar ( new nsVariant ( ) ) ;
rv = outVar - > SetAsUint32 ( match ? 1 : 0 ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
outVar . forget ( aResult ) ;
return NS_OK ;
}
} // namespace
nsresult nsOfflineCacheDevice : : Evict (
mozilla : : OriginAttributesPattern const & aPattern ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2016-01-18 22:20:08 +03:00
nsresult rv ;
nsCOMPtr < mozIStorageFunction > function1 ( new OriginMatch ( aPattern ) ) ;
rv = mDB - > CreateFunction ( NS_LITERAL_CSTRING ( " ORIGIN_MATCH " ) , 1 , function1 ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
class AutoRemoveFunc {
public :
mozIStorageConnection * mDB ;
explicit AutoRemoveFunc ( mozIStorageConnection * aDB ) : mDB ( aDB ) { }
~ AutoRemoveFunc ( ) {
mDB - > RemoveFunction ( NS_LITERAL_CSTRING ( " ORIGIN_MATCH " ) ) ;
}
} ;
AutoRemoveFunc autoRemove ( mDB ) ;
nsCOMPtr < mozIStorageStatement > statement ;
rv = mDB - > CreateStatement (
NS_LITERAL_CSTRING ( " SELECT GroupID, ActiveClientID FROM moz_cache_groups "
" WHERE ORIGIN_MATCH(GroupID); " ) ,
getter_AddRefs ( statement ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
AutoResetStatement statementScope ( statement ) ;
bool hasRows ;
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
while ( hasRows ) {
nsAutoCString group ;
rv = statement - > GetUTF8String ( 0 , group ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
nsCString clientID ;
rv = statement - > GetUTF8String ( 1 , clientID ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
nsCOMPtr < nsIRunnable > ev =
new nsOfflineCacheDiscardCache ( this , group , clientID ) ;
rv = nsCacheService : : DispatchToCacheIOThread ( ev ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = statement - > ExecuteStep ( & hasRows ) ;
2012-10-03 04:39:09 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
return NS_OK ;
}
2012-07-31 10:36:00 +04:00
bool nsOfflineCacheDevice : : CanUseCache ( nsIURI * keyURI ,
const nsACString & clientID ,
2013-09-20 13:11:25 +04:00
nsILoadContextInfo * loadContextInfo ) {
2013-08-15 14:42:02 +04:00
{
MutexAutoLock lock ( mLock ) ;
if ( ! mActiveCaches . Contains ( clientID ) ) return false ;
}
2008-09-30 22:34:23 +04:00
2012-07-31 10:36:00 +04:00
nsAutoCString groupID ;
nsresult rv = GetGroupForCache ( clientID , groupID ) ;
NS_ENSURE_SUCCESS ( rv , false ) ;
nsCOMPtr < nsIURI > groupURI ;
rv = NS_NewURI ( getter_AddRefs ( groupURI ) , groupID ) ;
2015-10-11 19:13:09 +03:00
if ( NS_FAILED ( rv ) ) {
2012-07-31 10:36:00 +04:00
return false ;
2015-10-11 19:13:09 +03:00
}
2012-07-31 10:36:00 +04:00
// 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.
if ( ! NS_SecurityCompareURIs ( keyURI , groupURI , GetStrictFileOriginPolicy ( ) ) ) {
return false ;
2012-10-02 17:55:00 +04:00
}
2012-07-31 10:36:00 +04:00
// 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.
2015-10-11 19:13:09 +03:00
2016-01-18 22:20:08 +03:00
nsAutoCString originSuffix ;
loadContextInfo - > OriginAttributesPtr ( ) - > CreateSuffix ( originSuffix ) ;
nsAutoCString demandedGroupID ;
rv = BuildApplicationCacheGroupID ( groupURI , originSuffix , demandedGroupID ) ;
2012-07-31 10:36:00 +04:00
NS_ENSURE_SUCCESS ( rv , false ) ;
2015-10-11 19:13:09 +03:00
if ( groupID ! = demandedGroupID ) {
2012-07-31 10:36:00 +04:00
return false ;
2015-10-11 19:13:09 +03:00
}
2012-07-31 10:36:00 +04:00
return true ;
2008-09-30 22:34:23 +04:00
}
2008-08-27 03:09:02 +04:00
nsresult nsOfflineCacheDevice : : ChooseApplicationCache (
2013-09-20 13:11:25 +04:00
const nsACString & key , nsILoadContextInfo * loadContextInfo ,
2008-08-27 03:09:02 +04:00
nsIApplicationCache * * out ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2016-01-18 22:20:08 +03:00
NS_ENSURE_ARG ( loadContextInfo ) ;
nsresult rv ;
2012-07-30 18:20:58 +04:00
* out = nullptr ;
2008-08-25 10:11:31 +04:00
2008-09-30 22:34:23 +04:00
nsCOMPtr < nsIURI > keyURI ;
2016-01-18 22:20:08 +03:00
rv = NS_NewURI ( getter_AddRefs ( keyURI ) , key ) ;
2008-09-30 22:34:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
// First try to find a matching cache entry.
2008-08-27 03:09:02 +04:00
AutoResetStatement statement ( mStatement_FindClient ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 0 , key ) ;
2008-02-07 12:04:30 +03:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-09-29 10:19:26 +04:00
bool hasRows ;
2008-02-07 12:04:30 +03:00
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2008-08-27 03:09:02 +04:00
while ( hasRows ) {
2012-08-22 19:56:38 +04:00
int32_t itemType ;
2008-08-28 05:15:32 +04:00
rv = statement - > GetInt32 ( 1 , & itemType ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2008-08-28 05:15:32 +04:00
if ( ! ( itemType & nsIApplicationCache : : ITEM_FOREIGN ) ) {
2012-09-02 06:35:17 +04:00
nsAutoCString clientID ;
2008-08-28 05:15:32 +04:00
rv = statement - > GetUTF8String ( 0 , clientID ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2013-09-20 13:11:25 +04:00
if ( CanUseCache ( keyURI , clientID , loadContextInfo ) ) {
2008-09-30 22:34:23 +04:00
return GetApplicationCache ( clientID , out ) ;
2008-08-28 05:15:32 +04:00
}
}
2008-02-07 12:04:30 +03:00
2008-08-27 03:09:02 +04:00
rv = statement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
2008-02-07 12:04:30 +03:00
2008-09-30 22:34:23 +04:00
// OK, we didn't find an exact match. Search for a client with a
// matching namespace.
AutoResetStatement nsstatement ( mStatement_FindClientByNamespace ) ;
2011-03-31 21:19:31 +04:00
rv = nsstatement - > BindUTF8StringByIndex ( 0 , key ) ;
2008-09-30 22:34:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = nsstatement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
while ( hasRows ) {
2012-08-22 19:56:38 +04:00
int32_t itemType ;
2008-09-30 22:34:23 +04:00
rv = nsstatement - > GetInt32 ( 1 , & itemType ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
// Don't associate with a cache based solely on a whitelist entry
if ( ! ( itemType & nsIApplicationCacheNamespace : : NAMESPACE_BYPASS ) ) {
2012-09-02 06:35:17 +04:00
nsAutoCString clientID ;
2008-09-30 22:34:23 +04:00
rv = nsstatement - > GetUTF8String ( 0 , clientID ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2013-09-20 13:11:25 +04:00
if ( CanUseCache ( keyURI , clientID , loadContextInfo ) ) {
2008-09-30 22:34:23 +04:00
return GetApplicationCache ( clientID , out ) ;
}
}
rv = nsstatement - > ExecuteStep ( & hasRows ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
2008-02-07 12:04:30 +03:00
return NS_OK ;
}
2008-09-30 22:34:23 +04:00
nsresult nsOfflineCacheDevice : : CacheOpportunistically (
nsIApplicationCache * cache , const nsACString & key ) {
NS_ENSURE_ARG_POINTER ( cache ) ;
nsresult rv ;
2012-09-02 06:35:17 +04:00
nsAutoCString clientID ;
2008-09-30 22:34:23 +04:00
rv = cache - > GetClientID ( clientID ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
return CacheOpportunistically ( clientID , key ) ;
}
2017-06-20 12:19:52 +03:00
nsresult nsOfflineCacheDevice : : ActivateCache ( const nsACString & group ,
const nsACString & clientID ) {
2016-07-27 13:10:00 +03:00
NS_ENSURE_TRUE ( Initialized ( ) , NS_ERROR_NOT_INITIALIZED ) ;
2008-08-27 03:09:02 +04:00
AutoResetStatement statement ( mStatement_ActivateClient ) ;
2011-03-31 21:19:31 +04:00
nsresult rv = statement - > BindUTF8StringByIndex ( 0 , group ) ;
2008-08-27 03:09:02 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindUTF8StringByIndex ( 1 , clientID ) ;
2007-05-15 00:09:20 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-03-31 21:19:31 +04:00
rv = statement - > BindInt32ByIndex ( 2 , SecondsFromPRTime ( PR_Now ( ) ) ) ;
2008-09-30 22:34:23 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2007-05-15 00:09:20 +04:00
2007-07-26 04:47:33 +04:00
rv = statement - > Execute ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2013-08-15 14:42:02 +04:00
MutexAutoLock lock ( mLock ) ;
2008-08-27 03:09:02 +04:00
nsCString * active ;
if ( mActiveCachesByGroup . Get ( group , & active ) ) {
2011-11-09 00:22:15 +04:00
mActiveCaches . RemoveEntry ( * active ) ;
2008-08-27 03:09:02 +04:00
mActiveCachesByGroup . Remove ( group ) ;
2012-07-30 18:20:58 +04:00
active = nullptr ;
2008-08-27 03:09:02 +04:00
}
if ( ! clientID . IsEmpty ( ) ) {
2011-11-09 00:22:15 +04:00
mActiveCaches . PutEntry ( clientID ) ;
2008-08-27 03:09:02 +04:00
mActiveCachesByGroup . Put ( group , new nsCString ( clientID ) ) ;
}
2007-07-26 04:47:33 +04:00
return NS_OK ;
2007-05-15 00:09:20 +04:00
}
2004-10-20 09:00:23 +04:00
2017-06-20 12:19:52 +03:00
bool nsOfflineCacheDevice : : IsActiveCache ( const nsACString & group ,
const nsACString & clientID ) {
2012-07-30 18:20:58 +04:00
nsCString * active = nullptr ;
2013-08-15 14:42:02 +04:00
MutexAutoLock lock ( mLock ) ;
2008-08-27 03:09:02 +04:00
return mActiveCachesByGroup . Get ( group , & active ) & & * active = = clientID ;
2007-07-25 10:31:27 +04:00
}
2004-10-20 09:00:23 +04:00
/**
* Preference accessors
*/
2012-06-06 06:08:30 +04:00
void nsOfflineCacheDevice : : SetCacheParentDirectory ( nsIFile * parentDir ) {
2004-10-20 09:00:23 +04:00
if ( Initialized ( ) ) {
NS_ERROR ( " cannot switch cache directory once initialized " ) ;
return ;
}
if ( ! parentDir ) {
2012-07-30 18:20:58 +04:00
mCacheDirectory = nullptr ;
2004-10-20 09:00:23 +04:00
return ;
}
// ensure parent directory exists
nsresult rv = EnsureDir ( parentDir ) ;
if ( NS_FAILED ( rv ) ) {
NS_WARNING ( " unable to create parent directory " ) ;
return ;
}
2012-06-04 18:12:24 +04:00
mBaseDirectory = parentDir ;
2004-10-20 09:00:23 +04:00
// cache dir may not exist, but that's ok
nsCOMPtr < nsIFile > dir ;
rv = parentDir - > Clone ( getter_AddRefs ( dir ) ) ;
if ( NS_FAILED ( rv ) ) return ;
2007-05-15 00:09:20 +04:00
rv = dir - > AppendNative ( NS_LITERAL_CSTRING ( " OfflineCache " ) ) ;
2004-10-20 09:00:23 +04:00
if ( NS_FAILED ( rv ) ) return ;
2018-10-02 00:38:01 +03:00
mCacheDirectory = dir ;
2004-10-20 09:00:23 +04:00
}
2012-08-22 19:56:38 +04:00
void nsOfflineCacheDevice : : SetCapacity ( uint32_t capacity ) {
2004-10-20 09:00:23 +04:00
mCacheCapacity = capacity * 1024 ;
}
2012-07-11 22:20:17 +04:00
bool nsOfflineCacheDevice : : AutoShutdown ( nsIApplicationCache * aAppCache ) {
if ( ! mAutoShutdown ) return false ;
mAutoShutdown = false ;
Shutdown ( ) ;
2016-01-18 22:20:08 +03:00
nsCOMPtr < nsICacheService > serv = do_GetService ( kCacheServiceCID ) ;
2015-10-18 08:24:48 +03:00
RefPtr < nsCacheService > cacheService = nsCacheService : : GlobalInstance ( ) ;
2012-07-11 22:20:17 +04:00
cacheService - > RemoveCustomOfflineDevice ( this ) ;
2012-09-02 06:35:17 +04:00
nsAutoCString clientID ;
2012-07-11 22:20:17 +04:00
aAppCache - > GetClientID ( clientID ) ;
2013-08-15 14:42:02 +04:00
MutexAutoLock lock ( mLock ) ;
2012-07-11 22:20:17 +04:00
mCaches . Remove ( clientID ) ;
return true ;
}