PageGroup.cpp 12.7 KB
Newer Older
darin@apple.com's avatar
darin@apple.com committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "PageGroup.h"

29
#include "Chrome.h"
darin@apple.com's avatar
darin@apple.com committed
30 31
#include "ChromeClient.h"
#include "Document.h"
32
#include "DocumentStyleSheetCollection.h"
33
#include "Frame.h"
34
#include "GroupSettings.h"
darin@apple.com's avatar
darin@apple.com committed
35
#include "Page.h"
36
#include "PageCache.h"
37
#include "SecurityOrigin.h"
38
#include "Settings.h"
39
#include "StorageNamespace.h"
darin@apple.com's avatar
darin@apple.com committed
40

41 42 43 44 45 46 47 48
#if ENABLE(VIDEO_TRACK)
#if PLATFORM(MAC)
#include "CaptionUserPreferencesMac.h"
#else
#include "CaptionUserPreferences.h"
#endif
#endif

brettw@chromium.org's avatar
brettw@chromium.org committed
49
#if PLATFORM(CHROMIUM)
50
#include "VisitedLinks.h"
brettw@chromium.org's avatar
brettw@chromium.org committed
51 52
#endif

darin@apple.com's avatar
darin@apple.com committed
53 54
namespace WebCore {

kmccullough@apple.com's avatar
kmccullough@apple.com committed
55 56 57 58 59 60
static unsigned getUniqueIdentifier()
{
    static unsigned currentIdentifier = 0;
    return ++currentIdentifier;
}

darin@apple.com's avatar
darin@apple.com committed
61 62
// --------

63
static bool shouldTrackVisitedLinks = false;
darin@apple.com's avatar
darin@apple.com committed
64

65 66 67 68
PageGroup::PageGroup(const String& name)
    : m_name(name)
    , m_visitedLinksPopulated(false)
    , m_identifier(getUniqueIdentifier())
69
    , m_groupSettings(GroupSettings::create())
70 71 72
{
}

darin@apple.com's avatar
darin@apple.com committed
73 74
PageGroup::PageGroup(Page* page)
    : m_visitedLinksPopulated(false)
kmccullough@apple.com's avatar
kmccullough@apple.com committed
75
    , m_identifier(getUniqueIdentifier())
76
    , m_groupSettings(GroupSettings::create())
darin@apple.com's avatar
darin@apple.com committed
77 78
{
    ASSERT(page);
79
    addPage(page);
darin@apple.com's avatar
darin@apple.com committed
80 81
}

82 83 84 85 86
PageGroup::~PageGroup()
{
    removeAllUserContent();
}

87 88 89 90 91
PassOwnPtr<PageGroup> PageGroup::create(Page* page)
{
    return adoptPtr(new PageGroup(page));
}

92 93 94 95 96 97 98 99 100 101
typedef HashMap<String, PageGroup*> PageGroupMap;
static PageGroupMap* pageGroups = 0;

PageGroup* PageGroup::pageGroup(const String& groupName)
{
    ASSERT(!groupName.isEmpty());
    
    if (!pageGroups)
        pageGroups = new PageGroupMap;

102
    PageGroupMap::AddResult result = pageGroups->add(groupName, 0);
103

104
    if (result.isNewEntry) {
105 106
        ASSERT(!result.iterator->value);
        result.iterator->value = new PageGroup(groupName);
107 108
    }

109 110
    ASSERT(result.iterator->value);
    return result.iterator->value;
111 112
}

beidson@apple.com's avatar
beidson@apple.com committed
113 114 115 116 117 118 119 120
void PageGroup::closeLocalStorage()
{
    if (!pageGroups)
        return;

    PageGroupMap::iterator end = pageGroups->end();

    for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
121 122
        if (it->value->hasLocalStorage())
            it->value->localStorage()->close();
beidson@apple.com's avatar
beidson@apple.com committed
123 124 125
    }
}

126 127 128 129 130 131 132
void PageGroup::clearLocalStorageForAllOrigins()
{
    if (!pageGroups)
        return;

    PageGroupMap::iterator end = pageGroups->end();
    for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
133 134
        if (it->value->hasLocalStorage())
            it->value->localStorage()->clearAllOriginsForDeletion();
135 136 137 138 139 140 141 142 143 144
    }
}

void PageGroup::clearLocalStorageForOrigin(SecurityOrigin* origin)
{
    if (!pageGroups)
        return;

    PageGroupMap::iterator end = pageGroups->end();
    for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
145 146
        if (it->value->hasLocalStorage())
            it->value->localStorage()->clearOriginForDeletion(origin);
147 148 149 150 151 152 153 154 155 156
    }    
}
    
void PageGroup::syncLocalStorage()
{
    if (!pageGroups)
        return;

    PageGroupMap::iterator end = pageGroups->end();
    for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
157 158
        if (it->value->hasLocalStorage())
            it->value->localStorage()->sync();
159 160 161 162 163 164 165 166 167 168 169
    }
}

unsigned PageGroup::numberOfPageGroups()
{
    if (!pageGroups)
        return 0;

    return pageGroups->size();
}

darin@apple.com's avatar
darin@apple.com committed
170 171 172 173 174 175 176 177 178 179 180 181 182 183
void PageGroup::addPage(Page* page)
{
    ASSERT(page);
    ASSERT(!m_pages.contains(page));
    m_pages.add(page);
}

void PageGroup::removePage(Page* page)
{
    ASSERT(page);
    ASSERT(m_pages.contains(page));
    m_pages.remove(page);
}

brettw@chromium.org's avatar
brettw@chromium.org committed
184
bool PageGroup::isLinkVisited(LinkHash visitedLinkHash)
darin@apple.com's avatar
darin@apple.com committed
185
{
brettw@chromium.org's avatar
brettw@chromium.org committed
186 187
#if PLATFORM(CHROMIUM)
    // Use Chromium's built-in visited link database.
188
    return VisitedLinks::isLinkVisited(visitedLinkHash);
brettw@chromium.org's avatar
brettw@chromium.org committed
189
#else
darin@apple.com's avatar
darin@apple.com committed
190 191 192 193 194
    if (!m_visitedLinksPopulated) {
        m_visitedLinksPopulated = true;
        ASSERT(!m_pages.isEmpty());
        (*m_pages.begin())->chrome()->client()->populateVisitedLinks();
    }
darin@apple.com's avatar
darin@apple.com committed
195
    return m_visitedLinkHashes.contains(visitedLinkHash);
brettw@chromium.org's avatar
brettw@chromium.org committed
196
#endif
darin@apple.com's avatar
darin@apple.com committed
197
}
darin@apple.com's avatar
darin@apple.com committed
198

199 200
void PageGroup::addVisitedLinkHash(LinkHash hash)
{
201 202
    if (shouldTrackVisitedLinks)
        addVisitedLink(hash);
203 204
}

brettw@chromium.org's avatar
brettw@chromium.org committed
205
inline void PageGroup::addVisitedLink(LinkHash hash)
darin@apple.com's avatar
darin@apple.com committed
206 207
{
    ASSERT(shouldTrackVisitedLinks);
brettw@chromium.org's avatar
brettw@chromium.org committed
208
#if !PLATFORM(CHROMIUM)
209
    if (!m_visitedLinkHashes.add(hash).isNewEntry)
darin@apple.com's avatar
darin@apple.com committed
210
        return;
brettw@chromium.org's avatar
brettw@chromium.org committed
211 212
#endif
    Page::visitedStateChanged(this, hash);
213
    pageCache()->markPagesForVistedLinkStyleRecalc();
darin@apple.com's avatar
darin@apple.com committed
214 215 216 217
}

void PageGroup::addVisitedLink(const KURL& url)
{
darin@apple.com's avatar
darin@apple.com committed
218 219
    if (!shouldTrackVisitedLinks)
        return;
darin@apple.com's avatar
darin@apple.com committed
220
    ASSERT(!url.isEmpty());
221
    addVisitedLink(visitedLinkHash(url.string()));
darin@apple.com's avatar
darin@apple.com committed
222 223 224 225
}

void PageGroup::addVisitedLink(const UChar* characters, size_t length)
{
darin@apple.com's avatar
darin@apple.com committed
226 227
    if (!shouldTrackVisitedLinks)
        return;
brettw@chromium.org's avatar
brettw@chromium.org committed
228
    addVisitedLink(visitedLinkHash(characters, length));
darin@apple.com's avatar
darin@apple.com committed
229 230 231 232
}

void PageGroup::removeVisitedLinks()
{
darin@apple.com's avatar
darin@apple.com committed
233
    m_visitedLinksPopulated = false;
darin@apple.com's avatar
darin@apple.com committed
234 235 236 237
    if (m_visitedLinkHashes.isEmpty())
        return;
    m_visitedLinkHashes.clear();
    Page::allVisitedStateChanged(this);
238
    pageCache()->markPagesForVistedLinkStyleRecalc();
darin@apple.com's avatar
darin@apple.com committed
239 240 241 242 243
}

void PageGroup::removeAllVisitedLinks()
{
    Page::removeAllVisitedLinks();
244
    pageCache()->markPagesForVistedLinkStyleRecalc();
darin@apple.com's avatar
darin@apple.com committed
245 246
}

darin@apple.com's avatar
darin@apple.com committed
247 248 249 250 251 252 253 254 255
void PageGroup::setShouldTrackVisitedLinks(bool shouldTrack)
{
    if (shouldTrackVisitedLinks == shouldTrack)
        return;
    shouldTrackVisitedLinks = shouldTrack;
    if (!shouldTrackVisitedLinks)
        removeAllVisitedLinks();
}

256
StorageNamespace* PageGroup::localStorage()
257
{
258
    if (!m_localStorage) {
259 260 261 262 263 264
        // Need a page in this page group to query the settings for the local storage database path.
        // Having these parameters attached to the page settings is unfortunate since these settings are
        // not per-page (and, in fact, we simply grab the settings from some page at random), but
        // at this point we're stuck with it.
        Page* page = *m_pages.begin();
        const String& path = page->settings()->localStorageDatabasePath();
265
        unsigned quota = m_groupSettings->localStorageQuotaBytes();
266
        m_localStorage = StorageNamespace::localStorageNamespace(path, quota);
267
    }
268

269 270
    return m_localStorage.get();
}
271

272
void PageGroup::addUserScriptToWorld(DOMWrapperWorld* world, const String& source, const KURL& url,
273
                                     const Vector<String>& whitelist, const Vector<String>& blacklist,
274
                                     UserScriptInjectionTime injectionTime, UserContentInjectedFrames injectedFrames)
275
{
276 277
    ASSERT_ARG(world, world);

278
    OwnPtr<UserScript> userScript = adoptPtr(new UserScript(source, url, whitelist, blacklist, injectionTime, injectedFrames));
279
    if (!m_userScripts)
280
        m_userScripts = adoptPtr(new UserScriptMap);
281
    OwnPtr<UserScriptVector>& scriptsInWorld = m_userScripts->add(world, nullptr).iterator->value;
282
    if (!scriptsInWorld)
283
        scriptsInWorld = adoptPtr(new UserScriptVector);
284 285 286
    scriptsInWorld->append(userScript.release());
}

287
void PageGroup::addUserStyleSheetToWorld(DOMWrapperWorld* world, const String& source, const KURL& url,
288
                                         const Vector<String>& whitelist, const Vector<String>& blacklist,
289
                                         UserContentInjectedFrames injectedFrames,
290 291
                                         UserStyleLevel level,
                                         UserStyleInjectionTime injectionTime)
292
{
293 294
    ASSERT_ARG(world, world);

295
    OwnPtr<UserStyleSheet> userStyleSheet = adoptPtr(new UserStyleSheet(source, url, whitelist, blacklist, injectedFrames, level));
296
    if (!m_userStyleSheets)
297
        m_userStyleSheets = adoptPtr(new UserStyleSheetMap);
298
    OwnPtr<UserStyleSheetVector>& styleSheetsInWorld = m_userStyleSheets->add(world, nullptr).iterator->value;
299
    if (!styleSheetsInWorld)
300
        styleSheetsInWorld = adoptPtr(new UserStyleSheetVector);
301
    styleSheetsInWorld->append(userStyleSheet.release());
302

303
    if (injectionTime == InjectInExistingDocuments)
304
        invalidatedInjectedStyleSheetCacheInAllFrames();
305
}
306

307
void PageGroup::removeUserScriptFromWorld(DOMWrapperWorld* world, const KURL& url)
308
{
309 310
    ASSERT_ARG(world, world);

311 312 313
    if (!m_userScripts)
        return;

314
    UserScriptMap::iterator it = m_userScripts->find(world);
315 316 317
    if (it == m_userScripts->end())
        return;
    
318
    UserScriptVector* scripts = it->value.get();
319 320 321
    for (int i = scripts->size() - 1; i >= 0; --i) {
        if (scripts->at(i)->url() == url)
            scripts->remove(i);
322 323
    }
    
324 325
    if (scripts->isEmpty())
        m_userScripts->remove(it);
326 327
}

328
void PageGroup::removeUserStyleSheetFromWorld(DOMWrapperWorld* world, const KURL& url)
329
{
330 331
    ASSERT_ARG(world, world);

332 333 334
    if (!m_userStyleSheets)
        return;

335
    UserStyleSheetMap::iterator it = m_userStyleSheets->find(world);
336 337 338 339
    bool sheetsChanged = false;
    if (it == m_userStyleSheets->end())
        return;
    
340
    UserStyleSheetVector* stylesheets = it->value.get();
341 342 343 344
    for (int i = stylesheets->size() - 1; i >= 0; --i) {
        if (stylesheets->at(i)->url() == url) {
            stylesheets->remove(i);
            sheetsChanged = true;
345
        }
346
    }
347
        
348 349 350
    if (!sheetsChanged)
        return;

351
    if (stylesheets->isEmpty())
352
        m_userStyleSheets->remove(it);
353

354
    invalidatedInjectedStyleSheetCacheInAllFrames();
355 356
}

357
void PageGroup::removeUserScriptsFromWorld(DOMWrapperWorld* world)
358
{
359 360
    ASSERT_ARG(world, world);

361 362 363
    if (!m_userScripts)
        return;

364
    UserScriptMap::iterator it = m_userScripts->find(world);
365 366 367 368 369 370
    if (it == m_userScripts->end())
        return;
       
    m_userScripts->remove(it);
}

371
void PageGroup::removeUserStyleSheetsFromWorld(DOMWrapperWorld* world)
372
{
373 374
    ASSERT_ARG(world, world);

375 376
    if (!m_userStyleSheets)
        return;
377
    
378
    UserStyleSheetMap::iterator it = m_userStyleSheets->find(world);
379 380
    if (it == m_userStyleSheets->end())
        return;
381
    
382 383
    m_userStyleSheets->remove(it);

384
    invalidatedInjectedStyleSheetCacheInAllFrames();
385 386 387 388
}

void PageGroup::removeAllUserContent()
{
389
    m_userScripts.clear();
390

391 392
    if (m_userStyleSheets) {
        m_userStyleSheets.clear();
393
        invalidatedInjectedStyleSheetCacheInAllFrames();
394
    }
395 396
}

397
void PageGroup::invalidatedInjectedStyleSheetCacheInAllFrames()
398 399 400 401 402
{
    // Clear our cached sheets and have them just reparse.
    HashSet<Page*>::const_iterator end = m_pages.end();
    for (HashSet<Page*>::const_iterator it = m_pages.begin(); it != end; ++it) {
        for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext())
403
            frame->document()->styleSheetCollection()->invalidateInjectedStyleSheetCache();
404 405 406
    }
}

407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
#if ENABLE(VIDEO_TRACK)
CaptionUserPreferences* PageGroup::captionPreferences()
{
    if (!m_captionPreferences)
#if PLATFORM(MAC)
        m_captionPreferences = CaptionUserPreferencesMac::create(this);
#else
        m_captionPreferences = CaptionUserPreferences::create(this);
#endif

    return m_captionPreferences.get();
}
    
void PageGroup::registerForCaptionPreferencesChangedCallbacks(CaptionPreferencesChangedListener* listener)
{
    captionPreferences()->registerForCaptionPreferencesChangedCallbacks(listener);
}

void PageGroup::unregisterForCaptionPreferencesChangedCallbacks(CaptionPreferencesChangedListener* listener)
{
    if (!m_captionPreferences)
        return;
    captionPreferences()->unregisterForCaptionPreferencesChangedCallbacks(listener);
}
    
bool PageGroup::userPrefersCaptions()
{
    return captionPreferences()->userPrefersCaptions();
}

bool PageGroup::userHasCaptionPreferences()
{
    return captionPreferences()->userPrefersCaptions();
}

float PageGroup::captionFontSizeScale()
{
    return captionPreferences()->captionFontSizeScale();
}

#endif

darin@apple.com's avatar
darin@apple.com committed
449
} // namespace WebCore