From 82cfe6ab4d94953531dfaf6349c0236ea6e8a6f3 Mon Sep 17 00:00:00 2001 From: Catalin Badea Date: Mon, 19 Dec 2016 04:38:53 +0200 Subject: [PATCH 01/21] Bug 1181127 - Don't run service workers for fetch events if no fetch handlers were added during script's evaluation. r=bkelly Display a warning when event listeners are added after the script's evaluation. --- dom/locales/en-US/chrome/dom/dom.properties | 2 + dom/workers/ServiceWorkerInfo.cpp | 1 + dom/workers/ServiceWorkerInfo.h | 22 +++++ dom/workers/ServiceWorkerManager.cpp | 3 + dom/workers/ServiceWorkerPrivate.cpp | 86 ++++++++++++++----- dom/workers/ServiceWorkerPrivate.h | 3 + dom/workers/ServiceWorkerRegistrar.cpp | 45 ++++++++++ dom/workers/ServiceWorkerRegistrar.h | 2 +- dom/workers/ServiceWorkerRegistrarTypes.ipdlh | 1 + dom/workers/WorkerPrivate.cpp | 1 + dom/workers/WorkerPrivate.h | 17 ++++ dom/workers/WorkerScope.cpp | 83 ++++++++++++++++++ dom/workers/WorkerScope.h | 14 ++- 13 files changed, 257 insertions(+), 23 deletions(-) diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties index f293c2300498..49aaca1ab7be 100644 --- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -229,6 +229,8 @@ ServiceWorkerRegisterNetworkError=Failed to register/update a ServiceWorker for ServiceWorkerRegisterMimeTypeError=Failed to register/update a ServiceWorker for scope ‘%1$S’: Bad Content-Type of ‘%2$S’ received for script ‘%3$S’. Must be ‘text/javascript’, ‘application/x-javascript’, or ‘application/javascript’. # LOCALIZATION NOTE: Do not translate "ServiceWorker". %1$S is a URL representing the scope of the ServiceWorker. ServiceWorkerGraceTimeoutTermination=Terminating ServiceWorker for scope ‘%1$S’ with pending waitUntil/respondWith promises because of grace timeout. +# LOCALIZATION NOTE (ServiceWorkerNoFetchHandler): Do not translate "Fetch". +ServiceWorkerNoFetchHandler=Fetch event handlers must be added during the worker script’s initial evaluation. ExecCommandCutCopyDeniedNotInputDriven=document.execCommand(‘cut’/‘copy’) was denied because it was not called from inside a short running user-generated event handler. ManifestShouldBeObject=Manifest should be an object. ManifestScopeURLInvalid=The scope URL is invalid. diff --git a/dom/workers/ServiceWorkerInfo.cpp b/dom/workers/ServiceWorkerInfo.cpp index fa08b97a6b17..5d7644b63078 100644 --- a/dom/workers/ServiceWorkerInfo.cpp +++ b/dom/workers/ServiceWorkerInfo.cpp @@ -180,6 +180,7 @@ ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal, , mServiceWorkerID(GetNextID()) , mServiceWorkerPrivate(new ServiceWorkerPrivate(this)) , mSkipWaitingFlag(false) + , mHandlesFetch(Unknown) { MOZ_ASSERT(mPrincipal); // cache origin attributes so we can use them off main thread diff --git a/dom/workers/ServiceWorkerInfo.h b/dom/workers/ServiceWorkerInfo.h index 80910bdad1b9..c82b1696d5c8 100644 --- a/dom/workers/ServiceWorkerInfo.h +++ b/dom/workers/ServiceWorkerInfo.h @@ -46,6 +46,12 @@ private: RefPtr mServiceWorkerPrivate; bool mSkipWaitingFlag; + enum { + Unknown, + Enabled, + Disabled + } mHandlesFetch; + ~ServiceWorkerInfo(); // Generates a unique id for the service worker, with zero being treated as @@ -134,6 +140,22 @@ public: mState = aState; } + void + SetHandlesFetch(bool aHandlesFetch) + { + AssertIsOnMainThread(); + MOZ_DIAGNOSTIC_ASSERT(mHandlesFetch == Unknown); + mHandlesFetch = aHandlesFetch ? Enabled : Disabled; + } + + bool + HandlesFetch() const + { + AssertIsOnMainThread(); + MOZ_DIAGNOSTIC_ASSERT(mHandlesFetch != Unknown); + return mHandlesFetch != Disabled; + } + void AppendWorker(ServiceWorker* aWorker); diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index e5f90cbf494a..2e7cb8f5efde 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -184,6 +184,7 @@ PopulateRegistrationData(nsIPrincipal* aPrincipal, if (aRegistration->GetActive()) { aData.currentWorkerURL() = aRegistration->GetActive()->ScriptSpec(); aData.cacheName() = aRegistration->GetActive()->CacheName(); + aData.currentWorkerHandlesFetch() = aRegistration->GetActive()->HandlesFetch(); } return NS_OK; @@ -1697,6 +1698,8 @@ ServiceWorkerManager::LoadRegistration( registration->SetActive( new ServiceWorkerInfo(registration->mPrincipal, registration->mScope, currentWorkerURL, aRegistration.cacheName())); + + registration->GetActive()->SetHandlesFetch(aRegistration.currentWorkerHandlesFetch()); registration->GetActive()->SetActivateStateUncheckedWithoutEvent(ServiceWorkerState::Activated); } } diff --git a/dom/workers/ServiceWorkerPrivate.cpp b/dom/workers/ServiceWorkerPrivate.cpp index a754d8610bc6..36d81bb75154 100644 --- a/dom/workers/ServiceWorkerPrivate.cpp +++ b/dom/workers/ServiceWorkerPrivate.cpp @@ -107,19 +107,26 @@ namespace { class CheckScriptEvaluationWithCallback final : public WorkerRunnable { + nsMainThreadPtrHandle mServiceWorkerPrivate; nsMainThreadPtrHandle mKeepAliveToken; - RefPtr mCallback; + + // The script evaluation result must be reported even if the runnable + // is cancelled. + RefPtr mScriptEvaluationCallback; + #ifdef DEBUG bool mDone; #endif public: CheckScriptEvaluationWithCallback(WorkerPrivate* aWorkerPrivate, + ServiceWorkerPrivate* aServiceWorkerPrivate, KeepAliveToken* aKeepAliveToken, - LifeCycleEventCallback* aCallback) + LifeCycleEventCallback* aScriptEvaluationCallback) : WorkerRunnable(aWorkerPrivate) + , mServiceWorkerPrivate(new nsMainThreadPtrHolder(aServiceWorkerPrivate)) , mKeepAliveToken(new nsMainThreadPtrHolder(aKeepAliveToken)) - , mCallback(aCallback) + , mScriptEvaluationCallback(aScriptEvaluationCallback) #ifdef DEBUG , mDone(false) #endif @@ -136,42 +143,55 @@ public: WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { aWorkerPrivate->AssertIsOnWorkerThread(); - Done(aWorkerPrivate->WorkerScriptExecutedSuccessfully()); + + bool fetchHandlerWasAdded = aWorkerPrivate->FetchHandlerWasAdded(); + nsCOMPtr runnable = NewRunnableMethod(this, + &CheckScriptEvaluationWithCallback::ReportFetchFlag, fetchHandlerWasAdded); + aWorkerPrivate->DispatchToMainThread(runnable.forget()); + + ReportScriptEvaluationResult(aWorkerPrivate->WorkerScriptExecutedSuccessfully()); return true; } + void + ReportFetchFlag(bool aFetchHandlerWasAdded) + { + AssertIsOnMainThread(); + mServiceWorkerPrivate->SetHandlesFetch(aFetchHandlerWasAdded); + } + nsresult Cancel() override { - Done(false); + ReportScriptEvaluationResult(false); return WorkerRunnable::Cancel(); } private: void - Done(bool aResult) + ReportScriptEvaluationResult(bool aScriptEvaluationResult) { #ifdef DEBUG mDone = true; #endif - mCallback->SetResult(aResult); - MOZ_ALWAYS_SUCCEEDS(mWorkerPrivate->DispatchToMainThread(mCallback)); + mScriptEvaluationCallback->SetResult(aScriptEvaluationResult); + MOZ_ALWAYS_SUCCEEDS(mWorkerPrivate->DispatchToMainThread(mScriptEvaluationCallback)); } }; } // anonymous namespace nsresult -ServiceWorkerPrivate::CheckScriptEvaluation(LifeCycleEventCallback* aCallback) +ServiceWorkerPrivate::CheckScriptEvaluation(LifeCycleEventCallback* aScriptEvaluationCallback) { nsresult rv = SpawnWorkerIfNeeded(LifeCycleEvent, nullptr); NS_ENSURE_SUCCESS(rv, rv); RefPtr token = CreateEventKeepAliveToken(); RefPtr r = new CheckScriptEvaluationWithCallback(mWorkerPrivate, - token, - aCallback); + this, token, + aScriptEvaluationCallback); if (NS_WARN_IF(!r->Dispatch())) { return NS_ERROR_FAILURE; } @@ -1682,6 +1702,28 @@ ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel, { AssertIsOnMainThread(); + if (NS_WARN_IF(!mInfo)) { + return NS_ERROR_FAILURE; + } + + RefPtr swm = ServiceWorkerManager::GetInstance(); + MOZ_ASSERT(swm); + + RefPtr registration = + swm->GetRegistration(mInfo->GetPrincipal(), mInfo->Scope()); + + // Handle Fetch algorithm - step 16. If the service worker didn't register + // any fetch event handlers, then abort the interception and maybe trigger + // the soft update algorithm. + if (!mInfo->HandlesFetch()) { + aChannel->ResetInterception(); + + // Trigger soft updates if necessary. + registration->MaybeScheduleTimeCheckAndUpdate(); + + return NS_OK; + } + // if the ServiceWorker script fails to load for some reason, just resume // the original channel. nsCOMPtr failRunnable = @@ -1693,16 +1735,6 @@ ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel, nsMainThreadPtrHandle handle( new nsMainThreadPtrHolder(aChannel, false)); - if (NS_WARN_IF(!mInfo)) { - return NS_ERROR_FAILURE; - } - - RefPtr swm = ServiceWorkerManager::GetInstance(); - MOZ_ASSERT(swm); - - RefPtr registration = - swm->GetRegistration(mInfo->GetPrincipal(), mInfo->Scope()); - nsMainThreadPtrHandle regInfo( new nsMainThreadPtrHolder(registration, false)); @@ -2120,4 +2152,16 @@ ServiceWorkerPrivate::Observe(nsISupports* aSubject, const char* aTopic, const c return NS_OK; } +void +ServiceWorkerPrivate::SetHandlesFetch(bool aValue) +{ + AssertIsOnMainThread(); + + if (NS_WARN_IF(!mInfo)) { + return; + } + + mInfo->SetHandlesFetch(aValue); +} + END_WORKERS_NAMESPACE diff --git a/dom/workers/ServiceWorkerPrivate.h b/dom/workers/ServiceWorkerPrivate.h index 16b1c436941b..9b59082bdbdf 100644 --- a/dom/workers/ServiceWorkerPrivate.h +++ b/dom/workers/ServiceWorkerPrivate.h @@ -153,6 +153,9 @@ public: void AddPendingWindow(Runnable* aPendingWindow); + void + SetHandlesFetch(bool aValue); + private: enum WakeUpReason { FetchEvent = 0, diff --git a/dom/workers/ServiceWorkerRegistrar.cpp b/dom/workers/ServiceWorkerRegistrar.cpp index d48e981aa7f8..5ee2d680916d 100644 --- a/dom/workers/ServiceWorkerRegistrar.cpp +++ b/dom/workers/ServiceWorkerRegistrar.cpp @@ -41,6 +41,7 @@ namespace { static const char* gSupportedRegistrarVersions[] = { SERVICEWORKERREGISTRAR_VERSION, + "4", "3", "2" }; @@ -351,6 +352,40 @@ ServiceWorkerRegistrar::ReadData() GET_LINE(entry->currentWorkerURL()); + nsAutoCString fetchFlag; + GET_LINE(fetchFlag); + if (!fetchFlag.EqualsLiteral(SERVICEWORKERREGISTRAR_TRUE) && + !fetchFlag.EqualsLiteral(SERVICEWORKERREGISTRAR_FALSE)) { + return NS_ERROR_INVALID_ARG; + } + entry->currentWorkerHandlesFetch() = + fetchFlag.EqualsLiteral(SERVICEWORKERREGISTRAR_TRUE); + + nsAutoCString cacheName; + GET_LINE(cacheName); + CopyUTF8toUTF16(cacheName, entry->cacheName()); + } else if (version.EqualsLiteral("4")) { + overwrite = true; + dedupe = true; + + nsAutoCString suffix; + GET_LINE(suffix); + + PrincipalOriginAttributes attrs; + if (!attrs.PopulateFromSuffix(suffix)) { + return NS_ERROR_INVALID_ARG; + } + + GET_LINE(entry->scope()); + + entry->principal() = + mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope()); + + GET_LINE(entry->currentWorkerURL()); + + // default handlesFetch flag to Enabled + entry->currentWorkerHandlesFetch() = true; + nsAutoCString cacheName; GET_LINE(cacheName); CopyUTF8toUTF16(cacheName, entry->cacheName()); @@ -376,6 +411,9 @@ ServiceWorkerRegistrar::ReadData() GET_LINE(entry->currentWorkerURL()); + // default handlesFetch flag to Enabled + entry->currentWorkerHandlesFetch() = true; + nsAutoCString cacheName; GET_LINE(cacheName); CopyUTF8toUTF16(cacheName, entry->cacheName()); @@ -404,6 +442,9 @@ ServiceWorkerRegistrar::ReadData() GET_LINE(entry->currentWorkerURL()); + // default handlesFetch flag to Enabled + entry->currentWorkerHandlesFetch() = true; + nsAutoCString cacheName; GET_LINE(cacheName); CopyUTF8toUTF16(cacheName, entry->cacheName()); @@ -699,6 +740,10 @@ ServiceWorkerRegistrar::WriteData() buffer.Append(data[i].currentWorkerURL()); buffer.Append('\n'); + buffer.Append(data[i].currentWorkerHandlesFetch() ? + SERVICEWORKERREGISTRAR_TRUE : SERVICEWORKERREGISTRAR_FALSE); + buffer.Append('\n'); + buffer.Append(NS_ConvertUTF16toUTF8(data[i].cacheName())); buffer.Append('\n'); diff --git a/dom/workers/ServiceWorkerRegistrar.h b/dom/workers/ServiceWorkerRegistrar.h index 43922cfc5b39..faf7dc1d5f28 100644 --- a/dom/workers/ServiceWorkerRegistrar.h +++ b/dom/workers/ServiceWorkerRegistrar.h @@ -16,7 +16,7 @@ #include "nsTArray.h" #define SERVICEWORKERREGISTRAR_FILE "serviceworker.txt" -#define SERVICEWORKERREGISTRAR_VERSION "4" +#define SERVICEWORKERREGISTRAR_VERSION "5" #define SERVICEWORKERREGISTRAR_TERMINATOR "#" #define SERVICEWORKERREGISTRAR_TRUE "true" #define SERVICEWORKERREGISTRAR_FALSE "false" diff --git a/dom/workers/ServiceWorkerRegistrarTypes.ipdlh b/dom/workers/ServiceWorkerRegistrarTypes.ipdlh index 7754a19e6652..7d208b2fb1e5 100644 --- a/dom/workers/ServiceWorkerRegistrarTypes.ipdlh +++ b/dom/workers/ServiceWorkerRegistrarTypes.ipdlh @@ -13,6 +13,7 @@ struct ServiceWorkerRegistrationData { nsCString scope; nsCString currentWorkerURL; + bool currentWorkerHandlesFetch; nsString cacheName; diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index cd1683a1cea7..07617802cf29 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -4019,6 +4019,7 @@ WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent, , mPeriodicGCTimerRunning(false) , mIdleGCTimerRunning(false) , mWorkerScriptExecutedSuccessfully(false) + , mFetchHandlerWasAdded(false) , mOnLine(false) { MOZ_ASSERT_IF(!IsDedicatedWorker(), !aWorkerName.IsVoid()); diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index 9d83513a99a3..d7f5831de72e 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -973,6 +973,7 @@ class WorkerPrivate : public WorkerPrivateParent bool mPeriodicGCTimerRunning; bool mIdleGCTimerRunning; bool mWorkerScriptExecutedSuccessfully; + bool mFetchHandlerWasAdded; bool mPreferences[WORKERPREF_COUNT]; bool mOnLine; @@ -1211,6 +1212,22 @@ public: void MemoryPressureInternal(); + void + SetFetchHandlerWasAdded() + { + MOZ_ASSERT(IsServiceWorker()); + AssertIsOnWorkerThread(); + mFetchHandlerWasAdded = true; + } + + bool + FetchHandlerWasAdded() const + { + MOZ_ASSERT(IsServiceWorker()); + AssertIsOnWorkerThread(); + return mFetchHandlerWasAdded; + } + JSContext* GetJSContext() const { diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index db2e99118899..dbb497bbb2d5 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -611,6 +611,89 @@ ServiceWorkerGlobalScope::Registration() return mRegistration; } +EventHandlerNonNull* +ServiceWorkerGlobalScope::GetOnfetch() +{ + MOZ_ASSERT(mWorkerPrivate); + mWorkerPrivate->AssertIsOnWorkerThread(); + + return GetEventHandler(nullptr, NS_LITERAL_STRING("fetch")); +} + +namespace { + +class ReportFetchListenerWarningRunnable final : public Runnable +{ + const nsCString mScope; + nsCString mSourceSpec; + uint32_t mLine; + uint32_t mColumn; + +public: + explicit ReportFetchListenerWarningRunnable(const nsString& aScope) + : mScope(NS_ConvertUTF16toUTF8(aScope)) + { + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(workerPrivate); + JSContext* cx = workerPrivate->GetJSContext(); + MOZ_ASSERT(cx); + + nsJSUtils::GetCallingLocation(cx, mSourceSpec, &mLine, &mColumn); + } + + NS_IMETHOD + Run() override + { + AssertIsOnMainThread(); + + ServiceWorkerManager::LocalizeAndReportToAllClients(mScope, "ServiceWorkerNoFetchHandler", + nsTArray{}, nsIScriptError::warningFlag, NS_ConvertUTF8toUTF16(mSourceSpec), + EmptyString(), mLine, mColumn); + + return NS_OK; + } +}; + +} // anonymous namespace + +void +ServiceWorkerGlobalScope::SetOnfetch(mozilla::dom::EventHandlerNonNull* aCallback) +{ + MOZ_ASSERT(mWorkerPrivate); + mWorkerPrivate->AssertIsOnWorkerThread(); + + if (aCallback) { + if (mWorkerPrivate->WorkerScriptExecutedSuccessfully()) { + RefPtr r = new ReportFetchListenerWarningRunnable(mScope); + mWorkerPrivate->DispatchToMainThread(r.forget()); + } + mWorkerPrivate->SetFetchHandlerWasAdded(); + } + SetEventHandler(nullptr, NS_LITERAL_STRING("fetch"), aCallback); +} + +void +ServiceWorkerGlobalScope::AddEventListener( + const nsAString& aType, + dom::EventListener* aListener, + const dom::AddEventListenerOptionsOrBoolean& aOptions, + const dom::Nullable& aWantsUntrusted, + ErrorResult& aRv) +{ + MOZ_ASSERT(mWorkerPrivate); + mWorkerPrivate->AssertIsOnWorkerThread(); + + if (mWorkerPrivate->WorkerScriptExecutedSuccessfully()) { + RefPtr r = new ReportFetchListenerWarningRunnable(mScope); + mWorkerPrivate->DispatchToMainThread(r.forget()); + } + DOMEventTargetHelper::AddEventListener(aType, aListener, aOptions, + aWantsUntrusted, aRv); + if (!aRv.Failed()) { + mWorkerPrivate->SetFetchHandlerWasAdded(); + } +} + namespace { class SkipWaitingResultRunnable final : public WorkerRunnable diff --git a/dom/workers/WorkerScope.h b/dom/workers/WorkerScope.h index 53d0a578e1b0..d473f4e27d32 100644 --- a/dom/workers/WorkerScope.h +++ b/dom/workers/WorkerScope.h @@ -281,13 +281,25 @@ public: SkipWaiting(ErrorResult& aRv); IMPL_EVENT_HANDLER(activate) - IMPL_EVENT_HANDLER(fetch) IMPL_EVENT_HANDLER(install) IMPL_EVENT_HANDLER(message) IMPL_EVENT_HANDLER(push) IMPL_EVENT_HANDLER(pushsubscriptionchange) + EventHandlerNonNull* + GetOnfetch(); + + void + SetOnfetch(mozilla::dom::EventHandlerNonNull* aCallback); + + using DOMEventTargetHelper::AddEventListener; + virtual void + AddEventListener(const nsAString& aType, + dom::EventListener* aListener, + const dom::AddEventListenerOptionsOrBoolean& aOptions, + const dom::Nullable& aWantsUntrusted, + ErrorResult& aRv) override; }; class WorkerDebuggerGlobalScope final : public DOMEventTargetHelper, From 6f3c7b97ba789563c7aaaacfd26b2dca49ee593b Mon Sep 17 00:00:00 2001 From: Catalin Badea Date: Mon, 19 Dec 2016 04:38:53 +0200 Subject: [PATCH 02/21] Bug 1181127 - Mochitest for nofetch handler optimization. r=bkelly --- dom/workers/test/serviceworkers/mochitest.ini | 2 + .../serviceworkers/nofetch_handler_worker.js | 8 +++ .../serviceworkers/test_nofetch_handler.html | 65 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 dom/workers/test/serviceworkers/nofetch_handler_worker.js create mode 100644 dom/workers/test/serviceworkers/test_nofetch_handler.html diff --git a/dom/workers/test/serviceworkers/mochitest.ini b/dom/workers/test/serviceworkers/mochitest.ini index 6fa4b60640f2..e7642f7c0d09 100644 --- a/dom/workers/test/serviceworkers/mochitest.ini +++ b/dom/workers/test/serviceworkers/mochitest.ini @@ -214,6 +214,7 @@ support-files = sharedWorker_fetch.js async_waituntil_worker.js lazy_worker.js + nofetch_handler_worker.js [test_bug1151916.html] [test_bug1240436.html] @@ -319,3 +320,4 @@ tags = openwindow [test_xslt.html] [test_async_waituntil.html] [test_worker_reference_gc_timeout.html] +[test_nofetch_handler.html] diff --git a/dom/workers/test/serviceworkers/nofetch_handler_worker.js b/dom/workers/test/serviceworkers/nofetch_handler_worker.js new file mode 100644 index 000000000000..b5df82d6aaba --- /dev/null +++ b/dom/workers/test/serviceworkers/nofetch_handler_worker.js @@ -0,0 +1,8 @@ +function handleFetch(event) { + event.respondWith(new Response('intercepted')); +} + +self.oninstall = function(event) { + addEventListener('fetch', handleFetch); + self.onfetch = handleFetch; +} diff --git a/dom/workers/test/serviceworkers/test_nofetch_handler.html b/dom/workers/test/serviceworkers/test_nofetch_handler.html new file mode 100644 index 000000000000..198836184abf --- /dev/null +++ b/dom/workers/test/serviceworkers/test_nofetch_handler.html @@ -0,0 +1,65 @@ + + + + Test for Bug 1181127 + + + + + + +Mozilla Bug 1181127 +

+ +
+
+ + + + From 48e3f68e98e4a96d8bd4862fb433fef931ab8fde Mon Sep 17 00:00:00 2001 From: Catalin Badea Date: Mon, 19 Dec 2016 04:38:53 +0200 Subject: [PATCH 03/21] Bug 1181127 - Update ServiceWorkerRegistrar gTest. r=bkelly --- dom/workers/test/gtest/TestReadWrite.cpp | 63 +++++++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/dom/workers/test/gtest/TestReadWrite.cpp b/dom/workers/test/gtest/TestReadWrite.cpp index 6a1aeb389e87..c8fd2914bee2 100644 --- a/dom/workers/test/gtest/TestReadWrite.cpp +++ b/dom/workers/test/gtest/TestReadWrite.cpp @@ -148,11 +148,15 @@ TEST(ServiceWorkerRegistrar, TestReadData) nsAutoCString buffer(SERVICEWORKERREGISTRAR_VERSION "\n"); buffer.Append("^appId=123&inBrowser=1\n"); - buffer.Append("scope 0\ncurrentWorkerURL 0\ncacheName 0\n"); + buffer.Append("scope 0\ncurrentWorkerURL 0\n"); + buffer.Append(SERVICEWORKERREGISTRAR_TRUE "\n"); + buffer.Append("cacheName 0\n"); buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n"); buffer.Append("\n"); - buffer.Append("scope 1\ncurrentWorkerURL 1\ncacheName 1\n"); + buffer.Append("scope 1\ncurrentWorkerURL 1\n"); + buffer.Append(SERVICEWORKERREGISTRAR_FALSE "\n"); + buffer.Append("cacheName 1\n"); buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n"); ASSERT_TRUE(CreateFile(buffer)) << "CreateFile should not fail"; @@ -176,6 +180,7 @@ TEST(ServiceWorkerRegistrar, TestReadData) ASSERT_STREQ("scope 0", cInfo0.spec().get()); ASSERT_STREQ("scope 0", data[0].scope().get()); ASSERT_STREQ("currentWorkerURL 0", data[0].currentWorkerURL().get()); + ASSERT_TRUE(data[0].currentWorkerHandlesFetch()); ASSERT_STREQ("cacheName 0", NS_ConvertUTF16toUTF8(data[0].cacheName()).get()); const mozilla::ipc::PrincipalInfo& info1 = data[1].principal(); @@ -189,6 +194,7 @@ TEST(ServiceWorkerRegistrar, TestReadData) ASSERT_STREQ("scope 1", cInfo1.spec().get()); ASSERT_STREQ("scope 1", data[1].scope().get()); ASSERT_STREQ("currentWorkerURL 1", data[1].currentWorkerURL().get()); + ASSERT_FALSE(data[1].currentWorkerHandlesFetch()); ASSERT_STREQ("cacheName 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get()); } @@ -370,6 +376,59 @@ TEST(ServiceWorkerRegistrar, TestVersion3Migration) ASSERT_STREQ("cacheName 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get()); } +TEST(ServiceWorkerRegistrar, TestVersion4Migration) +{ + nsAutoCString buffer("4" "\n"); + + buffer.Append("^appId=123&inBrowser=1\n"); + buffer.Append("scope 0\ncurrentWorkerURL 0\ncacheName 0\n"); + buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n"); + + buffer.Append("\n"); + buffer.Append("scope 1\ncurrentWorkerURL 1\ncacheName 1\n"); + buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n"); + + ASSERT_TRUE(CreateFile(buffer)) << "CreateFile should not fail"; + + RefPtr swr = new ServiceWorkerRegistrarTest; + + nsresult rv = swr->TestReadData(); + ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail"; + + const nsTArray& data = swr->TestGetData(); + ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found"; + + const mozilla::ipc::PrincipalInfo& info0 = data[0].principal(); + ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) << "First principal must be content"; + const mozilla::ipc::ContentPrincipalInfo& cInfo0 = data[0].principal(); + + nsAutoCString suffix0; + cInfo0.attrs().CreateSuffix(suffix0); + + ASSERT_STREQ("^appId=123&inBrowser=1", suffix0.get()); + ASSERT_STREQ("scope 0", cInfo0.spec().get()); + ASSERT_STREQ("scope 0", data[0].scope().get()); + ASSERT_STREQ("currentWorkerURL 0", data[0].currentWorkerURL().get()); + // default is true + ASSERT_EQ(true, data[1].currentWorkerHandlesFetch()); + ASSERT_STREQ("cacheName 0", NS_ConvertUTF16toUTF8(data[0].cacheName()).get()); + + const mozilla::ipc::PrincipalInfo& info1 = data[1].principal(); + ASSERT_EQ(info1.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) << "First principal must be content"; + const mozilla::ipc::ContentPrincipalInfo& cInfo1 = data[1].principal(); + + nsAutoCString suffix1; + cInfo1.attrs().CreateSuffix(suffix1); + + ASSERT_STREQ("", suffix1.get()); + ASSERT_STREQ("scope 1", cInfo1.spec().get()); + ASSERT_STREQ("scope 1", data[1].scope().get()); + ASSERT_STREQ("currentWorkerURL 1", data[1].currentWorkerURL().get()); + // default is true + ASSERT_EQ(true, data[1].currentWorkerHandlesFetch()); + ASSERT_STREQ("cacheName 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get()); +} + TEST(ServiceWorkerRegistrar, TestDedupeRead) { nsAutoCString buffer("3" "\n"); From 835fb3fcef69867462eb53eaf907204bcac1d48d Mon Sep 17 00:00:00 2001 From: Catalin Badea Date: Mon, 19 Dec 2016 04:38:53 +0200 Subject: [PATCH 04/21] Bug 1181127 - Fix nsContentUtils::FormatLocalizedString NS_ASSERTION. r=bkelly nsStringBundle::FormatStringFromName asserts that GetStringFromName should be used when the error message has no parameters. --- dom/base/nsContentUtils.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 5db02a53bbe9..b743e3cceb53 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -3570,6 +3570,11 @@ nsresult nsContentUtils::FormatLocalizedString(PropertiesFile aFile, NS_ENSURE_SUCCESS(rv, rv); nsIStringBundle *bundle = sStringBundles[aFile]; + if (!aParams || !aParamsLength) { + return bundle->GetStringFromName(NS_ConvertASCIItoUTF16(aKey).get(), + getter_Copies(aResult)); + } + return bundle->FormatStringFromName(NS_ConvertASCIItoUTF16(aKey).get(), aParams, aParamsLength, getter_Copies(aResult)); From d42aaaf304b596928b3cfd46150ea13ac04fd88f Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Sun, 4 Dec 2016 18:21:01 +1300 Subject: [PATCH 05/21] Bug 1322305. r=gerald MozReview-Commit-ID: BLPkf2yrASn --HG-- extra : amend_source : 58028c34dd322ff23c6b3e4bd6b266791096e200 --- .../gmp/widevine-adapter/WidevineAdapter.cpp | 2 +- dom/media/gmp/widevine-adapter/WidevineUtils.cpp | 16 ++++++++++++++++ dom/media/gmp/widevine-adapter/WidevineUtils.h | 16 ++++++---------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp b/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp index 99ff675c97ff..61c79f9849ec 100644 --- a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp +++ b/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp @@ -118,7 +118,7 @@ WidevineAdapter::GMPGetAPI(const char* aAPIName, return GMPGenericErr; } Log("cdm: 0x%x", cdm); - RefPtr wrapper(new CDMWrapper(cdm)); + RefPtr wrapper(new CDMWrapper(cdm, decryptor)); decryptor->SetCDM(wrapper, aDecryptorId); *aPluginAPI = decryptor; diff --git a/dom/media/gmp/widevine-adapter/WidevineUtils.cpp b/dom/media/gmp/widevine-adapter/WidevineUtils.cpp index b283cf713c8b..925dfe1a1fd5 100644 --- a/dom/media/gmp/widevine-adapter/WidevineUtils.cpp +++ b/dom/media/gmp/widevine-adapter/WidevineUtils.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WidevineUtils.h" +#include "WidevineDecryptor.h" #include "gmp-api/gmp-errors.h" #include @@ -76,4 +77,19 @@ void InitInputBuffer(const GMPEncryptedBufferMetadata* aCrypto, aInputBuffer.timestamp = aTimestamp; } +CDMWrapper::CDMWrapper(cdm::ContentDecryptionModule_8* aCDM, + WidevineDecryptor* aDecryptor) + : mCDM(aCDM) + , mDecryptor(aDecryptor) +{ + MOZ_ASSERT(mCDM); +} + +CDMWrapper::~CDMWrapper() +{ + Log("CDMWrapper destroying CDM=%p", mCDM); + mCDM->Destroy(); + mCDM = nullptr; +} + } // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineUtils.h b/dom/media/gmp/widevine-adapter/WidevineUtils.h index e5d20fe9c624..57c004a87c25 100644 --- a/dom/media/gmp/widevine-adapter/WidevineUtils.h +++ b/dom/media/gmp/widevine-adapter/WidevineUtils.h @@ -42,23 +42,19 @@ Log(const char* aFormat, ...); GMPErr ToGMPErr(cdm::Status aStatus); +class WidevineDecryptor; + class CDMWrapper { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMWrapper) - explicit CDMWrapper(cdm::ContentDecryptionModule_8* aCDM) - : mCDM(aCDM) - { - MOZ_ASSERT(mCDM); - } + explicit CDMWrapper(cdm::ContentDecryptionModule_8* aCDM, + WidevineDecryptor* aDecryptor); cdm::ContentDecryptionModule_8* GetCDM() const { return mCDM; } private: + ~CDMWrapper(); cdm::ContentDecryptionModule_8* mCDM; - ~CDMWrapper() { - Log("CDMWrapper destroying CDM=%p", mCDM); - mCDM->Destroy(); - mCDM = nullptr; - } + RefPtr mDecryptor; }; void InitInputBuffer(const GMPEncryptedBufferMetadata* aCrypto, From 71bdb68393d10724d5b6512d708b6a9d34d9a2e4 Mon Sep 17 00:00:00 2001 From: John Lin Date: Fri, 16 Dec 2016 13:41:15 +0800 Subject: [PATCH 06/21] Bug 1311960 - turn on remote media decoding preference on Fennec Nightly. r=snorp MozReview-Commit-ID: CUm6EwC1Dz9 --- mobile/android/app/mobile.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index 6c4d8000c54a..55c5f7d19168 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -628,7 +628,11 @@ pref("media.decoder.recycle.enabled", true); pref("media.android-media-codec.enabled", true); pref("media.android-media-codec.preferred", true); // Run decoder in seperate process. +#ifdef NIGHTLY_BUILD +pref("media.android-remote-codec.enabled", true); +#else pref("media.android-remote-codec.enabled", false); +#endif // Enable MSE pref("media.mediasource.enabled", true); From 74a1f89b9bc35cc23ab6b042bb28589b710a4442 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Mon, 19 Dec 2016 14:30:09 +0800 Subject: [PATCH 07/21] Bug 1324341 - Part 1: Convert eRestyle_Subtree into (eRestyle_Self | eRestyle_SomeDescendants), so Servo will actually restyle descendants. r=xidorn MozReview-Commit-ID: AjfgRua4WcF --- layout/base/ServoRestyleManager.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/layout/base/ServoRestyleManager.cpp b/layout/base/ServoRestyleManager.cpp index 5a22175919d2..d7fb12340250 100644 --- a/layout/base/ServoRestyleManager.cpp +++ b/layout/base/ServoRestyleManager.cpp @@ -59,6 +59,16 @@ ServoRestyleManager::PostRestyleEvent(Element* aElement, aRestyleHint |= eRestyle_Self | eRestyle_Subtree; } + // XXX For now, convert eRestyle_Subtree into (eRestyle_Self | + // eRestyle_SomeDescendants), which Servo will interpret as + // RESTYLE_SELF | RESTYLE_DESCENDANTS, since this is a commonly + // posted restyle hint that doesn't yet align with RestyleHint's + // bits. + if (aRestyleHint & eRestyle_Subtree) { + aRestyleHint &= ~eRestyle_Subtree; + aRestyleHint |= eRestyle_Self | eRestyle_SomeDescendants; + } + if (aRestyleHint || aMinChangeHint) { Servo_NoteExplicitHints(aElement, aRestyleHint, aMinChangeHint); } From e9a3df412d0c673e4b6287114c7c6ef9d6e0c181 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Mon, 19 Dec 2016 14:30:14 +0800 Subject: [PATCH 08/21] Bug 1324341 - Part 2: Redo the cascade when CSSOM methods modify style sheets. r=xidorn MozReview-Commit-ID: AIkwBaUlxD7 --- layout/base/PresShell.cpp | 7 ++++++- layout/style/ServoBindingList.h | 2 ++ layout/style/ServoStyleSet.cpp | 6 ++++++ layout/style/ServoStyleSet.h | 7 +++++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index 965524f34109..822574978b67 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -4518,6 +4518,12 @@ nsIPresShell::RestyleForCSSRuleChanges() } RestyleManagerHandle restyleManager = mPresContext->RestyleManager(); + + if (mStyleSet->IsServo()) { + // Tell Servo that the contents of style sheets have changed. + mStyleSet->AsServo()->NoteStyleSheetsChanged(); + } + if (scopeRoots.IsEmpty()) { // If scopeRoots is empty, we know that mStylesHaveChanged was true at // the beginning of this function, and that we need to restyle the whole @@ -4550,7 +4556,6 @@ PresShell::RecordStyleSheetChange(StyleSheet* aStyleSheet) } } else { NS_WARNING("stylo: ServoStyleSheets don't support