mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	 a3f34fb4b7
			
		
	
	
		a3f34fb4b7
		
			
		
	
	
	
	
		
			
			This leaves our firefox diff to gecko instrumentation changes only. Drive-by: rename webkit "src" folder into "embedder".
		
			
				
	
	
		
			1847 lines
		
	
	
		
			71 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			1847 lines
		
	
	
		
			71 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| diff --git a/accessible/base/NotificationController.h b/accessible/base/NotificationController.h
 | |
| index f239731e0ff06cb01a4c0e8cf0ba4ff5014f88e0..53447ef12eb59bd065abbfd031bd6336a60020a2 100644
 | |
| --- a/accessible/base/NotificationController.h
 | |
| +++ b/accessible/base/NotificationController.h
 | |
| @@ -284,6 +284,8 @@ class NotificationController final : public EventQueue,
 | |
|    }
 | |
|  #endif
 | |
|  
 | |
| +  bool IsUpdatePendingForJugglerAccessibility() { return IsUpdatePending(); }
 | |
| +
 | |
|   protected:
 | |
|    virtual ~NotificationController();
 | |
|  
 | |
| diff --git a/accessible/interfaces/nsIAccessibleDocument.idl b/accessible/interfaces/nsIAccessibleDocument.idl
 | |
| index a91df31c96afda66f478a5a38eaa4352039c2a0b..ee777c1746284027fb3aa2f1686f8082af9d89ee 100644
 | |
| --- a/accessible/interfaces/nsIAccessibleDocument.idl
 | |
| +++ b/accessible/interfaces/nsIAccessibleDocument.idl
 | |
| @@ -72,4 +72,9 @@ interface nsIAccessibleDocument : nsISupports
 | |
|     * Return the child document accessible at the given index.
 | |
|     */
 | |
|    nsIAccessibleDocument getChildDocumentAt(in unsigned long index);
 | |
| +
 | |
| +  /**
 | |
| +   * Return whether it is updating.
 | |
| +   */
 | |
| +  readonly attribute boolean isUpdatePendingForJugglerAccessibility;
 | |
|  };
 | |
| diff --git a/accessible/xpcom/xpcAccessibleDocument.cpp b/accessible/xpcom/xpcAccessibleDocument.cpp
 | |
| index e3dbe73f22252f11080c3f266b2309f842eba9dc..87f50fe3df7cc8f9bc26dabd5ee571cae270912a 100644
 | |
| --- a/accessible/xpcom/xpcAccessibleDocument.cpp
 | |
| +++ b/accessible/xpcom/xpcAccessibleDocument.cpp
 | |
| @@ -143,6 +143,15 @@ xpcAccessibleDocument::GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor) {
 | |
|    return NS_OK;
 | |
|  }
 | |
|  
 | |
| +
 | |
| +NS_IMETHODIMP
 | |
| +xpcAccessibleDocument::GetIsUpdatePendingForJugglerAccessibility(bool* updating) {
 | |
| +  NS_ENSURE_ARG_POINTER(updating);
 | |
| +  *updating = Intl()->Controller()->IsUpdatePendingForJugglerAccessibility();
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
| +
 | |
|  ////////////////////////////////////////////////////////////////////////////////
 | |
|  // xpcAccessibleDocument
 | |
|  
 | |
| diff --git a/accessible/xpcom/xpcAccessibleDocument.h b/accessible/xpcom/xpcAccessibleDocument.h
 | |
| index f042cc1081850ac60e329b70b5569f8b97d4e4dc..65bcff9b41b9471ef1427e3ea330481c194409bc 100644
 | |
| --- a/accessible/xpcom/xpcAccessibleDocument.h
 | |
| +++ b/accessible/xpcom/xpcAccessibleDocument.h
 | |
| @@ -48,6 +48,8 @@ class xpcAccessibleDocument : public xpcAccessibleHyperText,
 | |
|                                  nsIAccessibleDocument** aDocument) final;
 | |
|    NS_IMETHOD GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor) final;
 | |
|  
 | |
| +  NS_IMETHOD GetIsUpdatePendingForJugglerAccessibility(bool* aUpdating) final;
 | |
| +
 | |
|    /**
 | |
|     * Return XPCOM wrapper for the internal accessible.
 | |
|     */
 | |
| diff --git a/browser/installer/allowed-dupes.mn b/browser/installer/allowed-dupes.mn
 | |
| index 1154516f0f452def338110bd7407ae144e916506..f85db060474ad705f86739d64c7f18fc1c48fd02 100644
 | |
| --- a/browser/installer/allowed-dupes.mn
 | |
| +++ b/browser/installer/allowed-dupes.mn
 | |
| @@ -63,6 +63,12 @@ browser/chrome/browser/res/payments/formautofill/autofillEditForms.js
 | |
|  browser/defaults/settings/pinning/pins.json
 | |
|  browser/defaults/settings/main/example.json
 | |
|  
 | |
| +# 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
 | |
| +
 | |
|  #ifdef MOZ_EME_WIN32_ARTIFACT
 | |
|  gmp-clearkey/0.1/manifest.json
 | |
|  i686/gmp-clearkey/0.1/manifest.json
 | |
| diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
 | |
| index e011b74cc4b4014362397137e92a1f27e29b43c7..c3ac23c2416363ce897741ca457fa9086b4cdd05 100644
 | |
| --- a/browser/installer/package-manifest.in
 | |
| +++ b/browser/installer/package-manifest.in
 | |
| @@ -211,6 +211,11 @@
 | |
|  @RESPATH@/components/marionette.js
 | |
|  #endif
 | |
|  
 | |
| +@RESPATH@/chrome/juggler@JAREXT@
 | |
| +@RESPATH@/chrome/juggler.manifest
 | |
| +@RESPATH@/components/juggler.manifest
 | |
| +@RESPATH@/components/juggler.js
 | |
| +
 | |
|  #if defined(ENABLE_TESTS) && defined(MOZ_DEBUG)
 | |
|  @RESPATH@/components/TestInterfaceJS.js
 | |
|  @RESPATH@/components/TestInterfaceJS.manifest
 | |
| diff --git a/devtools/server/socket/websocket-server.js b/devtools/server/socket/websocket-server.js
 | |
| index 040c7b124dec6bb254563bbe74fe50012cb077a3..b4e6b8132786af70e8ad0dce88b67c2835307f88 100644
 | |
| --- a/devtools/server/socket/websocket-server.js
 | |
| +++ b/devtools/server/socket/websocket-server.js
 | |
| @@ -133,13 +133,12 @@ function writeHttpResponse(output, response) {
 | |
|   * Process the WebSocket handshake headers and return the key to be sent in
 | |
|   * Sec-WebSocket-Accept response header.
 | |
|   */
 | |
| -function processRequest({ requestLine, headers }) {
 | |
| +function processRequest({ requestLine, headers }, expectedPath) {
 | |
|    const [method, path] = requestLine.split(" ");
 | |
|    if (method !== "GET") {
 | |
|      throw new Error("The handshake request must use GET method");
 | |
|    }
 | |
| -
 | |
| -  if (path !== "/") {
 | |
| +  if (path !== expectedPath) {
 | |
|      throw new Error("The handshake request has unknown path");
 | |
|    }
 | |
|  
 | |
| @@ -189,13 +188,13 @@ function computeKey(key) {
 | |
|  /**
 | |
|   * Perform the server part of a WebSocket opening handshake on an incoming connection.
 | |
|   */
 | |
| -const serverHandshake = async function(input, output) {
 | |
| +const serverHandshake = async function(input, output, expectedPath) {
 | |
|    // Read the request
 | |
|    const request = await readHttpRequest(input);
 | |
|  
 | |
|    try {
 | |
|      // Check and extract info from the request
 | |
| -    const { acceptKey } = processRequest(request);
 | |
| +    const { acceptKey } = processRequest(request, expectedPath);
 | |
|  
 | |
|      // Send response headers
 | |
|      await writeHttpResponse(output, [
 | |
| @@ -217,8 +216,8 @@ const serverHandshake = async function(input, output) {
 | |
|   * Performs the WebSocket handshake and waits for the WebSocket to open.
 | |
|   * Returns Promise with a WebSocket ready to send and receive messages.
 | |
|   */
 | |
| -const accept = async function(transport, input, output) {
 | |
| -  await serverHandshake(input, output);
 | |
| +const accept = async function(transport, input, output, expectedPath) {
 | |
| +  await serverHandshake(input, output, expectedPath || "/");
 | |
|  
 | |
|    const transportProvider = {
 | |
|      setListener(upgradeListener) {
 | |
| diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
 | |
| index 52b04ca19b0f8db30ffec0a1cf06ab2f6df0443e..c65ad4d019f7089cdcc168d018e0389e661d0bcc 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"
 | |
| @@ -56,6 +62,7 @@
 | |
|  #include "mozilla/dom/ContentFrameMessageManager.h"
 | |
|  #include "mozilla/dom/DocGroup.h"
 | |
|  #include "mozilla/dom/Element.h"
 | |
| +#include "mozilla/dom/Geolocation.h"
 | |
|  #include "mozilla/dom/HTMLAnchorElement.h"
 | |
|  #include "mozilla/dom/PerformanceNavigation.h"
 | |
|  #include "mozilla/dom/PermissionMessageUtils.h"
 | |
| @@ -73,6 +80,7 @@
 | |
|  #include "mozilla/dom/nsCSPContext.h"
 | |
|  #include "mozilla/dom/LoadURIOptionsBinding.h"
 | |
|  #include "mozilla/dom/JSWindowActorChild.h"
 | |
| +#include "mozilla/dom/WorkerCommon.h"
 | |
|  #include "nsSHEntry.h"
 | |
|  #include "mozilla/net/DocumentChannel.h"
 | |
|  #include "mozilla/net/UrlClassifierFeatureFactory.h"
 | |
| @@ -97,6 +105,7 @@
 | |
|  #include "nsIDocShellTreeItem.h"
 | |
|  #include "nsIDocShellTreeOwner.h"
 | |
|  #include "mozilla/dom/Document.h"
 | |
| +#include "mozilla/dom/Element.h"
 | |
|  #include "nsIDocumentLoaderFactory.h"
 | |
|  #include "nsIDOMWindow.h"
 | |
|  #include "nsIEditingSession.h"
 | |
| @@ -185,6 +194,7 @@
 | |
|  #include "nsGlobalWindow.h"
 | |
|  #include "nsISearchService.h"
 | |
|  #include "nsJSEnvironment.h"
 | |
| +#include "nsJSUtils.h"
 | |
|  #include "nsNetCID.h"
 | |
|  #include "nsNetUtil.h"
 | |
|  #include "nsObjectLoadingContent.h"
 | |
| @@ -370,6 +380,11 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
 | |
|        mAllowWindowControl(true),
 | |
|        mUseErrorPages(true),
 | |
|        mCSSErrorReportingEnabled(false),
 | |
| +      mFileInputInterceptionEnabled(false),
 | |
| +      mOverrideHasFocus(false),
 | |
| +      mBypassCSPEnabled(false),
 | |
| +      mOnlineOverride(nsIDocShell::ONLINE_OVERRIDE_NONE),
 | |
| +      mColorSchemeOverride(COLOR_SCHEME_OVERRIDE_NONE),
 | |
|        mAllowAuth(mItemType == typeContent),
 | |
|        mAllowKeywordFixup(false),
 | |
|        mIsOffScreenBrowser(false),
 | |
| @@ -1245,6 +1260,7 @@ bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
 | |
|      isSubFrame = mLSHE->GetIsSubFrame();
 | |
|    }
 | |
|  
 | |
| +  FireOnFrameLocationChange(this, aRequest, aURI, aLocationFlags);
 | |
|    if (!isSubFrame && !isRoot) {
 | |
|      /*
 | |
|       * We don't want to send OnLocationChange notifications when
 | |
| @@ -3125,6 +3141,184 @@ 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;
 | |
| +}
 | |
| +
 | |
| +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) {
 | |
| +  MOZ_ASSERT(aEnabled);
 | |
| +  aLanguageOverride = GetRootDocShell()->mLanguageOverride;
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static void SetIcuLocale(const nsAString& aLanguageOverride) {
 | |
| +  icu::Locale locale(NS_LossyConvertUTF16toASCII(aLanguageOverride).get());
 | |
| +  if (icu::Locale::getDefault() == locale)
 | |
| +    return;
 | |
| +  UErrorCode error_code = U_ZERO_ERROR;
 | |
| +  const char* lang = locale.getLanguage();
 | |
| +  if (lang != nullptr && *lang != '\0') {
 | |
| +    icu::Locale::setDefault(locale, error_code);
 | |
| +  } else {
 | |
| +    fprintf(stderr, "SetIcuLocale Failed to set the ICU default locale to %s\n", NS_LossyConvertUTF16toASCII(aLanguageOverride).get());
 | |
| +  }
 | |
| +
 | |
| +  AutoJSAPI jsapi;
 | |
| +  jsapi.Init();
 | |
| +  JSContext* cx = jsapi.cx();
 | |
| +  JS_ResetDefaultLocale(JS_GetRuntime(cx));
 | |
| +
 | |
| +  ResetDefaultLocaleInAllWorkers();
 | |
| +}
 | |
| +
 | |
| +NS_IMETHODIMP
 | |
| +nsDocShell::SetLanguageOverride(const nsAString& aLanguageOverride) {
 | |
| +  mLanguageOverride = aLanguageOverride;
 | |
| +  SetIcuLocale(aLanguageOverride);
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
| +NS_IMETHODIMP
 | |
| +nsDocShell::OverrideTimezone(const nsAString& aTimezoneOverride,
 | |
| +                             bool* aSuccess) {
 | |
| +  NS_ENSURE_ARG(aSuccess);
 | |
| +  NS_LossyConvertUTF16toASCII timeZoneId(aTimezoneOverride);
 | |
| +  *aSuccess = nsJSUtils::SetTimeZoneOverride(timeZoneId.get());
 | |
| +
 | |
| +  // Set TZ which affects localtime_s().
 | |
| +  auto setTimeZoneEnv = [](const char* value) {
 | |
| +#if defined(_WIN32)
 | |
| +    return _putenv_s("TZ", value) == 0;
 | |
| +#else
 | |
| +    return setenv("TZ", value, true) == 0;
 | |
| +#endif /* _WIN32 */
 | |
| +  };
 | |
| +  if (*aSuccess) {
 | |
| +    *aSuccess = setTimeZoneEnv(timeZoneId.get());
 | |
| +    if (!*aSuccess) {
 | |
| +      fprintf(stderr, "Failed to set 'TZ' to '%s'\n", timeZoneId.get());
 | |
| +    }
 | |
| +  }
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
| +NS_IMETHODIMP
 | |
| +nsDocShell::GetFileInputInterceptionEnabled(bool* aEnabled) {
 | |
| +  MOZ_ASSERT(aEnabled);
 | |
| +  *aEnabled = GetRootDocShell()->mFileInputInterceptionEnabled;
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
| +NS_IMETHODIMP
 | |
| +nsDocShell::SetFileInputInterceptionEnabled(bool aEnabled) {
 | |
| +  mFileInputInterceptionEnabled = aEnabled;
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
| +bool nsDocShell::IsFileInputInterceptionEnabled() {
 | |
| +  return GetRootDocShell()->mFileInputInterceptionEnabled;
 | |
| +}
 | |
| +
 | |
| +void nsDocShell::FilePickerShown(mozilla::dom::Element* element) {
 | |
| +  nsCOMPtr<nsIObserverService> observerService =
 | |
| +      mozilla::services::GetObserverService();
 | |
| +  observerService->NotifyObservers(
 | |
| +      ToSupports(element), "juggler-file-picker-shown", nullptr);
 | |
| +}
 | |
| +
 | |
| +RefPtr<nsGeolocationService> nsDocShell::GetGeolocationServiceOverride() {
 | |
| +  return GetRootDocShell()->mGeolocationServiceOverride;
 | |
| +}
 | |
| +
 | |
| +NS_IMETHODIMP
 | |
| +nsDocShell::SetGeolocationOverride(nsIDOMGeoPosition* aGeolocationOverride) {
 | |
| +  if (aGeolocationOverride) {
 | |
| +    if (!mGeolocationServiceOverride) {
 | |
| +      mGeolocationServiceOverride = new nsGeolocationService();
 | |
| +      mGeolocationServiceOverride->Init();
 | |
| +    }
 | |
| +    mGeolocationServiceOverride->Update(aGeolocationOverride);
 | |
| +  } else {
 | |
| +    mGeolocationServiceOverride = nullptr;
 | |
| +  }
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
| +NS_IMETHODIMP
 | |
| +nsDocShell::GetOnlineOverride(OnlineOverride* aOnlineOverride) {
 | |
| +  *aOnlineOverride = GetRootDocShell()->mOnlineOverride;
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
| +NS_IMETHODIMP
 | |
| +nsDocShell::SetOnlineOverride(OnlineOverride aOnlineOverride) {
 | |
| +  // We don't have a way to verify this coming from Javascript, so this check is
 | |
| +  // still needed.
 | |
| +  if (!(aOnlineOverride == ONLINE_OVERRIDE_NONE ||
 | |
| +        aOnlineOverride == ONLINE_OVERRIDE_ONLINE ||
 | |
| +        aOnlineOverride == ONLINE_OVERRIDE_OFFLINE)) {
 | |
| +    return NS_ERROR_INVALID_ARG;
 | |
| +  }
 | |
| +
 | |
| +  mOnlineOverride = aOnlineOverride;
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
| +NS_IMETHODIMP
 | |
| +nsDocShell::GetColorSchemeOverride(ColorSchemeOverride* aColorSchemeOverride) {
 | |
| +  *aColorSchemeOverride = GetRootDocShell()->mColorSchemeOverride;
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
| +NS_IMETHODIMP
 | |
| +nsDocShell::SetColorSchemeOverride(ColorSchemeOverride aColorSchemeOverride) {
 | |
| +  mColorSchemeOverride = aColorSchemeOverride;
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
| +// =============== Juggler End =======================
 | |
| +
 | |
|  NS_IMETHODIMP
 | |
|  nsDocShell::GetIsNavigating(bool* aOut) {
 | |
|    *aOut = mIsNavigating;
 | |
| @@ -8236,6 +8430,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;
 | |
|      }
 | |
|  
 | |
| @@ -11777,6 +11977,9 @@ class OnLinkClickEvent : public Runnable {
 | |
|                                  mNoOpenerImplied, nullptr, nullptr,
 | |
|                                  mIsUserTriggered, mTriggeringPrincipal, mCsp);
 | |
|      }
 | |
| +    nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
 | |
| +    observerService->NotifyObservers(ToSupports(mContent), "juggler-link-click-sync", nullptr);
 | |
| +
 | |
|      return NS_OK;
 | |
|    }
 | |
|  
 | |
| @@ -11866,6 +12069,8 @@ nsresult nsDocShell::OnLinkClick(
 | |
|        this, aContent, aURI, target, aFileName, aPostDataStream,
 | |
|        aHeadersDataStream, noOpenerImplied, aIsUserTriggered, aIsTrusted,
 | |
|        aTriggeringPrincipal, aCsp);
 | |
| +  nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
 | |
| +  observerService->NotifyObservers(ToSupports(aContent), "juggler-link-click", nullptr);
 | |
|    return Dispatch(TaskCategory::UI, ev.forget());
 | |
|  }
 | |
|  
 | |
| diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
 | |
| index 9343cac02675aeec3a6491b53fd979b2d9ae6e0f..31355beae06e3c04f7cefe524e9e02e9932e8f14 100644
 | |
| --- a/docshell/base/nsDocShell.h
 | |
| +++ b/docshell/base/nsDocShell.h
 | |
| @@ -13,6 +13,7 @@
 | |
|  #include "Units.h"
 | |
|  #include "jsapi.h"
 | |
|  #include "mozilla/BasePrincipal.h"
 | |
| +#include "mozilla/dom/Geolocation.h"
 | |
|  #include "mozilla/HalScreenConfiguration.h"
 | |
|  #include "mozilla/LinkedList.h"
 | |
|  #include "mozilla/Maybe.h"
 | |
| @@ -25,6 +26,7 @@
 | |
|  #include "mozilla/UniquePtr.h"
 | |
|  #include "mozilla/WeakPtr.h"
 | |
|  #include "mozilla/dom/BrowsingContext.h"
 | |
| +#include "mozilla/dom/Element.h"
 | |
|  #include "mozilla/dom/ChildSHistory.h"
 | |
|  #include "mozilla/dom/ProfileTimelineMarkerBinding.h"
 | |
|  #include "mozilla/dom/WindowProxyHolder.h"
 | |
| @@ -476,6 +478,15 @@ class nsDocShell final : public nsDocLoader,
 | |
|  
 | |
|    void SetWillChangeProcess() { mWillChangeProcess = true; }
 | |
|  
 | |
| +  bool IsFileInputInterceptionEnabled();
 | |
| +  void FilePickerShown(mozilla::dom::Element* element);
 | |
| +
 | |
| +  bool ShouldOverrideHasFocus() const;
 | |
| +
 | |
| +  bool IsBypassCSPEnabled();
 | |
| +
 | |
| +  RefPtr<nsGeolocationService> GetGeolocationServiceOverride();
 | |
| +
 | |
|    // Create a content viewer within this nsDocShell for the given
 | |
|    // `WindowGlobalChild` actor.
 | |
|    nsresult CreateContentViewerForActor(
 | |
| @@ -1018,6 +1029,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
 | |
| @@ -1258,6 +1271,14 @@ class nsDocShell final : public nsDocLoader,
 | |
|    bool mAllowWindowControl : 1;
 | |
|    bool mUseErrorPages : 1;
 | |
|    bool mCSSErrorReportingEnabled : 1;
 | |
| +  bool mFileInputInterceptionEnabled: 1;
 | |
| +  bool mOverrideHasFocus : 1;
 | |
| +  bool mBypassCSPEnabled : 1;
 | |
| +  nsString mLanguageOverride;
 | |
| +  RefPtr<nsGeolocationService> mGeolocationServiceOverride;
 | |
| +  OnlineOverride mOnlineOverride;
 | |
| +  ColorSchemeOverride mColorSchemeOverride;
 | |
| +
 | |
|    bool mAllowAuth : 1;
 | |
|    bool mAllowKeywordFixup : 1;
 | |
|    bool mIsOffScreenBrowser : 1;
 | |
| diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl
 | |
| index 8a8159ad55d530f70de4a86b39793459cca2ccd9..3d9bd79a5d0c38adc8d9fa3135fc270253b6f586 100644
 | |
| --- a/docshell/base/nsIDocShell.idl
 | |
| +++ b/docshell/base/nsIDocShell.idl
 | |
| @@ -44,6 +44,7 @@ interface nsIURI;
 | |
|  interface nsIChannel;
 | |
|  interface nsIContentViewer;
 | |
|  interface nsIContentSecurityPolicy;
 | |
| +interface nsIDOMGeoPosition;
 | |
|  interface nsIDocShellLoadInfo;
 | |
|  interface nsIEditor;
 | |
|  interface nsIEditingSession;
 | |
| @@ -1073,6 +1074,33 @@ interface nsIDocShell : nsIDocShellTreeItem
 | |
|     */
 | |
|    void synchronizeLayoutHistoryState();
 | |
|  
 | |
| +  attribute boolean fileInputInterceptionEnabled;
 | |
| +
 | |
| +  attribute boolean overrideHasFocus;
 | |
| +
 | |
| +  attribute boolean bypassCSPEnabled;
 | |
| +
 | |
| +  attribute AString languageOverride;
 | |
| +
 | |
| +  boolean overrideTimezone(in AString timezoneId);
 | |
| +
 | |
| +  cenum OnlineOverride: 8 {
 | |
| +    ONLINE_OVERRIDE_NONE = 0,
 | |
| +    ONLINE_OVERRIDE_ONLINE = 1,
 | |
| +    ONLINE_OVERRIDE_OFFLINE = 2,
 | |
| +  };
 | |
| +  [infallible] attribute nsIDocShell_OnlineOverride onlineOverride;
 | |
| +
 | |
| +  cenum ColorSchemeOverride : 8 {
 | |
| +    COLOR_SCHEME_OVERRIDE_LIGHT,
 | |
| +    COLOR_SCHEME_OVERRIDE_DARK,
 | |
| +    COLOR_SCHEME_OVERRIDE_NO_PREFERENCE,
 | |
| +    COLOR_SCHEME_OVERRIDE_NONE, /* This clears the override. */
 | |
| +  };
 | |
| +  [infallible] attribute nsIDocShell_ColorSchemeOverride colorSchemeOverride;
 | |
| +
 | |
| +  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 d920acae67811acedf7d087e485a5c2c3cd01454..621a4109c7f2b1905274cfa0499b4bae129ae0d6 100644
 | |
| --- a/dom/base/Document.cpp
 | |
| +++ b/dom/base/Document.cpp
 | |
| @@ -3232,6 +3232,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
 | |
| @@ -3286,6 +3289,11 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
 | |
|      return NS_OK;
 | |
|    }
 | |
|  
 | |
| +  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;
 | |
| @@ -4024,6 +4032,10 @@ bool Document::HasFocus(ErrorResult& rv) const {
 | |
|      return false;
 | |
|    }
 | |
|  
 | |
| +  if (IsActive() && mDocumentContainer->ShouldOverrideHasFocus()) {
 | |
| +    return true;
 | |
| +  }
 | |
| +
 | |
|    // Is there a focused DOMWindow?
 | |
|    nsCOMPtr<mozIDOMWindowProxy> focusedWindow;
 | |
|    fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
 | |
| @@ -16292,6 +16304,20 @@ void Document::RemoveToplevelLoadingDocument(Document* aDoc) {
 | |
|  }
 | |
|  
 | |
|  StylePrefersColorScheme Document::PrefersColorScheme() const {
 | |
| +  auto* docShell = static_cast<nsDocShell*>(GetDocShell());
 | |
| +  nsIDocShell::ColorSchemeOverride colorScheme;
 | |
| +  if (docShell->GetColorSchemeOverride(&colorScheme) == NS_OK &&
 | |
| +      colorScheme != nsIDocShell::COLOR_SCHEME_OVERRIDE_NONE) {
 | |
| +    switch (colorScheme) {
 | |
| +      case nsIDocShell::COLOR_SCHEME_OVERRIDE_LIGHT:
 | |
| +        return StylePrefersColorScheme::Light;
 | |
| +      case nsIDocShell::COLOR_SCHEME_OVERRIDE_DARK:
 | |
| +        return StylePrefersColorScheme::Dark;
 | |
| +      case nsIDocShell::COLOR_SCHEME_OVERRIDE_NO_PREFERENCE:
 | |
| +        return StylePrefersColorScheme::NoPreference;
 | |
| +    };
 | |
| +  }
 | |
| +
 | |
|    if (nsContentUtils::ShouldResistFingerprinting(this)) {
 | |
|      return StylePrefersColorScheme::Light;
 | |
|    }
 | |
| diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp
 | |
| index e49bbceefb219c55e9643a7cf82dc42b605b7988..ad31c040498f8f11cdf07d38fb14630dd92a4f8d 100644
 | |
| --- a/dom/base/Navigator.cpp
 | |
| +++ b/dom/base/Navigator.cpp
 | |
| @@ -326,14 +326,18 @@ void Navigator::GetAppName(nsAString& aAppName, CallerType aCallerType) const {
 | |
|   * for more detail.
 | |
|   */
 | |
|  /* static */
 | |
| -void Navigator::GetAcceptLanguages(nsTArray<nsString>& aLanguages) {
 | |
| +void Navigator::GetAcceptLanguages(const nsString* aLanguageOverride, nsTArray<nsString>& aLanguages) {
 | |
|    MOZ_ASSERT(NS_IsMainThread());
 | |
|  
 | |
|    aLanguages.Clear();
 | |
|  
 | |
|    // E.g. "de-de, en-us,en".
 | |
|    nsAutoString acceptLang;
 | |
| -  Preferences::GetLocalizedString("intl.accept_languages", acceptLang);
 | |
| +  if (aLanguageOverride && aLanguageOverride->Length())
 | |
| +    acceptLang = *aLanguageOverride;
 | |
| +  else
 | |
| +    Preferences::GetLocalizedString("intl.accept_languages", acceptLang);
 | |
| +    
 | |
|  
 | |
|    // Split values on commas.
 | |
|    nsCharSeparatedTokenizer langTokenizer(acceptLang, ',');
 | |
| @@ -389,7 +393,9 @@ void Navigator::GetLanguage(nsAString& aLanguage) {
 | |
|  }
 | |
|  
 | |
|  void Navigator::GetLanguages(nsTArray<nsString>& aLanguages) {
 | |
| -  GetAcceptLanguages(aLanguages);
 | |
| +  nsString languageOverride;
 | |
| +  mWindow->GetDocShell()->GetLanguageOverride(languageOverride);
 | |
| +  GetAcceptLanguages(&languageOverride, aLanguages);
 | |
|  
 | |
|    // The returned value is cached by the binding code. The window listens to the
 | |
|    // accept languages change and will clear the cache when needed. It has to
 | |
| @@ -540,7 +546,13 @@ bool Navigator::CookieEnabled() {
 | |
|    return granted;
 | |
|  }
 | |
|  
 | |
| -bool Navigator::OnLine() { return !NS_IsOffline(); }
 | |
| +bool Navigator::OnLine() {
 | |
| +  nsDocShell* docShell = static_cast<nsDocShell*>(GetDocShell());
 | |
| +  nsIDocShell::OnlineOverride onlineOverride;
 | |
| +  if (!docShell || docShell->GetOnlineOverride(&onlineOverride) != NS_OK || onlineOverride == nsIDocShell::ONLINE_OVERRIDE_NONE)
 | |
| +    return !NS_IsOffline();
 | |
| +  return onlineOverride == nsIDocShell::ONLINE_OVERRIDE_ONLINE;
 | |
| +}
 | |
|  
 | |
|  void Navigator::GetBuildID(nsAString& aBuildID, CallerType aCallerType,
 | |
|                             ErrorResult& aRv) const {
 | |
| diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h
 | |
| index e268e2bbe8add1b43f6e4d6507cc7810d707a344..a34a7a292a02ea8d94042475a43ae3a05710c207 100644
 | |
| --- a/dom/base/Navigator.h
 | |
| +++ b/dom/base/Navigator.h
 | |
| @@ -216,7 +216,7 @@ class Navigator final : public nsISupports, public nsWrapperCache {
 | |
|  
 | |
|    StorageManager* Storage();
 | |
|  
 | |
| -  static void GetAcceptLanguages(nsTArray<nsString>& aLanguages);
 | |
| +  static void GetAcceptLanguages(const nsString* aLanguageOverride, nsTArray<nsString>& aLanguages);
 | |
|  
 | |
|    dom::MediaCapabilities* MediaCapabilities();
 | |
|    dom::MediaSession* MediaSession();
 | |
| diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp
 | |
| index b3ab072d7826fd00637a1ea5db605a98bae7d615..96cb32e3235950610f1cde4765ca14592b03f077 100644
 | |
| --- a/dom/base/nsGlobalWindowOuter.cpp
 | |
| +++ b/dom/base/nsGlobalWindowOuter.cpp
 | |
| @@ -3924,6 +3924,14 @@ Maybe<CSSIntSize> nsGlobalWindowOuter::GetRDMDeviceSize(
 | |
|        }
 | |
|      }
 | |
|    }
 | |
| +  if (topInProcessContentDoc) {
 | |
| +    nsIDocShell* docShell = topInProcessContentDoc->GetDocShell();
 | |
| +    if (docShell && docShell->GetDeviceSizeIsPageSize()) {
 | |
| +      nsPresContext* presContext = docShell->GetPresContext();
 | |
| +      if (presContext)
 | |
| +        return Some(CSSPixel::FromAppUnitsRounded(presContext->GetVisibleArea().Size()));
 | |
| +    }
 | |
| +  }
 | |
|    return Nothing();
 | |
|  }
 | |
|  
 | |
| diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp
 | |
| index ddd7d6a76bf0d974090b60f0a79929168ec57fac..195787295fd03d034a2d5110d58cd20856787845 100644
 | |
| --- a/dom/base/nsINode.cpp
 | |
| +++ b/dom/base/nsINode.cpp
 | |
| @@ -1260,6 +1260,48 @@ void nsINode::GetBoxQuadsFromWindowOrigin(const BoxQuadOptions& aOptions,
 | |
|    mozilla::GetBoxQuadsFromWindowOrigin(this, aOptions, aResult, aRv);
 | |
|  }
 | |
|  
 | |
| +void nsINode::ScrollRectIntoViewIfNeeded(int32_t x, int32_t y,
 | |
| +                                         int32_t w, int32_t h,
 | |
| +                                         ErrorResult& aRv) {
 | |
| +  aRv = NS_ERROR_UNEXPECTED;
 | |
| +  nsCOMPtr<Document> document = OwnerDoc();
 | |
| +  if (!document) {
 | |
| +    return;
 | |
| +  }
 | |
| +  PresShell* presShell = document->GetPresShell();
 | |
| +  if (!presShell) {
 | |
| +    return;
 | |
| +  }
 | |
| +  if (!IsContent()) {
 | |
| +    return;
 | |
| +  }
 | |
| +  aRv = NS_OK;
 | |
| +  nsIFrame* primaryFrame = AsContent()->GetPrimaryFrame(FlushType::Frames);
 | |
| +  if (!primaryFrame){
 | |
| +    return;
 | |
| +  }
 | |
| +  nsRect rect;
 | |
| +  if (x == -1 && y == -1 && w == -1 && h == -1) {
 | |
| +    rect = primaryFrame->GetRectRelativeToSelf();
 | |
| +  } else {
 | |
| +    rect = nsRect(nsPresContext::CSSPixelsToAppUnits(x),
 | |
| +                  nsPresContext::CSSPixelsToAppUnits(y),
 | |
| +                  nsPresContext::CSSPixelsToAppUnits(w),
 | |
| +                  nsPresContext::CSSPixelsToAppUnits(h));
 | |
| +  }
 | |
| +  presShell->ScrollFrameRectIntoView(
 | |
| +      primaryFrame, rect,
 | |
| +      ScrollAxis(kScrollToCenter, WhenToScroll::Always),
 | |
| +      ScrollAxis(kScrollToCenter, WhenToScroll::Always),
 | |
| +      ScrollFlags::ScrollOverflowHidden);
 | |
| +  // If a _visual_ scroll update is pending, cancel it; otherwise, it will
 | |
| +  // clobber next scroll (e.g. subsequent window.scrollTo(0, 0) wlll break).
 | |
| +  if (presShell->GetPendingVisualScrollUpdate()) {
 | |
| +    presShell->AcknowledgePendingVisualScrollUpdate();
 | |
| +    presShell->ClearPendingVisualScrollUpdate();
 | |
| +  }
 | |
| +}
 | |
| +
 | |
|  already_AddRefed<DOMQuad> nsINode::ConvertQuadFromNode(
 | |
|      DOMQuad& aQuad, const GeometryNode& aFrom,
 | |
|      const ConvertCoordinateOptions& aOptions, CallerType aCallerType,
 | |
| diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h
 | |
| index f97908bcc7d4d30b7b8135078b37843d7394d308..2c61dedfcae19d09f85e8ce81a73f408e0572ce8 100644
 | |
| --- a/dom/base/nsINode.h
 | |
| +++ b/dom/base/nsINode.h
 | |
| @@ -2014,6 +2014,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 cb2dfa0cb0b83c3c53257c20ee9e9af9ecba15d3..f8f8459281769a7bc1b3118ace1be27c5353d4f5 100644
 | |
| --- a/dom/base/nsJSUtils.cpp
 | |
| +++ b/dom/base/nsJSUtils.cpp
 | |
| @@ -585,6 +585,11 @@ bool nsJSUtils::GetScopeChainForElement(
 | |
|    return true;
 | |
|  }
 | |
|  
 | |
| +/* static */
 | |
| +bool nsJSUtils::SetTimeZoneOverride(const char* timezoneId) {
 | |
| +  return JS::SetTimeZoneOverride(timezoneId);
 | |
| +}
 | |
| +
 | |
|  /* static */
 | |
|  void nsJSUtils::ResetTimeZone() { JS::ResetTimeZone(); }
 | |
|  
 | |
| diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h
 | |
| index 2b654b490e53d0e258bcd4edb0470cb2e7cc9452..462e60d7fa84fb3bd09f7009c0a0cb3783caf651 100644
 | |
| --- a/dom/base/nsJSUtils.h
 | |
| +++ b/dom/base/nsJSUtils.h
 | |
| @@ -241,6 +241,7 @@ class nsJSUtils {
 | |
|        JSContext* aCx, mozilla::dom::Element* aElement,
 | |
|        JS::MutableHandleVector<JSObject*> aScopeChain);
 | |
|  
 | |
| +  static bool SetTimeZoneOverride(const char* timezoneId);
 | |
|    static void ResetTimeZone();
 | |
|  
 | |
|    static bool DumpEnabled();
 | |
| diff --git a/dom/geolocation/Geolocation.cpp b/dom/geolocation/Geolocation.cpp
 | |
| index 51c04d2f40f51c9163183559d6a92ea7b0179e17..72084201c77a4dfeabb9a2a6d42a3348b5aa6485 100644
 | |
| --- a/dom/geolocation/Geolocation.cpp
 | |
| +++ b/dom/geolocation/Geolocation.cpp
 | |
| @@ -23,6 +23,7 @@
 | |
|  #include "nsComponentManagerUtils.h"
 | |
|  #include "nsContentPermissionHelper.h"
 | |
|  #include "nsContentUtils.h"
 | |
| +#include "nsDocShell.h"
 | |
|  #include "nsGlobalWindow.h"
 | |
|  #include "mozilla/dom/Document.h"
 | |
|  #include "nsINamed.h"
 | |
| @@ -294,10 +295,8 @@ nsGeolocationRequest::Allow(JS::HandleValue aChoices) {
 | |
|      return NS_OK;
 | |
|    }
 | |
|  
 | |
| -  RefPtr<nsGeolocationService> gs =
 | |
| -      nsGeolocationService::GetGeolocationService();
 | |
| -
 | |
| -  bool canUseCache = false;
 | |
| +  nsGeolocationService* gs = mLocator->GetGeolocationService();
 | |
| +  bool canUseCache = gs != nsGeolocationService::sService.get();
 | |
|    CachedPositionAndAccuracy lastPosition = gs->GetCachedPosition();
 | |
|    if (lastPosition.position) {
 | |
|      DOMTimeStamp cachedPositionTime_ms;
 | |
| @@ -467,8 +466,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();
 | |
|      }
 | |
| @@ -745,8 +743,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;
 | |
|  
 | |
| @@ -838,7 +842,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 d92bd1c738016f93c66dbdc449c70937c37b6f9a..a4c1f0ca974470342cb8136705d78cfc00e35083 100644
 | |
| --- a/dom/geolocation/Geolocation.h
 | |
| +++ b/dom/geolocation/Geolocation.h
 | |
| @@ -57,7 +57,7 @@ struct CachedPositionAndAccuracy {
 | |
|  class nsGeolocationService final : public nsIGeolocationUpdate,
 | |
|                                     public nsIObserver {
 | |
|   public:
 | |
| -  static already_AddRefed<nsGeolocationService> GetGeolocationService();
 | |
| +  static already_AddRefed<nsGeolocationService> GetGeolocationService(nsDocShell* docShell = nullptr);
 | |
|    static mozilla::StaticRefPtr<nsGeolocationService> sService;
 | |
|  
 | |
|    NS_DECL_THREADSAFE_ISUPPORTS
 | |
| @@ -182,6 +182,8 @@ class Geolocation final : public nsIGeolocationUpdate, public nsWrapperCache {
 | |
|    // null.
 | |
|    static already_AddRefed<Geolocation> NonWindowSingleton();
 | |
|  
 | |
| +  nsGeolocationService* GetGeolocationService() { return mService; };
 | |
| +
 | |
|   private:
 | |
|    ~Geolocation();
 | |
|  
 | |
| diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
 | |
| index 036577742e32c513590f8e2980544deffb254483..8bf5b8644dc9db2ecbefc0c1310c63316c93d383 100644
 | |
| --- a/dom/html/HTMLInputElement.cpp
 | |
| +++ b/dom/html/HTMLInputElement.cpp
 | |
| @@ -44,6 +44,7 @@
 | |
|  #include "nsMappedAttributes.h"
 | |
|  #include "nsIFormControl.h"
 | |
|  #include "mozilla/dom/Document.h"
 | |
| +#include "nsDocShell.h"
 | |
|  #include "nsIFormControlFrame.h"
 | |
|  #include "nsITextControlFrame.h"
 | |
|  #include "nsIFrame.h"
 | |
| @@ -706,6 +707,12 @@ nsresult HTMLInputElement::InitFilePicker(FilePickerType aType) {
 | |
|      return NS_ERROR_FAILURE;
 | |
|    }
 | |
|  
 | |
| +  nsDocShell* docShell = static_cast<nsDocShell*>(win->GetDocShell());
 | |
| +  if (docShell && docShell->IsFileInputInterceptionEnabled()) {
 | |
| +    docShell->FilePickerShown(this);
 | |
| +    return NS_OK;
 | |
| +  }
 | |
| +
 | |
|    if (IsPopupBlocked()) {
 | |
|      return NS_OK;
 | |
|    }
 | |
| diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp
 | |
| index b0f10a8873507b580348ee5f161b9e7e939cb059..2d4d300d61fba40473a358f973658fe0dece870f 100644
 | |
| --- a/dom/ipc/BrowserChild.cpp
 | |
| +++ b/dom/ipc/BrowserChild.cpp
 | |
| @@ -3581,6 +3581,13 @@ NS_IMETHODIMP BrowserChild::OnStateChange(nsIWebProgress* aWebProgress,
 | |
|    return NS_OK;
 | |
|  }
 | |
|  
 | |
| +NS_IMETHODIMP BrowserChild::OnFrameLocationChange(nsIWebProgress *aWebProgress,
 | |
| +                                             nsIRequest *aRequest,
 | |
| +                                             nsIURI *aLocation,
 | |
| +                                             uint32_t aFlags) {
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
|  NS_IMETHODIMP BrowserChild::OnProgressChange(nsIWebProgress* aWebProgress,
 | |
|                                               nsIRequest* aRequest,
 | |
|                                               int32_t aCurSelfProgress,
 | |
| diff --git a/dom/script/ScriptSettings.cpp b/dom/script/ScriptSettings.cpp
 | |
| index e4c33aed753aab79d7e9d29abdce0a4d71d51466..d8fc1e7563dffa3fbe1f5281279774907549b311 100644
 | |
| --- a/dom/script/ScriptSettings.cpp
 | |
| +++ b/dom/script/ScriptSettings.cpp
 | |
| @@ -141,6 +141,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.
 | |
| @@ -168,7 +192,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 6908be00b3087df175508270f2097e0d908c370b..7b999d2f26454fb3cab50060cf1823566579a116 100644
 | |
| --- a/dom/security/nsCSPUtils.cpp
 | |
| +++ b/dom/security/nsCSPUtils.cpp
 | |
| @@ -121,6 +121,11 @@ void CSP_ApplyMetaCSPToDoc(mozilla::dom::Document& aDoc,
 | |
|      return;
 | |
|    }
 | |
|  
 | |
| +  if (aDoc.GetDocShell() &&
 | |
| +      nsDocShell::Cast(aDoc.GetDocShell())->IsBypassCSPEnabled()) {
 | |
| +    return;
 | |
| +  }
 | |
| +
 | |
|    nsAutoString policyStr(
 | |
|        nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
 | |
|            aPolicyStr));
 | |
| diff --git a/dom/webidl/GeometryUtils.webidl b/dom/webidl/GeometryUtils.webidl
 | |
| index 2f71b284ee5f7e11f117c447834b48355784448c..d996e0a3cbbb19c1dc320c305c6d74037bffa0d3 100644
 | |
| --- a/dom/webidl/GeometryUtils.webidl
 | |
| +++ b/dom/webidl/GeometryUtils.webidl
 | |
| @@ -27,6 +27,9 @@ interface mixin GeometryUtils {
 | |
|    [Throws, Func="nsINode::HasBoxQuadsSupport", NeedsCallerType]
 | |
|    sequence<DOMQuad> getBoxQuads(optional BoxQuadOptions options = {});
 | |
|  
 | |
| +  [ChromeOnly, Throws, Func="nsINode::HasBoxQuadsSupport"]
 | |
| +  void scrollRectIntoViewIfNeeded(long x, long y, long w, long h);
 | |
| +
 | |
|    /* getBoxQuadsFromWindowOrigin is similar to getBoxQuads, but the
 | |
|     * returned quads are further translated relative to the window
 | |
|     * origin -- which is not the layout origin. Further translation
 | |
| diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp
 | |
| index a20debb462588c36e53971318bbfe9f45b8c7bf3..63d90418ac52fb52a86875a40d173428b0392f7d 100644
 | |
| --- a/dom/workers/RuntimeService.cpp
 | |
| +++ b/dom/workers/RuntimeService.cpp
 | |
| @@ -1014,7 +1014,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) {
 | |
| @@ -1213,8 +1213,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;
 | |
|      }
 | |
|  
 | |
| @@ -1960,6 +1959,11 @@ void RuntimeService::PropagateFirstPartyStorageAccessGranted(
 | |
|    }
 | |
|  }
 | |
|  
 | |
| +void RuntimeService::ResetDefaultLocaleInAllWorkers() {
 | |
| +  AssertIsOnMainThread();
 | |
| +  BROADCAST_ALL_WORKERS(ResetDefaultLocale);
 | |
| +}
 | |
| +
 | |
|  void RuntimeService::NoteIdleThread(WorkerThread* aThread) {
 | |
|    AssertIsOnMainThread();
 | |
|    MOZ_ASSERT(aThread);
 | |
| @@ -2377,6 +2381,14 @@ void PropagateFirstPartyStorageAccessGrantedToWorkers(
 | |
|    }
 | |
|  }
 | |
|  
 | |
| +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 ee237dcc59f056c31e3d16c5bb0f00a70efb3649..299575f4d72742d256f51077d12409cfc7d61572 100644
 | |
| --- a/dom/workers/RuntimeService.h
 | |
| +++ b/dom/workers/RuntimeService.h
 | |
| @@ -117,6 +117,8 @@ class RuntimeService final : public nsIObserver {
 | |
|  
 | |
|    void PropagateFirstPartyStorageAccessGranted(nsPIDOMWindowInner* aWindow);
 | |
|  
 | |
| +  void ResetDefaultLocaleInAllWorkers();
 | |
| +
 | |
|    const NavigatorProperties& GetNavigatorProperties() const {
 | |
|      return mNavigatorProperties;
 | |
|    }
 | |
| diff --git a/dom/workers/WorkerCommon.h b/dom/workers/WorkerCommon.h
 | |
| index f5e5c232d424e25607fb2fcf089c747708e02104..ada9c56f9d31d8d1c7c4c918403f14279358a4a8 100644
 | |
| --- a/dom/workers/WorkerCommon.h
 | |
| +++ b/dom/workers/WorkerCommon.h
 | |
| @@ -47,6 +47,8 @@ void ResumeWorkersForWindow(nsPIDOMWindowInner* aWindow);
 | |
|  void PropagateFirstPartyStorageAccessGrantedToWorkers(
 | |
|      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 2b071cc1d60eb8aa76e9a2c88635ffddcd85a589..cf339e8fbf63ad158754c27443e3d3c9f937cf7e 100644
 | |
| --- a/dom/workers/WorkerPrivate.cpp
 | |
| +++ b/dom/workers/WorkerPrivate.cpp
 | |
| @@ -649,6 +649,18 @@ class UpdateContextOptionsRunnable final : public WorkerControlRunnable {
 | |
|    }
 | |
|  };
 | |
|  
 | |
| +class ResetDefaultLocaleRunnable final : public WorkerControlRunnable {
 | |
| + public:
 | |
| +  explicit ResetDefaultLocaleRunnable(WorkerPrivate* aWorkerPrivate)
 | |
| +      : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount) {}
 | |
| +
 | |
| +  virtual bool WorkerRun(JSContext* aCx,
 | |
| +                         WorkerPrivate* aWorkerPrivate) override {
 | |
| +    aWorkerPrivate->ResetDefaultLocaleInternal(aCx);
 | |
| +    return true;
 | |
| +  }
 | |
| +};
 | |
| +
 | |
|  class UpdateLanguagesRunnable final : public WorkerRunnable {
 | |
|    nsTArray<nsString> mLanguages;
 | |
|  
 | |
| @@ -1828,6 +1840,16 @@ void WorkerPrivate::UpdateContextOptions(
 | |
|    }
 | |
|  }
 | |
|  
 | |
| +void WorkerPrivate::ResetDefaultLocale() {
 | |
| +  AssertIsOnParentThread();
 | |
| +
 | |
| +  RefPtr<ResetDefaultLocaleRunnable> runnable =
 | |
| +      new ResetDefaultLocaleRunnable(this);
 | |
| +  if (!runnable->Dispatch()) {
 | |
| +    NS_WARNING("Failed to reset default locale in worker!");
 | |
| +  }
 | |
| +}
 | |
| +
 | |
|  void WorkerPrivate::UpdateLanguages(const nsTArray<nsString>& aLanguages) {
 | |
|    AssertIsOnParentThread();
 | |
|  
 | |
| @@ -4737,6 +4759,15 @@ void WorkerPrivate::UpdateContextOptionsInternal(
 | |
|    }
 | |
|  }
 | |
|  
 | |
| +void WorkerPrivate::ResetDefaultLocaleInternal(JSContext* aCx) {
 | |
| +  JS_ResetDefaultLocale(JS_GetRuntime(aCx));
 | |
| +
 | |
| +  MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
 | |
| +  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 35a2fbeff49e3e2b54854fc43b208c0a92f182d2..632d34ec768ebdf8ccbfc5f62187dc0d86fa5124 100644
 | |
| --- a/dom/workers/WorkerPrivate.h
 | |
| +++ b/dom/workers/WorkerPrivate.h
 | |
| @@ -281,6 +281,8 @@ class WorkerPrivate : public RelativeTimeline {
 | |
|    void UpdateContextOptionsInternal(JSContext* aCx,
 | |
|                                      const JS::ContextOptions& aContextOptions);
 | |
|  
 | |
| +  void ResetDefaultLocaleInternal(JSContext* aCx);
 | |
| +
 | |
|    void UpdateLanguagesInternal(const nsTArray<nsString>& aLanguages);
 | |
|  
 | |
|    void UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key,
 | |
| @@ -859,6 +861,8 @@ class WorkerPrivate : public RelativeTimeline {
 | |
|  
 | |
|    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/extensions/permissions/Permission.cpp b/extensions/permissions/Permission.cpp
 | |
| index 72ed1de82fd322ba2cafffbad5622e2fdb6aa677..0dd907ff05d1df313dd3b8f8561c4ab3296e2931 100644
 | |
| --- a/extensions/permissions/Permission.cpp
 | |
| +++ b/extensions/permissions/Permission.cpp
 | |
| @@ -34,7 +34,7 @@ already_AddRefed<nsIPrincipal> Permission::ClonePrincipalForPermission(
 | |
|  
 | |
|    mozilla::OriginAttributes attrs = aPrincipal->OriginAttributesRef();
 | |
|    if (!StaticPrefs::permissions_isolateBy_userContext()) {
 | |
| -    attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID);
 | |
| +    // attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID);
 | |
|    }
 | |
|  
 | |
|    nsAutoCString originNoSuffix;
 | |
| diff --git a/extensions/permissions/PermissionManager.cpp b/extensions/permissions/PermissionManager.cpp
 | |
| index aee1bf97dc55c66287dddfe449e495a1783dbcb4..153a2ec3e2177051283bfb008a2b94cf80018d03 100644
 | |
| --- a/extensions/permissions/PermissionManager.cpp
 | |
| +++ b/extensions/permissions/PermissionManager.cpp
 | |
| @@ -195,7 +195,7 @@ void MaybeStripOAs(bool aForceStrip, OriginAttributes& aOriginAttributes) {
 | |
|    }
 | |
|  
 | |
|    if (flags != 0) {
 | |
| -    aOriginAttributes.StripAttributes(flags);
 | |
| +    // aOriginAttributes.StripAttributes(flags);
 | |
|    }
 | |
|  }
 | |
|  
 | |
| @@ -228,6 +228,8 @@ nsresult GetOriginFromPrincipal(nsIPrincipal* aPrincipal, bool aForceStripOA,
 | |
|  
 | |
|    OriginAppendOASuffix(attrs, aForceStripOA, aOrigin);
 | |
|  
 | |
| +  // Disable userContext for permissions.
 | |
| +  // attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID);
 | |
|    return NS_OK;
 | |
|  }
 | |
|  
 | |
| diff --git a/image/DecoderFactory.cpp b/image/DecoderFactory.cpp
 | |
| index 2e444341783a09da055f33a44f51f2718609a04c..7e992310d96295950adff58b98f116a875515fb6 100644
 | |
| --- a/image/DecoderFactory.cpp
 | |
| +++ b/image/DecoderFactory.cpp
 | |
| @@ -20,7 +20,9 @@
 | |
|  #include "nsICODecoder.h"
 | |
|  #include "nsIconDecoder.h"
 | |
|  #include "nsWebPDecoder.h"
 | |
| +#ifdef MOZ_AV1
 | |
|  #include "nsAVIFDecoder.h"
 | |
| +#endif
 | |
|  
 | |
|  namespace mozilla {
 | |
|  
 | |
| @@ -79,9 +81,11 @@ DecoderType DecoderFactory::GetDecoderType(const char* aMimeType) {
 | |
|      type = DecoderType::WEBP;
 | |
|  
 | |
|      // AVIF
 | |
| +#ifdef MOZ_AV1
 | |
|    } else if (!strcmp(aMimeType, IMAGE_AVIF) &&
 | |
|               StaticPrefs::image_avif_enabled()) {
 | |
|      type = DecoderType::AVIF;
 | |
| +#endif
 | |
|    }
 | |
|  
 | |
|    return type;
 | |
| @@ -121,9 +125,11 @@ already_AddRefed<Decoder> DecoderFactory::GetDecoder(DecoderType aType,
 | |
|      case DecoderType::WEBP:
 | |
|        decoder = new nsWebPDecoder(aImage);
 | |
|        break;
 | |
| +#ifdef MOZ_AV1
 | |
|      case DecoderType::AVIF:
 | |
|        decoder = new nsAVIFDecoder(aImage);
 | |
|        break;
 | |
| +#endif
 | |
|      default:
 | |
|        MOZ_ASSERT_UNREACHABLE("Unknown decoder type");
 | |
|    }
 | |
| diff --git a/image/decoders/moz.build b/image/decoders/moz.build
 | |
| index a14e571b6cc778dc520f7fa0894cb01b0542aaa9..a974396aab043086b083aa17e3b7f9677415391c 100644
 | |
| --- a/image/decoders/moz.build
 | |
| +++ b/image/decoders/moz.build
 | |
| @@ -22,7 +22,6 @@ elif toolkit == 'android':
 | |
|  UNIFIED_SOURCES += [
 | |
|      'EXIF.cpp',
 | |
|      'iccjpeg.c',
 | |
| -    'nsAVIFDecoder.cpp',
 | |
|      'nsBMPDecoder.cpp',
 | |
|      'nsGIFDecoder2.cpp',
 | |
|      'nsICODecoder.cpp',
 | |
| @@ -32,6 +31,11 @@ UNIFIED_SOURCES += [
 | |
|      'nsWebPDecoder.cpp',
 | |
|  ]
 | |
|  
 | |
| +if CONFIG['MOZ_AV1']:
 | |
| +    UNIFIED_SOURCES += [
 | |
| +        'nsAVIFDecoder.cpp',
 | |
| +    ]
 | |
| +
 | |
|  include('/ipc/chromium/chromium-config.mozbuild')
 | |
|  
 | |
|  LOCAL_INCLUDES += [
 | |
| diff --git a/js/public/Date.h b/js/public/Date.h
 | |
| index e7a54d86c44499a3ec2adf1c156b9f9dfb0bc6b4..f56c1b419c4cb52bc371f6b8dbfffba464326fc4 100644
 | |
| --- a/js/public/Date.h
 | |
| +++ b/js/public/Date.h
 | |
| @@ -56,6 +56,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 add42a1c2da3fca6a4469435498a4c6d824d8f47..72a7f8eff3302586d6567287380ec5de9c1c5165 100644
 | |
| --- a/js/src/debugger/Object.cpp
 | |
| +++ b/js/src/debugger/Object.cpp
 | |
| @@ -2385,7 +2385,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 d27ba46016e0a01bd57dde7acc219eaaee9e65ca..3cfa6ec99272339238a4494b62b008de7036d426 100644
 | |
| --- a/js/src/vm/DateTime.cpp
 | |
| +++ b/js/src/vm/DateTime.cpp
 | |
| @@ -168,6 +168,11 @@ void js::DateTimeInfo::internalResetTimeZone(ResetTimeZoneMode mode) {
 | |
|    }
 | |
|  }
 | |
|  
 | |
| +void js::DateTimeInfo::internalSetTimeZoneOverride(mozilla::UniquePtr<icu::TimeZone> timeZone) {
 | |
| +  timeZoneOverride_ = std::move(timeZone);
 | |
| +  internalResetTimeZone(ResetTimeZoneMode::ResetEvenIfOffsetUnchanged);
 | |
| +}
 | |
| +
 | |
|  void js::DateTimeInfo::updateTimeZone() {
 | |
|    MOZ_ASSERT(timeZoneStatus_ != TimeZoneStatus::Valid);
 | |
|  
 | |
| @@ -528,10 +533,27 @@ void js::ResetTimeZoneInternal(ResetTimeZoneMode mode) {
 | |
|    js::DateTimeInfo::resetTimeZone(mode);
 | |
|  }
 | |
|  
 | |
| +void js::SetTimeZoneOverrideInternal(mozilla::UniquePtr<icu::TimeZone> timeZone) {
 | |
| +  auto guard = js::DateTimeInfo::instance->lock();
 | |
| +  guard->internalSetTimeZoneOverride(std::move(timeZone));
 | |
| +}
 | |
| +
 | |
|  JS_PUBLIC_API void JS::ResetTimeZone() {
 | |
|    js::ResetTimeZoneInternal(js::ResetTimeZoneMode::ResetEvenIfOffsetUnchanged);
 | |
|  }
 | |
|  
 | |
| +JS_PUBLIC_API bool JS::SetTimeZoneOverride(const char* timeZoneId) {
 | |
| +  // Validate timezone id.
 | |
| +  mozilla::UniquePtr<icu::TimeZone> timeZone(icu::TimeZone::createTimeZone(
 | |
| +      icu::UnicodeString(timeZoneId, -1, US_INV)));
 | |
| +  if (!timeZone || *timeZone == icu::TimeZone::getUnknown()) {
 | |
| +    fprintf(stderr, "Invalid timezone id: %s\n", timeZoneId);
 | |
| +    return false;
 | |
| +  }
 | |
| +  js::SetTimeZoneOverrideInternal(std::move(timeZone));
 | |
| +  return true;
 | |
| +}
 | |
| +
 | |
|  #if defined(XP_WIN)
 | |
|  static bool IsOlsonCompatibleWindowsTimeZoneId(const char* tz) {
 | |
|    // ICU ignores the TZ environment variable on Windows and instead directly
 | |
| @@ -726,6 +748,11 @@ void js::ResyncICUDefaultTimeZone() {
 | |
|  
 | |
|  void js::DateTimeInfo::internalResyncICUDefaultTimeZone() {
 | |
|  #if JS_HAS_INTL_API && !MOZ_SYSTEM_ICU
 | |
| +  if (timeZoneOverride_) {
 | |
| +    icu::TimeZone::setDefault(*timeZoneOverride_);
 | |
| +    return;
 | |
| +  }
 | |
| +
 | |
|    if (const char* tz = std::getenv("TZ")) {
 | |
|      icu::UnicodeString tzid;
 | |
|  
 | |
| diff --git a/js/src/vm/DateTime.h b/js/src/vm/DateTime.h
 | |
| index 25c5b01fc54c8d45da8ceb7cf6ba163bee3c5361..490c5ce49cd9b5f804df59abbfb0450fb9d1f877 100644
 | |
| --- a/js/src/vm/DateTime.h
 | |
| +++ b/js/src/vm/DateTime.h
 | |
| @@ -67,6 +67,8 @@ enum class ResetTimeZoneMode : bool {
 | |
|   */
 | |
|  extern void ResetTimeZoneInternal(ResetTimeZoneMode mode);
 | |
|  
 | |
| +extern void SetTimeZoneOverrideInternal(mozilla::UniquePtr<icu::TimeZone> timeZone);
 | |
| +
 | |
|  /**
 | |
|   * ICU's default time zone, used for various date/time formatting operations
 | |
|   * that include the local time in the representation, is allowed to go stale
 | |
| @@ -206,6 +208,7 @@ class DateTimeInfo {
 | |
|    // and js::ResyncICUDefaultTimeZone().
 | |
|    friend void js::ResetTimeZoneInternal(ResetTimeZoneMode);
 | |
|    friend void js::ResyncICUDefaultTimeZone();
 | |
| +  friend void js::SetTimeZoneOverrideInternal(mozilla::UniquePtr<icu::TimeZone>);
 | |
|  
 | |
|    static void resetTimeZone(ResetTimeZoneMode mode) {
 | |
|      auto guard = instance->lock();
 | |
| @@ -302,6 +305,8 @@ class DateTimeInfo {
 | |
|    JS::UniqueChars locale_;
 | |
|    JS::UniqueTwoByteChars standardName_;
 | |
|    JS::UniqueTwoByteChars daylightSavingsName_;
 | |
| +
 | |
| +  mozilla::UniquePtr<icu::TimeZone> 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
 | |
| @@ -317,6 +322,8 @@ class DateTimeInfo {
 | |
|  
 | |
|    void internalResetTimeZone(ResetTimeZoneMode mode);
 | |
|  
 | |
| +  void internalSetTimeZoneOverride(mozilla::UniquePtr<icu::TimeZone> timeZone);
 | |
| +
 | |
|    void updateTimeZone();
 | |
|  
 | |
|    void internalResyncICUDefaultTimeZone();
 | |
| diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp
 | |
| index 249349388e925bc1832593d6c0c9df642040eb08..33a7c3b7f4c66a08f0fb9a48fd9a16c1ee3eedb1 100644
 | |
| --- a/parser/html/nsHtml5TreeOpExecutor.cpp
 | |
| +++ b/parser/html/nsHtml5TreeOpExecutor.cpp
 | |
| @@ -1065,9 +1065,12 @@ void nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP) {
 | |
|    if (!StaticPrefs::security_csp_enable()) {
 | |
|      return;
 | |
|    }
 | |
| -
 | |
|    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/SSLServerCertVerification.cpp b/security/manager/ssl/SSLServerCertVerification.cpp
 | |
| index 33c88a1f12aae814e17be708f38514b606839b1a..bc5085343a64f7f09e2639d6fad8413ceedb44a4 100644
 | |
| --- a/security/manager/ssl/SSLServerCertVerification.cpp
 | |
| +++ b/security/manager/ssl/SSLServerCertVerification.cpp
 | |
| @@ -1183,8 +1183,8 @@ PRErrorCode AuthCertificateParseResults(
 | |
|          return SEC_ERROR_NO_MEMORY;
 | |
|        }
 | |
|        nsresult rv = overrideService->HasMatchingOverride(
 | |
| -          aHostName, aPort, nssCert, &overrideBits, &isTemporaryOverride,
 | |
| -          &haveOverride);
 | |
| +          aHostName, aPort, aOriginAttributes.mUserContextId, nssCert,
 | |
| +          &overrideBits, &isTemporaryOverride, &haveOverride);
 | |
|        if (NS_SUCCEEDED(rv) && haveOverride) {
 | |
|          // remove the errors that are already overriden
 | |
|          remainingDisplayErrors &= ~overrideBits;
 | |
| diff --git a/security/manager/ssl/nsCertOverrideService.cpp b/security/manager/ssl/nsCertOverrideService.cpp
 | |
| index d6b9e8f606b4d4871793d4c8ca85d7bfe0e86f37..fed251dec07057bd9a9398023e47bef5bd2ef6c4 100644
 | |
| --- a/security/manager/ssl/nsCertOverrideService.cpp
 | |
| +++ b/security/manager/ssl/nsCertOverrideService.cpp
 | |
| @@ -413,13 +413,20 @@ nsCertOverrideService::RememberTemporaryValidityOverrideUsingFingerprint(
 | |
|  
 | |
|  NS_IMETHODIMP
 | |
|  nsCertOverrideService::HasMatchingOverride(const nsACString& aHostName,
 | |
| -                                           int32_t aPort, nsIX509Cert* aCert,
 | |
| +                                           int32_t aPort,
 | |
| +                                           uint32_t aUserContextId,
 | |
| +                                           nsIX509Cert* aCert,
 | |
|                                             uint32_t* aOverrideBits,
 | |
|                                             bool* aIsTemporary, bool* _retval) {
 | |
|    bool disableAllSecurityCheck = false;
 | |
|    {
 | |
|      MutexAutoLock lock(mMutex);
 | |
| -    disableAllSecurityCheck = mDisableAllSecurityCheck;
 | |
| +    if (aUserContextId) {
 | |
| +      disableAllSecurityCheck = mUserContextIdsWithDisabledSecurityChecks.has(
 | |
| +          aUserContextId);
 | |
| +    } else {
 | |
| +      disableAllSecurityCheck = mDisableAllSecurityCheck;
 | |
| +    }
 | |
|    }
 | |
|    if (disableAllSecurityCheck) {
 | |
|      nsCertOverride::OverrideBits all = nsCertOverride::OverrideBits::Untrusted |
 | |
| @@ -632,12 +639,21 @@ 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);
 | |
| +  if (aUserContextId) {
 | |
| +    if (aDisable) {
 | |
| +      mozilla::Unused << mUserContextIdsWithDisabledSecurityChecks.put(aUserContextId);
 | |
| +    } else {
 | |
| +      mUserContextIdsWithDisabledSecurityChecks.remove(aUserContextId);
 | |
| +    }
 | |
| +    return NS_OK;
 | |
| +  }
 | |
|    mDisableAllSecurityCheck = aDisable;
 | |
|    return NS_OK;
 | |
|  }
 | |
| diff --git a/security/manager/ssl/nsCertOverrideService.h b/security/manager/ssl/nsCertOverrideService.h
 | |
| index a9fd392c18e330c107a5b2cf9720a9b6f6abd3db..ac2e2739ab2fffddea417dd73fba76d3dc639490 100644
 | |
| --- a/security/manager/ssl/nsCertOverrideService.h
 | |
| +++ b/security/manager/ssl/nsCertOverrideService.h
 | |
| @@ -120,6 +120,7 @@ class nsCertOverrideService final : public nsICertOverrideService,
 | |
|    ~nsCertOverrideService();
 | |
|  
 | |
|    bool mDisableAllSecurityCheck;
 | |
| +  mozilla::HashSet<uint32_t> mUserContextIdsWithDisabledSecurityChecks;
 | |
|    mozilla::Mutex mMutex;
 | |
|    nsCOMPtr<nsIFile> mSettingsFile;
 | |
|    nsTHashtable<nsCertOverrideEntry> mSettingsTable;
 | |
| diff --git a/security/manager/ssl/nsICertOverrideService.idl b/security/manager/ssl/nsICertOverrideService.idl
 | |
| index 6f0f8259b309c0a299c9c80b2943a498b0f1b0e6..03d17899be96bc87dc78f06277e1bd9eb93d08f8 100644
 | |
| --- a/security/manager/ssl/nsICertOverrideService.idl
 | |
| +++ b/security/manager/ssl/nsICertOverrideService.idl
 | |
| @@ -98,6 +98,7 @@ interface nsICertOverrideService : nsISupports {
 | |
|    [must_use]
 | |
|    boolean hasMatchingOverride(in AUTF8String aHostName,
 | |
|                                in int32_t aPort,
 | |
| +                              in uint32_t aUserContextId,
 | |
|                                in nsIX509Cert aCert,
 | |
|                                out uint32_t aOverrideBits,
 | |
|                                out boolean aIsTemporary);
 | |
| @@ -137,5 +138,7 @@ 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);
 | |
|  };
 | |
| diff --git a/services/settings/Utils.jsm b/services/settings/Utils.jsm
 | |
| index f44f839dd4a52cb7a2073dae57d86df54cd72706..4b4a2fbf3b303adfec7010250b3ed86259421f46 100644
 | |
| --- a/services/settings/Utils.jsm
 | |
| +++ b/services/settings/Utils.jsm
 | |
| @@ -55,7 +55,7 @@ var Utils = {
 | |
|        Ci.nsIEnvironment
 | |
|      );
 | |
|      const isXpcshell = env.exists("XPCSHELL_TEST_PROFILE_DIR");
 | |
| -    return AppConstants.RELEASE_OR_BETA && !Cu.isInAutomation && !isXpcshell
 | |
| +    return false && !Cu.isInAutomation && !isXpcshell
 | |
|        ? "https://firefox.settings.services.mozilla.com/v1"
 | |
|        : gServerURL;
 | |
|    },
 | |
| diff --git a/toolkit/components/startup/nsAppStartup.cpp b/toolkit/components/startup/nsAppStartup.cpp
 | |
| index 73d33f54032c0ec785145214fe572d6655ca12b2..87daad40c1d811b75e3b8acab6837469e8443383 100644
 | |
| --- a/toolkit/components/startup/nsAppStartup.cpp
 | |
| +++ b/toolkit/components/startup/nsAppStartup.cpp
 | |
| @@ -335,7 +335,7 @@ nsAppStartup::Quit(uint32_t aMode) {
 | |
|      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 ba7205c529c402512532c840225a535ce14fed5d..4597d7e950313dff1888aaf35cab49f04ae506bd 100644
 | |
| --- a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
 | |
| +++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
 | |
| @@ -176,8 +176,16 @@ nsBrowserStatusFilter::OnStateChange(nsIWebProgress* aWebProgress,
 | |
|  }
 | |
|  
 | |
|  NS_IMETHODIMP
 | |
| -nsBrowserStatusFilter::OnProgressChange(nsIWebProgress* aWebProgress,
 | |
| -                                        nsIRequest* aRequest,
 | |
| +nsBrowserStatusFilter::OnFrameLocationChange(nsIWebProgress *aWebProgress,
 | |
| +                                             nsIRequest *aRequest,
 | |
| +                                             nsIURI *aLocation,
 | |
| +                                             uint32_t aFlags) {
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
| +NS_IMETHODIMP
 | |
| +nsBrowserStatusFilter::OnProgressChange(nsIWebProgress *aWebProgress,
 | |
| +                                        nsIRequest *aRequest,
 | |
|                                          int32_t aCurSelfProgress,
 | |
|                                          int32_t aMaxSelfProgress,
 | |
|                                          int32_t aCurTotalProgress,
 | |
| diff --git a/toolkit/mozapps/update/UpdateService.jsm b/toolkit/mozapps/update/UpdateService.jsm
 | |
| index 1f6de902e738a00eb12003bf5cb2f4fcb0bd16ae..47d02fb5dd0283b5de1f95f9e7a780a169be14e4 100644
 | |
| --- a/toolkit/mozapps/update/UpdateService.jsm
 | |
| +++ b/toolkit/mozapps/update/UpdateService.jsm
 | |
| @@ -3076,7 +3076,7 @@ UpdateService.prototype = {
 | |
|        ).running;
 | |
|      }
 | |
|  
 | |
| -    return (
 | |
| +    return true || (
 | |
|        (Cu.isInAutomation || marionetteRunning) &&
 | |
|        Services.prefs.getBoolPref(PREF_APP_UPDATE_DISABLEDFORTESTING, false)
 | |
|      );
 | |
| diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild
 | |
| index 299230cb3bde5ecd111454ed6f59d1f0504b67a1..09f4ef69776217e5e9f5cc4ad4de939887d8c871 100644
 | |
| --- a/toolkit/toolkit.mozbuild
 | |
| +++ b/toolkit/toolkit.mozbuild
 | |
| @@ -168,6 +168,7 @@ if CONFIG['ENABLE_MARIONETTE']:
 | |
|      DIRS += [
 | |
|          '/testing/firefox-ui',
 | |
|          '/testing/marionette',
 | |
| +        '/juggler',
 | |
|          '/toolkit/components/telemetry/tests/marionette',
 | |
|      ]
 | |
|  
 | |
| diff --git a/uriloader/base/nsDocLoader.cpp b/uriloader/base/nsDocLoader.cpp
 | |
| index ef08f301d18466f1b08d18b88343fb4b7f11c476..04e3628094fe1c0afde7050e5b28c97a9e90e087 100644
 | |
| --- a/uriloader/base/nsDocLoader.cpp
 | |
| +++ b/uriloader/base/nsDocLoader.cpp
 | |
| @@ -757,6 +757,13 @@ void nsDocLoader::DocLoaderIsEmpty(bool aFlushLayout) {
 | |
|                          ("DocLoader:%p: Firing load event for document.open\n",
 | |
|                           this));
 | |
|  
 | |
| +                nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
 | |
| +                if (os) {
 | |
| +                  nsIPrincipal* principal = doc->NodePrincipal();
 | |
| +                  if (!principal->IsSystemPrincipal())
 | |
| +                    os->NotifyObservers(ToSupports(doc), "juggler-document-open-loaded", nullptr);
 | |
| +                }
 | |
| +
 | |
|                  // This is a very cut-down version of
 | |
|                  // nsDocumentViewer::LoadComplete that doesn't do various things
 | |
|                  // that are not relevant here because this wasn't an actual
 | |
| @@ -1363,6 +1370,24 @@ void nsDocLoader::FireOnLocationChange(nsIWebProgress* aWebProgress,
 | |
|    }
 | |
|  }
 | |
|  
 | |
| +void nsDocLoader::FireOnFrameLocationChange(nsIWebProgress* aWebProgress,
 | |
| +                                       nsIRequest* aRequest,
 | |
| +                                       nsIURI *aUri,
 | |
| +                                       uint32_t aFlags) {
 | |
| +  NOTIFY_LISTENERS(nsIWebProgress::NOTIFY_FRAME_LOCATION,
 | |
| +    nsCOMPtr<nsIWebProgressListener2> listener2 =
 | |
| +      do_QueryReferent(info.mWeakListener);
 | |
| +    if (!listener2)
 | |
| +      continue;
 | |
| +    listener2->OnFrameLocationChange(aWebProgress, aRequest, aUri, aFlags);
 | |
| +  );
 | |
| +
 | |
| +  // Pass the notification up to the parent...
 | |
| +  if (mParent) {
 | |
| +    mParent->FireOnFrameLocationChange(aWebProgress, aRequest, aUri, aFlags);
 | |
| +  }
 | |
| +}
 | |
| +
 | |
|  void nsDocLoader::FireOnStatusChange(nsIWebProgress* aWebProgress,
 | |
|                                       nsIRequest* aRequest, nsresult aStatus,
 | |
|                                       const char16_t* aMessage) {
 | |
| diff --git a/uriloader/base/nsDocLoader.h b/uriloader/base/nsDocLoader.h
 | |
| index 9fa3ebf90357db3996c8768b82822102405d1e56..96bbfa5069648ba94fa469e8d9791a29b00bd783 100644
 | |
| --- a/uriloader/base/nsDocLoader.h
 | |
| +++ b/uriloader/base/nsDocLoader.h
 | |
| @@ -206,6 +206,11 @@ class nsDocLoader : public nsIDocumentLoader,
 | |
|                                        nsIURI* aURI, int32_t aDelay,
 | |
|                                        bool aSameURI);
 | |
|  
 | |
| +  void FireOnFrameLocationChange(nsIWebProgress* aWebProgress,
 | |
| +                               nsIRequest* aRequest,
 | |
| +                               nsIURI *aUri,
 | |
| +                               uint32_t aFlags);
 | |
| +
 | |
|    // this function is overridden by the docshell, it is provided so that we
 | |
|    // can pass more information about redirect state (the normal OnStateChange
 | |
|    // doesn't get the new channel).
 | |
| diff --git a/uriloader/base/nsIWebProgress.idl b/uriloader/base/nsIWebProgress.idl
 | |
| index b0cde5026dc7c414e8f20300ac2b7d735dbd846e..09ebb0ef6799cf6a74fe529d4d000c6bed2c9497 100644
 | |
| --- a/uriloader/base/nsIWebProgress.idl
 | |
| +++ b/uriloader/base/nsIWebProgress.idl
 | |
| @@ -87,6 +87,10 @@ interface nsIWebProgress : nsISupports
 | |
|     * NOTIFY_REFRESH
 | |
|     *   Receive onRefreshAttempted events.
 | |
|     *   This is defined on nsIWebProgressListener2.
 | |
| +   *
 | |
| +   * NOTIFY_FRAME_LOCATION
 | |
| +   *   Receive onFrameLocationChange events.
 | |
| +   *   This is defined on nsIWebProgressListener2.
 | |
|     */
 | |
|    const unsigned long NOTIFY_PROGRESS         = 0x00000010;
 | |
|    const unsigned long NOTIFY_STATUS           = 0x00000020;
 | |
| @@ -94,11 +98,12 @@ interface nsIWebProgress : nsISupports
 | |
|    const unsigned long NOTIFY_LOCATION         = 0x00000080;
 | |
|    const unsigned long NOTIFY_REFRESH          = 0x00000100;
 | |
|    const unsigned long NOTIFY_CONTENT_BLOCKING = 0x00000200;
 | |
| +  const unsigned long NOTIFY_FRAME_LOCATION   = 0x00000400;
 | |
|  
 | |
|    /**
 | |
|     * This flag enables all notifications.
 | |
|     */
 | |
| -  const unsigned long NOTIFY_ALL              = 0x000003ff;
 | |
| +  const unsigned long NOTIFY_ALL              = 0x000007ff;
 | |
|  
 | |
|    /**
 | |
|     * Registers a listener to receive web progress events.
 | |
| diff --git a/uriloader/base/nsIWebProgressListener2.idl b/uriloader/base/nsIWebProgressListener2.idl
 | |
| index 87701f8d2cfee8bd84acd28c62b3be4989c9474c..ae1aa85c019cb21d4f7e79c35e8afe72709468a1 100644
 | |
| --- a/uriloader/base/nsIWebProgressListener2.idl
 | |
| +++ b/uriloader/base/nsIWebProgressListener2.idl
 | |
| @@ -66,4 +66,27 @@ interface nsIWebProgressListener2 : nsIWebProgressListener {
 | |
|                               in nsIURI aRefreshURI,
 | |
|                               in long aMillis,
 | |
|                               in boolean aSameURI);
 | |
| +
 | |
| +  /**
 | |
| +   * Called when the location of the window or its subframes changes.  This is not
 | |
| +   * when a load is requested, but rather once it is verified that the load is
 | |
| +   * going to occur in the given window.  For instance, a load that starts in a
 | |
| +   * window might send progress and status messages for the new site, but it
 | |
| +   * will not send the onLocationChange until we are sure that we are loading
 | |
| +   * this new page here.
 | |
| +   *
 | |
| +   * @param aWebProgress
 | |
| +   *        The nsIWebProgress instance that fired the notification.
 | |
| +   * @param aRequest
 | |
| +   *        The associated nsIRequest.  This may be null in some cases.
 | |
| +   * @param aLocation
 | |
| +   *        The URI of the location that is being loaded.
 | |
| +   * @param aFlags
 | |
| +   *        This is a value which explains the situation or the reason why
 | |
| +   *        the location has changed.
 | |
| +   */
 | |
| +  void onFrameLocationChange(in nsIWebProgress aWebProgress,
 | |
| +                             in nsIRequest aRequest,
 | |
| +                             in nsIURI aLocation,
 | |
| +                             [optional] in unsigned long aFlags);
 | |
|  };
 | |
| diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp
 | |
| index b06fe25ea23b97f17b8b53677f4167a7cc994bec..196e5d6b1e9965dd9c05cc50c7bcb0841b8dafb9 100644
 | |
| --- a/uriloader/exthandler/nsExternalHelperAppService.cpp
 | |
| +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
 | |
| @@ -99,6 +99,7 @@
 | |
|  
 | |
|  #include "mozilla/Components.h"
 | |
|  #include "mozilla/ClearOnShutdown.h"
 | |
| +#include "mozilla/ErrorNames.h"
 | |
|  #include "mozilla/Preferences.h"
 | |
|  #include "mozilla/ipc/URIUtils.h"
 | |
|  
 | |
| @@ -836,6 +837,12 @@ NS_IMETHODIMP nsExternalHelperAppService::ApplyDecodingForExtension(
 | |
|    return NS_OK;
 | |
|  }
 | |
|  
 | |
| +NS_IMETHODIMP nsExternalHelperAppService::SetDownloadInterceptor(
 | |
| +    nsIDownloadInterceptor* interceptor) {
 | |
| +  mInterceptor = interceptor;
 | |
| +  return NS_OK;
 | |
| +}
 | |
| +
 | |
|  nsresult nsExternalHelperAppService::GetFileTokenForPath(
 | |
|      const char16_t* aPlatformAppPath, nsIFile** aFile) {
 | |
|    nsDependentString platformAppPath(aPlatformAppPath);
 | |
| @@ -1418,7 +1425,12 @@ nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel* aChannel) {
 | |
|    // Strip off the ".part" from mTempLeafName
 | |
|    mTempLeafName.Truncate(mTempLeafName.Length() - ArrayLength(".part") + 1);
 | |
|  
 | |
| +  return CreateSaverForTempFile();
 | |
| +}
 | |
| +
 | |
| +nsresult nsExternalAppHandler::CreateSaverForTempFile() {
 | |
|    MOZ_ASSERT(!mSaver, "Output file initialization called more than once!");
 | |
| +  nsresult rv;
 | |
|    mSaver =
 | |
|        do_CreateInstance(NS_BACKGROUNDFILESAVERSTREAMLISTENER_CONTRACTID, &rv);
 | |
|    NS_ENSURE_SUCCESS(rv, rv);
 | |
| @@ -1578,7 +1590,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;
 | |
|  
 | |
| @@ -1626,6 +1667,11 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) {
 | |
|    mMimeInfo->GetAlwaysAskBeforeHandling(&alwaysAsk);
 | |
|    nsAutoCString MIMEType;
 | |
|    mMimeInfo->GetMIMEType(MIMEType);
 | |
| +
 | |
| +  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
 | |
| @@ -2026,6 +2072,15 @@ 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");
 | |
| +    }
 | |
| +  }
 | |
| +
 | |
|    return NS_OK;
 | |
|  }
 | |
|  
 | |
| @@ -2396,6 +2451,14 @@ 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");
 | |
| +  }
 | |
| +
 | |
|    // 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 c7a41c3b714b6d788ac4a6c6931939ce07672868..6fbe9a61b821fbb2cb417cc640d5ca9efdbff733 100644
 | |
| --- a/uriloader/exthandler/nsExternalHelperAppService.h
 | |
| +++ b/uriloader/exthandler/nsExternalHelperAppService.h
 | |
| @@ -188,6 +188,8 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService,
 | |
|        mozilla::dom::BrowsingContext* aContentContext, bool aForceSave,
 | |
|        nsIInterfaceRequestor* aWindowContext,
 | |
|        nsIStreamListener** aStreamListener);
 | |
| +
 | |
| +  nsCOMPtr<nsIDownloadInterceptor> mInterceptor;
 | |
|  };
 | |
|  
 | |
|  /**
 | |
| @@ -365,6 +367,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 8a55c1bd666c4f7a032863f1527a2315830643c5..f7891682bd1903e45f96bd081f5af5a20a098edd 100644
 | |
| --- a/uriloader/exthandler/nsIExternalHelperAppService.idl
 | |
| +++ b/uriloader/exthandler/nsIExternalHelperAppService.idl
 | |
| @@ -6,6 +6,8 @@
 | |
|  
 | |
|  #include "nsICancelable.idl"
 | |
|  
 | |
| +webidl BrowsingContext;
 | |
| +interface nsIHelperAppLauncher;
 | |
|  interface nsIURI;
 | |
|  interface nsIRequest;
 | |
|  interface nsIStreamListener;
 | |
| @@ -20,6 +22,17 @@ webidl BrowsingContext;
 | |
|  class nsExternalAppHandler;
 | |
|  %}
 | |
|  
 | |
| +/**
 | |
| + * Interceptor interface used by Juggler.
 | |
| + */
 | |
| +[scriptable, uuid(9a20e9b0-75d0-11ea-bc55-0242ac130003)]
 | |
| +interface nsIDownloadInterceptor : nsISupports
 | |
| +{
 | |
| +  bool interceptDownloadRequest(in nsIHelperAppLauncher aHandler, in nsIRequest aRequest, in BrowsingContext aBrowsingContext, out nsIFile file);
 | |
| +
 | |
| +  void onDownloadComplete(in nsIHelperAppLauncher aHandler, in ACString aErrorName);
 | |
| +};
 | |
| +
 | |
|  /**
 | |
|   * The external helper app service is used for finding and launching
 | |
|   * platform specific external applications for a given mime content type.
 | |
| @@ -49,7 +62,7 @@ interface nsIExternalHelperAppService : nsISupports
 | |
|                                 in nsIInterfaceRequestor aContentContext,
 | |
|                                 in boolean aForceSave,
 | |
|                                 [optional] in nsIInterfaceRequestor aWindowContext);
 | |
| -  
 | |
| +
 | |
|    /**
 | |
|     * Binds an external helper application to a stream listener. The caller
 | |
|     * should pump data into the returned stream listener. When the OnStopRequest
 | |
| @@ -82,6 +95,7 @@ interface nsIExternalHelperAppService : nsISupports
 | |
|    boolean applyDecodingForExtension(in AUTF8String aExtension,
 | |
|                                      in ACString aEncodingType);
 | |
|  
 | |
| +  void setDownloadInterceptor(in nsIDownloadInterceptor interceptor);
 | |
|  };
 | |
|  
 | |
|  /**
 |