Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1655)

Unified Diff: Source/web/tests/ServiceWorkerGlobalScopeProxyTest.cpp

Issue 383063008: Expose the ServiceWorker's v8 context to embedders. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@pinned
Patch Set: Don't #include .cpp files. :-P Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/web/WebEmbeddedWorkerImpl.cpp ('k') | Source/web/tests/data/blank.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/web/tests/ServiceWorkerGlobalScopeProxyTest.cpp
diff --git a/Source/web/tests/ServiceWorkerGlobalScopeProxyTest.cpp b/Source/web/tests/ServiceWorkerGlobalScopeProxyTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5ee9eaa861634d13030f2c01847f68101bff156d
--- /dev/null
+++ b/Source/web/tests/ServiceWorkerGlobalScopeProxyTest.cpp
@@ -0,0 +1,210 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+
+#include "Source/web/ServiceWorkerGlobalScopeProxy.h"
+
+#include "Source/bindings/core/v8/ScriptSourceCode.h"
+#include "Source/core/dom/CrossThreadTask.h"
+#include "platform/weborigin/KURL.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebThread.h"
+#include "public/platform/WebUnitTestSupport.h"
+#include "public/web/WebEmbeddedWorker.h"
+#include "public/web/WebEmbeddedWorkerStartData.h"
+#include "public/web/WebServiceWorkerContextClient.h"
+#include "web/WebEmbeddedWorkerImpl.h"
+#include "web/tests/URLTestHelpers.h"
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <v8.h>
+
+using namespace blink;
+using namespace WebCore;
+
+namespace {
+
+class ServiceWorkerGlobalScopeProxyTest : public testing::Test {
+protected:
+ ServiceWorkerGlobalScopeProxyTest()
+ : m_baseUrl("http://www.test.com/")
+ {
+ }
+
+ virtual ~ServiceWorkerGlobalScopeProxyTest()
+ {
+ Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
+ }
+
+ // Remember to call serveAsynchronousMockedRequests() in order to handle these mocked URLs.
+ void registerMockedHttpURLLoad(const std::string& fileName, const std::string& mimeType = "text/html")
+ {
+ URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseUrl), WebString::fromUTF8(fileName), WebString::fromUTF8(mimeType));
+ }
+
+ const std::string m_baseUrl;
+};
+
+// Can repeatedly run the current thread's loop, but unlike Chrome's RunLoop, cannot be recursively reentered.
+// quitWhenIdle() must be called exactly once per run() call.
+class RunLoop {
+public:
+ RunLoop()
+ : m_thread(blink::Platform::current()->currentThread())
+ , m_isRunning(false)
+ , m_isQuitting(false)
+ {
+ }
+
+ // Starts the thread's run loop, and returns when quitWhenIdle() is called.
+ void run()
+ {
+ EXPECT_FALSE(m_isRunning);
+ m_isRunning = true;
+ m_thread->enterRunLoop();
+ EXPECT_TRUE(m_isQuitting);
+ m_isRunning = m_isQuitting = false;
+ }
+
+ // This can be called before run() or concurrently with it from another thread.
+ // The loop will terminate when it's idle.
+ void quitWhenIdle()
+ {
+ EXPECT_FALSE(m_isQuitting);
+ m_isQuitting = true;
+ m_thread->postTask(new QuitTask(this));
+ }
+
+ bool isQuitting()
+ {
+ return m_isQuitting;
+ }
+
+private:
+ class QuitTask : public WebThread::Task {
+ public:
+ QuitTask(RunLoop* runLoop)
+ : m_runLoop(runLoop)
+ {
+ }
+
+ virtual void run()
+ {
+ EXPECT_TRUE(m_runLoop->m_isRunning);
+ EXPECT_TRUE(m_runLoop->m_isQuitting);
+ m_runLoop->m_thread->exitRunLoop();
+ }
+
+ RunLoop* m_runLoop;
+ };
+
+ WebThread* m_thread;
+ bool m_isRunning;
+ bool m_isQuitting;
+};
+
+// Continuously pumps the mocked-requests queue during the current execution of runLoop->run(), or next if run() isn't currently running.
+class ServeAsyncRequestsTask : public WebThread::Task {
+public:
+ ServeAsyncRequestsTask(RunLoop* runLoop)
+ : m_runLoop(runLoop)
+ {
+ }
+
+ virtual void run() OVERRIDE
+ {
+ Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
Jeffrey Yasskin 2014/07/17 18:32:09 dcheng says that this call is probably the best we
+ // The RunLoop only finishes quitting when it has no tasks left, so this task has to end its chain explicitly.
+ if (!m_runLoop->isQuitting())
+ Platform::current()->currentThread()->postTask(new ServeAsyncRequestsTask(m_runLoop));
+ }
+
+private:
+ RunLoop* m_runLoop;
+};
+
+class V8ContextTestContextClient : public WebServiceWorkerContextClient {
+public:
+ virtual void workerContextFailedToStart()
+ {
+ ADD_FAILURE() << "workerContextFailedToStart";
+ m_runLoop->quitWhenIdle();
+ }
+
+ virtual void reportException(const WebString& errorMessage, int lineNumber, int columnNumber, const WebString& sourceURL)
+ {
+ ADD_FAILURE() << sourceURL.utf8() << "(" << lineNumber << ":" << columnNumber << ") error: " << errorMessage.utf8();
+ m_runLoop->quitWhenIdle();
+ }
+
+ virtual void workerContextStarted(WebServiceWorkerContextProxy* proxy)
+ {
+ m_proxy = proxy;
+ v8::HandleScope scope(v8::Isolate::GetCurrent());
+ EXPECT_TRUE(*m_proxy->v8Context()) << "The v8 context should be valid as soon as the worker is started.";
+ m_runLoop->quitWhenIdle();
+ }
+
+ void checkContextAccessibleAfterClose()
+ {
+ v8::HandleScope scope(v8::Isolate::GetCurrent());
+ EXPECT_TRUE(*m_proxy->v8Context()) << "The v8 context should still be valid.";
+ static_cast<ServiceWorkerGlobalScopeProxy*>(m_proxy)->evaluate(String::fromUTF8("self.close();"));
+ // The context continues to exist until non-cleanup tasks stop running.
+ checkContextStillExists();
+ // close() will eventually terminate the worker, which will quit the
+ // RunLoop through workerContextDestroyed.
+ }
+
+ void checkContextStillExists()
+ {
+ // The context isn't valid after willDestroyWorkerContext().
+ if (!m_proxy)
+ return;
+ v8::HandleScope scope(v8::Isolate::GetCurrent());
+ EXPECT_TRUE(*m_proxy->v8Context());
+ static_cast<WebEmbeddedWorkerImpl*>(m_worker)->postTask(createCrossThreadTask(&V8ContextTestContextClient::checkContextStillExists, this));
+ }
+
+ virtual void willDestroyWorkerContext() OVERRIDE
+ {
+ m_proxy = 0;
+ }
+
+ virtual void workerContextDestroyed() OVERRIDE
+ {
+ // Now it's safe to finish the main test, which will destroy the WorkerThread.
+ m_runLoop->quitWhenIdle();
+ }
+
+ RunLoop* m_runLoop;
+ WebEmbeddedWorker* m_worker;
+ WebServiceWorkerContextProxy* m_proxy;
+};
+
+TEST_F(ServiceWorkerGlobalScopeProxyTest, V8ContextTest)
+{
+ V8ContextTestContextClient* contextClient = new V8ContextTestContextClient;
+
+ RunLoop runLoop;
+ contextClient->m_runLoop = &runLoop;
+
+ OwnPtr<WebEmbeddedWorker> worker = adoptPtr(WebEmbeddedWorker::create(contextClient, 0));
+ contextClient->m_worker = worker.get();
+
+ WebEmbeddedWorkerStartData startData;
+ registerMockedHttpURLLoad("blank.js", "text/javascript");
+ startData.scriptURL = URLTestHelpers::toKURL(m_baseUrl + "blank.js");
+ worker->startWorkerContext(startData);
+ // Serve requests until the message loop quits.
+ Platform::current()->currentThread()->postTask(new ServeAsyncRequestsTask(&runLoop));
+ runLoop.run(); // Wait for workerContextStarted().
+
+ static_cast<WebEmbeddedWorkerImpl&>(*worker).postTask(
+ createCrossThreadTask(&V8ContextTestContextClient::checkContextAccessibleAfterClose, contextClient));
+ runLoop.run(); // Wait for workerContextDestroyed().
+}
+
+} // namespace
« no previous file with comments | « Source/web/WebEmbeddedWorkerImpl.cpp ('k') | Source/web/tests/data/blank.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698