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 "Storage.h"
28
29#include "Document.h"
30#include "ExceptionCode.h"
31#include "Frame.h"
32#include "Page.h"
33#include "SchemeRegistry.h"
34#include "Settings.h"
35#include "StorageArea.h"
36#include <wtf/PassRefPtr.h>
37#include <wtf/text/WTFString.h>
38
39namespace WebCore {
40
41PassRefPtr<Storage> Storage::create(Frame* frame, PassRefPtr<StorageArea> storageArea)
42{
43    return adoptRef(new Storage(frame, storageArea));
44}
45
46Storage::Storage(Frame* frame, PassRefPtr<StorageArea> storageArea)
47    : DOMWindowProperty(frame)
48    , m_storageArea(storageArea)
49{
50    ASSERT(m_frame);
51    ASSERT(m_storageArea);
52
53    m_storageArea->incrementAccessCount();
54}
55
56Storage::~Storage()
57{
58    m_storageArea->decrementAccessCount();
59}
60
61unsigned Storage::length(ExceptionCode& ec) const
62{
63    ec = 0;
64    if (!m_storageArea->canAccessStorage(m_frame)) {
65        ec = SECURITY_ERR;
66        return 0;
67    }
68
69    if (isDisabledByPrivateBrowsing())
70        return 0;
71
72    return m_storageArea->length();
73}
74
75String Storage::key(unsigned index, ExceptionCode& ec) const
76{
77    if (!m_storageArea->canAccessStorage(m_frame)) {
78        ec = SECURITY_ERR;
79        return String();
80    }
81
82    if (isDisabledByPrivateBrowsing())
83        return String();
84
85    return m_storageArea->key(index);
86}
87
88String Storage::getItem(const String& key, ExceptionCode& ec) const
89{
90    if (!m_storageArea->canAccessStorage(m_frame)) {
91        ec = SECURITY_ERR;
92        return String();
93    }
94
95    if (isDisabledByPrivateBrowsing())
96        return String();
97
98    return m_storageArea->item(key);
99}
100
101void Storage::setItem(const String& key, const String& value, ExceptionCode& ec)
102{
103    if (!m_storageArea->canAccessStorage(m_frame)) {
104        ec = SECURITY_ERR;
105        return;
106    }
107
108    if (isDisabledByPrivateBrowsing()) {
109        ec = QUOTA_EXCEEDED_ERR;
110        return;
111    }
112
113    bool quotaException = false;
114    m_storageArea->setItem(m_frame, key, value, quotaException);
115
116    if (quotaException)
117        ec = QUOTA_EXCEEDED_ERR;
118}
119
120void Storage::removeItem(const String& key, ExceptionCode& ec)
121{
122    if (!m_storageArea->canAccessStorage(m_frame)) {
123        ec = SECURITY_ERR;
124        return;
125    }
126
127    if (isDisabledByPrivateBrowsing())
128        return;
129
130    m_storageArea->removeItem(m_frame, key);
131}
132
133void Storage::clear(ExceptionCode& ec)
134{
135    if (!m_storageArea->canAccessStorage(m_frame)) {
136        ec = SECURITY_ERR;
137        return;
138    }
139
140    if (isDisabledByPrivateBrowsing())
141        return;
142
143    m_storageArea->clear(m_frame);
144}
145
146bool Storage::contains(const String& key, ExceptionCode& ec) const
147{
148    if (!m_storageArea->canAccessStorage(m_frame)) {
149        ec = SECURITY_ERR;
150        return false;
151    }
152
153    if (isDisabledByPrivateBrowsing())
154        return false;
155
156    return m_storageArea->contains(key);
157}
158
159bool Storage::isDisabledByPrivateBrowsing() const
160{
161    if (!m_frame->page()->settings()->privateBrowsingEnabled())
162        return false;
163
164    if (m_storageArea->storageType() == LocalStorage) {
165        if (SchemeRegistry::allowsLocalStorageAccessInPrivateBrowsing(m_frame->document()->securityOrigin()->protocol()))
166            return false;
167    }
168
169    return true;
170}
171
172} // namespace WebCore
173