1/*
2 * Copyright (C) 2010 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 "WebPageGroup.h"
28
29#include "APIArray.h"
30#include "WebPageGroupProxyMessages.h"
31#include "WebPageProxy.h"
32#include "WebPreferences.h"
33#include <wtf/HashMap.h>
34#include <wtf/NeverDestroyed.h>
35#include <wtf/text/StringConcatenate.h>
36
37namespace WebKit {
38
39static uint64_t generatePageGroupID()
40{
41    static uint64_t uniquePageGroupID = 1;
42    return uniquePageGroupID++;
43}
44
45typedef HashMap<uint64_t, WebPageGroup*> WebPageGroupMap;
46
47static WebPageGroupMap& webPageGroupMap()
48{
49    static NeverDestroyed<WebPageGroupMap> map;
50    return map;
51}
52
53PassRefPtr<WebPageGroup> WebPageGroup::create(const String& identifier, bool visibleToInjectedBundle, bool visibleToHistoryClient)
54{
55    return adoptRef(new WebPageGroup(identifier, visibleToInjectedBundle, visibleToHistoryClient));
56}
57
58PassRef<WebPageGroup> WebPageGroup::createNonNull(const String& identifier, bool visibleToInjectedBundle, bool visibleToHistoryClient)
59{
60    return adoptRef(*new WebPageGroup(identifier, visibleToInjectedBundle, visibleToHistoryClient));
61}
62
63WebPageGroup* WebPageGroup::get(uint64_t pageGroupID)
64{
65    return webPageGroupMap().get(pageGroupID);
66}
67
68static WebPageGroupData pageGroupData(const String& identifier, bool visibleToInjectedBundle, bool visibleToHistoryClient)
69{
70    WebPageGroupData data;
71
72    data.pageGroupID = generatePageGroupID();
73
74    if (!identifier.isEmpty())
75        data.identifer = identifier;
76    else
77        data.identifer = makeString("__uniquePageGroupID-", String::number(data.pageGroupID));
78
79    data.visibleToInjectedBundle = visibleToInjectedBundle;
80    data.visibleToHistoryClient = visibleToHistoryClient;
81
82    return data;
83}
84
85// FIXME: Why does the WebPreferences object here use ".WebKit2" instead of "WebKit2." which all the other constructors use.
86// If it turns out that it's wrong, we can change it to to "WebKit2." and get rid of the globalDebugKeyPrefix from WebPreferences.
87WebPageGroup::WebPageGroup(const String& identifier, bool visibleToInjectedBundle, bool visibleToHistoryClient)
88    : m_data(pageGroupData(identifier, visibleToInjectedBundle, visibleToHistoryClient))
89    , m_preferences(WebPreferences::createWithLegacyDefaults(m_data.identifer, ".WebKit2", "WebKit2."))
90{
91    webPageGroupMap().set(m_data.pageGroupID, this);
92}
93
94WebPageGroup::~WebPageGroup()
95{
96    webPageGroupMap().remove(pageGroupID());
97}
98
99void WebPageGroup::addPage(WebPageProxy* page)
100{
101    m_pages.add(page);
102}
103
104void WebPageGroup::removePage(WebPageProxy* page)
105{
106    m_pages.remove(page);
107}
108
109void WebPageGroup::setPreferences(WebPreferences* preferences)
110{
111    if (preferences == m_preferences)
112        return;
113
114    m_preferences = preferences;
115
116    for (auto& webPageProxy : m_pages)
117        webPageProxy->setPreferences(*m_preferences);
118}
119
120WebPreferences& WebPageGroup::preferences() const
121{
122    return *m_preferences;
123}
124
125void WebPageGroup::preferencesDidChange()
126{
127    for (HashSet<WebPageProxy*>::iterator it = m_pages.begin(), end = m_pages.end(); it != end; ++it) {
128        WebPageProxy* page = *it;
129        page->preferencesDidChange();
130    }
131}
132
133void WebPageGroup::addUserStyleSheet(const String& source, const String& baseURL, API::Array* whitelist, API::Array* blacklist, WebCore::UserContentInjectedFrames injectedFrames, WebCore::UserStyleLevel level)
134{
135    if (source.isEmpty())
136        return;
137
138    WebCore::UserStyleSheet userStyleSheet = WebCore::UserStyleSheet(source, (baseURL.isEmpty() ? WebCore::blankURL() : WebCore::URL(WebCore::URL(), baseURL)), whitelist ? whitelist->toStringVector() : Vector<String>(), blacklist ? blacklist->toStringVector() : Vector<String>(), injectedFrames, level);
139
140    m_data.userStyleSheets.append(userStyleSheet);
141    sendToAllProcessesInGroup(Messages::WebPageGroupProxy::AddUserStyleSheet(userStyleSheet), m_data.pageGroupID);
142}
143
144void WebPageGroup::addUserScript(const String& source, const String& baseURL, API::Array* whitelist, API::Array* blacklist, WebCore::UserContentInjectedFrames injectedFrames, WebCore::UserScriptInjectionTime injectionTime)
145{
146    if (source.isEmpty())
147        return;
148
149    WebCore::UserScript userScript = WebCore::UserScript(source, (baseURL.isEmpty() ? WebCore::blankURL() : WebCore::URL(WebCore::URL(), baseURL)), whitelist ? whitelist->toStringVector() : Vector<String>(), blacklist ? blacklist->toStringVector() : Vector<String>(), injectionTime, injectedFrames);
150
151    m_data.userScripts.append(userScript);
152    sendToAllProcessesInGroup(Messages::WebPageGroupProxy::AddUserScript(userScript), m_data.pageGroupID);
153}
154
155void WebPageGroup::removeAllUserStyleSheets()
156{
157    m_data.userStyleSheets.clear();
158    sendToAllProcessesInGroup(Messages::WebPageGroupProxy::RemoveAllUserStyleSheets(), m_data.pageGroupID);
159}
160
161void WebPageGroup::removeAllUserScripts()
162{
163    m_data.userScripts.clear();
164    sendToAllProcessesInGroup(Messages::WebPageGroupProxy::RemoveAllUserScripts(), m_data.pageGroupID);
165}
166
167void WebPageGroup::removeAllUserContent()
168{
169    m_data.userStyleSheets.clear();
170    m_data.userScripts.clear();
171    sendToAllProcessesInGroup(Messages::WebPageGroupProxy::RemoveAllUserContent(), m_data.pageGroupID);
172}
173
174} // namespace WebKit
175