Bug 1217909 P1 Report service worker exceptions to controlled documents. r=catalinb

* * *
Bug 1217909 P1 interdiff 001 refactor
This commit is contained in:
Ben Kelly 2015-11-16 08:04:11 -08:00
Родитель 2a23ba2a31
Коммит c311fd953d
4 изменённых файлов: 108 добавлений и 54 удалений

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

@ -2399,14 +2399,53 @@ ServiceWorkerManager::FinishFetch(ServiceWorkerRegistrationInfo* aRegistration)
{
}
bool
void
ServiceWorkerManager::ReportToAllClients(const nsCString& aScope,
const nsString& aMessage,
const nsString& aFilename,
const nsString& aLine,
uint32_t aLineNumber,
uint32_t aColumnNumber,
uint32_t aFlags)
{
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), aFilename);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Report errors to the consoles of every controlled document
for (auto iter = mControlledDocuments.Iter(); !iter.Done(); iter.Next()) {
ServiceWorkerRegistrationInfo* reg = iter.UserData();
MOZ_ASSERT(reg);
if (!reg->mScope.Equals(aScope)) {
continue;
}
nsCOMPtr<nsIDocument> doc = do_QueryInterface(iter.Key());
if (!doc || !doc->GetWindow()) {
continue;
}
nsContentUtils::ReportToConsoleNonLocalized(aMessage,
aFlags,
NS_LITERAL_CSTRING("Service Workers"),
doc,
uri,
aLine,
aLineNumber,
aColumnNumber);
}
}
void
ServiceWorkerManager::HandleError(JSContext* aCx,
nsIPrincipal* aPrincipal,
const nsCString& aScope,
const nsString& aWorkerURL,
nsString aMessage,
nsString aFilename,
nsString aLine,
const nsString& aMessage,
const nsString& aFilename,
const nsString& aLine,
uint32_t aLineNumber,
uint32_t aColumnNumber,
uint32_t aFlags,
@ -2414,46 +2453,47 @@ ServiceWorkerManager::HandleError(JSContext* aCx,
{
AssertIsOnMainThread();
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(!JSREPORT_IS_WARNING(aFlags));
nsAutoCString scopeKey;
nsresult rv = PrincipalToScopeKey(aPrincipal, scopeKey);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
return;
}
ServiceWorkerManager::RegistrationDataPerPrincipal* data;
if (!mRegistrationInfos.Get(scopeKey, &data)) {
return false;
if (NS_WARN_IF(!mRegistrationInfos.Get(scopeKey, &data))) {
return;
}
if (!data->mSetOfScopesBeingUpdated.Contains(aScope)) {
return false;
// If this is a failure, we may need to cancel an in-progress registration.
if (!JSREPORT_IS_WARNING(aFlags)) {
ServiceWorkerJob* job = nullptr;
if (data->mSetOfScopesBeingUpdated.Contains(aScope)) {
data->mSetOfScopesBeingUpdated.Remove(aScope);
ServiceWorkerJobQueue* queue = data->mJobQueues.Get(aScope);
MOZ_ASSERT(queue);
job = queue->Peek();
}
if (job) {
MOZ_ASSERT(job->IsRegisterJob());
RefPtr<ServiceWorkerRegisterJob> regJob =
static_cast<ServiceWorkerRegisterJob*>(job);
RootedDictionary<ErrorEventInit> init(aCx);
init.mMessage = aMessage;
init.mFilename = aFilename;
init.mLineno = aLineNumber;
init.mColno = aColumnNumber;
regJob->Fail(aExnType, init);
}
}
data->mSetOfScopesBeingUpdated.Remove(aScope);
ServiceWorkerJobQueue* queue = data->mJobQueues.Get(aScope);
MOZ_ASSERT(queue);
ServiceWorkerJob* job = queue->Peek();
if (job) {
MOZ_ASSERT(job->IsRegisterJob());
RefPtr<ServiceWorkerRegisterJob> regJob = static_cast<ServiceWorkerRegisterJob*>(job);
RootedDictionary<ErrorEventInit> init(aCx);
init.mMessage = aMessage;
init.mFilename = aFilename;
init.mLineno = aLineNumber;
init.mColno = aColumnNumber;
NS_WARNING(nsPrintfCString(
"Script error caused ServiceWorker registration to fail: %s:%u '%s'",
NS_ConvertUTF16toUTF8(aFilename).get(), aLineNumber,
NS_ConvertUTF16toUTF8(aMessage).get()).get());
regJob->Fail(aExnType, init);
}
return true;
ReportToAllClients(aScope, aMessage, aFilename, aLine, aLineNumber,
aColumnNumber, aFlags);
}
void

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

@ -389,16 +389,25 @@ public:
void
FinishFetch(ServiceWorkerRegistrationInfo* aRegistration);
// Returns true if the error was handled, false if normal worker error
// handling should continue.
bool
void
ReportToAllClients(const nsCString& aScope,
const nsString& aMessage,
const nsString& aFilename,
const nsString& aLine,
uint32_t aLineNumber,
uint32_t aColumnNumber,
uint32_t aFlags);
// Always consumes the error by reporting to consoles of all controlled
// documents.
void
HandleError(JSContext* aCx,
nsIPrincipal* aPrincipal,
const nsCString& aScope,
const nsString& aWorkerURL,
nsString aMessage,
nsString aFilename,
nsString aLine,
const nsString& aMessage,
const nsString& aFilename,
const nsString& aLine,
uint32_t aLineNumber,
uint32_t aColumnNumber,
uint32_t aFlags,

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

@ -1173,6 +1173,10 @@ private:
event->ReportCanceled();
runnable = new CancelChannelRunnable(mInterceptedChannel,
NS_ERROR_INTERCEPTION_FAILED);
} else if (event->GetInternalNSEvent()->mFlags.mExceptionHasBeenRisen) {
// Exception logged via the WorkerPrivate ErrorReporter
runnable = new CancelChannelRunnable(mInterceptedChannel,
NS_ERROR_INTERCEPTION_FAILED);
} else {
runnable = new ResumeRequest(mInterceptedChannel);
}

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

@ -1070,27 +1070,28 @@ private:
return true;
}
if (aWorkerPrivate->IsServiceWorker() || aWorkerPrivate->IsSharedWorker()) {
if (aWorkerPrivate->IsServiceWorker() && !JSREPORT_IS_WARNING(mFlags)) {
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(swm);
bool handled = swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
aWorkerPrivate->WorkerName(),
aWorkerPrivate->ScriptURL(),
mMessage,
mFilename, mLine, mLineNumber,
mColumnNumber, mFlags, mExnType);
if (handled) {
return true;
}
}
if (aWorkerPrivate->IsSharedWorker()) {
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, mMessage, mFilename,
mLine, mLineNumber,
mColumnNumber, mFlags);
return true;
}
// Service workers do not have a main thread parent global, so normal
// worker error reporting will crash. Instead, pass the error to
// the ServiceWorkerManager to report on any controlled documents.
if (aWorkerPrivate->IsServiceWorker()) {
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(swm);
swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
aWorkerPrivate->WorkerName(),
aWorkerPrivate->ScriptURL(),
mMessage,
mFilename, mLine, mLineNumber,
mColumnNumber, mFlags, mExnType);
return true;
}
// The innerWindowId is only required if we are going to ReportError
// below, which is gated on this condition. The inner window correctness
// check is only going to succeed when the worker is accepting events.