Chromium Code Reviews| 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 |