forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			179 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* 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/. */
 | |
| 
 | |
| #include "SessionStorageCache.h"
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace dom {
 | |
| 
 | |
| SessionStorageCache::SessionStorageCache()
 | |
|   : mSessionDataSetActive(false)
 | |
| {}
 | |
| 
 | |
| SessionStorageCache::DataSet*
 | |
| SessionStorageCache::Set(DataSetType aDataSetType)
 | |
| {
 | |
|   if (aDataSetType == eDefaultSetType) {
 | |
|     return &mDefaultSet;
 | |
|   }
 | |
| 
 | |
|   MOZ_ASSERT(aDataSetType == eSessionSetType);
 | |
| 
 | |
|   if (!mSessionDataSetActive) {
 | |
|     mSessionSet.mOriginQuotaUsage = mDefaultSet.mOriginQuotaUsage;
 | |
| 
 | |
|     for (auto iter = mDefaultSet.mKeys.ConstIter(); !iter.Done(); iter.Next()) {
 | |
|       mSessionSet.mKeys.Put(iter.Key(), iter.Data());
 | |
|     }
 | |
| 
 | |
|     mSessionDataSetActive = true;
 | |
|   }
 | |
| 
 | |
|   return &mSessionSet;
 | |
| }
 | |
| 
 | |
| int64_t
 | |
| SessionStorageCache::GetOriginQuotaUsage(DataSetType aDataSetType)
 | |
| {
 | |
|   return Set(aDataSetType)->mOriginQuotaUsage;
 | |
| }
 | |
| 
 | |
| uint32_t
 | |
| SessionStorageCache::Length(DataSetType aDataSetType)
 | |
| {
 | |
|   return Set(aDataSetType)->mKeys.Count();
 | |
| }
 | |
| 
 | |
| void
 | |
| SessionStorageCache::Key(DataSetType aDataSetType, uint32_t aIndex,
 | |
|                          nsAString& aResult)
 | |
| {
 | |
|   aResult.SetIsVoid(true);
 | |
|   for (auto iter = Set(aDataSetType)->mKeys.Iter(); !iter.Done(); iter.Next()) {
 | |
|     if (aIndex == 0) {
 | |
|       aResult = iter.Key();
 | |
|       return;
 | |
|     }
 | |
|     aIndex--;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void
 | |
| SessionStorageCache::GetItem(DataSetType aDataSetType, const nsAString& aKey,
 | |
|                              nsAString& aResult)
 | |
| {
 | |
|   // not using AutoString since we don't want to copy buffer to result
 | |
|   nsString value;
 | |
|   if (!Set(aDataSetType)->mKeys.Get(aKey, &value)) {
 | |
|     SetDOMStringToNull(value);
 | |
|   }
 | |
|   aResult = value;
 | |
| }
 | |
| 
 | |
| void
 | |
| SessionStorageCache::GetKeys(DataSetType aDataSetType, nsTArray<nsString>& aKeys)
 | |
| {
 | |
|   for (auto iter = Set(aDataSetType)->mKeys.Iter(); !iter.Done(); iter.Next()) {
 | |
|     aKeys.AppendElement(iter.Key());
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| SessionStorageCache::SetItem(DataSetType aDataSetType, const nsAString& aKey,
 | |
|                              const nsAString& aValue, nsString& aOldValue)
 | |
| {
 | |
|   int64_t delta = 0;
 | |
|   DataSet* dataSet = Set(aDataSetType);
 | |
| 
 | |
|   if (!dataSet->mKeys.Get(aKey, &aOldValue)) {
 | |
|     SetDOMStringToNull(aOldValue);
 | |
| 
 | |
|     // We only consider key size if the key doesn't exist before.
 | |
|     delta = static_cast<int64_t>(aKey.Length());
 | |
|   }
 | |
| 
 | |
|   delta += static_cast<int64_t>(aValue.Length()) -
 | |
|            static_cast<int64_t>(aOldValue.Length());
 | |
| 
 | |
|   if (aValue == aOldValue &&
 | |
|       DOMStringIsNull(aValue) == DOMStringIsNull(aOldValue)) {
 | |
|     return NS_SUCCESS_DOM_NO_OPERATION;
 | |
|   }
 | |
| 
 | |
|   if (!dataSet->ProcessUsageDelta(delta)) {
 | |
|     return NS_ERROR_DOM_QUOTA_REACHED;
 | |
|   }
 | |
| 
 | |
|   dataSet->mKeys.Put(aKey, nsString(aValue));
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| SessionStorageCache::RemoveItem(DataSetType aDataSetType, const nsAString& aKey,
 | |
|                                 nsString& aOldValue)
 | |
| {
 | |
|   DataSet* dataSet = Set(aDataSetType);
 | |
| 
 | |
|   if (!dataSet->mKeys.Get(aKey, &aOldValue)) {
 | |
|     return NS_SUCCESS_DOM_NO_OPERATION;
 | |
|   }
 | |
| 
 | |
|   // Recalculate the cached data size
 | |
|   dataSet->ProcessUsageDelta(-(static_cast<int64_t>(aOldValue.Length()) +
 | |
|                                static_cast<int64_t>(aKey.Length())));
 | |
| 
 | |
|   dataSet->mKeys.Remove(aKey);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| void
 | |
| SessionStorageCache::Clear(DataSetType aDataSetType, bool aByUserInteraction)
 | |
| {
 | |
|   DataSet* dataSet = Set(aDataSetType);
 | |
|   dataSet->ProcessUsageDelta(-dataSet->mOriginQuotaUsage);
 | |
|   dataSet->mKeys.Clear();
 | |
| 
 | |
|   if (!aByUserInteraction && aDataSetType == eSessionSetType) {
 | |
|     mSessionDataSetActive = false;
 | |
|   }
 | |
| }
 | |
| 
 | |
| already_AddRefed<SessionStorageCache>
 | |
| SessionStorageCache::Clone() const
 | |
| {
 | |
|   RefPtr<SessionStorageCache> cache = new SessionStorageCache();
 | |
| 
 | |
|   cache->mSessionDataSetActive = mSessionDataSetActive;
 | |
| 
 | |
|   cache->mDefaultSet.mOriginQuotaUsage = mDefaultSet.mOriginQuotaUsage;
 | |
|   for (auto iter = mDefaultSet.mKeys.ConstIter(); !iter.Done(); iter.Next()) {
 | |
|     cache->mDefaultSet.mKeys.Put(iter.Key(), iter.Data());
 | |
|   }
 | |
| 
 | |
|   cache->mSessionSet.mOriginQuotaUsage = mSessionSet.mOriginQuotaUsage;
 | |
|   for (auto iter = mSessionSet.mKeys.ConstIter(); !iter.Done(); iter.Next()) {
 | |
|     cache->mSessionSet.mKeys.Put(iter.Key(), iter.Data());
 | |
|   }
 | |
| 
 | |
|   return cache.forget();
 | |
| }
 | |
| 
 | |
| bool
 | |
| SessionStorageCache::DataSet::ProcessUsageDelta(int64_t aDelta)
 | |
| {
 | |
|   // Check limit per this origin
 | |
|   uint64_t newOriginUsage = mOriginQuotaUsage + aDelta;
 | |
|   if (aDelta > 0 && newOriginUsage > LocalStorageManager::GetQuota()) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // Update size in our data set
 | |
|   mOriginQuotaUsage = newOriginUsage;
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| } // dom namespace
 | |
| } // mozilla namespace
 | 
