3328 lines
131 KiB
Diff
3328 lines
131 KiB
Diff
diff --git a/accessible/base/NotificationController.h b/accessible/base/NotificationController.h
|
|
index 1bcd464d3bd6b8465f78c62b074b0d57dbc6a082..f878ac9db2d800542dabcc2f48e8ae4727ec4b9a 100644
|
|
--- a/accessible/base/NotificationController.h
|
|
+++ b/accessible/base/NotificationController.h
|
|
@@ -244,6 +244,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 1886621c373fe1fd5ff54092afc4c64e9ca9a8fd..a0febf72885410b45227171c63e823eca118cb37 100644
|
|
--- a/accessible/interfaces/nsIAccessibleDocument.idl
|
|
+++ b/accessible/interfaces/nsIAccessibleDocument.idl
|
|
@@ -67,4 +67,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 d616e476b2149de5703077563680905e40db0459..7a8a48d5e7303a298a3e2e9fdf64558b3cdbe654 100644
|
|
--- a/accessible/xpcom/xpcAccessibleDocument.cpp
|
|
+++ b/accessible/xpcom/xpcAccessibleDocument.cpp
|
|
@@ -131,6 +131,13 @@ xpcAccessibleDocument::GetChildDocumentAt(uint32_t aIndex,
|
|
return *aDocument ? NS_OK : NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
+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 8e9bf2b413585b5a3db9370eee5d57fb6c6716ed..5a3b194b54e3813c89989f13a214c989a409f0f6 100644
|
|
--- a/accessible/xpcom/xpcAccessibleDocument.h
|
|
+++ b/accessible/xpcom/xpcAccessibleDocument.h
|
|
@@ -47,6 +47,8 @@ class xpcAccessibleDocument : public xpcAccessibleHyperText,
|
|
NS_IMETHOD GetChildDocumentAt(uint32_t aIndex,
|
|
nsIAccessibleDocument** aDocument) 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 8167d2b81c918e02ce757f7f448f22e07c29d140..3ae798880acfd8aa965ae08051f2f81855133711 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>
|
|
|
|
@@ -422,8 +423,18 @@ Maybe<int> LauncherMain(int& argc, wchar_t* argv[],
|
|
HANDLE stdHandles[] = {::GetStdHandle(STD_INPUT_HANDLE),
|
|
::GetStdHandle(STD_OUTPUT_HANDLE),
|
|
::GetStdHandle(STD_ERROR_HANDLE)};
|
|
-
|
|
attrs.AddInheritableHandles(stdHandles);
|
|
+ // Playwright pipe installation.
|
|
+ bool hasJugglerPipe =
|
|
+ mozilla::CheckArg(argc, argv, "juggler-pipe", nullptr,
|
|
+ mozilla::CheckArgFlag::None) == mozilla::ARG_FOUND;
|
|
+ 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;
|
|
|
|
diff --git a/browser/installer/allowed-dupes.mn b/browser/installer/allowed-dupes.mn
|
|
index 213a99ed433d5219c2b9a64baad82d14cdbcd432..ee4f6484cdfe80899c28a1d9607494e520bfc93d 100644
|
|
--- a/browser/installer/allowed-dupes.mn
|
|
+++ b/browser/installer/allowed-dupes.mn
|
|
@@ -67,6 +67,12 @@ browser/features/webcompat@mozilla.org/shims/empty-shim.txt
|
|
removed-files
|
|
#endif
|
|
|
|
+# 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
|
|
+
|
|
# Bug 1606928 - There's no reliable way to connect Top Sites favicons with the favicons in the Search Service
|
|
browser/chrome/browser/content/activity-stream/data/content/tippytop/favicons/allegro-pl.ico
|
|
browser/defaults/settings/main/search-config-icons/96327a73-c433-5eb4-a16d-b090cadfb80b
|
|
diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
|
|
index beae3018bb533529555496433b90403827ba07fc..3f3c750f4cef768b5429492c0077616505262cb9 100644
|
|
--- a/browser/installer/package-manifest.in
|
|
+++ b/browser/installer/package-manifest.in
|
|
@@ -196,6 +196,9 @@
|
|
@RESPATH@/chrome/remote.manifest
|
|
#endif
|
|
|
|
+@RESPATH@/chrome/juggler@JAREXT@
|
|
+@RESPATH@/chrome/juggler.manifest
|
|
+
|
|
; [Extensions]
|
|
@RESPATH@/components/extensions-toolkit.manifest
|
|
@RESPATH@/browser/components/extensions-browser.manifest
|
|
diff --git a/devtools/server/socket/websocket-server.js b/devtools/server/socket/websocket-server.js
|
|
index d49c6fbf1bf83b832795fa674f6b41f223eef812..7ea3540947ff5f61b15f27fbf4b955649f8e9ff9 100644
|
|
--- a/devtools/server/socket/websocket-server.js
|
|
+++ b/devtools/server/socket/websocket-server.js
|
|
@@ -134,13 +134,12 @@ function writeHttpResponse(output, response) {
|
|
* Process the WebSocket handshake headers and return the key to be sent in
|
|
* Sec-WebSocket-Accept response header.
|
|
*/
|
|
-function processRequest({ requestLine, headers }) {
|
|
+function processRequest({ requestLine, headers }, expectedPath) {
|
|
const [method, path] = requestLine.split(" ");
|
|
if (method !== "GET") {
|
|
throw new Error("The handshake request must use GET method");
|
|
}
|
|
-
|
|
- if (path !== "/") {
|
|
+ if (path !== expectedPath) {
|
|
throw new Error("The handshake request has unknown path");
|
|
}
|
|
|
|
@@ -190,13 +189,13 @@ function computeKey(key) {
|
|
/**
|
|
* Perform the server part of a WebSocket opening handshake on an incoming connection.
|
|
*/
|
|
-const serverHandshake = async function (input, output) {
|
|
+const serverHandshake = async function (input, output, expectedPath) {
|
|
// Read the request
|
|
const request = await readHttpRequest(input);
|
|
|
|
try {
|
|
// Check and extract info from the request
|
|
- const { acceptKey } = processRequest(request);
|
|
+ const { acceptKey } = processRequest(request, expectedPath);
|
|
|
|
// Send response headers
|
|
await writeHttpResponse(output, [
|
|
@@ -218,8 +217,8 @@ const serverHandshake = async function (input, output) {
|
|
* Performs the WebSocket handshake and waits for the WebSocket to open.
|
|
* Returns Promise with a WebSocket ready to send and receive messages.
|
|
*/
|
|
-const accept = async function (transport, input, output) {
|
|
- await serverHandshake(input, output);
|
|
+const accept = async function (transport, input, output, expectedPath) {
|
|
+ await serverHandshake(input, output, expectedPath || "/");
|
|
|
|
const transportProvider = {
|
|
setListener(upgradeListener) {
|
|
diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp
|
|
index 28e9d14bd7979798025f9fc30d9a45527488c34c..d6abf1c3e7e2b2cdfd51351ced4aa6fb0d51327b 100644
|
|
--- a/docshell/base/BrowsingContext.cpp
|
|
+++ b/docshell/base/BrowsingContext.cpp
|
|
@@ -106,8 +106,15 @@ struct ParamTraits<mozilla::dom::DisplayMode>
|
|
|
|
template <>
|
|
struct ParamTraits<mozilla::dom::PrefersColorSchemeOverride>
|
|
- : public mozilla::dom::WebIDLEnumSerializer<
|
|
- mozilla::dom::PrefersColorSchemeOverride> {};
|
|
+ : public mozilla::dom::WebIDLEnumSerializer<mozilla::dom::PrefersColorSchemeOverride> {};
|
|
+
|
|
+template <>
|
|
+struct ParamTraits<mozilla::dom::PrefersReducedMotionOverride>
|
|
+ : public mozilla::dom::WebIDLEnumSerializer<mozilla::dom::PrefersReducedMotionOverride> {};
|
|
+
|
|
+template <>
|
|
+struct ParamTraits<mozilla::dom::PrefersContrastOverride>
|
|
+ : public mozilla::dom::WebIDLEnumSerializer<mozilla::dom::PrefersContrastOverride> {};
|
|
|
|
template <>
|
|
struct ParamTraits<mozilla::dom::ForcedColorsOverride>
|
|
@@ -2887,6 +2894,32 @@ void BrowsingContext::DidSet(FieldIndex<IDX_ForcedColorsOverride>,
|
|
PresContextAffectingFieldChanged();
|
|
}
|
|
|
|
+void BrowsingContext::DidSet(FieldIndex<IDX_PrefersContrastOverride>,
|
|
+ dom::PrefersContrastOverride aOldValue) {
|
|
+ MOZ_ASSERT(IsTop());
|
|
+ if (PrefersContrastOverride() == aOldValue) {
|
|
+ return;
|
|
+ }
|
|
+ PresContextAffectingFieldChanged();
|
|
+}
|
|
+
|
|
+void BrowsingContext::DidSet(FieldIndex<IDX_PrefersReducedMotionOverride>,
|
|
+ dom::PrefersReducedMotionOverride aOldValue) {
|
|
+ MOZ_ASSERT(IsTop());
|
|
+ if (PrefersReducedMotionOverride() == aOldValue) {
|
|
+ return;
|
|
+ }
|
|
+ PreOrderWalk([&](BrowsingContext* aContext) {
|
|
+ if (nsIDocShell* shell = aContext->GetDocShell()) {
|
|
+ if (nsPresContext* pc = shell->GetPresContext()) {
|
|
+ pc->MediaFeatureValuesChanged(
|
|
+ {MediaFeatureChangeReason::SystemMetricsChange},
|
|
+ MediaFeatureChangePropagation::JustThisDocument);
|
|
+ }
|
|
+ }
|
|
+ });
|
|
+}
|
|
+
|
|
void BrowsingContext::DidSet(FieldIndex<IDX_MediumOverride>,
|
|
nsString&& aOldValue) {
|
|
MOZ_ASSERT(IsTop());
|
|
diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h
|
|
index 13815ddf7e13825970cafda19ca24412a5150b53..71c7ae2fce1d92614a60b2aba85bbd70629f682f 100644
|
|
--- a/docshell/base/BrowsingContext.h
|
|
+++ b/docshell/base/BrowsingContext.h
|
|
@@ -203,10 +203,10 @@ struct EmbedderColorSchemes {
|
|
FIELD(GVInaudibleAutoplayRequestStatus, GVAutoplayRequestStatus) \
|
|
/* ScreenOrientation-related APIs */ \
|
|
FIELD(CurrentOrientationAngle, float) \
|
|
- FIELD(CurrentOrientationType, mozilla::dom::OrientationType) \
|
|
+ FIELD(CurrentOrientationType, dom::OrientationType) \
|
|
FIELD(OrientationLock, mozilla::hal::ScreenOrientation) \
|
|
FIELD(UserAgentOverride, nsString) \
|
|
- FIELD(TouchEventsOverrideInternal, mozilla::dom::TouchEventsOverride) \
|
|
+ FIELD(TouchEventsOverrideInternal, dom::TouchEventsOverride) \
|
|
FIELD(EmbedderElementType, Maybe<nsString>) \
|
|
FIELD(MessageManagerGroup, nsString) \
|
|
FIELD(MaxTouchPointsOverride, uint8_t) \
|
|
@@ -246,6 +246,9 @@ struct EmbedderColorSchemes {
|
|
* <browser> embedder element. */ \
|
|
FIELD(EmbedderColorSchemes, EmbedderColorSchemes) \
|
|
FIELD(DisplayMode, dom::DisplayMode) \
|
|
+ /* playwright addition */ \
|
|
+ FIELD(PrefersReducedMotionOverride, dom::PrefersReducedMotionOverride) \
|
|
+ FIELD(PrefersContrastOverride, dom::PrefersContrastOverride) \
|
|
/* The number of entries added to the session history because of this \
|
|
* browsing context. */ \
|
|
FIELD(HistoryEntryCount, uint32_t) \
|
|
@@ -948,6 +951,14 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
|
return GetForcedColorsOverride();
|
|
}
|
|
|
|
+ dom::PrefersReducedMotionOverride PrefersReducedMotionOverride() const {
|
|
+ return GetPrefersReducedMotionOverride();
|
|
+ }
|
|
+
|
|
+ dom::PrefersContrastOverride PrefersContrastOverride() const {
|
|
+ return GetPrefersContrastOverride();
|
|
+ }
|
|
+
|
|
bool IsInBFCache() const;
|
|
|
|
bool AllowJavascript() const { return GetAllowJavascript(); }
|
|
@@ -1107,6 +1118,11 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
|
return IsTop();
|
|
}
|
|
|
|
+ bool CanSet(FieldIndex<IDX_PrefersContrastOverride>,
|
|
+ dom::PrefersContrastOverride, ContentParent*) {
|
|
+ return IsTop();
|
|
+ }
|
|
+
|
|
bool CanSet(FieldIndex<IDX_ForcedColorsOverride>, dom::ForcedColorsOverride,
|
|
ContentParent*) {
|
|
return IsTop();
|
|
@@ -1125,10 +1141,22 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
|
void DidSet(FieldIndex<IDX_ForcedColorsOverride>,
|
|
dom::ForcedColorsOverride aOldValue);
|
|
|
|
+ void DidSet(FieldIndex<IDX_PrefersContrastOverride>,
|
|
+ dom::PrefersContrastOverride aOldValue);
|
|
+
|
|
template <typename Callback>
|
|
void WalkPresContexts(Callback&&);
|
|
void PresContextAffectingFieldChanged();
|
|
|
|
+ bool CanSet(FieldIndex<IDX_PrefersReducedMotionOverride>,
|
|
+ dom::PrefersReducedMotionOverride, ContentParent*) {
|
|
+ return IsTop();
|
|
+ }
|
|
+
|
|
+ void DidSet(FieldIndex<IDX_PrefersReducedMotionOverride>,
|
|
+ dom::PrefersReducedMotionOverride aOldValue);
|
|
+
|
|
+
|
|
void DidSet(FieldIndex<IDX_MediumOverride>, nsString&& aOldValue);
|
|
|
|
bool CanSet(FieldIndex<IDX_SuspendMediaWhenInactive>, bool, ContentParent*) {
|
|
diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp
|
|
index 671a12de84d3b01c4331dbbb2fac050ce061cda1..afcd95e77185e6d606503b7c01d6ab48cc236cc8 100644
|
|
--- a/docshell/base/CanonicalBrowsingContext.cpp
|
|
+++ b/docshell/base/CanonicalBrowsingContext.cpp
|
|
@@ -323,6 +323,8 @@ void CanonicalBrowsingContext::ReplacedBy(
|
|
txn.SetShouldDelayMediaFromStart(GetShouldDelayMediaFromStart());
|
|
txn.SetForceOffline(GetForceOffline());
|
|
txn.SetTopInnerSizeForRFP(GetTopInnerSizeForRFP());
|
|
+ txn.SetPrefersReducedMotionOverride(GetPrefersReducedMotionOverride());
|
|
+ txn.SetForcedColorsOverride(GetForcedColorsOverride());
|
|
|
|
// Propagate some settings on BrowsingContext replacement so they're not lost
|
|
// on bfcached navigations. These are important for GeckoView (see bug
|
|
@@ -1600,6 +1602,12 @@ void CanonicalBrowsingContext::LoadURI(nsIURI* aURI,
|
|
return;
|
|
}
|
|
|
|
+ {
|
|
+ nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
|
+ if (observerService) {
|
|
+ observerService->NotifyObservers(ToSupports(this), "juggler-navigation-started-browser", NS_ConvertASCIItoUTF16(nsPrintfCString("%" PRIu64, loadState->GetLoadIdentifier())).get());
|
|
+ }
|
|
+ }
|
|
LoadURI(loadState, true);
|
|
}
|
|
|
|
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
|
|
index f3069febc1bd9f3ff6acbe162b5475963e004e6c..65ab560c9f13c837c9ed6af15704738700b0e14f 100644
|
|
--- 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"
|
|
@@ -66,6 +72,7 @@
|
|
#include "mozilla/dom/DocGroup.h"
|
|
#include "mozilla/dom/Element.h"
|
|
#include "mozilla/dom/FragmentDirective.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"
|
|
@@ -113,6 +121,7 @@
|
|
#include "nsIDocumentViewer.h"
|
|
#include "mozilla/dom/Document.h"
|
|
#include "nsHTMLDocument.h"
|
|
+#include "mozilla/dom/Element.h"
|
|
#include "nsIDocumentLoaderFactory.h"
|
|
#include "nsIDOMWindow.h"
|
|
#include "nsIEditingSession.h"
|
|
@@ -207,6 +216,7 @@
|
|
#include "nsGlobalWindowInner.h"
|
|
#include "nsGlobalWindowOuter.h"
|
|
#include "nsJSEnvironment.h"
|
|
+#include "nsJSUtils.h"
|
|
#include "nsNetCID.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsObjectLoadingContent.h"
|
|
@@ -347,6 +357,14 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
|
|
mAllowDNSPrefetch(true),
|
|
mAllowWindowControl(true),
|
|
mCSSErrorReportingEnabled(false),
|
|
+ mFileInputInterceptionEnabled(false),
|
|
+ mOverrideHasFocus(false),
|
|
+ mBypassCSPEnabled(false),
|
|
+ mForceActiveState(false),
|
|
+ mDisallowBFCache(false),
|
|
+ mReducedMotionOverride(REDUCED_MOTION_OVERRIDE_NONE),
|
|
+ mForcedColorsOverride(FORCED_COLORS_OVERRIDE_NO_OVERRIDE),
|
|
+ mContrastOverride(CONTRAST_OVERRIDE_NONE),
|
|
mAllowAuth(mItemType == typeContent),
|
|
mAllowKeywordFixup(false),
|
|
mDisableMetaRefreshWhenInactive(false),
|
|
@@ -3019,6 +3037,232 @@ nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) {
|
|
return NS_OK;
|
|
}
|
|
|
|
+// =============== Juggler Begin =======================
|
|
+
|
|
+nsDocShell* nsDocShell::GetRootDocShell() {
|
|
+ nsCOMPtr<nsIDocShellTreeItem> rootAsItem;
|
|
+ GetInProcessSameTypeRootTreeItem(getter_AddRefs(rootAsItem));
|
|
+ nsCOMPtr<nsIDocShell> rootShell = do_QueryInterface(rootAsItem);
|
|
+ return nsDocShell::Cast(rootShell);
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsDocShell::GetBypassCSPEnabled(bool* aEnabled) {
|
|
+ MOZ_ASSERT(aEnabled);
|
|
+ *aEnabled = mBypassCSPEnabled;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsDocShell::SetBypassCSPEnabled(bool aEnabled) {
|
|
+ mBypassCSPEnabled = aEnabled;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsDocShell::GetForceActiveState(bool* aEnabled) {
|
|
+ MOZ_ASSERT(aEnabled);
|
|
+ *aEnabled = mForceActiveState;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsDocShell::SetForceActiveState(bool aEnabled) {
|
|
+ mForceActiveState = aEnabled;
|
|
+ ActivenessMaybeChanged();
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsDocShell::GetDisallowBFCache(bool* aEnabled) {
|
|
+ MOZ_ASSERT(aEnabled);
|
|
+ *aEnabled = mDisallowBFCache;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsDocShell::SetDisallowBFCache(bool aEnabled) {
|
|
+ mDisallowBFCache = aEnabled;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+bool nsDocShell::IsBypassCSPEnabled() {
|
|
+ return GetRootDocShell()->mBypassCSPEnabled;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsDocShell::GetOverrideHasFocus(bool* aEnabled) {
|
|
+ MOZ_ASSERT(aEnabled);
|
|
+ *aEnabled = mOverrideHasFocus;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsDocShell::SetOverrideHasFocus(bool aEnabled) {
|
|
+ mOverrideHasFocus = aEnabled;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+bool nsDocShell::ShouldOverrideHasFocus() const {
|
|
+ return mOverrideHasFocus;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsDocShell::GetLanguageOverride(nsAString& aLanguageOverride) {
|
|
+ aLanguageOverride = GetRootDocShell()->mLanguageOverride;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+
|
|
+static void SetIcuLocale(const nsAString& aLanguageOverride) {
|
|
+ icu::Locale locale(NS_LossyConvertUTF16toASCII(aLanguageOverride).get());
|
|
+ if (icu::Locale::getDefault() != locale) {
|
|
+ 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::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;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsDocShell::GetContrastOverride(ContrastOverride* aContrastOverride) {
|
|
+ *aContrastOverride = GetRootDocShell()->mContrastOverride;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsDocShell::SetContrastOverride(ContrastOverride aContrastOverride) {
|
|
+ mContrastOverride = aContrastOverride;
|
|
+ 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;
|
|
@@ -4715,7 +4959,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();
|
|
}
|
|
@@ -6639,6 +6883,10 @@ bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
|
|
return false; // no entry to save into
|
|
}
|
|
|
|
+ if (mDisallowBFCache) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
MOZ_ASSERT(!mozilla::SessionHistoryInParent(),
|
|
"mOSHE cannot be non-null with SHIP");
|
|
nsCOMPtr<nsIDocumentViewer> viewer = mOSHE->GetDocumentViewer();
|
|
@@ -8377,6 +8625,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;
|
|
}
|
|
|
|
@@ -9531,6 +9785,16 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
|
|
nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
|
|
|
|
nsCOMPtr<nsIRequest> req;
|
|
+
|
|
+ // Juggler: report navigation started for non-same-document and non-javascript
|
|
+ // navigations.
|
|
+ if (!isJavaScript && !sameDocument) {
|
|
+ nsCOMPtr<nsIObserverService> observerService =
|
|
+ mozilla::services::GetObserverService();
|
|
+ if (observerService) {
|
|
+ observerService->NotifyObservers(GetAsSupports(this), "juggler-navigation-started-renderer", NS_ConvertASCIItoUTF16(nsPrintfCString("%" PRIu64, aLoadState->GetLoadIdentifier())).get());
|
|
+ }
|
|
+ }
|
|
rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
@@ -12733,6 +12997,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;
|
|
}
|
|
|
|
@@ -12819,6 +13086,8 @@ nsresult nsDocShell::OnLinkClick(
|
|
|
|
nsCOMPtr<nsIRunnable> ev = new OnLinkClickEvent(
|
|
this, aContent, loadState, noOpenerImplied, aTriggeringPrincipal);
|
|
+ nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
|
+ observerService->NotifyObservers(ToSupports(aContent), "juggler-link-click", nullptr);
|
|
return Dispatch(ev.forget());
|
|
}
|
|
|
|
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
|
|
index 888741f8490d6f0e885ed0ce73115c16e7bbe821..9cb32a1ec61bc4cb67f5fc5bb1fa723055bb1eaa 100644
|
|
--- a/docshell/base/nsDocShell.h
|
|
+++ b/docshell/base/nsDocShell.h
|
|
@@ -15,6 +15,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;
|
|
@@ -402,6 +404,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 CreateDocumentViewerForActor(
|
|
@@ -1005,6 +1016,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
|
|
@@ -1282,6 +1295,17 @@ class nsDocShell final : public nsDocLoader,
|
|
bool mAllowDNSPrefetch : 1;
|
|
bool mAllowWindowControl : 1;
|
|
bool mCSSErrorReportingEnabled : 1;
|
|
+ bool mFileInputInterceptionEnabled: 1;
|
|
+ bool mOverrideHasFocus : 1;
|
|
+ bool mBypassCSPEnabled : 1;
|
|
+ bool mForceActiveState : 1;
|
|
+ bool mDisallowBFCache : 1;
|
|
+ nsString mLanguageOverride;
|
|
+ RefPtr<nsGeolocationService> mGeolocationServiceOverride;
|
|
+ ReducedMotionOverride mReducedMotionOverride;
|
|
+ ForcedColorsOverride mForcedColorsOverride;
|
|
+ ContrastOverride mContrastOverride;
|
|
+
|
|
bool mAllowAuth : 1;
|
|
bool mAllowKeywordFixup : 1;
|
|
bool mDisableMetaRefreshWhenInactive : 1;
|
|
diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl
|
|
index 84e821e33e8164829dfee4f05340784e189b90ee..aa690eb747cb73bc6bff40a62546037c2e64c485 100644
|
|
--- a/docshell/base/nsIDocShell.idl
|
|
+++ b/docshell/base/nsIDocShell.idl
|
|
@@ -44,6 +44,7 @@ interface nsIURI;
|
|
interface nsIChannel;
|
|
interface nsIContentSecurityPolicy;
|
|
interface nsIDocumentViewer;
|
|
+interface nsIDOMGeoPosition;
|
|
interface nsIEditor;
|
|
interface nsIEditingSession;
|
|
interface nsIInputStream;
|
|
@@ -719,6 +720,45 @@ interface nsIDocShell : nsIDocShellTreeItem
|
|
*/
|
|
void synchronizeLayoutHistoryState();
|
|
|
|
+ attribute boolean fileInputInterceptionEnabled;
|
|
+
|
|
+ attribute boolean overrideHasFocus;
|
|
+
|
|
+ attribute boolean bypassCSPEnabled;
|
|
+
|
|
+ attribute boolean forceActiveState;
|
|
+
|
|
+ attribute boolean disallowBFCache;
|
|
+
|
|
+ attribute AString languageOverride;
|
|
+
|
|
+ boolean overrideTimezone(in AString timezoneId);
|
|
+
|
|
+ cenum 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;
|
|
+
|
|
+ cenum ContrastOverride : 8 {
|
|
+ CONTRAST_OVERRIDE_LESS,
|
|
+ CONTRAST_OVERRIDE_MORE,
|
|
+ CONTRAST_OVERRIDE_CUSTOM,
|
|
+ CONTRAST_OVERRIDE_NO_PREFERENCE,
|
|
+ CONTRAST_OVERRIDE_NONE, /* This clears the override. */
|
|
+ };
|
|
+ [infallible] attribute nsIDocShell_ContrastOverride contrastOverride;
|
|
+
|
|
+ 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 46de7024c0e148c5bc9b90553f0ab7c961acdaae..4ce29d24b940940ba7eefab60ac2be55bb888f78 100644
|
|
--- a/dom/base/Document.cpp
|
|
+++ b/dom/base/Document.cpp
|
|
@@ -3765,6 +3765,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
|
|
@@ -3822,6 +3825,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;
|
|
@@ -4629,6 +4637,10 @@ bool Document::HasFocus(ErrorResult& rv) const {
|
|
return false;
|
|
}
|
|
|
|
+ if (IsActive() && mDocumentContainer->ShouldOverrideHasFocus()) {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
if (!fm->IsInActiveWindow(bc)) {
|
|
return false;
|
|
}
|
|
@@ -19580,6 +19592,35 @@ ColorScheme Document::PreferredColorScheme(IgnoreRFP aIgnoreRFP) const {
|
|
return PreferenceSheet::PrefsFor(*this).mColorScheme;
|
|
}
|
|
|
|
+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:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return LookAndFeel::GetInt(LookAndFeel::IntID::PrefersReducedMotion, 0) == 1;
|
|
+}
|
|
+
|
|
bool Document::HasRecentlyStartedForegroundLoads() {
|
|
if (!sLoadingForegroundTopLevelContentDocument) {
|
|
return false;
|
|
diff --git a/dom/base/Document.h b/dom/base/Document.h
|
|
index 7eb244d65eb55322fb16ed185be83cb731fc268c..3cfb3c17c1a769e4d0fc3fa76288c570822dc48f 100644
|
|
--- a/dom/base/Document.h
|
|
+++ b/dom/base/Document.h
|
|
@@ -4134,6 +4134,8 @@ class Document : public nsINode,
|
|
// color-scheme meta tag.
|
|
ColorScheme DefaultColorScheme() const;
|
|
|
|
+ bool PrefersReducedMotion() const;
|
|
+
|
|
static bool HasRecentlyStartedForegroundLoads();
|
|
|
|
static bool AutomaticStorageAccessPermissionCanBeGranted(
|
|
diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp
|
|
index 0f159ad09a2a4b8962307b9f20abf30323377a36..e0cbb3f1f8af42825696d7152eb9993ab3802f90 100644
|
|
--- a/dom/base/Navigator.cpp
|
|
+++ b/dom/base/Navigator.cpp
|
|
@@ -344,14 +344,18 @@ void Navigator::GetAppName(nsAString& aAppName) 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 :
|
|
@@ -403,7 +407,13 @@ void Navigator::GetLanguage(nsAString& aLanguage) {
|
|
}
|
|
|
|
void Navigator::GetLanguages(nsTArray<nsString>& aLanguages) {
|
|
- GetAcceptLanguages(aLanguages);
|
|
+ if (mWindow && mWindow->GetDocShell()) {
|
|
+ nsString languageOverride;
|
|
+ mWindow->GetDocShell()->GetLanguageOverride(languageOverride);
|
|
+ GetAcceptLanguages(&languageOverride, aLanguages);
|
|
+ } else {
|
|
+ GetAcceptLanguages(nullptr, aLanguages);
|
|
+ }
|
|
|
|
// The returned value is cached by the binding code. The window listens to the
|
|
// accept languages change and will clear the cache when needed. It has to
|
|
@@ -2298,7 +2308,8 @@ bool Navigator::Webdriver() {
|
|
}
|
|
#endif
|
|
|
|
- return false;
|
|
+ // Playwright is automating the browser, so we should pretend to be a webdriver
|
|
+ return true;
|
|
}
|
|
|
|
AutoplayPolicy Navigator::GetAutoplayPolicy(AutoplayPolicyMediaType aType) {
|
|
diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h
|
|
index 6abf6cef230c97815f17f6b7abf9f1b1de274a6f..46ead1f32e0d710b5b32e61dff72a4f772d5421e 100644
|
|
--- a/dom/base/Navigator.h
|
|
+++ b/dom/base/Navigator.h
|
|
@@ -218,7 +218,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 3793f9845d12dc6d88604c43baca744fe559ed21..6f2ec74a8613b72be0ed27cb566bfdbc388a692b 100644
|
|
--- a/dom/base/nsContentUtils.cpp
|
|
+++ b/dom/base/nsContentUtils.cpp
|
|
@@ -8740,7 +8740,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, uint32_t aJugglerEventId) {
|
|
nsPoint offset;
|
|
nsCOMPtr<nsIWidget> widget = GetWidget(aPresShell, &offset);
|
|
if (!widget) return NS_ERROR_FAILURE;
|
|
@@ -8748,6 +8749,7 @@ nsresult nsContentUtils::SendMouseEvent(
|
|
EventMessage msg;
|
|
Maybe<WidgetMouseEvent::ExitFrom> exitFrom;
|
|
bool contextMenuKey = false;
|
|
+ bool isPWDragEventMessage = false;
|
|
if (aType.EqualsLiteral("mousedown")) {
|
|
msg = eMouseDown;
|
|
} else if (aType.EqualsLiteral("mouseup")) {
|
|
@@ -8773,6 +8775,12 @@ nsresult nsContentUtils::SendMouseEvent(
|
|
msg = eMouseHitTest;
|
|
} else if (aType.EqualsLiteral("MozMouseExploreByTouch")) {
|
|
msg = eMouseExploreByTouch;
|
|
+ } else if (aType.EqualsLiteral("dragover")) {
|
|
+ msg = eDragOver;
|
|
+ isPWDragEventMessage = true;
|
|
+ } else if (aType.EqualsLiteral("drop")) {
|
|
+ msg = eDrop;
|
|
+ isPWDragEventMessage = true;
|
|
} else {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
@@ -8783,7 +8791,14 @@ nsresult nsContentUtils::SendMouseEvent(
|
|
|
|
Maybe<WidgetPointerEvent> pointerEvent;
|
|
Maybe<WidgetMouseEvent> mouseEvent;
|
|
- if (IsPointerEventMessage(msg)) {
|
|
+ Maybe<WidgetDragEvent> pwDragEvent;
|
|
+
|
|
+ if (isPWDragEventMessage) {
|
|
+ pwDragEvent.emplace(true, msg, widget);
|
|
+ pwDragEvent->mReason = aIsWidgetEventSynthesized
|
|
+ ? WidgetMouseEvent::eSynthesized
|
|
+ : WidgetMouseEvent::eReal;
|
|
+ } else if (IsPointerEventMessage(msg)) {
|
|
MOZ_ASSERT(!aIsWidgetEventSynthesized,
|
|
"The event shouldn't be dispatched as a synthesized event");
|
|
if (MOZ_UNLIKELY(aIsWidgetEventSynthesized)) {
|
|
@@ -8802,8 +8817,11 @@ nsresult nsContentUtils::SendMouseEvent(
|
|
contextMenuKey ? WidgetMouseEvent::eContextMenuKey
|
|
: WidgetMouseEvent::eNormal);
|
|
}
|
|
+
|
|
WidgetMouseEvent& mouseOrPointerEvent =
|
|
+ pwDragEvent.isSome() ? pwDragEvent.ref() :
|
|
pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref();
|
|
+
|
|
mouseOrPointerEvent.pointerId = aIdentifier;
|
|
mouseOrPointerEvent.mModifiers = GetWidgetModifiers(aModifiers);
|
|
mouseOrPointerEvent.mButton = aButton;
|
|
@@ -8816,6 +8834,8 @@ nsresult nsContentUtils::SendMouseEvent(
|
|
mouseOrPointerEvent.mClickCount = aClickCount;
|
|
mouseOrPointerEvent.mFlags.mIsSynthesizedForTests = aIsDOMEventSynthesized;
|
|
mouseOrPointerEvent.mExitFrom = exitFrom;
|
|
+ mouseOrPointerEvent.mJugglerEventId = aJugglerEventId;
|
|
+ mouseOrPointerEvent.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 ed822f10425272124dd33a74d1cdac5011b1ba6a..0f29ce787f9cebc068d2e5faa9907d52b177283a 100644
|
|
--- a/dom/base/nsContentUtils.h
|
|
+++ b/dom/base/nsContentUtils.h
|
|
@@ -3019,7 +3019,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, uint32_t aJugglerEventId = 0);
|
|
|
|
static void FirePageShowEventForFrameLoaderSwap(
|
|
nsIDocShellTreeItem* aItem,
|
|
diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp
|
|
index fe23028691d0d06f6b036fd9da2c466730f58cb7..40cfc256510cbddea50574b531ce4369462fd956 100644
|
|
--- a/dom/base/nsDOMWindowUtils.cpp
|
|
+++ b/dom/base/nsDOMWindowUtils.cpp
|
|
@@ -710,6 +710,26 @@ nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
+static uint32_t sJugglerEventId = 1000;
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsDOMWindowUtils::JugglerSendMouseEvent(
|
|
+ const nsAString& aType, float aX, float aY, int32_t aButton,
|
|
+ int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame,
|
|
+ float aPressure, unsigned short aInputSourceArg,
|
|
+ bool aIsDOMEventSynthesized, bool aIsWidgetEventSynthesized,
|
|
+ int32_t aButtons, uint32_t aIdentifier, bool aDisablePointerEvent,
|
|
+ uint32_t* aJugglerEventId) {
|
|
+ *aJugglerEventId = ++sJugglerEventId;
|
|
+ return SendMouseEventCommon(
|
|
+ aType, aX, aY, aButton, aClickCount, aModifiers, aIgnoreRootScrollFrame,
|
|
+ aPressure, aInputSourceArg,
|
|
+ aIdentifier, false,
|
|
+ nullptr, aIsDOMEventSynthesized,
|
|
+ aIsWidgetEventSynthesized,
|
|
+ aButtons, !aDisablePointerEvent, *aJugglerEventId);
|
|
+}
|
|
+
|
|
NS_IMETHODIMP
|
|
nsDOMWindowUtils::SendMouseEvent(
|
|
const nsAString& aType, float aX, float aY, int32_t aButton,
|
|
@@ -724,7 +744,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, true, 0);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
@@ -742,7 +762,7 @@ nsDOMWindowUtils::SendMouseEventToWindow(
|
|
aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, true,
|
|
nullptr, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true,
|
|
aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false,
|
|
- aOptionalArgCount >= 6 ? aButtons : MOUSE_BUTTONS_NOT_SPECIFIED);
|
|
+ aOptionalArgCount >= 6 ? aButtons : MOUSE_BUTTONS_NOT_SPECIFIED, 0);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
@@ -751,13 +771,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, uint32_t aJugglerEventId) {
|
|
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, aJugglerEventId);
|
|
|
|
if (aPreventDefault) {
|
|
*aPreventDefault = preventDefaultResult != PreventDefaultResult::No;
|
|
diff --git a/dom/base/nsDOMWindowUtils.h b/dom/base/nsDOMWindowUtils.h
|
|
index 47ff326b202266b1d7d6af8bdfb72776df8a6a93..b8e084b0c788c46345b1455b8257f1719c851404 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, uint32_t aJugglerEventId = 0);
|
|
|
|
MOZ_CAN_RUN_SCRIPT
|
|
nsresult SendTouchEventCommon(
|
|
diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp
|
|
index a1d3ae3f3cb8d916a9a8bcca4cb515a2ab496ccb..72326b41064f6a86d76aba7b1902851e966365a8 100644
|
|
--- a/dom/base/nsFocusManager.cpp
|
|
+++ b/dom/base/nsFocusManager.cpp
|
|
@@ -1719,6 +1719,10 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
|
(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)) {
|
|
@@ -2304,6 +2308,7 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear,
|
|
bool aIsLeavingDocument, bool aAdjustWidget,
|
|
bool aRemainActive, Element* aElementToFocus,
|
|
uint64_t aActionId) {
|
|
+
|
|
LOGFOCUS(("<<Blur begin actionid: %" PRIu64 ">>", aActionId));
|
|
|
|
// hold a reference to the focused content, which may be null
|
|
@@ -2350,6 +2355,11 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear,
|
|
return true;
|
|
}
|
|
|
|
+ // Playwright: emulate focused page by never bluring when leaving document.
|
|
+ if (XRE_IsContentProcess() && aIsLeavingDocument && docShell && nsDocShell::Cast(docShell)->ShouldOverrideHasFocus()) {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
// Keep a ref to presShell since dispatching the DOM event may cause
|
|
// the document to be destroyed.
|
|
RefPtr<PresShell> presShell = docShell->GetPresShell();
|
|
@@ -3064,7 +3074,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 4d0483fb6cc4b7ed6cc9633c72413017e7b49249..9eb60397c94f567cc76fcbeec4585bf92b2fd0f7 100644
|
|
--- a/dom/base/nsGlobalWindowOuter.cpp
|
|
+++ b/dom/base/nsGlobalWindowOuter.cpp
|
|
@@ -2516,10 +2516,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));
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -2639,6 +2645,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) {
|
|
diff --git a/dom/base/nsGlobalWindowOuter.h b/dom/base/nsGlobalWindowOuter.h
|
|
index d4347e7a508742986f634e97394a9e3dd435d170..5088520537c8c5c6cc79c1dffd91a68de09f27eb 100644
|
|
--- a/dom/base/nsGlobalWindowOuter.h
|
|
+++ b/dom/base/nsGlobalWindowOuter.h
|
|
@@ -317,6 +317,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 4c1efbb1edf0e7d34a333e2724baf055eefa7e6e..c5d64fba742187c8ebaad8f45e868ab65722d07a 100644
|
|
--- a/dom/base/nsINode.cpp
|
|
+++ b/dom/base/nsINode.cpp
|
|
@@ -1437,6 +1437,61 @@ void nsINode::GetBoxQuadsFromWindowOrigin(const BoxQuadOptions& aOptions,
|
|
mozilla::GetBoxQuadsFromWindowOrigin(this, aOptions, aResult, aRv);
|
|
}
|
|
|
|
+static nsIFrame* GetFirstFrame(nsINode* aNode) {
|
|
+ if (!aNode->IsContent())
|
|
+ return nullptr;
|
|
+ nsIFrame* frame = aNode->AsContent()->GetPrimaryFrame(FlushType::Frames);
|
|
+ if (!frame) {
|
|
+ FlattenedChildIterator iter(aNode->AsContent());
|
|
+ for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
|
|
+ frame = child->GetPrimaryFrame(FlushType::Frames);
|
|
+ if (frame) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return frame;
|
|
+}
|
|
+
|
|
+void nsINode::ScrollRectIntoViewIfNeeded(int32_t x, int32_t y,
|
|
+ int32_t w, int32_t h,
|
|
+ ErrorResult& aRv) {
|
|
+ aRv = NS_ERROR_UNEXPECTED;
|
|
+ nsCOMPtr<Document> document = OwnerDoc();
|
|
+ if (!document) {
|
|
+ return aRv.ThrowNotFoundError("Node is detached from document");
|
|
+ }
|
|
+ PresShell* presShell = document->GetPresShell();
|
|
+ if (!presShell) {
|
|
+ return aRv.ThrowNotFoundError("Node is detached from document");
|
|
+ }
|
|
+ nsIFrame* primaryFrame = GetFirstFrame(this);
|
|
+ if (!primaryFrame) {
|
|
+ return aRv.ThrowNotFoundError("Node does not have a layout object");
|
|
+ }
|
|
+ aRv = NS_OK;
|
|
+ nsRect rect;
|
|
+ if (x == -1 && y == -1 && w == -1 && h == -1) {
|
|
+ rect = primaryFrame->GetRectRelativeToSelf();
|
|
+ } else {
|
|
+ rect = nsRect(nsPresContext::CSSPixelsToAppUnits(x),
|
|
+ nsPresContext::CSSPixelsToAppUnits(y),
|
|
+ nsPresContext::CSSPixelsToAppUnits(w),
|
|
+ nsPresContext::CSSPixelsToAppUnits(h));
|
|
+ }
|
|
+ presShell->ScrollFrameIntoView(
|
|
+ primaryFrame, Some(rect),
|
|
+ ScrollAxis(WhereToScroll::Center, WhenToScroll::IfNotFullyVisible),
|
|
+ ScrollAxis(WhereToScroll::Center, WhenToScroll::IfNotFullyVisible),
|
|
+ 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 e1fb6c2aeb67ab600b668b342bee0c716427d116..55e573dce8ad4d34542f89b9179a1da14f45d1bc 100644
|
|
--- a/dom/base/nsINode.h
|
|
+++ b/dom/base/nsINode.h
|
|
@@ -2356,6 +2356,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 bf7eb34da03c0958de688deecb53b407d430f645..a2ec3b1b7e86f72bee38d890c0834abfe4be8637 100644
|
|
--- a/dom/base/nsJSUtils.cpp
|
|
+++ b/dom/base/nsJSUtils.cpp
|
|
@@ -149,6 +149,11 @@ bool nsJSUtils::GetEnvironmentChainForElement(JSContext* aCx, Element* aElement,
|
|
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 f32e21752d5013bf143eb45391ab9218debab08e..83763d2354dade2f8d2b7930ba18ae91c55133ad 100644
|
|
--- a/dom/base/nsJSUtils.h
|
|
+++ b/dom/base/nsJSUtils.h
|
|
@@ -75,6 +75,7 @@ class nsJSUtils {
|
|
mozilla::dom::Element* aElement,
|
|
JS::EnvironmentChain& aEnvChain);
|
|
|
|
+ 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 28e8d8cb9c61ff8362b2d191d47c3630d2cb0b34..58c12d597978100507dbc21e88c49c5642a3ba1f 100644
|
|
--- a/dom/chrome-webidl/BrowsingContext.webidl
|
|
+++ b/dom/chrome-webidl/BrowsingContext.webidl
|
|
@@ -61,6 +61,26 @@ enum ForcedColorsOverride {
|
|
"active",
|
|
};
|
|
|
|
+/**
|
|
+ * CSS prefers-reduced-motion values.
|
|
+ */
|
|
+enum PrefersReducedMotionOverride {
|
|
+ "none",
|
|
+ "reduce",
|
|
+ "no-preference",
|
|
+};
|
|
+
|
|
+/**
|
|
+ * CSS prefers-contrast values.
|
|
+ */
|
|
+enum PrefersContrastOverride {
|
|
+ "none",
|
|
+ "no-preference",
|
|
+ "more",
|
|
+ "less",
|
|
+ "custom",
|
|
+};
|
|
+
|
|
/**
|
|
* Allowed overrides of platform/pref default behaviour for touch events.
|
|
*/
|
|
@@ -220,6 +240,12 @@ interface BrowsingContext {
|
|
// Forced-colors simulation, for DevTools
|
|
[SetterThrows] attribute ForcedColorsOverride forcedColorsOverride;
|
|
|
|
+ // Reduced-Motion simulation, for DevTools.
|
|
+ [SetterThrows] attribute PrefersReducedMotionOverride prefersReducedMotionOverride;
|
|
+
|
|
+ // Contrast simulation, for DevTools.
|
|
+ [SetterThrows] attribute PrefersContrastOverride prefersContrastOverride;
|
|
+
|
|
/**
|
|
* 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/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp
|
|
index a030f3f07b9f4a676f87ac482507056bc911edf5..68bd39affdbbe2e35fdac62b1e159ebc7ffd031c 100644
|
|
--- a/dom/fetch/Fetch.cpp
|
|
+++ b/dom/fetch/Fetch.cpp
|
|
@@ -689,6 +689,12 @@ already_AddRefed<Promise> FetchRequest(nsIGlobalObject* aGlobal,
|
|
ipcArgs.hasCSPEventListener() = false;
|
|
ipcArgs.isWorkerRequest() = false;
|
|
|
|
+ /* --> Playwright: associate keep-alive fetch with the window */
|
|
+ BrowsingContext* bc = window ? window->GetBrowsingContext() : nullptr;
|
|
+ if (bc)
|
|
+ ipcArgs.associatedBrowsingContextID() = bc->Id();
|
|
+ /* <-- Playwright */
|
|
+
|
|
actor->DoFetchOp(ipcArgs);
|
|
|
|
mozilla::glean::networking::fetch_keepalive_request_count.Get("main"_ns)
|
|
diff --git a/dom/fetch/FetchService.cpp b/dom/fetch/FetchService.cpp
|
|
index 6fc05bf6cc8341e7cfac63789b79f610bdbe9641..112db3c2e6d2f854103ddacde896904018f5ea90 100644
|
|
--- a/dom/fetch/FetchService.cpp
|
|
+++ b/dom/fetch/FetchService.cpp
|
|
@@ -265,6 +265,14 @@ RefPtr<FetchServicePromises> FetchService::FetchInstance::Fetch() {
|
|
false // IsTrackingFetch
|
|
);
|
|
|
|
+ /* --> Playwright: associate keep-alive fetch with the window */
|
|
+ if (mArgsType == FetchArgsType::MainThreadFetch) {
|
|
+ auto& args = mArgs.as<MainThreadFetchArgs>();
|
|
+ mFetchDriver->SetAssociatedBrowsingContextID(
|
|
+ args.mAssociatedBrowsingContextID);
|
|
+ }
|
|
+ /* <-- Playwright */
|
|
+
|
|
if (mArgsType == FetchArgsType::WorkerFetch) {
|
|
auto& args = mArgs.as<WorkerFetchArgs>();
|
|
mFetchDriver->SetWorkerScript(args.mWorkerScript);
|
|
diff --git a/dom/geolocation/Geolocation.cpp b/dom/geolocation/Geolocation.cpp
|
|
index e67cb4efce43b42fa876c906f7f1927c65d34ea7..a42da20dc6aaa1915c611d4bc339a8db974c75eb 100644
|
|
--- a/dom/geolocation/Geolocation.cpp
|
|
+++ b/dom/geolocation/Geolocation.cpp
|
|
@@ -29,6 +29,7 @@
|
|
#include "nsComponentManagerUtils.h"
|
|
#include "nsContentPermissionHelper.h"
|
|
#include "nsContentUtils.h"
|
|
+#include "nsDocShell.h"
|
|
#include "nsGlobalWindowInner.h"
|
|
#include "mozilla/dom/Document.h"
|
|
#include "nsINamed.h"
|
|
@@ -429,10 +430,8 @@ nsGeolocationRequest::Allow(JS::Handle<JS::Value> aChoices) {
|
|
return NS_OK;
|
|
}
|
|
|
|
- RefPtr<nsGeolocationService> gs =
|
|
- nsGeolocationService::GetGeolocationService();
|
|
-
|
|
- bool canUseCache = false;
|
|
+ nsGeolocationService* gs = mLocator->GetGeolocationService();
|
|
+ bool canUseCache = gs != nsGeolocationService::sService.get();
|
|
CachedPositionAndAccuracy lastPosition = gs->GetCachedPosition();
|
|
if (lastPosition.position) {
|
|
EpochTimeStamp cachedPositionTime_ms;
|
|
@@ -640,8 +639,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();
|
|
}
|
|
@@ -958,8 +956,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;
|
|
|
|
@@ -1051,7 +1055,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 992de29b5d2d09c19e55ebb2502215ec9d05a171..cdc20567b693283b0fd5a5923f7ea54210bd1712 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;
|
|
@@ -51,13 +52,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
|
|
@@ -189,6 +191,8 @@ class Geolocation final : public nsIGeolocationUpdate, public nsWrapperCache {
|
|
BrowsingContext* aBrowsingContext,
|
|
geolocation::ParentRequestResolver&& aResolver);
|
|
|
|
+ nsGeolocationService* GetGeolocationService() { return mService; };
|
|
+
|
|
private:
|
|
~Geolocation();
|
|
|
|
diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
|
|
index 2e6ef116be73d0794683189c07afc8a629859154..33f4add0cb7736edd416d31d0feca4fd5afc4526 100644
|
|
--- a/dom/html/HTMLInputElement.cpp
|
|
+++ b/dom/html/HTMLInputElement.cpp
|
|
@@ -64,6 +64,7 @@
|
|
#include "mozilla/dom/Document.h"
|
|
#include "mozilla/dom/HTMLDataListElement.h"
|
|
#include "mozilla/dom/HTMLOptionElement.h"
|
|
+#include "nsDocShell.h"
|
|
#include "nsIFrame.h"
|
|
#include "nsRangeFrame.h"
|
|
#include "nsError.h"
|
|
@@ -789,6 +790,13 @@ nsresult HTMLInputElement::InitFilePicker(FilePickerType aType) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
+ nsCOMPtr<nsPIDOMWindowOuter> win = doc->GetWindow();
|
|
+ nsDocShell* docShell = win ? static_cast<nsDocShell*>(win->GetDocShell()) : nullptr;
|
|
+ if (docShell && docShell->IsFileInputInterceptionEnabled()) {
|
|
+ docShell->FilePickerShown(this);
|
|
+ return NS_OK;
|
|
+ }
|
|
+
|
|
if (IsPickerBlocked(doc)) {
|
|
return NS_OK;
|
|
}
|
|
diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl
|
|
index 8ddde6e5de319142ce0898dc3667c08f1f24cce9..9e530a727f06b924e3d0bcf4ba52507231778257 100644
|
|
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
|
|
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
|
|
@@ -374,6 +374,26 @@ interface nsIDOMWindowUtils : nsISupports {
|
|
[optional] in long aButtons,
|
|
[optional] in unsigned long aIdentifier);
|
|
|
|
+ /**
|
|
+ * Playwright: a separate method to dispatch mouse event with a
|
|
+ * specific `jugglerEventId`.
|
|
+ */
|
|
+ [can_run_script]
|
|
+ unsigned long jugglerSendMouseEvent(in AString aType,
|
|
+ in float aX,
|
|
+ in float aY,
|
|
+ in long aButton,
|
|
+ in long aClickCount,
|
|
+ in long aModifiers,
|
|
+ in boolean aIgnoreRootScrollFrame,
|
|
+ in float aPressure,
|
|
+ in unsigned short aInputSourceArg,
|
|
+ in boolean aIsDOMEventSynthesized,
|
|
+ in boolean aIsWidgetEventSynthesized,
|
|
+ in long aButtons,
|
|
+ in unsigned long aIdentifier,
|
|
+ in boolean aDisablePointerEvent);
|
|
+
|
|
/** Synthesize a touch event. The event types supported are:
|
|
* touchstart, touchend, touchmove, and touchcancel
|
|
*
|
|
diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp
|
|
index 93f20a36acef74947d5377df5ff916546218d8b8..22b706b985d22a8c0c278a12ab4944e26ded51a4 100644
|
|
--- a/dom/ipc/BrowserChild.cpp
|
|
+++ b/dom/ipc/BrowserChild.cpp
|
|
@@ -1676,6 +1676,21 @@ void BrowserChild::HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
|
|
if (postLayerization) {
|
|
postLayerization->Register();
|
|
}
|
|
+
|
|
+ // Playwright: notify content that mouse event has been received and handled.
|
|
+ nsCOMPtr<nsIObserverService> observerService =
|
|
+ mozilla::services::GetObserverService();
|
|
+ if (observerService && aEvent.mJugglerEventId) {
|
|
+ if (aEvent.mMessage == eMouseUp) {
|
|
+ observerService->NotifyObservers(nullptr, "juggler-mouse-event-hit-renderer", NS_ConvertASCIItoUTF16(nsPrintfCString("mouseup %" PRIu32, aEvent.mJugglerEventId)).get());
|
|
+ } else if (aEvent.mMessage == eMouseDown) {
|
|
+ observerService->NotifyObservers(nullptr, "juggler-mouse-event-hit-renderer", NS_ConvertASCIItoUTF16(nsPrintfCString("mousedown %" PRIu32, aEvent.mJugglerEventId)).get());
|
|
+ } else if (aEvent.mMessage == eMouseMove) {
|
|
+ observerService->NotifyObservers(nullptr, "juggler-mouse-event-hit-renderer", NS_ConvertASCIItoUTF16(nsPrintfCString("mousemove %" PRIu32, aEvent.mJugglerEventId)).get());
|
|
+ } else if (aEvent.mMessage == eContextMenu) {
|
|
+ observerService->NotifyObservers(nullptr, "juggler-mouse-event-hit-renderer", NS_ConvertASCIItoUTF16(nsPrintfCString("contextmenu %" PRIu32, aEvent.mJugglerEventId)).get());
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
mozilla::ipc::IPCResult BrowserChild::RecvNormalPriorityRealMouseButtonEvent(
|
|
diff --git a/dom/ipc/CoalescedMouseData.cpp b/dom/ipc/CoalescedMouseData.cpp
|
|
index 5aa445d2e0a6169e57c44569974d557b3baf7064..671f71979b407f0ca17c66f13805e851ba30479e 100644
|
|
--- a/dom/ipc/CoalescedMouseData.cpp
|
|
+++ b/dom/ipc/CoalescedMouseData.cpp
|
|
@@ -67,6 +67,9 @@ bool CoalescedMouseData::CanCoalesce(const WidgetMouseEvent& aEvent,
|
|
mCoalescedInputEvent->pointerId == aEvent.pointerId &&
|
|
mCoalescedInputEvent->mButton == aEvent.mButton &&
|
|
mCoalescedInputEvent->mButtons == aEvent.mButtons && mGuid == aGuid &&
|
|
+ // `mJugglerEventId` is 0 for non-juggler events and a unique number for
|
|
+ // juggler-emitted events.
|
|
+ mCoalescedInputEvent->mJugglerEventId == aEvent.mJugglerEventId &&
|
|
mInputBlockId == aInputBlockId);
|
|
}
|
|
|
|
diff --git a/dom/media/systemservices/video_engine/desktop_capture_impl.cc b/dom/media/systemservices/video_engine/desktop_capture_impl.cc
|
|
index c43a1b3b245101c974742c5e50f54857e538bbfb..c07a568da3342cbf2af07471fa6959cb242b9a4e 100644
|
|
--- a/dom/media/systemservices/video_engine/desktop_capture_impl.cc
|
|
+++ b/dom/media/systemservices/video_engine/desktop_capture_impl.cc
|
|
@@ -52,9 +52,10 @@ namespace webrtc {
|
|
|
|
DesktopCaptureImpl* DesktopCaptureImpl::Create(const int32_t aModuleId,
|
|
const char* aUniqueId,
|
|
- const CaptureDeviceType aType) {
|
|
+ const CaptureDeviceType aType,
|
|
+ bool aCaptureCursor) {
|
|
return new rtc::RefCountedObject<DesktopCaptureImpl>(aModuleId, aUniqueId,
|
|
- aType);
|
|
+ aType, aCaptureCursor);
|
|
}
|
|
|
|
static DesktopCaptureOptions CreateDesktopCaptureOptions() {
|
|
@@ -155,8 +156,10 @@ static std::unique_ptr<DesktopCapturer> CreateTabCapturer(
|
|
|
|
static std::unique_ptr<DesktopCapturer> CreateDesktopCapturerAndThread(
|
|
CaptureDeviceType aDeviceType, DesktopCapturer::SourceId aSourceId,
|
|
- nsIThread** aOutThread) {
|
|
+ nsIThread** aOutThread, bool aCaptureCursor) {
|
|
DesktopCaptureOptions options = CreateDesktopCaptureOptions();
|
|
+ if (aCaptureCursor)
|
|
+ options.set_prefer_cursor_embedded(aCaptureCursor);
|
|
auto ensureThread = [&]() {
|
|
if (*aOutThread) {
|
|
return *aOutThread;
|
|
@@ -253,7 +256,8 @@ static std::unique_ptr<DesktopCapturer> CreateDesktopCapturerAndThread(
|
|
}
|
|
|
|
DesktopCaptureImpl::DesktopCaptureImpl(const int32_t aId, const char* aUniqueId,
|
|
- const CaptureDeviceType aType)
|
|
+ const CaptureDeviceType aType,
|
|
+ bool aCaptureCursor)
|
|
: mModuleId(aId),
|
|
mTrackingId(mozilla::TrackingId(CaptureEngineToTrackingSourceStr([&] {
|
|
switch (aType) {
|
|
@@ -270,6 +274,7 @@ DesktopCaptureImpl::DesktopCaptureImpl(const int32_t aId, const char* aUniqueId,
|
|
aId)),
|
|
mDeviceUniqueId(aUniqueId),
|
|
mDeviceType(aType),
|
|
+ capture_cursor_(aCaptureCursor),
|
|
mControlThread(mozilla::GetCurrentSerialEventTarget()),
|
|
mNextFrameMinimumTime(Timestamp::Zero()),
|
|
mCallbacks("DesktopCaptureImpl::mCallbacks") {}
|
|
@@ -294,6 +299,19 @@ void DesktopCaptureImpl::DeRegisterCaptureDataCallback(
|
|
}
|
|
}
|
|
|
|
+void DesktopCaptureImpl::RegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) {
|
|
+ rtc::CritScope lock(&mApiCs);
|
|
+ _rawFrameCallbacks.insert(rawFrameCallback);
|
|
+}
|
|
+
|
|
+void DesktopCaptureImpl::DeRegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) {
|
|
+ rtc::CritScope lock(&mApiCs);
|
|
+ auto it = _rawFrameCallbacks.find(rawFrameCallback);
|
|
+ if (it != _rawFrameCallbacks.end()) {
|
|
+ _rawFrameCallbacks.erase(it);
|
|
+ }
|
|
+}
|
|
+
|
|
int32_t DesktopCaptureImpl::StopCaptureIfAllClientsClose() {
|
|
{
|
|
auto callbacks = mCallbacks.Lock();
|
|
@@ -333,7 +351,7 @@ int32_t DesktopCaptureImpl::StartCapture(
|
|
|
|
DesktopCapturer::SourceId sourceId = std::stoi(mDeviceUniqueId);
|
|
std::unique_ptr capturer = CreateDesktopCapturerAndThread(
|
|
- mDeviceType, sourceId, getter_AddRefs(mCaptureThread));
|
|
+ mDeviceType, sourceId, getter_AddRefs(mCaptureThread), capture_cursor_);
|
|
|
|
MOZ_ASSERT(!capturer == !mCaptureThread);
|
|
if (!capturer) {
|
|
@@ -441,6 +459,15 @@ void DesktopCaptureImpl::OnCaptureResult(DesktopCapturer::Result aResult,
|
|
frameInfo.height = aFrame->size().height();
|
|
frameInfo.videoType = VideoType::kARGB;
|
|
|
|
+ size_t videoFrameStride =
|
|
+ frameInfo.width * DesktopFrame::kBytesPerPixel;
|
|
+ {
|
|
+ rtc::CritScope cs(&mApiCs);
|
|
+ for (auto rawFrameCallback : _rawFrameCallbacks) {
|
|
+ rawFrameCallback->OnRawFrame(videoFrame, videoFrameStride, frameInfo);
|
|
+ }
|
|
+ }
|
|
+
|
|
size_t videoFrameLength =
|
|
frameInfo.width * frameInfo.height * DesktopFrame::kBytesPerPixel;
|
|
|
|
diff --git a/dom/media/systemservices/video_engine/desktop_capture_impl.h b/dom/media/systemservices/video_engine/desktop_capture_impl.h
|
|
index a76b7de569db1cb42728a5514fb80e5c46e0344e..3d61ad8d3aa4a7eaf96957dcd680e1e1ee8abdf4 100644
|
|
--- a/dom/media/systemservices/video_engine/desktop_capture_impl.h
|
|
+++ b/dom/media/systemservices/video_engine/desktop_capture_impl.h
|
|
@@ -26,6 +26,7 @@
|
|
#include "api/video/video_sink_interface.h"
|
|
#include "modules/desktop_capture/desktop_capturer.h"
|
|
#include "modules/video_capture/video_capture.h"
|
|
+#include "rtc_base/deprecated/recursive_critical_section.h"
|
|
#include "mozilla/DataMutex.h"
|
|
#include "mozilla/Maybe.h"
|
|
#include "mozilla/TimeStamp.h"
|
|
@@ -42,17 +43,44 @@ 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;
|
|
+ int32_t StartCaptureCounted(const VideoCaptureCapability& aCapability) {
|
|
+ ++capture_counter_;
|
|
+ return capture_counter_ == 1 ? StartCapture(aCapability) : 0;
|
|
+ }
|
|
+
|
|
+ int32_t StopCaptureCounted() {
|
|
+ --capture_counter_;
|
|
+ return capture_counter_ == 0 ? StopCapture() : 0;
|
|
+ }
|
|
+
|
|
+ private:
|
|
+ int32_t capture_counter_ = 0;
|
|
+};
|
|
+
|
|
// Reuses the video engine pipeline for screen sharing.
|
|
// 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 DesktopCaptureImpl* Create(
|
|
const int32_t aModuleId, const char* aUniqueId,
|
|
- const mozilla::camera::CaptureDeviceType aType);
|
|
+ const mozilla::camera::CaptureDeviceType aType, bool aCaptureCursor = true);
|
|
|
|
[[nodiscard]] static std::shared_ptr<VideoCaptureModule::DeviceInfo>
|
|
CreateDeviceInfo(const int32_t aId,
|
|
@@ -66,6 +94,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
|
void DeRegisterCaptureDataCallback(
|
|
rtc::VideoSinkInterface<VideoFrame>* aCallback) override;
|
|
int32_t StopCaptureIfAllClientsClose() override;
|
|
+ void RegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) override;
|
|
+ void DeRegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) override;
|
|
|
|
int32_t SetCaptureRotation(VideoRotation aRotation) override;
|
|
bool SetApplyRotation(bool aEnable) override;
|
|
@@ -89,7 +119,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
|
|
|
protected:
|
|
DesktopCaptureImpl(const int32_t aId, const char* aUniqueId,
|
|
- const mozilla::camera::CaptureDeviceType aType);
|
|
+ const mozilla::camera::CaptureDeviceType aType,
|
|
+ bool aCaptureCusor);
|
|
virtual ~DesktopCaptureImpl();
|
|
|
|
private:
|
|
@@ -98,6 +129,9 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
|
void InitOnThread(std::unique_ptr<DesktopCapturer> aCapturer, int aFramerate);
|
|
void UpdateOnThread(int aFramerate);
|
|
void ShutdownOnThread();
|
|
+
|
|
+ rtc::RecursiveCriticalSection mApiCs;
|
|
+ std::set<RawFrameCallback*> _rawFrameCallbacks;
|
|
// DesktopCapturer::Callback interface.
|
|
void OnCaptureResult(DesktopCapturer::Result aResult,
|
|
std::unique_ptr<DesktopFrame> aFrame) override;
|
|
@@ -105,6 +139,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
|
// Notifies all mCallbacks of OnFrame(). mCaptureThread only.
|
|
void NotifyOnFrame(const VideoFrame& aFrame);
|
|
|
|
+ bool capture_cursor_ = true;
|
|
+
|
|
// Control thread on which the public API is called.
|
|
const nsCOMPtr<nsISerialEventTarget> mControlThread;
|
|
// Set in StartCapture.
|
|
diff --git a/dom/script/ScriptSettings.cpp b/dom/script/ScriptSettings.cpp
|
|
index 3b39538e51840cd9b1685b2efd2ff2e9ec83608a..c7bf4f2d53b58bbacb22b3ebebf6f3fc9b5e445f 100644
|
|
--- a/dom/script/ScriptSettings.cpp
|
|
+++ b/dom/script/ScriptSettings.cpp
|
|
@@ -150,6 +150,30 @@ ScriptSettingsStackEntry::~ScriptSettingsStackEntry() {
|
|
MOZ_ASSERT_IF(mGlobalObject, mGlobalObject->HasJSGlobal());
|
|
}
|
|
|
|
+static nsIGlobalObject* UnwrapSandboxGlobal(nsIGlobalObject* global) {
|
|
+ if (!global)
|
|
+ return global;
|
|
+ JSObject* globalObject = global->GetGlobalJSObject();
|
|
+ if (!globalObject)
|
|
+ return global;
|
|
+ JSContext* cx = nsContentUtils::GetCurrentJSContext();
|
|
+ if (!cx)
|
|
+ return global;
|
|
+ JS::Rooted<JSObject*> proto(cx);
|
|
+ JS::RootedObject rootedGlobal(cx, globalObject);
|
|
+ if (!JS_GetPrototype(cx, rootedGlobal, &proto))
|
|
+ return global;
|
|
+ if (!proto || !xpc::IsSandboxPrototypeProxy(proto))
|
|
+ return global;
|
|
+ // If this is a sandbox associated with a DOMWindow via a
|
|
+ // sandboxPrototype, use that DOMWindow. This supports GreaseMonkey
|
|
+ // and JetPack content scripts.
|
|
+ proto = js::CheckedUnwrapDynamic(proto, cx, /* stopAtWindowProxy = */ false);
|
|
+ if (!proto)
|
|
+ return global;
|
|
+ return xpc::WindowGlobalOrNull(proto);
|
|
+}
|
|
+
|
|
// If the entry or incumbent global ends up being something that the subject
|
|
// principal doesn't subsume, we don't want to use it. This never happens on
|
|
// the web, but can happen with asymmetric privilege relationships (i.e.
|
|
@@ -177,7 +201,7 @@ static nsIGlobalObject* ClampToSubject(nsIGlobalObject* aGlobalOrNull) {
|
|
NS_ENSURE_TRUE(globalPrin, GetCurrentGlobal());
|
|
if (!nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller()
|
|
->SubsumesConsideringDomain(globalPrin)) {
|
|
- return GetCurrentGlobal();
|
|
+ return UnwrapSandboxGlobal(GetCurrentGlobal());
|
|
}
|
|
|
|
return aGlobalOrNull;
|
|
diff --git a/dom/security/nsCSPUtils.cpp b/dom/security/nsCSPUtils.cpp
|
|
index 32a8d9496e674e752dd3ac41afc7f22ed534dce3..e57690654be4ae18f14d3171fa4eab9ec8aa991f 100644
|
|
--- a/dom/security/nsCSPUtils.cpp
|
|
+++ b/dom/security/nsCSPUtils.cpp
|
|
@@ -23,6 +23,7 @@
|
|
#include "nsSandboxFlags.h"
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "nsWhitespaceTokenizer.h"
|
|
+#include "nsDocShell.h"
|
|
|
|
#include "mozilla/Assertions.h"
|
|
#include "mozilla/Components.h"
|
|
@@ -134,6 +135,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 aee376e971ae01ac1e512c3920b115bfaf06afa8..1701311534bf77e6cd9bafc0e3a283610476aa8f 100644
|
|
--- a/dom/webidl/GeometryUtils.webidl
|
|
+++ b/dom/webidl/GeometryUtils.webidl
|
|
@@ -17,6 +17,8 @@ dictionary GeometryUtilsOptions {
|
|
boolean createFramesForSuppressedWhitespace = true;
|
|
[ChromeOnly]
|
|
boolean flush = true;
|
|
+ [ChromeOnly]
|
|
+ boolean recurseWhenNoFrame = false;
|
|
};
|
|
|
|
dictionary BoxQuadOptions : GeometryUtilsOptions {
|
|
@@ -35,6 +37,9 @@ interface mixin GeometryUtils {
|
|
[Throws, Func="nsINode::HasBoxQuadsSupport", NeedsCallerType]
|
|
sequence<DOMQuad> getBoxQuads(optional BoxQuadOptions options = {});
|
|
|
|
+ [ChromeOnly, Throws, Func="nsINode::HasBoxQuadsSupport"]
|
|
+ undefined scrollRectIntoViewIfNeeded(long x, long y, long w, long h);
|
|
+
|
|
/* getBoxQuadsFromWindowOrigin is similar to getBoxQuads, but the
|
|
* returned quads are further translated relative to the window
|
|
* origin -- which is not the layout origin. Further translation
|
|
diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp
|
|
index f528bec20afef533e4c6b99c5e9d1680fd0b636e..a0d22d38657f672d865f35c02975e7b611571353 100644
|
|
--- a/dom/workers/RuntimeService.cpp
|
|
+++ b/dom/workers/RuntimeService.cpp
|
|
@@ -1027,7 +1027,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) {
|
|
@@ -1215,8 +1215,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;
|
|
}
|
|
|
|
@@ -1837,6 +1836,13 @@ void RuntimeService::PropagateStorageAccessPermissionGranted(
|
|
}
|
|
}
|
|
|
|
+void RuntimeService::ResetDefaultLocaleInAllWorkers() {
|
|
+ AssertIsOnMainThread();
|
|
+ BroadcastAllWorkers([](auto& worker) {
|
|
+ worker.ResetDefaultLocale();
|
|
+ });
|
|
+}
|
|
+
|
|
template <typename Func>
|
|
void RuntimeService::BroadcastAllWorkers(const Func& aFunc) {
|
|
AssertIsOnMainThread();
|
|
@@ -2362,6 +2368,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 534bbe9ec4f0261189eb3322c1229c1eb5d8802e..6aa99b64fdbbff3704602e944b129879fbdf8c15 100644
|
|
--- a/dom/workers/RuntimeService.h
|
|
+++ b/dom/workers/RuntimeService.h
|
|
@@ -112,6 +112,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 58894a8361c7ef1dddd481ca5877a209a8b8ff5c..c481d40d79b6397b7f1d571bd9f6ae5c0a946217 100644
|
|
--- a/dom/workers/WorkerCommon.h
|
|
+++ b/dom/workers/WorkerCommon.h
|
|
@@ -47,6 +47,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 0076a8463fa9ff05b32edfe21462987610432b5d..9f810c9728b7d7caf9fbeb3e24346c219326637d 100644
|
|
--- a/dom/workers/WorkerPrivate.cpp
|
|
+++ b/dom/workers/WorkerPrivate.cpp
|
|
@@ -736,6 +736,18 @@ class UpdateContextOptionsRunnable final : public WorkerControlRunnable {
|
|
}
|
|
};
|
|
|
|
+class ResetDefaultLocaleRunnable final : public WorkerControlRunnable {
|
|
+ public:
|
|
+ explicit ResetDefaultLocaleRunnable(WorkerPrivate* aWorkerPrivate)
|
|
+ : WorkerControlRunnable("ResetDefaultLocaleRunnable") {}
|
|
+
|
|
+ virtual bool WorkerRun(JSContext* aCx,
|
|
+ WorkerPrivate* aWorkerPrivate) override {
|
|
+ aWorkerPrivate->ResetDefaultLocaleInternal(aCx);
|
|
+ return true;
|
|
+ }
|
|
+};
|
|
+
|
|
class UpdateLanguagesRunnable final : public WorkerThreadRunnable {
|
|
nsTArray<nsString> mLanguages;
|
|
|
|
@@ -2149,6 +2161,16 @@ void WorkerPrivate::UpdateContextOptions(
|
|
}
|
|
}
|
|
|
|
+void WorkerPrivate::ResetDefaultLocale() {
|
|
+ AssertIsOnParentThread();
|
|
+
|
|
+ RefPtr<ResetDefaultLocaleRunnable> runnable =
|
|
+ new ResetDefaultLocaleRunnable(this);
|
|
+ if (!runnable->Dispatch(this)) {
|
|
+ NS_WARNING("Failed to reset default locale in worker!");
|
|
+ }
|
|
+}
|
|
+
|
|
void WorkerPrivate::UpdateLanguages(const nsTArray<nsString>& aLanguages) {
|
|
AssertIsOnParentThread();
|
|
|
|
@@ -5833,6 +5855,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 c2ade467934d08587d4e3589b310c6302534d699..414814c03180b50d218ad84a0db262fff19f78a7 100644
|
|
--- a/dom/workers/WorkerPrivate.h
|
|
+++ b/dom/workers/WorkerPrivate.h
|
|
@@ -443,6 +443,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,
|
|
@@ -1086,6 +1088,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 7a069ef0c59895cf1f8dc35d612f1494c9c9f1ef..5b09dfdcc5323def65c35b0696141b44eef9dcda 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) {
|
|
@@ -318,6 +319,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 89770839ae108b5f3462a7f20684fdb72c4ab2fb..a7e40d6b7c33c234b41e586eac573ba4ce3a7d18 100644
|
|
--- a/intl/components/src/TimeZone.h
|
|
+++ b/intl/components/src/TimeZone.h
|
|
@@ -191,6 +191,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 523e84c8c93f4221701f90f2e8ee146ec8e1adbd..98d5b1176e5378431b859a2dbd4d4e778d236e78 100644
|
|
--- a/js/public/Date.h
|
|
+++ b/js/public/Date.h
|
|
@@ -55,6 +55,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 880e716c24464c93283410417f8e69d6d233d105..6e046fbd2e643dace5ad7796740253df3ddf2cbe 100644
|
|
--- a/js/src/debugger/Object.cpp
|
|
+++ b/js/src/debugger/Object.cpp
|
|
@@ -2474,7 +2474,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 cf63b124f39223a1a42c322dcc0ad108947d54f5..9e3a7b757cbad57ee6cfe2254d0355f62f7c8662 100644
|
|
--- a/js/src/vm/DateTime.cpp
|
|
+++ b/js/src/vm/DateTime.cpp
|
|
@@ -185,6 +185,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);
|
|
|
|
@@ -528,10 +533,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) {
|
|
@@ -749,6 +768,15 @@ static bool ReadTimeZoneLink(std::string_view tz,
|
|
|
|
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;
|
|
+ }
|
|
+
|
|
// In the future we should not be setting a default ICU time zone at all,
|
|
// instead all accesses should go through the appropriate DateTimeInfo
|
|
// instance depending on the resist fingerprinting status. For now we return
|
|
@@ -760,7 +788,6 @@ void js::DateTimeInfo::internalResyncICUDefaultTimeZone() {
|
|
|
|
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 e3cf82daa3749664aa8ced7e6553b8c6434dfec8..b45b49c4f3bbf12853c4afb12de21d99ac88d77b 100644
|
|
--- a/js/src/vm/DateTime.h
|
|
+++ b/js/src/vm/DateTime.h
|
|
@@ -65,6 +65,8 @@ enum class ResetTimeZoneMode : bool {
|
|
*/
|
|
extern void ResetTimeZoneInternal(ResetTimeZoneMode mode);
|
|
|
|
+extern void SetTimeZoneOverrideInternal(std::string timeZone);
|
|
+
|
|
/**
|
|
* Stores date/time information, particularly concerning the current local
|
|
* time zone, and implements a small cache for daylight saving time offset
|
|
@@ -253,6 +255,7 @@ class DateTimeInfo {
|
|
private:
|
|
// The method below should only be called via js::ResetTimeZoneInternal().
|
|
friend void js::ResetTimeZoneInternal(ResetTimeZoneMode);
|
|
+ friend void js::SetTimeZoneOverrideInternal(std::string);
|
|
|
|
static void resetTimeZone(ResetTimeZoneMode mode) {
|
|
{
|
|
@@ -352,6 +355,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
|
|
@@ -367,6 +372,8 @@ class DateTimeInfo {
|
|
|
|
void internalResetTimeZone(ResetTimeZoneMode mode);
|
|
|
|
+ void internalSetTimeZoneOverride(std::string timeZone);
|
|
+
|
|
void updateTimeZone();
|
|
|
|
void internalResyncICUDefaultTimeZone();
|
|
diff --git a/layout/base/GeometryUtils.cpp b/layout/base/GeometryUtils.cpp
|
|
index 4bfd336ddcbee8004ac538ca7b7d8216d04a61c3..cd22351c4aeacea8afc9828972222aca1b3063bf 100644
|
|
--- a/layout/base/GeometryUtils.cpp
|
|
+++ b/layout/base/GeometryUtils.cpp
|
|
@@ -23,6 +23,7 @@
|
|
#include "nsContentUtils.h"
|
|
#include "nsCSSFrameConstructor.h"
|
|
#include "nsLayoutUtils.h"
|
|
+#include "ChildIterator.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::dom;
|
|
@@ -265,10 +266,27 @@ static bool CheckFramesInSameTopLevelBrowsingContext(nsIFrame* aFrame1,
|
|
return false;
|
|
}
|
|
|
|
+static nsIFrame* GetFrameForNodeRecursive(nsINode* aNode,
|
|
+ const GeometryUtilsOptions& aOptions,
|
|
+ bool aRecurseWhenNoFrame) {
|
|
+ nsIFrame* frame = GetFrameForNode(aNode, aOptions);
|
|
+ if (!frame && aRecurseWhenNoFrame && aNode->IsContent()) {
|
|
+ dom::FlattenedChildIterator iter(aNode->AsContent());
|
|
+ for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
|
|
+ frame = GetFrameForNodeRecursive(child, aOptions, aRecurseWhenNoFrame);
|
|
+ if (frame) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return frame;
|
|
+}
|
|
+
|
|
void GetBoxQuads(nsINode* aNode, const dom::BoxQuadOptions& aOptions,
|
|
nsTArray<RefPtr<DOMQuad>>& aResult, CallerType aCallerType,
|
|
ErrorResult& aRv) {
|
|
- nsIFrame* frame = GetFrameForNode(aNode, aOptions);
|
|
+ nsIFrame* frame =
|
|
+ GetFrameForNodeRecursive(aNode, aOptions, aOptions.mRecurseWhenNoFrame);
|
|
if (!frame) {
|
|
// No boxes to return
|
|
return;
|
|
@@ -281,7 +299,8 @@ void GetBoxQuads(nsINode* aNode, const dom::BoxQuadOptions& aOptions,
|
|
// EnsureFrameForTextNode call. We need to get the first frame again
|
|
// when that happens and re-check it.
|
|
if (!weakFrame.IsAlive()) {
|
|
- frame = GetFrameForNode(aNode, aOptions);
|
|
+ frame =
|
|
+ GetFrameForNodeRecursive(aNode, aOptions, aOptions.mRecurseWhenNoFrame);
|
|
if (!frame) {
|
|
// No boxes to return
|
|
return;
|
|
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
|
|
index ede24b9c7ac3569d6467ac88bc491d2987ac0bca..a45ebcdf3a3caaad15a8dff0b8ebbec971aac8a6 100644
|
|
--- a/layout/base/PresShell.cpp
|
|
+++ b/layout/base/PresShell.cpp
|
|
@@ -11265,7 +11265,9 @@ bool PresShell::ComputeActiveness() const {
|
|
if (!browserChild->IsVisible()) {
|
|
MOZ_LOG(gLog, LogLevel::Debug,
|
|
(" > BrowserChild %p is not visible", browserChild));
|
|
- return false;
|
|
+ bool isActive;
|
|
+ root->GetDocShell()->GetForceActiveState(&isActive);
|
|
+ return isActive;
|
|
}
|
|
|
|
// If the browser is visible but just due to be preserving layers
|
|
diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp
|
|
index b9f06daa19e5aecb976ad198990a315bc39f736d..1600435c406e2e652abdab72a7947add7266c75a 100644
|
|
--- a/layout/base/nsLayoutUtils.cpp
|
|
+++ b/layout/base/nsLayoutUtils.cpp
|
|
@@ -708,6 +708,10 @@ bool nsLayoutUtils::AllowZoomingForDocument(
|
|
!aDocument->GetPresShell()->AsyncPanZoomEnabled()) {
|
|
return false;
|
|
}
|
|
+
|
|
+ /* Playwright: disable zooming as we don't support meta viewport tag */
|
|
+ if (1 == 1) return false;
|
|
+
|
|
// True if we allow zooming for all documents on this platform, or if we are
|
|
// in RDM.
|
|
BrowsingContext* bc = aDocument->GetBrowsingContext();
|
|
@@ -9748,6 +9752,9 @@ void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont,
|
|
|
|
/* static */
|
|
bool nsLayoutUtils::ShouldHandleMetaViewport(const Document* aDocument) {
|
|
+ /* Playwright: disable meta viewport handling since we don't require one */
|
|
+ if (1 == 1) return false;
|
|
+
|
|
BrowsingContext* bc = aDocument->GetBrowsingContext();
|
|
return StaticPrefs::dom_meta_viewport_enabled() || (bc && bc->InRDMPane());
|
|
}
|
|
diff --git a/layout/style/GeckoBindings.h b/layout/style/GeckoBindings.h
|
|
index 3f97c46ee5721c9f5bb9b86e2c0ece552ed00568..52f6c4d600baccc846503373af3476816f4c9fdc 100644
|
|
--- a/layout/style/GeckoBindings.h
|
|
+++ b/layout/style/GeckoBindings.h
|
|
@@ -595,6 +595,7 @@ float Gecko_MediaFeatures_GetResolution(const mozilla::dom::Document*);
|
|
bool Gecko_MediaFeatures_PrefersReducedMotion(const mozilla::dom::Document*);
|
|
bool Gecko_MediaFeatures_PrefersReducedTransparency(
|
|
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 ca382a3cfba8ce5839890d6e4cb3cf9789287e3b..5800fc23dc77ee5764beddd6fa48a7fd701d2939 100644
|
|
--- a/layout/style/nsMediaFeatures.cpp
|
|
+++ b/layout/style/nsMediaFeatures.cpp
|
|
@@ -264,11 +264,7 @@ bool Gecko_MediaFeatures_MatchesPlatform(StylePlatform aPlatform) {
|
|
}
|
|
|
|
bool Gecko_MediaFeatures_PrefersReducedMotion(const Document* aDocument) {
|
|
- if (aDocument->ShouldResistFingerprinting(
|
|
- RFPTarget::CSSPrefersReducedMotion)) {
|
|
- return false;
|
|
- }
|
|
- return LookAndFeel::GetInt(LookAndFeel::IntID::PrefersReducedMotion, 0) == 1;
|
|
+ return aDocument->PrefersReducedMotion();
|
|
}
|
|
|
|
bool Gecko_MediaFeatures_PrefersReducedTransparency(const Document* aDocument) {
|
|
@@ -293,6 +289,20 @@ StylePrefersColorScheme Gecko_MediaFeatures_PrefersColorScheme(
|
|
// as a signal.
|
|
StylePrefersContrast Gecko_MediaFeatures_PrefersContrast(
|
|
const Document* aDocument) {
|
|
+ if (auto* bc = aDocument->GetBrowsingContext()) {
|
|
+ switch (bc->Top()->PrefersContrastOverride()) {
|
|
+ case dom::PrefersContrastOverride::No_preference:
|
|
+ return StylePrefersContrast::NoPreference;
|
|
+ case dom::PrefersContrastOverride::Less:
|
|
+ return StylePrefersContrast::Less;
|
|
+ case dom::PrefersContrastOverride::More:
|
|
+ return StylePrefersContrast::More;
|
|
+ case dom::PrefersContrastOverride::Custom:
|
|
+ return StylePrefersContrast::Custom;
|
|
+ }
|
|
+ }
|
|
+
|
|
+
|
|
if (aDocument->ShouldResistFingerprinting(RFPTarget::CSSPrefersContrast)) {
|
|
return StylePrefersContrast::NoPreference;
|
|
}
|
|
diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
|
|
index 06acdc629c2b6ee0e29c50d8edc5a96d343b1ef2..6c263edf54117fd9cbf4a77abc396f1238730880 100644
|
|
--- a/netwerk/base/LoadInfo.cpp
|
|
+++ b/netwerk/base/LoadInfo.cpp
|
|
@@ -696,7 +696,8 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
|
|
rhs.mHasInjectedCookieForCookieBannerHandling),
|
|
mSchemelessInput(rhs.mSchemelessInput),
|
|
mHttpsUpgradeTelemetry(rhs.mHttpsUpgradeTelemetry),
|
|
- mIsNewWindowTarget(rhs.mIsNewWindowTarget) {
|
|
+ mIsNewWindowTarget(rhs.mIsNewWindowTarget),
|
|
+ mJugglerLoadIdentifier(rhs.mJugglerLoadIdentifier) {
|
|
}
|
|
|
|
LoadInfo::LoadInfo(
|
|
@@ -2515,4 +2516,16 @@ LoadInfo::SetSkipHTTPSUpgrade(bool aSkipHTTPSUpgrade) {
|
|
return NS_OK;
|
|
}
|
|
|
|
+NS_IMETHODIMP
|
|
+LoadInfo::GetJugglerLoadIdentifier(uint64_t* aResult) {
|
|
+ *aResult = mJugglerLoadIdentifier;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+LoadInfo::SetJugglerLoadIdentifier(uint64_t aID) {
|
|
+ mJugglerLoadIdentifier = aID;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
} // namespace mozilla::net
|
|
diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h
|
|
index c78602f6b46c983aa4d96c5727ebbaf7e2c7d984..e292766a0f34306ea1101be4ecd8848764726bad 100644
|
|
--- a/netwerk/base/LoadInfo.h
|
|
+++ b/netwerk/base/LoadInfo.h
|
|
@@ -423,6 +423,8 @@ class LoadInfo final : public nsILoadInfo {
|
|
|
|
bool mIsNewWindowTarget = false;
|
|
bool mSkipHTTPSUpgrade = false;
|
|
+
|
|
+ uint64_t mJugglerLoadIdentifier = 0;
|
|
};
|
|
|
|
// This is exposed solely for testing purposes and should not be used outside of
|
|
diff --git a/netwerk/base/TRRLoadInfo.cpp b/netwerk/base/TRRLoadInfo.cpp
|
|
index 5984a0a196615cca5544de052874cbb163a8233b..3617816a06651ae65c214ebd5f0affedc4d11390 100644
|
|
--- a/netwerk/base/TRRLoadInfo.cpp
|
|
+++ b/netwerk/base/TRRLoadInfo.cpp
|
|
@@ -936,5 +936,15 @@ TRRLoadInfo::GetFetchDestination(nsACString& aDestination) {
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
+NS_IMETHODIMP
|
|
+TRRLoadInfo::GetJugglerLoadIdentifier(uint64_t* aResult) {
|
|
+ return NS_ERROR_NOT_IMPLEMENTED;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+TRRLoadInfo::SetJugglerLoadIdentifier(uint64_t aResult) {
|
|
+ return NS_ERROR_NOT_IMPLEMENTED;
|
|
+}
|
|
+
|
|
} // namespace net
|
|
} // namespace mozilla
|
|
diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl
|
|
index 2d77b8aa8799ec6bb7f38722e837d070f9057ea6..0261e58afd17c78a1484ec55e45bf34442929200 100644
|
|
--- a/netwerk/base/nsILoadInfo.idl
|
|
+++ b/netwerk/base/nsILoadInfo.idl
|
|
@@ -1609,4 +1609,6 @@ interface nsILoadInfo : nsISupports
|
|
* When true, this load will never be upgraded to HTTPS.
|
|
*/
|
|
[infallible] attribute boolean skipHTTPSUpgrade;
|
|
+
|
|
+ [infallible] attribute unsigned long long jugglerLoadIdentifier;
|
|
};
|
|
diff --git a/netwerk/base/nsINetworkInterceptController.idl b/netwerk/base/nsINetworkInterceptController.idl
|
|
index 7f91d2df6f8bb4020c75c132dc8f6bf26625fa1e..ba6569f4be8fc54ec96ee44d5de45a0904c077ba 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/ipc/DocumentLoadListener.cpp b/netwerk/ipc/DocumentLoadListener.cpp
|
|
index cdf9ad443ebf49eabc362fd555ae54c09502395c..8bca3d81fef7b59334b2ab0cdccdd80ef19c675d 100644
|
|
--- a/netwerk/ipc/DocumentLoadListener.cpp
|
|
+++ b/netwerk/ipc/DocumentLoadListener.cpp
|
|
@@ -175,6 +175,7 @@ static auto CreateDocumentLoadInfo(CanonicalBrowsingContext* aBrowsingContext,
|
|
loadInfo->SetTextDirectiveUserActivation(
|
|
aLoadState->GetTextDirectiveUserActivation());
|
|
loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh());
|
|
+ loadInfo->SetJugglerLoadIdentifier(aLoadState->GetLoadIdentifier());
|
|
|
|
return loadInfo.forget();
|
|
}
|
|
diff --git a/netwerk/protocol/http/InterceptedHttpChannel.cpp b/netwerk/protocol/http/InterceptedHttpChannel.cpp
|
|
index 6d8d65c9335583d28aa3be8c05c065fa5aede908..6ab815111954b53b4dc722a1babe6b49a78bbedc 100644
|
|
--- a/netwerk/protocol/http/InterceptedHttpChannel.cpp
|
|
+++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp
|
|
@@ -727,6 +727,14 @@ NS_IMPL_ISUPPORTS(ResetInterceptionHeaderVisitor, nsIHttpHeaderVisitor)
|
|
|
|
} // anonymous namespace
|
|
|
|
+NS_IMETHODIMP
|
|
+InterceptedHttpChannel::ResetInterceptionWithURI(nsIURI* aURI) {
|
|
+ if (aURI) {
|
|
+ mURI = aURI;
|
|
+ }
|
|
+ return ResetInterception(true);
|
|
+}
|
|
+
|
|
NS_IMETHODIMP
|
|
InterceptedHttpChannel::ResetInterception(bool aBypass) {
|
|
INTERCEPTED_LOG(("InterceptedHttpChannel::ResetInterception [%p] bypass: %s",
|
|
@@ -1140,11 +1148,18 @@ InterceptedHttpChannel::OnStartRequest(nsIRequest* aRequest) {
|
|
GetCallback(mProgressSink);
|
|
}
|
|
|
|
+ // Playwright: main requests in firefox do not have loading principal.
|
|
+ // As they are intercepted by Playwright, they don't have
|
|
+ // serviceWorkerTainting as well.
|
|
+ // Thus these asserts are wrong for Playwright world.
|
|
+ // Note: these checks were added in https://github.com/mozilla/gecko-dev/commit/92e2cdde79c11510c3e4192e1b6264d00398ed95
|
|
+ /*
|
|
MOZ_ASSERT_IF(!mLoadInfo->GetServiceWorkerTaintingSynthesized(),
|
|
mLoadInfo->GetLoadingPrincipal());
|
|
// No need to do ORB checks if these conditions hold.
|
|
MOZ_DIAGNOSTIC_ASSERT(mLoadInfo->GetServiceWorkerTaintingSynthesized() ||
|
|
mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal());
|
|
+ */
|
|
|
|
if (mPump && mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) {
|
|
mPump->PeekStream(CallTypeSniffers, static_cast<nsIChannel*>(this));
|
|
diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp
|
|
index d05b06c3f9ddba3b40d5969730474eaf0d843cb1..9b2cc35c504e1044ac681c62c107f8feb6c16938 100644
|
|
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
|
|
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
|
|
@@ -1334,6 +1334,10 @@ void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta(
|
|
void nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP) {
|
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
|
|
|
+ if (mDocShell && static_cast<nsDocShell*>(mDocShell.get())->IsBypassCSPEnabled()) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp = mDocument->GetPreloadCsp();
|
|
if (!preloadCsp) {
|
|
diff --git a/security/manager/ssl/nsCertOverrideService.cpp b/security/manager/ssl/nsCertOverrideService.cpp
|
|
index 1b9f32fc97bf3c5000db95567eaab85b518fe03a..3a39859d58b05b373e9db7ebb2b7ae37166d74e7 100644
|
|
--- a/security/manager/ssl/nsCertOverrideService.cpp
|
|
+++ b/security/manager/ssl/nsCertOverrideService.cpp
|
|
@@ -433,7 +433,12 @@ nsCertOverrideService::HasMatchingOverride(
|
|
bool disableAllSecurityCheck = false;
|
|
{
|
|
MutexAutoLock lock(mMutex);
|
|
- disableAllSecurityCheck = mDisableAllSecurityCheck;
|
|
+ if (aOriginAttributes.mUserContextId) {
|
|
+ disableAllSecurityCheck = mUserContextIdsWithDisabledSecurityChecks.has(
|
|
+ aOriginAttributes.mUserContextId);
|
|
+ } else {
|
|
+ disableAllSecurityCheck = mDisableAllSecurityCheck;
|
|
+ }
|
|
}
|
|
if (disableAllSecurityCheck) {
|
|
*aIsTemporary = false;
|
|
@@ -645,14 +650,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 21cff56300db6490cf9649aa62099cb5525749b3..ce9a7fc16c2d5980be166e0f4ab9a25df300ca2f 100644
|
|
--- a/security/manager/ssl/nsCertOverrideService.h
|
|
+++ b/security/manager/ssl/nsCertOverrideService.h
|
|
@@ -118,6 +118,7 @@ class nsCertOverrideService final : public nsICertOverrideService,
|
|
|
|
mozilla::Mutex mMutex;
|
|
bool mDisableAllSecurityCheck MOZ_GUARDED_BY(mMutex);
|
|
+ mozilla::HashSet<uint32_t> mUserContextIdsWithDisabledSecurityChecks MOZ_GUARDED_BY(mMutex);
|
|
nsCOMPtr<nsIFile> mSettingsFile MOZ_GUARDED_BY(mMutex);
|
|
nsTHashtable<nsCertOverrideEntry> mSettingsTable MOZ_GUARDED_BY(mMutex);
|
|
|
|
diff --git a/security/manager/ssl/nsICertOverrideService.idl b/security/manager/ssl/nsICertOverrideService.idl
|
|
index 6dfd07d6b676a99993408921de8dea9d561f201d..e3c6794363cd6336effbeac83a179f3796dd71b0 100644
|
|
--- a/security/manager/ssl/nsICertOverrideService.idl
|
|
+++ b/security/manager/ssl/nsICertOverrideService.idl
|
|
@@ -137,7 +137,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.sys.mjs b/services/settings/Utils.sys.mjs
|
|
index d3643aedf21a26594268a47bc0f6ac53e3977f75..795c6f3b28278b9f65a596799d4e424880fcffa7 100644
|
|
--- a/services/settings/Utils.sys.mjs
|
|
+++ b/services/settings/Utils.sys.mjs
|
|
@@ -97,7 +97,7 @@ const _cdnURLs = {};
|
|
|
|
export var Utils = {
|
|
get SERVER_URL() {
|
|
- return lazy.allowServerURLOverride
|
|
+ return true || lazy.allowServerURLOverride
|
|
? lazy.gServerURL
|
|
: AppConstants.REMOTE_SETTINGS_SERVER_URL;
|
|
},
|
|
@@ -110,6 +110,9 @@ export var Utils = {
|
|
log,
|
|
|
|
get shouldSkipRemoteActivityDueToTests() {
|
|
+ // Playwright does not set Cu.isInAutomation, hence we just return true
|
|
+ // here in order to disable the remote activity.
|
|
+ return true;
|
|
return (
|
|
(lazy.isRunningTests || Cu.isInAutomation) &&
|
|
this.SERVER_URL == "data:,#remote-settings-dummy/v1"
|
|
diff --git a/toolkit/components/browser/nsIWebBrowserChrome.idl b/toolkit/components/browser/nsIWebBrowserChrome.idl
|
|
index 75555352b8a15a50e4a21e34fc8ede4e9246c7cc..72855a404effa42b6c55cd0c2fcb8bdd6c2b3f9f 100644
|
|
--- a/toolkit/components/browser/nsIWebBrowserChrome.idl
|
|
+++ b/toolkit/components/browser/nsIWebBrowserChrome.idl
|
|
@@ -74,6 +74,9 @@ interface nsIWebBrowserChrome : nsISupports
|
|
// Whether this window should use out-of-process cross-origin subframes.
|
|
const unsigned long CHROME_FISSION_WINDOW = 1 << 21;
|
|
|
|
+ // 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 = 1 << 24;
|
|
diff --git a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs
|
|
index 8b975a8b11bcf2eabbb7fa51a431ff99ff69a5bc..0eeb5924c43a21b8561dd4b68fa89228ddcbc708 100644
|
|
--- a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs
|
|
+++ b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs
|
|
@@ -108,6 +108,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/resistfingerprinting/nsUserCharacteristics.cpp b/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp
|
|
index cb235ed5b39fe5092a17b12976121ee3952d2062..649bba4c0faab1745f3040eba5925ef48b8f34f9 100644
|
|
--- a/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp
|
|
+++ b/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp
|
|
@@ -489,7 +489,7 @@ void PopulateLanguages() {
|
|
// sufficient to only collect this information as the other properties are
|
|
// just reformats of Navigator::GetAcceptLanguages.
|
|
nsTArray<nsString> languages;
|
|
- dom::Navigator::GetAcceptLanguages(languages);
|
|
+ dom::Navigator::GetAcceptLanguages(nullptr, languages);
|
|
nsCString output = "["_ns;
|
|
|
|
for (const auto& language : languages) {
|
|
diff --git a/toolkit/components/startup/nsAppStartup.cpp b/toolkit/components/startup/nsAppStartup.cpp
|
|
index dc0826f72134b91482e30d183ddf52e95146e12f..119a324e162b6965ddd3d6b2d53bd2856a174452 100644
|
|
--- a/toolkit/components/startup/nsAppStartup.cpp
|
|
+++ b/toolkit/components/startup/nsAppStartup.cpp
|
|
@@ -361,7 +361,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;
|
|
diff --git a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
|
|
index 654903fadb709be976b72f36f155e23bc0622152..815b3dc24c9fda6b1db6c4666ac68904c87ac0ab 100644
|
|
--- a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
|
|
+++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
|
|
@@ -174,8 +174,8 @@ nsBrowserStatusFilter::OnStateChange(nsIWebProgress* aWebProgress,
|
|
}
|
|
|
|
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 585a957fd8a1467dc262bd1ca2058584fd8762c9..16ad38c3b7d753c386e091af700d1bebd4c59e3e 100644
|
|
--- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp
|
|
+++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
|
|
@@ -1875,7 +1875,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.sys.mjs b/toolkit/mozapps/update/UpdateService.sys.mjs
|
|
index b050236a46af8dc5f1b72559065c813db9343088..85873915d92d49fddff3b7c4330cbe2d39719f39 100644
|
|
--- a/toolkit/mozapps/update/UpdateService.sys.mjs
|
|
+++ b/toolkit/mozapps/update/UpdateService.sys.mjs
|
|
@@ -3752,6 +3752,8 @@ export class UpdateService {
|
|
}
|
|
|
|
get disabledForTesting() {
|
|
+ /* playwright */
|
|
+ return true;
|
|
return lazy.UpdateServiceStub.updateDisabledForTesting;
|
|
}
|
|
|
|
diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild
|
|
index c50b7f3932e18da9fad4b673e353974a001e78c4..708e0d75594ddcd62276d4e08c4bd5c64d7f0698 100644
|
|
--- a/toolkit/toolkit.mozbuild
|
|
+++ b/toolkit/toolkit.mozbuild
|
|
@@ -152,6 +152,7 @@ if CONFIG["ENABLE_WEBDRIVER"]:
|
|
"/remote",
|
|
"/testing/firefox-ui",
|
|
"/testing/marionette",
|
|
+ "/juggler",
|
|
"/toolkit/components/telemetry/tests/marionette",
|
|
]
|
|
|
|
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
|
|
index 7a16ea20770dd945e743871e15e5b02da4842c60..e608a81c3b069b4a020da2d7807556975f603d33 100644
|
|
--- a/toolkit/xre/nsAppRunner.cpp
|
|
+++ b/toolkit/xre/nsAppRunner.cpp
|
|
@@ -5669,7 +5669,10 @@ nsresult XREMain::XRE_mainRun() {
|
|
|
|
if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
|
|
#ifdef XP_MACOSX
|
|
- if (!BackgroundTasks::IsBackgroundTaskMode()) {
|
|
+# if defined(MOZ_BACKGROUNDTASKS)
|
|
+ if (!BackgroundTasks::IsBackgroundTaskMode())
|
|
+# endif // defined(MOZ_BACKGROUNDTASKS)
|
|
+ {
|
|
rv = appStartup->CreateHiddenWindow();
|
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
|
}
|
|
diff --git a/toolkit/xre/nsWindowsWMain.cpp b/toolkit/xre/nsWindowsWMain.cpp
|
|
index 7eb9e1104682d4eb47060654f43a1efa8b2a6bb2..a8315d6decf654b5302bea5beeea34140c300ded 100644
|
|
--- a/toolkit/xre/nsWindowsWMain.cpp
|
|
+++ b/toolkit/xre/nsWindowsWMain.cpp
|
|
@@ -14,8 +14,10 @@
|
|
#endif
|
|
|
|
#include "mozilla/Char16.h"
|
|
+#include "mozilla/CmdLineAndEnvUtils.h"
|
|
#include "nsUTF8Utils.h"
|
|
|
|
+#include <io.h>
|
|
#include <windows.h>
|
|
|
|
#ifdef __MINGW32__
|
|
@@ -114,6 +116,19 @@ static void FreeAllocStrings(int argc, char** argv) {
|
|
int wmain(int argc, WCHAR** argv) {
|
|
SanitizeEnvironmentVariables();
|
|
SetDllDirectoryW(L"");
|
|
+ bool hasJugglerPipe =
|
|
+ mozilla::CheckArg(argc, argv, "juggler-pipe", 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.
|
|
diff --git a/uriloader/base/nsDocLoader.cpp b/uriloader/base/nsDocLoader.cpp
|
|
index e5cc386651e192710b61858ab5625c97a02b92da..e560ad4fef232a26ce1e1b244f4ccea05f4aea71 100644
|
|
--- a/uriloader/base/nsDocLoader.cpp
|
|
+++ b/uriloader/base/nsDocLoader.cpp
|
|
@@ -812,6 +812,12 @@ 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 418902fc1d00a2f0bc06bd68402e8bb342485c0a..101a7b63128743862d404c3fcadaa2aa886a7f8a 100644
|
|
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
|
|
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
|
|
@@ -112,6 +112,7 @@
|
|
|
|
#include "mozilla/Components.h"
|
|
#include "mozilla/ClearOnShutdown.h"
|
|
+#include "mozilla/ErrorNames.h"
|
|
#include "mozilla/Preferences.h"
|
|
#include "mozilla/ipc/URIUtils.h"
|
|
|
|
@@ -865,6 +866,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);
|
|
@@ -1486,7 +1493,12 @@ nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel* aChannel) {
|
|
// Strip off the ".part" from mTempLeafName
|
|
mTempLeafName.Truncate(mTempLeafName.Length() - std::size(".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);
|
|
@@ -1672,7 +1684,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;
|
|
|
|
@@ -1733,6 +1774,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
|
|
@@ -2249,6 +2293,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;
|
|
}
|
|
|
|
@@ -2732,6 +2786,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 2dd4ff87bda3e0ba395cca168c42b37db1713ddf..83e8a3d328e325b3f50f593c9ea71692f9c7d401 100644
|
|
--- a/uriloader/exthandler/nsExternalHelperAppService.h
|
|
+++ b/uriloader/exthandler/nsExternalHelperAppService.h
|
|
@@ -258,6 +258,8 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService,
|
|
mozilla::dom::BrowsingContext* aContentContext, bool aForceSave,
|
|
nsIInterfaceRequestor* aWindowContext,
|
|
nsIStreamListener** aStreamListener);
|
|
+
|
|
+ nsCOMPtr<nsIDownloadInterceptor> mInterceptor;
|
|
};
|
|
|
|
/**
|
|
@@ -455,6 +457,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 53ea934dd4876e4b491b724385c8fbf7d00ee6cd..0b7b88c853b21ce778d8e87fea0a2bfe839ad412 100644
|
|
--- a/uriloader/exthandler/nsIExternalHelperAppService.idl
|
|
+++ b/uriloader/exthandler/nsIExternalHelperAppService.idl
|
|
@@ -6,8 +6,11 @@
|
|
|
|
#include "nsICancelable.idl"
|
|
|
|
+webidl BrowsingContext;
|
|
+interface nsIHelperAppLauncher;
|
|
interface nsIURI;
|
|
interface nsIChannel;
|
|
+interface nsIRequest;
|
|
interface nsIStreamListener;
|
|
interface nsIFile;
|
|
interface nsIMIMEInfo;
|
|
@@ -15,6 +18,17 @@ interface nsIWebProgressListener2;
|
|
interface nsIInterfaceRequestor;
|
|
webidl BrowsingContext;
|
|
|
|
+/**
|
|
+ * Interceptor interface used by Juggler.
|
|
+ */
|
|
+[scriptable, uuid(9a20e9b0-75d0-11ea-bc55-0242ac130003)]
|
|
+interface nsIDownloadInterceptor : nsISupports
|
|
+{
|
|
+ boolean 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.
|
|
@@ -87,6 +101,8 @@ interface nsIExternalHelperAppService : nsISupports
|
|
* `DownloadIntegration.sys.mjs`, which is implemented on all platforms.
|
|
*/
|
|
nsIFile getPreferredDownloadsDirectory();
|
|
+
|
|
+ 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/MouseEvents.h b/widget/MouseEvents.h
|
|
index 5ca1a6fa13233b1bd00ee0467732c5875c51d343..0d3b8ebe127e59516802e8819f4bbed961f0992b 100644
|
|
--- a/widget/MouseEvents.h
|
|
+++ b/widget/MouseEvents.h
|
|
@@ -368,6 +368,9 @@ class WidgetMouseEvent : public WidgetMouseEventBase,
|
|
// Otherwise, this must be 0.
|
|
uint32_t mClickCount = 0;
|
|
|
|
+ // Unique event ID
|
|
+ uint32_t mJugglerEventId = 0;
|
|
+
|
|
// Whether the event should ignore scroll frame bounds during dispatch.
|
|
bool mIgnoreRootScrollFrame = false;
|
|
|
|
@@ -391,6 +394,7 @@ class WidgetMouseEvent : public WidgetMouseEventBase,
|
|
mContextMenuTrigger = aEvent.mContextMenuTrigger;
|
|
mExitFrom = aEvent.mExitFrom;
|
|
mClickCount = aEvent.mClickCount;
|
|
+ mJugglerEventId = aEvent.mJugglerEventId;
|
|
mIgnoreRootScrollFrame = aEvent.mIgnoreRootScrollFrame;
|
|
mIgnoreCapturingContent = aEvent.mIgnoreCapturingContent;
|
|
mClickEventPrevented = aEvent.mClickEventPrevented;
|
|
diff --git a/widget/cocoa/NativeKeyBindings.mm b/widget/cocoa/NativeKeyBindings.mm
|
|
index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce8050630a1aa 100644
|
|
--- a/widget/cocoa/NativeKeyBindings.mm
|
|
+++ b/widget/cocoa/NativeKeyBindings.mm
|
|
@@ -528,6 +528,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())) {
|
|
@@ -550,6 +557,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())) {
|
|
@@ -572,6 +586,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()) {
|
|
@@ -582,7 +600,7 @@
|
|
!aEvent.IsShift()
|
|
? ToObjcSelectorPtr(@selector(moveToBeginningOfDocument:))
|
|
: ToObjcSelectorPtr(
|
|
- @selector(moveToBegginingOfDocumentAndModifySelection:)),
|
|
+ @selector(moveToBeginningOfDocumentAndModifySelection:)),
|
|
aCommands);
|
|
break;
|
|
}
|
|
@@ -609,6 +627,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/gtk/nsFilePicker.cpp b/widget/gtk/nsFilePicker.cpp
|
|
index f4bded345e95674c66e4d4ad56b50844fce0871b..321e22d334a8bbc6057ee78e77e139a2804b2403 100644
|
|
--- a/widget/gtk/nsFilePicker.cpp
|
|
+++ b/widget/gtk/nsFilePicker.cpp
|
|
@@ -21,6 +21,7 @@
|
|
#include "mozilla/Components.h"
|
|
#include "mozilla/Preferences.h"
|
|
#include "mozilla/dom/Promise.h"
|
|
+#include "gfxPlatform.h"
|
|
|
|
#include "nsArrayEnumerator.h"
|
|
#include "nsEnumeratorUtils.h"
|
|
diff --git a/widget/headless/HeadlessCompositorWidget.cpp b/widget/headless/HeadlessCompositorWidget.cpp
|
|
index bb4ee9175e66dc40de1871a7f91368fe309494a3..747625e3869882300bfbc18b184db5151dd90c1a 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"
|
|
@@ -15,9 +16,32 @@ HeadlessCompositorWidget::HeadlessCompositorWidget(
|
|
const layers::CompositorOptions& aOptions, HeadlessWidget* aWindow)
|
|
: CompositorWidget(aOptions),
|
|
mWidget(aWindow),
|
|
+ mMon("snapshotListener"),
|
|
mClientSize(LayoutDeviceIntSize(aInitData.InitialClientSize()),
|
|
"HeadlessCompositorWidget::mClientSize") {}
|
|
|
|
+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()) {
|
|
@@ -31,6 +55,59 @@ void HeadlessCompositorWidget::NotifyClientSizeChanged(
|
|
const LayoutDeviceIntSize& aClientSize) {
|
|
auto size = mClientSize.Lock();
|
|
*size = 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 facd2bc65afab8ec1aa322faa20a67464964dfb9..d6dea95472bec6006411753c3dfdab2e3659171f 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,10 +47,18 @@ class HeadlessCompositorWidget final : public CompositorWidget,
|
|
}
|
|
|
|
private:
|
|
+ void UpdateDrawTarget(const LayoutDeviceIntSize& aClientSize);
|
|
+ void PeriodicSnapshot();
|
|
+ void TakeSnapshot();
|
|
+
|
|
HeadlessWidget* mWidget;
|
|
+ mozilla::ReentrantMonitor mMon;
|
|
|
|
// See GtkCompositorWidget for the justification for this mutex.
|
|
DataMutex<LayoutDeviceIntSize> mClientSize;
|
|
+
|
|
+ HeadlessWidget::SnapshotListener mSnapshotListener;
|
|
+ RefPtr<gfx::DrawTarget> mDrawTarget;
|
|
};
|
|
|
|
} // namespace widget
|
|
diff --git a/widget/headless/HeadlessWidget.cpp b/widget/headless/HeadlessWidget.cpp
|
|
index daa2d455374fd9f75a5c6ac9f7b91696d88b065c..f45184137b52db0a5774bf3365b15f784532fbdf 100644
|
|
--- a/widget/headless/HeadlessWidget.cpp
|
|
+++ b/widget/headless/HeadlessWidget.cpp
|
|
@@ -111,6 +111,8 @@ void HeadlessWidget::Destroy() {
|
|
}
|
|
}
|
|
|
|
+ SetSnapshotListener(nullptr);
|
|
+
|
|
nsBaseWidget::OnDestroy();
|
|
|
|
nsBaseWidget::Destroy();
|
|
@@ -593,5 +595,14 @@ nsresult HeadlessWidget::SynthesizeNativeTouchpadPan(
|
|
return NS_OK;
|
|
}
|
|
|
|
+void HeadlessWidget::SetSnapshotListener(SnapshotListener&& listener) {
|
|
+ if (!mCompositorWidget) {
|
|
+ if (listener)
|
|
+ fprintf(stderr, "Trying to set SnapshotListener without compositor widget\n");
|
|
+ return;
|
|
+ }
|
|
+ mCompositorWidget->SetSnapshotListener(std::move(listener));
|
|
+}
|
|
+
|
|
} // namespace widget
|
|
} // namespace mozilla
|
|
diff --git a/widget/headless/HeadlessWidget.h b/widget/headless/HeadlessWidget.h
|
|
index 39833c28e40c61e354119cde429b8389056bafac..a638fb7520b857219ce58fcbf9ca0ed939528924 100644
|
|
--- a/widget/headless/HeadlessWidget.h
|
|
+++ b/widget/headless/HeadlessWidget.h
|
|
@@ -132,6 +132,9 @@ class HeadlessWidget final : public nsBaseWidget {
|
|
int32_t aModifierFlags,
|
|
nsIObserver* aObserver) override;
|
|
|
|
+ using SnapshotListener = std::function<void(RefPtr<gfx::DataSourceSurface>&&)>;
|
|
+ void SetSnapshotListener(SnapshotListener&& listener);
|
|
+
|
|
private:
|
|
~HeadlessWidget();
|
|
bool mEnabled;
|
|
diff --git a/widget/nsGUIEventIPC.h b/widget/nsGUIEventIPC.h
|
|
index a1f48167403f5bfb30a66809ec3e64bea468fa05..eac7fccf3493e162629918462294456e6ee6b6e1 100644
|
|
--- a/widget/nsGUIEventIPC.h
|
|
+++ b/widget/nsGUIEventIPC.h
|
|
@@ -244,6 +244,7 @@ struct ParamTraits<mozilla::WidgetMouseEvent> {
|
|
aParam.mExitFrom.value()));
|
|
}
|
|
WriteParam(aWriter, aParam.mClickCount);
|
|
+ WriteParam(aWriter, aParam.mJugglerEventId);
|
|
}
|
|
|
|
static bool Read(MessageReader* aReader, paramType* aResult) {
|
|
@@ -268,6 +269,7 @@ struct ParamTraits<mozilla::WidgetMouseEvent> {
|
|
aResult->mExitFrom = Some(static_cast<paramType::ExitFrom>(exitFrom));
|
|
}
|
|
rv = rv && ReadParam(aReader, &aResult->mClickCount);
|
|
+ rv = rv && ReadParam(aReader, &aResult->mJugglerEventId);
|
|
return rv;
|
|
}
|
|
};
|
|
diff --git a/xpcom/reflect/xptinfo/xptinfo.h b/xpcom/reflect/xptinfo/xptinfo.h
|
|
index 787d30d881adedd57d2025ca57bff4bc6c57e803..ae1a0172c960ab16919133485722d2ae0cdbcbd4 100644
|
|
--- a/xpcom/reflect/xptinfo/xptinfo.h
|
|
+++ b/xpcom/reflect/xptinfo/xptinfo.h
|
|
@@ -505,7 +505,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
|
|
|
|
/**
|