mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 757133: Implement a WorkerDebuggerManager; r=khuey
This commit is contained in:
parent
26bbf370e9
commit
b739736c39
@ -235,6 +235,7 @@
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
@BINPATH@/components/dom_webspeechrecognition.xpt
|
||||
#endif
|
||||
@BINPATH@/components/dom_workers.xpt
|
||||
@BINPATH@/components/dom_xbl.xpt
|
||||
@BINPATH@/components/dom_xpath.xpt
|
||||
@BINPATH@/components/dom_xul.xpt
|
||||
|
236
dom/workers/WorkerDebuggerManager.cpp
Normal file
236
dom/workers/WorkerDebuggerManager.cpp
Normal file
@ -0,0 +1,236 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WorkerDebuggerManager.h"
|
||||
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
#include "WorkerPrivate.h"
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
|
||||
class RegisterDebuggerRunnable MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
nsRefPtr<WorkerDebuggerManager> mManager;
|
||||
nsRefPtr<WorkerDebugger> mDebugger;
|
||||
bool mHasListeners;
|
||||
|
||||
public:
|
||||
RegisterDebuggerRunnable(WorkerDebuggerManager* aManager,
|
||||
WorkerDebugger* aDebugger,
|
||||
bool aHasListeners)
|
||||
: mManager(aManager), mDebugger(aDebugger), mHasListeners(aHasListeners)
|
||||
{ }
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
private:
|
||||
~RegisterDebuggerRunnable()
|
||||
{ }
|
||||
|
||||
NS_IMETHOD
|
||||
Run() MOZ_OVERRIDE
|
||||
{
|
||||
mManager->RegisterDebuggerOnMainThread(mDebugger, mHasListeners);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(RegisterDebuggerRunnable, nsIRunnable);
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class WorkerDebuggerEnumerator MOZ_FINAL : public nsISimpleEnumerator
|
||||
{
|
||||
nsTArray<nsCOMPtr<nsISupports>> mDebuggers;
|
||||
uint32_t mIndex;
|
||||
|
||||
public:
|
||||
WorkerDebuggerEnumerator(const nsTArray<WorkerDebugger*>& aDebuggers)
|
||||
: mIndex(0)
|
||||
{
|
||||
mDebuggers.AppendElements(aDebuggers);
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
private:
|
||||
~WorkerDebuggerEnumerator() {}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(WorkerDebuggerEnumerator, nsISimpleEnumerator);
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerDebuggerEnumerator::HasMoreElements(bool* aResult)
|
||||
{
|
||||
*aResult = mIndex < mDebuggers.Length();
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerDebuggerEnumerator::GetNext(nsISupports** aResult)
|
||||
{
|
||||
if (mIndex == mDebuggers.Length()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> element = mDebuggers.ElementAt(mIndex++);
|
||||
element.forget(aResult);
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
WorkerDebuggerManager::WorkerDebuggerManager()
|
||||
: mMutex("WorkerDebuggerManager::mMutex")
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
WorkerDebuggerManager::~WorkerDebuggerManager()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(WorkerDebuggerManager, nsIWorkerDebuggerManager);
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerDebuggerManager::GetWorkerDebuggerEnumerator(
|
||||
nsISimpleEnumerator** aResult)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
nsRefPtr<WorkerDebuggerEnumerator> enumerator =
|
||||
new WorkerDebuggerEnumerator(mDebuggers);
|
||||
enumerator.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerDebuggerManager::AddListener(nsIWorkerDebuggerManagerListener* aListener)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (mListeners.Contains(aListener)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
mListeners.AppendElement(aListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerDebuggerManager::RemoveListener(
|
||||
nsIWorkerDebuggerManagerListener* aListener)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (!mListeners.Contains(aListener)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mListeners.RemoveElement(aListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebuggerManager::RegisterDebugger(WorkerDebugger* aDebugger)
|
||||
{
|
||||
// May be called on any thread!
|
||||
|
||||
bool hasListeners = false;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
hasListeners = !mListeners.IsEmpty();
|
||||
}
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
RegisterDebuggerOnMainThread(aDebugger, hasListeners);
|
||||
} else {
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
new RegisterDebuggerRunnable(this, aDebugger, hasListeners);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)));
|
||||
|
||||
if (hasListeners) {
|
||||
aDebugger->WaitIsEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebuggerManager::UnregisterDebugger(WorkerDebugger* aDebugger)
|
||||
{
|
||||
// May be called on any thread!
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
UnregisterDebuggerOnMainThread(aDebugger);
|
||||
} else {
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethodWithArg<nsRefPtr<WorkerDebugger>>(this,
|
||||
&WorkerDebuggerManager::UnregisterDebuggerOnMainThread, aDebugger);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)));
|
||||
|
||||
aDebugger->WaitIsEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebuggerManager::RegisterDebuggerOnMainThread(WorkerDebugger* aDebugger,
|
||||
bool aHasListeners)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MOZ_ASSERT(!mDebuggers.Contains(aDebugger));
|
||||
mDebuggers.AppendElement(aDebugger);
|
||||
|
||||
nsTArray<nsCOMPtr<nsIWorkerDebuggerManagerListener>> listeners;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
listeners.AppendElements(mListeners);
|
||||
}
|
||||
|
||||
if (aHasListeners) {
|
||||
for (size_t index = 0; index < listeners.Length(); ++index) {
|
||||
listeners[index]->OnRegister(aDebugger);
|
||||
}
|
||||
}
|
||||
|
||||
aDebugger->Enable();
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebuggerManager::UnregisterDebuggerOnMainThread(WorkerDebugger* aDebugger)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MOZ_ASSERT(mDebuggers.Contains(aDebugger));
|
||||
mDebuggers.RemoveElement(aDebugger);
|
||||
|
||||
nsTArray<nsCOMPtr<nsIWorkerDebuggerManagerListener>> listeners;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
listeners.AppendElements(mListeners);
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < listeners.Length(); ++index) {
|
||||
listeners[index]->OnUnregister(aDebugger);
|
||||
}
|
||||
|
||||
aDebugger->Disable();
|
||||
}
|
||||
|
||||
END_WORKERS_NAMESPACE
|
95
dom/workers/WorkerDebuggerManager.h
Normal file
95
dom/workers/WorkerDebuggerManager.h
Normal file
@ -0,0 +1,95 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_workers_workerdebuggermanager_h
|
||||
#define mozilla_dom_workers_workerdebuggermanager_h
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "nsIWorkerDebuggerManager.h"
|
||||
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#define WORKERDEBUGGERMANAGER_CID \
|
||||
{ 0x62ec8731, 0x55ad, 0x4246, \
|
||||
{ 0xb2, 0xea, 0xf2, 0x6c, 0x1f, 0xe1, 0x9d, 0x2d } }
|
||||
#define WORKERDEBUGGERMANAGER_CONTRACTID \
|
||||
"@mozilla.org/dom/workers/workerdebuggermanager;1"
|
||||
|
||||
class RegisterDebuggerRunnable;
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class WorkerDebugger;
|
||||
|
||||
class WorkerDebuggerManager MOZ_FINAL : public nsIWorkerDebuggerManager
|
||||
{
|
||||
friend class ::RegisterDebuggerRunnable;
|
||||
|
||||
mozilla::Mutex mMutex;
|
||||
|
||||
// Protected by mMutex.
|
||||
nsTArray<nsCOMPtr<nsIWorkerDebuggerManagerListener>> mListeners;
|
||||
|
||||
// Only touched on the main thread.
|
||||
nsTArray<WorkerDebugger*> mDebuggers;
|
||||
|
||||
public:
|
||||
static WorkerDebuggerManager*
|
||||
GetOrCreateService()
|
||||
{
|
||||
nsCOMPtr<nsIWorkerDebuggerManager> wdm =
|
||||
do_GetService(WORKERDEBUGGERMANAGER_CONTRACTID);
|
||||
return static_cast<WorkerDebuggerManager*>(wdm.get());
|
||||
}
|
||||
|
||||
WorkerDebuggerManager();
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIWORKERDEBUGGERMANAGER
|
||||
|
||||
void RegisterDebugger(WorkerDebugger* aDebugger);
|
||||
|
||||
void UnregisterDebugger(WorkerDebugger* aDebugger);
|
||||
|
||||
private:
|
||||
virtual ~WorkerDebuggerManager();
|
||||
|
||||
void RegisterDebuggerOnMainThread(WorkerDebugger* aDebugger,
|
||||
bool aHasListeners);
|
||||
|
||||
void UnregisterDebuggerOnMainThread(WorkerDebugger* aDebugger);
|
||||
};
|
||||
|
||||
inline nsresult
|
||||
RegisterWorkerDebugger(WorkerDebugger* aDebugger)
|
||||
{
|
||||
nsRefPtr<WorkerDebuggerManager> manager =
|
||||
WorkerDebuggerManager::GetOrCreateService();
|
||||
if (!manager) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
manager->RegisterDebugger(aDebugger);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
inline nsresult
|
||||
UnregisterWorkerDebugger(WorkerDebugger* aDebugger)
|
||||
{
|
||||
nsRefPtr<WorkerDebuggerManager> manager =
|
||||
WorkerDebuggerManager::GetOrCreateService();
|
||||
if (!manager) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
manager->UnregisterDebugger(aDebugger);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_workers_workerdebuggermanager_h
|
@ -27,6 +27,7 @@
|
||||
#include "nsITimer.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIWorkerDebugger.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -80,6 +81,7 @@
|
||||
#include "ScriptLoader.h"
|
||||
#include "ServiceWorkerManager.h"
|
||||
#include "SharedWorker.h"
|
||||
#include "WorkerDebuggerManager.h"
|
||||
#include "WorkerFeature.h"
|
||||
#include "WorkerRunnable.h"
|
||||
#include "WorkerScope.h"
|
||||
@ -656,6 +658,8 @@ private:
|
||||
RuntimeService* runtime = RuntimeService::GetService();
|
||||
NS_ASSERTION(runtime, "This should never be null!");
|
||||
|
||||
mFinishedWorker->DisableDebugger();
|
||||
|
||||
runtime->UnregisterWorker(aCx, mFinishedWorker);
|
||||
|
||||
mFinishedWorker->ClearSelfRef();
|
||||
@ -690,6 +694,8 @@ private:
|
||||
AutoSafeJSContext cx;
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
mFinishedWorker->DisableDebugger();
|
||||
|
||||
runtime->UnregisterWorker(cx, mFinishedWorker);
|
||||
|
||||
nsTArray<nsCOMPtr<nsISupports> > doomed;
|
||||
@ -2142,6 +2148,42 @@ WorkerPrivateParent<Derived>::DispatchPrivate(WorkerRunnable* aRunnable,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::EnableDebugger()
|
||||
{
|
||||
AssertIsOnParentThread();
|
||||
|
||||
WorkerPrivate* self = ParentAsWorkerPrivate();
|
||||
|
||||
MOZ_ASSERT(!self->mDebugger);
|
||||
self->mDebugger = new WorkerDebugger(self);
|
||||
|
||||
if (NS_FAILED(RegisterWorkerDebugger(self->mDebugger))) {
|
||||
NS_WARNING("Failed to register worker debugger!");
|
||||
self->mDebugger = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::DisableDebugger()
|
||||
{
|
||||
AssertIsOnParentThread();
|
||||
|
||||
WorkerPrivate* self = ParentAsWorkerPrivate();
|
||||
|
||||
if (!self->mDebugger) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_FAILED(UnregisterWorkerDebugger(self->mDebugger))) {
|
||||
NS_WARNING("Failed to unregister worker debugger!");
|
||||
}
|
||||
|
||||
self->mDebugger = nullptr;
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
nsresult
|
||||
WorkerPrivateParent<Derived>::DispatchControlRunnable(
|
||||
@ -3448,6 +3490,94 @@ WorkerPrivateParent<Derived>::AssertInnerWindowIsCorrect() const
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
WorkerDebugger::WorkerDebugger(WorkerPrivate* aWorkerPrivate)
|
||||
: mMutex("WorkerDebugger::mMutex"),
|
||||
mCondVar(mMutex, "WorkerDebugger::mCondVar"),
|
||||
mWorkerPrivate(aWorkerPrivate),
|
||||
mIsEnabled(false)
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnParentThread();
|
||||
}
|
||||
|
||||
WorkerDebugger::~WorkerDebugger()
|
||||
{
|
||||
MOZ_ASSERT(!mWorkerPrivate);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(WorkerDebugger, nsIWorkerDebugger)
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerDebugger::GetIsClosed(bool* aResult)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
*aResult = !mWorkerPrivate;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerDebugger::GetUrl(nsAString& aResult)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (!mWorkerPrivate) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
aResult = mWorkerPrivate->ScriptURL();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebugger::WaitIsEnabled(bool aIsEnabled)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
while (mIsEnabled != aIsEnabled) {
|
||||
mCondVar.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebugger::NotifyIsEnabled(bool aIsEnabled)
|
||||
{
|
||||
mMutex.AssertCurrentThreadOwns();
|
||||
|
||||
MOZ_ASSERT(mIsEnabled != aIsEnabled);
|
||||
mIsEnabled = aIsEnabled;
|
||||
mCondVar.Notify();
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebugger::Enable()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
|
||||
NotifyIsEnabled(true);
|
||||
}
|
||||
|
||||
void
|
||||
WorkerDebugger::Disable()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
mWorkerPrivate = nullptr;
|
||||
|
||||
NotifyIsEnabled(false);
|
||||
}
|
||||
|
||||
WorkerPrivate::WorkerPrivate(JSContext* aCx,
|
||||
WorkerPrivate* aParent,
|
||||
const nsAString& aScriptURL,
|
||||
@ -3621,6 +3751,8 @@ WorkerPrivate::Constructor(JSContext* aCx,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
worker->EnableDebugger();
|
||||
|
||||
nsRefPtr<CompileScriptRunnable> compiler = new CompileScriptRunnable(worker);
|
||||
if (!compiler->Dispatch(aCx)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "Workers.h"
|
||||
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsIWorkerDebugger.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
#include "mozilla/CondVar.h"
|
||||
@ -61,6 +62,7 @@ class WorkerControlRunnable;
|
||||
class WorkerGlobalScope;
|
||||
class WorkerPrivate;
|
||||
class WorkerRunnable;
|
||||
class WorkerDebugger;
|
||||
|
||||
enum WorkerType
|
||||
{
|
||||
@ -294,6 +296,12 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WorkerPrivateParent,
|
||||
DOMEventTargetHelper)
|
||||
|
||||
void
|
||||
EnableDebugger();
|
||||
|
||||
void
|
||||
DisableDebugger();
|
||||
|
||||
void
|
||||
ClearSelfRef()
|
||||
{
|
||||
@ -721,6 +729,34 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
class WorkerDebugger : public nsIWorkerDebugger {
|
||||
mozilla::Mutex mMutex;
|
||||
mozilla::CondVar mCondVar;
|
||||
|
||||
// Protected by mMutex
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
bool mIsEnabled;
|
||||
|
||||
public:
|
||||
WorkerDebugger(WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIWORKERDEBUGGER
|
||||
|
||||
void AssertIsOnParentThread();
|
||||
|
||||
void WaitIsEnabled(bool aIsEnabled);
|
||||
|
||||
void Enable();
|
||||
|
||||
void Disable();
|
||||
|
||||
private:
|
||||
virtual ~WorkerDebugger();
|
||||
|
||||
void NotifyIsEnabled(bool aIsEnabled);
|
||||
};
|
||||
|
||||
class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
||||
{
|
||||
friend class WorkerPrivateParent<WorkerPrivate>;
|
||||
@ -739,6 +775,8 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
||||
NoTimer
|
||||
};
|
||||
|
||||
nsRefPtr<WorkerDebugger> mDebugger;
|
||||
|
||||
Queue<WorkerControlRunnable*, 4> mControlQueue;
|
||||
|
||||
// Touched on multiple threads, protected with mMutex.
|
||||
|
@ -16,6 +16,7 @@ EXPORTS.mozilla.dom += [
|
||||
|
||||
EXPORTS.mozilla.dom.workers += [
|
||||
'ServiceWorkerManager.h',
|
||||
'WorkerDebuggerManager.h',
|
||||
'Workers.h',
|
||||
]
|
||||
|
||||
@ -36,6 +37,13 @@ EXPORTS.mozilla.dom.workers.bindings += [
|
||||
'XMLHttpRequestUpload.h',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_workers'
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIWorkerDebugger.idl',
|
||||
'nsIWorkerDebuggerManager.idl',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'ChromeWorkerScope.cpp',
|
||||
'DataStore.cpp',
|
||||
@ -56,6 +64,7 @@ UNIFIED_SOURCES += [
|
||||
'ServiceWorkerRegistration.cpp',
|
||||
'SharedWorker.cpp',
|
||||
'URL.cpp',
|
||||
'WorkerDebuggerManager.cpp',
|
||||
'WorkerPrivate.cpp',
|
||||
'WorkerRunnable.cpp',
|
||||
'WorkerScope.cpp',
|
||||
|
9
dom/workers/nsIWorkerDebugger.idl
Normal file
9
dom/workers/nsIWorkerDebugger.idl
Normal file
@ -0,0 +1,9 @@
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(0833b363-bffe-4cdb-ad50-1c4563e0C8ff)]
|
||||
interface nsIWorkerDebugger : nsISupports
|
||||
{
|
||||
readonly attribute bool isClosed;
|
||||
|
||||
readonly attribute DOMString url;
|
||||
};
|
22
dom/workers/nsIWorkerDebuggerManager.idl
Normal file
22
dom/workers/nsIWorkerDebuggerManager.idl
Normal file
@ -0,0 +1,22 @@
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsIWorkerDebugger;
|
||||
|
||||
[scriptable, uuid(d2aa74ee-6b98-4d5d-8173-4e23422daf1e)]
|
||||
interface nsIWorkerDebuggerManagerListener : nsISupports
|
||||
{
|
||||
void onRegister(in nsIWorkerDebugger debugger);
|
||||
|
||||
void onUnregister(in nsIWorkerDebugger debugger);
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(056d7918-dc86-452a-b4e6-86da3405f015)]
|
||||
interface nsIWorkerDebuggerManager : nsISupports
|
||||
{
|
||||
nsISimpleEnumerator getWorkerDebuggerEnumerator();
|
||||
|
||||
void addListener(in nsIWorkerDebuggerManagerListener listener);
|
||||
|
||||
void removeListener(in nsIWorkerDebuggerManagerListener listener);
|
||||
};
|
3
dom/workers/test/WorkerDebuggerManager_childWorker.js
Normal file
3
dom/workers/test/WorkerDebuggerManager_childWorker.js
Normal file
@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
|
||||
onmessage = function () {};
|
3
dom/workers/test/WorkerDebuggerManager_parentWorker.js
Normal file
3
dom/workers/test/WorkerDebuggerManager_parentWorker.js
Normal file
@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
|
||||
var worker = new Worker("WorkerDebuggerManager_childWorker.js");
|
@ -1,11 +1,15 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
WorkerDebuggerManager_childWorker.js
|
||||
WorkerDebuggerManager_parentWorker.js
|
||||
WorkerTest.jsm
|
||||
WorkerTest_subworker.js
|
||||
WorkerTest_worker.js
|
||||
chromeWorker_subworker.js
|
||||
chromeWorker_worker.js
|
||||
dom_worker_helper.js
|
||||
file_url.jsm
|
||||
file_worker.js
|
||||
fileBlobSubWorker_worker.js
|
||||
fileBlob_worker.js
|
||||
filePosting_worker.js
|
||||
@ -20,6 +24,7 @@ support-files =
|
||||
file_url.jsm
|
||||
bug1062920_worker.js
|
||||
|
||||
[test_WorkerDebuggerManager.xul]
|
||||
[test_bug883784.jsm]
|
||||
[test_bug883784.xul]
|
||||
[test_chromeWorker.xul]
|
||||
|
@ -3,6 +3,16 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/AddonManager.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const wdm = Cc["@mozilla.org/dom/workers/workerdebuggermanager;1"].
|
||||
getService(Ci.nsIWorkerDebuggerManager);
|
||||
|
||||
var gRemainingTests = 0;
|
||||
|
||||
function waitForWorkerFinish() {
|
||||
@ -19,3 +29,74 @@ function finish() {
|
||||
}
|
||||
}
|
||||
|
||||
function assertThrows(fun, message) {
|
||||
let throws = false;
|
||||
try {
|
||||
fun();
|
||||
} catch (e) {
|
||||
throws = true;
|
||||
}
|
||||
ok(throws, message);
|
||||
}
|
||||
|
||||
function* generateDebuggers() {
|
||||
let e = wdm.getWorkerDebuggerEnumerator();
|
||||
while (e.hasMoreElements()) {
|
||||
let dbg = e.getNext().QueryInterface(Ci.nsIWorkerDebugger);
|
||||
yield dbg;
|
||||
}
|
||||
}
|
||||
|
||||
function findDebugger(predicate) {
|
||||
for (let dbg of generateDebuggers()) {
|
||||
if (predicate(dbg)) {
|
||||
return dbg;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function waitForRegister(predicate = () => true) {
|
||||
return new Promise(function (resolve) {
|
||||
wdm.addListener({
|
||||
onRegister: function (dbg) {
|
||||
if (!predicate(dbg)) {
|
||||
return;
|
||||
}
|
||||
wdm.removeListener(this);
|
||||
resolve(dbg);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForUnregister(predicate = () => true) {
|
||||
return new Promise(function (resolve) {
|
||||
wdm.addListener({
|
||||
onUnregister: function (dbg) {
|
||||
if (!predicate(dbg)) {
|
||||
return;
|
||||
}
|
||||
wdm.removeListener(this);
|
||||
resolve(dbg);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForMultiple(promises) {
|
||||
return new Promise(function (resolve) {
|
||||
let results = [];
|
||||
for (let i = 0; i < promises.length; ++i) {
|
||||
let promise = promises[i];
|
||||
let index = i;
|
||||
promise.then(function (result) {
|
||||
is(results.length, index, "events should occur in the specified order");
|
||||
results.push(result);
|
||||
if (results.length === promises.length) {
|
||||
resolve(results);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
92
dom/workers/test/test_WorkerDebuggerManager.xul
Normal file
92
dom/workers/test/test_WorkerDebuggerManager.xul
Normal file
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<window title="Test for WorkerDebuggerManager"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="test();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
|
||||
<script type="application/javascript" src="dom_worker_helper.js"/>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
const PARENT_WORKER_URL = "WorkerDebuggerManager_parentWorker.js";
|
||||
const CHILD_WORKER_URL = "WorkerDebuggerManager_childWorker.js";
|
||||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
ok(!findDebugger((dbg) => dbg.url === PARENT_WORKER_URL),
|
||||
"debugger for parent worker should not be enumerated before it is " +
|
||||
"registered");
|
||||
ok(!findDebugger((dbg) => dbg.url === CHILD_WORKER_URL),
|
||||
"debugger for child worker should not be enumerated before it is " +
|
||||
"registered");
|
||||
|
||||
let promise = waitForMultiple([
|
||||
waitForRegister((dbg) => dbg.url === PARENT_WORKER_URL),
|
||||
waitForRegister((dbg) => dbg.url === CHILD_WORKER_URL),
|
||||
]);
|
||||
let worker = new Worker(PARENT_WORKER_URL);
|
||||
let dbgs = yield promise;
|
||||
is(dbgs[0].isClosed, false,
|
||||
"debugger for parent worker should not be closed after it is " +
|
||||
"registered");
|
||||
is(dbgs[1].isClosed, false,
|
||||
"debugger for child worker should not be closed after it is " +
|
||||
"registered");
|
||||
|
||||
ok(findDebugger((dbg) => dbg.url === PARENT_WORKER_URL),
|
||||
"debugger for parent worker should be enumerated after it is " +
|
||||
"registered");
|
||||
ok(findDebugger((dbg) => dbg.url === CHILD_WORKER_URL),
|
||||
"debugger for child worker should be enumerated after it is " +
|
||||
"registered");
|
||||
|
||||
promise = waitForMultiple([
|
||||
waitForUnregister((dbg) => dbg.url === CHILD_WORKER_URL),
|
||||
waitForUnregister((dbg) => dbg.url === PARENT_WORKER_URL),
|
||||
]);
|
||||
worker.terminate();
|
||||
dbgs = yield promise;
|
||||
is(dbgs[0].isClosed, true,
|
||||
"debugger for parent worker should be closed after it is " +
|
||||
"unregistered");
|
||||
is(dbgs[1].isClosed, true,
|
||||
"debugger for child worker should be closed after it is " +
|
||||
"unregistered");
|
||||
assertThrows(() => dbgs[0].url,
|
||||
"accessing debugger for parent worker should throw " +
|
||||
"after it is closed");
|
||||
assertThrows(() => dbgs[0].url,
|
||||
"accessing debugger for child worker should throw after " +
|
||||
"it is closed");
|
||||
|
||||
ok(!findDebugger((dbg) => dbg.url === PARENT_WORKER_URL),
|
||||
"debugger for parent worker should not be enumerated after it is " +
|
||||
"unregistered");
|
||||
ok(!findDebugger((dbg) => dbg.url === CHILD_WORKER_URL),
|
||||
"debugger for child worker should not be enumerated after it is " +
|
||||
"unregistered");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display:none;"></div>
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
<label id="test-result"/>
|
||||
</window>
|
@ -16,13 +16,6 @@
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function test() {
|
||||
const message = "woohoo";
|
||||
|
||||
|
@ -16,14 +16,6 @@
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/AddonManager.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function test() {
|
||||
const message = "woohoo";
|
||||
|
||||
|
@ -90,6 +90,7 @@
|
||||
#include "mozilla/dom/network/UDPSocketChild.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/dom/workers/ServiceWorkerManager.h"
|
||||
#include "mozilla/dom/workers/WorkerDebuggerManager.h"
|
||||
#include "mozilla/OSFileConstants.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
@ -248,6 +249,7 @@ using mozilla::dom::alarm::AlarmHalService;
|
||||
using mozilla::dom::power::PowerManagerService;
|
||||
using mozilla::dom::quota::QuotaManager;
|
||||
using mozilla::dom::workers::ServiceWorkerManager;
|
||||
using mozilla::dom::workers::WorkerDebuggerManager;
|
||||
using mozilla::dom::TCPSocketChild;
|
||||
using mozilla::dom::TCPSocketParent;
|
||||
using mozilla::dom::TCPServerSocketChild;
|
||||
@ -287,6 +289,8 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(QuotaManager,
|
||||
QuotaManager::FactoryCreate)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ServiceWorkerManager,
|
||||
ServiceWorkerManager::FactoryCreate)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(WorkerDebuggerManager)
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(SystemWorkerManager,
|
||||
SystemWorkerManager::FactoryCreate)
|
||||
@ -715,6 +719,7 @@ NS_DEFINE_NAMED_CID(NS_TEXTEDITOR_CID);
|
||||
NS_DEFINE_NAMED_CID(DOMREQUEST_SERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(QUOTA_MANAGER_CID);
|
||||
NS_DEFINE_NAMED_CID(SERVICEWORKERMANAGER_CID);
|
||||
NS_DEFINE_NAMED_CID(WORKERDEBUGGERMANAGER_CID);
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_DEFINE_NAMED_CID(SYSTEMWORKERMANAGER_CID);
|
||||
#endif
|
||||
@ -1005,6 +1010,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
|
||||
{ &kDOMREQUEST_SERVICE_CID, false, nullptr, DOMRequestServiceConstructor },
|
||||
{ &kQUOTA_MANAGER_CID, false, nullptr, QuotaManagerConstructor },
|
||||
{ &kSERVICEWORKERMANAGER_CID, false, nullptr, ServiceWorkerManagerConstructor },
|
||||
{ &kWORKERDEBUGGERMANAGER_CID, true, nullptr, WorkerDebuggerManagerConstructor },
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
{ &kSYSTEMWORKERMANAGER_CID, true, nullptr, SystemWorkerManagerConstructor },
|
||||
#endif
|
||||
@ -1162,6 +1168,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
|
||||
{ DOMREQUEST_SERVICE_CONTRACTID, &kDOMREQUEST_SERVICE_CID },
|
||||
{ QUOTA_MANAGER_CONTRACTID, &kQUOTA_MANAGER_CID },
|
||||
{ SERVICEWORKERMANAGER_CONTRACTID, &kSERVICEWORKERMANAGER_CID },
|
||||
{ WORKERDEBUGGERMANAGER_CONTRACTID, &kWORKERDEBUGGERMANAGER_CID },
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
{ SYSTEMWORKERMANAGER_CONTRACTID, &kSYSTEMWORKERMANAGER_CID },
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user