Bug 1315543 - Eliminate UAF in Navigator::NotifyVRDisplaysUpdated,r=dmu

This commit is contained in:
Kearwood (Kip) Gilbert 2016-11-24 11:50:43 -08:00
parent 934d575f3f
commit 53f4153710
5 changed files with 20 additions and 11 deletions

View File

@ -1647,9 +1647,9 @@ Navigator::GetVRDisplays(ErrorResult& aRv)
return nullptr;
}
// We pass ourself to RefreshVRDisplays, so NotifyVRDisplaysUpdated will
// We pass mWindow's id to RefreshVRDisplays, so NotifyVRDisplaysUpdated will
// be called asynchronously, resolving the promises in mVRGetDisplaysPromises.
if (!VRDisplay::RefreshVRDisplays(this)) {
if (!VRDisplay::RefreshVRDisplays(win->WindowID())) {
p->MaybeReject(NS_ERROR_FAILURE);
return p.forget();
}

View File

@ -77,10 +77,10 @@ VRDisplayCapabilities::MaxLayers() const
}
/*static*/ bool
VRDisplay::RefreshVRDisplays(dom::Navigator* aNavigator)
VRDisplay::RefreshVRDisplays(uint64_t aWindowId)
{
gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
return vm && vm->RefreshVRDisplaysWithCallback(aNavigator);
return vm && vm->RefreshVRDisplaysWithCallback(aWindowId);
}
/*static*/ void

View File

@ -282,7 +282,7 @@ public:
uint32_t DisplayId() const { return mDisplayId; }
void GetDisplayName(nsAString& aDisplayName) const { aDisplayName = mDisplayName; }
static bool RefreshVRDisplays(dom::Navigator* aNavigator);
static bool RefreshVRDisplays(uint64_t aWindowId);
static void UpdateVRDisplays(nsTArray<RefPtr<VRDisplay> >& aDisplays,
nsPIDOMWindowInner* aWindow);

View File

@ -269,13 +269,22 @@ mozilla::ipc::IPCResult
VRManagerChild::RecvUpdateDisplayInfo(nsTArray<VRDisplayInfo>&& aDisplayUpdates)
{
UpdateDisplayInfo(aDisplayUpdates);
for (auto& nav : mNavigatorCallbacks) {
for (auto& windowId : mNavigatorCallbacks) {
/** We must call NotifyVRDisplaysUpdated for every
* Navigator in mNavigatorCallbacks to ensure that
* window's Navigator in mNavigatorCallbacks to ensure that
* the promise returned by Navigator.GetVRDevices
* can resolve. This must happen even if no changes
* to VRDisplays have been detected here.
*/
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(windowId);
if (!window) {
continue;
}
ErrorResult result;
dom::Navigator* nav = window->GetNavigator(result);
if (NS_WARN_IF(result.Failed())) {
continue;
}
nav->NotifyVRDisplaysUpdated();
}
mNavigatorCallbacks.Clear();
@ -300,11 +309,11 @@ VRManagerChild::GetVRDisplays(nsTArray<RefPtr<VRDisplayClient>>& aDisplays)
}
bool
VRManagerChild::RefreshVRDisplaysWithCallback(dom::Navigator* aNavigator)
VRManagerChild::RefreshVRDisplaysWithCallback(uint64_t aWindowId)
{
bool success = SendRefreshDisplays();
if (success) {
mNavigatorCallbacks.AppendElement(aNavigator);
mNavigatorCallbacks.AppendElement(aWindowId);
}
return success;
}

View File

@ -49,7 +49,7 @@ public:
int GetInputFrameID();
bool GetVRDisplays(nsTArray<RefPtr<VRDisplayClient> >& aDisplays);
bool RefreshVRDisplaysWithCallback(dom::Navigator* aNavigator);
bool RefreshVRDisplaysWithCallback(uint64_t aWindowId);
static void InitSameProcess();
static void InitWithGPUProcess(Endpoint<PVRManagerChild>&& aEndpoint);
@ -152,7 +152,7 @@ private:
nsTArray<RefPtr<VRDisplayClient> > mDisplays;
bool mDisplaysInitialized;
nsTArray<dom::Navigator*> mNavigatorCallbacks;
nsTArray<uint64_t> mNavigatorCallbacks;
dom::GamepadManager* mGamepadManager;
int32_t mInputFrameID;