Bug 1288768 - Better error reporting for network errors in workers, r=bz

This commit is contained in:
Andrea Marchesini 2017-01-28 15:39:24 +01:00
Родитель fed1d780de
Коммит e14c51cdfd
5 изменённых файлов: 131 добавлений и 25 удалений

Просмотреть файл

@ -402,8 +402,17 @@ Event::Constructor(const GlobalObject& aGlobal,
ErrorResult& aRv)
{
nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
RefPtr<Event> e = new Event(t, nullptr, nullptr);
bool trusted = e->Init(t);
return Constructor(t, aType, aParam);
}
// static
already_AddRefed<Event>
Event::Constructor(EventTarget* aEventTarget,
const nsAString& aType,
const EventInit& aParam)
{
RefPtr<Event> e = new Event(aEventTarget, nullptr, nullptr);
bool trusted = e->Init(aEventTarget);
e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
e->SetTrusted(trusted);
e->SetComposed(aParam.mComposed);
@ -1207,7 +1216,7 @@ Event::Deserialize(const IPC::Message* aMsg, PickleIterator* aIter)
}
NS_IMETHODIMP_(void)
Event::SetOwner(mozilla::dom::EventTarget* aOwner)
Event::SetOwner(EventTarget* aOwner)
{
mOwner = nullptr;

Просмотреть файл

@ -142,6 +142,10 @@ public:
LayoutDeviceIntPoint aPoint,
CSSIntPoint aDefaultPoint);
static already_AddRefed<Event> Constructor(EventTarget* aEventTarget,
const nsAString& aType,
const EventInit& aParam);
static already_AddRefed<Event> Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const EventInit& aParam,

Просмотреть файл

@ -494,6 +494,82 @@ private:
}
};
class ReportCompileErrorRunnable final : public WorkerRunnable
{
public:
static void
CreateAndDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
RefPtr<ReportCompileErrorRunnable> runnable =
new ReportCompileErrorRunnable(aCx, aWorkerPrivate);
runnable->Dispatch();
}
private:
ReportCompileErrorRunnable(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
: WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount)
{
aWorkerPrivate->AssertIsOnWorkerThread();
}
void
PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
{
aWorkerPrivate->AssertIsOnWorkerThread();
// Dispatch may fail if the worker was canceled, no need to report that as
// an error, so don't call base class PostDispatch.
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
{
if (aWorkerPrivate->IsFrozen() ||
aWorkerPrivate->IsParentWindowPaused()) {
MOZ_ASSERT(!IsDebuggerRunnable());
aWorkerPrivate->QueueRunnable(this);
return true;
}
if (aWorkerPrivate->IsSharedWorker()) {
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, EmptyString(),
EmptyString(),
EmptyString(), 0, 0,
JSREPORT_ERROR,
/* isErrorEvent */ false);
return true;
}
if (aWorkerPrivate->IsServiceWorker()) {
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
if (swm) {
swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
aWorkerPrivate->WorkerName(),
aWorkerPrivate->ScriptURL(),
EmptyString(), EmptyString(), EmptyString(),
0, 0, JSREPORT_ERROR, JSEXN_ERR);
}
return true;
}
if (!aWorkerPrivate->IsAcceptingEvents()) {
return true;
}
RefPtr<Event> event =
Event::Constructor(aWorkerPrivate, NS_LITERAL_STRING("error"),
EventInit());
event->SetTrusted(true);
nsEventStatus status = nsEventStatus_eIgnore;
aWorkerPrivate->DispatchDOMEvent(nullptr, event, nullptr, &status);
return true;
}
};
class CompileScriptRunnable final : public WorkerRunnable
{
nsString mScriptURL;
@ -537,9 +613,15 @@ private:
}
// Make sure to propagate exceptions from rv onto aCx, so that they will get
// reported after we return. We do this for all failures on rv, because now
// we're using rv to track all the state we care about.
//
// reported after we return. We want to propagate just JS exceptions,
// because all the other errors are handled when the script is loaded.
// See: https://dom.spec.whatwg.org/#concept-event-fire
if (rv.Failed() && !rv.IsJSException()) {
ReportCompileErrorRunnable::CreateAndDispatch(aCx, aWorkerPrivate);
rv.SuppressException();
return false;
}
// This is a little dumb, but aCx is in the null compartment here because we
// set it up that way in our Run(), since we had not created the global at
// that point yet. So we need to enter the compartment of our global,
@ -1117,7 +1199,8 @@ private:
if (aWorkerPrivate->IsSharedWorker()) {
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, mMessage, mFilename,
mLine, mLineNumber,
mColumnNumber, mFlags);
mColumnNumber, mFlags,
/* isErrorEvent */ true);
return true;
}
@ -3291,7 +3374,8 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
const nsAString& aLine,
uint32_t aLineNumber,
uint32_t aColumnNumber,
uint32_t aFlags)
uint32_t aFlags,
bool aIsErrorEvent)
{
AssertIsOnMainThread();
@ -3322,31 +3406,42 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
// May be null.
nsPIDOMWindowInner* window = sharedWorker->GetOwner();
RootedDictionary<ErrorEventInit> errorInit(aCx);
errorInit.mBubbles = false;
errorInit.mCancelable = true;
errorInit.mMessage = aMessage;
errorInit.mFilename = aFilename;
errorInit.mLineno = aLineNumber;
errorInit.mColno = aColumnNumber;
RefPtr<Event> event;
RefPtr<ErrorEvent> errorEvent =
ErrorEvent::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
errorInit);
if (!errorEvent) {
if (aIsErrorEvent) {
RootedDictionary<ErrorEventInit> errorInit(aCx);
errorInit.mBubbles = false;
errorInit.mCancelable = true;
errorInit.mMessage = aMessage;
errorInit.mFilename = aFilename;
errorInit.mLineno = aLineNumber;
errorInit.mColno = aColumnNumber;
event = ErrorEvent::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
errorInit);
} else {
event = Event::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
EventInit());
}
if (!event) {
ThrowAndReport(window, NS_ERROR_UNEXPECTED);
continue;
}
errorEvent->SetTrusted(true);
event->SetTrusted(true);
bool defaultActionEnabled;
nsresult rv = sharedWorker->DispatchEvent(errorEvent, &defaultActionEnabled);
nsresult rv = sharedWorker->DispatchEvent(event, &defaultActionEnabled);
if (NS_FAILED(rv)) {
ThrowAndReport(window, rv);
continue;
}
if (!aIsErrorEvent) {
continue;
}
if (defaultActionEnabled) {
// Add the owning window to our list so that we will fire an error event
// at it later.

Просмотреть файл

@ -403,7 +403,8 @@ public:
const nsAString& aLine,
uint32_t aLineNumber,
uint32_t aColumnNumber,
uint32_t aFlags);
uint32_t aFlags,
bool aIsErrorEvent);
void
WorkerScriptLoaded();

Просмотреть файл

@ -1,3 +0,0 @@
[worker.html]
type: testharness
expected: ERROR