Changeset 254859 in webkit


Ignore:
Timestamp:
Jan 21, 2020 9:57:36 AM (4 years ago)
Author:
Chris Dumez
Message:

Minor improvements to StorageAreaMap
https://bugs.webkit.org/show_bug.cgi?id=206433

Reviewed by Darin Adler.

Source/WebCore:

Use inline initialization for some of StorageMap's data member.
Also specify uint8_t as underlying type of StorageType enum class for better packing.

  • inspector/InspectorInstrumentation.h:
  • storage/StorageArea.h:
  • storage/StorageMap.cpp:

(WebCore::StorageMap::StorageMap):

  • storage/StorageMap.h:
  • storage/StorageType.h:

Source/WebKit:

Minor improvements to StorageAreaMap:

  1. The class does not need to be RefCounted, as it is solely owned by StorageNamespaceImpl. Having it RefCounted was actually dangerous because StorageAreaMap had a raw pointer data member to its owner: m_storageNamespace. This raw pointer could become stale if you extend the lifetime of the StorageAreaMap object to outlive its StorageNamespaceImpl.
  2. Make StorageAreaMap::connect() private as it is never called from outside the class
  3. Reorder data members for better packing
  4. Use modern loops in the implementation
  5. Rename loadValuesIfNeeded() to ensureStorageMap() and have it return the StorageMap object. This makes calls site more concise and it makes it clearer when this method needs to be called.
  6. Mark class as final
  7. Replace LOG_ERROR() with RELEASE_LOG_ERROR() so that we can see error logging in sysdiagnoses
  8. Use more references instead of raw pointers to make it clear when null checks are not needed
  • WebProcess/WebStorage/StorageAreaImpl.cpp:

(WebKit::StorageAreaImpl::create):
(WebKit::StorageAreaImpl::StorageAreaImpl):

  • WebProcess/WebStorage/StorageAreaImpl.h:
  • WebProcess/WebStorage/StorageAreaMap.cpp:

(WebKit::StorageAreaMap::StorageAreaMap):
(WebKit::StorageAreaMap::length):
(WebKit::StorageAreaMap::key):
(WebKit::StorageAreaMap::item):
(WebKit::StorageAreaMap::setItem):
(WebKit::StorageAreaMap::removeItem):
(WebKit::StorageAreaMap::clear):
(WebKit::StorageAreaMap::contains):
(WebKit::StorageAreaMap::resetValues):
(WebKit::StorageAreaMap::ensureStorageMap):
(WebKit::StorageAreaMap::applyChange):
(WebKit::StorageAreaMap::dispatchSessionStorageEvent):
(WebKit::StorageAreaMap::dispatchLocalStorageEvent):
(WebKit::StorageAreaMap::connect):
(WebKit::StorageAreaMap::disconnect):

  • WebProcess/WebStorage/StorageAreaMap.h:
  • WebProcess/WebStorage/StorageAreaMap.messages.in:
  • WebProcess/WebStorage/StorageNamespaceImpl.cpp:

(WebKit::StorageNamespaceImpl::storageArea):

  • WebProcess/WebStorage/StorageNamespaceImpl.h:
Location:
trunk/Source
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r254858 r254859  
     12020-01-21  Chris Dumez  <cdumez@apple.com>
     2
     3        Minor improvements to StorageAreaMap
     4        https://bugs.webkit.org/show_bug.cgi?id=206433
     5
     6        Reviewed by Darin Adler.
     7
     8        Use inline initialization for some of StorageMap's data member.
     9        Also specify uint8_t as underlying type of StorageType enum class for better packing.
     10
     11        * inspector/InspectorInstrumentation.h:
     12        * storage/StorageArea.h:
     13        * storage/StorageMap.cpp:
     14        (WebCore::StorageMap::StorageMap):
     15        * storage/StorageMap.h:
     16        * storage/StorageType.h:
     17
    1182020-01-21  Chris Dumez  <cdumez@apple.com>
    219
  • trunk/Source/WebCore/inspector/InspectorInstrumentation.h

    r253226 r254859  
    109109#endif
    110110
    111 enum class StorageType;
     111enum class StorageType : uint8_t;
    112112
    113113struct ComputedEffectTiming;
  • trunk/Source/WebCore/page/Page.h

    r254739 r254859  
    717717#endif
    718718
    719     void forEachDocument(const WTF::Function<void(Document&)>&) const;
     719    WEBCORE_EXPORT void forEachDocument(const WTF::Function<void(Document&)>&) const;
    720720    void forEachMediaElement(const WTF::Function<void(HTMLMediaElement&)>&);
    721721
  • trunk/Source/WebCore/storage/StorageArea.h

    r248734 r254859  
    3636class StorageSyncManager;
    3737
    38 enum class StorageType;
     38enum class StorageType : uint8_t;
    3939
    4040struct SecurityOriginData;
  • trunk/Source/WebCore/storage/StorageMap.cpp

    r247486 r254859  
    3838StorageMap::StorageMap(unsigned quota)
    3939    : m_iterator(m_map.end())
    40     , m_iteratorIndex(UINT_MAX)
    4140    , m_quotaSize(quota)  // quota measured in bytes
    42     , m_currentLength(0)
    4341{
    4442}
  • trunk/Source/WebCore/storage/StorageMap.h

    r247486 r254859  
    6363    HashMap<String, String> m_map;
    6464    HashMap<String, String>::iterator m_iterator;
    65     unsigned m_iteratorIndex;
     65    unsigned m_iteratorIndex { std::numeric_limits<unsigned>::max() };
    6666
    6767    unsigned m_quotaSize; // Measured in bytes.
    68     unsigned m_currentLength; // Measured in UChars.
     68    unsigned m_currentLength { 0 }; // Measured in UChars.
    6969};
    7070
  • trunk/Source/WebCore/storage/StorageType.h

    r248734 r254859  
    2828namespace WebCore {
    2929
    30 enum class StorageType {
     30enum class StorageType : uint8_t {
    3131    Session,
    3232    Local,
  • trunk/Source/WebKit/ChangeLog

    r254852 r254859  
     12020-01-21  Chris Dumez  <cdumez@apple.com>
     2
     3        Minor improvements to StorageAreaMap
     4        https://bugs.webkit.org/show_bug.cgi?id=206433
     5
     6        Reviewed by Darin Adler.
     7
     8        Minor improvements to StorageAreaMap:
     9        1. The class does not need to be RefCounted, as it is solely owned by StorageNamespaceImpl. Having it
     10           RefCounted was actually dangerous because StorageAreaMap had a raw pointer data member to its owner:
     11           m_storageNamespace. This raw pointer could become stale if you extend the lifetime of the StorageAreaMap
     12           object to outlive its StorageNamespaceImpl.
     13        2. Make StorageAreaMap::connect() private as it is never called from outside the class
     14        3. Reorder data members for better packing
     15        4. Use modern loops in the implementation
     16        5. Rename loadValuesIfNeeded() to ensureStorageMap() and have it return the StorageMap object. This makes
     17           calls site more concise and it makes it clearer when this method needs to be called.
     18        6. Mark class as final
     19        7. Replace LOG_ERROR() with RELEASE_LOG_ERROR() so that we can see error logging in sysdiagnoses
     20        8. Use more references instead of raw pointers to make it clear when null checks are not needed
     21
     22        * WebProcess/WebStorage/StorageAreaImpl.cpp:
     23        (WebKit::StorageAreaImpl::create):
     24        (WebKit::StorageAreaImpl::StorageAreaImpl):
     25        * WebProcess/WebStorage/StorageAreaImpl.h:
     26        * WebProcess/WebStorage/StorageAreaMap.cpp:
     27        (WebKit::StorageAreaMap::StorageAreaMap):
     28        (WebKit::StorageAreaMap::length):
     29        (WebKit::StorageAreaMap::key):
     30        (WebKit::StorageAreaMap::item):
     31        (WebKit::StorageAreaMap::setItem):
     32        (WebKit::StorageAreaMap::removeItem):
     33        (WebKit::StorageAreaMap::clear):
     34        (WebKit::StorageAreaMap::contains):
     35        (WebKit::StorageAreaMap::resetValues):
     36        (WebKit::StorageAreaMap::ensureStorageMap):
     37        (WebKit::StorageAreaMap::applyChange):
     38        (WebKit::StorageAreaMap::dispatchSessionStorageEvent):
     39        (WebKit::StorageAreaMap::dispatchLocalStorageEvent):
     40        (WebKit::StorageAreaMap::connect):
     41        (WebKit::StorageAreaMap::disconnect):
     42        * WebProcess/WebStorage/StorageAreaMap.h:
     43        * WebProcess/WebStorage/StorageAreaMap.messages.in:
     44        * WebProcess/WebStorage/StorageNamespaceImpl.cpp:
     45        (WebKit::StorageNamespaceImpl::storageArea):
     46        * WebProcess/WebStorage/StorageNamespaceImpl.h:
     47
    1482020-01-21  Alejandro G. Castro  <alex@igalia.com>
    249
  • trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaImpl.cpp

    r250738 r254859  
    3838using namespace WebCore;
    3939
    40 Ref<StorageAreaImpl> StorageAreaImpl::create(Ref<StorageAreaMap>&& storageAreaMap)
     40Ref<StorageAreaImpl> StorageAreaImpl::create(StorageAreaMap& storageAreaMap)
    4141{
    42     return adoptRef(*new StorageAreaImpl(WTFMove(storageAreaMap)));
     42    return adoptRef(*new StorageAreaImpl(storageAreaMap));
    4343}
    4444
    45 StorageAreaImpl::StorageAreaImpl(Ref<StorageAreaMap>&& storageAreaMap)
     45StorageAreaImpl::StorageAreaImpl(StorageAreaMap& storageAreaMap)
    4646    : m_identifier(Identifier::generate())
    47     , m_storageAreaMap(makeWeakPtr(storageAreaMap.get()))
     47    , m_storageAreaMap(makeWeakPtr(storageAreaMap))
    4848{
    4949}
     
    9999{
    100100    if (m_storageAreaMap)
    101         return m_storageAreaMap->storageType();
     101        return m_storageAreaMap->type();
    102102
    103103    // We probably need an Invalid type.
  • trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaImpl.h

    r248817 r254859  
    4444    using Identifier = StorageAreaImplIdentifier;
    4545
    46     static Ref<StorageAreaImpl> create(Ref<StorageAreaMap>&&);
     46    static Ref<StorageAreaImpl> create(StorageAreaMap&);
    4747    virtual ~StorageAreaImpl();
    4848
     
    5050
    5151private:
    52     StorageAreaImpl(Ref<StorageAreaMap>&&);
     52    StorageAreaImpl(StorageAreaMap&);
    5353
    5454    // WebCore::StorageArea.
  • trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp

    r252757 r254859  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727#include "StorageAreaMap.h"
    2828
     29#include "Logging.h"
    2930#include "NetworkProcessConnection.h"
    3031#include "StorageAreaImpl.h"
     
    4950using namespace WebCore;
    5051
    51 Ref<StorageAreaMap> StorageAreaMap::create(StorageNamespaceImpl* storageNamespace, Ref<WebCore::SecurityOrigin>&& securityOrigin)
    52 {
    53     return adoptRef(*new StorageAreaMap(storageNamespace, WTFMove(securityOrigin)));
    54 }
    55 
    56 StorageAreaMap::StorageAreaMap(StorageNamespaceImpl* storageNamespace, Ref<WebCore::SecurityOrigin>&& securityOrigin)
    57     : m_storageNamespace(storageNamespace)
    58     , m_storageType(storageNamespace->storageType())
    59     , m_quotaInBytes(storageNamespace->quotaInBytes())
     52StorageAreaMap::StorageAreaMap(StorageNamespaceImpl& storageNamespace, Ref<WebCore::SecurityOrigin>&& securityOrigin)
     53    : m_namespace(storageNamespace)
    6054    , m_securityOrigin(WTFMove(securityOrigin))
    61     , m_currentSeed(0)
    62     , m_hasPendingClear(false)
     55    , m_quotaInBytes(storageNamespace.quotaInBytes())
     56    , m_type(storageNamespace.storageType())
    6357{
    6458    connect();
     
    7266unsigned StorageAreaMap::length()
    7367{
    74     loadValuesIfNeeded();
    75 
    76     return m_storageMap->length();
     68    return ensureMap().length();
    7769}
    7870
    7971String StorageAreaMap::key(unsigned index)
    8072{
    81     loadValuesIfNeeded();
    82 
    83     return m_storageMap->key(index);
     73    return ensureMap().key(index);
    8474}
    8575
    8676String StorageAreaMap::item(const String& key)
    8777{
    88     loadValuesIfNeeded();
    89 
    90     return m_storageMap->getItem(key);
     78    return ensureMap().getItem(key);
    9179}
    9280
    9381void StorageAreaMap::setItem(Frame* sourceFrame, StorageAreaImpl* sourceArea, const String& key, const String& value, bool& quotaException)
    9482{
    95     loadValuesIfNeeded();
    96 
    97     ASSERT(m_storageMap->hasOneRef());
     83    auto& map = ensureMap();
     84    ASSERT(map.hasOneRef());
    9885
    9986    String oldValue;
    10087    quotaException = false;
    101     m_storageMap->setItem(key, value, oldValue, quotaException);
     88    map.setItem(key, value, oldValue, quotaException);
    10289    if (quotaException)
    10390        return;
     
    10895    m_pendingValueChanges.add(key);
    10996
    110     if (m_storageMapID)
    111         WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManagerSet::SetItem(*m_storageMapID, sourceArea->identifier(), m_currentSeed, key, value, sourceFrame->document()->url()), 0);
     97    if (m_mapID)
     98        WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManagerSet::SetItem(*m_mapID, sourceArea->identifier(), m_currentSeed, key, value, sourceFrame->document()->url()), 0);
    11299    else
    113         LOG_ERROR("StorageAreaMap::setItem fails because storage map ID is invalid");
     100        RELEASE_LOG_ERROR(Storage, "StorageAreaMap::setItem failed because storage map ID is invalid");
    114101}
    115102
    116103void StorageAreaMap::removeItem(WebCore::Frame* sourceFrame, StorageAreaImpl* sourceArea, const String& key)
    117104{
    118     loadValuesIfNeeded();
    119     ASSERT(m_storageMap->hasOneRef());
     105    auto& map = ensureMap();
     106    ASSERT(map.hasOneRef());
    120107
    121108    String oldValue;
    122     m_storageMap->removeItem(key, oldValue);
     109    map.removeItem(key, oldValue);
    123110
    124111    if (oldValue.isNull())
     
    127114    m_pendingValueChanges.add(key);
    128115
    129     if (m_storageMapID)
    130         WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManagerSet::RemoveItem(*m_storageMapID, sourceArea->identifier(), m_currentSeed, key, sourceFrame->document()->url()), 0);
     116    if (m_mapID)
     117        WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManagerSet::RemoveItem(*m_mapID, sourceArea->identifier(), m_currentSeed, key, sourceFrame->document()->url()), 0);
    131118    else
    132         LOG_ERROR("StorageAreaMap::removeItem fails because storage map ID is invalid");
     119        RELEASE_LOG_ERROR(Storage, "StorageAreaMap::removeItem failed because storage map ID is invalid");
    133120}
    134121
     
    140127
    141128    m_hasPendingClear = true;
    142     m_storageMap = StorageMap::create(m_quotaInBytes);
    143 
    144     if (m_storageMapID)
    145         WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManagerSet::Clear(*m_storageMapID, sourceArea->identifier(), m_currentSeed, sourceFrame->document()->url()), 0);
     129    m_map = StorageMap::create(m_quotaInBytes);
     130
     131    if (m_mapID)
     132        WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManagerSet::Clear(*m_mapID, sourceArea->identifier(), m_currentSeed, sourceFrame->document()->url()), 0);
    146133    else
    147         LOG_ERROR("StorageAreaMap::removeItem fails because storage map ID is invalid");
     134        RELEASE_LOG_ERROR(Storage, "StorageAreaMap::clear failed because storage map ID is invalid");
    148135}
    149136
    150137bool StorageAreaMap::contains(const String& key)
    151138{
    152     loadValuesIfNeeded();
    153 
    154     return m_storageMap->contains(key);
     139    return ensureMap().contains(key);
    155140}
    156141
    157142void StorageAreaMap::resetValues()
    158143{
    159     m_storageMap = nullptr;
     144    m_map = nullptr;
    160145
    161146    m_pendingValueChanges.clear();
    162147    m_hasPendingClear = false;
    163     m_currentSeed++;
    164 }
    165 
    166 void StorageAreaMap::loadValuesIfNeeded()
     148    ++m_currentSeed;
     149}
     150
     151StorageMap& StorageAreaMap::ensureMap()
    167152{
    168153    connect();
    169154
    170     if (m_storageMap)
    171         return;
    172 
    173     HashMap<String, String> values;
    174 
    175     if (m_storageMapID) {
    176         // The StorageManagerSet::GetValues() IPC may be very slow because it may need to fetch the values from disk and there may be a lot
    177         // of data.
    178         IPC::UnboundedSynchronousIPCScope unboundedSynchronousIPCScope;
    179         WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManagerSet::GetValues(*m_storageMapID), Messages::StorageManagerSet::GetValues::Reply(values), 0);
    180     } else
    181         LOG_ERROR("StorageAreaMap::loadValuesIfNeeded fails to load from network process because storage map ID is invalid");
    182 
    183     m_storageMap = StorageMap::create(m_quotaInBytes);
    184     m_storageMap->importItems(WTFMove(values));
    185 }
    186 
    187 void StorageAreaMap::didSetItem(uint64_t storageMapSeed, const String& key, bool quotaError)
    188 {
    189     if (m_currentSeed != storageMapSeed)
     155    if (!m_map) {
     156        m_map = StorageMap::create(m_quotaInBytes);
     157
     158        if (m_mapID) {
     159            // We need to use a IPC::UnboundedSynchronousIPCScope to prevent UIProcess hangs in case we receive a synchronous IPC from the UIProcess while we're waiting for a response
     160            // from our StorageManagerSet::GetValues() IPC. This IPC may be very slow because it may need to fetch the values from disk and there may be a lot of data.
     161            IPC::UnboundedSynchronousIPCScope unboundedSynchronousIPCScope;
     162            HashMap<String, String> values;
     163            WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManagerSet::GetValues(*m_mapID), Messages::StorageManagerSet::GetValues::Reply(values), 0);
     164            m_map->importItems(WTFMove(values));
     165        } else
     166            RELEASE_LOG_ERROR(Storage, "StorageAreaMap::ensureMap failed to load from network process because storage map ID is invalid");
     167    }
     168    return *m_map;
     169}
     170
     171void StorageAreaMap::didSetItem(uint64_t mapSeed, const String& key, bool quotaError)
     172{
     173    if (m_currentSeed != mapSeed)
    190174        return;
    191175
     
    200184}
    201185
    202 void StorageAreaMap::didRemoveItem(uint64_t storageMapSeed, const String& key)
    203 {
    204     if (m_currentSeed != storageMapSeed)
     186void StorageAreaMap::didRemoveItem(uint64_t mapSeed, const String& key)
     187{
     188    if (m_currentSeed != mapSeed)
    205189        return;
    206190
     
    209193}
    210194
    211 void StorageAreaMap::didClear(uint64_t storageMapSeed)
    212 {
    213     if (m_currentSeed != storageMapSeed)
     195void StorageAreaMap::didClear(uint64_t mapSeed)
     196{
     197    if (m_currentSeed != mapSeed)
    214198        return;
    215199
     
    221205{
    222206    // We have not yet loaded anything from this storage map.
    223     if (!m_storageMap)
     207    if (!m_map)
    224208        return false;
    225209
     
    235219void StorageAreaMap::applyChange(const String& key, const String& newValue)
    236220{
    237     ASSERT(!m_storageMap || m_storageMap->hasOneRef());
     221    ASSERT(!m_map || m_map->hasOneRef());
    238222
    239223    // There is at least one clear pending we don't want to apply any changes until we get the corresponding DidClear messages.
     
    243227    if (!key) {
    244228        // A null key means clear.
    245         auto newStorageMap = StorageMap::create(m_quotaInBytes);
     229        auto newMap = StorageMap::create(m_quotaInBytes);
    246230
    247231        // Any changes that were made locally after the clear must still be kept around in the new map.
    248         for (auto it = m_pendingValueChanges.begin().keys(), end = m_pendingValueChanges.end().keys(); it != end; ++it) {
    249             const String& key = *it;
    250 
    251             String value = m_storageMap->getItem(key);
     232        for (auto& change : m_pendingValueChanges) {
     233            auto& key = change.key;
     234            String value = m_map->getItem(key);
    252235            if (!value) {
    253236                // This change must have been a pending remove, ignore it.
     
    256239
    257240            String oldValue;
    258             newStorageMap->setItemIgnoringQuota(key, oldValue);
     241            newMap->setItemIgnoringQuota(key, oldValue);
    259242        }
    260243
    261         m_storageMap = WTFMove(newStorageMap);
     244        m_map = WTFMove(newMap);
    262245        return;
    263246    }
     
    269252        // A null new value means that the item should be removed.
    270253        String oldValue;
    271         m_storageMap->removeItem(key, oldValue);
    272         return;
    273     }
    274 
    275     m_storageMap->setItemIgnoringQuota(key, newValue);
     254        m_map->removeItem(key, oldValue);
     255        return;
     256    }
     257
     258    m_map->setItemIgnoringQuota(key, newValue);
    276259}
    277260
     
    283266    }
    284267
    285     if (storageType() == StorageType::Session)
     268    if (type() == StorageType::Session)
    286269        dispatchSessionStorageEvent(storageAreaImplID, key, oldValue, newValue, urlString);
    287270    else
     
    294277}
    295278
     279static Vector<RefPtr<Frame>> framesForEventDispatching(Page& page, SecurityOrigin& origin, const Optional<StorageAreaImplIdentifier>& storageAreaImplID)
     280{
     281    Vector<RefPtr<Frame>> frames;
     282    page.forEachDocument([&](auto& document) {
     283        if (!document.securityOrigin().equal(&origin))
     284            return;
     285       
     286        auto* storage = document.domWindow() ? document.domWindow()->optionalSessionStorage() : nullptr;
     287        if (!storage)
     288            return;
     289       
     290        auto& storageArea = static_cast<StorageAreaImpl&>(storage->area());
     291        if (storageArea.identifier() == storageAreaImplID) {
     292            // This is the storage area that caused the event to be dispatched.
     293            return;
     294        }
     295       
     296        if (auto* frame = document.frame())
     297            frames.append(frame);
     298    });
     299    return frames;
     300}
     301
    296302void StorageAreaMap::dispatchSessionStorageEvent(const Optional<StorageAreaImplIdentifier>& storageAreaImplID, const String& key, const String& oldValue, const String& newValue, const String& urlString)
    297303{
    298304    // Namespace IDs for session storage namespaces are equivalent to web page IDs
    299305    // so we can get the right page here.
    300     WebPage* webPage = WebProcess::singleton().webPage(m_storageNamespace->sessionStoragePageID());
     306    auto* webPage = WebProcess::singleton().webPage(m_namespace.sessionStoragePageID());
    301307    if (!webPage)
    302308        return;
    303309
     310    auto* page = webPage->corePage();
     311    if (!page)
     312        return;
     313
     314    auto frames = framesForEventDispatching(*page, m_securityOrigin, storageAreaImplID);
     315    StorageEventDispatcher::dispatchSessionStorageEventsToFrames(*page, frames, key, oldValue, newValue, urlString, m_securityOrigin->data());
     316}
     317
     318void StorageAreaMap::dispatchLocalStorageEvent(const Optional<StorageAreaImplIdentifier>& storageAreaImplID, const String& key, const String& oldValue, const String& newValue, const String& urlString)
     319{
     320    ASSERT(isLocalStorage(type()));
     321
    304322    Vector<RefPtr<Frame>> frames;
    305323
    306     Page* page = webPage->corePage();
    307     for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
    308         Document* document = frame->document();
    309         if (!document->securityOrigin().equal(m_securityOrigin.ptr()))
    310             continue;
    311 
    312         Storage* storage = document->domWindow()->optionalSessionStorage();
    313         if (!storage)
    314             continue;
    315 
    316         StorageAreaImpl& storageArea = static_cast<StorageAreaImpl&>(storage->area());
    317         if (storageArea.identifier() == storageAreaImplID) {
    318             // This is the storage area that caused the event to be dispatched.
    319             continue;
    320         }
    321 
    322         frames.append(frame);
    323     }
    324 
    325     StorageEventDispatcher::dispatchSessionStorageEventsToFrames(*page, frames, key, oldValue, newValue, urlString, m_securityOrigin->data());
    326 }
    327 
    328 void StorageAreaMap::dispatchLocalStorageEvent(const Optional<StorageAreaImplIdentifier>& storageAreaImplID, const String& key, const String& oldValue, const String& newValue, const String& urlString)
    329 {
    330     ASSERT(isLocalStorage(storageType()));
    331 
    332     Vector<RefPtr<Frame>> frames;
    333 
    334324    // Namespace IDs for local storage namespaces are equivalent to web page group IDs.
    335     PageGroup& pageGroup = *WebProcess::singleton().webPageGroup(m_storageNamespace->pageGroupID())->corePageGroup();
    336     const HashSet<Page*>& pages = pageGroup.pages();
    337     for (HashSet<Page*>::const_iterator it = pages.begin(), end = pages.end(); it != end; ++it) {
    338         for (Frame* frame = &(*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) {
    339             Document* document = frame->document();
    340             if (!document->securityOrigin().equal(m_securityOrigin.ptr()))
    341                 continue;
    342 
    343             Storage* storage = document->domWindow()->optionalLocalStorage();
    344             if (!storage)
    345                 continue;
    346 
    347             StorageAreaImpl& storageArea = static_cast<StorageAreaImpl&>(storage->area());
    348             if (storageArea.identifier() == storageAreaImplID) {
    349                 // This is the storage area that caused the event to be dispatched.
    350                 continue;
    351             }
    352 
    353             frames.append(frame);
    354         }
    355     }
     325    auto& pageGroup = *WebProcess::singleton().webPageGroup(m_namespace.pageGroupID())->corePageGroup();
     326    for (auto* page : pageGroup.pages())
     327        frames.appendVector(framesForEventDispatching(*page, m_securityOrigin, storageAreaImplID));
    356328
    357329    StorageEventDispatcher::dispatchLocalStorageEventsToFrames(pageGroup, frames, key, oldValue, newValue, urlString, m_securityOrigin->data());
     
    360332void StorageAreaMap::connect()
    361333{
    362     if (m_storageMapID)
    363         return;
    364 
    365     switch (m_storageType) {
     334    if (m_mapID)
     335        return;
     336
     337    switch (m_type) {
    366338    case StorageType::Local:
    367339    case StorageType::TransientLocal:
    368         if (SecurityOrigin* topLevelOrigin = m_storageNamespace->topLevelOrigin())
    369             WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManagerSet::ConnectToTransientLocalStorageArea(WebProcess::singleton().sessionID(), m_storageNamespace->storageNamespaceID(), topLevelOrigin->data(), m_securityOrigin->data()), Messages::StorageManagerSet::ConnectToTransientLocalStorageArea::Reply(m_storageMapID), 0);
     340        if (SecurityOrigin* topLevelOrigin = m_namespace.topLevelOrigin())
     341            WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManagerSet::ConnectToTransientLocalStorageArea(WebProcess::singleton().sessionID(), m_namespace.storageNamespaceID(), topLevelOrigin->data(), m_securityOrigin->data()), Messages::StorageManagerSet::ConnectToTransientLocalStorageArea::Reply(m_mapID), 0);
    370342        else
    371             WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManagerSet::ConnectToLocalStorageArea(WebProcess::singleton().sessionID(), m_storageNamespace->storageNamespaceID(), m_securityOrigin->data()), Messages::StorageManagerSet::ConnectToLocalStorageArea::Reply(m_storageMapID), 0);
     343            WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManagerSet::ConnectToLocalStorageArea(WebProcess::singleton().sessionID(), m_namespace.storageNamespaceID(), m_securityOrigin->data()), Messages::StorageManagerSet::ConnectToLocalStorageArea::Reply(m_mapID), 0);
    372344        break;
    373345    case StorageType::Session:
    374         WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManagerSet::ConnectToSessionStorageArea(WebProcess::singleton().sessionID(), m_storageNamespace->storageNamespaceID(), m_securityOrigin->data()), Messages::StorageManagerSet::ConnectToSessionStorageArea::Reply(m_storageMapID), 0);
    375     }
    376 
    377     if (m_storageMapID)
     346        WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::StorageManagerSet::ConnectToSessionStorageArea(WebProcess::singleton().sessionID(), m_namespace.storageNamespaceID(), m_securityOrigin->data()), Messages::StorageManagerSet::ConnectToSessionStorageArea::Reply(m_mapID), 0);
     347    }
     348
     349    if (m_mapID)
    378350        WebProcess::singleton().registerStorageAreaMap(*this);
    379351}
     
    381353void StorageAreaMap::disconnect()
    382354{
    383     if (!m_storageMapID)
     355    if (!m_mapID)
    384356        return;
    385357
     
    387359    WebProcess::singleton().unregisterStorageAreaMap(*this);
    388360
    389     if (auto networkProcessConnection = WebProcess::singleton().existingNetworkProcessConnection())
    390         networkProcessConnection->connection().send(Messages::StorageManagerSet::DisconnectFromStorageArea(*m_storageMapID), 0);
    391 
    392     m_storageMapID = { };
     361    if (auto* networkProcessConnection = WebProcess::singleton().existingNetworkProcessConnection())
     362        networkProcessConnection->connection().send(Messages::StorageManagerSet::DisconnectFromStorageArea(*m_mapID), 0);
     363
     364    m_mapID = { };
    393365}
    394366
  • trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.h

    r248817 r254859  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4747class StorageNamespaceImpl;
    4848
    49 class StorageAreaMap : public RefCounted<StorageAreaMap>, private IPC::MessageReceiver, public CanMakeWeakPtr<StorageAreaMap> {
     49class StorageAreaMap final : private IPC::MessageReceiver, public CanMakeWeakPtr<StorageAreaMap> {
     50    WTF_MAKE_FAST_ALLOCATED;
    5051public:
    51     static Ref<StorageAreaMap> create(StorageNamespaceImpl*, Ref<WebCore::SecurityOrigin>&&);
     52    StorageAreaMap(StorageNamespaceImpl&, Ref<WebCore::SecurityOrigin>&&);
    5253    ~StorageAreaMap();
    5354
    54     WebCore::StorageType storageType() const { return m_storageType; }
     55    WebCore::StorageType type() const { return m_type; }
    5556
    5657    unsigned length();
     
    6364
    6465    // IPC::MessageReceiver
    65     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
     66    void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
    6667
    6768    const WebCore::SecurityOrigin& securityOrigin() const { return m_securityOrigin.get(); }
     69    const Optional<StorageAreaIdentifier>& identifier() const { return m_mapID; }
    6870
    69     void connect();
    7071    void disconnect();
    71     const Optional<StorageAreaIdentifier>& identifier() const { return m_storageMapID; }
    7272
    7373private:
    74     StorageAreaMap(StorageNamespaceImpl*, Ref<WebCore::SecurityOrigin>&&);
    75 
    76     void didSetItem(uint64_t storageMapSeed, const String& key, bool quotaError);
    77     void didRemoveItem(uint64_t storageMapSeed, const String& key);
    78     void didClear(uint64_t storageMapSeed);
     74    void didSetItem(uint64_t mapSeed, const String& key, bool quotaError);
     75    void didRemoveItem(uint64_t mapSeed, const String& key);
     76    void didClear(uint64_t mapSeed);
    7977
    8078    void dispatchStorageEvent(const Optional<StorageAreaImplIdentifier>& sourceStorageAreaID, const String& key, const String& oldValue, const String& newValue, const String& urlString);
     
    8280
    8381    void resetValues();
    84     void loadValuesIfNeeded();
     82    WebCore::StorageMap& ensureMap();
    8583
    8684    bool shouldApplyChangeForKey(const String& key) const;
     
    9088    void dispatchLocalStorageEvent(const Optional<StorageAreaImplIdentifier>&, const String& key, const String& oldValue, const String& newValue, const String& urlString);
    9189
    92     StorageNamespaceImpl* m_storageNamespace;
     90    void connect();
    9391
    94     Optional<StorageAreaIdentifier> m_storageMapID;
    95 
    96     WebCore::StorageType m_storageType;
     92    StorageNamespaceImpl& m_namespace;
     93    Ref<WebCore::SecurityOrigin> m_securityOrigin;
     94    RefPtr<WebCore::StorageMap> m_map;
     95    Optional<StorageAreaIdentifier> m_mapID;
     96    HashCountedSet<String> m_pendingValueChanges;
     97    uint64_t m_currentSeed { 0 };
    9798    unsigned m_quotaInBytes;
    98     Ref<WebCore::SecurityOrigin> m_securityOrigin;
    99 
    100     RefPtr<WebCore::StorageMap> m_storageMap;
    101 
    102     uint64_t m_currentSeed;
    103     bool m_hasPendingClear;
    104     HashCountedSet<String> m_pendingValueChanges;
     99    WebCore::StorageType m_type;
     100    bool m_hasPendingClear { false };
    105101};
    106102
  • trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.messages.in

    r248817 r254859  
    2121# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2222
    23 messages -> StorageAreaMap {
     23messages -> StorageAreaMap NotRefCounted {
    2424    DidSetItem(uint64_t storageMapSeed, String key, bool quotaException)
    2525    DidRemoveItem(uint64_t storageMapSeed, String key)
  • trunk/Source/WebKit/WebProcess/WebStorage/StorageNamespaceImpl.cpp

    r250083 r254859  
    103103Ref<StorageArea> StorageNamespaceImpl::storageArea(const SecurityOriginData& securityOriginData)
    104104{
    105     RefPtr<StorageAreaMap> map;
    106 
    107     auto securityOrigin = securityOriginData.securityOrigin();
    108     auto& slot = m_storageAreaMaps.add(securityOrigin->data(), nullptr).iterator->value;
    109     if (!slot) {
    110         map = StorageAreaMap::create(this, WTFMove(securityOrigin));
    111         slot = map.get();
    112     } else
    113         map = slot;
    114 
    115     return StorageAreaImpl::create(map.releaseNonNull());
     105    auto& map = m_storageAreaMaps.ensure(securityOriginData, [&] {
     106        return makeUnique<StorageAreaMap>(*this, securityOriginData.securityOrigin());
     107    }).iterator->value;
     108    return StorageAreaImpl::create(*map);
    116109}
    117110
  • trunk/Source/WebKit/WebProcess/WebStorage/StorageNamespaceImpl.h

    r250083 r254859  
    8080    const unsigned m_quotaInBytes;
    8181
    82     HashMap<WebCore::SecurityOriginData, RefPtr<StorageAreaMap>> m_storageAreaMaps;
     82    HashMap<WebCore::SecurityOriginData, std::unique_ptr<StorageAreaMap>> m_storageAreaMaps;
    8383};
    8484
Note: See TracChangeset for help on using the changeset viewer.