Changeset 215315 in webkit


Ignore:
Timestamp:
Apr 12, 2017 11:38:19 PM (7 years ago)
Author:
beidson@apple.com
Message:

QuotaExceededError when saving to localStorage in private mode.
https://bugs.webkit.org/show_bug.cgi?id=157010

Reviewed by Alex Christensen.

Source/WebCore:

No new tests (Covered by changes to existing test).

LocalStorage in private browsing is now effectively SessionStorage.
It's ephemeral, per-tab, and copied over to tabs window.open()'ed from the current.

  • loader/EmptyClients.cpp:

(WebCore::EmptyStorageNamespaceProvider::createEphemeralLocalStorageNamespace):

  • page/Chrome.cpp:

(WebCore::Chrome::createWindow):

  • page/Page.cpp:

(WebCore::Page::ephemeralLocalStorage):
(WebCore::Page::setEphemeralLocalStorage):

  • page/Page.h:
  • page/SecurityOriginData.h:
  • storage/Storage.cpp:

(WebCore::Storage::length):
(WebCore::Storage::key):
(WebCore::Storage::getItem):
(WebCore::Storage::setItem):
(WebCore::Storage::removeItem):
(WebCore::Storage::clear):
(WebCore::Storage::contains):
(WebCore::Storage::isDisabledByPrivateBrowsing): Deleted.

  • storage/StorageMap.h:
  • storage/StorageNamespaceProvider.cpp:

(WebCore::StorageNamespaceProvider::localStorageArea):

  • storage/StorageNamespaceProvider.h:
  • storage/StorageType.h:

(WebCore::isLocalStorage):
(WebCore::isPersistentLocalStorage):

Source/WebKit:

  • Storage/StorageNamespaceImpl.cpp:

(WebKit::StorageNamespaceImpl::createEphemeralLocalStorageNamespace):
(WebKit::StorageNamespaceImpl::StorageNamespaceImpl):
(WebKit::StorageNamespaceImpl::~StorageNamespaceImpl):
(WebKit::StorageNamespaceImpl::copy):
(WebKit::StorageNamespaceImpl::close):

  • Storage/StorageNamespaceImpl.h:
  • Storage/WebStorageNamespaceProvider.cpp:

(WebKit::WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace):

  • Storage/WebStorageNamespaceProvider.h:

Source/WebKit2:

  • WebProcess/Storage/StorageAreaMap.cpp:

(WebKit::StorageAreaMap::StorageAreaMap):
(WebKit::StorageAreaMap::~StorageAreaMap):

  • WebProcess/Storage/StorageNamespaceImpl.cpp:

(WebKit::StorageNamespaceImpl::createEphemeralLocalStorageNamespace):
(WebKit::StorageNamespaceImpl::storageArea):
(WebKit::StorageNamespaceImpl::ephemeralLocalStorageArea):
(WebKit::StorageNamespaceImpl::copy):

  • WebProcess/Storage/StorageNamespaceImpl.h:
  • WebProcess/Storage/WebStorageNamespaceProvider.cpp:

(WebKit::WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace):

  • WebProcess/Storage/WebStorageNamespaceProvider.h:

LayoutTests:

  • platform/mac-wk2/TestExpectations:
  • storage/domstorage/localstorage/private-browsing-affects-storage-expected.txt:
  • storage/domstorage/localstorage/private-browsing-affects-storage.html:
  • storage/domstorage/localstorage/resources/private-browsing-1.html: Added.
  • storage/domstorage/localstorage/resources/private-browsing-2.html: Added.
  • storage/domstorage/localstorage/resources/private-browsing-3.html: Added.
  • storage/domstorage/localstorage/resources/private-browsing-storage-2.html: Added.
  • storage/domstorage/sessionstorage/private-browsing-affects-storage-expected.txt: Removed.
  • storage/domstorage/sessionstorage/private-browsing-affects-storage.html: Removed.
Location:
trunk
Files:
4 added
2 deleted
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r215312 r215315  
     12017-04-12  Brady Eidson  <beidson@apple.com>
     2
     3        QuotaExceededError when saving to localStorage in private mode.
     4        https://bugs.webkit.org/show_bug.cgi?id=157010
     5
     6        Reviewed by Alex Christensen.
     7
     8        * platform/mac-wk2/TestExpectations:
     9        * storage/domstorage/localstorage/private-browsing-affects-storage-expected.txt:
     10        * storage/domstorage/localstorage/private-browsing-affects-storage.html:
     11        * storage/domstorage/localstorage/resources/private-browsing-1.html: Added.
     12        * storage/domstorage/localstorage/resources/private-browsing-2.html: Added.
     13        * storage/domstorage/localstorage/resources/private-browsing-3.html: Added.
     14        * storage/domstorage/localstorage/resources/private-browsing-storage-2.html: Added.
     15        * storage/domstorage/sessionstorage/private-browsing-affects-storage-expected.txt: Removed.
     16        * storage/domstorage/sessionstorage/private-browsing-affects-storage.html: Removed.
     17
    1182017-04-12  Joseph Pecoraro  <pecoraro@apple.com>
    219
  • trunk/LayoutTests/platform/mac-wk2/TestExpectations

    r215263 r215315  
    425425plugins/private-browsing-mode-2.html [ Skip ]
    426426plugins/private-browsing-mode.html [ Skip ]
    427 storage/domstorage/localstorage/private-browsing-affects-storage.html [ Skip ]
    428 storage/domstorage/sessionstorage/private-browsing-affects-storage.html [ Skip ]
    429427storage/websql/private-browsing-noread-nowrite.html [ Skip ]
    430428
  • trunk/LayoutTests/storage/domstorage/localstorage/private-browsing-affects-storage-expected.txt

    r203333 r215315  
    1 This is a test to make sure that when private browsing is on any attempt to change the localStorage area fail.
    2 Initial value of testItem is: null
    3 Caught exception trying to change item: QuotaExceededError (DOM Exception 22): The quota has been exceeded.
    4 After change attempt, testItem is: null
    5 After remove attempt, testItem is: null
    6 After clear attempt, testItem is: null
     1ALERT: Persistent localStorage testItem is: Persistent item!
     2ALERT: Start of private browsing test, testItem is: null
     3ALERT: localStorage's length is: 0
     4ALERT: After set attempt, testItem is: FirstValue
     5ALERT: After second set attempt, testItem is: ChangedValue
     6ALERT: Opening window...
     7ALERT: localStorage's length is: 1
     8ALERT: The item in new window starts out as: ChangedValue
     9ALERT: The item in new window is now: NewWindowValue
     10ALERT: Back in parent window, localStorage's length is: 1
     11ALERT: Back in parent window, testItem is: ChangedValue
     12ALERT: Final window, localStorage's length is: 1
     13ALERT: Final window, item is: Persistent item!
    714
  • trunk/LayoutTests/storage/domstorage/localstorage/private-browsing-affects-storage.html

    r120516 r215315  
    33<script>
    44
    5 if (window.testRunner)
     5if (window.testRunner) {
    66    testRunner.dumpAsText();
     7    testRunner.waitUntilDone();
     8}
    79
    810function log(a)
    911{
    10     document.getElementById("logger").innerHTML += a + "<br>";
     12    alert(a + "");
    1113}
    1214
    1315function runTest()
    1416{
    15     if (!window.localStorage) {
    16         log("window.localStorage DOES NOT exist");
     17    if (!window.testRunner) {
     18        log("Test only designed to be run under DumpRenderTree or WebKitTestRunner");
    1719        return;
    1820    }
    19     if (!window.testRunner) {
    20         log("Test only designed to be run under DumpRenderTree");
    21         return;
    22     }
    23     localStorage.clear();
     21
     22    localStorage.setItem("testItem", "Persistent item!");
     23    log("Persistent localStorage testItem is: " + localStorage.getItem("testItem"));
    2424   
    25     localStorage.setItem("testItem", "InitialValue");   
    2625    testRunner.setPrivateBrowsingEnabled(true);
    27     log("Initial value of testItem is: " + localStorage.getItem("testItem"));
    28 
    29     try {
    30         localStorage.setItem("testItem", "ChangedValue");
    31     } catch(e) {
    32         log("Caught exception trying to change item: " + e);
    33     }
    34 
    35     log("After change attempt, testItem is: " + localStorage.getItem("testItem"));
     26    testRunner.setCanOpenWindows();
    3627   
    37     localStorage.removeItem("testItem");
    38     log("After remove attempt, testItem is: " + localStorage.getItem("testItem"));
    39 
    40     localStorage.clear();
    41     log("After clear attempt, testItem is: " + localStorage.getItem("testItem"));
     28    window.location.href = "resources/private-browsing-1.html"
    4229}
    4330
     
    4532</head>
    4633<body onload="runTest();">
    47 This is a test to make sure that when private browsing is on any attempt to change the localStorage area fail.
     34This is a test to make sure that when private browsing is on changes to local storage are not persistent.
    4835<div id="logger"></div>
    4936</body>
  • trunk/Source/WebCore/ChangeLog

    r215314 r215315  
     12017-04-12  Brady Eidson  <beidson@apple.com>
     2
     3        QuotaExceededError when saving to localStorage in private mode.
     4        https://bugs.webkit.org/show_bug.cgi?id=157010
     5
     6        Reviewed by Alex Christensen.
     7
     8        No new tests (Covered by changes to existing test).
     9       
     10        LocalStorage in private browsing is now effectively SessionStorage.
     11        It's ephemeral, per-tab, and copied over to tabs window.open()'ed from the current.
     12
     13        * loader/EmptyClients.cpp:
     14        (WebCore::EmptyStorageNamespaceProvider::createEphemeralLocalStorageNamespace):
     15
     16        * page/Chrome.cpp:
     17        (WebCore::Chrome::createWindow):
     18
     19        * page/Page.cpp:
     20        (WebCore::Page::ephemeralLocalStorage):
     21        (WebCore::Page::setEphemeralLocalStorage):
     22        * page/Page.h:
     23
     24        * page/SecurityOriginData.h:
     25
     26        * storage/Storage.cpp:
     27        (WebCore::Storage::length):
     28        (WebCore::Storage::key):
     29        (WebCore::Storage::getItem):
     30        (WebCore::Storage::setItem):
     31        (WebCore::Storage::removeItem):
     32        (WebCore::Storage::clear):
     33        (WebCore::Storage::contains):
     34        (WebCore::Storage::isDisabledByPrivateBrowsing): Deleted.
     35
     36        * storage/StorageMap.h:
     37
     38        * storage/StorageNamespaceProvider.cpp:
     39        (WebCore::StorageNamespaceProvider::localStorageArea):
     40        * storage/StorageNamespaceProvider.h:
     41
     42        * storage/StorageType.h:
     43        (WebCore::isLocalStorage):
     44        (WebCore::isPersistentLocalStorage):
     45
    1462017-04-12  Myles C. Maxfield  <mmaxfield@apple.com>
    247
  • trunk/Source/WebCore/loader/EmptyClients.cpp

    r214680 r215315  
    563563    RefPtr<StorageNamespace> createSessionStorageNamespace(Page&, unsigned) final;
    564564    RefPtr<StorageNamespace> createLocalStorageNamespace(unsigned) final;
     565    RefPtr<StorageNamespace> createEphemeralLocalStorageNamespace(Page&, unsigned) final;
    565566    RefPtr<StorageNamespace> createTransientLocalStorageNamespace(SecurityOrigin&, unsigned) final;
    566567};
     
    673674
    674675RefPtr<StorageNamespace> EmptyStorageNamespaceProvider::createLocalStorageNamespace(unsigned)
     676{
     677    return adoptRef(*new EmptyStorageNamespace);
     678}
     679
     680RefPtr<StorageNamespace> EmptyStorageNamespaceProvider::createEphemeralLocalStorageNamespace(Page&, unsigned)
    675681{
    676682    return adoptRef(*new EmptyStorageNamespace);
  • trunk/Source/WebCore/page/Chrome.cpp

    r211033 r215315  
    193193    if (!newPage)
    194194        return nullptr;
     195
    195196    if (auto* oldSessionStorage = m_page.sessionStorage(false))
    196197        newPage->setSessionStorage(oldSessionStorage->copy(newPage));
     198    if (auto* oldEphemeralLocalStorage = m_page.ephemeralLocalStorage(false))
     199        newPage->setEphemeralLocalStorage(oldEphemeralLocalStorage->copy(newPage));
     200
    197201    return newPage;
    198202}
  • trunk/Source/WebCore/page/Page.cpp

    r214893 r215315  
    13121312}
    13131313
     1314StorageNamespace* Page::ephemeralLocalStorage(bool optionalCreate)
     1315{
     1316    if (!m_ephemeralLocalStorage && optionalCreate)
     1317        m_ephemeralLocalStorage = m_storageNamespaceProvider->createEphemeralLocalStorageNamespace(*this, m_settings->sessionStorageQuota());
     1318
     1319    return m_ephemeralLocalStorage.get();
     1320}
     1321
     1322void Page::setEphemeralLocalStorage(RefPtr<StorageNamespace>&& newStorage)
     1323{
     1324    m_ephemeralLocalStorage = WTFMove(newStorage);
     1325}
     1326
    13141327bool Page::hasCustomHTMLTokenizerTimeDelay() const
    13151328{
  • trunk/Source/WebCore/page/Page.h

    r214893 r215315  
    415415    void setSessionStorage(RefPtr<StorageNamespace>&&);
    416416
     417    StorageNamespace* ephemeralLocalStorage(bool optionalCreate = true);
     418    void setEphemeralLocalStorage(RefPtr<StorageNamespace>&&);
     419
    417420    bool hasCustomHTMLTokenizerTimeDelay() const;
    418421    double customHTMLTokenizerTimeDelay() const;
     
    717720
    718721    RefPtr<StorageNamespace> m_sessionStorage;
     722    RefPtr<StorageNamespace> m_ephemeralLocalStorage;
    719723
    720724#if ENABLE(VIEW_MODE_CSS_MEDIA)
  • trunk/Source/WebCore/page/SecurityOriginData.h

    r208985 r215315  
    7979   
    8080#if !LOG_DISABLED
    81     String debugString() const;
     81    WEBCORE_EXPORT String debugString() const;
    8282#endif
    8383};
  • trunk/Source/WebCore/storage/Storage.cpp

    r214680 r215315  
    6464        return Exception { SECURITY_ERR };
    6565
    66     if (isDisabledByPrivateBrowsing())
    67         return 0;
    68 
    6966    return m_storageArea->length();
    7067}
     
    7471    if (!m_storageArea->canAccessStorage(m_frame))
    7572        return Exception { SECURITY_ERR };
    76 
    77     if (isDisabledByPrivateBrowsing())
    78         return String();
    7973
    8074    return m_storageArea->key(index);
     
    8680        return Exception { SECURITY_ERR };
    8781
    88     if (isDisabledByPrivateBrowsing())
    89         return String();
    90 
    9182    return m_storageArea->item(key);
    9283}
     
    9687    if (!m_storageArea->canAccessStorage(m_frame))
    9788        return Exception { SECURITY_ERR };
    98 
    99     if (isDisabledByPrivateBrowsing())
    100         return Exception { QUOTA_EXCEEDED_ERR };
    10189
    10290    bool quotaException = false;
     
    112100        return Exception { SECURITY_ERR };
    113101
    114     if (isDisabledByPrivateBrowsing())
    115         return { };
    116 
    117102    m_storageArea->removeItem(m_frame, key);
    118103    return { };
     
    123108    if (!m_storageArea->canAccessStorage(m_frame))
    124109        return Exception { SECURITY_ERR };
    125 
    126     if (isDisabledByPrivateBrowsing())
    127         return { };
    128110
    129111    m_storageArea->clear(m_frame);
     
    136118        return Exception { SECURITY_ERR };
    137119
    138     if (isDisabledByPrivateBrowsing())
    139         return false;
    140 
    141120    return m_storageArea->contains(key);
    142121}
    143122
    144 bool Storage::isDisabledByPrivateBrowsing() const
    145 {
    146     if (!m_frame->page()->usesEphemeralSession())
    147         return false;
    148 
    149     if (isLocalStorage(m_storageArea->storageType())) {
    150         if (SchemeRegistry::allowsLocalStorageAccessInPrivateBrowsing(m_frame->document()->securityOrigin().protocol()))
    151             return false;
    152     }
    153 
    154     return true;
    155 }
    156 
    157123} // namespace WebCore
  • trunk/Source/WebCore/storage/StorageMap.h

    r208844 r215315  
    5252    unsigned quota() const { return m_quotaSize; }
    5353
     54    WEBCORE_EXPORT Ref<StorageMap> copy();
     55
    5456    static const constexpr unsigned noQuota = UINT_MAX;
    5557
    5658private:
    5759    explicit StorageMap(unsigned quota);
    58     Ref<StorageMap> copy();
    5960    void invalidateIterator();
    6061    void setIteratorToIndex(unsigned);
  • trunk/Source/WebCore/storage/StorageNamespaceProvider.cpp

    r210923 r215315  
    2828
    2929#include "Document.h"
     30#include "Page.h"
    3031#include "SecurityOriginData.h"
    3132#include "StorageArea.h"
     
    6263RefPtr<StorageArea> StorageNamespaceProvider::localStorageArea(Document& document)
    6364{
    64     auto& storageNamespace = document.securityOrigin().canAccessLocalStorage(&document.topOrigin()) ? localStorageNamespace() : transientLocalStorageNamespace(document.topOrigin());
     65    // This StorageNamespaceProvider was retrieved from the Document's Page,
     66    // so the Document had better still actually have a Page.
     67    ASSERT(document.page());
    6568
    66     return storageNamespace.storageArea(SecurityOriginData::fromSecurityOrigin(document.securityOrigin()));
     69    bool ephemeral = document.page()->usesEphemeralSession();
     70    bool transient = !document.securityOrigin().canAccessLocalStorage(&document.topOrigin());
     71
     72    RefPtr<StorageNamespace> storageNamespace;
     73
     74    if (transient)
     75        storageNamespace = &transientLocalStorageNamespace(document.topOrigin());
     76    else if (ephemeral)
     77        storageNamespace = document.page()->ephemeralLocalStorage();
     78    else
     79        storageNamespace = &localStorageNamespace();
     80
     81    return storageNamespace->storageArea(SecurityOriginData::fromSecurityOrigin(document.securityOrigin()));
    6782}
    6883
  • trunk/Source/WebCore/storage/StorageNamespaceProvider.h

    r208646 r215315  
    4646
    4747    virtual RefPtr<StorageNamespace> createSessionStorageNamespace(Page&, unsigned quota) = 0;
     48    virtual RefPtr<StorageNamespace> createEphemeralLocalStorageNamespace(Page&, unsigned quota) = 0;
     49
    4850    RefPtr<StorageArea> localStorageArea(Document&);
    4951
  • trunk/Source/WebCore/storage/StorageType.h

    r214680 r215315  
    3131    Session,
    3232    Local,
     33    EphemeralLocal,
    3334    TransientLocal,
    3435};
     
    3637inline bool isLocalStorage(StorageType storageType)
    3738{
     39    return storageType == StorageType::Local || storageType == StorageType::TransientLocal || storageType == StorageType::EphemeralLocal;
     40}
     41
     42inline bool isPersistentLocalStorage(StorageType storageType)
     43{
    3844    return storageType == StorageType::Local || storageType == StorageType::TransientLocal;
    3945}
  • trunk/Source/WebKit/ChangeLog

    r215265 r215315  
     12017-04-12  Brady Eidson  <beidson@apple.com>
     2
     3        QuotaExceededError when saving to localStorage in private mode.
     4        https://bugs.webkit.org/show_bug.cgi?id=157010
     5
     6        Reviewed by Alex Christensen.
     7
     8        * Storage/StorageNamespaceImpl.cpp:
     9        (WebKit::StorageNamespaceImpl::createEphemeralLocalStorageNamespace):
     10        (WebKit::StorageNamespaceImpl::StorageNamespaceImpl):
     11        (WebKit::StorageNamespaceImpl::~StorageNamespaceImpl):
     12        (WebKit::StorageNamespaceImpl::copy):
     13        (WebKit::StorageNamespaceImpl::close):
     14        * Storage/StorageNamespaceImpl.h:
     15
     16        * Storage/WebStorageNamespaceProvider.cpp:
     17        (WebKit::WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace):
     18        * Storage/WebStorageNamespaceProvider.h:
     19
    1202017-04-12  Yusuke Suzuki  <utatane.tea@gmail.com>
    221
  • trunk/Source/WebKit/Storage/StorageNamespaceImpl.cpp

    r214680 r215315  
    5151}
    5252
     53Ref<StorageNamespaceImpl> StorageNamespaceImpl::createEphemeralLocalStorageNamespace(unsigned quota)
     54{
     55    return adoptRef(*new StorageNamespaceImpl(StorageType::EphemeralLocal, String(), quota));
     56}
     57
    5358Ref<StorageNamespaceImpl> StorageNamespaceImpl::getOrCreateLocalStorageNamespace(const String& databasePath, unsigned quota)
    5459{
     
    7277    , m_isShutdown(false)
    7378{
    74     if (isLocalStorage(m_storageType) && !m_path.isEmpty())
     79    if (isPersistentLocalStorage(m_storageType) && !m_path.isEmpty())
    7580        m_syncManager = StorageSyncManager::create(m_path);
    7681}
     
    8085    ASSERT(isMainThread());
    8186
    82     if (isLocalStorage(m_storageType)) {
     87    if (isPersistentLocalStorage(m_storageType)) {
    8388        ASSERT(localStorageNamespaceMap().get(m_path) == this);
    8489        localStorageNamespaceMap().remove(m_path);
     
    9398    ASSERT(isMainThread());
    9499    ASSERT(!m_isShutdown);
    95     ASSERT(m_storageType == StorageType::Session);
     100    ASSERT(m_storageType == StorageType::Session || m_storageType == StorageType::EphemeralLocal);
    96101
    97102    RefPtr<StorageNamespaceImpl> newNamespace = adoptRef(new StorageNamespaceImpl(m_storageType, m_path, m_quota));
     103    for (auto& iter : m_storageAreaMap)
     104        newNamespace->m_storageAreaMap.set(iter.key, iter.value->copy());
    98105
    99     StorageAreaMap::iterator end = m_storageAreaMap.end();
    100     for (StorageAreaMap::iterator i = m_storageAreaMap.begin(); i != end; ++i)
    101         newNamespace->m_storageAreaMap.set(i->key, i->value->copy());
    102106    return newNamespace;
    103107}
     
    124128        return;
    125129
    126     // If we're session storage, we shouldn't need to do any work here.
    127     if (m_storageType == StorageType::Session) {
     130    // If we're not a persistent storage, we shouldn't need to do any work here.
     131    if (m_storageType == StorageType::Session || m_storageType == StorageType::EphemeralLocal) {
    128132        ASSERT(!m_syncManager);
    129133        return;
  • trunk/Source/WebKit/Storage/StorageNamespaceImpl.h

    r208727 r215315  
    4040public:
    4141    static Ref<StorageNamespaceImpl> createSessionStorageNamespace(unsigned quota);
     42    static Ref<StorageNamespaceImpl> createEphemeralLocalStorageNamespace(unsigned quota);
    4243    static Ref<StorageNamespaceImpl> getOrCreateLocalStorageNamespace(const String& databasePath, unsigned quota);
    4344    virtual ~StorageNamespaceImpl();
  • trunk/Source/WebKit/Storage/WebStorageNamespaceProvider.cpp

    r208727 r215315  
    102102}
    103103
     104RefPtr<StorageNamespace> WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace(Page&, unsigned quota)
     105{
     106    return StorageNamespaceImpl::createEphemeralLocalStorageNamespace(quota);
     107}
     108
    104109RefPtr<StorageNamespace> WebStorageNamespaceProvider::createLocalStorageNamespace(unsigned quota)
    105110{
  • trunk/Source/WebKit/Storage/WebStorageNamespaceProvider.h

    r208727 r215315  
    5151
    5252    RefPtr<WebCore::StorageNamespace> createSessionStorageNamespace(WebCore::Page&, unsigned quota) override;
     53    RefPtr<WebCore::StorageNamespace> createEphemeralLocalStorageNamespace(WebCore::Page&, unsigned quota) override;
    5354    RefPtr<WebCore::StorageNamespace> createLocalStorageNamespace(unsigned quota) override;
    5455    RefPtr<WebCore::StorageNamespace> createTransientLocalStorageNamespace(WebCore::SecurityOrigin&, unsigned quota) override;
  • trunk/Source/WebKit2/ChangeLog

    r215313 r215315  
     12017-04-12  Brady Eidson  <beidson@apple.com>
     2
     3        QuotaExceededError when saving to localStorage in private mode.
     4        https://bugs.webkit.org/show_bug.cgi?id=157010
     5
     6        Reviewed by Alex Christensen.
     7
     8        * WebProcess/Storage/StorageAreaMap.cpp:
     9        (WebKit::StorageAreaMap::StorageAreaMap):
     10        (WebKit::StorageAreaMap::~StorageAreaMap):
     11
     12        * WebProcess/Storage/StorageNamespaceImpl.cpp:
     13        (WebKit::StorageNamespaceImpl::createEphemeralLocalStorageNamespace):
     14        (WebKit::StorageNamespaceImpl::storageArea):
     15        (WebKit::StorageNamespaceImpl::ephemeralLocalStorageArea):
     16        (WebKit::StorageNamespaceImpl::copy):
     17        * WebProcess/Storage/StorageNamespaceImpl.h:
     18
     19        * WebProcess/Storage/WebStorageNamespaceProvider.cpp:
     20        (WebKit::WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace):
     21        * WebProcess/Storage/WebStorageNamespaceProvider.h:
     22
    1232017-04-12  Yusuke Suzuki  <utatane.tea@gmail.com>
    224
  • trunk/Source/WebKit2/WebProcess/Storage/StorageAreaMap.cpp

    r214680 r215315  
    8484        WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::CreateSessionStorageMap(m_storageMapID, storageNamespace->storageNamespaceID(), SecurityOriginData::fromSecurityOrigin(m_securityOrigin)), 0);
    8585        break;
     86
     87    case StorageType::EphemeralLocal:
     88        // The UI process is not involved for EphemeralLocal storages.
     89        return;
    8690    }
    8791
     
    9195StorageAreaMap::~StorageAreaMap()
    9296{
    93     WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::DestroyStorageMap(m_storageMapID), 0);
    94     WebProcess::singleton().removeMessageReceiver(Messages::StorageAreaMap::messageReceiverName(), m_storageMapID);
     97    if (m_storageType != StorageType::EphemeralLocal) {
     98        WebProcess::singleton().parentProcessConnection()->send(Messages::StorageManager::DestroyStorageMap(m_storageMapID), 0);
     99        WebProcess::singleton().removeMessageReceiver(Messages::StorageAreaMap::messageReceiverName(), m_storageMapID);
     100    }
    95101
    96102    m_storageNamespace->didDestroyStorageAreaMap(*this);
  • trunk/Source/WebKit2/WebProcess/Storage/StorageNamespaceImpl.cpp

    r214680 r215315  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3232#include "WebPageGroupProxy.h"
    3333#include "WebProcess.h"
     34#include <WebCore/Frame.h>
    3435#include <WebCore/PageGroup.h>
    3536#include <WebCore/SecurityOrigin.h>
     
    4445{
    4546    return adoptRef(new StorageNamespaceImpl(StorageType::Session, identifier, nullptr, quotaInBytes));
     47}
     48
     49RefPtr<StorageNamespaceImpl> StorageNamespaceImpl::createEphemeralLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes)
     50{
     51    return adoptRef(new StorageNamespaceImpl(StorageType::EphemeralLocal, identifier, nullptr, quotaInBytes));
    4652}
    4753
     
    7581RefPtr<StorageArea> StorageNamespaceImpl::storageArea(const SecurityOriginData& securityOrigin)
    7682{
     83    if (m_storageType == StorageType::EphemeralLocal)
     84        return ephemeralLocalStorageArea(securityOrigin);
     85
    7786    RefPtr<StorageAreaMap> map;
    7887
     
    8796}
    8897
     98class StorageNamespaceImpl::EphemeralStorageArea final : public StorageArea {
     99public:
     100    static Ref<EphemeralStorageArea> create(const SecurityOriginData& origin, unsigned quotaInBytes)
     101    {
     102        return adoptRef(*new EphemeralStorageArea(origin, quotaInBytes));
     103    }
     104
     105    Ref<EphemeralStorageArea> copy()
     106    {
     107        return adoptRef(*new EphemeralStorageArea(*this));
     108    }
     109
     110private:
     111    EphemeralStorageArea(const SecurityOriginData& origin, unsigned quotaInBytes)
     112        : m_securityOriginData(origin)
     113        , m_storageMap(StorageMap::create(quotaInBytes))
     114    {
     115    }
     116
     117    EphemeralStorageArea(EphemeralStorageArea& other)
     118        : m_securityOriginData(other.m_securityOriginData)
     119        , m_storageMap(other.m_storageMap)
     120    {
     121    }
     122
     123    // WebCore::StorageArea.
     124    unsigned length()
     125    {
     126        return m_storageMap->length();
     127    }
     128
     129    String key(unsigned index)
     130    {
     131        return m_storageMap->key(index);
     132    }
     133
     134    String item(const String& key)
     135    {
     136        return m_storageMap->getItem(key);
     137    }
     138
     139    void setItem(Frame*, const String& key, const String& value, bool& quotaException)
     140    {
     141        String oldValue;
     142        if (auto newMap = m_storageMap->setItem(key, value, oldValue, quotaException))
     143            m_storageMap = WTFMove(newMap);
     144    }
     145
     146    void removeItem(Frame*, const String& key)
     147    {
     148        String oldValue;
     149        if (auto newMap = m_storageMap->removeItem(key, oldValue))
     150            m_storageMap = WTFMove(newMap);
     151    }
     152
     153    void clear(Frame*)
     154    {
     155        if (!m_storageMap->length())
     156            return;
     157
     158        m_storageMap = StorageMap::create(m_storageMap->quota());
     159    }
     160
     161    bool contains(const String& key)
     162    {
     163        return m_storageMap->contains(key);
     164    }
     165
     166    bool canAccessStorage(Frame* frame)
     167    {
     168        return frame && frame->page();
     169    }
     170
     171    StorageType storageType() const
     172    {
     173        return StorageType::EphemeralLocal;
     174    }
     175
     176    size_t memoryBytesUsedByCache()
     177    {
     178        return 0;
     179    }
     180
     181    void incrementAccessCount() { }
     182    void decrementAccessCount() { }
     183    void closeDatabaseIfIdle() { }
     184
     185    SecurityOriginData securityOrigin() const
     186    {
     187        return m_securityOriginData;
     188    }
     189
     190    SecurityOriginData m_securityOriginData;
     191    RefPtr<StorageMap> m_storageMap;
     192};
     193
     194RefPtr<StorageArea> StorageNamespaceImpl::ephemeralLocalStorageArea(const SecurityOriginData& securityOrigin)
     195{
     196    auto& slot = m_ephemeralLocalStorageAreas.add(securityOrigin, nullptr).iterator->value;
     197    if (!slot)
     198        slot = StorageNamespaceImpl::EphemeralStorageArea::create(securityOrigin, m_quotaInBytes);
     199
     200    return slot.get();
     201}
     202
    89203RefPtr<StorageNamespace> StorageNamespaceImpl::copy(Page* newPage)
    90204{
    91205    ASSERT(m_storageNamespaceID);
    92206
    93     return createSessionStorageNamespace(WebPage::fromCorePage(newPage)->pageID(), m_quotaInBytes);
     207    if (m_storageType == StorageType::Session)
     208        return createSessionStorageNamespace(WebPage::fromCorePage(newPage)->pageID(), m_quotaInBytes);
     209
     210    ASSERT(m_storageType == StorageType::EphemeralLocal);
     211    RefPtr<StorageNamespaceImpl> newNamespace = adoptRef(new StorageNamespaceImpl(m_storageType, m_storageNamespaceID, m_topLevelOrigin.get(), m_quotaInBytes));
     212
     213    for (auto& iter : m_ephemeralLocalStorageAreas)
     214        newNamespace->m_ephemeralLocalStorageAreas.set(iter.key, iter.value->copy());
     215
     216    return newNamespace;
    94217}
    95218
  • trunk/Source/WebKit2/WebProcess/Storage/StorageNamespaceImpl.h

    r208727 r215315  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929#include <WebCore/SecurityOriginHash.h>
    3030#include <WebCore/StorageArea.h>
     31#include <WebCore/StorageMap.h>
    3132#include <WebCore/StorageNamespace.h>
    3233#include <wtf/HashMap.h>
     
    4041public:
    4142    static RefPtr<StorageNamespaceImpl> createSessionStorageNamespace(uint64_t identifier, unsigned quotaInBytes);
     43    static RefPtr<StorageNamespaceImpl> createEphemeralLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes);
    4244    static RefPtr<StorageNamespaceImpl> createLocalStorageNamespace(uint64_t identifier, unsigned quotaInBytes);
    4345    static RefPtr<StorageNamespaceImpl> createTransientLocalStorageNamespace(uint64_t identifier, WebCore::SecurityOrigin& topLevelOrigin, uint64_t quotaInBytes);
     
    5860    RefPtr<WebCore::StorageNamespace> copy(WebCore::Page*) override;
    5961
     62    RefPtr<WebCore::StorageArea> ephemeralLocalStorageArea(const WebCore::SecurityOriginData&);
     63
    6064    const WebCore::StorageType m_storageType;
    6165    const uint64_t m_storageNamespaceID;
     
    6771
    6872    HashMap<WebCore::SecurityOriginData, StorageAreaMap*> m_storageAreaMaps;
     73
     74    class EphemeralStorageArea;
     75    HashMap<WebCore::SecurityOriginData, RefPtr<EphemeralStorageArea>> m_ephemeralLocalStorageAreas;
    6976};
    7077
  • trunk/Source/WebKit2/WebProcess/Storage/WebStorageNamespaceProvider.cpp

    r177810 r215315  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    7272}
    7373
     74RefPtr<WebCore::StorageNamespace> WebStorageNamespaceProvider::createEphemeralLocalStorageNamespace(Page& page, unsigned quota)
     75{
     76    return StorageNamespaceImpl::createEphemeralLocalStorageNamespace(WebPage::fromCorePage(&page)->pageID(), quota);
     77}
     78
    7479RefPtr<WebCore::StorageNamespace> WebStorageNamespaceProvider::createLocalStorageNamespace(unsigned quota)
    7580{
  • trunk/Source/WebKit2/WebProcess/Storage/WebStorageNamespaceProvider.h

    r197563 r215315  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4040
    4141    RefPtr<WebCore::StorageNamespace> createSessionStorageNamespace(WebCore::Page&, unsigned quota) override;
     42    RefPtr<WebCore::StorageNamespace> createEphemeralLocalStorageNamespace(WebCore::Page&, unsigned quota) override;
    4243    RefPtr<WebCore::StorageNamespace> createLocalStorageNamespace(unsigned quota) override;
    4344    RefPtr<WebCore::StorageNamespace> createTransientLocalStorageNamespace(WebCore::SecurityOrigin&, unsigned quota) override;
Note: See TracChangeset for help on using the changeset viewer.