[WebKit2] Rework WebPreferencesStore to allow easier overriding of defaults
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 25 May 2014 18:59:41 +0000 (18:59 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 25 May 2014 18:59:41 +0000 (18:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=133258

Reviewed by Anders Carlsson.

To support changing default values of preferences based on which API you are using (either
the legacy C-SPI or the Objective-C API), overhaul the WebPreferencesStore to use a single
HashMap of String -> Value (where Value is new type that can be a String, bool, uint32_t or double)
instead of four HashMaps.  This allows us to use two of these new HashMaps, one for the actual
set values, and one for overridden defaults. This new Value class will also allow easier incremental
updating of preferences in the future.

Other notable changes:
- Removed Float kind of preferences. There were none.
- Move StorageBlockingPolicy preference to the correct group, it's a uint32_t, not bool.

* Shared/WebPreferencesStore.cpp:
* Shared/WebPreferencesStore.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@169321 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit2/ChangeLog
Source/WebKit2/Shared/WebPreferencesStore.cpp
Source/WebKit2/Shared/WebPreferencesStore.h
Source/WebKit2/UIProcess/API/Cocoa/WKPreferences.h

index 926edf4..60007bb 100644 (file)
@@ -1,3 +1,24 @@
+2014-05-24  Sam Weinig  <sam@webkit.org>
+
+        [WebKit2] Rework WebPreferencesStore to allow easier overriding of defaults
+        https://bugs.webkit.org/show_bug.cgi?id=133258
+
+        Reviewed by Anders Carlsson.
+
+        To support changing default values of preferences based on which API you are using (either
+        the legacy C-SPI or the Objective-C API), overhaul the WebPreferencesStore to use a single
+        HashMap of String -> Value (where Value is new type that can be a String, bool, uint32_t or double)
+        instead of four HashMaps.  This allows us to use two of these new HashMaps, one for the actual
+        set values, and one for overridden defaults. This new Value class will also allow easier incremental
+        updating of preferences in the future.
+        
+        Other notable changes:
+        - Removed Float kind of preferences. There were none.
+        - Move StorageBlockingPolicy preference to the correct group, it's a uint32_t, not bool.
+
+        * Shared/WebPreferencesStore.cpp:
+        * Shared/WebPreferencesStore.h:
+
 2014-05-25  David Kilzer  <ddkilzer@apple.com>
 
         Add type-checked casts for TransformOperations
index e2166f4..228dc33 100644 (file)
@@ -60,30 +60,87 @@ static BoolOverridesMap& boolTestRunnerOverridesMap()
     return map;
 }
 
+void WebPreferencesStore::Value::encode(IPC::ArgumentEncoder& encoder) const
+{
+    encoder.encodeEnum(m_type);
+    
+    switch (m_type) {
+    case Type::None:
+        break;
+    case Type::String:
+        encoder << m_string;
+        break;
+    case Type::Bool:
+        encoder << m_bool;
+        break;
+    case Type::UInt32:
+        encoder << m_uint32;
+        break;
+    case Type::Double:
+        encoder << m_double;
+        break;
+    }
+}
+
+bool WebPreferencesStore::Value::decode(IPC::ArgumentDecoder& decoder, Value& result)
+{
+    Value::Type type;
+    if (!decoder.decodeEnum(type))
+        return false;
+    
+    switch (type) {
+    case Type::None:
+        break;
+    case Type::String: {
+        String value;
+        if (!decoder.decode(value))
+            return false;
+        result = Value(value);
+        break;
+    }
+    case Type::Bool: {
+        bool value;
+        if (!decoder.decode(value))
+            return false;
+        result = Value(value);
+        break;
+    }
+    case Type::UInt32: {
+        uint32_t value;
+        if (!decoder.decode(value))
+            return false;
+        result = Value(value);
+        break;
+    }
+    case Type::Double: {
+        double value;
+        if (!decoder.decode(value))
+            return false;
+        result = Value(value);
+        break;
+    }
+    default:
+        return false;
+    }
+
+    return true;
+}
+
 WebPreferencesStore::WebPreferencesStore()
 {
 }
 
 void WebPreferencesStore::encode(IPC::ArgumentEncoder& encoder) const
 {
-    encoder << m_stringValues;
-    encoder << m_boolValues;
-    encoder << m_uint32Values;
-    encoder << m_doubleValues;
-    encoder << m_floatValues;
+    encoder << m_values;
+    encoder << m_overridenDefaults;
 }
 
 bool WebPreferencesStore::decode(IPC::ArgumentDecoder& decoder, WebPreferencesStore& result)
 {
-    if (!decoder.decode(result.m_stringValues))
-        return false;
-    if (!decoder.decode(result.m_boolValues))
+    if (!decoder.decode(result.m_values))
         return false;
-    if (!decoder.decode(result.m_uint32Values))
-        return false;
-    if (!decoder.decode(result.m_doubleValues))
-        return false;
-    if (!decoder.decode(result.m_floatValues))
+    if (!decoder.decode(result.m_overridenDefaults))
         return false;
     return true;
 }
@@ -98,149 +155,129 @@ void WebPreferencesStore::removeTestRunnerOverrides()
     boolTestRunnerOverridesMap().clear();
 }
 
+template <typename T> struct ToType { };
 
-template<typename MappedType>
-MappedType defaultValueForKey(const String&);
+template<> struct ToType<String> { static const auto value = WebPreferencesStore::Value::Type::String; };
+template<> struct ToType<bool> { static const auto value = WebPreferencesStore::Value::Type::Bool; };
+template<> struct ToType<uint32_t> { static const auto value = WebPreferencesStore::Value::Type::UInt32; };
+template<> struct ToType<double> { static const auto value = WebPreferencesStore::Value::Type::Double; };
 
-template<>
-String defaultValueForKey(const String& key)
-{
-    static HashMap<String, String>& defaults = *new HashMap<String, String>;
-    if (defaults.isEmpty()) {
-#define DEFINE_STRING_DEFAULTS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) defaults.set(WebPreferencesKey::KeyLower##Key(), DefaultValue);
-        FOR_EACH_WEBKIT_STRING_PREFERENCE(DEFINE_STRING_DEFAULTS)
-        FOR_EACH_WEBKIT_STRING_PREFERENCE_NOT_IN_WEBCORE(DEFINE_STRING_DEFAULTS)
-#undef DEFINE_STRING_DEFAULTS
-    }
 
-    return defaults.get(key);
-}
+template<typename MappedType> MappedType as(const WebPreferencesStore::Value&);
 
-template<>
-bool defaultValueForKey(const String& key)
-{
-    static HashMap<String, bool>& defaults = *new HashMap<String, bool>;
-    if (defaults.isEmpty()) {
-#define DEFINE_BOOL_DEFAULTS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) defaults.set(WebPreferencesKey::KeyLower##Key(), DefaultValue);
-        FOR_EACH_WEBKIT_BOOL_PREFERENCE(DEFINE_BOOL_DEFAULTS)
-#undef DEFINE_BOOL_DEFAULTS
-    }
-
-    return defaults.get(key);
-}
-
-template<>
-uint32_t defaultValueForKey(const String& key)
-{
-    static HashMap<String, uint32_t>& defaults = *new HashMap<String, uint32_t>;
-    if (defaults.isEmpty()) {
-#define DEFINE_UINT32_DEFAULTS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) defaults.set(WebPreferencesKey::KeyLower##Key(), DefaultValue);
-        FOR_EACH_WEBKIT_UINT32_PREFERENCE(DEFINE_UINT32_DEFAULTS)
-#undef DEFINE_UINT32_DEFAULTS
-    }
+template<> String as<String>(const WebPreferencesStore::Value& value) { return value.asString(); }
+template<> bool as<bool>(const WebPreferencesStore::Value& value) { return value.asBool(); }
+template<> uint32_t as<uint32_t>(const WebPreferencesStore::Value& value) { return value.asUInt32(); }
+template<> double as<double>(const WebPreferencesStore::Value& value) { return value.asDouble(); }
 
-    return defaults.get(key);
-}
 
-template<>
-double defaultValueForKey(const String& key)
+static WebPreferencesStore::ValueMap& defaults()
 {
-    static HashMap<String, double>& defaults = *new HashMap<String, double>;
-    if (defaults.isEmpty()) {
-#define DEFINE_DOUBLE_DEFAULTS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) defaults.set(WebPreferencesKey::KeyLower##Key(), DefaultValue);
-        FOR_EACH_WEBKIT_DOUBLE_PREFERENCE(DEFINE_DOUBLE_DEFAULTS)
-#undef DEFINE_DOUBLE_DEFAULTS
+    static NeverDestroyed<WebPreferencesStore::ValueMap> defaults;
+    if (defaults.get().isEmpty()) {
+#define DEFINE_DEFAULTS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) defaults.get().set(WebPreferencesKey::KeyLower##Key(), WebPreferencesStore::Value((Type)DefaultValue));
+        FOR_EACH_WEBKIT_PREFERENCE(DEFINE_DEFAULTS)
+#undef DEFINE_DEFAULTS
     }
 
-    return defaults.get(key);
+    return defaults;
 }
 
-template<>
-float defaultValueForKey(const String& key)
+template<typename MappedType>
+static MappedType valueForKey(const WebPreferencesStore::ValueMap& values, const WebPreferencesStore::ValueMap& overridenDefaults, const String& key)
 {
-    static HashMap<String, float>& defaults = *new HashMap<String, float>;
-    if (defaults.isEmpty()) {
-#define DEFINE_FLOAT_DEFAULTS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) defaults.set(WebPreferencesKey::KeyLower##Key(), DefaultValue);
-        FOR_EACH_WEBKIT_FLOAT_PREFERENCE(DEFINE_FLOAT_DEFAULTS)
-#undef DEFINE_FLOAT_DEFAULTS
-    }
+    auto valuesIt = values.find(key);
+    if (valuesIt != values.end() && valuesIt->value.type() == ToType<MappedType>::value)
+        return as<MappedType>(valuesIt->value);
 
-    return defaults.get(key);
-}
+    auto overridenDefaultsIt = overridenDefaults.find(key);
+    if (overridenDefaultsIt != overridenDefaults.end() && overridenDefaultsIt->value.type() == ToType<MappedType>::value)
+        return as<MappedType>(overridenDefaultsIt->value);
 
-template<typename MapType>
-static typename MapType::MappedType valueForKey(const MapType& map, const typename MapType::KeyType& key)
-{
-    typename MapType::const_iterator it = map.find(key);
-    if (it != map.end())
-        return it->value;
+    auto defaultsMap = defaults();
+    auto defaultsIt = defaultsMap.find(key);
+    if (defaultsIt != defaultsMap.end() && defaultsIt->value.type() == ToType<MappedType>::value)
+        return as<MappedType>(defaultsIt->value);
 
-    return defaultValueForKey<typename MapType::MappedType>(key);
+    return MappedType();
 }
 
-template<typename MapType>
-static bool setValueForKey(MapType& map, const typename MapType::KeyType& key, const typename MapType::MappedType& value)
+template<typename MappedType>
+static bool setValueForKey(WebPreferencesStore::ValueMap& map, const WebPreferencesStore::ValueMap& overridenDefaults, const String& key, const MappedType& value)
 {
-    typename MapType::MappedType existingValue = valueForKey(map, key);
+    MappedType existingValue = valueForKey<MappedType>(map, overridenDefaults, key);
     if (existingValue == value)
         return false;
-    
-    map.set(key, value);
+
+    map.set(key, WebPreferencesStore::Value(value));
     return true;
 }
 
 bool WebPreferencesStore::setStringValueForKey(const String& key, const String& value)
 {
-    return setValueForKey(m_stringValues, key, value);
+    return setValueForKey<String>(m_values, m_overridenDefaults, key, value);
 }
 
 String WebPreferencesStore::getStringValueForKey(const String& key) const
 {
-    return valueForKey(m_stringValues, key);
+    return valueForKey<String>(m_values, m_overridenDefaults, key);
 }
 
 bool WebPreferencesStore::setBoolValueForKey(const String& key, bool value)
 {
-    return setValueForKey(m_boolValues, key, value);
+    return setValueForKey<bool>(m_values, m_overridenDefaults, key, value);
 }
 
 bool WebPreferencesStore::getBoolValueForKey(const String& key) const
 {
     // FIXME: Extend overriding to other key types used from TestRunner.
-    BoolOverridesMap::const_iterator it = boolTestRunnerOverridesMap().find(key);
+    auto it = boolTestRunnerOverridesMap().find(key);
     if (it != boolTestRunnerOverridesMap().end())
         return it->value;
-    return valueForKey(m_boolValues, key);
+
+    return valueForKey<bool>(m_values, m_overridenDefaults, key);
 }
 
 bool WebPreferencesStore::setUInt32ValueForKey(const String& key, uint32_t value) 
 {
-    return setValueForKey(m_uint32Values, key, value);
+    return setValueForKey<uint32_t>(m_values, m_overridenDefaults, key, value);
 }
 
 uint32_t WebPreferencesStore::getUInt32ValueForKey(const String& key) const
 {
-    return valueForKey(m_uint32Values, key);
+    return valueForKey<uint32_t>(m_values, m_overridenDefaults, key);
 }
 
 bool WebPreferencesStore::setDoubleValueForKey(const String& key, double value) 
 {
-    return setValueForKey(m_doubleValues, key, value);
+    return setValueForKey<double>(m_values, m_overridenDefaults, key, value);
 }
 
 double WebPreferencesStore::getDoubleValueForKey(const String& key) const
 {
-    return valueForKey(m_doubleValues, key);
+    return valueForKey<double>(m_values, m_overridenDefaults, key);
+}
+
+// Overriden Defaults
+
+void WebPreferencesStore::setOverrideDefaultsStringValueForKey(const String& key, String value)
+{
+    m_overridenDefaults.set(key, Value(value));
+}
+
+void WebPreferencesStore::setOverrideDefaultsBoolValueForKey(const String& key, bool value)
+{
+    m_overridenDefaults.set(key, Value(value));
 }
 
-bool WebPreferencesStore::setFloatValueForKey(const String& key, float value) 
+void WebPreferencesStore::setOverrideDefaultsUInt32ValueForKey(const String& key, uint32_t value)
 {
-    return setValueForKey(m_floatValues, key, value);
+    m_overridenDefaults.set(key, Value(value));
 }
 
-float WebPreferencesStore::getFloatValueForKey(const String& key) const
+void WebPreferencesStore::setOverrideDefaultsDoubleValueForKey(const String& key, double value)
 {
-    return valueForKey(m_floatValues, key);
+    m_overridenDefaults.set(key, Value(value));
 }
 
 } // namespace WebKit
index f52c68e..253014f 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "ArgumentDecoder.h"
 #include "ArgumentEncoder.h"
+#include <WebCore/SecurityOrigin.h>
 #include <wtf/HashMap.h>
 #include <wtf/text/StringHash.h>
 #include <wtf/text/WTFString.h>
@@ -176,7 +177,6 @@ namespace WebKit {
     macro(TabToLinksEnabled, tabToLinksEnabled, Bool, bool, false) \
     macro(InteractiveFormValidationEnabled, interactiveFormValidationEnabled, Bool, bool, false) \
     macro(ScrollingPerformanceLoggingEnabled, scrollingPerformanceLoggingEnabled, Bool, bool, false) \
-    macro(StorageBlockingPolicy, storageBlockingPolicy, UInt32, uint32_t, 0) \
     macro(ScrollAnimatorEnabled, scrollAnimatorEnabled, Bool, bool, DEFAULT_WEBKIT_SCROLL_ANIMATOR_ENABLED) \
     macro(ScreenFontSubstitutionEnabled, screenFontSubstitutionEnabled, Bool, bool, DEFAULT_SCREEN_FONT_SUBSTITUTION_ENABLED) \
     macro(CookieEnabled, cookieEnabled, Bool, bool, true) \
@@ -233,9 +233,6 @@ namespace WebKit {
     macro(PasswordEchoDuration, passwordEchoDuration, Double, double, 2) \
     \
 
-#define FOR_EACH_WEBKIT_FLOAT_PREFERENCE(macro) \
-    \
-
 #define FOR_EACH_WEBKIT_UINT32_PREFERENCE(macro) \
     macro(FontSmoothingLevel, fontSmoothingLevel, UInt32, uint32_t, FontSmoothingLevelMedium) \
     macro(LayoutFallbackWidth, layoutFallbackWidth, UInt32, uint32_t, 980) \
@@ -246,6 +243,7 @@ namespace WebKit {
     macro(InspectorAttachedHeight, inspectorAttachedHeight, UInt32, uint32_t, 300) \
     macro(InspectorAttachedWidth, inspectorAttachedWidth, UInt32, uint32_t, 750) \
     macro(InspectorAttachmentSide, inspectorAttachmentSide, UInt32, uint32_t, 0) \
+    macro(StorageBlockingPolicy, storageBlockingPolicy, UInt32, uint32_t, WebCore::SecurityOrigin::AllowAllStorage) \
     \
 
 #if PLATFORM(COCOA)
@@ -296,7 +294,6 @@ namespace WebKit {
 #define FOR_EACH_WEBKIT_PREFERENCE(macro) \
     FOR_EACH_WEBKIT_BOOL_PREFERENCE(macro) \
     FOR_EACH_WEBKIT_DOUBLE_PREFERENCE(macro) \
-    FOR_EACH_WEBKIT_FLOAT_PREFERENCE(macro) \
     FOR_EACH_WEBKIT_UINT32_PREFERENCE(macro) \
     FOR_EACH_WEBKIT_STRING_PREFERENCE(macro) \
     FOR_EACH_WEBKIT_STRING_PREFERENCE_NOT_IN_WEBCORE(macro) \
@@ -332,18 +329,132 @@ struct WebPreferencesStore {
     bool setDoubleValueForKey(const String& key, double value);
     double getDoubleValueForKey(const String& key) const;
 
-    bool setFloatValueForKey(const String& key, float value);
-    float getFloatValueForKey(const String& key) const;
+    void setOverrideDefaultsStringValueForKey(const String& key, String value);
+    void setOverrideDefaultsBoolValueForKey(const String& key, bool value);
+    void setOverrideDefaultsUInt32ValueForKey(const String& key, uint32_t value);
+    void setOverrideDefaultsDoubleValueForKey(const String& key, double value);
 
     // For WebKitTestRunner usage.
     static void overrideBoolValueForKey(const String& key, bool value);
     static void removeTestRunnerOverrides();
 
-    HashMap<String, String> m_stringValues;
-    HashMap<String, bool> m_boolValues;
-    HashMap<String, uint32_t> m_uint32Values;
-    HashMap<String, double> m_doubleValues;
-    HashMap<String, float> m_floatValues;
+    struct Value {
+        enum class Type {
+            None,
+            String,
+            Bool,
+            UInt32,
+            Double,
+        };
+
+        void encode(IPC::ArgumentEncoder&) const;
+        static bool decode(IPC::ArgumentDecoder&, Value&);
+
+        explicit Value() : m_type(Type::None) { }
+        explicit Value(const String& value) : m_type(Type::String), m_string(value) { }
+        explicit Value(bool value) : m_type(Type::Bool), m_bool(value) { }
+        explicit Value(uint32_t value) : m_type(Type::UInt32), m_uint32(value) { }
+        explicit Value(double value) : m_type(Type::Double), m_double(value) { }
+
+        Value(Value&& value)
+            : m_type(value.m_type)
+        {
+            switch (m_type) {
+            case Type::None:
+                break;
+            case Type::String:
+                new (&m_string) String(std::move(value.m_string));
+                break;
+            case Type::Bool:
+                m_bool = value.m_bool;
+                break;
+            case Type::UInt32:
+                m_uint32 = value.m_uint32;
+                break;
+            case Type::Double:
+                m_double = value.m_double;
+                break;
+            }
+        }
+
+        Value& operator=(const Value& other)
+        {
+            if (this == &other)
+                return *this;
+                
+            destroy();
+
+            m_type = other.m_type;
+            switch (m_type) {
+            case Type::None:
+                break;
+            case Type::String:
+                new (&m_string) String(other.m_string);
+                break;
+            case Type::Bool:
+                m_bool = other.m_bool;
+                break;
+            case Type::UInt32:
+                m_uint32 = other.m_uint32;
+                break;
+            case Type::Double:
+                m_double = other.m_double;
+                break;
+            }
+    
+            return *this;
+        }
+
+        ~Value()
+        {
+            destroy();
+        }
+
+        Type type() const { return m_type; }
+
+        String asString() const
+        {
+            ASSERT(m_type == Type::String);
+            return m_string;
+        }
+
+        bool asBool() const
+        {
+            ASSERT(m_type == Type::Bool);
+            return m_bool;
+        }
+
+        uint32_t asUInt32() const
+        {
+            ASSERT(m_type == Type::UInt32);
+            return m_uint32;
+        }
+
+        double asDouble() const
+        {
+            ASSERT(m_type == Type::Double);
+            return m_double;
+        }
+
+    private:
+        void destroy()
+        {
+            if (m_type == Type::String)
+                m_string.~String();
+        }
+
+        Type m_type;
+        union {
+            String m_string;
+            bool m_bool;
+            uint32_t m_uint32;
+            double m_double;
+        };
+    };
+
+    typedef HashMap<String, Value> ValueMap;
+    ValueMap m_values;
+    ValueMap m_overridenDefaults;
 };
 
 } // namespace WebKit
index 229c6b5..5a2942c 100644 (file)
@@ -34,7 +34,7 @@
  A @link WKWebView @/link can specify which WKPreferences object it uses through its @link WKWebViewConfiguration @/link.
  */
 WK_CLASS_AVAILABLE(10_10, 8_0)
-@interface WKPreferences : NSObject
+@interface      : NSObject
 
 /*! @abstract Returns an initialized WKPreferences object.
  @param userDefaultsKeyPrefix The user defaults key prefix.