Changeset 247104 in webkit


Ignore:
Timestamp:
Jul 3, 2019 2:16:43 PM (5 years ago)
Author:
youenn@apple.com
Message:

Strengthen updating/removing of registrations from the database
https://bugs.webkit.org/show_bug.cgi?id=199450
rdar://problem/51891395

Reviewed by Chris Dumez.

SWServerWorker is ref counted and has a ref to its SWServer.
There is thus a possibility for SWServerWorker to live longer than its SWServer.
To mitigate this, have SWServerWorker use a WeakPtr<SWServer> and
check whether SWServer is null when receiving messages from WebProcess.
Make also sure that RegistrationStore updated registration map does not get corrupted by checking
the registration keys explicitly.

Covered by existing tests.

  • workers/service/ServiceWorkerRegistrationKey.h:

(WebCore::ServiceWorkerRegistrationKey::operator!= const):
(WebCore::ServiceWorkerRegistrationKey::isEmpty const):

  • workers/service/server/RegistrationStore.cpp:

(WebCore::RegistrationStore::updateRegistration):
(WebCore::RegistrationStore::removeRegistration):
(WebCore::RegistrationStore::addRegistrationFromDatabase):

  • workers/service/server/RegistrationStore.h:
  • workers/service/server/SWServer.cpp:

(WebCore::SWServer::workerByID const):
(WebCore::SWServer::removeRegistration):

  • workers/service/server/SWServer.h:
  • workers/service/server/SWServerWorker.cpp:

(WebCore::SWServerWorker::SWServerWorker):
(WebCore::m_scriptResourceMap):
(WebCore::SWServerWorker::contextData const):
(WebCore::SWServerWorker::terminate):
(WebCore::SWServerWorker::scriptContextFailedToStart):
(WebCore::SWServerWorker::scriptContextStarted):
(WebCore::SWServerWorker::didFinishInstall):
(WebCore::SWServerWorker::didFinishActivation):
(WebCore::SWServerWorker::contextTerminated):
(WebCore::SWServerWorker::findClientByIdentifier const):
(WebCore::SWServerWorker::matchAll):
(WebCore::SWServerWorker::userAgent const):
(WebCore::SWServerWorker::claim):
(WebCore::SWServerWorker::skipWaiting):
(WebCore::SWServerWorker::setHasPendingEvents):
(WebCore::SWServerWorker::setState):

  • workers/service/server/SWServerWorker.h:

(WebCore::SWServerWorker::server):

Location:
trunk/Source/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r247102 r247104  
     12019-07-03  Youenn Fablet  <youenn@apple.com>
     2
     3        Strengthen updating/removing of registrations from the database
     4        https://bugs.webkit.org/show_bug.cgi?id=199450
     5        rdar://problem/51891395
     6
     7        Reviewed by Chris Dumez.
     8
     9        SWServerWorker is ref counted and has a ref to its SWServer.
     10        There is thus a possibility for SWServerWorker to live longer than its SWServer.
     11        To mitigate this, have SWServerWorker use a WeakPtr<SWServer> and
     12        check whether SWServer is null when receiving messages from WebProcess.
     13        Make also sure that RegistrationStore updated registration map does not get corrupted by checking
     14        the registration keys explicitly.
     15
     16        Covered by existing tests.
     17
     18        * workers/service/ServiceWorkerRegistrationKey.h:
     19        (WebCore::ServiceWorkerRegistrationKey::operator!= const):
     20        (WebCore::ServiceWorkerRegistrationKey::isEmpty const):
     21        * workers/service/server/RegistrationStore.cpp:
     22        (WebCore::RegistrationStore::updateRegistration):
     23        (WebCore::RegistrationStore::removeRegistration):
     24        (WebCore::RegistrationStore::addRegistrationFromDatabase):
     25        * workers/service/server/RegistrationStore.h:
     26        * workers/service/server/SWServer.cpp:
     27        (WebCore::SWServer::workerByID const):
     28        (WebCore::SWServer::removeRegistration):
     29        * workers/service/server/SWServer.h:
     30        * workers/service/server/SWServerWorker.cpp:
     31        (WebCore::SWServerWorker::SWServerWorker):
     32        (WebCore::m_scriptResourceMap):
     33        (WebCore::SWServerWorker::contextData const):
     34        (WebCore::SWServerWorker::terminate):
     35        (WebCore::SWServerWorker::scriptContextFailedToStart):
     36        (WebCore::SWServerWorker::scriptContextStarted):
     37        (WebCore::SWServerWorker::didFinishInstall):
     38        (WebCore::SWServerWorker::didFinishActivation):
     39        (WebCore::SWServerWorker::contextTerminated):
     40        (WebCore::SWServerWorker::findClientByIdentifier const):
     41        (WebCore::SWServerWorker::matchAll):
     42        (WebCore::SWServerWorker::userAgent const):
     43        (WebCore::SWServerWorker::claim):
     44        (WebCore::SWServerWorker::skipWaiting):
     45        (WebCore::SWServerWorker::setHasPendingEvents):
     46        (WebCore::SWServerWorker::setState):
     47        * workers/service/server/SWServerWorker.h:
     48        (WebCore::SWServerWorker::server):
     49
    1502019-07-03  Sam Weinig  <weinig@apple.com>
    251
  • trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.h

    r239427 r247104  
    4242
    4343    bool operator==(const ServiceWorkerRegistrationKey&) const;
     44    bool operator!=(const ServiceWorkerRegistrationKey& key) const { return !(*this == key); }
     45    bool isEmpty() const { return *this == emptyKey(); }
    4446    WEBCORE_EXPORT bool isMatching(const SecurityOriginData& topOrigin, const URL& clientURL) const;
    4547    bool originIsMatching(const SecurityOriginData& topOrigin, const URL& clientURL) const;
  • trunk/Source/WebCore/workers/service/server/RegistrationStore.cpp

    r246184 r247104  
    105105void RegistrationStore::updateRegistration(const ServiceWorkerContextData& data)
    106106{
     107    ASSERT(isMainThread());
     108    ASSERT(!data.registration.key.isEmpty());
     109    if (data.registration.key.isEmpty())
     110        return;
     111
    107112    m_updatedRegistrations.set(data.registration.key, data);
    108113    scheduleDatabasePushIfNecessary();
    109114}
    110115
    111 void RegistrationStore::removeRegistration(SWServerRegistration& registration)
     116void RegistrationStore::removeRegistration(const ServiceWorkerRegistrationKey& key)
    112117{
     118    ASSERT(isMainThread());
     119    ASSERT(!key.isEmpty());
     120    if (key.isEmpty())
     121        return;
     122
    113123    ServiceWorkerContextData contextData;
    114     contextData.registration.key = registration.key();
    115     m_updatedRegistrations.set(registration.key(), WTFMove(contextData));
     124    contextData.registration.key = key;
     125    m_updatedRegistrations.set(key, WTFMove(contextData));
    116126    scheduleDatabasePushIfNecessary();
    117127}
    118128
    119 void RegistrationStore::addRegistrationFromDatabase(ServiceWorkerContextData&& context)
     129void RegistrationStore::addRegistrationFromDatabase(ServiceWorkerContextData&& data)
    120130{
    121     m_server.addRegistrationFromStore(WTFMove(context));
     131    ASSERT(!data.registration.key.isEmpty());
     132    if (data.registration.key.isEmpty())
     133        return;
     134
     135    m_server.addRegistrationFromStore(WTFMove(data));
    122136}
    123137
  • trunk/Source/WebCore/workers/service/server/RegistrationStore.h

    r246184 r247104  
    5858    // Callbacks from the SWServer
    5959    void updateRegistration(const ServiceWorkerContextData&);
    60     void removeRegistration(SWServerRegistration&);
     60    void removeRegistration(const ServiceWorkerRegistrationKey&);
    6161
    6262    // Callbacks from the database
  • trunk/Source/WebCore/workers/service/server/SWServer.cpp

    r246184 r247104  
    8484{
    8585    auto* worker = SWServerWorker::existingWorkerForIdentifier(identifier);
    86     ASSERT(!worker || &worker->server() == this);
     86    ASSERT(!worker || worker->server() == this);
    8787    return worker;
    8888}
     
    178178    m_originStore->remove(topOrigin);
    179179    if (m_registrationStore)
    180         m_registrationStore->removeRegistration(*registration);
     180        m_registrationStore->removeRegistration(key);
    181181}
    182182
  • trunk/Source/WebCore/workers/service/server/SWServer.h

    r246184 r247104  
    6363class Timer;
    6464
    65 class SWServer {
     65class SWServer : public CanMakeWeakPtr<SWServer> {
    6666    WTF_MAKE_FAST_ALLOCATED;
    6767public:
  • trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp

    r244115 r247104  
    4949// FIXME: Use r-value references for script and contentSecurityPolicy
    5050SWServerWorker::SWServerWorker(SWServer& server, SWServerRegistration& registration, const URL& scriptURL, const String& script, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicy, String&& referrerPolicy, WorkerType type, ServiceWorkerIdentifier identifier, HashMap<URL, ServiceWorkerContextData::ImportedScript>&& scriptResourceMap)
    51     : m_server(server)
     51    : m_server(makeWeakPtr(server))
    5252    , m_registrationKey(registration.key())
    5353    , m_data { identifier, scriptURL, ServiceWorkerState::Redundant, type, registration.identifier() }
     
    6363    ASSERT_UNUSED(result, result.isNewEntry);
    6464
    65     ASSERT(m_server.getRegistration(m_registrationKey));
     65    ASSERT(m_server->getRegistration(m_registrationKey));
    6666}
    6767
     
    7676ServiceWorkerContextData SWServerWorker::contextData() const
    7777{
    78     auto* registration = m_server.getRegistration(m_registrationKey);
     78    auto* registration = m_server->getRegistration(m_registrationKey);
    7979    ASSERT(registration);
    8080
    81     return { WTF::nullopt, registration->data(), m_data.identifier, m_script, m_contentSecurityPolicy, m_referrerPolicy, m_data.scriptURL, m_data.type, m_server.sessionID(), false, m_scriptResourceMap };
     81    return { WTF::nullopt, registration->data(), m_data.identifier, m_script, m_contentSecurityPolicy, m_referrerPolicy, m_data.scriptURL, m_data.type, m_server->sessionID(), false, m_scriptResourceMap };
    8282}
    8383
     
    8585{
    8686    if (isRunning())
    87         m_server.terminateWorker(*this);
     87        m_server->terminateWorker(*this);
    8888}
    8989
     
    103103void SWServerWorker::scriptContextFailedToStart(const Optional<ServiceWorkerJobDataIdentifier>& jobDataIdentifier, const String& message)
    104104{
    105     m_server.scriptContextFailedToStart(jobDataIdentifier, *this, message);
     105    ASSERT(m_server);
     106    if (m_server)
     107        m_server->scriptContextFailedToStart(jobDataIdentifier, *this, message);
    106108}
    107109
    108110void SWServerWorker::scriptContextStarted(const Optional<ServiceWorkerJobDataIdentifier>& jobDataIdentifier)
    109111{
    110     m_server.scriptContextStarted(jobDataIdentifier, *this);
     112    ASSERT(m_server);
     113    if (m_server)
     114        m_server->scriptContextStarted(jobDataIdentifier, *this);
    111115}
    112116
    113117void SWServerWorker::didFinishInstall(const Optional<ServiceWorkerJobDataIdentifier>& jobDataIdentifier, bool wasSuccessful)
    114118{
    115     m_server.didFinishInstall(jobDataIdentifier, *this, wasSuccessful);
     119    ASSERT(m_server);
     120    if (m_server)
     121        m_server->didFinishInstall(jobDataIdentifier, *this, wasSuccessful);
    116122}
    117123
    118124void SWServerWorker::didFinishActivation()
    119125{
    120     m_server.didFinishActivation(*this);
     126    ASSERT(m_server);
     127    if (m_server)
     128        m_server->didFinishActivation(*this);
    121129}
    122130
    123131void SWServerWorker::contextTerminated()
    124132{
    125     m_server.workerContextTerminated(*this);
     133    ASSERT(m_server);
     134    if (m_server)
     135        m_server->workerContextTerminated(*this);
    126136}
    127137
    128138Optional<ServiceWorkerClientData> SWServerWorker::findClientByIdentifier(const ServiceWorkerClientIdentifier& clientId) const
    129139{
    130     return m_server.serviceWorkerClientWithOriginByID(origin(), clientId);
     140    ASSERT(m_server);
     141    if (!m_server)
     142        return { };
     143    return m_server->serviceWorkerClientWithOriginByID(origin(), clientId);
    131144}
    132145
    133146void SWServerWorker::matchAll(const ServiceWorkerClientQueryOptions& options, ServiceWorkerClientsMatchAllCallback&& callback)
    134147{
    135     return m_server.matchAll(*this, options, WTFMove(callback));
     148    ASSERT(m_server);
     149    if (!m_server)
     150        return callback({ });
     151    return m_server->matchAll(*this, options, WTFMove(callback));
    136152}
    137153
    138154String SWServerWorker::userAgent() const
    139155{
    140     return m_server.serviceWorkerClientUserAgent(origin());
     156    ASSERT(m_server);
     157    if (!m_server)
     158        return { };
     159    return m_server->serviceWorkerClientUserAgent(origin());
    141160}
    142161
    143162void SWServerWorker::claim()
    144163{
    145     return m_server.claim(*this);
     164    ASSERT(m_server);
     165    if (m_server)
     166        m_server->claim(*this);
    146167}
    147168
     
    155176    m_isSkipWaitingFlagSet = true;
    156177
    157     auto* registration = m_server.getRegistration(m_registrationKey);
     178    auto* registration = m_server->getRegistration(m_registrationKey);
    158179    ASSERT(registration || isTerminating());
    159180    if (registration)
     
    171192
    172193    // Do tryClear/tryActivate, as per https://w3c.github.io/ServiceWorker/#wait-until-method.
    173     auto* registration = m_server.getRegistration(m_registrationKey);
     194    auto* registration = m_server->getRegistration(m_registrationKey);
    174195    if (!registration)
    175196        return;
     
    196217    m_data.state = state;
    197218
    198     auto* registration = m_server.getRegistration(m_registrationKey);
     219    auto* registration = m_server->getRegistration(m_registrationKey);
    199220    ASSERT(registration || state == ServiceWorkerState::Redundant);
    200221    if (registration) {
     
    217238void SWServerWorker::setState(State state)
    218239{
    219     ASSERT(state != State::Running || m_server.getRegistration(m_registrationKey));
     240    ASSERT(state != State::Running || m_server->getRegistration(m_registrationKey));
    220241    m_state = state;
    221242}
  • trunk/Source/WebCore/workers/service/server/SWServerWorker.h

    r244115 r247104  
    7474    void setState(State);
    7575
    76     SWServer& server() { return m_server; }
     76    SWServer* server() { return m_server.get(); }
    7777    const ServiceWorkerRegistrationKey& registrationKey() const { return m_registrationKey; }
    7878    const URL& scriptURL() const { return m_data.scriptURL; }
     
    118118    void callWhenActivatedHandler(bool success);
    119119
    120     SWServer& m_server;
     120    WeakPtr<SWServer> m_server;
    121121    ServiceWorkerRegistrationKey m_registrationKey;
    122122    ServiceWorkerData m_data;
Note: See TracChangeset for help on using the changeset viewer.