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 "WebPageGroupProxyMessages.h"
30#include "WebPageProxy.h"
31#include "WebPreferences.h"
32#include <wtf/HashMap.h>
33#include <wtf/text/StringConcatenate.h>
34
35namespace WebKit {
36
37static uint64_t generatePageGroupID()
38{
39    static uint64_t uniquePageGroupID = 1;
40    return uniquePageGroupID++;
41}
42
43typedef HashMap<uint64_t, WebPageGroup*> WebPageGroupMap;
44
45static WebPageGroupMap& webPageGroupMap()
46{
47    DEFINE_STATIC_LOCAL(WebPageGroupMap, map, ());
48    return map;
49}
50
51PassRefPtr<WebPageGroup> WebPageGroup::create(const String& identifier, bool visibleToInjectedBundle, bool visibleToHistoryClient)
52{
53    RefPtr<WebPageGroup> pageGroup = adoptRef(new WebPageGroup(identifier, visibleToInjectedBundle, visibleToHistoryClient));
54
55    webPageGroupMap().set(pageGroup->pageGroupID(), pageGroup.get());
56
57    return pageGroup.release();
58}
59
60WebPageGroup* WebPageGroup::get(uint64_t pageGroupID)
61{
62    return webPageGroupMap().get(pageGroupID);
63}
64
65WebPageGroup::WebPageGroup(const String& identifier, bool visibleToInjectedBundle, bool visibleToHistoryClient)
66{
67    m_data.pageGroupID = generatePageGroupID();
68
69    if (!identifier.isNull())
70        m_data.identifer = identifier;
71    else
72        m_data.identifer = m_data.identifer = makeString("__uniquePageGroupID-", String::number(m_data.pageGroupID));
73
74    m_data.visibleToInjectedBundle = visibleToInjectedBundle;
75    m_data.visibleToHistoryClient = visibleToHistoryClient;
76}
77
78WebPageGroup::~WebPageGroup()
79{
80    if (m_preferences)
81        m_preferences->removePageGroup(this);
82    webPageGroupMap().remove(pageGroupID());
83}
84
85void WebPageGroup::addPage(WebPageProxy* page)
86{
87    m_pages.add(page);
88}
89
90void WebPageGroup::removePage(WebPageProxy* page)
91{
92    m_pages.remove(page);
93}
94
95void WebPageGroup::setPreferences(WebPreferences* preferences)
96{
97    if (preferences == m_preferences)
98        return;
99
100    if (!m_preferences) {
101        m_preferences = preferences;
102        m_preferences->addPageGroup(this);
103    } else {
104        m_preferences->removePageGroup(this);
105        m_preferences = preferences;
106        m_preferences->addPageGroup(this);
107
108        preferencesDidChange();
109    }
110}
111
112WebPreferences* WebPageGroup::preferences() const
113{
114    if (!m_preferences) {
115        if (!m_data.identifer.isNull())
116            m_preferences = WebPreferences::create(m_data.identifer);
117        else
118            m_preferences = WebPreferences::create();
119        m_preferences->addPageGroup(const_cast<WebPageGroup*>(this));
120    }
121    return m_preferences.get();
122}
123
124void WebPageGroup::preferencesDidChange()
125{
126    for (HashSet<WebPageProxy*>::iterator it = m_pages.begin(), end = m_pages.end(); it != end; ++it) {
127        WebPageProxy* page = *it;
128        page->preferencesDidChange();
129    }
130}
131
132static Vector<String> toStringVector(ImmutableArray* array)
133{
134    Vector<String> patternVector;
135    if (!array)
136        return patternVector;
137
138    size_t size = array->size();
139    if (!size)
140        return patternVector;
141
142    patternVector.reserveInitialCapacity(size);
143    for (size_t i = 0; i < size; ++i) {
144        WebString* webString = array->at<WebString>(i);
145        ASSERT(webString);
146        patternVector.uncheckedAppend(webString->string());
147    }
148
149    return patternVector;
150}
151
152void WebPageGroup::addUserStyleSheet(const String& source, const String& baseURL, ImmutableArray* whitelist, ImmutableArray* blacklist, WebCore::UserContentInjectedFrames injectedFrames, WebCore::UserStyleLevel level)
153{
154    if (source.isEmpty())
155        return;
156
157    WebCore::UserStyleSheet userStyleSheet = WebCore::UserStyleSheet(source, (baseURL.isEmpty() ? WebCore::blankURL() : WebCore::KURL(WebCore::KURL(), baseURL)), toStringVector(whitelist), toStringVector(blacklist), injectedFrames, level);
158
159    m_data.userStyleSheets.append(userStyleSheet);
160    sendToAllProcessesInGroup(Messages::WebPageGroupProxy::AddUserStyleSheet(userStyleSheet), m_data.pageGroupID);
161}
162
163void WebPageGroup::addUserScript(const String& source, const String& baseURL, ImmutableArray* whitelist, ImmutableArray* blacklist, WebCore::UserContentInjectedFrames injectedFrames, WebCore::UserScriptInjectionTime injectionTime)
164{
165    if (source.isEmpty())
166        return;
167
168    WebCore::UserScript userScript = WebCore::UserScript(source, (baseURL.isEmpty() ? WebCore::blankURL() : WebCore::KURL(WebCore::KURL(), baseURL)), toStringVector(whitelist), toStringVector(blacklist), injectionTime, injectedFrames);
169
170    m_data.userScripts.append(userScript);
171    sendToAllProcessesInGroup(Messages::WebPageGroupProxy::AddUserScript(userScript), m_data.pageGroupID);
172}
173
174void WebPageGroup::removeAllUserStyleSheets()
175{
176    m_data.userStyleSheets.clear();
177    sendToAllProcessesInGroup(Messages::WebPageGroupProxy::RemoveAllUserStyleSheets(), m_data.pageGroupID);
178}
179
180void WebPageGroup::removeAllUserScripts()
181{
182    m_data.userScripts.clear();
183    sendToAllProcessesInGroup(Messages::WebPageGroupProxy::RemoveAllUserScripts(), m_data.pageGroupID);
184}
185
186void WebPageGroup::removeAllUserContent()
187{
188    m_data.userStyleSheets.clear();
189    m_data.userScripts.clear();
190    sendToAllProcessesInGroup(Messages::WebPageGroupProxy::RemoveAllUserContent(), m_data.pageGroupID);
191}
192
193} // namespace WebKit
194