Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / custom / CustomElementMicrotaskDispatcher.cpp
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "core/dom/custom/CustomElementMicrotaskDispatcher.h"
7
8 #include "core/dom/Microtask.h"
9 #include "core/dom/custom/CustomElementCallbackDispatcher.h"
10 #include "core/dom/custom/CustomElementCallbackQueue.h"
11 #include "core/dom/custom/CustomElementMicrotaskImportStep.h"
12 #include "core/dom/custom/CustomElementMicrotaskQueue.h"
13 #include "core/dom/custom/CustomElementScheduler.h"
14 #include "core/html/imports/HTMLImportLoader.h"
15 #include "wtf/MainThread.h"
16
17 namespace WebCore {
18
19 static const CustomElementCallbackQueue::ElementQueueId kMicrotaskQueueId = 0;
20
21 CustomElementMicrotaskDispatcher::CustomElementMicrotaskDispatcher()
22     : m_hasScheduledMicrotask(false)
23     , m_phase(Quiescent)
24     , m_resolutionAndImports(CustomElementMicrotaskQueue::create())
25 {
26 }
27
28 CustomElementMicrotaskDispatcher& CustomElementMicrotaskDispatcher::instance()
29 {
30     DEFINE_STATIC_LOCAL(CustomElementMicrotaskDispatcher, instance, ());
31     return instance;
32 }
33
34 void CustomElementMicrotaskDispatcher::enqueue(HTMLImportLoader* importLoader, PassOwnPtr<CustomElementMicrotaskStep> step)
35 {
36     ASSERT(m_phase == Quiescent || m_phase == DispatchingCallbacks);
37     ensureMicrotaskScheduled();
38     if (importLoader)
39         importLoader->microtaskQueue()->enqueue(step);
40     else
41         m_resolutionAndImports->enqueue(step);
42 }
43
44 void CustomElementMicrotaskDispatcher::enqueue(CustomElementCallbackQueue* queue)
45 {
46     ASSERT(m_phase == Quiescent || m_phase == Resolving);
47     ensureMicrotaskScheduled();
48     queue->setOwner(kMicrotaskQueueId);
49     m_elements.append(queue);
50 }
51
52 void CustomElementMicrotaskDispatcher::importDidFinish(CustomElementMicrotaskImportStep* step)
53 {
54     ASSERT(m_phase == Quiescent || m_phase == DispatchingCallbacks);
55     ensureMicrotaskScheduled();
56 }
57
58 void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduled()
59 {
60     if (!m_hasScheduledMicrotask) {
61         Microtask::enqueueMicrotask(WTF::bind(&dispatch));
62         m_hasScheduledMicrotask = true;
63     }
64 }
65
66 void CustomElementMicrotaskDispatcher::dispatch()
67 {
68     instance().doDispatch();
69 }
70
71 void CustomElementMicrotaskDispatcher::doDispatch()
72 {
73     ASSERT(isMainThread());
74
75     ASSERT(m_phase == Quiescent && m_hasScheduledMicrotask);
76     m_hasScheduledMicrotask = false;
77
78     // Finishing microtask work deletes all
79     // CustomElementCallbackQueues. Being in a callback delivery scope
80     // implies those queues could still be in use.
81     ASSERT_WITH_SECURITY_IMPLICATION(!CustomElementCallbackDispatcher::inCallbackDeliveryScope());
82
83     m_phase = Resolving;
84     m_resolutionAndImports->dispatch();
85
86     m_phase = DispatchingCallbacks;
87     for (Vector<CustomElementCallbackQueue*>::iterator it = m_elements.begin();it != m_elements.end(); ++it) {
88         // Created callback may enqueue an attached callback.
89         CustomElementCallbackDispatcher::CallbackDeliveryScope scope;
90         (*it)->processInElementQueue(kMicrotaskQueueId);
91     }
92
93     m_elements.clear();
94     CustomElementScheduler::microtaskDispatcherDidFinish();
95     m_phase = Quiescent;
96 }
97
98 #if !defined(NDEBUG)
99 void CustomElementMicrotaskDispatcher::show()
100 {
101     fprintf(stderr, "Dispatcher:\n");
102     m_resolutionAndImports->show(1);
103 }
104 #endif
105
106 } // namespace WebCore
107
108 #if !defined(NDEBUG)
109 void showCEMD()
110 {
111     WebCore::CustomElementMicrotaskDispatcher::instance().show();
112 }
113 #endif