2986 lines
116 KiB
Diff
Raw Normal View History

diff --git a/accessible/base/NotificationController.h b/accessible/base/NotificationController.h
index 2f0428b53d5e1fc4fd97cbc6c0619edbe425e7bd..8e72e1b3d0f69ab613eb95bc1d4676dcaec5c6a9 100644
--- a/accessible/base/NotificationController.h
+++ b/accessible/base/NotificationController.h
@@ -245,6 +245,8 @@ class NotificationController final : public EventQueue,
}
#endif
+ bool IsUpdatePendingForJugglerAccessibility() { return IsUpdatePending(); }
+
protected:
virtual ~NotificationController();
diff --git a/accessible/interfaces/nsIAccessibleDocument.idl b/accessible/interfaces/nsIAccessibleDocument.idl
index a91df31c96afda66f478a5a38eaa4352039c2a0b..ee777c1746284027fb3aa2f1686f8082af9d89ee 100644
--- a/accessible/interfaces/nsIAccessibleDocument.idl
+++ b/accessible/interfaces/nsIAccessibleDocument.idl
@@ -72,4 +72,9 @@ interface nsIAccessibleDocument : nsISupports
* Return the child document accessible at the given index.
*/
nsIAccessibleDocument getChildDocumentAt(in unsigned long index);
+
+ /**
+ * Return whether it is updating.
+ */
+ readonly attribute boolean isUpdatePendingForJugglerAccessibility;
};
diff --git a/accessible/xpcom/xpcAccessibleDocument.cpp b/accessible/xpcom/xpcAccessibleDocument.cpp
index 1ddd5c8372c2742a8dc4e7a8156c084aaf2442fc..7e3aa30c20d8b2fcae5c12d293ca7772ecd28657 100644
--- a/accessible/xpcom/xpcAccessibleDocument.cpp
+++ b/accessible/xpcom/xpcAccessibleDocument.cpp
@@ -143,6 +143,15 @@ xpcAccessibleDocument::GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor) {
return NS_OK;
}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetIsUpdatePendingForJugglerAccessibility(bool* updating) {
+ NS_ENSURE_ARG_POINTER(updating);
+ *updating = Intl()->Controller()->IsUpdatePendingForJugglerAccessibility();
+ return NS_OK;
+}
+
+
////////////////////////////////////////////////////////////////////////////////
// xpcAccessibleDocument
diff --git a/accessible/xpcom/xpcAccessibleDocument.h b/accessible/xpcom/xpcAccessibleDocument.h
index 416a1c5497c97ed80cc0f37d72545e36f7e36b4c..b81983cf7153378260a21f6af225e3493f8f30dc 100644
--- a/accessible/xpcom/xpcAccessibleDocument.h
+++ b/accessible/xpcom/xpcAccessibleDocument.h
@@ -48,6 +48,8 @@ class xpcAccessibleDocument : public xpcAccessibleHyperText,
nsIAccessibleDocument** aDocument) final;
NS_IMETHOD GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor) final;
+ NS_IMETHOD GetIsUpdatePendingForJugglerAccessibility(bool* aUpdating) final;
+
/**
* Return XPCOM wrapper for the internal accessible.
*/
diff --git a/browser/app/winlauncher/LauncherProcessWin.cpp b/browser/app/winlauncher/LauncherProcessWin.cpp
index 16e8c466e00d7dafe12e5e958c5be5967b06360b..a34658a87ac19797e694fb69dd369bb2476fb7d4 100644
--- a/browser/app/winlauncher/LauncherProcessWin.cpp
+++ b/browser/app/winlauncher/LauncherProcessWin.cpp
@@ -23,6 +23,7 @@
#include "mozilla/WinHeaderOnlyUtils.h"
#include "nsWindowsHelpers.h"
+#include <io.h>
#include <windows.h>
#include <processthreadsapi.h>
@@ -421,8 +422,18 @@ Maybe<int> LauncherMain(int& argc, wchar_t* argv[],
HANDLE stdHandles[] = {::GetStdHandle(STD_INPUT_HANDLE),
::GetStdHandle(STD_OUTPUT_HANDLE),
::GetStdHandle(STD_ERROR_HANDLE)};
-
attrs.AddInheritableHandles(stdHandles);
+ // Playwright pipe installation.
+ bool hasJugglerPipe =
+ mozilla::CheckArg(argc, argv, "juggler-pipe", nullptr,
+ mozilla::CheckArgFlag::None) == mozilla::ARG_FOUND;
browser(firefox): properly initialize debugging pipe on windows (#5514) browser(firefox): properly initialize debugging pipe on windows Firefox on Windows has 2 launch modes: - default: a special "launcher process" is used to start browser as a sub-process - non-default: browser process starts right away Firefox has a logic to detect how successful was the use of the launcher process to do self-recovery when things go wrong. Namely: - when attempting to use launcher process, firefox records a timestamp of the attempt beginning - once the launcher process successfully launches browser sub-process, firefox records another timestamp of the completion On a new launch, firefox checks what timestamps are present. If there's a timestamp that signifies start of launcher process, but no successful timestamp, it decides that last "launcher process" use was not successful and falls back to launching browser right away. When launching 2 firefox processes right away, the first process uses attempts to use launcher process and records the first timestamp. At the same time, the second instance sees the first timestamp and doesn't see the second timestamp, and falls back to launching browser right away. Our debugging pipe code, however, does not support non-launcher-process code path. This patch adds support for remote debugging pipe in case of non-launcher-process startup. Drive-by: - disable crashreporter altogether - remove stray dcheck that breaks firefox debug compilation - disable compilation of firefox update agent - do not use WIN32_DISTRIB flag unless doing full builds since it kills incremental compilation References #4660
2021-02-19 10:32:47 -08:00
+ if (hasJugglerPipe) {
+ intptr_t stdio3 = _get_osfhandle(3);
+ intptr_t stdio4 = _get_osfhandle(4);
+ HANDLE pipeHandles[] = {reinterpret_cast<HANDLE>(stdio3),
+ reinterpret_cast<HANDLE>(stdio4)};
+ attrs.AddInheritableHandles(pipeHandles);
+ }
DWORD creationFlags = CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT;
2019-11-18 18:18:28 -08:00
diff --git a/browser/installer/allowed-dupes.mn b/browser/installer/allowed-dupes.mn
index 6ab29ba31e937e1c5bb1208a9a2508ff0496fd02..7989da51c5368fa80cc66cccdfc018a9b3fb2f38 100644
2019-11-18 18:18:28 -08:00
--- a/browser/installer/allowed-dupes.mn
+++ b/browser/installer/allowed-dupes.mn
@@ -67,6 +67,12 @@ browser/features/webcompat@mozilla.org/shims/empty-shim.txt
removed-files
#endif
2019-11-18 18:18:28 -08:00
+# Juggler/marionette files
+chrome/juggler/content/content/floating-scrollbars.css
+browser/chrome/devtools/skin/floating-scrollbars-responsive-design.css
+chrome/juggler/content/server/stream-utils.js
+chrome/marionette/content/stream-utils.js
+
2019-11-18 18:18:28 -08:00
#ifdef MOZ_EME_WIN32_ARTIFACT
gmp-clearkey/0.1/manifest.json
i686/gmp-clearkey/0.1/manifest.json
diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
index 9229a0bd0e041815331aaf2973afda22c007423d..3ce0e453d4124d110e11877f5bbade776d11cfd4 100644
2019-11-18 18:18:28 -08:00
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -196,6 +196,9 @@
@RESPATH@/chrome/remote.manifest
2019-11-18 18:18:28 -08:00
#endif
+@RESPATH@/chrome/juggler@JAREXT@
+@RESPATH@/chrome/juggler.manifest
+
; [Extensions]
@RESPATH@/components/extensions-toolkit.manifest
@RESPATH@/browser/components/extensions-browser.manifest
diff --git a/devtools/server/socket/websocket-server.js b/devtools/server/socket/websocket-server.js
index a32156978aacd7c8cbe9001250bfa1516dbc360f..ff03ff48b505ef8a9117671bf21e8b0e8214ec1f 100644
--- a/devtools/server/socket/websocket-server.js
+++ b/devtools/server/socket/websocket-server.js
@@ -134,13 +134,12 @@ function writeHttpResponse(output, response) {
* Process the WebSocket handshake headers and return the key to be sent in
* Sec-WebSocket-Accept response header.
*/
-function processRequest({ requestLine, headers }) {
+function processRequest({ requestLine, headers }, expectedPath) {
const [method, path] = requestLine.split(" ");
if (method !== "GET") {
throw new Error("The handshake request must use GET method");
}
-
- if (path !== "/") {
+ if (path !== expectedPath) {
throw new Error("The handshake request has unknown path");
}
@@ -190,13 +189,13 @@ function computeKey(key) {
/**
* Perform the server part of a WebSocket opening handshake on an incoming connection.
*/
-const serverHandshake = async function(input, output) {
+const serverHandshake = async function(input, output, expectedPath) {
// Read the request
const request = await readHttpRequest(input);
try {
// Check and extract info from the request
- const { acceptKey } = processRequest(request);
+ const { acceptKey } = processRequest(request, expectedPath);
// Send response headers
await writeHttpResponse(output, [
@@ -218,8 +217,8 @@ const serverHandshake = async function(input, output) {
* Performs the WebSocket handshake and waits for the WebSocket to open.
* Returns Promise with a WebSocket ready to send and receive messages.
*/
-const accept = async function(transport, input, output) {
- await serverHandshake(input, output);
+const accept = async function(transport, input, output, expectedPath) {
+ await serverHandshake(input, output, expectedPath || "/");
const transportProvider = {
setListener(upgradeListener) {
diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp
index 31a929e3150366d25f5acc295fe81ea0352d4621..217fe517155382ef7fa4d3cb6144be6784b83b55 100644
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -111,6 +111,20 @@ struct ParamTraits<mozilla::dom::PrefersColorSchemeOverride>
mozilla::dom::PrefersColorSchemeOverride::None,
mozilla::dom::PrefersColorSchemeOverride::EndGuard_> {};
+template <>
+struct ParamTraits<mozilla::dom::PrefersReducedMotionOverride>
+ : public ContiguousEnumSerializer<
+ mozilla::dom::PrefersReducedMotionOverride,
+ mozilla::dom::PrefersReducedMotionOverride::None,
+ mozilla::dom::PrefersReducedMotionOverride::EndGuard_> {};
+
+template <>
+struct ParamTraits<mozilla::dom::ForcedColorsOverride>
+ : public ContiguousEnumSerializer<
+ mozilla::dom::ForcedColorsOverride,
+ mozilla::dom::ForcedColorsOverride::None,
+ mozilla::dom::ForcedColorsOverride::EndGuard_> {};
+
template <>
struct ParamTraits<mozilla::dom::ExplicitActiveStatus>
: public ContiguousEnumSerializer<
@@ -2839,6 +2853,40 @@ void BrowsingContext::DidSet(FieldIndex<IDX_PrefersColorSchemeOverride>,
PresContextAffectingFieldChanged();
}
+void BrowsingContext::DidSet(FieldIndex<IDX_PrefersReducedMotionOverride>,
+ dom::PrefersReducedMotionOverride aOldValue) {
+ MOZ_ASSERT(IsTop());
+ if (PrefersReducedMotionOverride() == aOldValue) {
+ return;
+ }
+ PreOrderWalk([&](BrowsingContext* aContext) {
+ if (nsIDocShell* shell = aContext->GetDocShell()) {
+ if (nsPresContext* pc = shell->GetPresContext()) {
+ pc->MediaFeatureValuesChanged(
+ {MediaFeatureChangeReason::SystemMetricsChange},
+ MediaFeatureChangePropagation::JustThisDocument);
+ }
+ }
+ });
+}
+
+void BrowsingContext::DidSet(FieldIndex<IDX_ForcedColorsOverride>,
+ dom::ForcedColorsOverride aOldValue) {
+ MOZ_ASSERT(IsTop());
+ if (ForcedColorsOverride() == aOldValue) {
+ return;
+ }
+ PreOrderWalk([&](BrowsingContext* aContext) {
+ if (nsIDocShell* shell = aContext->GetDocShell()) {
+ if (nsPresContext* pc = shell->GetPresContext()) {
+ pc->MediaFeatureValuesChanged(
+ {MediaFeatureChangeReason::SystemMetricsChange},
+ MediaFeatureChangePropagation::JustThisDocument);
+ }
+ }
+ });
+}
+
void BrowsingContext::DidSet(FieldIndex<IDX_MediumOverride>,
nsString&& aOldValue) {
MOZ_ASSERT(IsTop());
diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h
index 8d32d0f5a37396eb18aa217bcac887f131df9fa2..4971c7ea0c38e2fef4b138dbadd17de1288afe08 100644
--- a/docshell/base/BrowsingContext.h
+++ b/docshell/base/BrowsingContext.h
@@ -190,10 +190,10 @@ struct EmbedderColorSchemes {
FIELD(GVInaudibleAutoplayRequestStatus, GVAutoplayRequestStatus) \
/* ScreenOrientation-related APIs */ \
FIELD(CurrentOrientationAngle, float) \
- FIELD(CurrentOrientationType, mozilla::dom::OrientationType) \
+ FIELD(CurrentOrientationType, dom::OrientationType) \
FIELD(OrientationLock, mozilla::hal::ScreenOrientation) \
FIELD(UserAgentOverride, nsString) \
- FIELD(TouchEventsOverrideInternal, mozilla::dom::TouchEventsOverride) \
+ FIELD(TouchEventsOverrideInternal, dom::TouchEventsOverride) \
FIELD(EmbedderElementType, Maybe<nsString>) \
FIELD(MessageManagerGroup, nsString) \
FIELD(MaxTouchPointsOverride, uint8_t) \
@@ -231,6 +231,10 @@ struct EmbedderColorSchemes {
* <browser> embedder element. */ \
FIELD(EmbedderColorSchemes, EmbedderColorSchemes) \
FIELD(DisplayMode, dom::DisplayMode) \
+ /* playwright addition */ \
+ FIELD(PrefersReducedMotionOverride, dom::PrefersReducedMotionOverride) \
+ /* playwright addition */ \
+ FIELD(ForcedColorsOverride, dom::ForcedColorsOverride) \
/* The number of entries added to the session history because of this \
* browsing context. */ \
FIELD(HistoryEntryCount, uint32_t) \
@@ -922,6 +926,14 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
return GetPrefersColorSchemeOverride();
}
+ dom::PrefersReducedMotionOverride PrefersReducedMotionOverride() const {
+ return GetPrefersReducedMotionOverride();
+ }
+
+ dom::ForcedColorsOverride ForcedColorsOverride() const {
+ return GetForcedColorsOverride();
+ }
+
bool IsInBFCache() const;
bool AllowJavascript() const { return GetAllowJavascript(); }
@@ -1079,6 +1091,23 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
void PresContextAffectingFieldChanged();
+ bool CanSet(FieldIndex<IDX_PrefersReducedMotionOverride>,
+ dom::PrefersReducedMotionOverride, ContentParent*) {
+ return IsTop();
+ }
+
+ void DidSet(FieldIndex<IDX_PrefersReducedMotionOverride>,
+ dom::PrefersReducedMotionOverride aOldValue);
+
+
+ bool CanSet(FieldIndex<IDX_ForcedColorsOverride>,
+ dom::ForcedColorsOverride, ContentParent*) {
+ return IsTop();
+ }
+
+ void DidSet(FieldIndex<IDX_ForcedColorsOverride>,
+ dom::ForcedColorsOverride aOldValue);
+
void DidSet(FieldIndex<IDX_MediumOverride>, nsString&& aOldValue);
bool CanSet(FieldIndex<IDX_SuspendMediaWhenInactive>, bool, ContentParent*) {
2019-11-18 18:18:28 -08:00
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 0a029957c8232018f46dd1a677e131bc91f12ad6..f24d066592c186ec9059732e3ab59938ab7061e0 100644
2019-11-18 18:18:28 -08:00
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -15,6 +15,12 @@
# include <unistd.h> // for getpid()
#endif
+#if JS_HAS_INTL_API && !MOZ_SYSTEM_ICU
+# include "unicode/locid.h"
+#endif /* JS_HAS_INTL_API && !MOZ_SYSTEM_ICU */
+
+#include "js/LocaleSensitive.h"
+
#include "mozilla/ArrayUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/AutoRestore.h"
@@ -65,6 +71,7 @@
#include "mozilla/dom/ContentFrameMessageManager.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/Element.h"
+#include "mozilla/dom/Geolocation.h"
#include "mozilla/dom/HTMLAnchorElement.h"
#include "mozilla/dom/HTMLIFrameElement.h"
#include "mozilla/dom/PerformanceNavigation.h"
@@ -90,6 +97,7 @@
#include "mozilla/dom/JSWindowActorChild.h"
#include "mozilla/dom/DocumentBinding.h"
#include "mozilla/ipc/ProtocolUtils.h"
+#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/net/DocumentChannel.h"
#include "mozilla/net/DocumentChannelChild.h"
#include "mozilla/net/ParentChannelWrapper.h"
@@ -114,6 +122,7 @@
#include "nsIDocShellTreeOwner.h"
#include "mozilla/dom/Document.h"
#include "nsHTMLDocument.h"
+#include "mozilla/dom/Element.h"
#include "nsIDocumentLoaderFactory.h"
#include "nsIDOMWindow.h"
#include "nsIEditingSession.h"
@@ -208,6 +217,7 @@
#include "nsFocusManager.h"
#include "nsGlobalWindow.h"
#include "nsJSEnvironment.h"
+#include "nsJSUtils.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsObjectLoadingContent.h"
@@ -371,6 +381,14 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
mAllowDNSPrefetch(true),
mAllowWindowControl(true),
mCSSErrorReportingEnabled(false),
+ mFileInputInterceptionEnabled(false),
+ mOverrideHasFocus(false),
+ mBypassCSPEnabled(false),
+ mForceActiveState(false),
+ mDisallowBFCache(false),
+ mOnlineOverride(nsIDocShell::ONLINE_OVERRIDE_NONE),
+ mReducedMotionOverride(REDUCED_MOTION_OVERRIDE_NONE),
+ mForcedColorsOverride(FORCED_COLORS_OVERRIDE_NO_OVERRIDE),
mAllowAuth(mItemType == typeContent),
mAllowKeywordFixup(false),
mDisableMetaRefreshWhenInactive(false),
@@ -3268,6 +3286,234 @@ nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) {
return NS_OK;
}
+// =============== Juggler Begin =======================
+
+nsDocShell* nsDocShell::GetRootDocShell() {
+ nsCOMPtr<nsIDocShellTreeItem> rootAsItem;
+ GetInProcessSameTypeRootTreeItem(getter_AddRefs(rootAsItem));
+ nsCOMPtr<nsIDocShell> rootShell = do_QueryInterface(rootAsItem);
+ return nsDocShell::Cast(rootShell);
+}
+
+NS_IMETHODIMP
+nsDocShell::GetBypassCSPEnabled(bool* aEnabled) {
+ MOZ_ASSERT(aEnabled);
+ *aEnabled = mBypassCSPEnabled;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetBypassCSPEnabled(bool aEnabled) {
+ mBypassCSPEnabled = aEnabled;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::GetForceActiveState(bool* aEnabled) {
+ MOZ_ASSERT(aEnabled);
+ *aEnabled = mForceActiveState;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetForceActiveState(bool aEnabled) {
+ mForceActiveState = aEnabled;
+ ActivenessMaybeChanged();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::GetDisallowBFCache(bool* aEnabled) {
+ MOZ_ASSERT(aEnabled);
+ *aEnabled = mDisallowBFCache;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetDisallowBFCache(bool aEnabled) {
+ mDisallowBFCache = aEnabled;
+ return NS_OK;
+}
+
+bool nsDocShell::IsBypassCSPEnabled() {
+ return GetRootDocShell()->mBypassCSPEnabled;
+}
+
+NS_IMETHODIMP
+nsDocShell::GetOverrideHasFocus(bool* aEnabled) {
+ MOZ_ASSERT(aEnabled);
+ *aEnabled = mOverrideHasFocus;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetOverrideHasFocus(bool aEnabled) {
+ mOverrideHasFocus = aEnabled;
+ return NS_OK;
+}
+
+bool nsDocShell::ShouldOverrideHasFocus() const {
+ return mOverrideHasFocus;
+}
+
+NS_IMETHODIMP
+nsDocShell::GetLanguageOverride(nsAString& aLanguageOverride) {
+ aLanguageOverride = GetRootDocShell()->mLanguageOverride;
+ return NS_OK;
+}
+
+
+static void SetIcuLocale(const nsAString& aLanguageOverride) {
+ icu::Locale locale(NS_LossyConvertUTF16toASCII(aLanguageOverride).get());
+ if (icu::Locale::getDefault() == locale)
+ return;
+ UErrorCode error_code = U_ZERO_ERROR;
+ const char* lang = locale.getLanguage();
+ if (lang != nullptr && *lang != '\0') {
+ icu::Locale::setDefault(locale, error_code);
+ } else {
+ fprintf(stderr, "SetIcuLocale Failed to set the ICU default locale to %s\n", NS_LossyConvertUTF16toASCII(aLanguageOverride).get());
+ }
+
+ AutoJSAPI jsapi;
+ jsapi.Init();
+ JSContext* cx = jsapi.cx();
+ JS_ResetDefaultLocale(JS_GetRuntime(cx));
+
+ ResetDefaultLocaleInAllWorkers();
+}
+
+NS_IMETHODIMP
+nsDocShell::SetLanguageOverride(const nsAString& aLanguageOverride) {
+ mLanguageOverride = aLanguageOverride;
+ SetIcuLocale(aLanguageOverride);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::OverrideTimezone(const nsAString& aTimezoneOverride,
+ bool* aSuccess) {
+ NS_ENSURE_ARG(aSuccess);
+ NS_LossyConvertUTF16toASCII timeZoneId(aTimezoneOverride);
+ *aSuccess = nsJSUtils::SetTimeZoneOverride(timeZoneId.get());
+
+ // Set TZ which affects localtime_s().
+ auto setTimeZoneEnv = [](const char* value) {
+#if defined(_WIN32)
+ return _putenv_s("TZ", value) == 0;
+#else
+ return setenv("TZ", value, true) == 0;
+#endif /* _WIN32 */
+ };
+ if (*aSuccess) {
+ *aSuccess = setTimeZoneEnv(timeZoneId.get());
+ if (!*aSuccess) {
+ fprintf(stderr, "Failed to set 'TZ' to '%s'\n", timeZoneId.get());
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::GetFileInputInterceptionEnabled(bool* aEnabled) {
+ MOZ_ASSERT(aEnabled);
+ *aEnabled = GetRootDocShell()->mFileInputInterceptionEnabled;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetFileInputInterceptionEnabled(bool aEnabled) {
+ mFileInputInterceptionEnabled = aEnabled;
+ return NS_OK;
+}
+
+bool nsDocShell::IsFileInputInterceptionEnabled() {
+ return GetRootDocShell()->mFileInputInterceptionEnabled;
+}
+
+void nsDocShell::FilePickerShown(mozilla::dom::Element* element) {
+ nsCOMPtr<nsIObserverService> observerService =
+ mozilla::services::GetObserverService();
+ observerService->NotifyObservers(
+ ToSupports(element), "juggler-file-picker-shown", nullptr);
+}
+
+RefPtr<nsGeolocationService> nsDocShell::GetGeolocationServiceOverride() {
+ return GetRootDocShell()->mGeolocationServiceOverride;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetGeolocationOverride(nsIDOMGeoPosition* aGeolocationOverride) {
+ if (aGeolocationOverride) {
+ if (!mGeolocationServiceOverride) {
+ mGeolocationServiceOverride = new nsGeolocationService();
+ mGeolocationServiceOverride->Init();
+ }
+ mGeolocationServiceOverride->Update(aGeolocationOverride);
+ } else {
+ mGeolocationServiceOverride = nullptr;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::GetOnlineOverride(OnlineOverride* aOnlineOverride) {
+ *aOnlineOverride = GetRootDocShell()->mOnlineOverride;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetOnlineOverride(OnlineOverride aOnlineOverride) {
+ // We don't have a way to verify this coming from Javascript, so this check is
+ // still needed.
+ if (!(aOnlineOverride == ONLINE_OVERRIDE_NONE ||
+ aOnlineOverride == ONLINE_OVERRIDE_ONLINE ||
+ aOnlineOverride == ONLINE_OVERRIDE_OFFLINE)) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ mOnlineOverride = aOnlineOverride;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::GetReducedMotionOverride(ReducedMotionOverride* aReducedMotionOverride) {
+ *aReducedMotionOverride = GetRootDocShell()->mReducedMotionOverride;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetReducedMotionOverride(ReducedMotionOverride aReducedMotionOverride) {
+ mReducedMotionOverride = aReducedMotionOverride;
+ RefPtr<nsPresContext> presContext = GetPresContext();
+ if (presContext) {
+ presContext->MediaFeatureValuesChanged(
+ {MediaFeatureChangeReason::SystemMetricsChange},
+ MediaFeatureChangePropagation::JustThisDocument);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::GetForcedColorsOverride(ForcedColorsOverride* aForcedColorsOverride) {
+ *aForcedColorsOverride = GetRootDocShell()->mForcedColorsOverride;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetForcedColorsOverride(ForcedColorsOverride aForcedColorsOverride) {
+ mForcedColorsOverride = aForcedColorsOverride;
+ RefPtr<nsPresContext> presContext = GetPresContext();
+ if (presContext) {
+ presContext->MediaFeatureValuesChanged(
+ {MediaFeatureChangeReason::SystemMetricsChange},
+ MediaFeatureChangePropagation::JustThisDocument);
+ }
+ return NS_OK;
+}
+
+// =============== Juggler End =======================
+
NS_IMETHODIMP
nsDocShell::GetIsNavigating(bool* aOut) {
*aOut = mIsNavigating;
@@ -4895,7 +5141,7 @@ nsDocShell::GetVisibility(bool* aVisibility) {
}
void nsDocShell::ActivenessMaybeChanged() {
- const bool isActive = mBrowsingContext->IsActive();
+ const bool isActive = mForceActiveState || mBrowsingContext->IsActive();
if (RefPtr<PresShell> presShell = GetPresShell()) {
presShell->ActivenessMaybeChanged();
}
@@ -6847,6 +7093,10 @@ bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
return false; // no entry to save into
}
+ if (mDisallowBFCache) {
+ return false;
+ }
+
MOZ_ASSERT(!mozilla::SessionHistoryInParent(),
"mOSHE cannot be non-null with SHIP");
nsCOMPtr<nsIContentViewer> viewer = mOSHE->GetContentViewer();
@@ -8634,6 +8884,12 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
true, // aForceNoOpener
getter_AddRefs(newBC));
MOZ_ASSERT(!newBC);
+ if (rv == NS_OK) {
+ nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
+ if (observerService) {
+ observerService->NotifyObservers(GetAsSupports(this), "juggler-window-open-in-new-context", nullptr);
+ }
+ }
return rv;
}
@@ -12793,6 +13049,9 @@ class OnLinkClickEvent : public Runnable {
mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied,
mTriggeringPrincipal);
}
+ nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
+ observerService->NotifyObservers(ToSupports(mContent), "juggler-link-click-sync", nullptr);
+
return NS_OK;
}
@@ -12872,6 +13131,8 @@ nsresult nsDocShell::OnLinkClick(
nsCOMPtr<nsIRunnable> ev =
new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied,
aIsTrusted, aTriggeringPrincipal);
+ nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
+ observerService->NotifyObservers(ToSupports(aContent), "juggler-link-click", nullptr);
return Dispatch(TaskCategory::UI, ev.forget());
}
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
index 293bfeee6e0779d15dd6ef60fc06f9969f70f003..a0481717f5f7b5ceb0301b7311c27b5631c258ee 100644
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -16,6 +16,7 @@
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/dom/BrowsingContext.h"
+#include "mozilla/dom/Element.h"
#include "mozilla/dom/WindowProxyHolder.h"
#include "nsCOMPtr.h"
#include "nsCharsetSource.h"
@@ -77,6 +78,7 @@ class nsCommandManager;
class nsDocShellEditorData;
class nsDOMNavigationTiming;
class nsDSURIContentListener;
+class nsGeolocationService;
class nsGlobalWindowOuter;
class FramingChecker;
@@ -409,6 +411,15 @@ class nsDocShell final : public nsDocLoader,
void SetWillChangeProcess() { mWillChangeProcess = true; }
bool WillChangeProcess() { return mWillChangeProcess; }
+ bool IsFileInputInterceptionEnabled();
+ void FilePickerShown(mozilla::dom::Element* element);
+
+ bool ShouldOverrideHasFocus() const;
+
+ bool IsBypassCSPEnabled();
+
+ RefPtr<nsGeolocationService> GetGeolocationServiceOverride();
+
// Create a content viewer within this nsDocShell for the given
// `WindowGlobalChild` actor.
nsresult CreateContentViewerForActor(
@@ -1028,6 +1039,8 @@ class nsDocShell final : public nsDocLoader,
bool CSSErrorReportingEnabled() const { return mCSSErrorReportingEnabled; }
+ nsDocShell* GetRootDocShell();
+
// Handles retrieval of subframe session history for nsDocShell::LoadURI. If a
// load is requested in a subframe of the current DocShell, the subframe
// loadType may need to reflect the loadType of the parent document, or in
@@ -1313,6 +1326,17 @@ class nsDocShell final : public nsDocLoader,
bool mAllowDNSPrefetch : 1;
bool mAllowWindowControl : 1;
bool mCSSErrorReportingEnabled : 1;
+ bool mFileInputInterceptionEnabled: 1;
+ bool mOverrideHasFocus : 1;
+ bool mBypassCSPEnabled : 1;
+ bool mForceActiveState : 1;
+ bool mDisallowBFCache : 1;
+ nsString mLanguageOverride;
+ RefPtr<nsGeolocationService> mGeolocationServiceOverride;
+ OnlineOverride mOnlineOverride;
+ ReducedMotionOverride mReducedMotionOverride;
+ ForcedColorsOverride mForcedColorsOverride;
+
bool mAllowAuth : 1;
bool mAllowKeywordFixup : 1;
bool mDisableMetaRefreshWhenInactive : 1;
diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl
index 6b85ddd842a6d2e29f86047017b78b2007b99867..f530ab61ac26cb7c94c8ccd07d11aa90c5148212 100644
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -44,6 +44,7 @@ interface nsIURI;
interface nsIChannel;
interface nsIContentViewer;
interface nsIContentSecurityPolicy;
+interface nsIDOMGeoPosition;
interface nsIEditor;
interface nsIEditingSession;
interface nsIInputStream;
@@ -803,6 +804,43 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
void synchronizeLayoutHistoryState();
+ attribute boolean fileInputInterceptionEnabled;
+
+ attribute boolean overrideHasFocus;
+
+ attribute boolean bypassCSPEnabled;
+
+ attribute boolean forceActiveState;
+
+ attribute boolean disallowBFCache;
+
+ attribute AString languageOverride;
+
+ boolean overrideTimezone(in AString timezoneId);
+
+ cenum OnlineOverride: 8 {
+ ONLINE_OVERRIDE_NONE = 0,
+ ONLINE_OVERRIDE_ONLINE = 1,
+ ONLINE_OVERRIDE_OFFLINE = 2,
+ };
+ [infallible] attribute nsIDocShell_OnlineOverride onlineOverride;
+
+ cenum ReducedMotionOverride : 8 {
+ REDUCED_MOTION_OVERRIDE_REDUCE,
+ REDUCED_MOTION_OVERRIDE_NO_PREFERENCE,
+ REDUCED_MOTION_OVERRIDE_NONE, /* This clears the override. */
+ };
+ [infallible] attribute nsIDocShell_ReducedMotionOverride reducedMotionOverride;
+
+ cenum ForcedColorsOverride : 8 {
+ FORCED_COLORS_OVERRIDE_ACTIVE,
+ FORCED_COLORS_OVERRIDE_NONE,
+ FORCED_COLORS_OVERRIDE_NO_OVERRIDE, /* This clears the override. */
+ };
+ [infallible] attribute nsIDocShell_ForcedColorsOverride forcedColorsOverride;
+
+ void setGeolocationOverride(in nsIDOMGeoPosition position);
+
/**
* This attempts to save any applicable layout history state (like
* scroll position) in the nsISHEntry. This is normally done
diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp
index 5d529f6023db60091054b975ac9738b91326c330..a06117382098e45693e2170398dbf0b7715184cb 100644
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -3619,6 +3619,9 @@ void Document::SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages) {
}
void Document::ApplySettingsFromCSP(bool aSpeculative) {
+ if (mDocumentContainer && mDocumentContainer->IsBypassCSPEnabled())
+ return;
+
nsresult rv = NS_OK;
if (!aSpeculative) {
// 1) apply settings from regular CSP
@@ -3676,6 +3679,11 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
MOZ_ASSERT(!mScriptGlobalObject,
"CSP must be initialized before mScriptGlobalObject is set!");
+ nsCOMPtr<nsIDocShell> shell(mDocumentContainer);
+ if (shell && nsDocShell::Cast(shell)->IsBypassCSPEnabled()) {
+ return NS_OK;
+ }
+
// If this is a data document - no need to set CSP.
if (mLoadedAsData) {
return NS_OK;
@@ -4491,6 +4499,10 @@ bool Document::HasFocus(ErrorResult& rv) const {
return false;
}
+ if (IsActive() && mDocumentContainer->ShouldOverrideHasFocus()) {
+ return true;
+ }
+
if (!fm->IsInActiveWindow(bc)) {
return false;
}
@@ -17838,6 +17850,71 @@ ColorScheme Document::PreferredColorScheme(IgnoreRFP aIgnoreRFP) const {
return LookAndFeel::PreferredColorSchemeForContent();
}
+bool Document::PrefersReducedMotion() const {
+ auto* docShell = static_cast<nsDocShell*>(GetDocShell());
+ nsIDocShell::ReducedMotionOverride reducedMotion;
+ if (docShell && docShell->GetReducedMotionOverride(&reducedMotion) == NS_OK &&
+ reducedMotion != nsIDocShell::REDUCED_MOTION_OVERRIDE_NONE) {
+ switch (reducedMotion) {
+ case nsIDocShell::REDUCED_MOTION_OVERRIDE_REDUCE:
+ return true;
+ case nsIDocShell::REDUCED_MOTION_OVERRIDE_NO_PREFERENCE:
+ return false;
+ case nsIDocShell::REDUCED_MOTION_OVERRIDE_NONE:
+ break;
+ };
+ }
+
+ if (auto* bc = GetBrowsingContext()) {
+ switch (bc->Top()->PrefersReducedMotionOverride()) {
+ case dom::PrefersReducedMotionOverride::Reduce:
+ return true;
+ case dom::PrefersReducedMotionOverride::No_preference:
+ return false;
+ case dom::PrefersReducedMotionOverride::None:
+ case dom::PrefersReducedMotionOverride::EndGuard_:
+ break;
+ }
+ }
+
+ if (nsContentUtils::ShouldResistFingerprinting(this)) {
+ return false;
+ }
+ return LookAndFeel::GetInt(LookAndFeel::IntID::PrefersReducedMotion, 0) == 1;
+}
+
+bool Document::ForcedColors() const {
+ auto* docShell = static_cast<nsDocShell*>(GetDocShell());
+ nsIDocShell::ForcedColorsOverride forcedColors;
+ if (docShell && docShell->GetForcedColorsOverride(&forcedColors) == NS_OK) {
+ switch (forcedColors) {
+ case nsIDocShell::FORCED_COLORS_OVERRIDE_ACTIVE:
+ return true;
+ case nsIDocShell::FORCED_COLORS_OVERRIDE_NONE:
+ return false;
+ case nsIDocShell::FORCED_COLORS_OVERRIDE_NO_OVERRIDE:
+ break;
+ };
+ }
+
+ if (auto* bc = GetBrowsingContext()) {
+ switch (bc->Top()->ForcedColorsOverride()) {
+ case dom::ForcedColorsOverride::Active:
+ return true;
+ case dom::ForcedColorsOverride::None:
+ return false;
+ case dom::ForcedColorsOverride::No_override:
+ case dom::ForcedColorsOverride::EndGuard_:
+ break;
+ }
+ }
+
+ if (mIsBeingUsedAsImage) {
+ return false;
+ }
+ return !PreferenceSheet::PrefsFor(*this).mUseDocumentColors;
+}
+
bool Document::HasRecentlyStartedForegroundLoads() {
if (!sLoadingForegroundTopLevelContentDocument) {
return false;
diff --git a/dom/base/Document.h b/dom/base/Document.h
index b81fb1088ab0025555c24e7353cda836f896b26b..21403d0a219cc478b8de20fda410eb265eb1569a 100644
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -4023,6 +4023,9 @@ class Document : public nsINode,
// color-scheme meta tag.
ColorScheme DefaultColorScheme() const;
+ bool PrefersReducedMotion() const;
+ bool ForcedColors() const;
+
static bool HasRecentlyStartedForegroundLoads();
static bool AutomaticStorageAccessPermissionCanBeGranted(
diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp
index e432d25c7397be64b009e4cb671cb6e322175830..074b1c7241c64412ee58a6239d36c9f74476ae46 100644
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -326,14 +326,18 @@ void Navigator::GetAppName(nsAString& aAppName, CallerType aCallerType) const {
* for more detail.
*/
/* static */
-void Navigator::GetAcceptLanguages(nsTArray<nsString>& aLanguages) {
+void Navigator::GetAcceptLanguages(const nsString* aLanguageOverride, nsTArray<nsString>& aLanguages) {
MOZ_ASSERT(NS_IsMainThread());
aLanguages.Clear();
// E.g. "de-de, en-us,en".
nsAutoString acceptLang;
- Preferences::GetLocalizedString("intl.accept_languages", acceptLang);
+ if (aLanguageOverride && aLanguageOverride->Length())
+ acceptLang = *aLanguageOverride;
+ else
+ Preferences::GetLocalizedString("intl.accept_languages", acceptLang);
+
// Split values on commas.
for (nsDependentSubstring lang :
@@ -385,7 +389,13 @@ void Navigator::GetLanguage(nsAString& aLanguage) {
}
void Navigator::GetLanguages(nsTArray<nsString>& aLanguages) {
- GetAcceptLanguages(aLanguages);
+ if (mWindow && mWindow->GetDocShell()) {
+ nsString languageOverride;
+ mWindow->GetDocShell()->GetLanguageOverride(languageOverride);
+ GetAcceptLanguages(&languageOverride, aLanguages);
+ } else {
+ GetAcceptLanguages(nullptr, aLanguages);
+ }
// The returned value is cached by the binding code. The window listens to the
// accept languages change and will clear the cache when needed. It has to
@@ -564,7 +574,13 @@ bool Navigator::CookieEnabled() {
return granted;
}
-bool Navigator::OnLine() { return !NS_IsOffline(); }
+bool Navigator::OnLine() {
+ nsDocShell* docShell = static_cast<nsDocShell*>(GetDocShell());
+ nsIDocShell::OnlineOverride onlineOverride;
+ if (!docShell || docShell->GetOnlineOverride(&onlineOverride) != NS_OK || onlineOverride == nsIDocShell::ONLINE_OVERRIDE_NONE)
+ return !NS_IsOffline();
+ return onlineOverride == nsIDocShell::ONLINE_OVERRIDE_ONLINE;
+}
void Navigator::GetBuildID(nsAString& aBuildID, CallerType aCallerType,
ErrorResult& aRv) const {
@@ -2257,7 +2273,8 @@ bool Navigator::Webdriver() {
}
#endif
- return false;
+ // Playwright is automating the browser, so we should pretend to be a webdriver
+ return true;
}
} // namespace mozilla::dom
diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h
index 19b9c31fa2464fc3e865e7a7d69ff91140153510..14b617eefc5c23fcca20c407cb71b5618321f6da 100644
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -219,7 +219,7 @@ class Navigator final : public nsISupports, public nsWrapperCache {
StorageManager* Storage();
- static void GetAcceptLanguages(nsTArray<nsString>& aLanguages);
+ static void GetAcceptLanguages(const nsString* aLanguageOverride, nsTArray<nsString>& aLanguages);
dom::MediaCapabilities* MediaCapabilities();
dom::MediaSession* MediaSession();
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index 5a11c595acf75c2de3a50e33572e61f60379dbe9..4b0818df3622ee285f13d7d47bbbe681b5bfb8a3 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -8357,7 +8357,8 @@ nsresult nsContentUtils::SendMouseEvent(
bool aIgnoreRootScrollFrame, float aPressure,
unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow,
PreventDefaultResult* aPreventDefault, bool aIsDOMEventSynthesized,
- bool aIsWidgetEventSynthesized) {
+ bool aIsWidgetEventSynthesized,
+ bool convertToPointer) {
nsPoint offset;
nsCOMPtr<nsIWidget> widget = GetWidget(aPresShell, &offset);
if (!widget) return NS_ERROR_FAILURE;
@@ -8365,6 +8366,7 @@ nsresult nsContentUtils::SendMouseEvent(
EventMessage msg;
Maybe<WidgetMouseEvent::ExitFrom> exitFrom;
bool contextMenuKey = false;
+ bool isDragEvent = false;
if (aType.EqualsLiteral("mousedown")) {
msg = eMouseDown;
} else if (aType.EqualsLiteral("mouseup")) {
@@ -8389,6 +8391,12 @@ nsresult nsContentUtils::SendMouseEvent(
msg = eMouseHitTest;
} else if (aType.EqualsLiteral("MozMouseExploreByTouch")) {
msg = eMouseExploreByTouch;
+ } else if (aType.EqualsLiteral("dragover")) {
+ msg = eDragOver;
+ isDragEvent = true;
+ } else if (aType.EqualsLiteral("drop")) {
+ msg = eDrop;
+ isDragEvent = true;
} else {
return NS_ERROR_FAILURE;
}
@@ -8397,12 +8405,21 @@ nsresult nsContentUtils::SendMouseEvent(
aInputSourceArg = MouseEvent_Binding::MOZ_SOURCE_MOUSE;
}
- WidgetMouseEvent event(true, msg, widget,
+ std::unique_ptr<WidgetMouseEvent> eventOwner;
+ if (isDragEvent) {
+ eventOwner.reset(new WidgetDragEvent(true, msg, widget));
+ eventOwner->mReason = aIsWidgetEventSynthesized
+ ? WidgetMouseEvent::eSynthesized
+ : WidgetMouseEvent::eReal;
+ } else {
+ eventOwner.reset(new WidgetMouseEvent(true, msg, widget,
aIsWidgetEventSynthesized
? WidgetMouseEvent::eSynthesized
: WidgetMouseEvent::eReal,
contextMenuKey ? WidgetMouseEvent::eContextMenuKey
- : WidgetMouseEvent::eNormal);
+ : WidgetMouseEvent::eNormal));
+ }
+ WidgetMouseEvent& event = *eventOwner.get();
event.pointerId = aIdentifier;
event.mModifiers = GetWidgetModifiers(aModifiers);
event.mButton = aButton;
@@ -8416,6 +8433,7 @@ nsresult nsContentUtils::SendMouseEvent(
event.mTime = PR_IntervalNow();
event.mFlags.mIsSynthesizedForTests = aIsDOMEventSynthesized;
event.mExitFrom = exitFrom;
+ event.convertToPointer = convertToPointer;
nsPresContext* presContext = aPresShell->GetPresContext();
if (!presContext) return NS_ERROR_FAILURE;
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
index 0f48e5319a23b149f0daf38bf0910090c7bf616c..2263a70fe578800301f719a27d084840bc1d6e93 100644
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2944,7 +2944,8 @@ class nsContentUtils {
int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure,
unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow,
mozilla::PreventDefaultResult* aPreventDefault,
- bool aIsDOMEventSynthesized, bool aIsWidgetEventSynthesized);
+ bool aIsDOMEventSynthesized, bool aIsWidgetEventSynthesized,
+ bool convertToPointer = true);
static void FirePageShowEventForFrameLoaderSwap(
nsIDocShellTreeItem* aItem,
diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp
index 885083ab95bf5cfe8183934dfedc4e36b7eb6225..e51374306f322685f0fc1f1da9996d64281dfb79 100644
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -683,7 +683,7 @@ nsDOMWindowUtils::SendMouseEvent(
int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame,
float aPressure, unsigned short aInputSourceArg,
bool aIsDOMEventSynthesized, bool aIsWidgetEventSynthesized,
- int32_t aButtons, uint32_t aIdentifier, uint8_t aOptionalArgCount,
+ int32_t aButtons, uint32_t aIdentifier, bool aDisablePointerEvent, uint8_t aOptionalArgCount,
bool* aPreventDefault) {
return SendMouseEventCommon(
aType, aX, aY, aButton, aClickCount, aModifiers, aIgnoreRootScrollFrame,
@@ -691,7 +691,7 @@ nsDOMWindowUtils::SendMouseEvent(
aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, false,
aPreventDefault, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true,
aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false,
- aOptionalArgCount >= 6 ? aButtons : MOUSE_BUTTONS_NOT_SPECIFIED);
+ aOptionalArgCount >= 6 ? aButtons : MOUSE_BUTTONS_NOT_SPECIFIED, !aDisablePointerEvent);
}
NS_IMETHODIMP
@@ -718,13 +718,13 @@ nsDOMWindowUtils::SendMouseEventCommon(
int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame,
float aPressure, unsigned short aInputSourceArg, uint32_t aPointerId,
bool aToWindow, bool* aPreventDefault, bool aIsDOMEventSynthesized,
- bool aIsWidgetEventSynthesized, int32_t aButtons) {
+ bool aIsWidgetEventSynthesized, int32_t aButtons, bool aConvertToPointer) {
RefPtr<PresShell> presShell = GetPresShell();
PreventDefaultResult preventDefaultResult;
nsresult rv = nsContentUtils::SendMouseEvent(
presShell, aType, aX, aY, aButton, aButtons, aClickCount, aModifiers,
aIgnoreRootScrollFrame, aPressure, aInputSourceArg, aPointerId, aToWindow,
- &preventDefaultResult, aIsDOMEventSynthesized, aIsWidgetEventSynthesized);
+ &preventDefaultResult, aIsDOMEventSynthesized, aIsWidgetEventSynthesized, aConvertToPointer);
if (aPreventDefault) {
*aPreventDefault = preventDefaultResult != PreventDefaultResult::No;
diff --git a/dom/base/nsDOMWindowUtils.h b/dom/base/nsDOMWindowUtils.h
index 30e0fafa77857c33e9871259a6ac0cebac965df8..3d8810abcfac1c220529b4e6163b0159475723ff 100644
--- a/dom/base/nsDOMWindowUtils.h
+++ b/dom/base/nsDOMWindowUtils.h
@@ -93,7 +93,7 @@ class nsDOMWindowUtils final : public nsIDOMWindowUtils,
int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame,
float aPressure, unsigned short aInputSourceArg, uint32_t aIdentifier,
bool aToWindow, bool* aPreventDefault, bool aIsDOMEventSynthesized,
- bool aIsWidgetEventSynthesized, int32_t aButtons);
+ bool aIsWidgetEventSynthesized, int32_t aButtons, bool aConvertToPointer = true);
MOZ_CAN_RUN_SCRIPT
nsresult SendTouchEventCommon(
diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp
index cf46ac3458eb2d45b8cf2bfd2e06c8597a07d30b..e308ee762ed5936fb92332cf65e53e69e063ebeb 100644
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -1613,6 +1613,10 @@ void nsFocusManager::SetFocusInner(Element* aNewContent, int32_t aFlags,
(GetActiveBrowsingContext() == newRootBrowsingContext);
}
+ // In Playwright, we want to send focus events even if the element
+ // isn't actually in the active window.
+ isElementInActiveWindow = true;
+
// Exit fullscreen if a website focuses another window
if (StaticPrefs::full_screen_api_exit_on_windowRaise() &&
!isElementInActiveWindow && (aFlags & FLAG_RAISE) &&
@@ -2927,7 +2931,9 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow,
}
}
- if (sTestMode) {
+ // In Playwright, we still want to execte the embedder functions
+ // to actually show / focus windows.
+ if (false && sTestMode) {
// In test mode, emulate raising the window. WindowRaised takes
// care of lowering the present active window. This happens in
// a separate runnable to avoid touching multiple windows in
diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp
index d8e2ac7cc54c2ca8adb914b05328c76e909a3041..2b49a20cac7376ea561b2bad1bce1bd216dc960e 100644
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -2485,7 +2485,7 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument,
&nsGlobalWindowInner::FireOnNewGlobalObject));
}
- if (newInnerWindow && !newInnerWindow->mHasNotifiedGlobalCreated && mDoc) {
+ if (newInnerWindow && mDoc) {
// We should probably notify. However if this is the, arguably bad,
// situation when we're creating a temporary non-chrome-about-blank
// document in a chrome docshell, don't notify just yet. Instead wait
@@ -2504,10 +2504,16 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument,
}();
if (!isContentAboutBlankInChromeDocshell) {
- newInnerWindow->mHasNotifiedGlobalCreated = true;
- nsContentUtils::AddScriptRunner(NewRunnableMethod(
- "nsGlobalWindowOuter::DispatchDOMWindowCreated", this,
- &nsGlobalWindowOuter::DispatchDOMWindowCreated));
+ if (!newInnerWindow->mHasNotifiedGlobalCreated) {
+ newInnerWindow->mHasNotifiedGlobalCreated = true;
+ nsContentUtils::AddScriptRunner(NewRunnableMethod(
+ "nsGlobalWindowOuter::DispatchDOMWindowCreated", this,
+ &nsGlobalWindowOuter::DispatchDOMWindowCreated));
+ } else if (!reUseInnerWindow) {
+ nsContentUtils::AddScriptRunner(NewRunnableMethod(
+ "nsGlobalWindowOuter::JugglerDispatchDOMWindowReused", this,
+ &nsGlobalWindowOuter::JugglerDispatchDOMWindowReused));
+ }
}
}
@@ -2628,6 +2634,19 @@ void nsGlobalWindowOuter::DispatchDOMWindowCreated() {
}
}
+void nsGlobalWindowOuter::JugglerDispatchDOMWindowReused() {
+ nsCOMPtr<nsIObserverService> observerService =
+ mozilla::services::GetObserverService();
+ if (observerService && mDoc) {
+ nsIPrincipal* principal = mDoc->NodePrincipal();
+ if (!principal->IsSystemPrincipal()) {
+ observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
+ "juggler-dom-window-reused",
+ nullptr);
+ }
+ }
+}
+
void nsGlobalWindowOuter::ClearStatus() { SetStatusOuter(u""_ns); }
void nsGlobalWindowOuter::SetDocShell(nsDocShell* aDocShell) {
@@ -3765,6 +3784,14 @@ Maybe<CSSIntSize> nsGlobalWindowOuter::GetRDMDeviceSize(
}
}
}
+ if (topInProcessContentDoc) {
+ nsIDocShell* docShell = topInProcessContentDoc->GetDocShell();
+ if (docShell && docShell->GetDeviceSizeIsPageSize()) {
+ nsPresContext* presContext = docShell->GetPresContext();
+ if (presContext)
+ return Some(CSSPixel::FromAppUnitsRounded(presContext->GetVisibleArea().Size()));
+ }
+ }
return Nothing();
}
diff --git a/dom/base/nsGlobalWindowOuter.h b/dom/base/nsGlobalWindowOuter.h
index 96bb20c65ab6211e4fdf04b0d5f15b0764143672..4c54c97fb6789798921cc6e3b4d4ef7318756d00 100644
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -333,6 +333,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
// Outer windows only.
void DispatchDOMWindowCreated();
+ void JugglerDispatchDOMWindowReused();
// Outer windows only.
virtual void EnsureSizeAndPositionUpToDate() override;
diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp
index 7260effcc77431adb800e3577183002369c614d3..4fe3d05882d6a14dbf32dd842d7039ae8da4cae4 100644
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -1331,6 +1331,62 @@ void nsINode::GetBoxQuadsFromWindowOrigin(const BoxQuadOptions& aOptions,
mozilla::GetBoxQuadsFromWindowOrigin(this, aOptions, aResult, aRv);
}
+static nsIFrame* GetFirstFrame(nsINode* aNode) {
+ if (!aNode->IsContent())
+ return nullptr;
+ nsIFrame* frame = aNode->AsContent()->GetPrimaryFrame(FlushType::Frames);
+ if (!frame) {
+ FlattenedChildIterator iter(aNode->AsContent());
+ for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
+ frame = child->GetPrimaryFrame(FlushType::Frames);
+ if (frame) {
+ break;
+ }
+ }
+ }
+ return frame;
+}
+
+void nsINode::ScrollRectIntoViewIfNeeded(int32_t x, int32_t y,
+ int32_t w, int32_t h,
+ ErrorResult& aRv) {
+ aRv = NS_ERROR_UNEXPECTED;
+ nsCOMPtr<Document> document = OwnerDoc();
+ if (!document) {
+ return aRv.ThrowNotFoundError("Node is detached from document");
+ }
+ PresShell* presShell = document->GetPresShell();
+ if (!presShell) {
+ return aRv.ThrowNotFoundError("Node is detached from document");
+ }
+ nsIFrame* primaryFrame = GetFirstFrame(this);
+ if (!primaryFrame) {
+ return aRv.ThrowNotFoundError("Node does not have a layout object");
+ }
+ aRv = NS_OK;
+ nsRect rect;
+ if (x == -1 && y == -1 && w == -1 && h == -1) {
+ rect = primaryFrame->GetRectRelativeToSelf();
+ } else {
+ rect = nsRect(nsPresContext::CSSPixelsToAppUnits(x),
+ nsPresContext::CSSPixelsToAppUnits(y),
+ nsPresContext::CSSPixelsToAppUnits(w),
+ nsPresContext::CSSPixelsToAppUnits(h));
+ }
+ presShell->ScrollFrameRectIntoView(
+ primaryFrame, rect,
+ nsMargin(),
+ ScrollAxis(kScrollToCenter, WhenToScroll::Always),
+ ScrollAxis(kScrollToCenter, WhenToScroll::Always),
+ ScrollFlags::ScrollOverflowHidden);
+ // If a _visual_ scroll update is pending, cancel it; otherwise, it will
+ // clobber next scroll (e.g. subsequent window.scrollTo(0, 0) wlll break).
+ if (presShell->GetPendingVisualScrollUpdate()) {
+ presShell->AcknowledgePendingVisualScrollUpdate();
+ presShell->ClearPendingVisualScrollUpdate();
+ }
+}
+
already_AddRefed<DOMQuad> nsINode::ConvertQuadFromNode(
DOMQuad& aQuad, const GeometryNode& aFrom,
const ConvertCoordinateOptions& aOptions, CallerType aCallerType,
diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h
index fccf07b43eb05f709eaf49e63c00ab7ddb6df11b..2c07a0f1cf8e321df047b3ef8bcba88752fb855b 100644
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -2140,6 +2140,10 @@ class nsINode : public mozilla::dom::EventTarget {
nsTArray<RefPtr<DOMQuad>>& aResult,
ErrorResult& aRv);
+ void ScrollRectIntoViewIfNeeded(int32_t x, int32_t y,
+ int32_t w, int32_t h,
+ ErrorResult& aRv);
+
already_AddRefed<DOMQuad> ConvertQuadFromNode(
DOMQuad& aQuad, const TextOrElementOrDocument& aFrom,
const ConvertCoordinateOptions& aOptions, CallerType aCallerType,
diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp
index 1da84501bf3ce25b932ec3693f247cdb1a4fdf21..2305a1730e18ba7293a41772b9b7495b5aa66210 100644
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -169,6 +169,11 @@ bool nsJSUtils::GetScopeChainForElement(
return true;
}
+/* static */
+bool nsJSUtils::SetTimeZoneOverride(const char* timezoneId) {
+ return JS::SetTimeZoneOverride(timezoneId);
+}
+
/* static */
void nsJSUtils::ResetTimeZone() { JS::ResetTimeZone(); }
diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h
index 85a21e459305f556933f4dc0fa7441d8f9ed95a9..d7cb86479ba2ed06542307349d6d86dfd026d55d 100644
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -78,6 +78,7 @@ class nsJSUtils {
JSContext* aCx, mozilla::dom::Element* aElement,
JS::MutableHandleVector<JSObject*> aScopeChain);
+ static bool SetTimeZoneOverride(const char* timezoneId);
static void ResetTimeZone();
static bool DumpEnabled();
diff --git a/dom/chrome-webidl/BrowsingContext.webidl b/dom/chrome-webidl/BrowsingContext.webidl
index 76d0d088dea7520f5fd7753525e98840f30db969..fa8ddfc7fbe0969079892b8f035eece2aeed61eb 100644
--- a/dom/chrome-webidl/BrowsingContext.webidl
+++ b/dom/chrome-webidl/BrowsingContext.webidl
@@ -52,6 +52,24 @@ enum PrefersColorSchemeOverride {
"dark",
};
+/**
+ * CSS prefers-reduced-motion values.
+ */
+enum PrefersReducedMotionOverride {
+ "none",
+ "reduce",
+ "no-preference",
+};
+
+/**
+ * CSS forced-colors values.
+ */
+enum ForcedColorsOverride {
+ "none",
+ "active",
+ "no-override", /* This clears the override. */
+};
+
/**
* Allowed overrides of platform/pref default behaviour for touch events.
*/
@@ -186,6 +204,12 @@ interface BrowsingContext {
// Color-scheme simulation, for DevTools.
[SetterThrows] attribute PrefersColorSchemeOverride prefersColorSchemeOverride;
+ // Reduced-Motion simulation, for DevTools.
+ [SetterThrows] attribute PrefersReducedMotionOverride prefersReducedMotionOverride;
+
+ // Forced-Colors simulation, for DevTools.
+ [SetterThrows] attribute ForcedColorsOverride forcedColorsOverride;
+
/**
* A unique identifier for the browser element that is hosting this
* BrowsingContext tree. Every BrowsingContext in the element's tree will
diff --git a/dom/geolocation/Geolocation.cpp b/dom/geolocation/Geolocation.cpp
index 1d2f65deb8add446993a8a578e1f8bb5b46de090..8dd68391e0e0eb1e6d92898f5263cc984836ee7c 100644
--- a/dom/geolocation/Geolocation.cpp
+++ b/dom/geolocation/Geolocation.cpp
@@ -23,6 +23,7 @@
#include "nsComponentManagerUtils.h"
#include "nsContentPermissionHelper.h"
#include "nsContentUtils.h"
+#include "nsDocShell.h"
#include "nsGlobalWindow.h"
#include "mozilla/dom/Document.h"
#include "nsINamed.h"
@@ -260,10 +261,8 @@ nsGeolocationRequest::Allow(JS::Handle<JS::Value> aChoices) {
return NS_OK;
}
- RefPtr<nsGeolocationService> gs =
- nsGeolocationService::GetGeolocationService();
-
- bool canUseCache = false;
+ nsGeolocationService* gs = mLocator->GetGeolocationService();
+ bool canUseCache = gs != nsGeolocationService::sService.get();
CachedPositionAndAccuracy lastPosition = gs->GetCachedPosition();
if (lastPosition.position) {
EpochTimeStamp cachedPositionTime_ms;
@@ -441,8 +440,7 @@ void nsGeolocationRequest::Shutdown() {
// If there are no other high accuracy requests, the geolocation service will
// notify the provider to switch to the default accuracy.
if (mOptions && mOptions->mEnableHighAccuracy) {
- RefPtr<nsGeolocationService> gs =
- nsGeolocationService::GetGeolocationService();
+ nsGeolocationService* gs = mLocator ? mLocator->GetGeolocationService() : nullptr;
if (gs) {
gs->UpdateAccuracy();
}
@@ -732,8 +730,14 @@ void nsGeolocationService::StopDevice() {
StaticRefPtr<nsGeolocationService> nsGeolocationService::sService;
already_AddRefed<nsGeolocationService>
-nsGeolocationService::GetGeolocationService() {
+nsGeolocationService::GetGeolocationService(nsDocShell* docShell) {
RefPtr<nsGeolocationService> result;
+ if (docShell) {
+ result = docShell->GetGeolocationServiceOverride();
+ if (result)
+ return result.forget();
+ }
+
if (nsGeolocationService::sService) {
result = nsGeolocationService::sService;
@@ -825,7 +829,9 @@ nsresult Geolocation::Init(nsPIDOMWindowInner* aContentDom) {
// If no aContentDom was passed into us, we are being used
// by chrome/c++ and have no mOwner, no mPrincipal, and no need
// to prompt.
- mService = nsGeolocationService::GetGeolocationService();
+ nsCOMPtr<Document> doc = aContentDom ? aContentDom->GetDoc() : nullptr;
+ mService = nsGeolocationService::GetGeolocationService(
+ doc ? static_cast<nsDocShell*>(doc->GetDocShell()) : nullptr);
if (mService) {
mService->AddLocator(this);
}
diff --git a/dom/geolocation/Geolocation.h b/dom/geolocation/Geolocation.h
index 7e1af00d05fbafa2d828e2c7e4dcc5c82d115f5b..e85af9718d064e4d2865bc944e9d4ba1efb9a5d7 100644
--- a/dom/geolocation/Geolocation.h
+++ b/dom/geolocation/Geolocation.h
@@ -31,6 +31,7 @@
#include "nsIGeolocationProvider.h"
#include "mozilla/Attributes.h"
+#include "nsDocShell.h"
class nsGeolocationService;
class nsGeolocationRequest;
@@ -48,13 +49,14 @@ struct CachedPositionAndAccuracy {
bool isHighAccuracy;
};
+
/**
* Singleton that manages the geolocation provider
*/
class nsGeolocationService final : public nsIGeolocationUpdate,
public nsIObserver {
public:
- static already_AddRefed<nsGeolocationService> GetGeolocationService();
+ static already_AddRefed<nsGeolocationService> GetGeolocationService(nsDocShell* docShell = nullptr);
static mozilla::StaticRefPtr<nsGeolocationService> sService;
NS_DECL_THREADSAFE_ISUPPORTS
@@ -179,6 +181,8 @@ class Geolocation final : public nsIGeolocationUpdate, public nsWrapperCache {
// null.
static already_AddRefed<Geolocation> NonWindowSingleton();
+ nsGeolocationService* GetGeolocationService() { return mService; };
+
private:
~Geolocation();
diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
index 6a724b3e39c0a37450780804c8b07003b2a6656e..dbc79440e34f9dc01a16bf579446ca19a80cc59a 100644
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -53,6 +53,7 @@
#include "nsMappedAttributes.h"
#include "nsIFormControl.h"
#include "mozilla/dom/Document.h"
+#include "nsDocShell.h"
#include "nsIFormControlFrame.h"
#include "nsITextControlFrame.h"
#include "nsIFrame.h"
@@ -746,6 +747,12 @@ nsresult HTMLInputElement::InitFilePicker(FilePickerType aType) {
return NS_ERROR_FAILURE;
}
+ nsDocShell* docShell = static_cast<nsDocShell*>(win->GetDocShell());
+ if (docShell && docShell->IsFileInputInterceptionEnabled()) {
+ docShell->FilePickerShown(this);
+ return NS_OK;
+ }
+
if (IsPopupBlocked(doc)) {
return NS_OK;
}
diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl
index faefb552491e75b674e4f27418089ef7fcc1a3c0..a1e79fce86440e617ee2e7ae4a3eb0769aa72cfb 100644
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -372,7 +372,8 @@ interface nsIDOMWindowUtils : nsISupports {
[optional] in boolean aIsDOMEventSynthesized,
[optional] in boolean aIsWidgetEventSynthesized,
[optional] in long aButtons,
- [optional] in unsigned long aIdentifier);
+ [optional] in unsigned long aIdentifier,
+ [optional] in boolean aDisablePointerEvent);
/** Synthesize a touch event. The event types supported are:
* touchstart, touchend, touchmove, and touchcancel
diff --git a/dom/media/systemservices/video_engine/desktop_capture_impl.cc b/dom/media/systemservices/video_engine/desktop_capture_impl.cc
index 3d8f2a67e3ec273bc0e7be610b4e683dc23280d4..728f2fdaf1410b86c0d20df0cfbb29beab4c03bf 100644
--- a/dom/media/systemservices/video_engine/desktop_capture_impl.cc
+++ b/dom/media/systemservices/video_engine/desktop_capture_impl.cc
@@ -124,10 +124,11 @@ int32_t ScreenDeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8,
return 0;
}
-VideoCaptureModule* DesktopCaptureImpl::Create(const int32_t id,
+VideoCaptureModuleEx* DesktopCaptureImpl::Create(const int32_t id,
const char* uniqueId,
- const CaptureDeviceType type) {
- return new rtc::RefCountedObject<DesktopCaptureImpl>(id, uniqueId, type);
+ const CaptureDeviceType type,
+ bool captureCursor) {
+ return new rtc::RefCountedObject<DesktopCaptureImpl>(id, uniqueId, type, captureCursor);
}
int32_t WindowDeviceInfoImpl::Init() {
@@ -365,9 +366,13 @@ int32_t DesktopCaptureImpl::LazyInitDesktopCapturer() {
DesktopCapturer::SourceId sourceId = atoi(_deviceUniqueId.c_str());
pWindowCapturer->SelectSource(sourceId);
- desktop_capturer_cursor_composer_ =
- std::unique_ptr<DesktopAndCursorComposer>(
- new DesktopAndCursorComposer(std::move(pWindowCapturer), options));
+ if (capture_cursor_) {
+ desktop_capturer_cursor_composer_ =
+ std::unique_ptr<DesktopAndCursorComposer>(
+ new DesktopAndCursorComposer(std::move(pWindowCapturer), options));
+ } else {
+ desktop_capturer_cursor_composer_ = std::move(pWindowCapturer);
+ }
} else if (_deviceType == CaptureDeviceType::Browser) {
// XXX We don't capture cursors, so avoid the extra indirection layer. We
// could also pass null for the pMouseCursorMonitor.
@@ -384,13 +389,15 @@ int32_t DesktopCaptureImpl::LazyInitDesktopCapturer() {
}
DesktopCaptureImpl::DesktopCaptureImpl(const int32_t id, const char* uniqueId,
- const CaptureDeviceType type)
+ const CaptureDeviceType type,
+ bool captureCursor)
: _id(id),
_deviceUniqueId(uniqueId),
_deviceType(type),
_requestedCapability(),
_rotateFrame(kVideoRotation_0),
last_capture_time_ms_(rtc::TimeMillis()),
+ capture_cursor_(captureCursor),
time_event_(EventWrapper::Create()),
capturer_thread_(nullptr),
started_(false) {
@@ -428,6 +435,19 @@ void DesktopCaptureImpl::DeRegisterCaptureDataCallback(
}
}
+void DesktopCaptureImpl::RegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) {
+ rtc::CritScope lock(&_apiCs);
+ _rawFrameCallbacks.insert(rawFrameCallback);
+}
+
+void DesktopCaptureImpl::DeRegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) {
+ rtc::CritScope lock(&_apiCs);
+ auto it = _rawFrameCallbacks.find(rawFrameCallback);
+ if (it != _rawFrameCallbacks.end()) {
+ _rawFrameCallbacks.erase(it);
+ }
+}
+
int32_t DesktopCaptureImpl::StopCaptureIfAllClientsClose() {
if (_dataCallBacks.empty()) {
return StopCapture();
@@ -645,6 +665,15 @@ void DesktopCaptureImpl::OnCaptureResult(DesktopCapturer::Result result,
frameInfo.height = frame->size().height();
frameInfo.videoType = VideoType::kARGB;
+ size_t videoFrameStride =
+ frameInfo.width * DesktopFrame::kBytesPerPixel;
+ {
+ rtc::CritScope cs(&_apiCs);
+ for (auto rawFrameCallback : _rawFrameCallbacks) {
+ rawFrameCallback->OnRawFrame(videoFrame, videoFrameStride, frameInfo);
+ }
+ }
+
size_t videoFrameLength =
frameInfo.width * frameInfo.height * DesktopFrame::kBytesPerPixel;
IncomingFrame(videoFrame, videoFrameLength,
diff --git a/dom/media/systemservices/video_engine/desktop_capture_impl.h b/dom/media/systemservices/video_engine/desktop_capture_impl.h
index e8414b154fb615afd888ae06aae1d3046f042e69..fd86601a774befc8b7a03d953a73390870aa380f 100644
--- a/dom/media/systemservices/video_engine/desktop_capture_impl.h
+++ b/dom/media/systemservices/video_engine/desktop_capture_impl.h
@@ -48,6 +48,21 @@ namespace webrtc {
class VideoCaptureEncodeInterface;
+class RawFrameCallback {
+ public:
+ virtual ~RawFrameCallback() {}
+
+ virtual void OnRawFrame(uint8_t* videoFrame, size_t videoFrameLength, const VideoCaptureCapability& frameInfo) = 0;
+};
+
+class VideoCaptureModuleEx : public VideoCaptureModule {
+ public:
+ virtual ~VideoCaptureModuleEx() {}
+
+ virtual void RegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) = 0;
+ virtual void DeRegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) = 0;
+};
+
// simulate deviceInfo interface for video engine, bridge screen/application and
// real screen/application device info
@@ -160,12 +175,13 @@ class BrowserDeviceInfoImpl : public VideoCaptureModule::DeviceInfo {
// As with video, DesktopCaptureImpl is a proxy for screen sharing
// and follows the video pipeline design
class DesktopCaptureImpl : public DesktopCapturer::Callback,
- public VideoCaptureModule {
+ public VideoCaptureModuleEx {
public:
/* Create a screen capture modules object
*/
- static VideoCaptureModule* Create(const int32_t id, const char* uniqueId,
- const CaptureDeviceType type);
+ static VideoCaptureModuleEx* Create(const int32_t id, const char* uniqueId,
+ const CaptureDeviceType type,
+ bool captureCursor = true);
static VideoCaptureModule::DeviceInfo* CreateDeviceInfo(
const int32_t id, const CaptureDeviceType type);
@@ -175,6 +191,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
void DeRegisterCaptureDataCallback(
rtc::VideoSinkInterface<VideoFrame>* dataCallback) override;
int32_t StopCaptureIfAllClientsClose() override;
+ void RegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) override;
+ void DeRegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) override;
int32_t SetCaptureRotation(VideoRotation rotation) override;
bool SetApplyRotation(bool enable) override;
@@ -195,7 +213,7 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
protected:
DesktopCaptureImpl(const int32_t id, const char* uniqueId,
- const CaptureDeviceType type);
+ const CaptureDeviceType type, bool captureCursor);
virtual ~DesktopCaptureImpl();
int32_t DeliverCapturedFrame(webrtc::VideoFrame& captureFrame);
@@ -218,6 +236,7 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
rtc::RecursiveCriticalSection _apiCs;
std::set<rtc::VideoSinkInterface<VideoFrame>*> _dataCallBacks;
+ std::set<RawFrameCallback*> _rawFrameCallbacks;
int64_t _incomingFrameTimesNanos
[kFrameRateCountHistorySize]; // timestamp for local captured frames
@@ -240,6 +259,7 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
void ProcessIter();
private:
+ bool capture_cursor_ = true;
// This is created on the main thread and accessed on both the main thread
// and the capturer thread. It is created prior to the capturer thread
// starting and is destroyed after it is stopped.
diff --git a/dom/script/ScriptSettings.cpp b/dom/script/ScriptSettings.cpp
index 8c8a5810fd56512cf37635da1f43757719f06113..d2bc58fcd3b05f989f948839d574d00d0409873c 100644
--- a/dom/script/ScriptSettings.cpp
+++ b/dom/script/ScriptSettings.cpp
@@ -150,6 +150,30 @@ ScriptSettingsStackEntry::~ScriptSettingsStackEntry() {
MOZ_ASSERT_IF(mGlobalObject, mGlobalObject->HasJSGlobal());
}
+static nsIGlobalObject* UnwrapSandboxGlobal(nsIGlobalObject* global) {
+ if (!global)
+ return global;
+ JSObject* globalObject = global->GetGlobalJSObject();
+ if (!globalObject)
+ return global;
+ JSContext* cx = nsContentUtils::GetCurrentJSContext();
+ if (!cx)
+ return global;
+ JS::Rooted<JSObject*> proto(cx);
+ JS::RootedObject rootedGlobal(cx, globalObject);
+ if (!JS_GetPrototype(cx, rootedGlobal, &proto))
+ return global;
+ if (!proto || !xpc::IsSandboxPrototypeProxy(proto))
+ return global;
+ // If this is a sandbox associated with a DOMWindow via a
+ // sandboxPrototype, use that DOMWindow. This supports GreaseMonkey
+ // and JetPack content scripts.
+ proto = js::CheckedUnwrapDynamic(proto, cx, /* stopAtWindowProxy = */ false);
+ if (!proto)
+ return global;
+ return xpc::WindowGlobalOrNull(proto);
+}
+
// If the entry or incumbent global ends up being something that the subject
// principal doesn't subsume, we don't want to use it. This never happens on
// the web, but can happen with asymmetric privilege relationships (i.e.
@@ -177,7 +201,7 @@ static nsIGlobalObject* ClampToSubject(nsIGlobalObject* aGlobalOrNull) {
NS_ENSURE_TRUE(globalPrin, GetCurrentGlobal());
if (!nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller()
->SubsumesConsideringDomain(globalPrin)) {
- return GetCurrentGlobal();
+ return UnwrapSandboxGlobal(GetCurrentGlobal());
}
return aGlobalOrNull;
diff --git a/dom/security/nsCSPUtils.cpp b/dom/security/nsCSPUtils.cpp
index 3f0ca7fb77fc7722b8cf666b8af20ade826a7bb5..0864882a17e18c12bce73cbc5f259ea7641559b2 100644
--- a/dom/security/nsCSPUtils.cpp
+++ b/dom/security/nsCSPUtils.cpp
@@ -127,6 +127,11 @@ void CSP_ApplyMetaCSPToDoc(mozilla::dom::Document& aDoc,
return;
}
+ if (aDoc.GetDocShell() &&
+ nsDocShell::Cast(aDoc.GetDocShell())->IsBypassCSPEnabled()) {
+ return;
+ }
+
nsAutoString policyStr(
nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
aPolicyStr));
diff --git a/dom/webidl/GeometryUtils.webidl b/dom/webidl/GeometryUtils.webidl
index 2f71b284ee5f7e11f117c447834b48355784448c..2640bd57123c2b03bf4b06a2419cd020ba95f155 100644
--- a/dom/webidl/GeometryUtils.webidl
+++ b/dom/webidl/GeometryUtils.webidl
@@ -16,6 +16,8 @@ dictionary BoxQuadOptions {
GeometryNode relativeTo;
[ChromeOnly]
boolean createFramesForSuppressedWhitespace = true;
+ [ChromeOnly]
+ boolean recurseWhenNoFrame = false;
};
dictionary ConvertCoordinateOptions {
@@ -27,6 +29,9 @@ interface mixin GeometryUtils {
[Throws, Func="nsINode::HasBoxQuadsSupport", NeedsCallerType]
sequence<DOMQuad> getBoxQuads(optional BoxQuadOptions options = {});
+ [ChromeOnly, Throws, Func="nsINode::HasBoxQuadsSupport"]
+ undefined scrollRectIntoViewIfNeeded(long x, long y, long w, long h);
+
/* getBoxQuadsFromWindowOrigin is similar to getBoxQuads, but the
* returned quads are further translated relative to the window
* origin -- which is not the layout origin. Further translation
diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp
index 2f9beef0bde229a2f414f46d3ec2b10eac5c4f1c..2aa8c6b75b7791e29b6f579718a2d6e250dc4236 100644
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -981,7 +981,7 @@ void PrefLanguagesChanged(const char* /* aPrefName */, void* /* aClosure */) {
AssertIsOnMainThread();
nsTArray<nsString> languages;
- Navigator::GetAcceptLanguages(languages);
+ Navigator::GetAcceptLanguages(nullptr, languages);
RuntimeService* runtime = RuntimeService::GetService();
if (runtime) {
@@ -1183,8 +1183,7 @@ bool RuntimeService::RegisterWorker(WorkerPrivate& aWorkerPrivate) {
}
// The navigator overridden properties should have already been read.
-
- Navigator::GetAcceptLanguages(mNavigatorProperties.mLanguages);
+ Navigator::GetAcceptLanguages(nullptr, mNavigatorProperties.mLanguages);
mNavigatorPropertiesLoaded = true;
}
@@ -1782,6 +1781,13 @@ void RuntimeService::PropagateStorageAccessPermissionGranted(
}
}
+void RuntimeService::ResetDefaultLocaleInAllWorkers() {
+ AssertIsOnMainThread();
+ BroadcastAllWorkers([](auto& worker) {
+ worker.ResetDefaultLocale();
+ });
+}
+
template <typename Func>
void RuntimeService::BroadcastAllWorkers(const Func& aFunc) {
AssertIsOnMainThread();
@@ -2197,6 +2203,14 @@ void PropagateStorageAccessPermissionGrantedToWorkers(
}
}
+void ResetDefaultLocaleInAllWorkers() {
+ AssertIsOnMainThread();
+ RuntimeService* runtime = RuntimeService::GetService();
+ if (runtime) {
+ runtime->ResetDefaultLocaleInAllWorkers();
+ }
+}
+
WorkerPrivate* GetWorkerPrivateFromContext(JSContext* aCx) {
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aCx);
diff --git a/dom/workers/RuntimeService.h b/dom/workers/RuntimeService.h
index d1a44a19e865fb76cf2b7bfe5e1fbd9c64ec0465..1a44fee6508ea0ef3f48700b83b1185565778cc8 100644
--- a/dom/workers/RuntimeService.h
+++ b/dom/workers/RuntimeService.h
@@ -110,6 +110,8 @@ class RuntimeService final : public nsIObserver {
void PropagateStorageAccessPermissionGranted(
const nsPIDOMWindowInner& aWindow);
+ void ResetDefaultLocaleInAllWorkers();
+
const NavigatorProperties& GetNavigatorProperties() const {
return mNavigatorProperties;
}
diff --git a/dom/workers/WorkerCommon.h b/dom/workers/WorkerCommon.h
index d10dabb5c5ff8e17851edf2bd2efc08e74584d8e..53c4070c5fde43b27fb8fbfdcf4c23d8af57fba3 100644
--- a/dom/workers/WorkerCommon.h
+++ b/dom/workers/WorkerCommon.h
@@ -44,6 +44,8 @@ void ResumeWorkersForWindow(const nsPIDOMWindowInner& aWindow);
void PropagateStorageAccessPermissionGrantedToWorkers(
const nsPIDOMWindowInner& aWindow);
+void ResetDefaultLocaleInAllWorkers();
+
// All of these are implemented in WorkerScope.cpp
bool IsWorkerGlobal(JSObject* global);
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
index e15afcdebdecb9ceed97cb539a511b34670b19c1..9879d33cbe2a6ac3bc7965c9287f72804d60d8ec 100644
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -700,6 +700,18 @@ class UpdateContextOptionsRunnable final : public WorkerControlRunnable {
}
};
+class ResetDefaultLocaleRunnable final : public WorkerControlRunnable {
+ public:
+ explicit ResetDefaultLocaleRunnable(WorkerPrivate* aWorkerPrivate)
+ : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount) {}
+
+ virtual bool WorkerRun(JSContext* aCx,
+ WorkerPrivate* aWorkerPrivate) override {
+ aWorkerPrivate->ResetDefaultLocaleInternal(aCx);
+ return true;
+ }
+};
+
class UpdateLanguagesRunnable final : public WorkerRunnable {
nsTArray<nsString> mLanguages;
@@ -1952,6 +1964,16 @@ void WorkerPrivate::UpdateContextOptions(
}
}
+void WorkerPrivate::ResetDefaultLocale() {
+ AssertIsOnParentThread();
+
+ RefPtr<ResetDefaultLocaleRunnable> runnable =
+ new ResetDefaultLocaleRunnable(this);
+ if (!runnable->Dispatch()) {
+ NS_WARNING("Failed to reset default locale in worker!");
+ }
+}
+
void WorkerPrivate::UpdateLanguages(const nsTArray<nsString>& aLanguages) {
AssertIsOnParentThread();
@@ -5123,6 +5145,15 @@ void WorkerPrivate::UpdateContextOptionsInternal(
}
}
+void WorkerPrivate::ResetDefaultLocaleInternal(JSContext* aCx) {
+ JS_ResetDefaultLocale(JS_GetRuntime(aCx));
+ auto data = mWorkerThreadAccessible.Access();
+
+ for (uint32_t index = 0; index < data->mChildWorkers.Length(); index++) {
+ data->mChildWorkers[index]->ResetDefaultLocale();
+ }
+}
+
void WorkerPrivate::UpdateLanguagesInternal(
const nsTArray<nsString>& aLanguages) {
WorkerGlobalScope* globalScope = GlobalScope();
diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h
index 41eb3a9cad9a5d49573faef26b4f6e3815064c85..9e58fc7746d4953ee29a76b4af4c488db35fe0df 100644
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -330,6 +330,8 @@ class WorkerPrivate final
void UpdateContextOptionsInternal(JSContext* aCx,
const JS::ContextOptions& aContextOptions);
+ void ResetDefaultLocaleInternal(JSContext* aCx);
+
void UpdateLanguagesInternal(const nsTArray<nsString>& aLanguages);
void UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key,
@@ -956,6 +958,8 @@ class WorkerPrivate final
void UpdateContextOptions(const JS::ContextOptions& aContextOptions);
+ void ResetDefaultLocale();
+
void UpdateLanguages(const nsTArray<nsString>& aLanguages);
void UpdateJSWorkerMemoryParameter(JSGCParamKey key, Maybe<uint32_t> value);
diff --git a/intl/components/src/TimeZone.cpp b/intl/components/src/TimeZone.cpp
index 145dd3f07112c2390325de50f8eae674484adfe6..8cb3787e1b6bb25c6a58f1d910ae7dbc440d9ace 100644
--- a/intl/components/src/TimeZone.cpp
+++ b/intl/components/src/TimeZone.cpp
@@ -16,6 +16,7 @@
namespace mozilla::intl {
+
/* static */
Result<UniquePtr<TimeZone>, ICUError> TimeZone::TryCreate(
Maybe<Span<const char16_t>> aTimeZoneOverride) {
@@ -239,6 +240,13 @@ static ICUResult SetDefaultTimeZone(TimeZoneIdentifierVector& timeZone) {
}
#endif
+bool TimeZone::IsValidTimeZoneId(const char* timeZoneId) {
+ // Validate timezone id.
+ mozilla::UniquePtr<icu::TimeZone> timeZone(icu::TimeZone::createTimeZone(
+ icu::UnicodeString(timeZoneId, -1, US_INV)));
+ return timeZone && *timeZone != icu::TimeZone::getUnknown();
+}
+
Result<bool, ICUError> TimeZone::SetDefaultTimeZone(
Span<const char> aTimeZone) {
#if MOZ_INTL_USE_ICU_CPP_TIMEZONE
diff --git a/intl/components/src/TimeZone.h b/intl/components/src/TimeZone.h
index 180092bd3fc0b70462cc6ba67e72946e4c4c7604..bcaecb9fcd7b630c75289581a887cc6894733168 100644
--- a/intl/components/src/TimeZone.h
+++ b/intl/components/src/TimeZone.h
@@ -154,6 +154,8 @@ class TimeZone final {
return FillBufferWithICUCall(aBuffer, ucal_getHostTimeZone);
}
+ static bool IsValidTimeZoneId(const char* timeZoneId);
+
/**
* Set the default time zone.
*/
diff --git a/js/public/Date.h b/js/public/Date.h
index bb69d58dc96ed7f0b37f73e26abdd0bdfeaaf556..8436d439f72287176a2fe6a1a837d3db73409e67 100644
--- a/js/public/Date.h
+++ b/js/public/Date.h
@@ -53,6 +53,8 @@ namespace JS {
*/
extern JS_PUBLIC_API void ResetTimeZone();
+extern JS_PUBLIC_API bool SetTimeZoneOverride(const char* timezoneId);
+
class ClippedTime;
inline ClippedTime TimeClip(double time);
diff --git a/js/src/debugger/Object.cpp b/js/src/debugger/Object.cpp
index baf9debd7b2153aa37e791001e6b37bc1bd14122..68a4d69a4e16711b00a46428e9a51c53154ec923 100644
--- a/js/src/debugger/Object.cpp
+++ b/js/src/debugger/Object.cpp
@@ -2373,7 +2373,11 @@ Maybe<Completion> DebuggerObject::call(JSContext* cx,
invokeArgs[i].set(args2[i]);
}
+ // Disable CSP for the scope of the call.
+ const JSSecurityCallbacks* securityCallbacks = JS_GetSecurityCallbacks(cx);
+ JS_SetSecurityCallbacks(cx, nullptr);
ok = js::Call(cx, calleev, thisv, invokeArgs, &result);
+ JS_SetSecurityCallbacks(cx, securityCallbacks);
}
}
diff --git a/js/src/vm/DateTime.cpp b/js/src/vm/DateTime.cpp
index a86a6e9f7177c86624f118ebbc2e012766137bd1..5ebd1f106a556471fda5961d1f11f8eac31718cc 100644
--- a/js/src/vm/DateTime.cpp
+++ b/js/src/vm/DateTime.cpp
@@ -178,6 +178,11 @@ void js::DateTimeInfo::internalResetTimeZone(ResetTimeZoneMode mode) {
}
}
+void js::DateTimeInfo::internalSetTimeZoneOverride(std::string timeZone) {
+ timeZoneOverride_ = std::move(timeZone);
+ internalResetTimeZone(ResetTimeZoneMode::ResetEvenIfOffsetUnchanged);
+}
+
void js::DateTimeInfo::updateTimeZone() {
MOZ_ASSERT(timeZoneStatus_ != TimeZoneStatus::Valid);
@@ -502,10 +507,24 @@ void js::ResetTimeZoneInternal(ResetTimeZoneMode mode) {
js::DateTimeInfo::resetTimeZone(mode);
}
+void js::SetTimeZoneOverrideInternal(std::string timeZone) {
+ auto guard = js::DateTimeInfo::instance->lock();
+ guard->internalSetTimeZoneOverride(timeZone);
+}
+
JS_PUBLIC_API void JS::ResetTimeZone() {
js::ResetTimeZoneInternal(js::ResetTimeZoneMode::ResetEvenIfOffsetUnchanged);
}
+JS_PUBLIC_API bool JS::SetTimeZoneOverride(const char* timeZoneId) {
+ if (!mozilla::intl::TimeZone::IsValidTimeZoneId(timeZoneId)) {
+ fprintf(stderr, "Invalid timezone id: %s\n", timeZoneId);
+ return false;
+ }
+ js::SetTimeZoneOverrideInternal(std::string(timeZoneId));
+ return true;
+}
+
#if JS_HAS_INTL_API
# if defined(XP_WIN)
static bool IsOlsonCompatibleWindowsTimeZoneId(std::string_view tz) {
@@ -727,9 +746,17 @@ void js::ResyncICUDefaultTimeZone() {
void js::DateTimeInfo::internalResyncICUDefaultTimeZone() {
#if JS_HAS_INTL_API
+ if (!timeZoneOverride_.empty()) {
+ mozilla::Span<const char> tzid = mozilla::Span(timeZoneOverride_.data(), timeZoneOverride_.length());
+ auto result = mozilla::intl::TimeZone::SetDefaultTimeZone(tzid);
+ if (result.isErr()) {
+ fprintf(stderr, "ERROR: failed to setup default time zone\n");
+ }
+ return;
+ }
+
if (const char* tzenv = std::getenv("TZ")) {
std::string_view tz(tzenv);
-
mozilla::Span<const char> tzid;
# if defined(XP_WIN)
diff --git a/js/src/vm/DateTime.h b/js/src/vm/DateTime.h
index b70e4e0ae25947daed0079334956b8cabd5c52b7..38750b81cf82749d5cc6aaa72aa037bc466468f4 100644
--- a/js/src/vm/DateTime.h
+++ b/js/src/vm/DateTime.h
@@ -62,6 +62,8 @@ enum class ResetTimeZoneMode : bool {
*/
extern void ResetTimeZoneInternal(ResetTimeZoneMode mode);
+extern void SetTimeZoneOverrideInternal(std::string timeZone);
+
/**
* ICU's default time zone, used for various date/time formatting operations
* that include the local time in the representation, is allowed to go stale
@@ -201,6 +203,7 @@ class DateTimeInfo {
// and js::ResyncICUDefaultTimeZone().
friend void js::ResetTimeZoneInternal(ResetTimeZoneMode);
friend void js::ResyncICUDefaultTimeZone();
+ friend void js::SetTimeZoneOverrideInternal(std::string);
static void resetTimeZone(ResetTimeZoneMode mode) {
auto guard = instance->lock();
@@ -292,6 +295,8 @@ class DateTimeInfo {
JS::UniqueChars locale_;
JS::UniqueTwoByteChars standardName_;
JS::UniqueTwoByteChars daylightSavingsName_;
+
+ std::string timeZoneOverride_;
#else
// Restrict the data-time range to the minimum required time_t range as
// specified in POSIX. Most operating systems support 64-bit time_t
@@ -307,6 +312,8 @@ class DateTimeInfo {
void internalResetTimeZone(ResetTimeZoneMode mode);
+ void internalSetTimeZoneOverride(std::string timeZone);
+
void updateTimeZone();
void internalResyncICUDefaultTimeZone();
diff --git a/layout/base/GeometryUtils.cpp b/layout/base/GeometryUtils.cpp
index dac899f7558b26d6848da8b98ed8a93555c8751a..2a07d67fa1c2840b25085566e84dc3b2d9b789cf 100644
--- a/layout/base/GeometryUtils.cpp
+++ b/layout/base/GeometryUtils.cpp
@@ -23,6 +23,7 @@
#include "nsContentUtils.h"
#include "nsCSSFrameConstructor.h"
#include "nsLayoutUtils.h"
+#include "ChildIterator.h"
using namespace mozilla;
using namespace mozilla::dom;
@@ -261,11 +262,27 @@ static bool CheckFramesInSameTopLevelBrowsingContext(nsIFrame* aFrame1,
return false;
}
+static nsIFrame* GetFrameForNode(nsINode* aNode,
+ bool aCreateFramesForSuppressedWhitespace,
+ bool aRecurseWhenNoFrame) {
+ nsIFrame* frame = GetFrameForNode(aNode, aCreateFramesForSuppressedWhitespace);
+ if (!frame && aRecurseWhenNoFrame && aNode->IsContent()) {
+ dom::FlattenedChildIterator iter(aNode->AsContent());
+ for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
+ frame = GetFrameForNode(child, aCreateFramesForSuppressedWhitespace, aRecurseWhenNoFrame);
+ if (frame) {
+ break;
+ }
+ }
+ }
+ return frame;
+}
+
void GetBoxQuads(nsINode* aNode, const dom::BoxQuadOptions& aOptions,
nsTArray<RefPtr<DOMQuad> >& aResult, CallerType aCallerType,
ErrorResult& aRv) {
nsIFrame* frame =
- GetFrameForNode(aNode, aOptions.mCreateFramesForSuppressedWhitespace);
+ GetFrameForNode(aNode, aOptions.mCreateFramesForSuppressedWhitespace, aOptions.mRecurseWhenNoFrame);
if (!frame) {
// No boxes to return
return;
@@ -280,7 +297,7 @@ void GetBoxQuads(nsINode* aNode, const dom::BoxQuadOptions& aOptions,
// when that happens and re-check it.
if (!weakFrame.IsAlive()) {
frame =
- GetFrameForNode(aNode, aOptions.mCreateFramesForSuppressedWhitespace);
+ GetFrameForNode(aNode, aOptions.mCreateFramesForSuppressedWhitespace, aOptions.mRecurseWhenNoFrame);
if (!frame) {
// No boxes to return
return;
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
index 13c0b901b39279c023e99d8b42852c315baf847d..5dd2741fd06d8a16af050d55c5333c4c095bf591 100644
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -10923,7 +10923,9 @@ auto PresShell::ComputeActiveness() const -> Activeness {
if (!browserChild->IsVisible()) {
MOZ_LOG(gLog, LogLevel::Debug,
(" > BrowserChild %p is not visible", browserChild));
- return {false, inActiveTab};
+ bool isActive;
+ root->GetDocShell()->GetForceActiveState(&isActive);
+ return {isActive, inActiveTab};
}
// If the browser is visible but just due to be preserving layers
diff --git a/layout/style/GeckoBindings.h b/layout/style/GeckoBindings.h
index e5762879ea3120dca4864e286ffce6d52d33d40e..b2281efd2529c3155355eb18a6a1b7b417514869 100644
--- a/layout/style/GeckoBindings.h
+++ b/layout/style/GeckoBindings.h
@@ -605,6 +605,7 @@ void Gecko_MediaFeatures_GetDeviceSize(const mozilla::dom::Document*,
float Gecko_MediaFeatures_GetResolution(const mozilla::dom::Document*);
bool Gecko_MediaFeatures_PrefersReducedMotion(const mozilla::dom::Document*);
+bool Gecko_MediaFeatures_ForcedColors(const mozilla::dom::Document*);
mozilla::StylePrefersContrast Gecko_MediaFeatures_PrefersContrast(
const mozilla::dom::Document*);
mozilla::StylePrefersColorScheme Gecko_MediaFeatures_PrefersColorScheme(
diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp
index a9d3f075f3587fc1e55544b010864cd0e4b67107..d9ce4a1a7d9e2cd27e20f0ef36132e6599b0bb66 100644
--- a/layout/style/nsMediaFeatures.cpp
+++ b/layout/style/nsMediaFeatures.cpp
@@ -264,10 +264,11 @@ bool Gecko_MediaFeatures_MatchesPlatform(StylePlatform aPlatform) {
}
bool Gecko_MediaFeatures_PrefersReducedMotion(const Document* aDocument) {
- if (nsContentUtils::ShouldResistFingerprinting(aDocument)) {
- return false;
- }
- return LookAndFeel::GetInt(LookAndFeel::IntID::PrefersReducedMotion, 0) == 1;
+ return aDocument->PrefersReducedMotion();
+}
+
+bool Gecko_MediaFeatures_ForcedColors(const Document* aDocument) {
+ return aDocument->ForcedColors();
}
StylePrefersColorScheme Gecko_MediaFeatures_PrefersColorScheme(
diff --git a/media/libjpeg/jconfig.h b/media/libjpeg/jconfig.h
index f2723e654098ff27542e1eb16a536c11ad0af617..b0b480551ff7d895dfdeb5a9800874858929c8ba 100644
--- a/media/libjpeg/jconfig.h
+++ b/media/libjpeg/jconfig.h
@@ -17,6 +17,7 @@
/* #undef D_ARITH_CODING_SUPPORTED */
/* Support in-memory source/destination managers */
+#define MEM_SRCDST_SUPPORTED 1
/* #undef MEM_SRCDST_SUPPORTED */
/* Use accelerated SIMD routines. */
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index dfe52b1d7477fea400a387ed221557454d746589..fb50c04fe18c1c876f649bedac7b5ae231e98da8 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4241,7 +4241,9 @@ pref("devtools.experiment.f12.shortcut_disabled", false);
// doesn't provide a way to lock the pref
pref("dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled", false);
#else
-pref("dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled", false, locked);
+// Playwright: DO NOT make preference locked so that we can overwrite it
+// later in our playwright.cfg file.
+pref("dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled", false);
#endif
// Whether sites require the open-protocol-handler permission to open a
diff --git a/netwerk/base/nsINetworkInterceptController.idl b/netwerk/base/nsINetworkInterceptController.idl
index fba1a83231165cbda92e9b017c70ec6c1d59d037..e8093ed2a06f728c125a4ad8a096d205ef8d3155 100644
--- a/netwerk/base/nsINetworkInterceptController.idl
+++ b/netwerk/base/nsINetworkInterceptController.idl
@@ -59,6 +59,7 @@ interface nsIInterceptedChannel : nsISupports
* results in the resulting client not being controlled.
*/
void resetInterception(in boolean bypass);
+ void resetInterceptionWithURI(in nsIURI aURI);
/**
* Set the status and reason for the forthcoming synthesized response.
diff --git a/netwerk/protocol/http/InterceptedHttpChannel.cpp b/netwerk/protocol/http/InterceptedHttpChannel.cpp
index 2c02db86d5ac9567d7174ac5e685296d4466d16c..a0a91ab331d0289a53b3d29c11d3df9496ae9f2b 100644
--- a/netwerk/protocol/http/InterceptedHttpChannel.cpp
+++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp
@@ -728,6 +728,14 @@ NS_IMPL_ISUPPORTS(ResetInterceptionHeaderVisitor, nsIHttpHeaderVisitor)
} // anonymous namespace
+NS_IMETHODIMP
+InterceptedHttpChannel::ResetInterceptionWithURI(nsIURI* aURI) {
+ if (aURI) {
+ mURI = aURI;
+ }
+ return ResetInterception(true);
+}
+
NS_IMETHODIMP
InterceptedHttpChannel::ResetInterception(bool aBypass) {
INTERCEPTED_LOG(("InterceptedHttpChannel::ResetInterception [%p] bypass: %s",
diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp
index 55c7dbe1ae90d64e5aa993424cc1c5659833582f..a451248676b9b7cdd773a74948eb3b4d442a2b18 100644
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -1363,6 +1363,10 @@ void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta(
void nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP) {
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+ if (mDocShell && static_cast<nsDocShell*>(mDocShell.get())->IsBypassCSPEnabled()) {
+ return;
+ }
+
nsresult rv = NS_OK;
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp = mDocument->GetPreloadCsp();
if (!preloadCsp) {
diff --git a/security/manager/ssl/nsCertOverrideService.cpp b/security/manager/ssl/nsCertOverrideService.cpp
index 4f2f595fb14c7c7244d5fe9a3da2eadc0c3b3adc..3ca0b4a3b9f4bdf21c1107a1e5ea3f0f58050f51 100644
--- a/security/manager/ssl/nsCertOverrideService.cpp
+++ b/security/manager/ssl/nsCertOverrideService.cpp
@@ -472,7 +472,12 @@ nsCertOverrideService::HasMatchingOverride(
bool disableAllSecurityCheck = false;
{
MutexAutoLock lock(mMutex);
- disableAllSecurityCheck = mDisableAllSecurityCheck;
+ if (aOriginAttributes.mUserContextId) {
+ disableAllSecurityCheck = mUserContextIdsWithDisabledSecurityChecks.has(
+ aOriginAttributes.mUserContextId);
+ } else {
+ disableAllSecurityCheck = mDisableAllSecurityCheck;
+ }
}
if (disableAllSecurityCheck) {
*aIsTemporary = false;
@@ -689,14 +694,24 @@ static bool IsDebugger() {
NS_IMETHODIMP
nsCertOverrideService::
- SetDisableAllSecurityChecksAndLetAttackersInterceptMyData(bool aDisable) {
- if (!(PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR") || IsDebugger())) {
+ SetDisableAllSecurityChecksAndLetAttackersInterceptMyData(
+ bool aDisable, uint32_t aUserContextId) {
+ if (false /* juggler hacks */ && !(PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR") || IsDebugger())) {
return NS_ERROR_NOT_AVAILABLE;
}
{
MutexAutoLock lock(mMutex);
- mDisableAllSecurityCheck = aDisable;
+ if (aUserContextId) {
+ if (aDisable) {
+ mozilla::Unused << mUserContextIdsWithDisabledSecurityChecks.put(aUserContextId);
+ } else {
+ mUserContextIdsWithDisabledSecurityChecks.remove(aUserContextId);
+ }
+ return NS_OK;
+ } else {
+ mDisableAllSecurityCheck = aDisable;
+ }
}
nsCOMPtr<nsINSSComponent> nss(do_GetService(PSM_COMPONENT_CONTRACTID));
diff --git a/security/manager/ssl/nsCertOverrideService.h b/security/manager/ssl/nsCertOverrideService.h
index 42760f8ec675af22bdf27a07954b1d3b600d29ab..aad868ef636dbb743f3268d662db7914a2418588 100644
--- a/security/manager/ssl/nsCertOverrideService.h
+++ b/security/manager/ssl/nsCertOverrideService.h
@@ -119,6 +119,7 @@ class nsCertOverrideService final : public nsICertOverrideService,
mozilla::Mutex mMutex;
bool mDisableAllSecurityCheck MOZ_GUARDED_BY(mMutex);
+ mozilla::HashSet<uint32_t> mUserContextIdsWithDisabledSecurityChecks MOZ_GUARDED_BY(mMutex);
nsCOMPtr<nsIFile> mSettingsFile MOZ_GUARDED_BY(mMutex);
nsTHashtable<nsCertOverrideEntry> mSettingsTable MOZ_GUARDED_BY(mMutex);
diff --git a/security/manager/ssl/nsICertOverrideService.idl b/security/manager/ssl/nsICertOverrideService.idl
index e31cf158dcac3540b0c721cbd677b8522d7549b3..029fc67df81911e3abf3724e8ed99e4bde010f4b 100644
--- a/security/manager/ssl/nsICertOverrideService.idl
+++ b/security/manager/ssl/nsICertOverrideService.idl
@@ -143,7 +143,9 @@ interface nsICertOverrideService : nsISupports {
* @param aDisable If true, disable all security check and make
* hasMatchingOverride always return true.
*/
- void setDisableAllSecurityChecksAndLetAttackersInterceptMyData(in boolean aDisable);
+ void setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
+ in boolean aDisable,
+ [optional] in uint32_t aUserContextId);
readonly attribute boolean securityCheckDisabled;
};
diff --git a/services/settings/Utils.jsm b/services/settings/Utils.jsm
index de557af4275b51a0e4dbc95bd4f6896dd585c232..5049f8613c7a1efa3fec5cc28ff761abe18c557c 100644
--- a/services/settings/Utils.jsm
+++ b/services/settings/Utils.jsm
@@ -102,7 +102,7 @@ function _isUndefined(value) {
var Utils = {
get SERVER_URL() {
- return lazy.allowServerURLOverride
+ return true || lazy.allowServerURLOverride
? lazy.gServerURL
: AppConstants.REMOTE_SETTINGS_SERVER_URL;
},
diff --git a/servo/components/style/gecko/media_features.rs b/servo/components/style/gecko/media_features.rs
index f44fd788b00005c64d94a67d72f83946178a7848..015c8c5cb9fc764d0cf1cab2e448da135cbded10 100644
--- a/servo/components/style/gecko/media_features.rs
+++ b/servo/components/style/gecko/media_features.rs
@@ -232,10 +232,15 @@ pub enum ForcedColors {
/// https://drafts.csswg.org/mediaqueries-5/#forced-colors
fn eval_forced_colors(context: &Context, query_value: Option<ForcedColors>) -> bool {
- let forced = !context.device().use_document_colors();
+ let prefers_forced_colors =
+ unsafe { bindings::Gecko_MediaFeatures_ForcedColors(context.device().document()) };
+ let query_value = match query_value {
+ Some(v) => v,
+ None => return prefers_forced_colors,
+ };
match query_value {
- Some(query_value) => forced == (query_value == ForcedColors::Active),
- None => forced,
+ ForcedColors::Active => prefers_forced_colors,
+ ForcedColors::None => !prefers_forced_colors,
}
}
diff --git a/toolkit/components/browser/nsIWebBrowserChrome.idl b/toolkit/components/browser/nsIWebBrowserChrome.idl
index 4f7337926efbb086a2be97cdbcb3dca39e27c786..f2005cb726ff153d6b1011d6af0479dbf1af02a5 100644
--- a/toolkit/components/browser/nsIWebBrowserChrome.idl
+++ b/toolkit/components/browser/nsIWebBrowserChrome.idl
@@ -70,6 +70,9 @@ interface nsIWebBrowserChrome : nsISupports
// Whether this window should use out-of-process cross-origin subframes.
const unsigned long CHROME_FISSION_WINDOW = 0x00200000;
+ // Whether this window has "width" or "height" defined in features
+ const unsigned long JUGGLER_WINDOW_EXPLICIT_SIZE = 0x00400000;
+
// Prevents new window animations on MacOS and Windows. Currently
// ignored for Linux.
const unsigned long CHROME_SUPPRESS_ANIMATION = 0x01000000;
diff --git a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs
index 0a7ba257a4d43c74841f003a8a0556d7f057700b..cf78a44fa64248ecf5b3ade8a8e92efffeb9f831 100644
--- a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs
+++ b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs
@@ -116,6 +116,12 @@ EnterprisePoliciesManager.prototype = {
Services.prefs.clearUserPref(PREF_POLICIES_APPLIED);
}
+ // Playwright: Disable enterprise policies
+ if (true) {
+ this.status = Ci.nsIEnterprisePolicies.INACTIVE;
+ return;
+ }
+
let provider = this._chooseProvider();
if (provider.failed) {
diff --git a/toolkit/components/startup/nsAppStartup.cpp b/toolkit/components/startup/nsAppStartup.cpp
index 34ced370120f843ab7afd330fb5626ae6f6da7e4..205fc4e5fe3adeacbfe5ab6c15d1bbccf7baf9e8 100644
--- a/toolkit/components/startup/nsAppStartup.cpp
+++ b/toolkit/components/startup/nsAppStartup.cpp
@@ -370,7 +370,7 @@ nsAppStartup::Quit(uint32_t aMode, int aExitCode, bool* aUserAllowedQuit) {
nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
nsCOMPtr<nsIWindowMediator> mediator(
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
- if (mediator) {
+ if (ferocity != eForceQuit && mediator) {
mediator->GetEnumerator(nullptr, getter_AddRefs(windowEnumerator));
if (windowEnumerator) {
bool more;
2019-11-18 18:18:28 -08:00
diff --git a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
index 3e9672fdfe9ddab8acd0f8b18772aece92bb3b64..83454a9c27c96d72597445653beaa014c38728cd 100644
2019-11-18 18:18:28 -08:00
--- a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
+++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
@@ -174,8 +174,8 @@ nsBrowserStatusFilter::OnStateChange(nsIWebProgress* aWebProgress,
2019-11-18 18:18:28 -08:00
}
NS_IMETHODIMP
-nsBrowserStatusFilter::OnProgressChange(nsIWebProgress* aWebProgress,
- nsIRequest* aRequest,
+nsBrowserStatusFilter::OnProgressChange(nsIWebProgress *aWebProgress,
+ nsIRequest *aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
diff --git a/toolkit/components/windowwatcher/nsWindowWatcher.cpp b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
index 3afb5e02eb9c65b2d4dc34692f7c94e43a103b1a..4037e9118dae628ed370cd14934f1dafc3f99feb 100644
--- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp
+++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
@@ -1852,7 +1852,11 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForContent(
// Open a minimal popup.
*aIsPopupRequested = true;
- return nsIWebBrowserChrome::CHROME_MINIMAL_POPUP;
+ uint32_t chromeFlags = 0;
+ if (aFeatures.Exists("width") || aFeatures.Exists("height")) {
+ chromeFlags |= nsIWebBrowserChrome::JUGGLER_WINDOW_EXPLICIT_SIZE;
+ }
+ return chromeFlags | nsIWebBrowserChrome::CHROME_MINIMAL_POPUP;
}
/**
diff --git a/toolkit/mozapps/update/UpdateService.jsm b/toolkit/mozapps/update/UpdateService.jsm
index d969d9e8d0790bff7c837828b92e1a92d945b116..34f2a030eca9c8258900c5b8d2564fa06580f1f3 100644
--- a/toolkit/mozapps/update/UpdateService.jsm
+++ b/toolkit/mozapps/update/UpdateService.jsm
@@ -3610,6 +3610,8 @@ UpdateService.prototype = {
},
get disabledForTesting() {
+ /* for playwright */
+ return true;
return (
(Cu.isInAutomation ||
lazy.Marionette.running ||
2019-11-18 18:18:28 -08:00
diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild
index 04453a437873b2e6339cb7e81ee11c2a5bb46bb1..2ce3151b9a97e7b86619109716a6d942b80f58ed 100644
2019-11-18 18:18:28 -08:00
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -153,6 +153,7 @@ if CONFIG['ENABLE_WEBDRIVER']:
'/remote',
2019-11-18 18:18:28 -08:00
'/testing/firefox-ui',
'/testing/marionette',
+ '/juggler',
2019-11-18 18:18:28 -08:00
'/toolkit/components/telemetry/tests/marionette',
]
browser(firefox): properly initialize debugging pipe on windows (#5514) browser(firefox): properly initialize debugging pipe on windows Firefox on Windows has 2 launch modes: - default: a special "launcher process" is used to start browser as a sub-process - non-default: browser process starts right away Firefox has a logic to detect how successful was the use of the launcher process to do self-recovery when things go wrong. Namely: - when attempting to use launcher process, firefox records a timestamp of the attempt beginning - once the launcher process successfully launches browser sub-process, firefox records another timestamp of the completion On a new launch, firefox checks what timestamps are present. If there's a timestamp that signifies start of launcher process, but no successful timestamp, it decides that last "launcher process" use was not successful and falls back to launching browser right away. When launching 2 firefox processes right away, the first process uses attempts to use launcher process and records the first timestamp. At the same time, the second instance sees the first timestamp and doesn't see the second timestamp, and falls back to launching browser right away. Our debugging pipe code, however, does not support non-launcher-process code path. This patch adds support for remote debugging pipe in case of non-launcher-process startup. Drive-by: - disable crashreporter altogether - remove stray dcheck that breaks firefox debug compilation - disable compilation of firefox update agent - do not use WIN32_DISTRIB flag unless doing full builds since it kills incremental compilation References #4660
2021-02-19 10:32:47 -08:00
diff --git a/toolkit/xre/nsWindowsWMain.cpp b/toolkit/xre/nsWindowsWMain.cpp
index ea14a59b80bbfbaa17d7569734b8409d9d21fcde..28cb052c3115f91e6a036ad8466385ff1d740cd0 100644
browser(firefox): properly initialize debugging pipe on windows (#5514) browser(firefox): properly initialize debugging pipe on windows Firefox on Windows has 2 launch modes: - default: a special "launcher process" is used to start browser as a sub-process - non-default: browser process starts right away Firefox has a logic to detect how successful was the use of the launcher process to do self-recovery when things go wrong. Namely: - when attempting to use launcher process, firefox records a timestamp of the attempt beginning - once the launcher process successfully launches browser sub-process, firefox records another timestamp of the completion On a new launch, firefox checks what timestamps are present. If there's a timestamp that signifies start of launcher process, but no successful timestamp, it decides that last "launcher process" use was not successful and falls back to launching browser right away. When launching 2 firefox processes right away, the first process uses attempts to use launcher process and records the first timestamp. At the same time, the second instance sees the first timestamp and doesn't see the second timestamp, and falls back to launching browser right away. Our debugging pipe code, however, does not support non-launcher-process code path. This patch adds support for remote debugging pipe in case of non-launcher-process startup. Drive-by: - disable crashreporter altogether - remove stray dcheck that breaks firefox debug compilation - disable compilation of firefox update agent - do not use WIN32_DISTRIB flag unless doing full builds since it kills incremental compilation References #4660
2021-02-19 10:32:47 -08:00
--- a/toolkit/xre/nsWindowsWMain.cpp
+++ b/toolkit/xre/nsWindowsWMain.cpp
@@ -14,9 +14,11 @@
browser(firefox): properly initialize debugging pipe on windows (#5514) browser(firefox): properly initialize debugging pipe on windows Firefox on Windows has 2 launch modes: - default: a special "launcher process" is used to start browser as a sub-process - non-default: browser process starts right away Firefox has a logic to detect how successful was the use of the launcher process to do self-recovery when things go wrong. Namely: - when attempting to use launcher process, firefox records a timestamp of the attempt beginning - once the launcher process successfully launches browser sub-process, firefox records another timestamp of the completion On a new launch, firefox checks what timestamps are present. If there's a timestamp that signifies start of launcher process, but no successful timestamp, it decides that last "launcher process" use was not successful and falls back to launching browser right away. When launching 2 firefox processes right away, the first process uses attempts to use launcher process and records the first timestamp. At the same time, the second instance sees the first timestamp and doesn't see the second timestamp, and falls back to launching browser right away. Our debugging pipe code, however, does not support non-launcher-process code path. This patch adds support for remote debugging pipe in case of non-launcher-process startup. Drive-by: - disable crashreporter altogether - remove stray dcheck that breaks firefox debug compilation - disable compilation of firefox update agent - do not use WIN32_DISTRIB flag unless doing full builds since it kills incremental compilation References #4660
2021-02-19 10:32:47 -08:00
#endif
#include "mozilla/Char16.h"
+#include "mozilla/CmdLineAndEnvUtils.h"
#include "nsUTF8Utils.h"
#include "nsWindowsHelpers.h"
browser(firefox): properly initialize debugging pipe on windows (#5514) browser(firefox): properly initialize debugging pipe on windows Firefox on Windows has 2 launch modes: - default: a special "launcher process" is used to start browser as a sub-process - non-default: browser process starts right away Firefox has a logic to detect how successful was the use of the launcher process to do self-recovery when things go wrong. Namely: - when attempting to use launcher process, firefox records a timestamp of the attempt beginning - once the launcher process successfully launches browser sub-process, firefox records another timestamp of the completion On a new launch, firefox checks what timestamps are present. If there's a timestamp that signifies start of launcher process, but no successful timestamp, it decides that last "launcher process" use was not successful and falls back to launching browser right away. When launching 2 firefox processes right away, the first process uses attempts to use launcher process and records the first timestamp. At the same time, the second instance sees the first timestamp and doesn't see the second timestamp, and falls back to launching browser right away. Our debugging pipe code, however, does not support non-launcher-process code path. This patch adds support for remote debugging pipe in case of non-launcher-process startup. Drive-by: - disable crashreporter altogether - remove stray dcheck that breaks firefox debug compilation - disable compilation of firefox update agent - do not use WIN32_DISTRIB flag unless doing full builds since it kills incremental compilation References #4660
2021-02-19 10:32:47 -08:00
+#include <io.h>
#include <windows.h>
#include <versionhelpers.h>
@@ -130,6 +132,19 @@ int wmain(int argc, WCHAR** argv) {
browser(firefox): properly initialize debugging pipe on windows (#5514) browser(firefox): properly initialize debugging pipe on windows Firefox on Windows has 2 launch modes: - default: a special "launcher process" is used to start browser as a sub-process - non-default: browser process starts right away Firefox has a logic to detect how successful was the use of the launcher process to do self-recovery when things go wrong. Namely: - when attempting to use launcher process, firefox records a timestamp of the attempt beginning - once the launcher process successfully launches browser sub-process, firefox records another timestamp of the completion On a new launch, firefox checks what timestamps are present. If there's a timestamp that signifies start of launcher process, but no successful timestamp, it decides that last "launcher process" use was not successful and falls back to launching browser right away. When launching 2 firefox processes right away, the first process uses attempts to use launcher process and records the first timestamp. At the same time, the second instance sees the first timestamp and doesn't see the second timestamp, and falls back to launching browser right away. Our debugging pipe code, however, does not support non-launcher-process code path. This patch adds support for remote debugging pipe in case of non-launcher-process startup. Drive-by: - disable crashreporter altogether - remove stray dcheck that breaks firefox debug compilation - disable compilation of firefox update agent - do not use WIN32_DISTRIB flag unless doing full builds since it kills incremental compilation References #4660
2021-02-19 10:32:47 -08:00
SanitizeEnvironmentVariables();
SetDllDirectoryW(L"");
+ bool hasJugglerPipe =
+ mozilla::CheckArg(argc, argv, "juggler-pipe", nullptr,
browser(firefox): properly initialize debugging pipe on windows (#5514) browser(firefox): properly initialize debugging pipe on windows Firefox on Windows has 2 launch modes: - default: a special "launcher process" is used to start browser as a sub-process - non-default: browser process starts right away Firefox has a logic to detect how successful was the use of the launcher process to do self-recovery when things go wrong. Namely: - when attempting to use launcher process, firefox records a timestamp of the attempt beginning - once the launcher process successfully launches browser sub-process, firefox records another timestamp of the completion On a new launch, firefox checks what timestamps are present. If there's a timestamp that signifies start of launcher process, but no successful timestamp, it decides that last "launcher process" use was not successful and falls back to launching browser right away. When launching 2 firefox processes right away, the first process uses attempts to use launcher process and records the first timestamp. At the same time, the second instance sees the first timestamp and doesn't see the second timestamp, and falls back to launching browser right away. Our debugging pipe code, however, does not support non-launcher-process code path. This patch adds support for remote debugging pipe in case of non-launcher-process startup. Drive-by: - disable crashreporter altogether - remove stray dcheck that breaks firefox debug compilation - disable compilation of firefox update agent - do not use WIN32_DISTRIB flag unless doing full builds since it kills incremental compilation References #4660
2021-02-19 10:32:47 -08:00
+ mozilla::CheckArgFlag::None) == mozilla::ARG_FOUND;
+ if (hasJugglerPipe && !mozilla::EnvHasValue("PW_PIPE_READ")) {
+ intptr_t stdio3 = _get_osfhandle(3);
+ intptr_t stdio4 = _get_osfhandle(4);
+ CHAR stdio3str[20];
+ CHAR stdio4str[20];
+ itoa(stdio3, stdio3str, 10);
+ itoa(stdio4, stdio4str, 10);
+ SetEnvironmentVariableA("PW_PIPE_READ", stdio3str);
+ SetEnvironmentVariableA("PW_PIPE_WRITE", stdio4str);
+ }
// Only run this code if LauncherProcessWin.h was included beforehand, thus
// signalling that the hosting process should support launcher mode.
2019-11-18 18:18:28 -08:00
diff --git a/uriloader/base/nsDocLoader.cpp b/uriloader/base/nsDocLoader.cpp
index e1e46ccdceae595f95d100116ff480905047e82b..eaa0252e768140120158525723ad867b8cb020be 100644
2019-11-18 18:18:28 -08:00
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -830,6 +830,13 @@ void nsDocLoader::DocLoaderIsEmpty(bool aFlushLayout,
("DocLoader:%p: Firing load event for document.open\n",
this));
+ nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+ if (os) {
+ nsIPrincipal* principal = doc->NodePrincipal();
+ if (!principal->IsSystemPrincipal())
+ os->NotifyObservers(ToSupports(doc), "juggler-document-open-loaded", nullptr);
+ }
+
// This is a very cut-down version of
// nsDocumentViewer::LoadComplete that doesn't do various things
// that are not relevant here because this wasn't an actual
diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp
index 54a8d617308c2fb2ce816bb4a88162b8395c2723..140059c6ae4e52b4720aaa34d6313a92729b98a7 100644
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -112,6 +112,7 @@
#include "mozilla/Components.h"
#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/ErrorNames.h"
#include "mozilla/Preferences.h"
#include "mozilla/ipc/URIUtils.h"
@@ -836,6 +837,12 @@ NS_IMETHODIMP nsExternalHelperAppService::ApplyDecodingForExtension(
return NS_OK;
}
+NS_IMETHODIMP nsExternalHelperAppService::SetDownloadInterceptor(
+ nsIDownloadInterceptor* interceptor) {
+ mInterceptor = interceptor;
+ return NS_OK;
+}
+
nsresult nsExternalHelperAppService::GetFileTokenForPath(
const char16_t* aPlatformAppPath, nsIFile** aFile) {
nsDependentString platformAppPath(aPlatformAppPath);
@@ -1446,7 +1453,12 @@ nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel* aChannel) {
// Strip off the ".part" from mTempLeafName
mTempLeafName.Truncate(mTempLeafName.Length() - ArrayLength(".part") + 1);
+ return CreateSaverForTempFile();
+}
+
+nsresult nsExternalAppHandler::CreateSaverForTempFile() {
MOZ_ASSERT(!mSaver, "Output file initialization called more than once!");
+ nsresult rv;
mSaver =
do_CreateInstance(NS_BACKGROUNDFILESAVERSTREAMLISTENER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
@@ -1637,7 +1649,36 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) {
return NS_OK;
}
- rv = SetUpTempFile(aChannel);
+ bool isIntercepted = false;
+ nsCOMPtr<nsIDownloadInterceptor> interceptor = mExtProtSvc->mInterceptor;
+ if (interceptor) {
+ nsCOMPtr<nsIFile> fileToUse;
+ rv = interceptor->InterceptDownloadRequest(this, request, mBrowsingContext, getter_AddRefs(fileToUse), &isIntercepted);
+ if (!NS_SUCCEEDED(rv)) {
+ LOG((" failed to call nsIDowloadInterceptor.interceptDownloadRequest"));
+ return rv;
+ }
+ if (isIntercepted) {
+ LOG((" request interceped by nsIDowloadInterceptor"));
+ if (fileToUse) {
+ mTempFile = fileToUse;
+ rv = mTempFile->GetLeafName(mTempLeafName);
+ NS_ENSURE_SUCCESS(rv, rv);
+ } else {
+ Cancel(NS_BINDING_ABORTED);
+ return NS_OK;
+ }
+ }
+ }
+
+ // Temp file is the final destination when download is intercepted. In that
+ // case we only need to create saver (and not create transfer later). Not creating
+ // mTransfer also cuts off all downloads handling logic in the js compoenents and
+ // browser UI.
+ if (isIntercepted)
+ rv = CreateSaverForTempFile();
+ else
+ rv = SetUpTempFile(aChannel);
if (NS_FAILED(rv)) {
nsresult transferError = rv;
@@ -1691,6 +1732,9 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) {
bool alwaysAsk = true;
mMimeInfo->GetAlwaysAskBeforeHandling(&alwaysAsk);
+ if (isIntercepted) {
+ return NS_OK;
+ }
if (alwaysAsk) {
// But we *don't* ask if this mimeInfo didn't come from
// our user configuration datastore and the user has said
@@ -2259,6 +2303,16 @@ nsExternalAppHandler::OnSaveComplete(nsIBackgroundFileSaver* aSaver,
NotifyTransfer(aStatus);
}
+ if (!mCanceled) {
+ nsCOMPtr<nsIDownloadInterceptor> interceptor = mExtProtSvc->mInterceptor;
+ if (interceptor) {
+ nsCString noError;
+ nsresult rv = interceptor->OnDownloadComplete(this, noError);
+ MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to call nsIDowloadInterceptor.OnDownloadComplete");
+ Unused << rv;
+ }
+ }
+
return NS_OK;
}
@@ -2744,6 +2798,15 @@ NS_IMETHODIMP nsExternalAppHandler::Cancel(nsresult aReason) {
}
}
+ nsCOMPtr<nsIDownloadInterceptor> interceptor = mExtProtSvc->mInterceptor;
+ if (interceptor) {
+ nsCString errorName;
+ GetErrorName(aReason, errorName);
+ nsresult rv = interceptor->OnDownloadComplete(this, errorName);
+ MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed notify nsIDowloadInterceptor about cancel");
+ Unused << rv;
+ }
+
// Break our reference cycle with the helper app dialog (set up in
// OnStartRequest)
mDialog = nullptr;
diff --git a/uriloader/exthandler/nsExternalHelperAppService.h b/uriloader/exthandler/nsExternalHelperAppService.h
index 17c7dccf0217b0aa71cff630dd7b0e9beda9f5aa..06558286f5ed9d1e324654365909f9f8cad957ac 100644
--- a/uriloader/exthandler/nsExternalHelperAppService.h
+++ b/uriloader/exthandler/nsExternalHelperAppService.h
@@ -245,6 +245,8 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService,
mozilla::dom::BrowsingContext* aContentContext, bool aForceSave,
nsIInterfaceRequestor* aWindowContext,
nsIStreamListener** aStreamListener);
+
+ nsCOMPtr<nsIDownloadInterceptor> mInterceptor;
};
/**
@@ -447,6 +449,9 @@ class nsExternalAppHandler final : public nsIStreamListener,
* Upon successful return, both mTempFile and mSaver will be valid.
*/
nsresult SetUpTempFile(nsIChannel* aChannel);
+
+ nsresult CreateSaverForTempFile();
+
/**
* When we download a helper app, we are going to retarget all load
* notifications into our own docloader and load group instead of
diff --git a/uriloader/exthandler/nsIExternalHelperAppService.idl b/uriloader/exthandler/nsIExternalHelperAppService.idl
index 307e6196a89df52d0bccc3ebd1359f58e32de75d..c3692d0f76178ac3aeb1c77a0e973bfa22359346 100644
--- a/uriloader/exthandler/nsIExternalHelperAppService.idl
+++ b/uriloader/exthandler/nsIExternalHelperAppService.idl
@@ -6,6 +6,8 @@
#include "nsICancelable.idl"
+webidl BrowsingContext;
+interface nsIHelperAppLauncher;
interface nsIURI;
interface nsIRequest;
interface nsIStreamListener;
@@ -15,6 +17,17 @@ interface nsIWebProgressListener2;
interface nsIInterfaceRequestor;
webidl BrowsingContext;
+/**
+ * Interceptor interface used by Juggler.
+ */
+[scriptable, uuid(9a20e9b0-75d0-11ea-bc55-0242ac130003)]
+interface nsIDownloadInterceptor : nsISupports
+{
+ bool interceptDownloadRequest(in nsIHelperAppLauncher aHandler, in nsIRequest aRequest, in BrowsingContext aBrowsingContext, out nsIFile file);
+
+ void onDownloadComplete(in nsIHelperAppLauncher aHandler, in ACString aErrorName);
+};
+
/**
* The external helper app service is used for finding and launching
* platform specific external applications for a given mime content type.
@@ -76,6 +89,7 @@ interface nsIExternalHelperAppService : nsISupports
boolean applyDecodingForExtension(in AUTF8String aExtension,
in ACString aEncodingType);
+ void setDownloadInterceptor(in nsIDownloadInterceptor interceptor);
};
/**
diff --git a/widget/InProcessCompositorWidget.cpp b/widget/InProcessCompositorWidget.cpp
index 1c25e9d9a101233f71e92288a0f93125b81ac1c5..22cf67b0f6e3ddd2b3ed725a314ba6a9896abd1c 100644
--- a/widget/InProcessCompositorWidget.cpp
+++ b/widget/InProcessCompositorWidget.cpp
@@ -4,7 +4,10 @@
#include "InProcessCompositorWidget.h"
+#include "HeadlessCompositorWidget.h"
+#include "HeadlessWidget.h"
#include "mozilla/VsyncDispatcher.h"
+#include "mozilla/widget/PlatformWidgetTypes.h"
#include "nsBaseWidget.h"
namespace mozilla {
@@ -23,6 +26,12 @@ RefPtr<CompositorWidget> CompositorWidget::CreateLocal(
// do it after the static_cast.
nsBaseWidget* widget = static_cast<nsBaseWidget*>(aWidget);
MOZ_RELEASE_ASSERT(widget);
+ if (aInitData.type() ==
+ CompositorWidgetInitData::THeadlessCompositorWidgetInitData) {
+ return new HeadlessCompositorWidget(
+ aInitData.get_HeadlessCompositorWidgetInitData(), aOptions,
+ static_cast<HeadlessWidget*>(aWidget));
+ }
return new InProcessCompositorWidget(aOptions, widget);
}
#endif
diff --git a/widget/cocoa/NativeKeyBindings.mm b/widget/cocoa/NativeKeyBindings.mm
index d3e5983259053175584254e7ac01ca9ce024f33a..97f5b851c402fea5477c0ee57af451c62b016eec 100644
--- a/widget/cocoa/NativeKeyBindings.mm
+++ b/widget/cocoa/NativeKeyBindings.mm
@@ -492,6 +492,13 @@
break;
case KEY_NAME_INDEX_ArrowLeft:
if (aEvent.IsAlt()) {
+ if (aEvent.IsMeta() || aEvent.IsControl())
+ break;
+ instance->AppendEditCommandsForSelector(
+ !aEvent.IsShift()
+ ? ToObjcSelectorPtr(@selector(moveWordLeft:))
+ : ToObjcSelectorPtr(@selector(moveWordLeftAndModifySelection:)),
+ aCommands);
break;
}
if (aEvent.IsMeta() || (aEvent.IsControl() && aEvent.IsShift())) {
@@ -512,6 +519,13 @@
break;
case KEY_NAME_INDEX_ArrowRight:
if (aEvent.IsAlt()) {
+ if (aEvent.IsMeta() || aEvent.IsControl())
+ break;
+ instance->AppendEditCommandsForSelector(
+ !aEvent.IsShift()
+ ? ToObjcSelectorPtr(@selector(moveWordRight:))
+ : ToObjcSelectorPtr(@selector(moveWordRightAndModifySelection:)),
+ aCommands);
break;
}
if (aEvent.IsMeta() || (aEvent.IsControl() && aEvent.IsShift())) {
@@ -532,6 +546,10 @@
break;
case KEY_NAME_INDEX_ArrowUp:
if (aEvent.IsControl()) {
+ if (aEvent.IsMeta() || aEvent.IsAlt())
+ break;
+ instance->AppendEditCommandsForSelector(
+ ToObjcSelectorPtr(@selector(scrollPageUp:)), aCommands);
break;
}
if (aEvent.IsMeta()) {
@@ -541,7 +559,7 @@
instance->AppendEditCommandsForSelector(
!aEvent.IsShift()
? ToObjcSelectorPtr(@selector(moveToBeginningOfDocument:))
- : ToObjcSelectorPtr(@selector(moveToBegginingOfDocumentAndModifySelection:)),
+ : ToObjcSelectorPtr(@selector(moveToBeginningOfDocumentAndModifySelection:)),
aCommands);
break;
}
@@ -564,6 +582,10 @@
break;
case KEY_NAME_INDEX_ArrowDown:
if (aEvent.IsControl()) {
+ if (aEvent.IsMeta() || aEvent.IsAlt())
+ break;
+ instance->AppendEditCommandsForSelector(
+ ToObjcSelectorPtr(@selector(scrollPageDown:)), aCommands);
break;
}
if (aEvent.IsMeta()) {
diff --git a/widget/headless/HeadlessCompositorWidget.cpp b/widget/headless/HeadlessCompositorWidget.cpp
index b31a969b7ab3d0fc80912b110d91dfdf3e5991f4..52aed4f9fb51f3f58a440d7e57eaccd6dfcbc2ab 100644
--- a/widget/headless/HeadlessCompositorWidget.cpp
+++ b/widget/headless/HeadlessCompositorWidget.cpp
@@ -3,6 +3,7 @@
* 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 "mozilla/layers/CompositorThread.h"
#include "mozilla/widget/PlatformWidgetTypes.h"
#include "HeadlessCompositorWidget.h"
#include "VsyncDispatcher.h"
@@ -13,10 +14,32 @@ namespace widget {
HeadlessCompositorWidget::HeadlessCompositorWidget(
const HeadlessCompositorWidgetInitData& aInitData,
const layers::CompositorOptions& aOptions, HeadlessWidget* aWindow)
- : CompositorWidget(aOptions), mWidget(aWindow) {
+ : CompositorWidget(aOptions), mWidget(aWindow), mMon("snapshotListener") {
mClientSize = aInitData.InitialClientSize();
}
+void HeadlessCompositorWidget::SetSnapshotListener(HeadlessWidget::SnapshotListener&& listener) {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ ReentrantMonitorAutoEnter lock(mMon);
+ mSnapshotListener = std::move(listener);
+ layers::CompositorThread()->Dispatch(NewRunnableMethod(
+ "HeadlessCompositorWidget::PeriodicSnapshot", this,
+ &HeadlessCompositorWidget::PeriodicSnapshot
+ ));
+}
+
+already_AddRefed<gfx::DrawTarget> HeadlessCompositorWidget::StartRemoteDrawingInRegion(
+ const LayoutDeviceIntRegion& aInvalidRegion,
+ layers::BufferMode* aBufferMode) {
+ if (!mDrawTarget)
+ return nullptr;
+
+ *aBufferMode = layers::BufferMode::BUFFER_NONE;
+ RefPtr<gfx::DrawTarget> result = mDrawTarget;
+ return result.forget();
+}
+
void HeadlessCompositorWidget::ObserveVsync(VsyncObserver* aObserver) {
if (RefPtr<CompositorVsyncDispatcher> cvd =
mWidget->GetCompositorVsyncDispatcher()) {
@@ -29,6 +52,59 @@ nsIWidget* HeadlessCompositorWidget::RealWidget() { return mWidget; }
void HeadlessCompositorWidget::NotifyClientSizeChanged(
const LayoutDeviceIntSize& aClientSize) {
mClientSize = aClientSize;
+ layers::CompositorThread()->Dispatch(NewRunnableMethod<LayoutDeviceIntSize>(
+ "HeadlessCompositorWidget::UpdateDrawTarget", this,
+ &HeadlessCompositorWidget::UpdateDrawTarget,
+ aClientSize));
+}
+
+void HeadlessCompositorWidget::UpdateDrawTarget(const LayoutDeviceIntSize& aClientSize) {
+ MOZ_ASSERT(NS_IsInCompositorThread());
+ if (aClientSize.IsEmpty()) {
+ mDrawTarget = nullptr;
+ return;
+ }
+
+ RefPtr<gfx::DrawTarget> old = std::move(mDrawTarget);
+ gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
+ gfx::IntSize size = aClientSize.ToUnknownSize();
+ mDrawTarget = mozilla::gfx::Factory::CreateDrawTarget(
+ mozilla::gfx::BackendType::SKIA, size, format);
+ if (old) {
+ RefPtr<gfx::SourceSurface> snapshot = old->Snapshot();
+ if (snapshot)
+ mDrawTarget->CopySurface(snapshot.get(), old->GetRect(), gfx::IntPoint(0, 0));
+ }
+}
+
+void HeadlessCompositorWidget::PeriodicSnapshot() {
+ ReentrantMonitorAutoEnter lock(mMon);
+ if (!mSnapshotListener)
+ return;
+
+ TakeSnapshot();
+ NS_DelayedDispatchToCurrentThread(NewRunnableMethod(
+ "HeadlessCompositorWidget::PeriodicSnapshot", this,
+ &HeadlessCompositorWidget::PeriodicSnapshot), 40);
+}
+
+void HeadlessCompositorWidget::TakeSnapshot() {
+ if (!mDrawTarget)
+ return;
+
+ RefPtr<gfx::SourceSurface> snapshot = mDrawTarget->Snapshot();
+ if (!snapshot) {
+ fprintf(stderr, "Failed to get snapshot of draw target\n");
+ return;
+ }
+
+ RefPtr<gfx::DataSourceSurface> dataSurface = snapshot->GetDataSurface();
+ if (!dataSurface) {
+ fprintf(stderr, "Failed to get data surface from snapshot\n");
+ return;
+ }
+
+ mSnapshotListener(std::move(dataSurface));
}
LayoutDeviceIntSize HeadlessCompositorWidget::GetClientSize() {
diff --git a/widget/headless/HeadlessCompositorWidget.h b/widget/headless/HeadlessCompositorWidget.h
index 7f91de9e67d7ffa02de3eef1d760e5cfd05e7ad6..753b8902026626e8f0a190ea3130ba5e65c24835 100644
--- a/widget/headless/HeadlessCompositorWidget.h
+++ b/widget/headless/HeadlessCompositorWidget.h
@@ -6,6 +6,7 @@
#ifndef widget_headless_HeadlessCompositorWidget_h
#define widget_headless_HeadlessCompositorWidget_h
+#include "mozilla/ReentrantMonitor.h"
#include "mozilla/widget/CompositorWidget.h"
#include "HeadlessWidget.h"
@@ -23,8 +24,12 @@ class HeadlessCompositorWidget final : public CompositorWidget,
HeadlessWidget* aWindow);
void NotifyClientSizeChanged(const LayoutDeviceIntSize& aClientSize);
+ void SetSnapshotListener(HeadlessWidget::SnapshotListener&& listener);
// CompositorWidget Overrides
+ already_AddRefed<gfx::DrawTarget> StartRemoteDrawingInRegion(
+ const LayoutDeviceIntRegion& aInvalidRegion,
+ layers::BufferMode* aBufferMode) override;
uintptr_t GetWidgetKey() override;
@@ -42,9 +47,17 @@ class HeadlessCompositorWidget final : public CompositorWidget,
}
private:
+ void UpdateDrawTarget(const LayoutDeviceIntSize& aClientSize);
+ void PeriodicSnapshot();
+ void TakeSnapshot();
+
HeadlessWidget* mWidget;
+ mozilla::ReentrantMonitor mMon;
LayoutDeviceIntSize mClientSize;
+
+ HeadlessWidget::SnapshotListener mSnapshotListener;
+ RefPtr<gfx::DrawTarget> mDrawTarget;
};
} // namespace widget
diff --git a/widget/headless/HeadlessWidget.cpp b/widget/headless/HeadlessWidget.cpp
index 340cb723bd4de51e64164b67b69c77da5c5fa443..252f9411479f6aaa0b65942668ccfb7030af7b46 100644
--- a/widget/headless/HeadlessWidget.cpp
+++ b/widget/headless/HeadlessWidget.cpp
@@ -110,6 +110,8 @@ void HeadlessWidget::Destroy() {
}
}
+ SetSnapshotListener(nullptr);
+
nsBaseWidget::OnDestroy();
nsBaseWidget::Destroy();
@@ -608,5 +610,14 @@ nsresult HeadlessWidget::SynthesizeNativeTouchpadPan(
return NS_OK;
}
+void HeadlessWidget::SetSnapshotListener(SnapshotListener&& listener) {
+ if (!mCompositorWidget) {
+ if (listener)
+ fprintf(stderr, "Trying to set SnapshotListener without compositor widget\n");
+ return;
+ }
+ mCompositorWidget->SetSnapshotListener(std::move(listener));
+}
+
} // namespace widget
} // namespace mozilla
diff --git a/widget/headless/HeadlessWidget.h b/widget/headless/HeadlessWidget.h
index b77ec632a90ff98f4df7af6846fc02fd6411d2e1..ccdbaac472b4c9f6d94e6f8665af9ee740f61311 100644
--- a/widget/headless/HeadlessWidget.h
+++ b/widget/headless/HeadlessWidget.h
@@ -141,6 +141,9 @@ class HeadlessWidget : public nsBaseWidget {
int32_t aModifierFlags,
nsIObserver* aObserver) override;
+ using SnapshotListener = std::function<void(RefPtr<gfx::DataSourceSurface>&&)>;
+ void SetSnapshotListener(SnapshotListener&& listener);
+
private:
~HeadlessWidget();
bool mEnabled;
diff --git a/xpcom/reflect/xptinfo/xptinfo.h b/xpcom/reflect/xptinfo/xptinfo.h
index 2456c2c2b58b27cd595880b547ed20fb687a1835..e967c089b2331c7cd36d34e511543fbc84320b7d 100644
--- a/xpcom/reflect/xptinfo/xptinfo.h
+++ b/xpcom/reflect/xptinfo/xptinfo.h
@@ -514,7 +514,7 @@ static_assert(sizeof(nsXPTMethodInfo) == 8, "wrong size");
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
# define PARAM_BUFFER_COUNT 18
#else
-# define PARAM_BUFFER_COUNT 14
+# define PARAM_BUFFER_COUNT 15
#endif
/**