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.cpp" | |
| 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() | |
|
dominicc (has gone to gerrit)
2014/07/17 02:43:44
Run -> run
Jeffrey Yasskin
2014/07/17 16:19:33
Oops. Got my coding conventions confused.
| |
| 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() | |
|
dominicc (has gone to gerrit)
2014/07/17 02:43:44
quitWhenIdle.
Jeffrey Yasskin
2014/07/17 16:19:32
Done.
| |
| 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 virtual void run() | |
|
dominicc (has gone to gerrit)
2014/07/17 02:43:44
The lack of vertical whitespace here seems inconsi
Jeffrey Yasskin
2014/07/17 16:19:32
Done.
| |
| 93 { | |
| 94 EXPECT_TRUE(m_runLoop->m_isRunning); | |
| 95 EXPECT_TRUE(m_runLoop->m_isQuitting); | |
| 96 m_runLoop->m_thread->exitRunLoop(); | |
| 97 } | |
| 98 RunLoop* m_runLoop; | |
| 99 }; | |
| 100 | |
| 101 WebThread* m_thread; | |
| 102 bool m_isRunning; | |
| 103 bool m_isQuitting; | |
| 104 }; | |
| 105 | |
| 106 // Continuously pumps the mocked-requests queue during the current execution of runLoop->Run(), or next if Run() isn't currently running. | |
|
dominicc (has gone to gerrit)
2014/07/17 02:43:44
Run -> run, right?
Jeffrey Yasskin
2014/07/17 16:19:33
Done.
| |
| 107 class ServeAsyncRequestsTask : public WebThread::Task { | |
| 108 public: | |
| 109 ServeAsyncRequestsTask(RunLoop* runLoop) | |
| 110 : m_runLoop(runLoop) | |
| 111 { | |
| 112 } | |
| 113 | |
| 114 virtual void run() OVERRIDE | |
| 115 { | |
| 116 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests( ); | |
| 117 // The RunLoop only finishes quitting when it has no tasks left, so this task has to end its chain explicitly. | |
| 118 if (!m_runLoop->isQuitting()) { | |
|
dominicc (has gone to gerrit)
2014/07/17 02:43:44
No {}s for single line bodies unless it is clearer
Jeffrey Yasskin
2014/07/17 16:19:32
After goto-fail, I've been more inclined to keep t
| |
| 119 Platform::current()->currentThread()->postTask(new ServeAsyncRequest sTask(m_runLoop)); | |
| 120 } | |
| 121 } | |
| 122 | |
| 123 private: | |
| 124 RunLoop* m_runLoop; | |
| 125 }; | |
| 126 | |
| 127 class V8ContextTestSWContextClient : public WebServiceWorkerContextClient { | |
|
dominicc (has gone to gerrit)
2014/07/17 02:43:44
SW -> ServiceWorker
I am all for brevity but you
Jeffrey Yasskin
2014/07/17 16:19:33
If it's just TestContextClient, that'll make it ha
| |
| 128 public: | |
| 129 virtual void workerContextFailedToStart() | |
| 130 { | |
| 131 ADD_FAILURE() << "workerContextFailedToStart"; | |
| 132 m_runLoop->QuitWhenIdle(); | |
| 133 } | |
| 134 | |
| 135 virtual void reportException(const WebString& errorMessage, int lineNumber, int columnNumber, const WebString& sourceURL) | |
| 136 { | |
| 137 ADD_FAILURE() << sourceURL.utf8() << "(" << lineNumber << ":" << columnN umber << ") error: " << errorMessage.utf8(); | |
| 138 m_runLoop->QuitWhenIdle(); | |
| 139 } | |
| 140 | |
| 141 virtual void workerContextStarted(WebServiceWorkerContextProxy* proxy) | |
| 142 { | |
| 143 m_proxy = proxy; | |
| 144 v8::HandleScope scope(v8::Isolate::GetCurrent()); | |
| 145 EXPECT_TRUE(*m_proxy->v8Context()) << "The v8 context should be valid as soon as the worker is started."; | |
| 146 m_runLoop->QuitWhenIdle(); | |
| 147 } | |
| 148 | |
| 149 void checkContextAccessibleAfterClose() | |
| 150 { | |
| 151 v8::HandleScope scope(v8::Isolate::GetCurrent()); | |
| 152 EXPECT_TRUE(*m_proxy->v8Context()) << "The v8 context should still be va lid."; | |
| 153 static_cast<ServiceWorkerGlobalScopeProxy*>(m_proxy)->evaluate(String::f romUTF8("self.close();")); | |
| 154 // The context continues to exist until non-cleanup tasks stop running. | |
| 155 checkContextStillExists(); | |
| 156 // close() will eventually terminate the worker, which will quit the | |
| 157 // RunLoop through workerContextDestroyed. | |
| 158 } | |
| 159 | |
| 160 void checkContextStillExists() | |
| 161 { | |
| 162 // The context isn't valid after willDestroyWorkerContext(). | |
| 163 if (!m_proxy) | |
| 164 return; | |
| 165 v8::HandleScope scope(v8::Isolate::GetCurrent()); | |
| 166 EXPECT_TRUE(*m_proxy->v8Context()); | |
| 167 static_cast<WebEmbeddedWorkerImpl*>(m_worker)->postTask(createCrossThrea dTask(&V8ContextTestSWContextClient::checkContextStillExists, this)); | |
| 168 } | |
| 169 | |
| 170 virtual void willDestroyWorkerContext() OVERRIDE | |
| 171 { | |
| 172 m_proxy = 0; | |
| 173 } | |
| 174 | |
| 175 virtual void workerContextDestroyed() OVERRIDE | |
| 176 { | |
| 177 // Now it's safe to finish the main test, which will destroy the WorkerT hread. | |
| 178 m_runLoop->QuitWhenIdle(); | |
| 179 } | |
| 180 | |
| 181 RunLoop* m_runLoop; | |
| 182 WebEmbeddedWorker* m_worker; | |
| 183 WebServiceWorkerContextProxy* m_proxy; | |
| 184 }; | |
| 185 | |
| 186 TEST_F(ServiceWorkerGlobalScopeProxyTest, V8ContextText) | |
| 187 { | |
| 188 V8ContextTestSWContextClient* contextClient = new V8ContextTestSWContextClie nt; | |
| 189 | |
| 190 RunLoop runLoop; | |
| 191 contextClient->m_runLoop = &runLoop; | |
| 192 | |
| 193 OwnPtr<WebEmbeddedWorker> worker = adoptPtr(WebEmbeddedWorker::create(contex tClient, 0)); | |
| 194 contextClient->m_worker = worker.get(); | |
| 195 | |
| 196 WebEmbeddedWorkerStartData startData; | |
| 197 registerMockedHttpURLLoad("blank.js", "text/javascript"); | |
| 198 startData.scriptURL = URLTestHelpers::toKURL(m_baseUrl + "blank.js"); | |
| 199 worker->startWorkerContext(startData); | |
| 200 // Serve requests until the message loop quits. | |
| 201 Platform::current()->currentThread()->postTask(new ServeAsyncRequestsTask(&r unLoop)); | |
| 202 runLoop.Run(); // Wait for workerContextStarted(). | |
| 203 | |
| 204 static_cast<WebEmbeddedWorkerImpl&>(*worker).postTask( | |
| 205 createCrossThreadTask(&V8ContextTestSWContextClient::checkContextAccessi bleAfterClose, contextClient)); | |
| 206 runLoop.Run(); // Wait for workerContextDestroyed(). | |
| 207 } | |
| 208 | |
| 209 } // namespace | |
| OLD | NEW |