blob: 972122c72bc867f73c02f54762f275043ffc2a40 [file] [log] [blame]
// Copyright 2016 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 "bindings/core/v8/SourceLocation.h"
#include "bindings/core/v8/V8CacheOptions.h"
#include "bindings/core/v8/V8GCController.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/workers/WorkerBackingThread.h"
#include "core/workers/WorkerClients.h"
#include "core/workers/WorkerGlobalScope.h"
#include "core/workers/WorkerLoaderProxy.h"
#include "core/workers/WorkerReportingProxy.h"
#include "core/workers/WorkerThread.h"
#include "core/workers/WorkerThreadLifecycleObserver.h"
#include "core/workers/WorkerThreadStartupData.h"
#include "platform/CrossThreadFunctional.h"
#include "platform/WaitableEvent.h"
#include "platform/WebThreadSupportingGC.h"
#include "platform/heap/Handle.h"
#include "platform/network/ContentSecurityPolicyParsers.h"
#include "platform/weborigin/KURL.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "public/platform/WebAddressSpace.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "wtf/CurrentTime.h"
#include "wtf/Forward.h"
#include "wtf/PtrUtil.h"
#include "wtf/Vector.h"
#include <memory>
#include <v8.h>
namespace blink {
class MockWorkerLoaderProxyProvider : public WorkerLoaderProxyProvider {
public:
MockWorkerLoaderProxyProvider() { }
~MockWorkerLoaderProxyProvider() override { }
void postTaskToLoader(std::unique_ptr<ExecutionContextTask>) override
{
NOTIMPLEMENTED();
}
bool postTaskToWorkerGlobalScope(std::unique_ptr<ExecutionContextTask>) override
{
NOTIMPLEMENTED();
return false;
}
};
class MockWorkerReportingProxy : public WorkerReportingProxy {
public:
MockWorkerReportingProxy() { }
~MockWorkerReportingProxy() override { }
MOCK_METHOD2(reportExceptionMock, void(const String& errorMessage, SourceLocation*));
void reportException(const String& errorMessage, std::unique_ptr<SourceLocation> location)
{
reportExceptionMock(errorMessage, location.get());
}
MOCK_METHOD1(reportConsoleMessage, void(ConsoleMessage*));
MOCK_METHOD1(postMessageToPageInspector, void(const String&));
MOCK_METHOD1(didEvaluateWorkerScript, void(bool success));
MOCK_METHOD1(workerGlobalScopeStarted, void(WorkerOrWorkletGlobalScope*));
MOCK_METHOD0(workerGlobalScopeClosed, void());
MOCK_METHOD0(workerThreadTerminated, void());
MOCK_METHOD0(willDestroyWorkerGlobalScope, void());
};
class MockWorkerThreadLifecycleObserver final : public GarbageCollectedFinalized<MockWorkerThreadLifecycleObserver>, public WorkerThreadLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(MockWorkerThreadLifecycleObserver);
WTF_MAKE_NONCOPYABLE(MockWorkerThreadLifecycleObserver);
public:
explicit MockWorkerThreadLifecycleObserver(WorkerThreadLifecycleContext* context)
: WorkerThreadLifecycleObserver(context) { }
MOCK_METHOD0(contextDestroyed, void());
};
class WorkerThreadForTest : public WorkerThread {
public:
WorkerThreadForTest(
WorkerLoaderProxyProvider* mockWorkerLoaderProxyProvider,
WorkerReportingProxy& mockWorkerReportingProxy)
: WorkerThread(WorkerLoaderProxy::create(mockWorkerLoaderProxyProvider), mockWorkerReportingProxy)
, m_workerBackingThread(WorkerBackingThread::createForTest("Test thread"))
, m_scriptLoadedEvent(wrapUnique(new WaitableEvent()))
{
}
~WorkerThreadForTest() override { }
WorkerBackingThread& workerBackingThread() override { return *m_workerBackingThread; }
ConsoleMessageStorage* consoleMessageStorage() final { return toWorkerGlobalScope(globalScope())->consoleMessageStorage(); }
WorkerOrWorkletGlobalScope* createWorkerGlobalScope(std::unique_ptr<WorkerThreadStartupData>) override;
void waitUntilScriptLoaded()
{
m_scriptLoadedEvent->wait();
}
void scriptLoaded()
{
m_scriptLoadedEvent->signal();
}
void startWithSourceCode(SecurityOrigin* securityOrigin, const String& source)
{
std::unique_ptr<Vector<CSPHeaderAndType>> headers = wrapUnique(new Vector<CSPHeaderAndType>());
CSPHeaderAndType headerAndType("contentSecurityPolicy", ContentSecurityPolicyHeaderTypeReport);
headers->append(headerAndType);
WorkerClients* clients = nullptr;
start(WorkerThreadStartupData::create(
KURL(ParsedURLString, "http://fake.url/"),
"fake user agent",
source,
nullptr,
DontPauseWorkerGlobalScopeOnStart,
headers.get(),
"",
securityOrigin,
clients,
WebAddressSpaceLocal,
nullptr,
nullptr,
V8CacheOptionsDefault));
}
void waitForInit()
{
std::unique_ptr<WaitableEvent> completionEvent = wrapUnique(new WaitableEvent());
workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, crossThreadBind(&WaitableEvent::signal, crossThreadUnretained(completionEvent.get())));
completionEvent->wait();
}
private:
std::unique_ptr<WorkerBackingThread> m_workerBackingThread;
std::unique_ptr<WaitableEvent> m_scriptLoadedEvent;
};
class FakeWorkerGlobalScope : public WorkerGlobalScope {
public:
FakeWorkerGlobalScope(const KURL& url, const String& userAgent, WorkerThreadForTest* thread, std::unique_ptr<SecurityOrigin::PrivilegeData> starterOriginPrivilegeData, WorkerClients* workerClients)
: WorkerGlobalScope(url, userAgent, thread, monotonicallyIncreasingTime(), std::move(starterOriginPrivilegeData), workerClients)
, m_thread(thread)
{
}
~FakeWorkerGlobalScope() override
{
}
void scriptLoaded(size_t, size_t) override
{
m_thread->scriptLoaded();
}
// EventTarget
const AtomicString& interfaceName() const override
{
return EventTargetNames::DedicatedWorkerGlobalScope;
}
void exceptionThrown(const String&, std::unique_ptr<SourceLocation>) override
{
}
private:
WorkerThreadForTest* m_thread;
};
inline WorkerOrWorkletGlobalScope* WorkerThreadForTest::createWorkerGlobalScope(std::unique_ptr<WorkerThreadStartupData> startupData)
{
return new FakeWorkerGlobalScope(startupData->m_scriptURL, startupData->m_userAgent, this, std::move(startupData->m_starterOriginPrivilegeData), std::move(startupData->m_workerClients));
}
} // namespace blink