From 938961e76b2d0ad7d5ecc5bdfe0f8d48a9ed8abe Mon Sep 17 00:00:00 2001 From: roytam1 Date: Mon, 26 Sep 2022 16:21:15 +0800 Subject: [PATCH] import changes from `dev' branch of rmottola/Arctic-Fox: - Bug 1182147: Ensure ImageHost does not attempt to call DrawQuad with an effect unsupported by the compositor. r=nical (5624e9134f) - Bug 1151749 - "Win-Only: Disabled Hardware Acceleration + CSS 3D transform on canvas -> black artefacts on hover". r=nical (54c49071b9) - Bug 1184224 - Remove gfxPrefs.h include from gfxPlatformGtk.h. r=karlt (eb907daa58) - Bug 1183820 - Expose if cairo uses XRender to GetAzureBackendInfo. r=mattwoodrow (10044ecfb0) - Bug 1128934 - Call XFlush after compositing to prevent jank. r=karlt (f63b9dc1b5) - Bug 1151663 - New mochitest for this bug. r=kats (9344d22ed6) - Bug 1176402 - Have synthesizeNativeWheel() and synthesizeNativeMouseMove() accept coordinates relative to the element's bounding rect. r=kats (cbdffe3869) - Bug 1177018 - Work around the iframe in which mochitests are run not being scrollable. r=kats (d24291080c) - Bug 1177018 - Disable smooth scrolling in the APZ layerization test. r=kats (e1af545da1) - Bug 1181678 - Improve the check for skipping test_layerization if APZ is disabled. r=botond (91e5ead610) - Bug 1177018 - Enable chaos mode for the APZ layerization test. r=kats (f07fdeb936) - Bug 1177018 - Only enable APZ test logging for tests that actually use it. r=kats (9f24ea01c4) - Bug 1196294 - Remove the mCause from TimelineMarkers, r=tromey (5abd1c057d) - Bug 1195232 - Stop using TracingMetadata from GeckoProfiler.h, r=tromey (e736038873) - Bug 1200118 - Create a barebones TimelineMarker abstract class, r=tromey (9930c83c2f) - Bug 1200252 - Add marker for when the IPC request for a composite is sent to the compositor thread, r=jsantell,matt (becc11f58b) - align some minor thing to gecko (5bb64e322a) - Bug 1204581 - Add a deprecation warning for the usage of AppCache when service worker fetch interception is enabled; r=mcmanus,baku (69949c8d96) - Bug 1210941 P2 Use LOAD_BYPASS_SERVICE_WORKER in HttpBaseChannel instead of mForceNoIntercept. r=jduell (fdb7afc0be) - Bug 1173171 - Disable external jar: via preference. r=jduell (704cfb0b9c) - Bug 1210941 P3 Make jar channels use LOAD_BYPASS_SERVICE_WORKER internally. r=jduell (d871dc4837) - Bug 1210941 P4 Use LOAD_BYPASS_SERVICE_WORKER instead of ForceNoIntercept in nsDocShell. r=ehsan (ea5ed76717) - Bug 1210941 P5 Use LOAD_BYPASS_SERVICE_WORKER in nsObjectLoadingContent instead of ForceNoIntercept(). r=ehsan (9e821adfaa) - Bug 1210941 P6 Use LOAD_BYPASS_SERVICE_WORKER instead of ForceNoIntercept in FetchDriver. r=ehsan (02685be882) - Bug 1210941 P7 Use LOAD_BYPASS_SERVICE_WORKER in ServiceWorkerScriptCache. r=ehsan (45fa163dd2) - Bug 1182112 - XML documents should not be intercepted by ServiceWorkers. r=ehsan (a9dfeffcb3) - Bug 1210941 P8 Use LOAD_BYPASS_SERVICE_WORKER in xslt txURIUtils. r=ehsan (d7686d572b) - Bug 1210941 P9 Use LOAD_BYPASS_SERVICE_WORKER in nsCORSListenerProxy. r=ehsan (653f50de45) - Bug 1205302 - Disallow intercepting OCSP requests; r=jdm (b4650e78d9) - Bug 1210941 P10 Use LOAD_BYPASS_SERVICE_WORKER in nsNSSCallbacks. r=ehsan (b4b8b3f503) - Bug 1210941 P11 Use LOAD_BYPASS_SERVICE_WORKER in worker ScriptLoader. r=ehsan (ac07404832) - Bug 1210941 P12 Remove http channel's ForceNoIntercept. r=jduell IGNORE IDL (a7592a83c4) - Bug 1210941 P13 Remove ForceNoIntercept from jar channel. r=jduell (617544fcee) - Bug 1169613 - Use content type of synthesized response for JAR channel requests if available. Part 1: Set Content-Type of synthesized reponses for JAR channel requests. r=jdm (e32061a26a) - Bug 1169613 - Use content type of synthesized response for JAR channel requests if available. Part 2: Set Content-Type for JAR Channel requests on Fetch API responses. r=nsm (da43e29583) - Bug 1207556 - Part 1: Stop reusing the loadinfo in StartCORSPreflight; r=sicking (4724bfa8cd) - Bug 1207556 - Part 2: Fix the beacon CORS preflight tests; r=sicking (c61a699f9f) - Bug 1111834 - CORS preflight of navigator.sendBeacon() should not follow 30x redirect - tests. r=sicking (2871ad22e7) - fix build because of previous backports (e3096e6f9a) - Bug 1161677 - Expose dev mode state read-only through the navigator.hasFeature() api r=ehsan (013399847b) - Bug 1203680 P8 nsCORSListenerProxy::OnStartRequest must always call outer OnStartRequest. r=ehsan (9a67709770) - spacing (d4511b37c4) - missing bit of 920017 and some telemetry (2bf267ce72) --- browser/app/profile/palemoon.js | 3 +- docshell/base/nsDocShell.cpp | 24 +++-- docshell/base/nsDocShell.h | 13 ++- .../base/timeline/AbstractTimelineMarker.cpp | 50 +++++++++ .../base/timeline/AbstractTimelineMarker.h | 57 ++++++++++ .../timeline/AutoGlobalTimelineMarker.cpp | 4 +- docshell/base/timeline/AutoTimelineMarker.cpp | 4 +- .../base/timeline/ConsoleTimelineMarker.h | 22 ++-- docshell/base/timeline/EventTimelineMarker.h | 12 ++- .../base/timeline/JavascriptTimelineMarker.h | 8 +- docshell/base/timeline/LayerTimelineMarker.h | 2 +- docshell/base/timeline/ObservedDocShell.cpp | 10 +- .../base/timeline/RestyleTimelineMarker.h | 6 +- docshell/base/timeline/TimelineConsumers.cpp | 24 ++--- docshell/base/timeline/TimelineConsumers.h | 16 +-- docshell/base/timeline/TimelineMarker.cpp | 101 +++++++----------- docshell/base/timeline/TimelineMarker.h | 85 +++------------ docshell/base/timeline/TimelineMarkerEnums.h | 26 +++++ .../base/timeline/TimestampTimelineMarker.h | 10 +- docshell/base/timeline/moz.build | 3 + dom/base/Console.cpp | 4 +- dom/base/Navigator.cpp | 32 ++++++ dom/base/nsDeprecatedOperationList.h | 1 + dom/base/nsObjectLoadingContent.cpp | 11 +- dom/base/test/test_getFeature_with_perm.html | 20 +++- dom/events/EventListenerManager.cpp | 4 +- dom/fetch/FetchDriver.cpp | 30 +++--- dom/ipc/TabChild.cpp | 17 ++- dom/ipc/TabChild.h | 2 + dom/locales/en-US/chrome/dom/dom.properties | 4 +- .../beacon/beacon-cors-redirect-handler.sjs | 52 +++++++++ .../beacon/beacon-preflight-handler.sjs | 39 +++++++ dom/tests/mochitest/beacon/mochitest.ini | 4 + .../beacon/test_beaconCORSRedirect.html | 57 ++++++++++ .../beacon/test_beaconPreflight.html | 26 ++++- .../beacon/test_beaconPreflightFailure.html | 56 ++++++++++ dom/workers/ScriptLoader.cpp | 31 +++--- dom/workers/ServiceWorkerScriptCache.cpp | 10 +- dom/xslt/base/txURIUtils.cpp | 6 +- .../apz/test/apz_test_native_event_utils.js | 51 ++++++--- gfx/layers/apz/test/helper_bug1151663.html | 81 ++++++++++++++ gfx/layers/apz/test/mochitest.ini | 8 ++ gfx/layers/apz/test/test_bug1151663.html | 35 ++++++ gfx/layers/apz/test/test_bug1151667.html | 6 +- gfx/layers/apz/test/test_bug982141.html | 4 +- gfx/layers/apz/test/test_layerization.html | 32 ++++-- gfx/layers/basic/BasicCompositor.cpp | 3 +- gfx/layers/basic/X11BasicCompositor.cpp | 7 ++ gfx/layers/basic/X11BasicCompositor.h | 2 + gfx/layers/client/ClientLayerManager.cpp | 19 +++- gfx/layers/composite/ImageHost.cpp | 4 + gfx/thebes/gfxPlatform.h | 2 +- gfx/thebes/gfxPlatformGtk.cpp | 13 +++ gfx/thebes/gfxPlatformGtk.h | 18 ++-- gfx/thebes/gfxPrefs.h | 2 +- layout/base/RestyleTracker.cpp | 8 +- layout/base/nsPresShell.cpp | 4 +- layout/base/nsRefreshDriver.cpp | 4 +- modules/libjar/InterceptedJARChannel.cpp | 5 +- modules/libjar/InterceptedJARChannel.h | 3 + modules/libjar/nsIJARChannel.idl | 8 +- modules/libjar/nsJARChannel.cpp | 35 ++++-- modules/libjar/nsJARChannel.h | 10 +- modules/libjar/test/mochitest/mochitest.ini | 1 + .../test/mochitest/test_bug1173171.html | 66 ++++++++++++ modules/libpref/init/all.js | 2 + netwerk/base/BackgroundFileSaver.cpp | 15 ++- netwerk/base/LoadInfo.cpp | 23 ++++ netwerk/base/LoadInfo.h | 3 + netwerk/base/moz.build | 1 + netwerk/base/nsIDeprecationWarner.idl | 23 ++++ netwerk/protocol/app/AppProtocolHandler.cpp | 5 - netwerk/protocol/http/HttpBaseChannel.cpp | 24 ++--- netwerk/protocol/http/HttpBaseChannel.h | 6 +- netwerk/protocol/http/HttpChannelChild.cpp | 15 ++- netwerk/protocol/http/HttpChannelChild.h | 3 + netwerk/protocol/http/HttpChannelParent.cpp | 15 ++- netwerk/protocol/http/HttpChannelParent.h | 3 + netwerk/protocol/http/PHttpChannel.ipdl | 3 + netwerk/protocol/http/nsCORSListenerProxy.cpp | 37 ++++--- netwerk/protocol/http/nsHttpChannel.cpp | 38 ++++++- netwerk/protocol/http/nsHttpChannel.h | 2 + .../protocol/http/nsIHttpChannelInternal.idl | 6 -- security/manager/ssl/nsNSSCallbacks.cpp | 3 +- testing/profiles/prefs_general.js | 3 - .../devtools/performance/modules/markers.js | 5 + view/nsView.cpp | 4 +- 87 files changed, 1154 insertions(+), 402 deletions(-) create mode 100644 docshell/base/timeline/AbstractTimelineMarker.cpp create mode 100644 docshell/base/timeline/AbstractTimelineMarker.h create mode 100644 docshell/base/timeline/TimelineMarkerEnums.h create mode 100644 dom/tests/mochitest/beacon/beacon-cors-redirect-handler.sjs create mode 100644 dom/tests/mochitest/beacon/beacon-preflight-handler.sjs create mode 100644 dom/tests/mochitest/beacon/test_beaconCORSRedirect.html create mode 100644 dom/tests/mochitest/beacon/test_beaconPreflightFailure.html create mode 100644 gfx/layers/apz/test/helper_bug1151663.html create mode 100644 gfx/layers/apz/test/mochitest.ini create mode 100644 gfx/layers/apz/test/test_bug1151663.html create mode 100644 modules/libjar/test/mochitest/test_bug1173171.html create mode 100644 netwerk/base/nsIDeprecationWarner.idl diff --git a/browser/app/profile/palemoon.js b/browser/app/profile/palemoon.js index a166504ce0..e2d52d4af7 100644 --- a/browser/app/profile/palemoon.js +++ b/browser/app/profile/palemoon.js @@ -1131,7 +1131,8 @@ pref("devtools.performance.enabled", true); // The default Performance UI settings pref("devtools.performance.memory.sample-probability", "0.05"); pref("devtools.performance.memory.max-log-length", 2147483647); // Math.pow(2,31) - 1 -pref("devtools.performance.timeline.hidden-markers", "[]"); +pref("devtools.performance.timeline.hidden-markers", + "[\"Composite\",\"CompositeForwardTransaction\"]"); pref("devtools.performance.profiler.buffer-size", 10000000); pref("devtools.performance.profiler.sample-frequency-khz", 1); pref("devtools.performance.ui.show-jit-optimizations", false); diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 5e28f9c64c..89fde88a28 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -946,6 +946,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocShell) NS_INTERFACE_MAP_ENTRY(nsIClipboardCommands) NS_INTERFACE_MAP_ENTRY(nsIDOMStorageManager) NS_INTERFACE_MAP_ENTRY(nsINetworkInterceptController) + NS_INTERFACE_MAP_ENTRY(nsIDeprecationWarner) NS_INTERFACE_MAP_END_INHERITING(nsDocLoader) NS_IMETHODIMP @@ -10937,17 +10938,14 @@ nsDocShell::DoChannelLoad(nsIChannel* aChannel, loadFlags |= nsIChannel::LOAD_CLASSIFY_URI; } - (void)aChannel->SetLoadFlags(loadFlags); - // If the user pressed shift-reload, then do not allow ServiceWorker // interception to occur. See step 12.1 of the SW HandleFetch algorithm. if (IsForceReloadType(mLoadType)) { - nsCOMPtr internal = do_QueryInterface(aChannel); - if (internal) { - internal->ForceNoIntercept(); - } + loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER; } + (void)aChannel->SetLoadFlags(loadFlags); + uint32_t openFlags = 0; if (mLoadType == LOAD_LINK) { openFlags |= nsIURILoader::IS_CONTENT_PREFERRED; @@ -13959,7 +13957,7 @@ nsDocShell::NotifyJSRunToCompletionStart(const char* aReason, // If first start, mark interval start. if (timelineOn && mJSRunToCompletionDepth == 0) { UniquePtr marker = MakeUnique( - aReason, aFunctionName, aFilename, aLineNumber, TRACING_INTERVAL_START); + aReason, aFunctionName, aFilename, aLineNumber, MarkerTracingType::START); TimelineConsumers::AddMarkerForDocShell(this, Move(marker)); } mJSRunToCompletionDepth++; @@ -13973,7 +13971,7 @@ nsDocShell::NotifyJSRunToCompletionStop() // If last stop, mark interval end. mJSRunToCompletionDepth--; if (timelineOn && mJSRunToCompletionDepth == 0) { - TimelineConsumers::AddMarkerForDocShell(this, "Javascript", TRACING_INTERVAL_END); + TimelineConsumers::AddMarkerForDocShell(this, "Javascript", MarkerTracingType::END); } } @@ -14223,3 +14221,13 @@ nsDocShell::InFrameSwap() } while (shell); return false; } + +NS_IMETHODIMP +nsDocShell::IssueWarning(uint32_t aWarning, bool aAsError) +{ + nsCOMPtr doc = mContentViewer->GetDocument(); + if (doc) { + doc->WarnOnceAbout(nsIDocument::DeprecatedOperations(aWarning), aAsError); + } + return NS_OK; +} diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index acb505b4f1..c3c54c0dd7 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -59,6 +59,7 @@ #include "prtime.h" #include "nsRect.h" #include "Units.h" +#include "nsIDeprecationWarner.h" namespace mozilla { namespace dom { @@ -147,6 +148,7 @@ class nsDocShell final , public nsIClipboardCommands , public nsIDOMStorageManager , public nsINetworkInterceptController + , public nsIDeprecationWarner , public mozilla::SupportsWeakPtr { friend class nsDSURIContentListener; @@ -180,6 +182,7 @@ public: NS_DECL_NSICLIPBOARDCOMMANDS NS_DECL_NSIWEBSHELLSERVICES NS_DECL_NSINETWORKINTERCEPTCONTROLLER + NS_DECL_NSIDEPRECATIONWARNER NS_FORWARD_SAFE_NSIDOMSTORAGEMANAGER(TopSessionStorageManager()) NS_IMETHOD Stop() override @@ -283,14 +286,14 @@ private: // be very fast, so instead of using a Map or having to search for some // docshell-specific markers storage, a pointer to an `ObservedDocShell` is // is stored on docshells directly. - friend void mozilla::TimelineConsumers::AddConsumer(nsDocShell* aDocShell); - friend void mozilla::TimelineConsumers::RemoveConsumer(nsDocShell* aDocShell); + friend void mozilla::TimelineConsumers::AddConsumer(nsDocShell*); + friend void mozilla::TimelineConsumers::RemoveConsumer(nsDocShell*); friend void mozilla::TimelineConsumers::AddMarkerForDocShell( - nsDocShell* aDocShell, const char* aName, TracingMetadata aMetaData); + nsDocShell*, const char*, MarkerTracingType); friend void mozilla::TimelineConsumers::AddMarkerForDocShell( - nsDocShell* aDocShell, const char* aName, const TimeStamp& aTime, TracingMetadata aMetaData); + nsDocShell*, const char*, const TimeStamp&, MarkerTracingType); friend void mozilla::TimelineConsumers::AddMarkerForDocShell( - nsDocShell* aDocShell, UniquePtr&& aMarker); + nsDocShell*, UniquePtr&&); public: // Tell the favicon service that aNewURI has the same favicon as aOldURI. diff --git a/docshell/base/timeline/AbstractTimelineMarker.cpp b/docshell/base/timeline/AbstractTimelineMarker.cpp new file mode 100644 index 0000000000..4bec4eefaf --- /dev/null +++ b/docshell/base/timeline/AbstractTimelineMarker.cpp @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "AbstractTimelineMarker.h" +#include "mozilla/TimeStamp.h" + +namespace mozilla { + +AbstractTimelineMarker::AbstractTimelineMarker(const char* aName, + MarkerTracingType aTracingType) + : mName(aName) + , mTracingType(aTracingType) +{ + MOZ_COUNT_CTOR(AbstractTimelineMarker); + SetCurrentTime(); +} + +AbstractTimelineMarker::AbstractTimelineMarker(const char* aName, + const TimeStamp& aTime, + MarkerTracingType aTracingType) + : mName(aName) + , mTracingType(aTracingType) +{ + MOZ_COUNT_CTOR(AbstractTimelineMarker); + SetCustomTime(aTime); +} + +AbstractTimelineMarker::~AbstractTimelineMarker() +{ + MOZ_COUNT_DTOR(AbstractTimelineMarker); +} + +void +AbstractTimelineMarker::SetCurrentTime() +{ + TimeStamp now = TimeStamp::Now(); + SetCustomTime(now); +} + +void +AbstractTimelineMarker::SetCustomTime(const TimeStamp& aTime) +{ + bool isInconsistent = false; + mTime = (aTime - TimeStamp::ProcessCreation(isInconsistent)).ToMilliseconds(); +} + +} // namespace mozilla diff --git a/docshell/base/timeline/AbstractTimelineMarker.h b/docshell/base/timeline/AbstractTimelineMarker.h new file mode 100644 index 0000000000..95a803df31 --- /dev/null +++ b/docshell/base/timeline/AbstractTimelineMarker.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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_AbstractTimelineMarker_h_ +#define mozilla_AbstractTimelineMarker_h_ + +#include "TimelineMarkerEnums.h" // for MarkerTracingType +#include "nsDOMNavigationTiming.h" // for DOMHighResTimeStamp + +struct JSContext; + +namespace mozilla { +class TimeStamp; + +namespace dom { +struct ProfileTimelineMarker; +} + +class AbstractTimelineMarker +{ +private: + AbstractTimelineMarker() = delete; + AbstractTimelineMarker(const AbstractTimelineMarker& aOther) = delete; + void operator=(const AbstractTimelineMarker& aOther) = delete; + +public: + AbstractTimelineMarker(const char* aName, + MarkerTracingType aTracingType); + + AbstractTimelineMarker(const char* aName, + const TimeStamp& aTime, + MarkerTracingType aTracingType); + + virtual ~AbstractTimelineMarker(); + + virtual bool Equals(const AbstractTimelineMarker& aOther) = 0; + virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) = 0; + + const char* GetName() const { return mName; } + DOMHighResTimeStamp GetTime() const { return mTime; } + MarkerTracingType GetTracingType() const { return mTracingType; } + +private: + const char* mName; + DOMHighResTimeStamp mTime; + MarkerTracingType mTracingType; + + void SetCurrentTime(); + void SetCustomTime(const TimeStamp& aTime); +}; + +} // namespace mozilla + +#endif /* mozilla_AbstractTimelineMarker_h_ */ diff --git a/docshell/base/timeline/AutoGlobalTimelineMarker.cpp b/docshell/base/timeline/AutoGlobalTimelineMarker.cpp index a098443cce..17bda01ca9 100644 --- a/docshell/base/timeline/AutoGlobalTimelineMarker.cpp +++ b/docshell/base/timeline/AutoGlobalTimelineMarker.cpp @@ -22,7 +22,7 @@ AutoGlobalTimelineMarker::AutoGlobalTimelineMarker(const char* aName return; } - TimelineConsumers::AddMarkerForAllObservedDocShells(mName, TRACING_INTERVAL_START); + TimelineConsumers::AddMarkerForAllObservedDocShells(mName, MarkerTracingType::START); } AutoGlobalTimelineMarker::~AutoGlobalTimelineMarker() @@ -31,7 +31,7 @@ AutoGlobalTimelineMarker::~AutoGlobalTimelineMarker() return; } - TimelineConsumers::AddMarkerForAllObservedDocShells(mName, TRACING_INTERVAL_END); + TimelineConsumers::AddMarkerForAllObservedDocShells(mName, MarkerTracingType::END); } } // namespace mozilla diff --git a/docshell/base/timeline/AutoTimelineMarker.cpp b/docshell/base/timeline/AutoTimelineMarker.cpp index 2ef8b144db..e18f1cd710 100644 --- a/docshell/base/timeline/AutoTimelineMarker.cpp +++ b/docshell/base/timeline/AutoTimelineMarker.cpp @@ -25,7 +25,7 @@ AutoTimelineMarker::AutoTimelineMarker(nsIDocShell* aDocShell, const char* aName } mDocShell = static_cast(aDocShell); - TimelineConsumers::AddMarkerForDocShell(mDocShell, mName, TRACING_INTERVAL_START); + TimelineConsumers::AddMarkerForDocShell(mDocShell, mName, MarkerTracingType::START); } AutoTimelineMarker::~AutoTimelineMarker() @@ -34,7 +34,7 @@ AutoTimelineMarker::~AutoTimelineMarker() return; } - TimelineConsumers::AddMarkerForDocShell(mDocShell, mName, TRACING_INTERVAL_END); + TimelineConsumers::AddMarkerForDocShell(mDocShell, mName, MarkerTracingType::END); } } // namespace mozilla diff --git a/docshell/base/timeline/ConsoleTimelineMarker.h b/docshell/base/timeline/ConsoleTimelineMarker.h index f74929ab36..ecf3254560 100644 --- a/docshell/base/timeline/ConsoleTimelineMarker.h +++ b/docshell/base/timeline/ConsoleTimelineMarker.h @@ -16,33 +16,39 @@ class ConsoleTimelineMarker : public TimelineMarker { public: explicit ConsoleTimelineMarker(const nsAString& aCause, - TracingMetadata aMetaData) - : TimelineMarker("ConsoleTime", aCause, aMetaData) + MarkerTracingType aTracingType) + : TimelineMarker("ConsoleTime", aTracingType) + , mCause(aCause) { // Stack is captured by default on the "start" marker. Explicitly also // capture stack on the "end" marker. - if (aMetaData == TRACING_INTERVAL_END) { + if (aTracingType == MarkerTracingType::END) { CaptureStack(); } } - virtual bool Equals(const TimelineMarker& aOther) override + virtual bool Equals(const AbstractTimelineMarker& aOther) override { if (!TimelineMarker::Equals(aOther)) { return false; } - // Console markers must have matching causes as well. - return GetCause() == aOther.GetCause(); + // Console markers must have matching causes as well. It is safe to perform + // a static_cast here as the previous equality check ensures that this is + // a console marker instance. + return mCause == static_cast(&aOther)->mCause; } virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) override { - if (GetMetaData() == TRACING_INTERVAL_START) { - aMarker.mCauseName.Construct(GetCause()); + if (GetTracingType() == MarkerTracingType::START) { + aMarker.mCauseName.Construct(mCause); } else { aMarker.mEndStack = GetStack(); } } + +private: + nsString mCause; }; } // namespace mozilla diff --git a/docshell/base/timeline/EventTimelineMarker.h b/docshell/base/timeline/EventTimelineMarker.h index 6bfd7c04a2..2779f2037a 100644 --- a/docshell/base/timeline/EventTimelineMarker.h +++ b/docshell/base/timeline/EventTimelineMarker.h @@ -15,22 +15,24 @@ namespace mozilla { class EventTimelineMarker : public TimelineMarker { public: - explicit EventTimelineMarker(const nsAString& aCause, + explicit EventTimelineMarker(const nsAString& aType, uint16_t aPhase, - TracingMetadata aMetaData) - : TimelineMarker("DOMEvent", aCause, aMetaData) + MarkerTracingType aTracingType) + : TimelineMarker("DOMEvent", aTracingType) + , mType(aType) , mPhase(aPhase) {} virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) override { - if (GetMetaData() == TRACING_INTERVAL_START) { - aMarker.mType.Construct(GetCause()); + if (GetTracingType() == MarkerTracingType::START) { + aMarker.mType.Construct(mType); aMarker.mEventPhase.Construct(mPhase); } } private: + nsString mType; uint16_t mPhase; }; diff --git a/docshell/base/timeline/JavascriptTimelineMarker.h b/docshell/base/timeline/JavascriptTimelineMarker.h index 6b1ff4d824..e3a60054e1 100644 --- a/docshell/base/timeline/JavascriptTimelineMarker.h +++ b/docshell/base/timeline/JavascriptTimelineMarker.h @@ -21,8 +21,9 @@ public: const char16_t* aFunctionName, const char16_t* aFileName, uint32_t aLineNumber, - TracingMetadata aMetaData) - : TimelineMarker("Javascript", NS_ConvertUTF8toUTF16(aReason), aMetaData, NO_STACK) + MarkerTracingType aTracingType) + : TimelineMarker("Javascript", aTracingType, MarkerStackRequest::NO_STACK) + , mCause(NS_ConvertUTF8toUTF16(aReason)) , mFunctionName(aFunctionName) , mFileName(aFileName) , mLineNumber(aLineNumber) @@ -30,7 +31,7 @@ public: virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) override { - aMarker.mCauseName.Construct(GetCause()); + aMarker.mCauseName.Construct(mCause); if (!mFunctionName.IsEmpty() || !mFileName.IsEmpty()) { dom::RootedDictionary stackFrame(aCx); @@ -50,6 +51,7 @@ public: } private: + nsString mCause; nsString mFunctionName; nsString mFileName; uint32_t mLineNumber; diff --git a/docshell/base/timeline/LayerTimelineMarker.h b/docshell/base/timeline/LayerTimelineMarker.h index bfa9c02aeb..6f8547259c 100644 --- a/docshell/base/timeline/LayerTimelineMarker.h +++ b/docshell/base/timeline/LayerTimelineMarker.h @@ -16,7 +16,7 @@ class LayerTimelineMarker : public TimelineMarker { public: explicit LayerTimelineMarker(const nsIntRegion& aRegion) - : TimelineMarker("Layer", TRACING_EVENT) + : TimelineMarker("Layer", MarkerTracingType::HELPER_EVENT) , mRegion(aRegion) {} diff --git a/docshell/base/timeline/ObservedDocShell.cpp b/docshell/base/timeline/ObservedDocShell.cpp index 92c0a6851a..0ab05f3687 100644 --- a/docshell/base/timeline/ObservedDocShell.cpp +++ b/docshell/base/timeline/ObservedDocShell.cpp @@ -39,9 +39,9 @@ ObservedDocShell::PopMarkers(JSContext* aCx, for (uint32_t i = 0; i < mTimelineMarkers.Length(); ++i) { UniquePtr& startPayload = mTimelineMarkers[i]; - // If this is a TRACING_TIMESTAMP marker, there's no corresponding END + // If this is a TIMESTAMP marker, there's no corresponding END, // as it's a single unit of time, not a duration. - if (startPayload->GetMetaData() == TRACING_TIMESTAMP) { + if (startPayload->GetTracingType() == MarkerTracingType::TIMESTAMP) { dom::ProfileTimelineMarker* marker = aStore.AppendElement(); marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName()); marker->mStart = startPayload->GetTime(); @@ -53,7 +53,7 @@ ObservedDocShell::PopMarkers(JSContext* aCx, // Whenever a START marker is found, look for the corresponding END // and build a {name,start,end} JS object. - if (startPayload->GetMetaData() == TRACING_INTERVAL_START) { + if (startPayload->GetTracingType() == MarkerTracingType::START) { bool hasSeenEnd = false; // "Paint" markers are different because painting is handled at root @@ -88,11 +88,11 @@ ObservedDocShell::PopMarkers(JSContext* aCx, if (!startPayload->Equals(*endPayload)) { continue; } - if (endPayload->GetMetaData() == TRACING_INTERVAL_START) { + if (endPayload->GetTracingType() == MarkerTracingType::START) { ++markerDepth; continue; } - if (endPayload->GetMetaData() == TRACING_INTERVAL_END) { + if (endPayload->GetTracingType() == MarkerTracingType::END) { if (markerDepth > 0) { --markerDepth; continue; diff --git a/docshell/base/timeline/RestyleTimelineMarker.h b/docshell/base/timeline/RestyleTimelineMarker.h index f91a787858..87207f9251 100644 --- a/docshell/base/timeline/RestyleTimelineMarker.h +++ b/docshell/base/timeline/RestyleTimelineMarker.h @@ -16,8 +16,8 @@ class RestyleTimelineMarker : public TimelineMarker { public: explicit RestyleTimelineMarker(nsRestyleHint aRestyleHint, - TracingMetadata aMetaData) - : TimelineMarker("Styles", aMetaData) + MarkerTracingType aTracingType) + : TimelineMarker("Styles", aTracingType) { if (aRestyleHint) { mRestyleHint.AssignWithConversion(RestyleManager::RestyleHintToString(aRestyleHint)); @@ -26,7 +26,7 @@ public: virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) override { - if (GetMetaData() == TRACING_INTERVAL_START) { + if (GetTracingType() == MarkerTracingType::START) { aMarker.mRestyleHint.Construct(mRestyleHint); } } diff --git a/docshell/base/timeline/TimelineConsumers.cpp b/docshell/base/timeline/TimelineConsumers.cpp index 4fa6b147a4..5e4fa8ca75 100644 --- a/docshell/base/timeline/TimelineConsumers.cpp +++ b/docshell/base/timeline/TimelineConsumers.cpp @@ -68,10 +68,10 @@ TimelineConsumers::GetKnownDocShells(Vector>& aStore) void TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell, const char* aName, - TracingMetadata aMetaData) + MarkerTracingType aTracingType) { if (aDocShell->IsObserved()) { - aDocShell->mObserved->AddMarker(Move(MakeUnique(aName, aMetaData))); + aDocShell->mObserved->AddMarker(Move(MakeUnique(aName, aTracingType))); } } @@ -79,10 +79,10 @@ void TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell, const char* aName, const TimeStamp& aTime, - TracingMetadata aMetaData) + MarkerTracingType aTracingType) { if (aDocShell->IsObserved()) { - aDocShell->mObserved->AddMarker(Move(MakeUnique(aName, aTime, aMetaData))); + aDocShell->mObserved->AddMarker(Move(MakeUnique(aName, aTime, aTracingType))); } } @@ -98,18 +98,18 @@ TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell, void TimelineConsumers::AddMarkerForDocShell(nsIDocShell* aDocShell, const char* aName, - TracingMetadata aMetaData) + MarkerTracingType aTracingType) { - AddMarkerForDocShell(static_cast(aDocShell), aName, aMetaData); + AddMarkerForDocShell(static_cast(aDocShell), aName, aTracingType); } void TimelineConsumers::AddMarkerForDocShell(nsIDocShell* aDocShell, const char* aName, const TimeStamp& aTime, - TracingMetadata aMetaData) + MarkerTracingType aTracingType) { - AddMarkerForDocShell(static_cast(aDocShell), aName, aTime, aMetaData); + AddMarkerForDocShell(static_cast(aDocShell), aName, aTime, aTracingType); } void @@ -122,18 +122,18 @@ TimelineConsumers::AddMarkerForDocShell(nsIDocShell* aDocShell, void TimelineConsumers::AddMarkerForDocShellsList(Vector>& aDocShells, const char* aName, - TracingMetadata aMetaData) + MarkerTracingType aTracingType) { for (Vector>::Range range = aDocShells.all(); !range.empty(); range.popFront()) { - AddMarkerForDocShell(range.front(), aName, aMetaData); + AddMarkerForDocShell(range.front(), aName, aTracingType); } } void TimelineConsumers::AddMarkerForAllObservedDocShells(const char* aName, - TracingMetadata aMetaData) + MarkerTracingType aTracingType) { Vector> docShells; if (!GetKnownDocShells(docShells)) { @@ -142,7 +142,7 @@ TimelineConsumers::AddMarkerForAllObservedDocShells(const char* aName, return; } - AddMarkerForDocShellsList(docShells, aName, aMetaData); + AddMarkerForDocShellsList(docShells, aName, aTracingType); } } // namespace mozilla diff --git a/docshell/base/timeline/TimelineConsumers.h b/docshell/base/timeline/TimelineConsumers.h index b6258fea55..56f2a3e285 100644 --- a/docshell/base/timeline/TimelineConsumers.h +++ b/docshell/base/timeline/TimelineConsumers.h @@ -10,7 +10,9 @@ #include "mozilla/UniquePtr.h" #include "mozilla/LinkedList.h" #include "mozilla/Vector.h" -#include "GeckoProfiler.h" +#include "mozilla/TimeStamp.h" + +#include "TimelineMarkerEnums.h" class nsDocShell; class nsIDocShell; @@ -46,19 +48,19 @@ public: // relevant for a specific docshell. static void AddMarkerForDocShell(nsDocShell* aDocShell, const char* aName, - TracingMetadata aMetaData); + MarkerTracingType aTracingType); static void AddMarkerForDocShell(nsIDocShell* aDocShell, const char* aName, - TracingMetadata aMetaData); + MarkerTracingType aTracingType); static void AddMarkerForDocShell(nsDocShell* aDocShell, const char* aName, const TimeStamp& aTime, - TracingMetadata aMetaData); + MarkerTracingType aTracingType); static void AddMarkerForDocShell(nsIDocShell* aDocShell, const char* aName, const TimeStamp& aTime, - TracingMetadata aMetaData); + MarkerTracingType aTracingType); // These methods register and receive ownership of an already created marker, // relevant for a specific docshell. @@ -70,12 +72,12 @@ public: // This method creates custom markers, relevant for a list of docshells. static void AddMarkerForDocShellsList(Vector>& aDocShells, const char* aName, - TracingMetadata aMetaData); + MarkerTracingType aTracingType); // This method creates custom markers, none of which have to be tied to a // particular docshell. static void AddMarkerForAllObservedDocShells(const char* aName, - TracingMetadata aMetaData); + MarkerTracingType aTracingType); }; } // namespace mozilla diff --git a/docshell/base/timeline/TimelineMarker.cpp b/docshell/base/timeline/TimelineMarker.cpp index 4c4b2cfe13..ef721f49a1 100644 --- a/docshell/base/timeline/TimelineMarker.cpp +++ b/docshell/base/timeline/TimelineMarker.cpp @@ -9,89 +9,66 @@ namespace mozilla { TimelineMarker::TimelineMarker(const char* aName, - TracingMetadata aMetaData, - TimelineStackRequest aStackRequest) - : mName(aName) - , mMetaData(aMetaData) + MarkerTracingType aTracingType, + MarkerStackRequest aStackRequest) + : AbstractTimelineMarker(aName, aTracingType) { - MOZ_COUNT_CTOR(TimelineMarker); - MOZ_ASSERT(aName); - - SetCurrentTime(); - CaptureStackIfNecessary(aMetaData, aStackRequest); + CaptureStackIfNecessary(aTracingType, aStackRequest); } TimelineMarker::TimelineMarker(const char* aName, const TimeStamp& aTime, - TracingMetadata aMetaData, - TimelineStackRequest aStackRequest) - : mName(aName) - , mMetaData(aMetaData) + MarkerTracingType aTracingType, + MarkerStackRequest aStackRequest) + : AbstractTimelineMarker(aName, aTime, aTracingType) { - MOZ_COUNT_CTOR(TimelineMarker); - MOZ_ASSERT(aName); - - SetCustomTime(aTime); - CaptureStackIfNecessary(aMetaData, aStackRequest); + CaptureStackIfNecessary(aTracingType, aStackRequest); } -TimelineMarker::TimelineMarker(const char* aName, - const nsAString& aCause, - TracingMetadata aMetaData, - TimelineStackRequest aStackRequest) - : mName(aName) - , mCause(aCause) - , mMetaData(aMetaData) +bool +TimelineMarker::Equals(const AbstractTimelineMarker& aOther) { - MOZ_COUNT_CTOR(TimelineMarker); - MOZ_ASSERT(aName); - - SetCurrentTime(); - CaptureStackIfNecessary(aMetaData, aStackRequest); -} - -TimelineMarker::TimelineMarker(const char* aName, - const nsAString& aCause, - const TimeStamp& aTime, - TracingMetadata aMetaData, - TimelineStackRequest aStackRequest) - : mName(aName) - , mCause(aCause) - , mMetaData(aMetaData) -{ - MOZ_COUNT_CTOR(TimelineMarker); - MOZ_ASSERT(aName); - - SetCustomTime(aTime); - CaptureStackIfNecessary(aMetaData, aStackRequest); -} - -TimelineMarker::~TimelineMarker() -{ - MOZ_COUNT_DTOR(TimelineMarker); + // Check whether two markers should be considered the same, for the purpose + // of pairing start and end markers. Normally this definition suffices. + return strcmp(GetName(), aOther.GetName()) == 0; } void -TimelineMarker::SetCurrentTime() +TimelineMarker::AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) { - TimeStamp now = TimeStamp::Now(); - SetCustomTime(now); + // Nothing to do here for plain markers. +} + +JSObject* +TimelineMarker::GetStack() +{ + if (mStackTrace.initialized()) { + return mStackTrace; + } + return nullptr; } void -TimelineMarker::SetCustomTime(const TimeStamp& aTime) +TimelineMarker::CaptureStack() { - bool isInconsistent = false; - mTime = (aTime - TimeStamp::ProcessCreation(isInconsistent)).ToMilliseconds(); + JSContext* ctx = nsContentUtils::GetCurrentJSContext(); + if (ctx) { + JS::RootedObject stack(ctx); + if (JS::CaptureCurrentStack(ctx, &stack)) { + mStackTrace.init(ctx, stack.get()); + } else { + JS_ClearPendingException(ctx); + } + } } void -TimelineMarker::CaptureStackIfNecessary(TracingMetadata aMetaData, - TimelineStackRequest aStackRequest) +TimelineMarker::CaptureStackIfNecessary(MarkerTracingType aTracingType, + MarkerStackRequest aStackRequest) { - if ((aMetaData == TRACING_INTERVAL_START || - aMetaData == TRACING_TIMESTAMP) && - aStackRequest != NO_STACK) { + if ((aTracingType == MarkerTracingType::START || + aTracingType == MarkerTracingType::TIMESTAMP) && + aStackRequest != MarkerStackRequest::NO_STACK) { CaptureStack(); } } diff --git a/docshell/base/timeline/TimelineMarker.h b/docshell/base/timeline/TimelineMarker.h index e010f0fb6e..c940110265 100644 --- a/docshell/base/timeline/TimelineMarker.h +++ b/docshell/base/timeline/TimelineMarker.h @@ -7,104 +7,43 @@ #ifndef mozilla_TimelineMarker_h_ #define mozilla_TimelineMarker_h_ -#include "nsString.h" #include "nsContentUtils.h" -#include "GeckoProfiler.h" - -class nsDocShell; +#include "AbstractTimelineMarker.h" namespace mozilla { -namespace dom { -struct ProfileTimelineMarker; -} // Objects of this type can be added to the timeline if there is an interested // consumer. The class can also be subclassed to let a given marker creator // provide custom details. -class TimelineMarker +class TimelineMarker : public AbstractTimelineMarker { public: - enum TimelineStackRequest { STACK, NO_STACK }; - TimelineMarker(const char* aName, - TracingMetadata aMetaData, - TimelineStackRequest aStackRequest = STACK); + MarkerTracingType aTracingType, + MarkerStackRequest aStackRequest = MarkerStackRequest::STACK); TimelineMarker(const char* aName, const TimeStamp& aTime, - TracingMetadata aMetaData, - TimelineStackRequest aStackRequest = STACK); + MarkerTracingType aTracingType, + MarkerStackRequest aStackRequest = MarkerStackRequest::STACK); - TimelineMarker(const char* aName, - const nsAString& aCause, - TracingMetadata aMetaData, - TimelineStackRequest aStackRequest = STACK); + virtual bool Equals(const AbstractTimelineMarker& aOther) override; + virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) override; - TimelineMarker(const char* aName, - const nsAString& aCause, - const TimeStamp& aTime, - TracingMetadata aMetaData, - TimelineStackRequest aStackRequest = STACK); - - virtual ~TimelineMarker(); - - // Check whether two markers should be considered the same, for the purpose - // of pairing start and end markers. Normally this definition suffices. - virtual bool Equals(const TimelineMarker& aOther) - { - return strcmp(mName, aOther.mName) == 0; - } - - // Add details specific to this marker type to aMarker. The standard elements - // have already been set. This method is called on both the starting and - // ending markers of a pair. Ordinarily the ending marker doesn't need to do - // anything here. - virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) - {} - - const char* GetName() const { return mName; } - const nsString& GetCause() const { return mCause; } - DOMHighResTimeStamp GetTime() const { return mTime; } - TracingMetadata GetMetaData() const { return mMetaData; } - - JSObject* GetStack() - { - if (mStackTrace.initialized()) { - return mStackTrace; - } - return nullptr; - } + JSObject* GetStack(); protected: - void CaptureStack() - { - JSContext* ctx = nsContentUtils::GetCurrentJSContext(); - if (ctx) { - JS::RootedObject stack(ctx); - if (JS::CaptureCurrentStack(ctx, &stack)) { - mStackTrace.init(ctx, stack.get()); - } else { - JS_ClearPendingException(ctx); - } - } - } + void CaptureStack(); private: - const char* mName; - nsString mCause; - DOMHighResTimeStamp mTime; - TracingMetadata mMetaData; - // While normally it is not a good idea to make a persistent root, // in this case changing nsDocShell to participate in cycle // collection was deemed too invasive, and the markers are only held // here temporarily to boot. JS::PersistentRooted mStackTrace; - void SetCurrentTime(); - void SetCustomTime(const TimeStamp& aTime); - void CaptureStackIfNecessary(TracingMetadata aMetaData, - TimelineStackRequest aStackRequest); + void CaptureStackIfNecessary(MarkerTracingType aTracingType, + MarkerStackRequest aStackRequest); }; } // namespace mozilla diff --git a/docshell/base/timeline/TimelineMarkerEnums.h b/docshell/base/timeline/TimelineMarkerEnums.h new file mode 100644 index 0000000000..779f8ba729 --- /dev/null +++ b/docshell/base/timeline/TimelineMarkerEnums.h @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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_TimelineMarkerEnums_h_ +#define mozilla_TimelineMarkerEnums_h_ + +namespace mozilla { + +enum class MarkerTracingType { + START, + END, + TIMESTAMP, + HELPER_EVENT +}; + +enum class MarkerStackRequest { + STACK, + NO_STACK +}; + +} // namespace mozilla + +#endif // mozilla_TimelineMarkerEnums_h_ diff --git a/docshell/base/timeline/TimestampTimelineMarker.h b/docshell/base/timeline/TimestampTimelineMarker.h index 9eaa6ae07b..73ed91800a 100644 --- a/docshell/base/timeline/TimestampTimelineMarker.h +++ b/docshell/base/timeline/TimestampTimelineMarker.h @@ -16,15 +16,19 @@ class TimestampTimelineMarker : public TimelineMarker { public: explicit TimestampTimelineMarker(const nsAString& aCause) - : TimelineMarker("TimeStamp", aCause, TRACING_TIMESTAMP) + : TimelineMarker("TimeStamp", MarkerTracingType::TIMESTAMP) + , mCause(aCause) {} virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) override { - if (!GetCause().IsEmpty()) { - aMarker.mCauseName.Construct(GetCause()); + if (!mCause.IsEmpty()) { + aMarker.mCauseName.Construct(mCause); } } + +private: + nsString mCause; }; } // namespace mozilla diff --git a/docshell/base/timeline/moz.build b/docshell/base/timeline/moz.build index bef6dd20a8..9a79e8d7a2 100644 --- a/docshell/base/timeline/moz.build +++ b/docshell/base/timeline/moz.build @@ -5,6 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXPORTS.mozilla += [ + 'AbstractTimelineMarker.h', 'AutoGlobalTimelineMarker.h', 'AutoTimelineMarker.h', 'ConsoleTimelineMarker.h', @@ -15,10 +16,12 @@ EXPORTS.mozilla += [ 'RestyleTimelineMarker.h', 'TimelineConsumers.h', 'TimelineMarker.h', + 'TimelineMarkerEnums.h', 'TimestampTimelineMarker.h', ] UNIFIED_SOURCES += [ + 'AbstractTimelineMarker.cpp', 'AutoGlobalTimelineMarker.cpp', 'AutoTimelineMarker.cpp', 'ObservedDocShell.cpp', diff --git a/dom/base/Console.cpp b/dom/base/Console.cpp index 7c1e8d8666..e5db9d6a9d 100644 --- a/dom/base/Console.cpp +++ b/dom/base/Console.cpp @@ -1102,8 +1102,8 @@ Console::Method(JSContext* aCx, MethodName aMethodName, nsAutoJSString key; if (key.init(aCx, jsString)) { UniquePtr marker = MakeUnique( - key, aMethodName == MethodTime ? TRACING_INTERVAL_START - : TRACING_INTERVAL_END); + key, aMethodName == MethodTime ? MarkerTracingType::START + : MarkerTracingType::END); TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker)); } } diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 891bebaf08..b70f351170 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -118,6 +118,10 @@ #include "mozilla/dom/FeatureList.h" +#ifdef MOZ_WIDGET_GONK +#include +#endif + namespace mozilla { namespace dom { @@ -1554,6 +1558,26 @@ Navigator::GetFeature(const nsAString& aName, ErrorResult& aRv) } // hardware.memory #endif +#ifdef MOZ_WIDGET_GONK + if (StringBeginsWith(aName, NS_LITERAL_STRING("acl.")) && + (aName.EqualsLiteral("acl.version") || CheckPermission("external-app"))) { + char value[PROPERTY_VALUE_MAX]; + nsCString propertyKey("persist."); + propertyKey.Append(NS_ConvertUTF16toUTF8(aName)); + uint32_t len = property_get(propertyKey.get(), value, nullptr); + if (len > 0) { + p->MaybeResolve(NS_ConvertUTF8toUTF16(value)); + return p.forget(); + } + } +#endif + + // Mirror the dom.apps.developer_mode pref to let apps get it read-only. + if (aName.EqualsLiteral("dom.apps.developer_mode")) { + p->MaybeResolve(Preferences::GetBool("dom.apps.developer_mode", false)); + return p.forget(); + } + p->MaybeResolve(JS::UndefinedHandleValue); return p.forget(); } @@ -1567,6 +1591,14 @@ Navigator::HasFeature(const nsAString& aName, ErrorResult& aRv) return nullptr; } + // Hardcoded web-extensions feature which is b2g specific. +#ifdef MOZ_B2G + if (aName.EqualsLiteral("web-extensions")) { + p->MaybeResolve(true); + return p.forget(); + } +#endif + // Hardcoded manifest features. Some are still b2g specific. const char manifestFeatures[][64] = { "manifest.origin" diff --git a/dom/base/nsDeprecatedOperationList.h b/dom/base/nsDeprecatedOperationList.h index fed7c176cc..3adab2d940 100644 --- a/dom/base/nsDeprecatedOperationList.h +++ b/dom/base/nsDeprecatedOperationList.h @@ -41,3 +41,4 @@ DEPRECATED_OPERATION(DataContainerEvent) DEPRECATED_OPERATION(Window_Controllers) DEPRECATED_OPERATION(ImportXULIntoContent) DEPRECATED_OPERATION(PannerNodeDoppler) +DEPRECATED_OPERATION(AppCache) diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp index e929777578..bac83938d2 100644 --- a/dom/base/nsObjectLoadingContent.cpp +++ b/dom/base/nsObjectLoadingContent.cpp @@ -21,7 +21,6 @@ #include "nsIDOMHTMLAppletElement.h" #include "nsIExternalProtocolHandler.h" #include "nsIInterfaceRequestorUtils.h" -#include "nsIHttpChannelInternal.h" #include "nsIObjectFrame.h" #include "nsIPermissionManager.h" #include "nsPluginHost.h" @@ -2495,7 +2494,8 @@ nsObjectLoadingContent::OpenChannel() group, // aLoadGroup shim, // aCallbacks nsIChannel::LOAD_CALL_CONTENT_SNIFFERS | - nsIChannel::LOAD_CLASSIFY_URI); + nsIChannel::LOAD_CLASSIFY_URI | + nsIChannel::LOAD_BYPASS_SERVICE_WORKER); NS_ENSURE_SUCCESS(rv, rv); @@ -2518,13 +2518,6 @@ nsObjectLoadingContent::OpenChannel() scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL); } - nsCOMPtr internalChannel = do_QueryInterface(httpChan); - if (internalChannel) { - // Bug 1168676. object/embed tags are not allowed to be intercepted by - // ServiceWorkers. - internalChannel->ForceNoIntercept(); - } - // AsyncOpen can fail if a file does not exist. rv = chan->AsyncOpen(shim, nullptr); NS_ENSURE_SUCCESS(rv, rv); diff --git a/dom/base/test/test_getFeature_with_perm.html b/dom/base/test/test_getFeature_with_perm.html index 80a0bfe9a3..eec8288f06 100644 --- a/dom/base/test/test_getFeature_with_perm.html +++ b/dom/base/test/test_getFeature_with_perm.html @@ -76,13 +76,31 @@ function createManifestTest(aFeature) { } } +function testDevMode(aExpected) { + return function() { + navigator.getFeature("dom.apps.developer_mode").then(res => { + is(res, aExpected, "dom.apps.developer_mode is " + aExpected); + runNextTest(); + }, function() { + ok(false, "The Promise should not be rejected"); + }); + } +} + +function enableDevMode() { + SpecialPowers.pushPrefEnv({"set": [["dom.apps.developer_mode", true]]}, runNextTest); +} + var currentTest = -1; var tests = [ testNotSupported, testNotSupportedManifest, testSupported, createManifestTest("manifest.origin"), - createManifestTest("manifest.redirects") + createManifestTest("manifest.redirects"), + testDevMode(false), + enableDevMode, + testDevMode(true) ]; function runNextTest() { diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp index a2d6a69f2e..ff035acd7e 100644 --- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -1130,7 +1130,7 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext, uint16_t phase; (*aDOMEvent)->GetEventPhase(&phase); UniquePtr marker = MakeUnique( - typeStr, phase, TRACING_INTERVAL_START); + typeStr, phase, MarkerTracingType::START); TimelineConsumers::AddMarkerForDocShell(ds, Move(marker)); } } @@ -1142,7 +1142,7 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext, if (isTimelineRecording) { nsDocShell* ds = static_cast(docShell.get()); - TimelineConsumers::AddMarkerForDocShell(ds, "DOMEvent", TRACING_INTERVAL_END); + TimelineConsumers::AddMarkerForDocShell(ds, "DOMEvent", MarkerTracingType::END); } } } diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index 16094ec641..ebf8ea6cd5 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -415,6 +415,12 @@ FetchDriver::HttpFetch(bool aCORSFlag, bool aCORSPreflightFlag, bool aAuthentica // new cookies sent by the server from being stored. const nsLoadFlags credentialsFlag = useCredentials ? 0 : nsIRequest::LOAD_ANONYMOUS; + // Set skip serviceworker flag. + // While the spec also gates on the client being a ServiceWorker, we can't + // infer that here. Instead we rely on callers to set the flag correctly. + const nsLoadFlags bypassFlag = mRequest->SkipServiceWorker() ? + nsIChannel::LOAD_BYPASS_SERVICE_WORKER : 0; + // From here on we create a channel and set its properties with the // information from the InternalRequest. This is an implementation detail. MOZ_ASSERT(mLoadGroup); @@ -426,7 +432,7 @@ FetchDriver::HttpFetch(bool aCORSFlag, bool aCORSPreflightFlag, bool aAuthentica mRequest->ContentPolicyType(), mLoadGroup, nullptr, /* aCallbacks */ - nsIRequest::LOAD_NORMAL | credentialsFlag, + nsIRequest::LOAD_NORMAL | credentialsFlag | bypassFlag, ios); mLoadGroup = nullptr; if (NS_WARN_IF(NS_FAILED(rv))) { @@ -562,21 +568,6 @@ FetchDriver::HttpFetch(bool aCORSFlag, bool aCORSPreflightFlag, bool aAuthentica } } - // Set skip serviceworker flag. - // While the spec also gates on the client being a ServiceWorker, we can't - // infer that here. Instead we rely on callers to set the flag correctly. - if (mRequest->SkipServiceWorker()) { - if (httpChan) { - nsCOMPtr internalChan = do_QueryInterface(httpChan); - internalChan->ForceNoIntercept(); - } else { - nsCOMPtr jarChannel = do_QueryInterface(chan); - // If it is not an http channel, it has to be a jar one. - MOZ_ASSERT(jarChannel); - jarChannel->ForceNoIntercept(); - } - } - nsCOMPtr listener = this; // Only use nsCORSListenerProxy if we are in CORS mode. Otherwise it @@ -786,6 +777,13 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest, uint32_t responseStatus = 200; nsAutoCString statusText; response = new InternalResponse(responseStatus, NS_LITERAL_CSTRING("OK")); + ErrorResult result; + nsAutoCString contentType; + jarChannel->GetContentType(contentType); + response->Headers()->Append(NS_LITERAL_CSTRING("content-type"), + contentType, + result); + MOZ_ASSERT(!result.Failed()); } // We open a pipe so that we can immediately set the pipe's read end as the diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 7797d96a63..c4733804e5 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1633,7 +1633,7 @@ TabChild::MaybeRequestPreinitCamera() nsCOMPtr app; nsresult rv = appsService->GetAppByLocalId(OwnAppId(), getter_AddRefs(app)); - if (NS_WARN_IF(NS_FAILED(rv))) { + if (NS_WARN_IF(NS_FAILED(rv)) || !app) { return; } @@ -2953,6 +2953,21 @@ TabChild::DidComposite(uint64_t aTransactionId, manager->DidComposite(aTransactionId, aCompositeStart, aCompositeEnd); } +void +TabChild::DidRequestComposite(const TimeStamp& aCompositeReqStart, + const TimeStamp& aCompositeReqEnd) +{ + nsCOMPtr docShell = do_GetInterface(WebNavigation()); + if (!docShell) { + return; + } + + TimelineConsumers::AddMarkerForDocShell(docShell.get(), + "CompositeForwardTransaction", aCompositeReqStart, MarkerTracingType::START); + TimelineConsumers::AddMarkerForDocShell(docShell.get(), + "CompositeForwardTransaction", aCompositeReqEnd, MarkerTracingType::END); +} + void TabChild::ClearCachedResources() { diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 968dbb890b..125556a1f1 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -469,6 +469,8 @@ public: void DidComposite(uint64_t aTransactionId, const TimeStamp& aCompositeStart, const TimeStamp& aCompositeEnd); + void DidRequestComposite(const TimeStamp& aCompositeReqStart, + const TimeStamp& aCompositeReqEnd); void ClearCachedResources(); diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties index 148c80f90e..e98fd33e26 100644 --- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -160,8 +160,10 @@ IndexedDBTransactionAbortNavigation=An IndexedDB transaction that was not yet co WillChangeBudgetWarning=Will-change memory consumption is too high. Surface area covers %1$S pixels, budget is the document surface area multiplied by %2$S (%3$S pixels). Occurences of will-change over the budget will be ignored. # LOCALIZATION NOTE: Do not translate "ServiceWorker". HittingMaxWorkersPerDomain=A ServiceWorker could not be started immediately because other documents in the same origin are already using the maximum number of workers. The ServiceWorker is now queued and will be started after some of the other workers have completed. -# LOCALIZATION NOTE: Do no translate "setVelocity", "PannerNode", "AudioListener", "speedOfSound" and "dopplerFactor" +# LOCALIZATION NOTE: Do not translate "setVelocity", "PannerNode", "AudioListener", "speedOfSound" and "dopplerFactor" PannerNodeDopplerWarning=Use of setVelocity on the PannerNode and AudioListener, and speedOfSound and dopplerFactor on the AudioListener are deprecated and those members will be removed. For more help https://developer.mozilla.org/en-US/docs/Web/API/AudioListener#Deprecated_features +# LOCALIZATION NOTE: Do not translate "Application Cache API", "AppCache" and "ServiceWorker". +AppCacheWarning=The Application Cache API (AppCache) is deprecated and will be removed at a future date. Please consider using ServiceWorker for offline support. # LOCALIZATION NOTE: Do not translate "Worker". EmptyWorkerSourceWarning=Attempting to create a Worker from an empty source. This is probably unintentional. # LOCALIZATION NOTE: Do not translate "ServiceWorker". diff --git a/dom/tests/mochitest/beacon/beacon-cors-redirect-handler.sjs b/dom/tests/mochitest/beacon/beacon-cors-redirect-handler.sjs new file mode 100644 index 0000000000..b20c7265dd --- /dev/null +++ b/dom/tests/mochitest/beacon/beacon-cors-redirect-handler.sjs @@ -0,0 +1,52 @@ +/* + * TestSever customized specifically for the needs of: + * Bug 1111834 - sendBeacon() should not follow 30x redirect after preflight + * + * Here is a sequence of the test: + * [1] preflight channel (identified by the queryString 'beacon' and method 'OPTIONS') + * [2] actual channel (identified by the queryString 'beacon') which gets redirected + * [3] should never happen (the actual redirected request) + * [4] xhr request (identified by the queryString 'verifyRedirectDidNotSucceed') + * which checks if the state was not changed from 'green' to 'red'. If the channel + * woulnd't be blocked correctly the redirected channel would set the state to 'red'. + * + */ + +function handleRequest(request, response) +{ + response.setHeader("Cache-Control", "no-cache, must-revalidate", false); + + // [Sequence 4] + if (request.queryString === "verifyRedirectDidNotSucceed") { + var redirectState = getState("redirectState"); + response.write(redirectState); + return; + } + + var originHeader = request.getHeader("origin"); + response.setHeader("Cache-Control", "no-cache, must-revalidate", false); + response.setHeader("Access-Control-Allow-Headers", "content-type", false); + response.setHeader("Access-Control-Allow-Methods", "POST, GET", false); + response.setHeader("Access-Control-Allow-Origin", originHeader, false); + response.setHeader("Access-Control-Allow-Credentials", "true", false); + + // [Sequence 1,2] + if (request.queryString === "beacon") { + setState("redirectState", "green"); + // [1] + if (request.method == "OPTIONS") { + response.setStatusLine(null, 200, "OK"); + return; + } + // [Sequence 2] + var newLocation = + "http://mochi.test:8888/tests/dom/tests/mochitest/beacon/beacon-cors-redirect-handler.sjs?redirected"; + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", newLocation, false); + return; + } + + // [Sequence 3] + setState("redirectState", "red"); + response.setStatusLine(null, 200, "OK"); +} diff --git a/dom/tests/mochitest/beacon/beacon-preflight-handler.sjs b/dom/tests/mochitest/beacon/beacon-preflight-handler.sjs new file mode 100644 index 0000000000..6a760cb84c --- /dev/null +++ b/dom/tests/mochitest/beacon/beacon-preflight-handler.sjs @@ -0,0 +1,39 @@ +function handleRequest(request, response) +{ + response.setHeader("Cache-Control", "no-cache, must-revalidate", false); + + if (request.queryString === "verify") { + var preflightState = getState("preflight"); + response.write(preflightState === "done" ? "green" : "red"); + return; + } + + var originHeader = request.getHeader("origin"); + response.setHeader("Access-Control-Allow-Headers", "content-type", false); + response.setHeader("Access-Control-Allow-Methods", "POST, GET", false); + response.setHeader("Access-Control-Allow-Origin", originHeader, false); + response.setHeader("Access-Control-Allow-Credentials", "true", false); + + if (request.queryString === "beacon") { + if (request.method == "OPTIONS") { + setState("preflight", "done"); + response.setStatusLine(null, 200, "OK"); + return; + } + response.setStatusLine(null, 200, "OK"); + response.write("DONE"); + return; + } + + if (request.queryString === "fail") { + if (request.method == "OPTIONS") { + setState("preflight", "done"); + response.setStatusLine(null, 400, "Bad Request"); + return; + } + setState("preflight", "oops"); + response.setStatusLine(null, 200, "OK"); + response.write("DONE"); + return; + } +} diff --git a/dom/tests/mochitest/beacon/mochitest.ini b/dom/tests/mochitest/beacon/mochitest.ini index 133c55abda..c15c52461a 100644 --- a/dom/tests/mochitest/beacon/mochitest.ini +++ b/dom/tests/mochitest/beacon/mochitest.ini @@ -2,10 +2,14 @@ skip-if = buildapp == 'b2g' support-files = beacon-frame.html beacon-handler.sjs + beacon-preflight-handler.sjs beacon-originheader-handler.sjs + beacon-cors-redirect-handler.sjs [test_beacon.html] [test_beaconFrame.html] [test_beaconPreflight.html] +[test_beaconPreflightFailure.html] [test_beaconContentPolicy.html] [test_beaconOriginHeader.html] +[test_beaconCORSRedirect.html] diff --git a/dom/tests/mochitest/beacon/test_beaconCORSRedirect.html b/dom/tests/mochitest/beacon/test_beaconCORSRedirect.html new file mode 100644 index 0000000000..0305f9890a --- /dev/null +++ b/dom/tests/mochitest/beacon/test_beaconCORSRedirect.html @@ -0,0 +1,57 @@ + + + + Bug 1111834 - sendBeacon() should not follow 30x redirect after preflight + + + + + +

+ + + + + + diff --git a/dom/tests/mochitest/beacon/test_beaconPreflight.html b/dom/tests/mochitest/beacon/test_beaconPreflight.html index 63f4d78570..cec5df84a1 100644 --- a/dom/tests/mochitest/beacon/test_beaconPreflight.html +++ b/dom/tests/mochitest/beacon/test_beaconPreflight.html @@ -17,7 +17,24 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=936340
 
diff --git a/dom/tests/mochitest/beacon/test_beaconPreflightFailure.html b/dom/tests/mochitest/beacon/test_beaconPreflightFailure.html
new file mode 100644
index 0000000000..11879222f1
--- /dev/null
+++ b/dom/tests/mochitest/beacon/test_beaconPreflightFailure.html
@@ -0,0 +1,56 @@
+
+
+
+
+  Test for Bug 1207556
+  
+  
+
+
+Mozilla Bug 1207556
+

+ +
+
+
+ + diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp index 399a103a62..d6ebe075eb 100644 --- a/dom/workers/ScriptLoader.cpp +++ b/dom/workers/ScriptLoader.cpp @@ -108,6 +108,7 @@ ChannelFromScriptURL(nsIPrincipal* principal, bool aIsMainScript, WorkerScriptType aWorkerScriptType, nsContentPolicyType aContentPolicyType, + nsLoadFlags aLoadFlags, nsIChannel** aChannel) { AssertIsOnMainThread(); @@ -167,7 +168,7 @@ ChannelFromScriptURL(nsIPrincipal* principal, NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SECURITY_ERR); } - uint32_t flags = nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI; + aLoadFlags |= nsIChannel::LOAD_CLASSIFY_URI; nsCOMPtr channel; // If we have the document, use it @@ -179,7 +180,7 @@ ChannelFromScriptURL(nsIPrincipal* principal, aContentPolicyType, loadGroup, nullptr, // aCallbacks - flags, + aLoadFlags, ios); } else { // We must have a loadGroup with a load context for the principal to @@ -194,7 +195,7 @@ ChannelFromScriptURL(nsIPrincipal* principal, aContentPolicyType, loadGroup, nullptr, // aCallbacks - flags, + aLoadFlags, ios); } @@ -855,11 +856,20 @@ private: ScriptLoadInfo& loadInfo = mLoadInfos[aIndex]; nsresult& rv = loadInfo.mLoadResult; + nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL; + + // If we are loading a script for a ServiceWorker then we must not + // try to intercept it. If the interception matches the current + // ServiceWorker's scope then we could deadlock the load. + if (mWorkerPrivate->IsServiceWorker()) { + loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER; + } + if (!channel) { rv = ChannelFromScriptURL(principal, baseURI, parentDoc, loadGroup, ios, secMan, loadInfo.mURL, IsMainWorkerScript(), mWorkerScriptType, - mWorkerPrivate->ContentPolicyType(), + mWorkerPrivate->ContentPolicyType(), loadFlags, getter_AddRefs(channel)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; @@ -887,16 +897,6 @@ private: return rv; } - // If we are loading a script for a ServiceWorker then we must not - // try to intercept it. If the interception matches the current - // ServiceWorker's scope then we could deadlock the load. - if (mWorkerPrivate->IsServiceWorker()) { - nsCOMPtr internal = do_QueryInterface(channel); - if (internal) { - internal->ForceNoIntercept(); - } - } - if (loadInfo.mCacheStatus != ScriptLoadInfo::ToBeCached) { rv = channel->AsyncOpen(loader, indexSupports); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -1847,7 +1847,8 @@ ChannelFromScriptURLMainThread(nsIPrincipal* aPrincipal, return ChannelFromScriptURL(aPrincipal, aBaseURI, aParentDoc, aLoadGroup, ios, secMan, aScriptURL, true, WorkerScript, - aContentPolicyType, aChannel); + aContentPolicyType, nsIRequest::LOAD_NORMAL, + aChannel); } nsresult diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorkerScriptCache.cpp index 1c44aa1ed8..03f91ba5be 100644 --- a/dom/workers/ServiceWorkerScriptCache.cpp +++ b/dom/workers/ServiceWorkerScriptCache.cpp @@ -117,7 +117,9 @@ public: uri, aPrincipal, nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_INTERNAL_SCRIPT, - loadGroup); + loadGroup, + nullptr, // aCallbacks + nsIChannel::LOAD_BYPASS_SERVICE_WORKER); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -140,12 +142,6 @@ public: httpChannel->SetRedirectionLimit(0); } - // Don't let serviceworker intercept. - nsCOMPtr internalChannel = do_QueryInterface(mChannel); - if (internalChannel) { - internalChannel->ForceNoIntercept(); - } - nsCOMPtr loader; rv = NS_NewStreamLoader(getter_AddRefs(loader), this, this); if (NS_WARN_IF(NS_FAILED(rv))) { diff --git a/dom/xslt/base/txURIUtils.cpp b/dom/xslt/base/txURIUtils.cpp index b2a78db2e4..33f7e919aa 100644 --- a/dom/xslt/base/txURIUtils.cpp +++ b/dom/xslt/base/txURIUtils.cpp @@ -6,6 +6,7 @@ #include "txURIUtils.h" #include "nsNetUtil.h" #include "nsIDocument.h" +#include "nsIHttpChannelInternal.h" #include "nsIPrincipal.h" #include "mozilla/LoadInfo.h" @@ -64,12 +65,15 @@ URIUtils::ResetWithSource(nsIDocument *aNewDoc, nsIDOMNode *aSourceNode) sourceDoc, nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL, nsIContentPolicy::TYPE_OTHER, - loadGroup); + loadGroup, + nullptr, // aCallbacks + nsIChannel::LOAD_BYPASS_SERVICE_WORKER); if (NS_FAILED(rv)) { return; } } + aNewDoc->Reset(channel, loadGroup); aNewDoc->SetPrincipal(sourcePrincipal); aNewDoc->SetBaseURI(sourceDoc->GetDocBaseURI()); diff --git a/gfx/layers/apz/test/apz_test_native_event_utils.js b/gfx/layers/apz/test/apz_test_native_event_utils.js index 787e6843a7..2c15897448 100644 --- a/gfx/layers/apz/test/apz_test_native_event_utils.js +++ b/gfx/layers/apz/test/apz_test_native_event_utils.js @@ -31,19 +31,30 @@ function nativeHorizontalWheelEventMsg() { throw "Native wheel events not supported on platform " + getPlatform(); } +// Convert (aX, aY), in CSS pixels relative to aElement's bounding rect, +// to device pixels relative to aElement's containing window. +function coordinatesRelativeToWindow(aX, aY, aElement) { + var targetWindow = aElement.ownerDocument.defaultView; + var scale = targetWindow.devicePixelRatio; + var rect = aElement.getBoundingClientRect(); + return { + x: targetWindow.mozInnerScreenX + ((rect.left + aX) * scale), + y: targetWindow.mozInnerScreenY + ((rect.top + aY) * scale) + }; +} + // Synthesizes a native mousewheel event and returns immediately. This does not // guarantee anything; you probably want to use one of the other functions below // which actually wait for results. // aX and aY are relative to |window|'s top-left. aDeltaX and aDeltaY // are pixel deltas, and aObserver can be left undefined if not needed. function synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY, aObserver) { - aX += window.mozInnerScreenX; - aY += window.mozInnerScreenY; + var pt = coordinatesRelativeToWindow(aX, aY, aElement); if (aDeltaX && aDeltaY) { throw "Simultaneous wheeling of horizontal and vertical is not supported on all platforms."; } var msg = aDeltaX ? nativeHorizontalWheelEventMsg() : nativeVerticalWheelEventMsg(); - _getDOMWindowUtils().sendNativeMouseScrollEvent(aX, aY, msg, aDeltaX, aDeltaY, 0, 0, 0, aElement, aObserver); + _getDOMWindowUtils().sendNativeMouseScrollEvent(pt.x, pt.y, msg, aDeltaX, aDeltaY, 0, 0, 0, aElement, aObserver); return true; } @@ -85,18 +96,34 @@ function synthesizeNativeWheelAndWaitForScrollEvent(aElement, aX, aY, aDeltaX, a return synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY); } +// Synthesizes a native mouse move event and returns immediately. +// aX and aY are relative to the top-left of |aElement|'s containing window. +function synthesizeNativeMouseMove(aElement, aX, aY) { + var pt = coordinatesRelativeToWindow(aX, aY, aElement); + _getDOMWindowUtils().sendNativeMouseEvent(pt.x, pt.y, nativeMouseMoveEventMsg(), 0, aElement); + return true; +} + +// Synthesizes a native mouse move event and invokes the callback once the +// mouse move event is dispatched to |aElement|'s containing window. If the event +// targets content in a subdocument, |aElement| should be inside the +// subdocument. See synthesizeNativeMouseMove for details on the other +// parameters. +function synthesizeNativeMouseMoveAndWaitForMoveEvent(aElement, aX, aY, aCallback) { + var targetWindow = aElement.ownerDocument.defaultView; + targetWindow.addEventListener("mousemove", function mousemoveWaiter(e) { + targetWindow.removeEventListener("mousemove", mousemoveWaiter); + setTimeout(aCallback, 0); + }); + return synthesizeNativeMouseMove(aElement, aX, aY); +} + // Synthesizes a native touch event and dispatches it. aX and aY in CSS pixels // relative to the top-left of |aElement|'s bounding rect. function synthesizeNativeTouch(aElement, aX, aY, aType, aObserver = null, aTouchId = 0) { - var targetWindow = aElement.ownerDocument.defaultView; - - var scale = targetWindow.devicePixelRatio; - var rect = aElement.getBoundingClientRect(); - var x = targetWindow.mozInnerScreenX + ((rect.left + aX) * scale); - var y = targetWindow.mozInnerScreenY + ((rect.top + aY) * scale); - - var utils = SpecialPowers.getDOMWindowUtils(targetWindow); - utils.sendNativeTouchPoint(aTouchId, aType, x, y, 1, 90, aObserver); + var pt = coordinatesRelativeToWindow(aX, aY, aElement); + var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView); + utils.sendNativeTouchPoint(aTouchId, aType, pt.x, pt.y, 1, 90, aObserver); return true; } diff --git a/gfx/layers/apz/test/helper_bug1151663.html b/gfx/layers/apz/test/helper_bug1151663.html new file mode 100644 index 0000000000..15b3dc011a --- /dev/null +++ b/gfx/layers/apz/test/helper_bug1151663.html @@ -0,0 +1,81 @@ + + + + + + Test for Bug 1151663, helper page + + + + + Mozilla Bug 1151663 +
+ +
+
+ +
+ + diff --git a/gfx/layers/apz/test/mochitest.ini b/gfx/layers/apz/test/mochitest.ini new file mode 100644 index 0000000000..2834fe4c9b --- /dev/null +++ b/gfx/layers/apz/test/mochitest.ini @@ -0,0 +1,8 @@ +[DEFAULT] +support-files = apz_test_utils.js +[test_bug982141.html] +skip-if = toolkit != 'gonk' # bug 991198 +support-files = helper_bug982141.html +[test_bug1151663.html] +skip-if = toolkit != 'gonk' # bug 991198 +support-files = helper_bug1151663.html diff --git a/gfx/layers/apz/test/test_bug1151663.html b/gfx/layers/apz/test/test_bug1151663.html new file mode 100644 index 0000000000..df8bb538ba --- /dev/null +++ b/gfx/layers/apz/test/test_bug1151663.html @@ -0,0 +1,35 @@ + + + + + + Test for Bug 1151663 + + + + + + Mozilla Bug 1151663 + + diff --git a/gfx/layers/apz/test/test_bug1151667.html b/gfx/layers/apz/test/test_bug1151667.html index 7437a5220c..4f0dcea934 100644 --- a/gfx/layers/apz/test/test_bug1151667.html +++ b/gfx/layers/apz/test/test_bug1151667.html @@ -44,11 +44,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1151667 function startTest() { var subframe = document.getElementById('subframe'); - var scale = window.devicePixelRatio; - var rect = subframe.getBoundingClientRect(); - var x = (rect.left + 100) * scale; - var y = (rect.top + 150) * scale; - synthesizeNativeWheelAndWaitForScrollEvent(subframe, x, y, 0, -10, continueTest); + synthesizeNativeWheelAndWaitForScrollEvent(subframe, 100, 150, 0, -10, continueTest); } function continueTest() { diff --git a/gfx/layers/apz/test/test_bug982141.html b/gfx/layers/apz/test/test_bug982141.html index 2bcc6a2dd0..139f8486eb 100644 --- a/gfx/layers/apz/test/test_bug982141.html +++ b/gfx/layers/apz/test/test_bug982141.html @@ -17,7 +17,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=982141 // inside an iframe which means we have no control over the root APZC. var w = null; window.onload = function() { - w = window.open("helper_bug982141.html", "_blank"); + SpecialPowers.pushPrefEnv({"set": [["apz.test.logging_enabled", true]]}, function() { + w = window.open("helper_bug982141.html", "_blank"); + }); }; function finishTest() { diff --git a/gfx/layers/apz/test/test_layerization.html b/gfx/layers/apz/test/test_layerization.html index 63d455d0e2..0eeb7c1c65 100644 --- a/gfx/layers/apz/test/test_layerization.html +++ b/gfx/layers/apz/test/test_layerization.html @@ -14,6 +14,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1173580 @@ -42,20 +44,18 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1173580 + +
- -
 
 
diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 42791b243a..6328cef755 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -161,7 +161,7 @@ BasicCompositor::CreateDataTextureSource(TextureFlags aFlags) bool BasicCompositor::SupportsEffect(EffectTypes aEffect) { - return static_cast(aEffect) != EffectTypes::YCBCR; + return aEffect != EffectTypes::YCBCR && aEffect != EffectTypes::COMPONENT_ALPHA; } static void @@ -479,6 +479,7 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, #endif ); if (NS_WARN_IF(!temp)) { + buffer->PopClip(); return; } diff --git a/gfx/layers/basic/X11BasicCompositor.cpp b/gfx/layers/basic/X11BasicCompositor.cpp index e6595a4dfa..b3e98e6260 100644 --- a/gfx/layers/basic/X11BasicCompositor.cpp +++ b/gfx/layers/basic/X11BasicCompositor.cpp @@ -125,5 +125,12 @@ X11BasicCompositor::CreateDataTextureSource(TextureFlags aFlags) return result.forget(); } +void +X11BasicCompositor::EndFrame() +{ + BasicCompositor::EndFrame(); + XFlush(DefaultXDisplay()); +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/basic/X11BasicCompositor.h b/gfx/layers/basic/X11BasicCompositor.h index f897ce04e0..4e3cf037d8 100644 --- a/gfx/layers/basic/X11BasicCompositor.h +++ b/gfx/layers/basic/X11BasicCompositor.h @@ -49,6 +49,8 @@ public: virtual already_AddRefed CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override; + + virtual void EndFrame() override; }; } // namespace layers diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index fbbe7cbdcf..9a58b32829 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -231,9 +231,14 @@ ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget) } // If this is a new paint, increment the paint sequence number. - if (!mIsRepeatTransaction && gfxPrefs::APZTestLoggingEnabled()) { + if (!mIsRepeatTransaction) { + // Increment the paint sequence number even if test logging isn't + // enabled in this process; it may be enabled in the parent process, + // and the parent process expects unique sequence numbers. ++mPaintSequenceNumber; - mApzTestData.StartNewPaint(mPaintSequenceNumber); + if (gfxPrefs::APZTestLoggingEnabled()) { + mApzTestData.StartNewPaint(mPaintSequenceNumber); + } } } @@ -509,7 +514,7 @@ ClientLayerManager::MakeSnapshotIfRequired() gfx::Matrix rotate = ComputeTransformForUnRotation(outerBounds, mTargetRotation); gfx::Matrix oldMatrix = dt->GetTransform(); - dt->SetTransform(oldMatrix * rotate); + dt->SetTransform(rotate * oldMatrix); dt->DrawSurface(surf, dstRect, srcRect, DrawSurfaceOptions(), DrawOptions(1.0f, CompositionOp::OP_OVER)); @@ -566,6 +571,8 @@ ClientLayerManager::StopFrameTimeRecording(uint32_t aStartIndex, void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) { + TimeStamp start = TimeStamp::Now(); + if (mForwarder->GetSyncObject()) { mForwarder->GetSyncObject()->FinalizeFrame(); } @@ -640,6 +647,12 @@ ClientLayerManager::ForwardTransaction(bool aScheduleComposite) // this may result in Layers being deleted, which results in // PLayer::Send__delete__() and DeallocShmem() mKeepAlive.Clear(); + + TabChild* window = mWidget->GetOwningTabChild(); + if (window) { + TimeStamp end = TimeStamp::Now(); + window->DidRequestComposite(start, end); + } } ShadowableLayer* diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp index 548d55c9c0..ddf540aab1 100644 --- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -294,6 +294,10 @@ ImageHost::Composite(LayerComposite* aLayer, return; } + if (!GetCompositor()->SupportsEffect(effect->mType)) { + return; + } + if (mLastFrameID != img->mFrameID || mLastProducerID != img->mProducerID) { if (mImageContainer) { aLayer->GetLayerManager()-> diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 289699a984..761edee2e4 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -272,7 +272,7 @@ public: static bool AsyncPanZoomEnabled(); - void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) { + virtual void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) { aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend)); aObj.DefineProperty("AzureSkiaAccelerated", UseAcceleratedSkiaCanvas()); aObj.DefineProperty("AzureFallbackCanvasBackend", GetBackendName(mFallbackCanvasBackend)); diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp index 36a7445930..dc1bde896d 100644 --- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -19,6 +19,7 @@ #include "gfxUserFontSet.h" #include "gfxUtils.h" #include "gfxFT2FontBase.h" +#include "gfxPrefs.h" #include "mozilla/gfx/2D.h" @@ -338,6 +339,18 @@ gfxPlatformGtk::GetDPIScale() return (dpi > 96) ? round(dpi/96.0) : 1.0; } +bool +gfxPlatformGtk::UseImageOffscreenSurfaces() +{ + // We want to turn on image offscreen surfaces ONLY for GTK3 builds since + // GTK2 theme rendering still requires xlib surfaces. +#if (MOZ_WIDGET_GTK == 3) + return gfxPrefs::UseImageOffscreenSurfaces(); +#else + return false; +#endif +} + gfxImageFormat gfxPlatformGtk::GetOffscreenFormat() { diff --git a/gfx/thebes/gfxPlatformGtk.h b/gfx/thebes/gfxPlatformGtk.h index 0987efbe51..548d7b704d 100644 --- a/gfx/thebes/gfxPlatformGtk.h +++ b/gfx/thebes/gfxPlatformGtk.h @@ -7,7 +7,6 @@ #define GFX_PLATFORM_GTK_H #include "gfxPlatform.h" -#include "gfxPrefs.h" #include "nsAutoRef.h" #include "nsTArray.h" @@ -110,17 +109,16 @@ public: #endif } +#ifdef MOZ_X11 + virtual void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) override { + gfxPlatform::GetAzureBackendInfo(aObj); + aObj.DefineProperty("CairoUseXRender", UseXRender()); + } +#endif + static bool UseFcFontList() { return sUseFcFontList; } - bool UseImageOffscreenSurfaces() { - // We want to turn on image offscreen surfaces ONLY for GTK3 builds - // since GTK2 theme rendering still requires xlib surfaces per se. -#if (MOZ_WIDGET_GTK == 3) - return gfxPrefs::UseImageOffscreenSurfaces(); -#else - return false; -#endif - } + bool UseImageOffscreenSurfaces(); virtual gfxImageFormat GetOffscreenFormat() override; diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index 792913db75..a4d86b4e94 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -180,7 +180,7 @@ private: DECL_GFX_PREF(Live, "apz.pan_repaint_interval", APZPanRepaintInterval, int32_t, 250); DECL_GFX_PREF(Live, "apz.printtree", APZPrintTree, bool, false); DECL_GFX_PREF(Live, "apz.smooth_scroll_repaint_interval", APZSmoothScrollRepaintInterval, int32_t, 75); - DECL_GFX_PREF(Once, "apz.test.logging_enabled", APZTestLoggingEnabled, bool, false); + DECL_GFX_PREF(Live, "apz.test.logging_enabled", APZTestLoggingEnabled, bool, false); DECL_GFX_PREF(Live, "apz.touch_start_tolerance", APZTouchStartTolerance, float, 1.0f/4.5f); DECL_GFX_PREF(Live, "apz.use_paint_duration", APZUsePaintDuration, bool, true); DECL_GFX_PREF(Live, "apz.velocity_bias", APZVelocityBias, float, 1.0f); diff --git a/layout/base/RestyleTracker.cpp b/layout/base/RestyleTracker.cpp index 5215f6252c..9dffeba33e 100644 --- a/layout/base/RestyleTracker.cpp +++ b/layout/base/RestyleTracker.cpp @@ -341,7 +341,7 @@ RestyleTracker::DoProcessRestyles() if (isTimelineRecording) { UniquePtr marker = MakeUnique( - data->mRestyleHint, TRACING_INTERVAL_START); + data->mRestyleHint, MarkerTracingType::START); TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker)); } @@ -357,7 +357,7 @@ RestyleTracker::DoProcessRestyles() if (isTimelineRecording) { UniquePtr marker = MakeUnique( - data->mRestyleHint, TRACING_INTERVAL_END); + data->mRestyleHint, MarkerTracingType::END); TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker)); } } @@ -402,7 +402,7 @@ RestyleTracker::DoProcessRestyles() #endif if (isTimelineRecording) { UniquePtr marker = MakeUnique( - currentRestyle->mRestyleHint, TRACING_INTERVAL_START); + currentRestyle->mRestyleHint, MarkerTracingType::START); TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker)); } @@ -413,7 +413,7 @@ RestyleTracker::DoProcessRestyles() if (isTimelineRecording) { UniquePtr marker = MakeUnique( - currentRestyle->mRestyleHint, TRACING_INTERVAL_END); + currentRestyle->mRestyleHint, MarkerTracingType::END); TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker)); } } diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 21140a4a0c..cfc9a1d097 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -8983,7 +8983,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible) nsDocShell* docShell = static_cast(GetPresContext()->GetDocShell()); if (docShell) { - TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow", TRACING_INTERVAL_START); + TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow", MarkerTracingType::START); } if (mReflowContinueTimer) { @@ -9161,7 +9161,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible) } if (docShell) { - TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow", TRACING_INTERVAL_END); + TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow", MarkerTracingType::END); } return !interrupted; } diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 599ee8ddd5..f2649ab950 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -1866,7 +1866,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime) for (nsDocShell* docShell : profilingDocShells) { // For the sake of the profile timeline's simplicity, this is flagged as // paint even if it includes creating display lists - TimelineConsumers::AddMarkerForDocShell(docShell, "Paint", TRACING_INTERVAL_START); + TimelineConsumers::AddMarkerForDocShell(docShell, "Paint", MarkerTracingType::START); } #ifdef MOZ_DUMP_PAINTING if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { @@ -1883,7 +1883,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime) } #endif for (nsDocShell* docShell : profilingDocShells) { - TimelineConsumers::AddMarkerForDocShell(docShell, "Paint", TRACING_INTERVAL_END); + TimelineConsumers::AddMarkerForDocShell(docShell, "Paint", MarkerTracingType::END); } if (nsContentUtils::XPConnect()) { diff --git a/modules/libjar/InterceptedJARChannel.cpp b/modules/libjar/InterceptedJARChannel.cpp index c4a8a1474c..b5c4579427 100644 --- a/modules/libjar/InterceptedJARChannel.cpp +++ b/modules/libjar/InterceptedJARChannel.cpp @@ -80,6 +80,9 @@ NS_IMETHODIMP InterceptedJARChannel::SynthesizeHeader(const nsACString& aName, const nsACString& aValue) { + if (aName.LowerCaseEqualsLiteral("content-type")) { + mContentType = aValue; + } return NS_OK; } @@ -90,7 +93,7 @@ InterceptedJARChannel::FinishSynthesizedResponse() return NS_ERROR_NOT_AVAILABLE; } - mChannel->OverrideWithSynthesizedResponse(mSynthesizedInput); + mChannel->OverrideWithSynthesizedResponse(mSynthesizedInput, mContentType); mResponseBody = nullptr; mChannel = nullptr; diff --git a/modules/libjar/InterceptedJARChannel.h b/modules/libjar/InterceptedJARChannel.h index cd48dd2348..1aa8bb68cc 100644 --- a/modules/libjar/InterceptedJARChannel.h +++ b/modules/libjar/InterceptedJARChannel.h @@ -41,6 +41,9 @@ class InterceptedJARChannel : public nsIInterceptedChannel // The stream to write the body of the synthesized response. nsCOMPtr mResponseBody; + // The content type of the synthesized response. + nsCString mContentType; + // Wether this intercepted channel was performing a navigation. bool mIsNavigation; diff --git a/modules/libjar/nsIJARChannel.idl b/modules/libjar/nsIJARChannel.idl index 7fb6484ab4..b1ec6c722f 100644 --- a/modules/libjar/nsIJARChannel.idl +++ b/modules/libjar/nsIJARChannel.idl @@ -8,7 +8,7 @@ interface nsIFile; interface nsIZipEntry; -[scriptable, builtinclass, uuid(1adea16e-aa6c-4201-8f71-e9ff0acfb52e)] +[scriptable, builtinclass, uuid(e72b179b-d5df-4d87-b5de-fd73a65c60f6)] interface nsIJARChannel : nsIChannel { /** @@ -34,10 +34,4 @@ interface nsIJARChannel : nsIChannel * This will work even without opening the channel. */ readonly attribute nsIZipEntry zipEntry; - - /** - * Force the channel to skip any chack for possible interception and - * proceed immediately to the network. - */ - void forceNoIntercept(); }; diff --git a/modules/libjar/nsJARChannel.cpp b/modules/libjar/nsJARChannel.cpp index 034c6cb667..ef05b9c245 100644 --- a/modules/libjar/nsJARChannel.cpp +++ b/modules/libjar/nsJARChannel.cpp @@ -203,11 +203,13 @@ nsJARChannel::nsJARChannel() , mIsUnsafe(true) , mOpeningRemote(false) , mSynthesizedStreamLength(0) - , mForceNoIntercept(false) + , mBlockRemoteFiles(false) { if (!gJarProtocolLog) gJarProtocolLog = PR_NewLogModule("nsJarProtocol"); + mBlockRemoteFiles = Preferences::GetBool("network.jar.block-remote-files", false); + // hold an owning reference to the jar handler NS_ADDREF(gJarHandler); } @@ -864,6 +866,12 @@ nsJARChannel::Open2(nsIInputStream** aStream) return Open(aStream); } +bool +nsJARChannel::BypassServiceWorker() const +{ + return mLoadFlags & LOAD_BYPASS_SERVICE_WORKER; +} + bool nsJARChannel::ShouldIntercept() { @@ -878,7 +886,7 @@ nsJARChannel::ShouldIntercept() NS_GET_IID(nsINetworkInterceptController), getter_AddRefs(controller)); bool shouldIntercept = false; - if (controller && !mForceNoIntercept && mLoadInfo) { + if (controller && !BypassServiceWorker() && mLoadInfo) { bool isNavigation = mLoadFlags & LOAD_DOCUMENT_URI; nsContentPolicyType type = mLoadInfo->InternalContentPolicyType(); nsresult rv = controller->ShouldPrepareForIntercept(mAppURI, @@ -901,7 +909,8 @@ void nsJARChannel::ResetInterception() } void -nsJARChannel::OverrideWithSynthesizedResponse(nsIInputStream* aSynthesizedInput) +nsJARChannel::OverrideWithSynthesizedResponse(nsIInputStream* aSynthesizedInput, + const nsACString& aContentType) { // In our current implementation, the FetchEvent handler will copy the // response stream completely into the pipe backing the input stream so we @@ -922,6 +931,8 @@ nsJARChannel::OverrideWithSynthesizedResponse(nsIInputStream* aSynthesizedInput) return; } + SetContentType(aContentType); + FinishAsyncOpen(); rv = mSynthesizedResponsePump->AsyncRead(this, nullptr); @@ -1006,6 +1017,13 @@ nsJARChannel::ContinueAsyncOpen() if (!mJarFile) { // Not a local file... + + // Check preferences to see if all remote jar support should be disabled + if (mBlockRemoteFiles) { + mIsUnsafe = true; + return NS_ERROR_UNSAFE_CONTENT_TYPE; + } + // kick off an async download of the base URI... nsCOMPtr downloader = new MemoryDownloader(this); uint32_t loadFlags = @@ -1105,13 +1123,6 @@ nsJARChannel::GetZipEntry(nsIZipEntry **aZipEntry) return reader->GetEntry(mJarEntry, aZipEntry); } -NS_IMETHODIMP -nsJARChannel::ForceNoIntercept() -{ - mForceNoIntercept = true; - return NS_OK; -} - //----------------------------------------------------------------------------- // mozilla::net::MemoryDownloader::IObserver //----------------------------------------------------------------------------- @@ -1185,6 +1196,10 @@ nsJARChannel::OnDownloadComplete(MemoryDownloader* aDownloader, mContentDisposition = NS_GetContentDispositionFromHeader(mContentDispositionHeader, this); } + // This is a defense-in-depth check for the preferences to see if all remote jar + // support should be disabled. This check may not be needed. + MOZ_RELEASE_ASSERT(!mBlockRemoteFiles); + if (NS_SUCCEEDED(status) && mIsUnsafe && !Preferences::GetBool("network.jar.open-unsafe-types", false)) { status = NS_ERROR_UNSAFE_CONTENT_TYPE; diff --git a/modules/libjar/nsJARChannel.h b/modules/libjar/nsJARChannel.h index 59caad55f9..b8cad253af 100644 --- a/modules/libjar/nsJARChannel.h +++ b/modules/libjar/nsJARChannel.h @@ -80,6 +80,8 @@ private: mozilla::net::MemoryDownloader::Data aData) override; + bool BypassServiceWorker() const; + // Returns true if this channel should intercept the network request and // prepare for a possible synthesized response instead. bool ShouldIntercept(); @@ -92,7 +94,8 @@ private: void ResetInterception(); // Override this channel's pending response with a synthesized one. The // content will be asynchronously read from the pump. - void OverrideWithSynthesizedResponse(nsIInputStream* aSynthesizedInput); + void OverrideWithSynthesizedResponse(nsIInputStream* aSynthesizedInput, + const nsACString& aContentType); nsCString mSpec; @@ -135,9 +138,8 @@ private: nsRefPtr mSynthesizedResponsePump; int64_t mSynthesizedStreamLength; - // True if this channel should skip any interception checks. - bool mForceNoIntercept; - + // True if this channel should not download any remote files. + bool mBlockRemoteFiles; friend class mozilla::net::InterceptedJARChannel; }; diff --git a/modules/libjar/test/mochitest/mochitest.ini b/modules/libjar/test/mochitest/mochitest.ini index 9ed0efee73..b31b07a39a 100644 --- a/modules/libjar/test/mochitest/mochitest.ini +++ b/modules/libjar/test/mochitest/mochitest.ini @@ -8,3 +8,4 @@ support-files = [test_bug403331.html] [test_bug1034143_mapped.html] run-if = os == 'linux' +[test_bug1173171.html] \ No newline at end of file diff --git a/modules/libjar/test/mochitest/test_bug1173171.html b/modules/libjar/test/mochitest/test_bug1173171.html new file mode 100644 index 0000000000..909f080661 --- /dev/null +++ b/modules/libjar/test/mochitest/test_bug1173171.html @@ -0,0 +1,66 @@ + + + + + Test for Bug 1173171 + + + + + + + + +
+
+
+ + + diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 9694bab252..8fc417d51c 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1809,6 +1809,8 @@ pref("dom.server-events.default-reconnection-time", 5000); // in milliseconds // application/java-archive or application/x-jar will not be opened // by the jar channel. pref("network.jar.open-unsafe-types", false); +// If true, loading remote JAR files using the jar: protocol will be prevented. +pref("network.jar.block-remote-files", false); // This preference, if true, causes all UTF-8 domain names to be normalized to // punycode. The intention is to allow UTF-8 domain names as input, but never diff --git a/netwerk/base/BackgroundFileSaver.cpp b/netwerk/base/BackgroundFileSaver.cpp index 3e1e2a45a1..a5eda27862 100644 --- a/netwerk/base/BackgroundFileSaver.cpp +++ b/netwerk/base/BackgroundFileSaver.cpp @@ -21,6 +21,7 @@ #include "nsThreadUtils.h" #include "BackgroundFileSaver.h" +#include "mozilla/Telemetry.h" #ifdef XP_WIN #include @@ -158,6 +159,8 @@ BackgroundFileSaver::Init() rv = NS_NewThread(getter_AddRefs(mWorkerThread)); NS_ENSURE_SUCCESS(rv, rv); + sThreadCount++; + return NS_OK; } @@ -504,16 +507,10 @@ BackgroundFileSaver::ProcessStateChange() NS_ENSURE_SUCCESS(rv, rv); } - // We should not only update the mActualTarget with renameTarget when - // they point to the different files. - // In this way, if mActualTarget and renamedTarget point to the same file - // with different addresses, "CheckCompletion()" will return false forever. + // Now we can update the actual target file name. + mActualTarget = renamedTarget; + mActualTargetKeepPartial = renamedTargetKeepPartial; } - - // Update mActualTarget with renameTarget, - // even if they point to the same file. - mActualTarget = renamedTarget; - mActualTargetKeepPartial = renamedTargetKeepPartial; } // Notify if the target file name actually changed. diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index d6d241cd34..62441ab355 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -82,6 +82,22 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, } } +LoadInfo::LoadInfo(const LoadInfo& rhs) + : mLoadingPrincipal(rhs.mLoadingPrincipal) + , mTriggeringPrincipal(rhs.mTriggeringPrincipal) + , mLoadingContext(rhs.mLoadingContext) + , mSecurityFlags(rhs.mSecurityFlags) + , mInternalContentPolicyType(rhs.mInternalContentPolicyType) + , mUpgradeInsecureRequests(rhs.mUpgradeInsecureRequests) + , mInnerWindowID(rhs.mInnerWindowID) + , mOuterWindowID(rhs.mOuterWindowID) + , mParentOuterWindowID(rhs.mParentOuterWindowID) + , mEnforceSecurity(false) + , mInitialSecurityCheckDone(false) + , mIsFromProcessingFrameAttributes(rhs.mIsFromProcessingFrameAttributes) +{ +} + LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal, nsSecurityFlags aSecurityFlags, @@ -125,6 +141,13 @@ LoadInfo::CloneWithNewSecFlags(nsSecurityFlags aSecurityFlags) const NS_IMPL_ISUPPORTS(LoadInfo, nsILoadInfo) +already_AddRefed +LoadInfo::Clone() const +{ + nsRefPtr copy(new LoadInfo(*this)); + return copy.forget(); +} + NS_IMETHODIMP LoadInfo::GetLoadingPrincipal(nsIPrincipal** aLoadingPrincipal) { diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index ae356bc818..6a76c29ece 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -51,6 +51,8 @@ public: already_AddRefed CloneWithNewSecFlags(nsSecurityFlags aSecurityFlags) const; + already_AddRefed Clone() const; + void SetIsFromProcessingFrameAttributes(); private: @@ -69,6 +71,7 @@ private: bool aEnforceSecurity, bool aInitialSecurityCheckDone, nsTArray>& aRedirectChain); + LoadInfo(const LoadInfo& rhs); friend nsresult mozilla::ipc::LoadInfoArgsToLoadInfo( diff --git a/netwerk/base/moz.build b/netwerk/base/moz.build index d7e38fcae8..61ac28d117 100644 --- a/netwerk/base/moz.build +++ b/netwerk/base/moz.build @@ -38,6 +38,7 @@ XPIDL_SOURCES += [ 'nsICryptoHMAC.idl', 'nsIDashboard.idl', 'nsIDashboardEventNotifier.idl', + 'nsIDeprecationWarner.idl', 'nsIDivertableChannel.idl', 'nsIDownloader.idl', 'nsIEncodedChannel.idl', diff --git a/netwerk/base/nsIDeprecationWarner.idl b/netwerk/base/nsIDeprecationWarner.idl new file mode 100644 index 0000000000..72303b8156 --- /dev/null +++ b/netwerk/base/nsIDeprecationWarner.idl @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* 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 "nsISupports.idl" + +/** + * Interface for warning about deprecated operations. Consumers should + * attach this interface to the channel's notification callbacks/loadgroup. + */ +[uuid(665c5124-2c52-41ba-ae72-2393f8e76c25)] +interface nsIDeprecationWarner : nsISupports +{ + /** + * Issue a deprecation warning. + * + * @param aWarning a warning code as declared in nsDeprecatedOperationList.h. + * @param aAsError optional boolean flag indicating whether the warning + * should be treated as an error. + */ + void issueWarning(in uint32_t aWarning, [optional] in bool aAsError); +}; diff --git a/netwerk/protocol/app/AppProtocolHandler.cpp b/netwerk/protocol/app/AppProtocolHandler.cpp index 48f892b1a0..0be12a947b 100644 --- a/netwerk/protocol/app/AppProtocolHandler.cpp +++ b/netwerk/protocol/app/AppProtocolHandler.cpp @@ -316,11 +316,6 @@ NS_IMETHODIMP DummyChannel::GetContentDispositionHeader(nsACString&) return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP DummyChannel::ForceNoIntercept() -{ - return NS_OK; -} - /** * app:// protocol implementation. */ diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index d96c3247fc..935b526ad7 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -78,7 +78,6 @@ HttpBaseChannel::HttpBaseChannel() , mAllRedirectsSameOrigin(true) , mAllRedirectsPassTimingAllowCheck(true) , mResponseCouldBeSynthesized(false) - , mForceNoIntercept(false) , mAllowStaleCacheContent(false) , mSuspendCount(0) , mInitialRwin(0) @@ -1613,6 +1612,8 @@ HttpBaseChannel::OverrideSecurityInfo(nsISupports* aSecurityInfo) "This can only be called when we don't have a security info object already"); MOZ_RELEASE_ASSERT(aSecurityInfo, "This can only be called with a valid security info object"); + MOZ_ASSERT(!BypassServiceWorker(), + "This can only be called on channels that are not bypassing interception"); MOZ_ASSERT(mResponseCouldBeSynthesized, "This can only be called on channels that can be intercepted"); if (mSecurityInfo) { @@ -2176,14 +2177,6 @@ HttpBaseChannel::GetLastModifiedTime(PRTime* lastModifiedTime) return NS_OK; } -NS_IMETHODIMP -HttpBaseChannel::ForceNoIntercept() -{ - mForceNoIntercept = true; - mResponseCouldBeSynthesized = false; - return NS_OK; -} - NS_IMETHODIMP HttpBaseChannel::GetCorsIncludeCredentials(bool* aInclude) { @@ -2324,13 +2317,19 @@ HttpBaseChannel::IsNavigation() return mForceMainDocumentChannel; } +bool +HttpBaseChannel::BypassServiceWorker() const +{ + return mLoadFlags & LOAD_BYPASS_SERVICE_WORKER; +} + bool HttpBaseChannel::ShouldIntercept() { nsCOMPtr controller; GetCallback(controller); bool shouldIntercept = false; - if (controller && !mForceNoIntercept && mLoadInfo) { + if (controller && !BypassServiceWorker() && mLoadInfo) { nsContentPolicyType type = mLoadInfo->InternalContentPolicyType(); nsresult rv = controller->ShouldPrepareForIntercept(mURI, IsNavigation(), @@ -2612,11 +2611,6 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI, httpInternal->SetCacheKeysRedirectChain(mRedirectedCachekeys.forget()); } - // Preserve any skip-serviceworker-flag. - if (mForceNoIntercept) { - httpInternal->ForceNoIntercept(); - } - // Preserve CORS mode flag. httpInternal->SetCorsMode(mCorsMode); diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index 6adda387fc..66ea86c554 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -196,7 +196,6 @@ public: NS_IMETHOD SetNetworkInterfaceId(const nsACString& aNetworkInterfaceId) override; NS_IMETHOD ForcePending(bool aForcePending) override; NS_IMETHOD GetLastModifiedTime(PRTime* lastModifiedTime) override; - NS_IMETHOD ForceNoIntercept() override; NS_IMETHOD GetCorsIncludeCredentials(bool* aInclude) override; NS_IMETHOD SetCorsIncludeCredentials(bool aInclude) override; NS_IMETHOD GetCorsMode(uint32_t* aCorsMode) override; @@ -316,6 +315,8 @@ protected: // GetPrincipal Returns the channel's URI principal. nsIPrincipal *GetURIPrincipal(); + bool BypassServiceWorker() const; + // Returns true if this channel should intercept the network request and prepare // for a possible synthesized response instead. bool ShouldIntercept(); @@ -395,9 +396,6 @@ protected: // pass the Resource Timing timing-allow-check uint32_t mAllRedirectsPassTimingAllowCheck : 1; - // True if this channel should skip any interception checks - uint32_t mForceNoIntercept : 1; - // If true, we behave as if the LOAD_FROM_CACHE flag has been set. // Used to enforce that flag's behavior but not expose it externally. uint32_t mAllowStaleCacheContent : 1; diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index dd43677ccd..93fba2c920 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -34,6 +34,7 @@ #include "nsPerformance.h" #include "mozIThirdPartyUtil.h" #include "nsContentSecurityManager.h" +#include "nsIDeprecationWarner.h" #ifdef OS_POSIX #include "chrome/common/file_descriptor_set_posix.h" @@ -2257,7 +2258,7 @@ HttpChannelChild::ResetInterception() // The chance to intercept any further requests associated with this channel // (such as redirects) has passed. - ForceNoIntercept(); + mLoadFlags |= LOAD_BYPASS_SERVICE_WORKER; // Continue with the original cross-process request nsresult rv = ContinueAsyncOpen(); @@ -2334,5 +2335,17 @@ HttpChannelChild::ForceIntercepted() return NS_OK; } +bool +HttpChannelChild::RecvIssueDeprecationWarning(const uint32_t& warning, + const bool& asError) +{ + nsCOMPtr warner; + GetCallback(warner); + if (warner) { + warner->IssueWarning(warning, asError); + } + return true; +} + } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/http/HttpChannelChild.h b/netwerk/protocol/http/HttpChannelChild.h index 79406a91c6..541dbec1d9 100644 --- a/netwerk/protocol/http/HttpChannelChild.h +++ b/netwerk/protocol/http/HttpChannelChild.h @@ -148,6 +148,9 @@ protected: bool RecvReportSecurityMessage(const nsString& messageTag, const nsString& messageCategory) override; + bool RecvIssueDeprecationWarning(const uint32_t& warning, + const bool& asError) override; + bool GetAssociatedContentSecurity(nsIAssociatedContentSecurity** res = nullptr); virtual void DoNotifyListenerCleanup() override; diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index 0af899c3f5..59befa62f2 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -153,7 +153,8 @@ NS_IMPL_ISUPPORTS(HttpChannelParent, nsIParentChannel, nsIAuthPromptProvider, nsIParentRedirectingChannel, - nsINetworkInterceptController) + nsINetworkInterceptController, + nsIDeprecationWarner) NS_IMETHODIMP HttpChannelParent::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate, @@ -471,7 +472,10 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI, } } else { - mChannel->ForceNoIntercept(); + nsLoadFlags loadFlags; + mChannel->GetLoadFlags(&loadFlags); + loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER; + mChannel->SetLoadFlags(loadFlags); } nsCOMPtr cacheKey = @@ -1580,5 +1584,12 @@ HttpChannelParent::ReportSecurityMessage(const nsAString& aMessageTag, return NS_OK; } +NS_IMETHODIMP +HttpChannelParent::IssueWarning(uint32_t aWarning, bool aAsError) +{ + unused << SendIssueDeprecationWarning(aWarning, aAsError); + return NS_OK; +} + } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/http/HttpChannelParent.h b/netwerk/protocol/http/HttpChannelParent.h index 3515903e8c..d500c04702 100644 --- a/netwerk/protocol/http/HttpChannelParent.h +++ b/netwerk/protocol/http/HttpChannelParent.h @@ -21,6 +21,7 @@ #include "nsIAuthPromptProvider.h" #include "mozilla/dom/ipc/IdType.h" #include "nsINetworkInterceptController.h" +#include "nsIDeprecationWarner.h" class nsICacheEntry; class nsIAssociatedContentSecurity; @@ -43,6 +44,7 @@ class HttpChannelParent final : public PHttpChannelParent , public ADivertableParentChannel , public nsIAuthPromptProvider , public nsINetworkInterceptController + , public nsIDeprecationWarner , public DisconnectableParent , public HttpChannelSecurityWarningReporter { @@ -58,6 +60,7 @@ public: NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIAUTHPROMPTPROVIDER NS_DECL_NSINETWORKINTERCEPTCONTROLLER + NS_DECL_NSIDEPRECATIONWARNER HttpChannelParent(const dom::PBrowserOrId& iframeEmbedding, nsILoadContext* aLoadContext, diff --git a/netwerk/protocol/http/PHttpChannel.ipdl b/netwerk/protocol/http/PHttpChannel.ipdl index 1456b961ac..04a24579a7 100644 --- a/netwerk/protocol/http/PHttpChannel.ipdl +++ b/netwerk/protocol/http/PHttpChannel.ipdl @@ -154,6 +154,9 @@ child: // Tell child to delete channel (all IPDL deletes must be done from child to // avoid races: see bug 591708). DeleteSelf(); + + // Tell the child to issue a deprecation warning. + IssueDeprecationWarning(uint32_t warning, bool asError); }; diff --git a/netwerk/protocol/http/nsCORSListenerProxy.cpp b/netwerk/protocol/http/nsCORSListenerProxy.cpp index 1d63b6ad2f..9b1a472324 100644 --- a/netwerk/protocol/http/nsCORSListenerProxy.cpp +++ b/netwerk/protocol/http/nsCORSListenerProxy.cpp @@ -41,6 +41,7 @@ #include "nsINetworkInterceptController.h" #include "nsNullPrincipal.h" #include "nsICorsPreflightCallback.h" +#include "mozilla/LoadInfo.h" #include using namespace mozilla; @@ -516,8 +517,10 @@ nsCORSListenerProxy::OnStartRequest(nsIRequest* aRequest, do_QueryInterface(channel); if (httpChannelChild) { rv = httpChannelChild->RemoveCorsPreflightCacheEntry(uri, mRequestingPrincipal); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; + if (NS_FAILED(rv)) { + // Only warn here to ensure we fall through the request Cancel() + // and outer listener OnStartRequest() calls. + NS_WARNING("Failed to remove CORS preflight cache entry!"); } } } @@ -831,7 +834,7 @@ nsCORSListenerProxy::OnRedirectVerifyCallback(nsresult result) NS_ASSERTION(mNewRedirectChannel, "mNewRedirectChannel not set in callback"); if (NS_SUCCEEDED(result)) { - nsresult rv = UpdateChannel(mNewRedirectChannel, DataURIHandling::Disallow); + nsresult rv = UpdateChannel(mNewRedirectChannel, DataURIHandling::Disallow); if (NS_FAILED(rv)) { NS_WARNING("nsCORSListenerProxy::OnRedirectVerifyCallback: " "UpdateChannel() returned failure"); @@ -1308,12 +1311,15 @@ nsCORSListenerProxy::StartCORSPreflight(nsIChannel* aRequestChannel, nsresult rv = NS_GetFinalChannelURI(aRequestChannel, getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr loadInfo = aRequestChannel->GetLoadInfo(); - MOZ_ASSERT(loadInfo, "can not perform CORS preflight without a loadInfo"); - if (!loadInfo) { + nsCOMPtr originalLoadInfo = aRequestChannel->GetLoadInfo(); + MOZ_ASSERT(originalLoadInfo, "can not perform CORS preflight without a loadInfo"); + if (!originalLoadInfo) { return NS_ERROR_FAILURE; } + nsCOMPtr loadInfo = static_cast + (originalLoadInfo.get())->Clone(); + nsSecurityFlags securityMode = loadInfo->GetSecurityMode(); MOZ_ASSERT(securityMode == 0 || @@ -1341,6 +1347,14 @@ nsCORSListenerProxy::StartCORSPreflight(nsIChannel* aRequestChannel, rv = aRequestChannel->GetLoadFlags(&loadFlags); NS_ENSURE_SUCCESS(rv, rv); + // Preflight requests should never be intercepted by service workers. + // NOTE: We ignore CORS checks on synthesized responses (see the CORS + // preflights, then we need to extend the GetResponseSynthesized() check in + // nsCORSListenerProxy::CheckRequestApproved()). If we change our behavior + // here and allow service workers to intercept CORS preflights, then that + // check won't be safe any more. + loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER; + nsCOMPtr preflightChannel; rv = NS_NewChannelInternal(getter_AddRefs(preflightChannel), uri, @@ -1356,17 +1370,6 @@ nsCORSListenerProxy::StartCORSPreflight(nsIChannel* aRequestChannel, rv = preHttp->SetRequestMethod(NS_LITERAL_CSTRING("OPTIONS")); NS_ENSURE_SUCCESS(rv, rv); - // Preflight requests should never be intercepted by service workers. - nsCOMPtr preInternal = do_QueryInterface(preflightChannel); - if (preInternal) { - // NOTE: We ignore CORS checks on synthesized responses (see the CORS - // preflights, then we need to extend the GetResponseSynthesized() check in - // nsCORSListenerProxy::CheckRequestApproved()). If we change our behavior - // here and allow service workers to intercept CORS preflights, then that - // check won't be safe any more. - preInternal->ForceNoIntercept(); - } - // Set up listener which will start the original channel nsCOMPtr preflightListener = new nsCORSPreflightListener(aRequestChannel, aListener, nullptr, aPrincipal, diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index d37dab20c3..525c2eb956 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -86,6 +86,7 @@ #include "ScopedNSSTypes.h" #include "nsNullPrincipal.h" #include "nsIPackagedAppService.h" +#include "nsIDeprecationWarner.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" @@ -2056,10 +2057,12 @@ nsHttpChannel::StartRedirectChannelToURI(nsIURI *upgradedURI, uint32_t flags) // Ensure that internally-redirected channels cannot be intercepted, which would look // like two separate requests to the nsINetworkInterceptController. - nsCOMPtr httpRedirect = do_QueryInterface(mRedirectChannel); - if (httpRedirect) { - httpRedirect->ForceNoIntercept(); - } + nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL; + rv = mRedirectChannel->GetLoadFlags(&loadFlags); + NS_ENSURE_SUCCESS(rv, rv); + loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER; + rv = mRedirectChannel->SetLoadFlags(loadFlags); + NS_ENSURE_SUCCESS(rv, rv); PushRedirectAsyncFunc( &nsHttpChannel::ContinueAsyncRedirectChannelToURI); @@ -2869,6 +2872,10 @@ nsHttpChannel::ContinueProcessFallback(nsresult rv) } NS_ENSURE_SUCCESS(rv, rv); + if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) { + MaybeWarnAboutAppCache(); + } + // close down this channel Cancel(NS_BINDING_REDIRECTED); @@ -3660,6 +3667,10 @@ nsHttpChannel::OnOfflineCacheEntryAvailable(nsICacheEntry *aEntry, mCacheEntry = aEntry; mCacheEntryIsWriteOnly = false; + if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI && !mApplicationCacheForWrite) { + MaybeWarnAboutAppCache(); + } + return NS_OK; } @@ -7025,6 +7036,7 @@ nsHttpChannel::OnPush(const nsACString &url, Http2PushedStream *pushedStream) void nsHttpChannel::SetCouldBeSynthesized() { + MOZ_ASSERT(!BypassServiceWorker()); mResponseCouldBeSynthesized = true; } @@ -7050,5 +7062,23 @@ nsHttpChannel::OnPreflightFailed(nsresult aError) return NS_OK; } +void +nsHttpChannel::MaybeWarnAboutAppCache() +{ + // First, accumulate a telemetry ping about appcache usage. + /*Telemetry::Accumulate(Telemetry::HTTP_OFFLINE_CACHE_DOCUMENT_LOAD, + true);*/ + + // Then, issue a deprecation warning if service worker interception is + // enabled. + if (nsContentUtils::ServiceWorkerInterceptionEnabled()) { + nsCOMPtr warner; + GetCallback(warner); + if (warner) { + warner->IssueWarning(nsIDocument::eAppCache, false); + } + } +} + } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h index 13d7ed7cec..9ce5049131 100644 --- a/netwerk/protocol/http/nsHttpChannel.h +++ b/netwerk/protocol/http/nsHttpChannel.h @@ -398,6 +398,8 @@ private: void SetPushedStream(Http2PushedStream *stream); + void MaybeWarnAboutAppCache(); + private: nsCOMPtr mProxyRequest; diff --git a/netwerk/protocol/http/nsIHttpChannelInternal.idl b/netwerk/protocol/http/nsIHttpChannelInternal.idl index cb6345708d..3bc2817ea8 100644 --- a/netwerk/protocol/http/nsIHttpChannelInternal.idl +++ b/netwerk/protocol/http/nsIHttpChannelInternal.idl @@ -223,12 +223,6 @@ interface nsIHttpChannelInternal : nsISupports readonly attribute PRTime lastModifiedTime; - /** - * Force a channel that has not been AsyncOpen'ed to skip any check for possible - * interception and proceed immediately to the network/cache. - */ - void forceNoIntercept(); - readonly attribute boolean responseSynthesized; /** diff --git a/security/manager/ssl/nsNSSCallbacks.cpp b/security/manager/ssl/nsNSSCallbacks.cpp index e958c9567a..0c8a9f1f35 100644 --- a/security/manager/ssl/nsNSSCallbacks.cpp +++ b/security/manager/ssl/nsNSSCallbacks.cpp @@ -90,7 +90,8 @@ nsHTTPDownloadEvent::Run() if (priorityChannel) priorityChannel->AdjustPriority(nsISupportsPriority::PRIORITY_HIGHEST); - chan->SetLoadFlags(nsIRequest::LOAD_ANONYMOUS); + chan->SetLoadFlags(nsIRequest::LOAD_ANONYMOUS | + nsIChannel::LOAD_BYPASS_SERVICE_WORKER); // Create a loadgroup for this new channel. This way if the channel // is redirected, we'll have a way to cancel the resulting channel. diff --git a/testing/profiles/prefs_general.js b/testing/profiles/prefs_general.js index 65b924de3f..ccd4e66ae2 100644 --- a/testing/profiles/prefs_general.js +++ b/testing/profiles/prefs_general.js @@ -240,9 +240,6 @@ user_pref("identity.fxaccounts.remote.force_auth.uri", "https://%(server)s/fxa-f user_pref("identity.fxaccounts.remote.signin.uri", "https://%(server)s/fxa-signin"); user_pref("identity.fxaccounts.settings.uri", "https://%(server)s/fxa-settings"); -// Enable logging of APZ test data (see bug 961289). -user_pref('apz.test.logging_enabled', true); - // Make sure SSL Error reports don't hit the network user_pref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?succeed"); diff --git a/toolkit/devtools/performance/modules/markers.js b/toolkit/devtools/performance/modules/markers.js index 4b0897c76f..01ded44514 100644 --- a/toolkit/devtools/performance/modules/markers.js +++ b/toolkit/devtools/performance/modules/markers.js @@ -82,6 +82,11 @@ const TIMELINE_BLUEPRINT = { colorName: "graphs-green", label: L10N.getStr("marker.label.composite"), }, + "CompositeForwardTransaction": { + group: 0, + colorName: "graphs-bluegrey", + label: L10N.getStr("marker.label.compositeForwardTransaction"), + }, /* Group 1 - JS */ "DOMEvent": { diff --git a/view/nsView.cpp b/view/nsView.cpp index 4942985f03..71d541ffe4 100644 --- a/view/nsView.cpp +++ b/view/nsView.cpp @@ -1091,9 +1091,9 @@ nsView::DidCompositeWindow(const TimeStamp& aCompositeStart, nsIDocShell* docShell = context->GetDocShell(); TimelineConsumers::AddMarkerForDocShell(docShell, - "Composite", aCompositeStart, TRACING_INTERVAL_START); + "Composite", aCompositeStart, MarkerTracingType::START); TimelineConsumers::AddMarkerForDocShell(docShell, - "Composite", aCompositeEnd, TRACING_INTERVAL_END); + "Composite", aCompositeEnd, MarkerTracingType::END); } }