NS_IMETHODIMP nsDOMStorage::RemoveItem(const nsAString& aKey) { if (!CacheStoragePermissions()) return NS_ERROR_DOM_SECURITY_ERR; if (aKey.IsEmpty()) return NS_OK; nsSessionStorageEntry *entry = mItems.GetEntry(aKey); if (entry && entry->mItem->IsSecure() && !IsCallerSecure()) { return NS_ERROR_DOM_SECURITY_ERR; } if (UseDB()) { #ifdef MOZ_STORAGE nsresult rv = InitDB(); NS_ENSURE_SUCCESS(rv, rv); nsAutoString value; PRBool secureItem; nsAutoString owner; rv = GetDBValue(aKey, value, &secureItem, owner); if (rv == NS_ERROR_DOM_NOT_FOUND_ERR) return NS_OK; NS_ENSURE_SUCCESS(rv, rv); rv = gStorageDB->RemoveKey(mDomain, aKey, owner, aKey.Length() + value.Length()); NS_ENSURE_SUCCESS(rv, rv); mItemsCached = PR_FALSE; BroadcastChangeNotification(); #endif } else if (entry) { // clear string as StorageItems may be referencing this item entry->mItem->ClearValue(); BroadcastChangeNotification(); } if (entry) { mItems.RawRemoveEntry(entry); } return NS_OK; }
nsresult nsDOMStorage::Clear() { if (!CacheStoragePermissions()) return NS_ERROR_DOM_SECURITY_ERR; if (UseDB()) CacheKeysFromDB(); PRBool foundSecureItem = PR_FALSE; mItems.EnumerateEntries(CheckSecure, &foundSecureItem); if (foundSecureItem && !IsCallerSecure()) { return NS_ERROR_DOM_SECURITY_ERR; } #ifdef MOZ_STORAGE if (UseDB()) { nsresult rv = InitDB(); NS_ENSURE_SUCCESS(rv, rv); rv = gStorageDB->ClearStorage(this); NS_ENSURE_SUCCESS(rv, rv); } #endif mItems.Clear(); BroadcastChangeNotification(); return NS_OK; }
nsresult nsDOMStorage::SetDBValue(const nsAString& aKey, const nsAString& aValue, PRBool aSecure) { #ifdef MOZ_STORAGE if (!UseDB()) return NS_OK; nsresult rv = InitDB(); NS_ENSURE_SUCCESS(rv, rv); // Get the current domain for quota enforcement nsCOMPtr<nsIPrincipal> subjectPrincipal; nsContentUtils::GetSecurityManager()-> GetSubjectPrincipal(getter_AddRefs(subjectPrincipal)); nsAutoString currentDomain; if (subjectPrincipal) { nsCOMPtr<nsIURI> uri; rv = subjectPrincipal->GetURI(getter_AddRefs(uri)); if (NS_SUCCEEDED(rv) && uri) { nsCAutoString currentDomainAscii; uri->GetAsciiHost(currentDomainAscii); currentDomain = NS_ConvertUTF8toUTF16(currentDomainAscii); } if (currentDomain.IsEmpty()) { return NS_ERROR_DOM_SECURITY_ERR; } } else { currentDomain = mDomain; } rv = gStorageDB->SetKey(mDomain, aKey, aValue, aSecure, currentDomain, GetQuota(currentDomain)); NS_ENSURE_SUCCESS(rv, rv); mItemsCached = PR_FALSE; BroadcastChangeNotification(); #endif return NS_OK; }
NS_IMETHODIMP nsDOMStorage::SetItem(const nsAString& aKey, const nsAString& aData) { if (!CacheStoragePermissions()) return NS_ERROR_DOM_SECURITY_ERR; if (aKey.IsEmpty()) return NS_OK; nsresult rv; nsRefPtr<nsDOMStorageItem> newitem = nsnull; nsSessionStorageEntry *entry = mItems.GetEntry(aKey); if (entry) { if (entry->mItem->IsSecure() && !IsCallerSecure()) { return NS_ERROR_DOM_SECURITY_ERR; } if (!UseDB()) { entry->mItem->SetValueInternal(aData); } } else { if (UseDB()) newitem = new nsDOMStorageItem(this, aKey, aData, PR_FALSE); else newitem = new nsDOMStorageItem(this, aKey, aData, PR_FALSE); if (!newitem) return NS_ERROR_OUT_OF_MEMORY; } if (UseDB()) { rv = SetDBValue(aKey, aData, IsCallerSecure()); NS_ENSURE_SUCCESS(rv, rv); } if (newitem) { entry = mItems.PutEntry(aKey); NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); entry->mItem = newitem; } // SetDBValue already calls BroadcastChangeNotification so don't do it again if (!UseDB()) BroadcastChangeNotification(); return NS_OK; }
nsresult nsDOMStorage::SetDBValue(const nsAString& aKey, const nsAString& aValue, PRBool aSecure) { #ifdef MOZ_STORAGE if (!UseDB()) return NS_OK; nsresult rv = InitDB(); NS_ENSURE_SUCCESS(rv, rv); // Get the current domain for quota enforcement nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); if (!ssm) return NS_ERROR_FAILURE; nsCOMPtr<nsIPrincipal> subjectPrincipal; ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal)); nsCAutoString currentDomain; if (subjectPrincipal) { nsCOMPtr<nsIURI> unused; rv = GetPrincipalURIAndHost(subjectPrincipal, getter_AddRefs(unused), currentDomain); // Don't bail out on NS_ERROR_DOM_SECURITY_ERR, since we want to allow // trusted file:// URIs below. if (NS_FAILED(rv) && rv != NS_ERROR_DOM_SECURITY_ERR) { return rv; } if (currentDomain.IsEmpty()) { // allow chrome urls and trusted file urls to write using // the storage's domain if (nsContentUtils::IsCallerTrustedForWrite()) currentDomain = mDomain; else return NS_ERROR_DOM_SECURITY_ERR; } } else { currentDomain = mDomain; } PRInt32 quota; PRInt32 warnQuota; GetQuota(currentDomain, "a, &warnQuota); PRInt32 usage; rv = gStorageDB->SetKey(this, aKey, aValue, aSecure, quota, &usage); NS_ENSURE_SUCCESS(rv, rv); mItemsCached = PR_FALSE; if (warnQuota >= 0 && usage > warnQuota) { // try to include the window that exceeded the warn quota nsCOMPtr<nsIDOMWindow> window; JSContext *cx; nsCOMPtr<nsIJSContextStack> stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); if (stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx) { nsCOMPtr<nsIScriptContext> scriptContext; scriptContext = GetScriptContextFromJSContext(cx); if (scriptContext) { window = do_QueryInterface(scriptContext->GetGlobalObject()); } } nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1"); os->NotifyObservers(window, "dom-storage-warn-quota-exceeded", NS_ConvertUTF8toUTF16(currentDomain).get()); } BroadcastChangeNotification(); #endif return NS_OK; }