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// FIXME: On Windows, we require all WebKit source files to include config.h
27// before including any other files. Failing to include config.h will leave
28// WTF_USE_CF undefined, causing build failures in this
29// file. But Mac doesn't have a config.h for WebKit, so we can't include the
30// Windows one here. For now we can just define WTF_USE_CF and
31// WTF_USE_CFNETWORK manually, but we need a better long-term solution.
32#ifndef WTF_USE_CF
33#define WTF_USE_CF 1
34#endif
35
36#include <wtf/Platform.h>
37
38#if PLATFORM(WIN) && !OS(WINCE)
39#ifndef WTF_USE_CG
40#define WTF_USE_CG 1
41#endif
42#endif
43
44// NOTE: These need to appear up top, as they declare macros
45// used in the JS and WTF headers.
46#include <runtime/JSExportMacros.h>
47#include <wtf/ExportMacros.h>
48
49#include "WebInspectorClient.h"
50
51#include <CoreFoundation/CoreFoundation.h>
52
53#include <WebCore/Frame.h>
54#include <WebCore/InspectorFrontendClientLocal.h>
55#include <WebCore/Page.h>
56
57#include <wtf/PassOwnPtr.h>
58#include <wtf/RetainPtr.h>
59#include <wtf/Vector.h>
60#include <wtf/text/WTFString.h>
61
62using namespace WebCore;
63
64static const char* inspectorStartsAttachedSetting = "inspectorStartsAttached";
65static const char* inspectorAttachDisabledSetting = "inspectorAttachDisabled";
66
67static inline RetainPtr<CFStringRef> createKeyForPreferences(const String& key)
68{
69    return adoptCF(CFStringCreateWithFormat(0, 0, CFSTR("WebKit Web Inspector Setting - %@"), key.createCFString().get()));
70}
71
72static void populateSetting(const String& key, String* setting)
73{
74    RetainPtr<CFStringRef> preferencesKey = createKeyForPreferences(key);
75    RetainPtr<CFPropertyListRef> value = adoptCF(CFPreferencesCopyAppValue(preferencesKey.get(), kCFPreferencesCurrentApplication));
76
77    if (!value)
78        return;
79
80    CFTypeID type = CFGetTypeID(value.get());
81    if (type == CFStringGetTypeID())
82        *setting = static_cast<String>(static_cast<CFStringRef>(value.get()));
83    else if (type == CFBooleanGetTypeID())
84        *setting = static_cast<bool>(CFBooleanGetValue(static_cast<CFBooleanRef>(value.get()))) ? "true" : "false";
85    else
86        *setting = "";
87}
88
89static void storeSetting(const String& key, const String& setting)
90{
91    CFPreferencesSetAppValue(createKeyForPreferences(key).get(), setting.createCFString().get(), kCFPreferencesCurrentApplication);
92}
93
94bool WebInspectorClient::sendMessageToFrontend(const String& message)
95{
96    return doDispatchMessageOnFrontendPage(m_frontendPage, message);
97}
98
99bool WebInspectorClient::inspectorAttachDisabled()
100{
101    String value;
102    populateSetting(inspectorAttachDisabledSetting, &value);
103    if (value.isEmpty())
104        return false;
105    return value == "true";
106}
107
108void WebInspectorClient::setInspectorAttachDisabled(bool disabled)
109{
110    storeSetting(inspectorAttachDisabledSetting, disabled ? "true" : "false");
111}
112
113bool WebInspectorClient::inspectorStartsAttached()
114{
115    String value;
116    populateSetting(inspectorStartsAttachedSetting, &value);
117    if (value.isEmpty())
118        return true;
119    return value == "true";
120}
121
122void WebInspectorClient::setInspectorStartsAttached(bool attached)
123{
124    storeSetting(inspectorStartsAttachedSetting, attached ? "true" : "false");
125}
126
127std::unique_ptr<WebCore::InspectorFrontendClientLocal::Settings> WebInspectorClient::createFrontendSettings()
128{
129    class InspectorFrontendSettingsCF : public WebCore::InspectorFrontendClientLocal::Settings {
130    public:
131        virtual ~InspectorFrontendSettingsCF() { }
132        virtual String getProperty(const String& name)
133        {
134            String value;
135            populateSetting(name, &value);
136            return value;
137        }
138
139        virtual void setProperty(const String& name, const String& value)
140        {
141            storeSetting(name, value);
142        }
143    };
144    return std::make_unique<InspectorFrontendSettingsCF>();
145}
146