1 /* 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "StorageNamespaceImpl.h" 28 29 #if ENABLE(DOM_STORAGE) 30 31 #include "SecurityOriginHash.h" 32 #include "StorageAreaImpl.h" 33 #include "StorageMap.h" 34 #include "StorageSyncManager.h" 35 #include "StorageTracker.h" 36 #include <wtf/StdLibExtras.h> 37 #include <wtf/text/StringHash.h> 38 39 #ifdef ANDROID 40 #include "Page.h" 41 #endif 42 43 namespace WebCore { 44 45 typedef HashMap<String, StorageNamespace*> LocalStorageNamespaceMap; 46 47 static LocalStorageNamespaceMap& localStorageNamespaceMap() 48 { 49 DEFINE_STATIC_LOCAL(LocalStorageNamespaceMap, localStorageNamespaceMap, ()); 50 return localStorageNamespaceMap; 51 } 52 53 PassRefPtr<StorageNamespace> StorageNamespaceImpl::localStorageNamespace(const String& path, unsigned quota) 54 { 55 const String lookupPath = path.isNull() ? String("") : path; 56 LocalStorageNamespaceMap::iterator it = localStorageNamespaceMap().find(lookupPath); 57 if (it == localStorageNamespaceMap().end()) { 58 RefPtr<StorageNamespace> storageNamespace = adoptRef(new StorageNamespaceImpl(LocalStorage, lookupPath, quota)); 59 localStorageNamespaceMap().set(lookupPath, storageNamespace.get()); 60 return storageNamespace.release(); 61 } 62 63 return it->second; 64 } 65 66 PassRefPtr<StorageNamespace> StorageNamespaceImpl::sessionStorageNamespace(unsigned quota) 67 { 68 return adoptRef(new StorageNamespaceImpl(SessionStorage, String(), quota)); 69 } 70 71 StorageNamespaceImpl::StorageNamespaceImpl(StorageType storageType, const String& path, unsigned quota) 72 : m_storageType(storageType) 73 , m_path(path.crossThreadString()) 74 , m_syncManager(0) 75 , m_quota(quota) 76 , m_isShutdown(false) 77 { 78 if (m_storageType == LocalStorage && !m_path.isEmpty()) 79 m_syncManager = StorageSyncManager::create(m_path); 80 } 81 82 StorageNamespaceImpl::~StorageNamespaceImpl() 83 { 84 ASSERT(isMainThread()); 85 86 if (m_storageType == LocalStorage) { 87 ASSERT(localStorageNamespaceMap().get(m_path) == this); 88 localStorageNamespaceMap().remove(m_path); 89 } 90 91 if (!m_isShutdown) 92 close(); 93 } 94 95 PassRefPtr<StorageNamespace> StorageNamespaceImpl::copy() 96 { 97 ASSERT(isMainThread()); 98 ASSERT(!m_isShutdown); 99 ASSERT(m_storageType == SessionStorage); 100 101 RefPtr<StorageNamespaceImpl> newNamespace = adoptRef(new StorageNamespaceImpl(m_storageType, m_path, m_quota)); 102 103 StorageAreaMap::iterator end = m_storageAreaMap.end(); 104 for (StorageAreaMap::iterator i = m_storageAreaMap.begin(); i != end; ++i) 105 newNamespace->m_storageAreaMap.set(i->first, i->second->copy()); 106 return newNamespace.release(); 107 } 108 109 PassRefPtr<StorageArea> StorageNamespaceImpl::storageArea(PassRefPtr<SecurityOrigin> prpOrigin) 110 { 111 ASSERT(isMainThread()); 112 ASSERT(!m_isShutdown); 113 114 RefPtr<SecurityOrigin> origin = prpOrigin; 115 RefPtr<StorageAreaImpl> storageArea; 116 if ((storageArea = m_storageAreaMap.get(origin))) 117 return storageArea.release(); 118 119 storageArea = StorageAreaImpl::create(m_storageType, origin, m_syncManager, m_quota); 120 m_storageAreaMap.set(origin.release(), storageArea); 121 return storageArea.release(); 122 } 123 124 void StorageNamespaceImpl::close() 125 { 126 ASSERT(isMainThread()); 127 128 if (m_isShutdown) 129 return; 130 131 // If we're session storage, we shouldn't need to do any work here. 132 if (m_storageType == SessionStorage) { 133 ASSERT(!m_syncManager); 134 return; 135 } 136 137 StorageAreaMap::iterator end = m_storageAreaMap.end(); 138 for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it) 139 it->second->close(); 140 141 if (m_syncManager) 142 m_syncManager->close(); 143 144 m_isShutdown = true; 145 } 146 147 #ifdef ANDROID 148 void StorageNamespaceImpl::clear(Page* page) 149 { 150 ASSERT(isMainThread()); 151 if (m_isShutdown) 152 return; 153 154 // Clear all the keys for each of the storage areas. 155 StorageAreaMap::iterator end = m_storageAreaMap.end(); 156 for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it) { 157 // if there is no page provided, then the user tried to clear storage 158 // with only pages in private browsing mode open. So we do not need to 159 // provide a Frame* here (as the frame is only used to dispatch storage events 160 // and private browsing pages won't be using them). 161 it->second->clear(page ? page->mainFrame() : 0); 162 } 163 } 164 #endif 165 166 void StorageNamespaceImpl::unlock() 167 { 168 // Because there's a single event loop per-process, this is a no-op. 169 } 170 171 void StorageNamespaceImpl::clearOriginForDeletion(SecurityOrigin* origin) 172 { 173 ASSERT(isMainThread()); 174 175 RefPtr<StorageAreaImpl> storageArea = m_storageAreaMap.get(origin); 176 if (storageArea) 177 storageArea->clearForOriginDeletion(); 178 } 179 180 void StorageNamespaceImpl::clearAllOriginsForDeletion() 181 { 182 ASSERT(isMainThread()); 183 184 StorageAreaMap::iterator end = m_storageAreaMap.end(); 185 for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it) 186 it->second->clearForOriginDeletion(); 187 } 188 189 void StorageNamespaceImpl::sync() 190 { 191 ASSERT(isMainThread()); 192 StorageAreaMap::iterator end = m_storageAreaMap.end(); 193 for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it) 194 it->second->sync(); 195 } 196 197 } // namespace WebCore 198 199 #endif // ENABLE(DOM_STORAGE) 200