109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// found in the LICENSE file.
409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "config.h"
609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/dom/custom/CustomElementMicrotaskDispatcher.h"
709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/dom/Microtask.h"
909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/dom/custom/CustomElementCallbackQueue.h"
1009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/dom/custom/CustomElementMicrotaskImportStep.h"
117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/dom/custom/CustomElementProcessingStack.h"
1209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/dom/custom/CustomElementScheduler.h"
1309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "wtf/MainThread.h"
1409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
15c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
1609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static const CustomElementCallbackQueue::ElementQueueId kMicrotaskQueueId = 0;
1809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)CustomElementMicrotaskDispatcher::CustomElementMicrotaskDispatcher()
2009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    : m_hasScheduledMicrotask(false)
2109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , m_phase(Quiescent)
2209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
2309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
2409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
25d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CustomElementMicrotaskDispatcher)
26d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
2709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)CustomElementMicrotaskDispatcher& CustomElementMicrotaskDispatcher::instance()
2809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
29d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<CustomElementMicrotaskDispatcher>, instance, (adoptPtrWillBeNoop(new CustomElementMicrotaskDispatcher())));
30d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    return *instance;
3109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
3209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
3309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void CustomElementMicrotaskDispatcher::enqueue(CustomElementCallbackQueue* queue)
3409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
35f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ensureMicrotaskScheduledForElementQueue();
3609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    queue->setOwner(kMicrotaskQueueId);
3709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_elements.append(queue);
3809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
3909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
40f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduledForElementQueue()
41f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
42f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(m_phase == Quiescent || m_phase == Resolving);
43f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ensureMicrotaskScheduled();
44f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
45f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduled()
4709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!m_hasScheduledMicrotask) {
4910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        Microtask::enqueueMicrotask(WTF::bind(&dispatch));
5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_hasScheduledMicrotask = true;
5109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
5209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void CustomElementMicrotaskDispatcher::dispatch()
5509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
5609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    instance().doDispatch();
5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
5809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
5909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void CustomElementMicrotaskDispatcher::doDispatch()
6009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
6109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(isMainThread());
6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(m_phase == Quiescent && m_hasScheduledMicrotask);
6409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_hasScheduledMicrotask = false;
6509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Finishing microtask work deletes all
6709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // CustomElementCallbackQueues. Being in a callback delivery scope
6809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // implies those queues could still be in use.
697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT_WITH_SECURITY_IMPLICATION(!CustomElementProcessingStack::inCallbackDeliveryScope());
7009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
7109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_phase = Resolving;
7209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_phase = DispatchingCallbacks;
74d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    for (WillBeHeapVector<RawPtrWillBeMember<CustomElementCallbackQueue> >::iterator it = m_elements.begin(); it != m_elements.end(); ++it) {
7509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // Created callback may enqueue an attached callback.
767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        CustomElementProcessingStack::CallbackDeliveryScope scope;
7709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        (*it)->processInElementQueue(kMicrotaskQueueId);
7809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
7909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
8009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_elements.clear();
8109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    CustomElementScheduler::microtaskDispatcherDidFinish();
8209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_phase = Quiescent;
8309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
8409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
85d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void CustomElementMicrotaskDispatcher::trace(Visitor* visitor)
86d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
87d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#if ENABLE(OILPAN)
88d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    visitor->trace(m_elements);
89d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#endif
90d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
91d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
92c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
93