author | Marcos Cáceres <marcos@marcosc.com> |
Mon, 19 Jul 2021 01:20:55 +0000 | |
changeset 585911 | 5388c654aee14b0a7e2b72ab06d89577454b2a39 |
parent 585910 | b181b8a09ecb720839b187341cb0e5b1420f84b5 |
child 585912 | 675e63b1d3184436be699861305d6296dd96df6f |
push id | 146466 |
push user | marcos@marcosc.com |
push date | Mon, 19 Jul 2021 01:23:24 +0000 |
treeherder | autoland@5388c654aee1 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | edgar |
bugs | 1653549 |
milestone | 92.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/geolocation/Geolocation.cpp +++ b/dom/geolocation/Geolocation.cpp @@ -857,16 +857,28 @@ void Geolocation::RemoveRequest(nsGeoloc NS_IMETHODIMP Geolocation::Update(nsIDOMGeoPosition* aSomewhere) { if (!WindowOwnerStillExists()) { Shutdown(); return NS_OK; } + // Don't update position if window is not fully active or the document is + // hidden. We keep the pending callaback and watchers waiting for the next + // update. + nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(this->GetOwner()); + if (window) { + nsCOMPtr<Document> document = window->GetDoc(); + bool isHidden = document && document->Hidden(); + if (isHidden || !window->IsFullyActive()) { + return NS_OK; + } + } + if (aSomewhere) { nsCOMPtr<nsIDOMGeoPositionCoords> coords; aSomewhere->GetCoords(getter_AddRefs(coords)); if (coords) { double accuracy = -1; coords->GetAccuracy(&accuracy); mozilla::Telemetry::Accumulate( mozilla::Telemetry::GEOLOCATION_ACCURACY_EXPONENTIAL, accuracy);
--- a/dom/tests/mochitest/geolocation/mochitest.ini +++ b/dom/tests/mochitest/geolocation/mochitest.ini @@ -1,26 +1,31 @@ [DEFAULT] tags = geolocation scheme = https support-files = geolocation.html geolocation_common.js network_geolocation.sjs windowTest.html + popup.html prefs = dom.security.featurePolicy.header.enabled=true dom.security.featurePolicy.webidl.enabled=true [test_allowCurrent.html] skip-if = xorigin # Hangs [test_allowWatch.html] skip-if = xorigin # Hangs +[test_hidden.html] +skip-if = xorigin # Hangs + toolkit == 'android' # test uses popup windows +support-files = popup.html [test_cachedPosition.html] -fail-if = xorigin +fail-if = xorigin [test_cancelCurrent.html] [test_cancelWatch.html] [test_clearWatch.html] skip-if = xorigin # Hangs [test_clearWatchBeforeAllowing.html] skip-if = xorigin # Hangs [test_clearWatch_invalid.html] [test_crossorigin_iframe.html]
new file mode 100644 --- /dev/null +++ b/dom/tests/mochitest/geolocation/popup.html @@ -0,0 +1,19 @@ +<html> + <head> + <title>Simple access of geolocation</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="geolocation_common.js"></script> + <meta charset="utf-8"> + <head> + <script> + async function loadedWindow() { + await new Promise(r => force_prompt(true, r)); + opener.postMessage("initialized", "*"); + } + navigator.geolocation.getCurrentPosition(loadedWindow, loadedWindow, {timeout:30000}); + </script> + </head> + <body> + <h1>Just a support file</h1> + </body> +</html>
new file mode 100644 --- /dev/null +++ b/dom/tests/mochitest/geolocation/test_hidden.html @@ -0,0 +1,110 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1653549 +--> +<meta charset="utf-8"> +<title>Test that geolocation position can't be gotten when document is hidden</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script src="geolocation_common.js"></script> +<link rel="stylesheet" href="/tests/SimpleTest/test.css" /> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1653549">Mozilla Bug 1653549</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> + +<script class="testbody"> +SimpleTest.waitForExplicitFinish(); + +// Little promise wrapper helper. +function p(f) { + return new Promise((r) => f(r)); +} + +resume_geolocationProvider(async () => { + // Initialize + await new Promise((r) => force_prompt(true, r)); + const popupWindow = window.open("popup.html"); + popupWindow.opener = window; + await new Promise((r) => + window.addEventListener("message", r, { once: true }) + ); + + // Confirm everything is working ok... + const geo = popupWindow.navigator.geolocation; + await new Promise((resolve, reject) => { + geo.getCurrentPosition(resolve, reject); + }); + + // Hide the document... + const hiddenPromise = new Promise( + (r) => (popupWindow.document.onvisibilitychange = r) + ); + await SimpleTest.promiseFocus(window); + await hiddenPromise; + + // The following promises only resolve successfully when document is visible, + // meaning that position updates are ignored when the document is hidden. + let success = false; + let watchId = null; + const watchPositionPromise = new Promise((resolve) => { + watchId = geo.watchPosition( + () => { + ok(success, "watchPosition was called."); + if (!success) { + throw new Error("watchPosition was called too early"); + } + resolve(); + }, + () => { + ok(false, "Error callback of watchPosition must not be called."); + } + ); + }); + + const currentPositionPromise = new Promise((resolve) => { + geo.getCurrentPosition( + () => { + ok(success, "getCurrentPosition was called."); + if (!success){ + throw new Error("getCurrentPosition was called too early"); + } + resolve(); + }, + () => { + ok(false, "Error callback of getCurrentPosition must not be called."); + } + ); + }); + + // Send data to be ignored... + await p(start_sending_garbage); + await p(stop_sending_garbage); + await p(resume_geolocationProvider); + + // Refocus popup window... + const visiblePopupPromise = new Promise( + (r) => (popupWindow.document.onvisibilitychange = r) + ); + await SimpleTest.promiseFocus(popupWindow); + await visiblePopupPromise; + + // Resuming the geolocation events must now cause the promises to resolve correctly (with success = true). + success = true; + await p(resume_geolocationProvider); + await Promise.all([currentPositionPromise, watchPositionPromise]); + + // Cleanup and finish! + geo.clearWatch(watchId); + await SimpleTest.promiseFocus(window); + popupWindow.close(); + SimpleTest.finish(); +}); + +</script> +</pre> +</body> +</html> +