2824 lines
110 KiB
Diff
Raw Normal View History

diff --git a/accessible/base/NotificationController.h b/accessible/base/NotificationController.h
index b2e16c00e6e67d640974cd4f1aa7a819d4d32063..e80b42794f1fc425e25e6ea8b7a284000080708f 100644
--- a/accessible/base/NotificationController.h
+++ b/accessible/base/NotificationController.h
@@ -275,6 +275,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 ec83b699e1449b2610b43b35694ee18d80cee2ff..66854bda7d8c20627949289b9f2e2e161a00fea8 100644
--- a/accessible/xpcom/xpcAccessibleDocument.cpp
+++ b/accessible/xpcom/xpcAccessibleDocument.cpp
@@ -142,6 +142,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 4460774865769609b66c0710f7c83f4d5c02b6fa..2ca95607b9b093218d48f83adc95c514cebe661b 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>
@@ -359,8 +360,19 @@ 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, L"juggler-pipe",
+ static_cast<const wchar_t**>(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 b59fe4b1854fec7cb329139f9c6773498fb9de51..29973af04902848808e850b40bf85e5f694d349a 100644
2019-11-18 18:18:28 -08:00
--- a/browser/installer/allowed-dupes.mn
+++ b/browser/installer/allowed-dupes.mn
@@ -71,6 +71,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 73a41dc25b9ad674750ce5849a9db8f9878e5e11..e669054d361a148fff895ee24d1ea28c11d0a484 100644
2019-11-18 18:18:28 -08:00
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -198,6 +198,11 @@
@RESPATH@/chrome/remote.manifest
2019-11-18 18:18:28 -08:00
#endif
+@RESPATH@/chrome/juggler@JAREXT@
+@RESPATH@/chrome/juggler.manifest
+@RESPATH@/components/juggler.manifest
+@RESPATH@/components/juggler.js
+
#if defined(ENABLE_TESTS) && defined(MOZ_DEBUG)
@RESPATH@/components/TestInterfaceJS.js
@RESPATH@/components/TestInterfaceJS.manifest
diff --git a/devtools/server/socket/websocket-server.js b/devtools/server/socket/websocket-server.js
index 040c7b124dec6bb254563bbe74fe50012cb077a3..b4e6b8132786af70e8ad0dce88b67c2835307f88 100644
--- a/devtools/server/socket/websocket-server.js
+++ b/devtools/server/socket/websocket-server.js
@@ -133,13 +133,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");
}
@@ -189,13 +188,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, [
@@ -217,8 +216,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 ae0944e11bd31da239698a961658f59594a43559..75df488014a7e1ab085bc712b6ceee645e3fb715 100644
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -109,6 +109,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<
@@ -2796,6 +2810,40 @@ void BrowsingContext::DidSet(FieldIndex<IDX_PrefersColorSchemeOverride>,
});
}
+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 9a2d542a03a758cca90ec05eec184d1247848677..637616310cccdf0e7445ea86a4fe3a48634d6bef 100644
--- a/docshell/base/BrowsingContext.h
+++ b/docshell/base/BrowsingContext.h
@@ -211,6 +211,8 @@ enum class ExplicitActiveStatus : uint8_t {
FIELD(ServiceWorkersTestingEnabled, bool) \
FIELD(MediumOverride, nsString) \
FIELD(PrefersColorSchemeOverride, mozilla::dom::PrefersColorSchemeOverride) \
+ FIELD(PrefersReducedMotionOverride, mozilla::dom::PrefersReducedMotionOverride) \
+ FIELD(ForcedColorsOverride, mozilla::dom::ForcedColorsOverride) \
FIELD(DisplayMode, mozilla::dom::DisplayMode) \
/* The number of entries added to the session history because of this \
* browsing context. */ \
@@ -883,6 +885,14 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
return GetPrefersColorSchemeOverride();
}
+ dom::PrefersReducedMotionOverride PrefersReducedMotionOverride() const {
+ return GetPrefersReducedMotionOverride();
+ }
+
+ dom::ForcedColorsOverride ForcedColorsOverride() const {
+ return GetForcedColorsOverride();
+ }
+
void FlushSessionStore();
bool IsInBFCache() const;
@@ -1027,6 +1037,23 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
void DidSet(FieldIndex<IDX_PrefersColorSchemeOverride>,
dom::PrefersColorSchemeOverride aOldValue);
+ 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 ca056143a56d3f2156bc857daa223c59a723f709..210c791392996294bfd44709210c5cd7e04be3c3 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"
@@ -372,6 +382,13 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
mAllowDNSPrefetch(true),
mAllowWindowControl(true),
mCSSErrorReportingEnabled(false),
+ mFileInputInterceptionEnabled(false),
+ mOverrideHasFocus(false),
+ mBypassCSPEnabled(false),
+ mForceActiveState(false),
+ mOnlineOverride(nsIDocShell::ONLINE_OVERRIDE_NONE),
+ mReducedMotionOverride(REDUCED_MOTION_OVERRIDE_NONE),
+ mForcedColorsOverride(FORCED_COLORS_OVERRIDE_NO_OVERRIDE),
mAllowAuth(mItemType == typeContent),
mAllowKeywordFixup(false),
mDisableMetaRefreshWhenInactive(false),
@@ -3280,6 +3297,221 @@ 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;
+}
+
+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;
@@ -4915,7 +5147,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();
}
@@ -8644,6 +8876,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;
}
@@ -12803,6 +13041,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;
}
@@ -12881,6 +13122,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 dddabae38e18da6bc52bbd23921e813a29b5c7f1..25c2db3fc86f47259fe25a2a495308da1401bc8d 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"
@@ -76,6 +77,7 @@ class nsCommandManager;
class nsDocShellEditorData;
class nsDOMNavigationTiming;
class nsDSURIContentListener;
+class nsGeolocationService;
class nsGlobalWindowOuter;
class FramingChecker;
@@ -411,6 +413,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(
@@ -1026,6 +1037,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
@@ -1310,6 +1323,16 @@ 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;
+ 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 cf95a1a1d08a7ea225267a23a8a91714c20fecba..6af02d667af8a19d6e584467c92a7b1bc2926b99 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;
@@ -804,6 +805,41 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
void synchronizeLayoutHistoryState();
+ attribute boolean fileInputInterceptionEnabled;
+
+ attribute boolean overrideHasFocus;
+
+ attribute boolean bypassCSPEnabled;
+
+ attribute boolean forceActiveState;
+
+ 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 80a39fbe9addfffea12141eec61fef52ece84cac..61a657401693f4f06bba66b01877081ffd05d50e 100644
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -3555,6 +3555,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
@@ -3612,6 +3615,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;
@@ -4423,6 +4431,10 @@ bool Document::HasFocus(ErrorResult& rv) const {
return false;
}
+ if (IsActive() && mDocumentContainer->ShouldOverrideHasFocus()) {
+ return true;
+ }
+
if (!fm->IsInActiveWindow(bc)) {
return false;
}
@@ -17774,6 +17786,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 8b9a275591ecccd3f750e96e9853cf6d8ff3996e..a8f812439371650468ce3812adc5cf5a32083b8b 100644
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -4006,6 +4006,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 0e3d16593b220eea0a65428a0ff18694113781cd..2f0341bd8dc058c78f61d193346e9a7a4a8562b6 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,9 @@ void Navigator::GetLanguage(nsAString& aLanguage) {
}
void Navigator::GetLanguages(nsTArray<nsString>& aLanguages) {
- GetAcceptLanguages(aLanguages);
+ nsString languageOverride;
+ mWindow->GetDocShell()->GetLanguageOverride(languageOverride);
+ GetAcceptLanguages(&languageOverride, 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 +570,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 {
diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h
index 7184795e21afe8b1ac5d36c6f645fc9a027f74d5..0d9c6ae7edd65cd8b7660cff22853ec4859ec608 100644
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -216,7 +216,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 c4f19e1adbf95913b79818aaf7d3dd809e7dbd1a..cdd4eb134210ceac53f3b291d34e9ee65ce94b0f 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -8210,7 +8210,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;
@@ -8269,6 +8270,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 0dbce2bdf40bf23ec748996f1b8f2f543b005b16..cdb2e5d62169d36077e9c9d6c50d8edf8b6ebe56 100644
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2928,7 +2928,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 c6dce5c9fdf7ed9e74c11372f1cab03af9e2c89c..c19937f1fdd4f4a94981565fc721e0a62992a790 100644
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -652,7 +652,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,
@@ -660,7 +660,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
@@ -687,13 +687,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 ffeb42544dccb0efb5c94b652aba4d1801d953aa..49681f4adcbac3fcb80d66ab4a08a21d7fb08472 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) &&
@@ -2923,7 +2927,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 5d1b2392ab5fc65b073d0e2205d02a9e91fe40e5..5d79d5fdf2305c87e7b947adc235008db1acbdbb 100644
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -2478,7 +2478,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
@@ -2497,10 +2497,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));
+ }
}
}
@@ -2624,6 +2630,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) {
@@ -3792,6 +3811,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 ab3a63025e19a68811ea98b77c728ac70a0a63b8..32d37910dbd3a04c64ccb4f2b2cf1505e50330aa 100644
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -327,6 +327,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 22c32682fd1a332cf77b811ae28497932cf7108f..15adc1c0dfda0d80c310db815dc9cf2215464c9c 100644
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -1312,6 +1312,49 @@ void nsINode::GetBoxQuadsFromWindowOrigin(const BoxQuadOptions& aOptions,
mozilla::GetBoxQuadsFromWindowOrigin(this, aOptions, aResult, aRv);
}
+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");
+ }
+ if (!IsContent()) {
+ return aRv.ThrowNotFoundError("Node does not have a layout object");
+ }
+ aRv = NS_OK;
+ nsIFrame* primaryFrame = AsContent()->GetPrimaryFrame(FlushType::Frames);
+ if (!primaryFrame) {
+ return aRv.ThrowNotFoundError("Node does not have a layout object");
+ }
+ 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 3991f8007498f04a07b7a46b82fb41c944330ffa..ac06535828a22c9261641c880be788b29c976b3d 100644
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -2123,6 +2123,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 399bae250043708540d99c188ae3dfc4587cb5ea..43c315aa22b97b30ebbc72d13296fd89076b231c 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 92f41a598ed62d920cd6f9ded96b856ebf897e16..f54348db54b07adc8f9bb5d4632b3060a32ce392 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 7858c69827b31320073fb40a7d7c8a020d7fe617..7c164f75e6d29f0386467476a58ac00f4be1a35c 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"
@@ -254,10 +255,8 @@ nsGeolocationRequest::Allow(JS::HandleValue 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;
@@ -430,8 +429,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();
}
@@ -707,8 +705,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;
@@ -800,7 +804,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 893192d7a33ade248dc32a201fbf5ec418793920..d85ffb5b3b19698b1ed6edd4615976167cf8c034 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;
@@ -42,6 +43,11 @@ using GeoPositionCallback =
CallbackObjectHolder<PositionCallback, nsIDOMGeoPositionCallback>;
using GeoPositionErrorCallback =
CallbackObjectHolder<PositionErrorCallback, nsIDOMGeoPositionErrorCallback>;
+typedef CallbackObjectHolder<PositionCallback, nsIDOMGeoPositionCallback>
+ GeoPositionCallback;
+typedef CallbackObjectHolder<PositionErrorCallback,
+ nsIDOMGeoPositionErrorCallback>
+ GeoPositionErrorCallback;
} // namespace dom
} // namespace mozilla
@@ -50,13 +56,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
@@ -182,6 +189,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 fe0b8a768c21957043bfa0042755022862211378..fc4fca7903829c6cf0bf307b611d4c8e808a60ca 100644
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -52,6 +52,7 @@
#include "nsMappedAttributes.h"
#include "nsIFormControl.h"
#include "mozilla/dom/Document.h"
+#include "nsDocShell.h"
#include "nsIFormControlFrame.h"
#include "nsITextControlFrame.h"
#include "nsIFrame.h"
@@ -742,6 +743,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 2e495039c98784e4d3164cc470704cafa6bee01c..4a532959e15bba3b5e732bd0f0027c1d2f9a9248 100644
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -364,7 +364,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 e744940a8e7517b39a73509da3942c2cac9ee0c1..9ba6fe797ed0707137f9cf32b784544d0db0195c 100644
--- a/dom/media/systemservices/video_engine/desktop_capture_impl.cc
+++ b/dom/media/systemservices/video_engine/desktop_capture_impl.cc
@@ -122,10 +122,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() {
@@ -357,9 +358,13 @@ int32_t DesktopCaptureImpl::Init() {
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.
@@ -376,13 +381,15 @@ int32_t DesktopCaptureImpl::Init() {
}
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()),
#if defined(_WIN32)
capturer_thread_(
@@ -427,6 +434,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();
@@ -627,6 +647,12 @@ void DesktopCaptureImpl::OnCaptureResult(DesktopCapturer::Result result,
frameInfo.height = frame->size().height();
frameInfo.videoType = VideoType::kARGB;
+ size_t videoFrameStride =
+ frameInfo.width * DesktopFrame::kBytesPerPixel;
+ 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 a07735e4f046b98d4380ecaa8327620e3819c4d8..29b9b63f1b8dfbcec302a5db49f1032205076795 100644
--- a/dom/media/systemservices/video_engine/desktop_capture_impl.h
+++ b/dom/media/systemservices/video_engine/desktop_capture_impl.h
@@ -44,6 +44,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
@@ -156,12 +171,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);
@@ -171,6 +187,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;
@@ -191,7 +209,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);
@@ -213,6 +231,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
@@ -234,6 +253,7 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
void process();
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 af35617f2948fc78b496c57353371a2293fedf5a..914d886d9a7f9d5d85e73d33d2d219cf20434076 100644
--- a/dom/script/ScriptSettings.cpp
+++ b/dom/script/ScriptSettings.cpp
@@ -178,6 +178,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.
@@ -205,7 +229,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 7c270d908b14088cb67e3d21919b7c7af447c190..c7b7123b7639995772aa23ae81f2c7f488ddb966 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..d996e0a3cbbb19c1dc320c305c6d74037bffa0d3 100644
--- a/dom/webidl/GeometryUtils.webidl
+++ b/dom/webidl/GeometryUtils.webidl
@@ -27,6 +27,9 @@ interface mixin GeometryUtils {
[Throws, Func="nsINode::HasBoxQuadsSupport", NeedsCallerType]
sequence<DOMQuad> getBoxQuads(optional BoxQuadOptions options = {});
+ [ChromeOnly, Throws, Func="nsINode::HasBoxQuadsSupport"]
+ void 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 f600cf99ab5a9fb02e069a2de56792d10d76de14..18d368143b60dab98f046cad39c1c03d99abadbf 100644
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -964,7 +964,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) {
@@ -1166,8 +1166,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;
}
@@ -1861,6 +1860,13 @@ void RuntimeService::PropagateStorageAccessPermissionGranted(
}
}
+void RuntimeService::ResetDefaultLocaleInAllWorkers() {
+ AssertIsOnMainThread();
+ BroadcastAllWorkers([](auto& worker) {
+ worker.ResetDefaultLocale();
+ });
+}
+
void RuntimeService::NoteIdleThread(SafeRefPtr<WorkerThread> aThread) {
AssertIsOnMainThread();
MOZ_ASSERT(aThread);
@@ -2321,6 +2327,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 d0752a975382ec0f51238b5aa96bd57658d5389a..4466adcc3a5e01f04586f55d17ec195a35f3ea5a 100644
--- a/dom/workers/RuntimeService.h
+++ b/dom/workers/RuntimeService.h
@@ -123,6 +123,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 8b1b46d69f2c90d851d292c285a1ba9bdbd4d9b7..dea5259b0a82e5e6d3c431fc78e60d5df80b3eda 100644
--- a/dom/workers/WorkerCommon.h
+++ b/dom/workers/WorkerCommon.h
@@ -45,6 +45,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 5de91115e53608b20ed3ca8314c0777391b992a1..28850de41036a71dfcdde7b4c2b82bbd4e08bb93 100644
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -694,6 +694,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;
@@ -1891,6 +1903,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();
@@ -5033,6 +5055,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 43a0a10d14b2b52c1318d8678fc9d549381a811d..ed3b79125a412634853bc0ced6f108a21aa40453 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,
@@ -950,6 +952,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 db5ebebd663689371464a14e5b35ace2637cc8e6..dcb3b79a6d68854f56491616401f134712886e15 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) {
@@ -244,6 +245,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 838eb84e208a6ee101371ea05ce048615bcd1f1f..ee248d0069d2b710d6ec4279d88e4a63ede721f5 100644
--- a/js/src/debugger/Object.cpp
+++ b/js/src/debugger/Object.cpp
@@ -2371,7 +2371,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 e8f27fb69691aa6062c860a14ec94660fb9e5189..83cffc97f12072c24a7ea1bbd7b26ee37d856df3 100644
--- a/js/src/vm/DateTime.cpp
+++ b/js/src/vm/DateTime.cpp
@@ -170,6 +170,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);
@@ -494,10 +499,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) {
@@ -719,9 +738,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 3ce936fe3a4a83f9161eddc9e5289322d6a363e3..6b1c34244d8b2f2102ec423e2d96812fb5d41a9d 100644
--- a/js/src/vm/DateTime.h
+++ b/js/src/vm/DateTime.h
@@ -63,6 +63,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
@@ -202,6 +204,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();
@@ -293,6 +296,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
@@ -308,6 +313,8 @@ class DateTimeInfo {
void internalResetTimeZone(ResetTimeZoneMode mode);
+ void internalSetTimeZoneOverride(std::string timeZone);
+
void updateTimeZone();
void internalResyncICUDefaultTimeZone();
diff --git a/layout/style/GeckoBindings.h b/layout/style/GeckoBindings.h
index a384a0d00ce970a3e9db8983deaa012b45a76324..954bf59def43fdbb62924f35b45cde5f6c1a9fff 100644
--- a/layout/style/GeckoBindings.h
+++ b/layout/style/GeckoBindings.h
@@ -586,6 +586,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 6d01ac9bb5e81c02e647dc722daa7586273c1846..f77c0e57d452d273c8c8c956f161cdf8b722f873 100644
--- a/layout/style/nsMediaFeatures.cpp
+++ b/layout/style/nsMediaFeatures.cpp
@@ -260,10 +260,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 1bfb8fefab89512bb8597f5ddcd3c00c023ba5d7..824d55d09f9889c7909b6e347a6405591a1e8a82 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4549,7 +4549,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 to start the private browsing mode at application startup
diff --git a/netwerk/base/nsINetworkInterceptController.idl b/netwerk/base/nsINetworkInterceptController.idl
index e869cd28d396aa87c522241d3e63d435ee8dbae6..2d307f089209721d88d231b03e8628890b8228ea 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 b9b0a1e9ac5e15106fdd417451bf4b6f5297fd6f..7c6fc15cc362492264aaa8500bbbac6670a2ca87 100644
--- a/netwerk/protocol/http/InterceptedHttpChannel.cpp
+++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp
@@ -652,6 +652,14 @@ void InterceptedHttpChannel::DoAsyncAbort(nsresult aStatus) {
Unused << AsyncAbort(aStatus);
}
+NS_IMETHODIMP
+InterceptedHttpChannel::ResetInterceptionWithURI(nsIURI* aURI) {
+ if (aURI) {
+ mURI = aURI;
+ }
+ return ResetInterception(true);
+}
+
NS_IMETHODIMP
InterceptedHttpChannel::ResetInterception(bool aBypass) {
if (mCanceled) {
diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp
index 93504fa7ffa922a96dd34fbf2da706f2765e875e..846c1ac0933ee4241415645787f86b73b76751df 100644
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -1321,6 +1321,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/python/mozbuild/mozpack/executables.py b/python/mozbuild/mozpack/executables.py
index 4504ade8e6b3be9404e0d72fd30f60939831ed0f..34988ac3ede846d0aaa0d4637439108fd922361f 100644
--- a/python/mozbuild/mozpack/executables.py
+++ b/python/mozbuild/mozpack/executables.py
@@ -107,7 +107,7 @@ def strip(path):
"""
from buildconfig import substs
- strip = substs["STRIP"]
+ strip = os.getenv("CMD_STRIP") or substs["STRIP"]
flags = substs.get("STRIP_FLAGS", [])
cmd = [strip] + flags + [path]
if subprocess.call(cmd) != 0:
diff --git a/security/manager/ssl/nsCertOverrideService.cpp b/security/manager/ssl/nsCertOverrideService.cpp
index 9089442005f6ab1fc98c245579a0e49261be3267..2eca12599d1f22a9297dc2f8f471a7a0d85ed275 100644
--- a/security/manager/ssl/nsCertOverrideService.cpp
+++ b/security/manager/ssl/nsCertOverrideService.cpp
@@ -570,7 +570,12 @@ nsCertOverrideService::HasMatchingOverride(
bool disableAllSecurityCheck = false;
{
MutexAutoLock lock(mMutex);
- disableAllSecurityCheck = mDisableAllSecurityCheck;
+ if (aOriginAttributes.mUserContextId) {
+ disableAllSecurityCheck = mUserContextIdsWithDisabledSecurityChecks.has(
+ aOriginAttributes.mUserContextId);
+ } else {
+ disableAllSecurityCheck = mDisableAllSecurityCheck;
+ }
}
if (disableAllSecurityCheck) {
nsCertOverride::OverrideBits all = nsCertOverride::OverrideBits::Untrusted |
@@ -774,14 +779,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 6f924246ee1c6c3bb118e643d7851c320a380664..ea3af29f08ec1e0aa5093ca375601a027c148fcb 100644
--- a/security/manager/ssl/nsCertOverrideService.h
+++ b/security/manager/ssl/nsCertOverrideService.h
@@ -133,6 +133,7 @@ class nsCertOverrideService final : public nsICertOverrideService,
~nsCertOverrideService();
mozilla::Mutex mMutex MOZ_UNANNOTATED;
+ mozilla::HashSet<uint32_t> mUserContextIdsWithDisabledSecurityChecks;
bool mDisableAllSecurityCheck;
nsCOMPtr<nsIFile> mSettingsFile;
nsTHashtable<nsCertOverrideEntry> mSettingsTable;
diff --git a/security/manager/ssl/nsICertOverrideService.idl b/security/manager/ssl/nsICertOverrideService.idl
index 3862fe6830874c036592fd217cab7ad5f4cd3e27..3166b37db0e52f7f2972d2bcb7a72ed819805794 100644
--- a/security/manager/ssl/nsICertOverrideService.idl
+++ b/security/manager/ssl/nsICertOverrideService.idl
@@ -201,7 +201,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 2ce9e87c65caf10f1ea998d65976aad3403f12b8..259bc07709a595e49aa96e216cca6182e5ba4cfb 100644
--- a/services/settings/Utils.jsm
+++ b/services/settings/Utils.jsm
@@ -87,7 +87,7 @@ function _isUndefined(value) {
var Utils = {
get SERVER_URL() {
- return allowServerURLOverride
+ return true || allowServerURLOverride
? gServerURL
: "https://firefox.settings.services.mozilla.com/v1";
},
diff --git a/servo/components/style/gecko/media_features.rs b/servo/components/style/gecko/media_features.rs
index c873ac92b87999437f9bde3da7895e057af31989..02f70bbc971a642bcbad58ae57086644b0519b55 100644
--- a/servo/components/style/gecko/media_features.rs
+++ b/servo/components/style/gecko/media_features.rs
@@ -347,10 +347,15 @@ pub enum ForcedColors {
/// https://drafts.csswg.org/mediaqueries-5/#forced-colors
fn eval_forced_colors(device: &Device, query_value: Option<ForcedColors>) -> bool {
- let forced = !device.use_document_colors();
+ let prefers_forced_colors =
+ unsafe { bindings::Gecko_MediaFeatures_ForcedColors(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.jsm b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.jsm
index 6cf104c07f5140d881eed17783d404075766ed41..1d476170119aa9b9e1007ea25d8039e80bf6785b 100644
--- a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.jsm
+++ b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.jsm
@@ -115,6 +115,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 a76e612bc7149155305468307bebf0e69679897d..ba3c5dc0af69a34fcfbf04a3dbc506ef45833107 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 0f8f1560e734dd82ffdace9edf755d525a0028d9..9f0c24184dc09b31c8f0629a946d9ec0dfeec58f 100644
--- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp
+++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
@@ -1813,7 +1813,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 fcd59ca03a98534e1a567827152164245515d5ec..2a3b7c8f8e8174a9ef8a14935f24c9c951882d4b 100644
--- a/toolkit/mozapps/update/UpdateService.jsm
+++ b/toolkit/mozapps/update/UpdateService.jsm
@@ -3594,7 +3594,7 @@ UpdateService.prototype = {
},
get disabledForTesting() {
- return (
+ return true || (
(Cu.isInAutomation || Marionette.running || RemoteAgent.listening) &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_DISABLEDFORTESTING, false)
);
2019-11-18 18:18:28 -08:00
diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild
index 79df0d9e61a645f23d1c9544841f6963a94fc43c..60423fb04d43a56160c6409bbef1aa6d93fd93be 100644
2019-11-18 18:18:28 -08:00
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -160,6 +160,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..f993e78e02563cada8c131be3d4658bc8f7532b6 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,20 @@ 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, L"juggler-pipe",
+ static_cast<const wchar_t**>(nullptr),
+ 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 9ca3975c99c8bff3829bce1cf49d1235910c3ab8..6606eb02fba53ea8bd401d07460b85b068abd2bd 100644
2019-11-18 18:18:28 -08:00
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -827,6 +827,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 6e9fb1aff06f247ad43c9e70bfa2dd88ee874d04..b7a5e5aef5eea020e0a19eea745a3afee7a83ac1 100644
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -105,6 +105,7 @@
#include "mozilla/Components.h"
#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/ErrorNames.h"
#include "mozilla/Preferences.h"
#include "mozilla/ipc/URIUtils.h"
@@ -993,6 +994,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);
@@ -1646,7 +1653,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);
@@ -1837,7 +1849,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;
@@ -1892,6 +1933,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
@@ -2458,6 +2502,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;
}
@@ -2931,6 +2985,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 06d1e09304cfb89a235036dca3871a9ad07e350d..73d4139be95ef97026b346b3a01e6154b19f8b02 100644
--- a/uriloader/exthandler/nsExternalHelperAppService.h
+++ b/uriloader/exthandler/nsExternalHelperAppService.h
@@ -214,6 +214,8 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService,
mozilla::dom::BrowsingContext* aContentContext, bool aForceSave,
nsIInterfaceRequestor* aWindowContext,
nsIStreamListener** aStreamListener);
+
+ nsCOMPtr<nsIDownloadInterceptor> mInterceptor;
};
/**
@@ -410,6 +412,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 3554c69aaced17631d8d1e4d9a000f0dd8b7ba9c..52d6b60707d076906e79160fef155eaaf999470c 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 a79d86ce6f8f6ffda89739bf735f2c3f5abffe21..43684040367d7888263bf65a908f0757ad2fcad8 100644
--- a/widget/headless/HeadlessWidget.cpp
+++ b/widget/headless/HeadlessWidget.cpp
@@ -108,6 +108,8 @@ void HeadlessWidget::Destroy() {
}
}
+ SetSnapshotListener(nullptr);
+
nsBaseWidget::OnDestroy();
nsBaseWidget::Destroy();
@@ -559,5 +561,15 @@ nsresult HeadlessWidget::SynthesizeNativeTouchPadPinch(
DispatchPinchGestureInput(inputToDispatch);
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 a9ba98c048b51eece158b9a04ff2770f4c7afa76..de8d25ffd94ff92dde3ece18e9b6d7df98a995c5 100644
--- a/widget/headless/HeadlessWidget.h
+++ b/widget/headless/HeadlessWidget.h
@@ -134,6 +134,9 @@ class HeadlessWidget : public nsBaseWidget {
TouchpadGesturePhase aEventPhase, float aScale,
LayoutDeviceIntPoint aPoint, int32_t aModifierFlags) 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 efee881c142175c29d15f7ceaaebf852f39e44cd..014bf4b39b99eaf2fba6fb08827e7d2f964bab33 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
/**