StorageNamespaceImpl.cpp 6.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "StorageNamespaceImpl.h"

29 30 31
#include "GroupSettings.h"
#include "Page.h"
#include "PageGroup.h"
32
#include "SecurityOriginHash.h"
33
#include "Settings.h"
34
#include "StorageAreaImpl.h"
35
#include "StorageMap.h"
36
#include "StorageSyncManager.h"
37
#include "StorageTracker.h"
38
#include <wtf/MainThread.h>
39
#include <wtf/StdLibExtras.h>
40
#include <wtf/text/StringHash.h>
41 42 43 44 45 46 47 48 49 50 51

namespace WebCore {

typedef HashMap<String, StorageNamespace*> LocalStorageNamespaceMap;

static LocalStorageNamespaceMap& localStorageNamespaceMap()
{
    DEFINE_STATIC_LOCAL(LocalStorageNamespaceMap, localStorageNamespaceMap, ());
    return localStorageNamespaceMap;
}

52
PassRefPtr<StorageNamespace> StorageNamespaceImpl::localStorageNamespace(PageGroup* pageGroup)
53
{
54 55 56 57 58 59 60
    // Need a page in this page group to query the settings for the local storage database path.
    // Having these parameters attached to the page settings is unfortunate since these settings are
    // not per-page (and, in fact, we simply grab the settings from some page at random), but
    // at this point we're stuck with it.
    Page* page = *pageGroup->pages().begin();
    const String& path = page->settings()->localStorageDatabasePath();
    unsigned quota = pageGroup->groupSettings()->localStorageQuotaBytes();
61
    const String lookupPath = path.isNull() ? emptyString() : path;
62

63 64 65 66 67 68 69 70
    LocalStorageNamespaceMap::AddResult result = localStorageNamespaceMap().add(lookupPath, 0);
    if (!result.isNewEntry)
        return result.iterator->value;

    RefPtr<StorageNamespace> storageNamespace = adoptRef(new StorageNamespaceImpl(LocalStorage, lookupPath, quota));

    result.iterator->value = storageNamespace.get();
    return storageNamespace.release();
71 72
}

73
PassRefPtr<StorageNamespace> StorageNamespaceImpl::sessionStorageNamespace(Page* page)
74
{
75
    return adoptRef(new StorageNamespaceImpl(SessionStorage, String(), page->settings()->sessionStorageQuota()));
76 77
}

78
StorageNamespaceImpl::StorageNamespaceImpl(StorageType storageType, const String& path, unsigned quota)
79
    : m_storageType(storageType)
80
    , m_path(path.isolatedCopy())
81
    , m_syncManager(0)
82
    , m_quota(quota)
83 84 85 86 87 88 89 90 91 92 93 94 95 96
    , m_isShutdown(false)
{
    if (m_storageType == LocalStorage && !m_path.isEmpty())
        m_syncManager = StorageSyncManager::create(m_path);
}

StorageNamespaceImpl::~StorageNamespaceImpl()
{
    ASSERT(isMainThread());

    if (m_storageType == LocalStorage) {
        ASSERT(localStorageNamespaceMap().get(m_path) == this);
        localStorageNamespaceMap().remove(m_path);
    }
97

98 99
    if (!m_isShutdown)
        close();
100 101
}

102
PassRefPtr<StorageNamespace> StorageNamespaceImpl::copy(Page*)
103 104 105
{
    ASSERT(isMainThread());
    ASSERT(!m_isShutdown);
106
    ASSERT(m_storageType == SessionStorage);
107

108
    RefPtr<StorageNamespaceImpl> newNamespace = adoptRef(new StorageNamespaceImpl(m_storageType, m_path, m_quota));
109 110

    StorageAreaMap::iterator end = m_storageAreaMap.end();
111
    for (StorageAreaMap::iterator i = m_storageAreaMap.begin(); i != end; ++i)
112
        newNamespace->m_storageAreaMap.set(i->key, i->value->copy());
113
    return newNamespace.release();
114 115
}

116
PassRefPtr<StorageArea> StorageNamespaceImpl::storageArea(PassRefPtr<SecurityOrigin> prpOrigin)
117 118 119 120
{
    ASSERT(isMainThread());
    ASSERT(!m_isShutdown);

121
    RefPtr<SecurityOrigin> origin = prpOrigin;
122
    RefPtr<StorageAreaImpl> storageArea;
123
    if ((storageArea = m_storageAreaMap.get(origin)))
124 125
        return storageArea.release();

126
    storageArea = StorageAreaImpl::create(m_storageType, origin, m_syncManager, m_quota);
127
    m_storageAreaMap.set(origin.release(), storageArea);
128 129 130 131 132 133
    return storageArea.release();
}

void StorageNamespaceImpl::close()
{
    ASSERT(isMainThread());
134 135 136

    if (m_isShutdown)
        return;
137

138 139 140 141 142
    // If we're session storage, we shouldn't need to do any work here.
    if (m_storageType == SessionStorage) {
        ASSERT(!m_syncManager);
        return;
    }
143 144 145

    StorageAreaMap::iterator end = m_storageAreaMap.end();
    for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
146
        it->value->close();
147

148 149
    if (m_syncManager)
        m_syncManager->close();
150 151 152 153

    m_isShutdown = true;
}

154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
void StorageNamespaceImpl::clearOriginForDeletion(SecurityOrigin* origin)
{
    ASSERT(isMainThread());

    RefPtr<StorageAreaImpl> storageArea = m_storageAreaMap.get(origin);
    if (storageArea)
        storageArea->clearForOriginDeletion();
}

void StorageNamespaceImpl::clearAllOriginsForDeletion()
{
    ASSERT(isMainThread());

    StorageAreaMap::iterator end = m_storageAreaMap.end();
    for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
169
        it->value->clearForOriginDeletion();
170 171 172 173 174 175 176
}
    
void StorageNamespaceImpl::sync()
{
    ASSERT(isMainThread());
    StorageAreaMap::iterator end = m_storageAreaMap.end();
    for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
177
        it->value->sync();
178 179
}

180 181 182 183 184 185 186 187
void StorageNamespaceImpl::closeIdleLocalStorageDatabases()
{
    ASSERT(isMainThread());
    StorageAreaMap::iterator end = m_storageAreaMap.end();
    for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
        it->value->closeDatabaseIfIdle();
}

188
} // namespace WebCore