mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1353939 - Disable drag service in headless mode. r=jrmuizel
Drag service calls into GTK causing a crash in headless mode.
This commit is contained in:
parent
e0c482815a
commit
b082e33320
@ -26,6 +26,7 @@
|
||||
#include "nsCRT.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
|
||||
#include "gfxXlibSurface.h"
|
||||
#include "gfxContext.h"
|
||||
@ -151,13 +152,20 @@ nsDragService::~nsDragService()
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsDragService, nsBaseDragService, nsIObserver)
|
||||
|
||||
/* static */ nsDragService*
|
||||
mozilla::StaticRefPtr<nsDragService> sDragServiceInstance;
|
||||
/* static */ already_AddRefed<nsDragService>
|
||||
nsDragService::GetInstance()
|
||||
{
|
||||
static const nsIID iid = NS_DRAGSERVICE_CID;
|
||||
nsCOMPtr<nsIDragService> dragService = do_GetService(iid);
|
||||
return static_cast<nsDragService*>(dragService.get());
|
||||
// We rely on XPCOM keeping a reference to the service.
|
||||
if (gfxPlatform::IsHeadless()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!sDragServiceInstance) {
|
||||
sDragServiceInstance = new nsDragService();
|
||||
ClearOnShutdown(&sDragServiceInstance);
|
||||
}
|
||||
|
||||
RefPtr<nsDragService> service = sDragServiceInstance.get();
|
||||
return service.forget();
|
||||
}
|
||||
|
||||
// nsIObserver
|
||||
|
@ -85,7 +85,7 @@ public:
|
||||
// Methods called from nsWindow to handle responding to GTK drag
|
||||
// destination signals
|
||||
|
||||
static nsDragService* GetInstance();
|
||||
static already_AddRefed<nsDragService> GetInstance();
|
||||
|
||||
void TargetDataReceived (GtkWidget *aWidget,
|
||||
GdkDragContext *aContext,
|
||||
|
@ -74,7 +74,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceGTK, nsIdleServiceGTK::GetInstance)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsClipboard, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDragService, nsDragService::GetInstance)
|
||||
#endif
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton)
|
||||
|
@ -735,7 +735,7 @@ nsWindow::Destroy()
|
||||
}
|
||||
|
||||
// dragService will be null after shutdown of the service manager.
|
||||
nsDragService *dragService = nsDragService::GetInstance();
|
||||
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
|
||||
if (dragService && this == dragService->GetMostRecentDestWindow()) {
|
||||
dragService->ScheduleLeaveEvent();
|
||||
}
|
||||
@ -3397,7 +3397,8 @@ nsWindow::OnDragDataReceivedEvent(GtkWidget *aWidget,
|
||||
{
|
||||
LOGDRAG(("nsWindow::OnDragDataReceived(%p)\n", (void*)this));
|
||||
|
||||
nsDragService::GetInstance()->
|
||||
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
|
||||
dragService->
|
||||
TargetDataReceived(aWidget, aDragContext, aX, aY,
|
||||
aSelectionData, aInfo, aTime);
|
||||
}
|
||||
@ -5911,7 +5912,8 @@ drag_motion_event_cb(GtkWidget *aWidget,
|
||||
|
||||
LayoutDeviceIntPoint point = window->GdkPointToDevicePixels({ retx, rety });
|
||||
|
||||
return nsDragService::GetInstance()->
|
||||
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
|
||||
return dragService->
|
||||
ScheduleMotionEvent(innerMostWindow, aDragContext,
|
||||
point, aTime);
|
||||
}
|
||||
@ -5926,7 +5928,7 @@ drag_leave_event_cb(GtkWidget *aWidget,
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
nsDragService *dragService = nsDragService::GetInstance();
|
||||
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
|
||||
|
||||
nsWindow *mostRecentDragWindow = dragService->GetMostRecentDestWindow();
|
||||
if (!mostRecentDragWindow) {
|
||||
@ -5983,7 +5985,8 @@ drag_drop_event_cb(GtkWidget *aWidget,
|
||||
|
||||
LayoutDeviceIntPoint point = window->GdkPointToDevicePixels({ retx, rety });
|
||||
|
||||
return nsDragService::GetInstance()->
|
||||
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
|
||||
return dragService->
|
||||
ScheduleDropEvent(innerMostWindow, aDragContext,
|
||||
point, aTime);
|
||||
}
|
||||
|
@ -126,6 +126,8 @@ HeadlessWidget::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus)
|
||||
|
||||
if (mAttachedWidgetListener) {
|
||||
aStatus = mAttachedWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
|
||||
} else if (mWidgetListener) {
|
||||
aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
6
widget/headless/tests/headless_button.html
Normal file
6
widget/headless/tests/headless_button.html
Normal file
@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<head><meta content="text/html; charset=utf-8" http-equiv="Content-Type"></head>
|
||||
<body>
|
||||
<button id="btn">button</button>
|
||||
</body>
|
||||
</html>
|
@ -12,6 +12,8 @@ server.start(-1);
|
||||
const ROOT = `http://localhost:${server.identity.primaryPort}`;
|
||||
const BASE = `${ROOT}/`;
|
||||
const HEADLESS_URL = `${BASE}/headless.html`;
|
||||
const HEADLESS_BUTTON_URL = `${BASE}/headless_button.html`;
|
||||
do_register_cleanup(() => { server.stop(() => {})});
|
||||
|
||||
function loadContentWindow(webNavigation, uri) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -88,7 +90,52 @@ add_task(function* test_snapshot() {
|
||||
ok(found, "Found blue text on page.");
|
||||
|
||||
webNavigation.close();
|
||||
yield new Promise((resolve) => {
|
||||
server.stop(resolve);
|
||||
});
|
||||
});
|
||||
|
||||
// Ensure keydown events are triggered on the windowless browser.
|
||||
add_task(function* test_keydown() {
|
||||
let windowlessBrowser = Services.appShell.createWindowlessBrowser(false);
|
||||
let webNavigation = windowlessBrowser.QueryInterface(Ci.nsIWebNavigation);
|
||||
let contentWindow = yield loadContentWindow(webNavigation, HEADLESS_URL);
|
||||
|
||||
let utils = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let keydown = new Promise((resolve) => {
|
||||
contentWindow.addEventListener("keydown", () => {
|
||||
resolve();
|
||||
}, { once: true });
|
||||
})
|
||||
utils.sendKeyEvent("keydown", 65, 65, 0);
|
||||
|
||||
yield keydown;
|
||||
ok(true, "Send keydown didn't crash");
|
||||
|
||||
webNavigation.close();
|
||||
});
|
||||
|
||||
// Test dragging the mouse on a button to ensure the creation of the drag
|
||||
// service doesn't crash in headless.
|
||||
add_task(function* test_mouse_drag() {
|
||||
let windowlessBrowser = Services.appShell.createWindowlessBrowser(false);
|
||||
let webNavigation = windowlessBrowser.QueryInterface(Ci.nsIWebNavigation);
|
||||
let contentWindow = yield loadContentWindow(webNavigation, HEADLESS_BUTTON_URL);
|
||||
contentWindow.resizeTo(400, 400);
|
||||
|
||||
let target = contentWindow.document.getElementById('btn');
|
||||
let rect = target.getBoundingClientRect();
|
||||
let left = rect.left;
|
||||
let top = rect.top;
|
||||
|
||||
let utils = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
|
||||
utils.sendMouseEvent("mousemove", left, top, 0, 1, 0, false, 0, 0);
|
||||
// Wait for a turn of the event loop since the synthetic mouse event
|
||||
// that creates the drag service is processed during the refresh driver.
|
||||
yield new Promise((r) => {do_execute_soon(r)});
|
||||
utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
|
||||
|
||||
ok(true, "Send mouse event didn't crash");
|
||||
|
||||
webNavigation.close();
|
||||
});
|
||||
|
@ -1,4 +1,6 @@
|
||||
[test_headless.js]
|
||||
skip-if = os != "linux"
|
||||
headless = true
|
||||
support-files = headless.html
|
||||
support-files =
|
||||
headless.html
|
||||
headless_button.html
|
||||
|
Loading…
Reference in New Issue
Block a user