OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/compositorworker/CompositorWorkerThread.h" | 5 #include "modules/compositorworker/AnimationWorkletThread.h" |
6 | 6 |
7 #include "bindings/core/v8/ScriptSourceCode.h" | 7 #include "bindings/core/v8/ScriptSourceCode.h" |
8 #include "bindings/core/v8/SourceLocation.h" | 8 #include "bindings/core/v8/SourceLocation.h" |
9 #include "bindings/core/v8/V8GCController.h" | 9 #include "bindings/core/v8/V8GCController.h" |
10 #include "bindings/core/v8/WorkerOrWorkletScriptController.h" | 10 #include "bindings/core/v8/WorkerOrWorkletScriptController.h" |
11 #include "core/dom/CompositorProxyClient.h" | |
12 #include "core/inspector/ConsoleMessage.h" | 11 #include "core/inspector/ConsoleMessage.h" |
13 #include "core/testing/DummyPageHolder.h" | |
14 #include "core/workers/InProcessWorkerObjectProxy.h" | 12 #include "core/workers/InProcessWorkerObjectProxy.h" |
15 #include "core/workers/WorkerBackingThread.h" | 13 #include "core/workers/WorkerBackingThread.h" |
16 #include "core/workers/WorkerLoaderProxy.h" | 14 #include "core/workers/WorkerLoaderProxy.h" |
17 #include "core/workers/WorkerOrWorkletGlobalScope.h" | 15 #include "core/workers/WorkerOrWorkletGlobalScope.h" |
18 #include "core/workers/WorkerThreadStartupData.h" | 16 #include "core/workers/WorkerThreadStartupData.h" |
19 #include "platform/CrossThreadFunctional.h" | 17 #include "platform/CrossThreadFunctional.h" |
20 #include "platform/WaitableEvent.h" | 18 #include "platform/WaitableEvent.h" |
21 #include "platform/WebThreadSupportingGC.h" | 19 #include "platform/WebThreadSupportingGC.h" |
22 #include "platform/heap/Handle.h" | 20 #include "platform/heap/Handle.h" |
23 #include "platform/testing/TestingPlatformSupport.h" | 21 #include "platform/testing/TestingPlatformSupport.h" |
24 #include "platform/testing/UnitTestHelpers.h" | 22 #include "platform/testing/UnitTestHelpers.h" |
25 #include "public/platform/Platform.h" | 23 #include "public/platform/Platform.h" |
26 #include "public/platform/WebAddressSpace.h" | 24 #include "public/platform/WebAddressSpace.h" |
27 #include "testing/gtest/include/gtest/gtest.h" | 25 #include "testing/gtest/include/gtest/gtest.h" |
28 #include "wtf/PtrUtil.h" | 26 #include "wtf/PtrUtil.h" |
29 #include <memory> | 27 #include <memory> |
30 | 28 |
31 namespace blink { | 29 namespace blink { |
32 namespace { | 30 namespace { |
33 | 31 |
34 // A null InProcessWorkerObjectProxy, supplied when creating CompositorWorkerThr eads. | 32 // A null WorkerReportingProxy, supplied when creating AnimationWorkletThreads. |
35 class TestCompositorWorkerObjectProxy : public InProcessWorkerObjectProxy { | 33 class TestAnimationWorkletReportingProxy : public WorkerReportingProxy { |
36 public: | 34 public: |
37 static std::unique_ptr<TestCompositorWorkerObjectProxy> create(ExecutionCont ext* context) | 35 static std::unique_ptr<TestAnimationWorkletReportingProxy> create() |
38 { | 36 { |
39 return wrapUnique(new TestCompositorWorkerObjectProxy(context)); | 37 return wrapUnique(new TestAnimationWorkletReportingProxy()); |
40 } | 38 } |
41 | 39 |
42 // (Empty) WorkerReportingProxy implementation: | 40 // (Empty) WorkerReportingProxy implementation: |
43 virtual void reportException(const String& errorMessage, std::unique_ptr<Sou rceLocation>, int exceptionId) {} | 41 void reportException(const String& errorMessage, std::unique_ptr<SourceLocat ion>, int exceptionId) override {} |
44 void reportConsoleMessage(MessageSource, MessageLevel, const String& message , SourceLocation*) override {} | 42 void reportConsoleMessage(MessageSource, MessageLevel, const String& message , SourceLocation*) override {} |
45 void postMessageToPageInspector(const String&) override {} | 43 void postMessageToPageInspector(const String&) override {} |
46 | 44 |
47 void didEvaluateWorkerScript(bool success) override {} | 45 void didEvaluateWorkerScript(bool success) override {} |
48 void workerGlobalScopeStarted(WorkerOrWorkletGlobalScope*) override {} | 46 void workerGlobalScopeStarted(WorkerOrWorkletGlobalScope*) override {} |
49 void workerGlobalScopeClosed() override {} | 47 void workerGlobalScopeClosed() override {} |
50 void workerThreadTerminated() override {} | 48 void workerThreadTerminated() override {} |
51 void willDestroyWorkerGlobalScope() override {} | 49 void willDestroyWorkerGlobalScope() override {} |
52 | 50 |
53 ExecutionContext* getExecutionContext() override { return m_executionContext .get(); } | |
54 | |
55 private: | 51 private: |
56 TestCompositorWorkerObjectProxy(ExecutionContext* context) | 52 TestAnimationWorkletReportingProxy() { } |
nhiroki
2016/08/17 05:56:57
nit: { } -> {}
ikilpatrick
2016/08/22 19:07:32
Done.
| |
57 : InProcessWorkerObjectProxy(nullptr) | |
58 , m_executionContext(context) | |
59 { | |
60 } | |
61 | |
62 Persistent<ExecutionContext> m_executionContext; | |
63 }; | |
64 | |
65 class TestCompositorProxyClient | |
66 : public GarbageCollected<TestCompositorProxyClient> | |
67 , public CompositorProxyClient { | |
68 USING_GARBAGE_COLLECTED_MIXIN(TestCompositorProxyClient); | |
69 public: | |
70 TestCompositorProxyClient() {} | |
71 | |
72 void setGlobalScope(WorkerGlobalScope*) override {} | |
73 void requestAnimationFrame() override {} | |
74 void registerCompositorProxy(CompositorProxy*) override {} | |
75 void unregisterCompositorProxy(CompositorProxy*) override {} | |
76 }; | |
77 | |
78 class CompositorWorkerTestPlatform : public TestingPlatformSupport { | |
79 public: | |
80 CompositorWorkerTestPlatform() | |
81 : m_thread(wrapUnique(m_oldPlatform->createThread("Compositor"))) | |
82 { | |
83 } | |
84 | |
85 WebThread* compositorThread() const override | |
86 { | |
87 return m_thread.get(); | |
88 } | |
89 | |
90 WebCompositorSupport* compositorSupport() override { return &m_compositorSup port; } | |
91 | |
92 private: | |
93 std::unique_ptr<WebThread> m_thread; | |
94 TestingCompositorSupport m_compositorSupport; | |
95 }; | 53 }; |
96 | 54 |
97 } // namespace | 55 } // namespace |
98 | 56 |
99 class CompositorWorkerThreadTest : public ::testing::Test { | 57 class AnimationWorkletThreadTest : public ::testing::Test { |
100 public: | 58 public: |
101 void SetUp() override | 59 void SetUp() override |
102 { | 60 { |
103 CompositorWorkerThread::createSharedBackingThreadForTest(); | 61 AnimationWorkletThread::createSharedBackingThreadForTest(); |
104 m_page = DummyPageHolder::create(); | 62 m_reportingProxy = TestAnimationWorkletReportingProxy::create(); |
105 m_objectProxy = TestCompositorWorkerObjectProxy::create(&m_page->documen t()); | |
106 m_securityOrigin = SecurityOrigin::create(KURL(ParsedURLString, "http:// fake.url/")); | 63 m_securityOrigin = SecurityOrigin::create(KURL(ParsedURLString, "http:// fake.url/")); |
107 } | 64 } |
108 | 65 |
109 void TearDown() override | 66 void TearDown() override |
110 { | 67 { |
111 m_page.reset(); | 68 AnimationWorkletThread::clearSharedBackingThread(); |
112 CompositorWorkerThread::clearSharedBackingThread(); | |
113 } | 69 } |
114 | 70 |
115 std::unique_ptr<CompositorWorkerThread> createCompositorWorker() | 71 std::unique_ptr<AnimationWorkletThread> createAnimationWorkletThread() |
116 { | 72 { |
117 std::unique_ptr<CompositorWorkerThread> workerThread = CompositorWorkerT hread::create(nullptr, *m_objectProxy, 0); | 73 std::unique_ptr<AnimationWorkletThread> thread = AnimationWorkletThread: :create(nullptr, *m_reportingProxy); |
118 WorkerClients* clients = WorkerClients::create(); | 74 thread->start(WorkerThreadStartupData::create( |
119 provideCompositorProxyClientTo(clients, new TestCompositorProxyClient); | |
flackr
2016/08/22 18:41:14
Can you remind me how we will eventually get the C
ikilpatrick
2016/08/22 19:07:32
Can just be passed in here on worklet thread start
| |
120 workerThread->start(WorkerThreadStartupData::create( | |
121 KURL(ParsedURLString, "http://fake.url/"), | 75 KURL(ParsedURLString, "http://fake.url/"), |
122 "fake user agent", | 76 "fake user agent", |
123 "//fake source code", | 77 "", |
124 nullptr, | 78 nullptr, |
125 DontPauseWorkerGlobalScopeOnStart, | 79 DontPauseWorkerGlobalScopeOnStart, |
126 nullptr, | 80 nullptr, |
127 "", | 81 "", |
128 m_securityOrigin.get(), | 82 m_securityOrigin.get(), |
129 clients, | 83 nullptr, |
130 WebAddressSpaceLocal, | 84 WebAddressSpaceLocal, |
131 nullptr, | 85 nullptr, |
132 nullptr, | 86 nullptr, |
133 V8CacheOptionsDefault)); | 87 V8CacheOptionsDefault)); |
134 return workerThread; | 88 return thread; |
135 } | 89 } |
136 | 90 |
137 // Attempts to run some simple script for |worker|. | 91 // Attempts to run some simple script for |thread|. |
138 void checkWorkerCanExecuteScript(WorkerThread* worker) | 92 void checkWorkletCanExecuteScript(WorkerThread* thread) |
139 { | 93 { |
140 std::unique_ptr<WaitableEvent> waitEvent = wrapUnique(new WaitableEvent( )); | 94 std::unique_ptr<WaitableEvent> waitEvent = wrapUnique(new WaitableEvent( )); |
141 worker->workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, crossThreadBind(&CompositorWorkerThreadTest::executeScriptInWorker, crossThreadU nretained(this), | 95 thread->workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, crossThreadBind(&AnimationWorkletThreadTest::executeScriptInWorklet, crossThread Unretained(this), |
142 crossThreadUnretained(worker), crossThreadUnretained(waitEvent.get() ))); | 96 crossThreadUnretained(thread), crossThreadUnretained(waitEvent.get() ))); |
143 waitEvent->wait(); | 97 waitEvent->wait(); |
144 } | 98 } |
145 | 99 |
146 private: | 100 private: |
147 void executeScriptInWorker(WorkerThread* worker, WaitableEvent* waitEvent) | 101 void executeScriptInWorklet(WorkerThread* thread, WaitableEvent* waitEvent) |
148 { | 102 { |
149 WorkerOrWorkletScriptController* scriptController = worker->globalScope( )->scriptController(); | 103 WorkerOrWorkletScriptController* scriptController = thread->globalScope( )->scriptController(); |
150 bool evaluateResult = scriptController->evaluate(ScriptSourceCode("var c ounter = 0; ++counter;")); | 104 scriptController->evaluate(ScriptSourceCode("var counter = 0; ++counter; ")); |
151 ASSERT_UNUSED(evaluateResult, evaluateResult); | |
152 waitEvent->signal(); | 105 waitEvent->signal(); |
153 } | 106 } |
154 | 107 |
155 std::unique_ptr<DummyPageHolder> m_page; | |
156 RefPtr<SecurityOrigin> m_securityOrigin; | 108 RefPtr<SecurityOrigin> m_securityOrigin; |
157 std::unique_ptr<InProcessWorkerObjectProxy> m_objectProxy; | 109 std::unique_ptr<WorkerReportingProxy> m_reportingProxy; |
158 CompositorWorkerTestPlatform m_testPlatform; | |
159 }; | 110 }; |
160 | 111 |
161 TEST_F(CompositorWorkerThreadTest, Basic) | 112 TEST_F(AnimationWorkletThreadTest, Basic) |
162 { | 113 { |
163 std::unique_ptr<CompositorWorkerThread> compositorWorker = createCompositorW orker(); | 114 std::unique_ptr<AnimationWorkletThread> worklet = createAnimationWorkletThre ad(); |
164 checkWorkerCanExecuteScript(compositorWorker.get()); | 115 checkWorkletCanExecuteScript(worklet.get()); |
165 compositorWorker->terminateAndWait(); | 116 worklet->terminateAndWait(); |
166 } | 117 } |
167 | 118 |
168 // Tests that the same WebThread is used for new workers if the WebThread is sti ll alive. | 119 // Tests that the same WebThread is used for new worklets if the WebThread is |
169 TEST_F(CompositorWorkerThreadTest, CreateSecondAndTerminateFirst) | 120 // still alive. |
121 TEST_F(AnimationWorkletThreadTest, CreateSecondAndTerminateFirst) | |
170 { | 122 { |
171 // Create the first worker and wait until it is initialized. | 123 // Create the first worklet and wait until it is initialized. |
172 std::unique_ptr<CompositorWorkerThread> firstWorker = createCompositorWorker (); | 124 std::unique_ptr<AnimationWorkletThread> firstWorklet = createAnimationWorkle tThread(); |
173 WebThreadSupportingGC* firstThread = &firstWorker->workerBackingThread().bac kingThread(); | 125 WebThreadSupportingGC* firstThread = &firstWorklet->workerBackingThread().ba ckingThread(); |
174 checkWorkerCanExecuteScript(firstWorker.get()); | 126 checkWorkletCanExecuteScript(firstWorklet.get()); |
175 v8::Isolate* firstIsolate = firstWorker->isolate(); | 127 v8::Isolate* firstIsolate = firstWorklet->isolate(); |
176 ASSERT_TRUE(firstIsolate); | 128 ASSERT_TRUE(firstIsolate); |
177 | 129 |
178 // Create the second worker and immediately destroy the first worker. | 130 // Create the second worklet and immediately destroy the first worklet. |
179 std::unique_ptr<CompositorWorkerThread> secondWorker = createCompositorWorke r(); | 131 std::unique_ptr<AnimationWorkletThread> secondWorklet = createAnimationWorkl etThread(); |
180 // We don't use terminateAndWait here to avoid forcible termination. | 132 // We don't use terminateAndWait here to avoid forcible termination. |
181 firstWorker->terminate(); | 133 firstWorklet->terminate(); |
182 firstWorker->waitForShutdownForTesting(); | 134 firstWorklet->waitForShutdownForTesting(); |
183 | 135 |
184 // Wait until the second worker is initialized. Verify that the second worke r is using the same | 136 // Wait until the second worklet is initialized. Verify that the second |
185 // thread and Isolate as the first worker. | 137 // worklet is using the same thread and Isolate as the first worklet. |
186 WebThreadSupportingGC* secondThread = &secondWorker->workerBackingThread().b ackingThread(); | 138 WebThreadSupportingGC* secondThread = &secondWorklet->workerBackingThread(). backingThread(); |
187 ASSERT_EQ(firstThread, secondThread); | 139 ASSERT_EQ(firstThread, secondThread); |
188 | 140 |
189 v8::Isolate* secondIsolate = secondWorker->isolate(); | 141 v8::Isolate* secondIsolate = secondWorklet->isolate(); |
190 ASSERT_TRUE(secondIsolate); | 142 ASSERT_TRUE(secondIsolate); |
191 EXPECT_EQ(firstIsolate, secondIsolate); | 143 EXPECT_EQ(firstIsolate, secondIsolate); |
192 | 144 |
193 // Verify that the worker can still successfully execute script. | 145 // Verify that the worklet can still successfully execute script. |
194 checkWorkerCanExecuteScript(secondWorker.get()); | 146 checkWorkletCanExecuteScript(secondWorklet.get()); |
195 | 147 |
196 secondWorker->terminateAndWait(); | 148 secondWorklet->terminateAndWait(); |
197 } | 149 } |
198 | 150 |
199 // Tests that a new WebThread is created if all existing workers are terminated before a new worker is created. | 151 // Tests that a new WebThread is created if all existing worklets are |
200 TEST_F(CompositorWorkerThreadTest, TerminateFirstAndCreateSecond) | 152 // terminated before a new worklet is created. |
153 TEST_F(AnimationWorkletThreadTest, TerminateFirstAndCreateSecond) | |
201 { | 154 { |
202 // Create the first worker, wait until it is initialized, and terminate it. | 155 // Create the first worklet, wait until it is initialized, and terminate it. |
203 std::unique_ptr<CompositorWorkerThread> compositorWorker = createCompositorW orker(); | 156 std::unique_ptr<AnimationWorkletThread> worklet = createAnimationWorkletThre ad(); |
204 WebThreadSupportingGC* firstThread = &compositorWorker->workerBackingThread( ).backingThread(); | 157 WebThreadSupportingGC* firstThread = &worklet->workerBackingThread().backing Thread(); |
205 checkWorkerCanExecuteScript(compositorWorker.get()); | 158 checkWorkletCanExecuteScript(worklet.get()); |
206 | 159 |
207 // We don't use terminateAndWait here to avoid forcible termination. | 160 // We don't use terminateAndWait here to avoid forcible termination. |
208 compositorWorker->terminate(); | 161 worklet->terminate(); |
209 compositorWorker->waitForShutdownForTesting(); | 162 worklet->waitForShutdownForTesting(); |
210 | 163 |
211 // Create the second worker. The backing thread is same. | 164 // Create the second worklet. The backing thread is same. |
212 compositorWorker = createCompositorWorker(); | 165 worklet = createAnimationWorkletThread(); |
213 WebThreadSupportingGC* secondThread = &compositorWorker->workerBackingThread ().backingThread(); | 166 WebThreadSupportingGC* secondThread = &worklet->workerBackingThread().backin gThread(); |
214 EXPECT_EQ(firstThread, secondThread); | 167 EXPECT_EQ(firstThread, secondThread); |
215 checkWorkerCanExecuteScript(compositorWorker.get()); | 168 checkWorkletCanExecuteScript(worklet.get()); |
216 | 169 |
217 compositorWorker->terminateAndWait(); | 170 worklet->terminateAndWait(); |
218 } | 171 } |
219 | 172 |
220 // Tests that v8::Isolate and WebThread are correctly set-up if a worker is crea ted while another is terminating. | 173 // Tests that v8::Isolate and WebThread are correctly set-up if a worklet is |
221 TEST_F(CompositorWorkerThreadTest, CreatingSecondDuringTerminationOfFirst) | 174 // created while another is terminating. |
175 TEST_F(AnimationWorkletThreadTest, CreatingSecondDuringTerminationOfFirst) | |
222 { | 176 { |
223 std::unique_ptr<CompositorWorkerThread> firstWorker = createCompositorWorker (); | 177 std::unique_ptr<AnimationWorkletThread> firstWorklet = createAnimationWorkle tThread(); |
224 checkWorkerCanExecuteScript(firstWorker.get()); | 178 checkWorkletCanExecuteScript(firstWorklet.get()); |
225 v8::Isolate* firstIsolate = firstWorker->isolate(); | 179 v8::Isolate* firstIsolate = firstWorklet->isolate(); |
226 ASSERT_TRUE(firstIsolate); | 180 ASSERT_TRUE(firstIsolate); |
227 | 181 |
228 // Request termination of the first worker and create the second worker | 182 // Request termination of the first worklet and create the second worklet |
229 // as soon as possible. | 183 // as soon as possible. |
230 firstWorker->terminate(); | 184 firstWorklet->terminate(); |
231 // We don't wait for its termination. | 185 // We don't wait for its termination. |
232 // Note: We rely on the assumption that the termination steps don't run | 186 // Note: We rely on the assumption that the termination steps don't run |
233 // on the worker thread so quickly. This could be a source of flakiness. | 187 // on the worklet thread so quickly. This could be a source of flakiness. |
234 | 188 |
235 std::unique_ptr<CompositorWorkerThread> secondWorker = createCompositorWorke r(); | 189 std::unique_ptr<AnimationWorkletThread> secondWorklet = createAnimationWorkl etThread(); |
236 | 190 |
237 v8::Isolate* secondIsolate = secondWorker->isolate(); | 191 v8::Isolate* secondIsolate = secondWorklet->isolate(); |
238 ASSERT_TRUE(secondIsolate); | 192 ASSERT_TRUE(secondIsolate); |
239 EXPECT_EQ(firstIsolate, secondIsolate); | 193 EXPECT_EQ(firstIsolate, secondIsolate); |
240 | 194 |
241 // Verify that the isolate can run some scripts correctly in the second work er. | 195 // Verify that the isolate can run some scripts correctly in the second |
242 checkWorkerCanExecuteScript(secondWorker.get()); | 196 // worklet. |
243 secondWorker->terminateAndWait(); | 197 checkWorkletCanExecuteScript(secondWorklet.get()); |
198 secondWorklet->terminateAndWait(); | |
244 } | 199 } |
245 | 200 |
246 } // namespace blink | 201 } // namespace blink |
OLD | NEW |