1/*
2 * Copyright (C) 2010, 2011 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. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "WebPreferences.h"
28
29#include "WebContext.h"
30#include "WebPageGroup.h"
31#include "WebPreferencesKeys.h"
32#include <wtf/ThreadingPrimitives.h>
33
34namespace WebKit {
35
36// FIXME: Manipulating this variable is not thread safe.
37// Instead of tracking private browsing state as a boolean preference, we should let the client provide storage sessions explicitly.
38static unsigned privateBrowsingPageCount;
39
40PassRefPtr<WebPreferences> WebPreferences::create(const String& identifier, const String& keyPrefix, const String& globalDebugKeyPrefix)
41{
42    return adoptRef(new WebPreferences(identifier, keyPrefix, globalDebugKeyPrefix));
43}
44
45PassRefPtr<WebPreferences> WebPreferences::createWithLegacyDefaults(const String& identifier, const String& keyPrefix, const String& globalDebugKeyPrefix)
46{
47    RefPtr<WebPreferences> preferences = adoptRef(new WebPreferences(identifier, keyPrefix, globalDebugKeyPrefix));
48    // FIXME: The registerDefault...ValueForKey machinery is unnecessarily heavyweight and complicated.
49    // We can just compute different defaults for modern and legacy APIs in WebPreferencesDefinitions.h macros.
50    preferences->registerDefaultBoolValueForKey(WebPreferencesKey::javaEnabledKey(), true);
51    preferences->registerDefaultBoolValueForKey(WebPreferencesKey::javaEnabledForLocalFilesKey(), true);
52    preferences->registerDefaultBoolValueForKey(WebPreferencesKey::pluginsEnabledKey(), true);
53    preferences->registerDefaultUInt32ValueForKey(WebPreferencesKey::storageBlockingPolicyKey(), WebCore::SecurityOrigin::AllowAllStorage);
54    return preferences.release();
55}
56
57WebPreferences::WebPreferences(const String& identifier, const String& keyPrefix, const String& globalDebugKeyPrefix)
58    : m_identifier(identifier)
59    , m_keyPrefix(keyPrefix)
60    , m_globalDebugKeyPrefix(globalDebugKeyPrefix)
61{
62    platformInitializeStore();
63}
64
65WebPreferences::WebPreferences(const WebPreferences& other)
66    : m_keyPrefix(other.m_keyPrefix)
67    , m_globalDebugKeyPrefix(other.m_globalDebugKeyPrefix)
68    , m_store(other.m_store)
69{
70    platformInitializeStore();
71}
72
73WebPreferences::~WebPreferences()
74{
75    ASSERT(m_pages.isEmpty());
76}
77
78PassRefPtr<WebPreferences> WebPreferences::copy() const
79{
80    return adoptRef(new WebPreferences(*this));
81}
82
83void WebPreferences::addPage(WebPageProxy& webPageProxy)
84{
85    ASSERT(!m_pages.contains(&webPageProxy));
86    m_pages.add(&webPageProxy);
87
88    if (privateBrowsingEnabled()) {
89        if (!privateBrowsingPageCount)
90            WebContext::willStartUsingPrivateBrowsing();
91
92        ++privateBrowsingPageCount;
93    }
94}
95
96void WebPreferences::removePage(WebPageProxy& webPageProxy)
97{
98    ASSERT(m_pages.contains(&webPageProxy));
99    m_pages.remove(&webPageProxy);
100
101    if (privateBrowsingEnabled()) {
102        --privateBrowsingPageCount;
103        if (!privateBrowsingPageCount)
104            WebContext::willStopUsingPrivateBrowsing();
105    }
106}
107
108void WebPreferences::update()
109{
110    for (auto& webPageProxy : m_pages)
111        webPageProxy->preferencesDidChange();
112}
113
114void WebPreferences::updateStringValueForKey(const String& key, const String& value)
115{
116    platformUpdateStringValueForKey(key, value);
117    update(); // FIXME: Only send over the changed key and value.
118}
119
120void WebPreferences::updateBoolValueForKey(const String& key, bool value)
121{
122    if (key == WebPreferencesKey::privateBrowsingEnabledKey()) {
123        updatePrivateBrowsingValue(value);
124        return;
125    }
126
127    platformUpdateBoolValueForKey(key, value);
128    update(); // FIXME: Only send over the changed key and value.
129}
130
131void WebPreferences::updateUInt32ValueForKey(const String& key, uint32_t value)
132{
133    platformUpdateUInt32ValueForKey(key, value);
134    update(); // FIXME: Only send over the changed key and value.
135}
136
137void WebPreferences::updateDoubleValueForKey(const String& key, double value)
138{
139    platformUpdateDoubleValueForKey(key, value);
140    update(); // FIXME: Only send over the changed key and value.
141}
142
143void WebPreferences::updateFloatValueForKey(const String& key, float value)
144{
145    platformUpdateFloatValueForKey(key, value);
146    update(); // FIXME: Only send over the changed key and value.
147}
148
149void WebPreferences::updatePrivateBrowsingValue(bool value)
150{
151    platformUpdateBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey(), value);
152
153    unsigned pagesChanged = m_pages.size();
154    if (!pagesChanged)
155        return;
156
157    if (value) {
158        if (!privateBrowsingPageCount)
159            WebContext::willStartUsingPrivateBrowsing();
160        privateBrowsingPageCount += pagesChanged;
161    }
162
163    update(); // FIXME: Only send over the changed key and value.
164
165    if (!value) {
166        ASSERT(privateBrowsingPageCount >= pagesChanged);
167        privateBrowsingPageCount -= pagesChanged;
168        if (!privateBrowsingPageCount)
169            WebContext::willStopUsingPrivateBrowsing();
170    }
171}
172
173#define DEFINE_PREFERENCE_GETTER_AND_SETTERS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) \
174    void WebPreferences::set##KeyUpper(const Type& value) \
175    { \
176        if (!m_store.set##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key(), value)) \
177            return; \
178        update##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key(), value); \
179        \
180    } \
181    \
182    Type WebPreferences::KeyLower() const \
183    { \
184        return m_store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key()); \
185    } \
186
187FOR_EACH_WEBKIT_PREFERENCE(DEFINE_PREFERENCE_GETTER_AND_SETTERS)
188FOR_EACH_WEBKIT_DEBUG_PREFERENCE(DEFINE_PREFERENCE_GETTER_AND_SETTERS)
189
190#undef DEFINE_PREFERENCE_GETTER_AND_SETTERS
191
192bool WebPreferences::anyPagesAreUsingPrivateBrowsing()
193{
194    return privateBrowsingPageCount;
195}
196
197void WebPreferences::registerDefaultBoolValueForKey(const String& key, bool value)
198{
199    m_store.setOverrideDefaultsBoolValueForKey(key, value);
200    bool userValue;
201    if (platformGetBoolUserValueForKey(key, userValue))
202        m_store.setBoolValueForKey(key, userValue);
203}
204
205void WebPreferences::registerDefaultUInt32ValueForKey(const String& key, uint32_t value)
206{
207    m_store.setOverrideDefaultsUInt32ValueForKey(key, value);
208    uint32_t userValue;
209    if (platformGetUInt32UserValueForKey(key, userValue))
210        m_store.setUInt32ValueForKey(key, userValue);
211}
212
213} // namespace WebKit
214