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 "WebPageGroup.h"
30#include "WebPreferencesKeys.h"
31#include "WebProcessPool.h"
32#include <WebCore/LibWebRTCProvider.h>
33#include <wtf/NeverDestroyed.h>
34#include <wtf/ThreadingPrimitives.h>
35
36namespace WebKit {
37
38// FIXME: Manipulating this variable is not thread safe.
39// Instead of tracking private browsing state as a boolean preference, we should let the client provide storage sessions explicitly.
40static unsigned privateBrowsingPageCount;
41
42Ref<WebPreferences> WebPreferences::create(const String& identifier, const String& keyPrefix, const String& globalDebugKeyPrefix)
43{
44 return adoptRef(*new WebPreferences(identifier, keyPrefix, globalDebugKeyPrefix));
45}
46
47Ref<WebPreferences> WebPreferences::createWithLegacyDefaults(const String& identifier, const String& keyPrefix, const String& globalDebugKeyPrefix)
48{
49 auto preferences = WebPreferences::create(identifier, keyPrefix, globalDebugKeyPrefix);
50 // FIXME: The registerDefault...ValueForKey machinery is unnecessarily heavyweight and complicated.
51 // We can just compute different defaults for modern and legacy APIs in WebPreferencesDefinitions.h macros.
52 preferences->registerDefaultBoolValueForKey(WebPreferencesKey::javaEnabledKey(), true);
53 preferences->registerDefaultBoolValueForKey(WebPreferencesKey::javaEnabledForLocalFilesKey(), true);
54 preferences->registerDefaultBoolValueForKey(WebPreferencesKey::pluginsEnabledKey(), true);
55 preferences->registerDefaultUInt32ValueForKey(WebPreferencesKey::storageBlockingPolicyKey(), WebCore::SecurityOrigin::AllowAllStorage);
56 return preferences;
57}
58
59WebPreferences::WebPreferences(const String& identifier, const String& keyPrefix, const String& globalDebugKeyPrefix)
60 : m_identifier(identifier)
61 , m_keyPrefix(keyPrefix)
62 , m_globalDebugKeyPrefix(globalDebugKeyPrefix)
63{
64 platformInitializeStore();
65}
66
67WebPreferences::WebPreferences(const WebPreferences& other)
68 : m_identifier()
69 , m_keyPrefix(other.m_keyPrefix)
70 , m_globalDebugKeyPrefix(other.m_globalDebugKeyPrefix)
71 , m_store(other.m_store)
72{
73 platformInitializeStore();
74}
75
76WebPreferences::~WebPreferences()
77{
78 ASSERT(m_pages.isEmpty());
79}
80
81Ref<WebPreferences> WebPreferences::copy() const
82{
83 return adoptRef(*new WebPreferences(*this));
84}
85
86void WebPreferences::addPage(WebPageProxy& webPageProxy)
87{
88 ASSERT(!m_pages.contains(&webPageProxy));
89 m_pages.add(&webPageProxy);
90
91 if (privateBrowsingEnabled()) {
92 if (!privateBrowsingPageCount)
93 WebProcessPool::willStartUsingPrivateBrowsing();
94
95 ++privateBrowsingPageCount;
96 }
97}
98
99void WebPreferences::removePage(WebPageProxy& webPageProxy)
100{
101 ASSERT(m_pages.contains(&webPageProxy));
102 m_pages.remove(&webPageProxy);
103
104 if (privateBrowsingEnabled()) {
105 --privateBrowsingPageCount;
106 if (!privateBrowsingPageCount)
107 WebProcessPool::willStopUsingPrivateBrowsing();
108 }
109}
110
111void WebPreferences::update()
112{
113 for (auto& webPageProxy : m_pages)
114 webPageProxy->preferencesDidChange();
115}
116
117void WebPreferences::updateStringValueForKey(const String& key, const String& value)
118{
119 platformUpdateStringValueForKey(key, value);
120 update(); // FIXME: Only send over the changed key and value.
121}
122
123void WebPreferences::updateBoolValueForKey(const String& key, bool value)
124{
125 if (key == WebPreferencesKey::privateBrowsingEnabledKey()) {
126 updatePrivateBrowsingValue(value);
127 return;
128 }
129
130 platformUpdateBoolValueForKey(key, value);
131 update(); // FIXME: Only send over the changed key and value.
132}
133
134void WebPreferences::updateBoolValueForInternalDebugFeatureKey(const String& key, bool value)
135{
136 if (key == WebPreferencesKey::processSwapOnCrossSiteNavigationEnabledKey()) {
137 for (auto* page : m_pages)
138 page->process().processPool().configuration().setProcessSwapsOnNavigation(value);
139
140 return;
141 }
142 if (key == WebPreferencesKey::captureAudioInUIProcessEnabledKey()) {
143 for (auto* page : m_pages)
144 page->process().processPool().configuration().setShouldCaptureAudioInUIProcess(value);
145
146 return;
147 }
148 if (key == WebPreferencesKey::captureVideoInUIProcessEnabledKey()) {
149 for (auto* page : m_pages)
150 page->process().processPool().configuration().setShouldCaptureVideoInUIProcess(value);
151
152 return;
153 }
154
155 update(); // FIXME: Only send over the changed key and value.
156}
157
158void WebPreferences::updateBoolValueForExperimentalFeatureKey(const String& key, bool value)
159{
160 update(); // FIXME: Only send over the changed key and value.
161}
162
163void WebPreferences::updateUInt32ValueForKey(const String& key, uint32_t value)
164{
165 platformUpdateUInt32ValueForKey(key, value);
166 update(); // FIXME: Only send over the changed key and value.
167}
168
169void WebPreferences::updateDoubleValueForKey(const String& key, double value)
170{
171 platformUpdateDoubleValueForKey(key, value);
172 update(); // FIXME: Only send over the changed key and value.
173}
174
175void WebPreferences::updateFloatValueForKey(const String& key, float value)
176{
177 platformUpdateFloatValueForKey(key, value);
178 update(); // FIXME: Only send over the changed key and value.
179}
180
181void WebPreferences::updatePrivateBrowsingValue(bool value)
182{
183 platformUpdateBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey(), value);
184
185 unsigned pagesChanged = m_pages.size();
186 if (!pagesChanged)
187 return;
188
189 if (value) {
190 if (!privateBrowsingPageCount)
191 WebProcessPool::willStartUsingPrivateBrowsing();
192 privateBrowsingPageCount += pagesChanged;
193 }
194
195 update(); // FIXME: Only send over the changed key and value.
196
197 if (!value) {
198 ASSERT(privateBrowsingPageCount >= pagesChanged);
199 privateBrowsingPageCount -= pagesChanged;
200 if (!privateBrowsingPageCount)
201 WebProcessPool::willStopUsingPrivateBrowsing();
202 }
203}
204
205#define DEFINE_PREFERENCE_GETTER_AND_SETTERS(KeyUpper, KeyLower, TypeName, Type, DefaultValue, HumanReadableName, HumanReadableDescription) \
206 void WebPreferences::set##KeyUpper(const Type& value) \
207 { \
208 if (!m_store.set##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key(), value)) \
209 return; \
210 update##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key(), value); \
211 \
212 } \
213 \
214 Type WebPreferences::KeyLower() const \
215 { \
216 return m_store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key()); \
217 } \
218
219FOR_EACH_WEBKIT_PREFERENCE(DEFINE_PREFERENCE_GETTER_AND_SETTERS)
220FOR_EACH_WEBKIT_DEBUG_PREFERENCE(DEFINE_PREFERENCE_GETTER_AND_SETTERS)
221
222#undef DEFINE_PREFERENCE_GETTER_AND_SETTERS
223
224
225bool WebPreferences::anyPagesAreUsingPrivateBrowsing()
226{
227 return privateBrowsingPageCount;
228}
229
230void WebPreferences::registerDefaultBoolValueForKey(const String& key, bool value)
231{
232 m_store.setOverrideDefaultsBoolValueForKey(key, value);
233 bool userValue;
234 if (platformGetBoolUserValueForKey(key, userValue))
235 m_store.setBoolValueForKey(key, userValue);
236}
237
238void WebPreferences::registerDefaultUInt32ValueForKey(const String& key, uint32_t value)
239{
240 m_store.setOverrideDefaultsUInt32ValueForKey(key, value);
241 uint32_t userValue;
242 if (platformGetUInt32UserValueForKey(key, userValue))
243 m_store.setUInt32ValueForKey(key, userValue);
244}
245
246} // namespace WebKit
247