Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 7 #include "Source/web/ServiceWorkerGlobalScopeProxy.h" | |
| 8 | |
| 9 #include "Source/bindings/core/v8/ScriptSourceCode.h" | |
| 10 #include "Source/core/dom/CrossThreadTask.h" | |
| 11 #include "platform/weborigin/KURL.h" | |
| 12 #include "public/platform/Platform.h" | |
| 13 #include "public/platform/WebThread.h" | |
| 14 #include "public/platform/WebUnitTestSupport.h" | |
| 15 #include "public/web/WebEmbeddedWorker.h" | |
| 16 #include "public/web/WebEmbeddedWorkerStartData.h" | |
| 17 #include "public/web/WebServiceWorkerContextClient.h" | |
| 18 #include "web/WebEmbeddedWorkerImpl.h" | |
| 19 #include "web/tests/URLTestHelpers.h" | |
| 20 #include <gmock/gmock.h> | |
| 21 #include <gtest/gtest.h> | |
| 22 #include <v8.h> | |
| 23 | |
| 24 using namespace blink; | |
| 25 using namespace WebCore; | |
| 26 | |
| 27 namespace { | |
| 28 | |
| 29 class ServiceWorkerGlobalScopeProxyTest : public testing::Test { | |
| 30 protected: | |
| 31 ServiceWorkerGlobalScopeProxyTest() | |
| 32 : m_baseUrl("http://www.test.com/") | |
| 33 { | |
| 34 } | |
| 35 | |
| 36 virtual ~ServiceWorkerGlobalScopeProxyTest() | |
| 37 { | |
| 38 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); | |
| 39 } | |
| 40 | |
| 41 // Remember to call serveAsynchronousMockedRequests() in order to handle the se mocked URLs. | |
| 42 void registerMockedHttpURLLoad(const std::string& fileName, const std::strin g& mimeType = "text/html") | |
| 43 { | |
| 44 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseU rl), WebString::fromUTF8(fileName), WebString::fromUTF8(mimeType)); | |
| 45 } | |
| 46 | |
| 47 const std::string m_baseUrl; | |
| 48 }; | |
| 49 | |
| 50 // Can repeatedly run the current thread's loop, but unlike Chrome's RunLoop, ca nnot be recursively reentered. | |
| 51 // quitWhenIdle() must be called exactly once per run() call. | |
| 52 class RunLoop { | |
| 53 public: | |
| 54 RunLoop() | |
| 55 : m_thread(blink::Platform::current()->currentThread()) | |
| 56 , m_isRunning(false) | |
| 57 , m_isQuitting(false) | |
| 58 { | |
| 59 } | |
| 60 | |
| 61 // Starts the thread's run loop, and returns when quitWhenIdle() is called. | |
| 62 void run() | |
| 63 { | |
| 64 EXPECT_FALSE(m_isRunning); | |
| 65 m_isRunning = true; | |
| 66 m_thread->enterRunLoop(); | |
| 67 EXPECT_TRUE(m_isQuitting); | |
| 68 m_isRunning = m_isQuitting = false; | |
| 69 } | |
| 70 | |
| 71 // This can be called before run() or concurrently with it from another thre ad. | |
| 72 // The loop will terminate when it's idle. | |
| 73 void quitWhenIdle() | |
| 74 { | |
| 75 EXPECT_FALSE(m_isQuitting); | |
| 76 m_isQuitting = true; | |
| 77 m_thread->postTask(new QuitTask(this)); | |
| 78 } | |
| 79 | |
| 80 bool isQuitting() | |
| 81 { | |
| 82 return m_isQuitting; | |
| 83 } | |
| 84 | |
| 85 private: | |
| 86 class QuitTask : public WebThread::Task { | |
| 87 public: | |
| 88 QuitTask(RunLoop* runLoop) | |
| 89 : m_runLoop(runLoop) | |
| 90 { | |
| 91 } | |
| 92 | |
| 93 virtual void run() | |
| 94 { | |
| 95 EXPECT_TRUE(m_runLoop->m_isRunning); | |
| 96 EXPECT_TRUE(m_runLoop->m_isQuitting); | |
| 97 m_runLoop->m_thread->exitRunLoop(); | |
| 98 } | |
| 99 | |
| 100 RunLoop* m_runLoop; | |
| 101 }; | |
| 102 | |
| 103 WebThread* m_thread; | |
| 104 bool m_isRunning; | |
| 105 bool m_isQuitting; | |
| 106 }; | |
| 107 | |
| 108 // Continuously pumps the mocked-requests queue during the current execution of runLoop->run(), or next if run() isn't currently running. | |
| 109 class ServeAsyncRequestsTask : public WebThread::Task { | |
| 110 public: | |
| 111 ServeAsyncRequestsTask(RunLoop* runLoop) | |
| 112 : m_runLoop(runLoop) | |
| 113 { | |
| 114 } | |
| 115 | |
| 116 virtual void run() OVERRIDE | |
| 117 { | |
| 118 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests( ); | |
|
Jeffrey Yasskin
2014/07/17 18:32:09
dcheng says that this call is probably the best we
| |
| 119 // The RunLoop only finishes quitting when it has no tasks left, so this task has to end its chain explicitly. | |
| 120 if (!m_runLoop->isQuitting()) | |
| 121 Platform::current()->currentThread()->postTask(new ServeAsyncRequest sTask(m_runLoop)); | |
| 122 } | |
| 123 | |
| 124 private: | |
| 125 RunLoop* m_runLoop; | |
| 126 }; | |
| 127 | |
| 128 class V8ContextTestContextClient : public WebServiceWorkerContextClient { | |
| 129 public: | |
| 130 virtual void workerContextFailedToStart() | |
| 131 { | |
| 132 ADD_FAILURE() << "workerContextFailedToStart"; | |
| 133 m_runLoop->quitWhenIdle(); | |
| 134 } | |
| 135 | |
| 136 virtual void reportException(const WebString& errorMessage, int lineNumber, int columnNumber, const WebString& sourceURL) | |
| 137 { | |
| 138 ADD_FAILURE() << sourceURL.utf8() << "(" << lineNumber << ":" << columnN umber << ") error: " << errorMessage.utf8(); | |
| 139 m_runLoop->quitWhenIdle(); | |
| 140 } | |
| 141 | |
| 142 virtual void workerContextStarted(WebServiceWorkerContextProxy* proxy) | |
| 143 { | |
| 144 m_proxy = proxy; | |
| 145 v8::HandleScope scope(v8::Isolate::GetCurrent()); | |
| 146 EXPECT_TRUE(*m_proxy->v8Context()) << "The v8 context should be valid as soon as the worker is started."; | |
| 147 m_runLoop->quitWhenIdle(); | |
| 148 } | |
| 149 | |
| 150 void checkContextAccessibleAfterClose() | |
| 151 { | |
| 152 v8::HandleScope scope(v8::Isolate::GetCurrent()); | |
| 153 EXPECT_TRUE(*m_proxy->v8Context()) << "The v8 context should still be va lid."; | |
| 154 static_cast<ServiceWorkerGlobalScopeProxy*>(m_proxy)->evaluate(String::f romUTF8("self.close();")); | |
| 155 // The context continues to exist until non-cleanup tasks stop running. | |
| 156 checkContextStillExists(); | |
| 157 // close() will eventually terminate the worker, which will quit the | |
| 158 // RunLoop through workerContextDestroyed. | |
| 159 } | |
| 160 | |
| 161 void checkContextStillExists() | |
| 162 { | |
| 163 // The context isn't valid after willDestroyWorkerContext(). | |
| 164 if (!m_proxy) | |
| 165 return; | |
| 166 v8::HandleScope scope(v8::Isolate::GetCurrent()); | |
| 167 EXPECT_TRUE(*m_proxy->v8Context()); | |
| 168 static_cast<WebEmbeddedWorkerImpl*>(m_worker)->postTask(createCrossThrea dTask(&V8ContextTestContextClient::checkContextStillExists, this)); | |
| 169 } | |
| 170 | |
| 171 virtual void willDestroyWorkerContext() OVERRIDE | |
| 172 { | |
| 173 m_proxy = 0; | |
| 174 } | |
| 175 | |
| 176 virtual void workerContextDestroyed() OVERRIDE | |
| 177 { | |
| 178 // Now it's safe to finish the main test, which will destroy the WorkerT hread. | |
| 179 m_runLoop->quitWhenIdle(); | |
| 180 } | |
| 181 | |
| 182 RunLoop* m_runLoop; | |
| 183 WebEmbeddedWorker* m_worker; | |
| 184 WebServiceWorkerContextProxy* m_proxy; | |
| 185 }; | |
| 186 | |
| 187 TEST_F(ServiceWorkerGlobalScopeProxyTest, V8ContextTest) | |
| 188 { | |
| 189 V8ContextTestContextClient* contextClient = new V8ContextTestContextClient; | |
| 190 | |
| 191 RunLoop runLoop; | |
| 192 contextClient->m_runLoop = &runLoop; | |
| 193 | |
| 194 OwnPtr<WebEmbeddedWorker> worker = adoptPtr(WebEmbeddedWorker::create(contex tClient, 0)); | |
| 195 contextClient->m_worker = worker.get(); | |
| 196 | |
| 197 WebEmbeddedWorkerStartData startData; | |
| 198 registerMockedHttpURLLoad("blank.js", "text/javascript"); | |
| 199 startData.scriptURL = URLTestHelpers::toKURL(m_baseUrl + "blank.js"); | |
| 200 worker->startWorkerContext(startData); | |
| 201 // Serve requests until the message loop quits. | |
| 202 Platform::current()->currentThread()->postTask(new ServeAsyncRequestsTask(&r unLoop)); | |
| 203 runLoop.run(); // Wait for workerContextStarted(). | |
| 204 | |
| 205 static_cast<WebEmbeddedWorkerImpl&>(*worker).postTask( | |
| 206 createCrossThreadTask(&V8ContextTestContextClient::checkContextAccessibl eAfterClose, contextClient)); | |
| 207 runLoop.run(); // Wait for workerContextDestroyed(). | |
| 208 } | |
| 209 | |
| 210 } // namespace | |
| OLD | NEW |