mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1238427 - Avoid a strong reference from the timeout timer to nsGeolocationRequest. r=jdm
The timeout timer of a geolocation request holds a strong reference to the request. This can cause the window to leak if the request is not completed before the tab containing the window is closed. To fix this, I made the timer instead hold a strong reference to a wrapper class that has only a weak reference to the request. The request destructor must now cancel the timeout timer. I also outlined a call to StopTimeoutTimer() in nsGeolocationRequest::Shutdown().
This commit is contained in:
parent
eabaad6c5b
commit
2956f16566
@ -31,6 +31,7 @@
|
|||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/dom/Event.h"
|
#include "mozilla/dom/Event.h"
|
||||||
|
#include "mozilla/WeakPtr.h"
|
||||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||||
#include "mozilla/dom/SettingChangeNotificationBinding.h"
|
#include "mozilla/dom/SettingChangeNotificationBinding.h"
|
||||||
#include "mozilla/dom/WakeLock.h"
|
#include "mozilla/dom/WakeLock.h"
|
||||||
@ -75,13 +76,12 @@ using namespace mozilla::hal;
|
|||||||
|
|
||||||
class nsGeolocationRequest final
|
class nsGeolocationRequest final
|
||||||
: public nsIContentPermissionRequest
|
: public nsIContentPermissionRequest
|
||||||
, public nsITimerCallback
|
|
||||||
, public nsIGeolocationUpdate
|
, public nsIGeolocationUpdate
|
||||||
|
, public SupportsWeakPtr<nsGeolocationRequest>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_NSICONTENTPERMISSIONREQUEST
|
NS_DECL_NSICONTENTPERMISSIONREQUEST
|
||||||
NS_DECL_NSITIMERCALLBACK
|
|
||||||
NS_DECL_NSIGEOLOCATIONUPDATE
|
NS_DECL_NSIGEOLOCATIONUPDATE
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGeolocationRequest, nsIContentPermissionRequest)
|
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGeolocationRequest, nsIContentPermissionRequest)
|
||||||
@ -93,6 +93,9 @@ class nsGeolocationRequest final
|
|||||||
uint8_t aProtocolType,
|
uint8_t aProtocolType,
|
||||||
bool aWatchPositionRequest = false,
|
bool aWatchPositionRequest = false,
|
||||||
int32_t aWatchId = 0);
|
int32_t aWatchId = 0);
|
||||||
|
|
||||||
|
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsGeolocationRequest)
|
||||||
|
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
void SendLocation(nsIDOMGeoPosition* aLocation);
|
void SendLocation(nsIDOMGeoPosition* aLocation);
|
||||||
@ -107,6 +110,23 @@ class nsGeolocationRequest final
|
|||||||
private:
|
private:
|
||||||
virtual ~nsGeolocationRequest();
|
virtual ~nsGeolocationRequest();
|
||||||
|
|
||||||
|
class TimerCallbackHolder final : public nsITimerCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSITIMERCALLBACK
|
||||||
|
|
||||||
|
explicit TimerCallbackHolder(nsGeolocationRequest* aRequest)
|
||||||
|
: mRequest(aRequest)
|
||||||
|
{}
|
||||||
|
|
||||||
|
private:
|
||||||
|
~TimerCallbackHolder() {}
|
||||||
|
WeakPtr<nsGeolocationRequest> mRequest;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Notify();
|
||||||
|
|
||||||
already_AddRefed<nsIDOMGeoPosition> AdjustedLocation(nsIDOMGeoPosition*);
|
already_AddRefed<nsIDOMGeoPosition> AdjustedLocation(nsIDOMGeoPosition*);
|
||||||
|
|
||||||
bool mIsWatchPositionRequest;
|
bool mIsWatchPositionRequest;
|
||||||
@ -379,12 +399,12 @@ nsGeolocationRequest::nsGeolocationRequest(Geolocation* aLocator,
|
|||||||
|
|
||||||
nsGeolocationRequest::~nsGeolocationRequest()
|
nsGeolocationRequest::~nsGeolocationRequest()
|
||||||
{
|
{
|
||||||
|
StopTimeoutTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGeolocationRequest)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGeolocationRequest)
|
||||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentPermissionRequest)
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentPermissionRequest)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIContentPermissionRequest)
|
NS_INTERFACE_MAP_ENTRY(nsIContentPermissionRequest)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIGeolocationUpdate)
|
NS_INTERFACE_MAP_ENTRY(nsIGeolocationUpdate)
|
||||||
NS_INTERFACE_MAP_END
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
@ -393,12 +413,11 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGeolocationRequest)
|
|||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION(nsGeolocationRequest, mCallback, mErrorCallback, mLocator)
|
NS_IMPL_CYCLE_COLLECTION(nsGeolocationRequest, mCallback, mErrorCallback, mLocator)
|
||||||
|
|
||||||
NS_IMETHODIMP
|
void
|
||||||
nsGeolocationRequest::Notify(nsITimer* aTimer)
|
nsGeolocationRequest::Notify()
|
||||||
{
|
{
|
||||||
StopTimeoutTimer();
|
StopTimeoutTimer();
|
||||||
NotifyErrorAndShutdown(nsIDOMGeoPositionError::TIMEOUT);
|
NotifyErrorAndShutdown(nsIDOMGeoPositionError::TIMEOUT);
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -561,7 +580,8 @@ nsGeolocationRequest::SetTimeoutTimer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
mTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1");
|
mTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||||
mTimeoutTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT);
|
RefPtr<TimerCallbackHolder> holder = new TimerCallbackHolder(this);
|
||||||
|
mTimeoutTimer->InitWithCallback(holder, timeout, nsITimer::TYPE_ONE_SHOT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,10 +761,7 @@ nsGeolocationRequest::Shutdown()
|
|||||||
MOZ_ASSERT(!mShutdown, "request shutdown twice");
|
MOZ_ASSERT(!mShutdown, "request shutdown twice");
|
||||||
mShutdown = true;
|
mShutdown = true;
|
||||||
|
|
||||||
if (mTimeoutTimer) {
|
StopTimeoutTimer();
|
||||||
mTimeoutTimer->Cancel();
|
|
||||||
mTimeoutTimer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are no other high accuracy requests, the geolocation service will
|
// If there are no other high accuracy requests, the geolocation service will
|
||||||
// notify the provider to switch to the default accuracy.
|
// notify the provider to switch to the default accuracy.
|
||||||
@ -756,6 +773,23 @@ nsGeolocationRequest::Shutdown()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////
|
||||||
|
// nsGeolocationRequest::TimerCallbackHolder
|
||||||
|
////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(nsGeolocationRequest::TimerCallbackHolder, nsISupports, nsITimerCallback)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsGeolocationRequest::TimerCallbackHolder::Notify(nsITimer*)
|
||||||
|
{
|
||||||
|
if (mRequest) {
|
||||||
|
mRequest->Notify();
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
// nsGeolocationService
|
// nsGeolocationService
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
|
@ -7,6 +7,7 @@ support-files =
|
|||||||
test-console-api.html
|
test-console-api.html
|
||||||
test_bug1004814.html
|
test_bug1004814.html
|
||||||
worker_bug1004814.js
|
worker_bug1004814.js
|
||||||
|
geo_leak_test.html
|
||||||
|
|
||||||
[browser_test_toolbars_visibility.js]
|
[browser_test_toolbars_visibility.js]
|
||||||
support-files =
|
support-files =
|
||||||
@ -20,6 +21,7 @@ skip-if = buildapp == 'mulet'
|
|||||||
[browser_autofocus_background.js]
|
[browser_autofocus_background.js]
|
||||||
skip-if= buildapp == 'mulet'
|
skip-if= buildapp == 'mulet'
|
||||||
[browser_autofocus_preference.js]
|
[browser_autofocus_preference.js]
|
||||||
|
[browser_bug1238427.js]
|
||||||
[browser_bug396843.js]
|
[browser_bug396843.js]
|
||||||
[browser_focus_steal_from_chrome.js]
|
[browser_focus_steal_from_chrome.js]
|
||||||
[browser_focus_steal_from_chrome_during_mousedown.js]
|
[browser_focus_steal_from_chrome_during_mousedown.js]
|
||||||
|
31
dom/tests/browser/browser_bug1238427.js
Normal file
31
dom/tests/browser/browser_bug1238427.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const TEST_URI = "http://example.com/" +
|
||||||
|
"browser/dom/tests/browser/geo_leak_test.html";
|
||||||
|
|
||||||
|
const BASE_GEO_URL = "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs";
|
||||||
|
|
||||||
|
add_task(function* () {
|
||||||
|
Services.prefs.setBoolPref("geo.prompt.testing", true);
|
||||||
|
Services.prefs.setBoolPref("geo.prompt.testing.allow", true);
|
||||||
|
|
||||||
|
// Make the geolocation provider responder very slowly to ensure that
|
||||||
|
// it does not reply before we close the tab.
|
||||||
|
Services.prefs.setCharPref("geo.wifi.uri", BASE_GEO_URL + "?delay=100000");
|
||||||
|
|
||||||
|
// Open the test URI and close it. The test harness will make sure that the
|
||||||
|
// page is cleaned up after some GCs. If geolocation is not shut down properly,
|
||||||
|
// it will show up as a non-shutdown leak.
|
||||||
|
yield BrowserTestUtils.withNewTab({
|
||||||
|
gBrowser,
|
||||||
|
url: TEST_URI
|
||||||
|
}, function* (browser) { /* ... */ });
|
||||||
|
|
||||||
|
ok(true, "Need to do something in this test");
|
||||||
|
});
|
||||||
|
|
17
dom/tests/browser/geo_leak_test.html
Normal file
17
dom/tests/browser/geo_leak_test.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||||
|
<title>Geolocation incomplete position leak test</title>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
function successCallback(position) {}
|
||||||
|
function errorCallback() {}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="init()">
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user