dom/plugins/test/mochitest/dialog_watcher.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 const EVENT_OBJECT_SHOW = 0x8002;
michael@0 2 const EVENT_OBJECT_HIDE = 0x8003;
michael@0 3 const WINEVENT_OUTOFCONTEXT = 0;
michael@0 4 const WINEVENT_SKIPOWNPROCESS = 2;
michael@0 5 const QS_ALLINPUT = 0x04FF;
michael@0 6 const INFINITE = 0xFFFFFFFF;
michael@0 7 const WAIT_OBJECT_0 = 0;
michael@0 8 const WAIT_TIMEOUT = 258;
michael@0 9 const PM_NOREMOVE = 0;
michael@0 10
michael@0 11 function DialogWatcher(titleText, onDialogStart, onDialogEnd) {
michael@0 12 this.titleText = titleText;
michael@0 13 this.onDialogStart = onDialogStart;
michael@0 14 this.onDialogEnd = onDialogEnd;
michael@0 15 }
michael@0 16
michael@0 17 DialogWatcher.prototype.init = function() {
michael@0 18 this.hwnd = undefined;
michael@0 19 if (!this.user32) {
michael@0 20 this.user32 = ctypes.open("user32.dll");
michael@0 21 }
michael@0 22 if (!this.findWindow) {
michael@0 23 this.findWindow = user32.declare("FindWindowW",
michael@0 24 ctypes.winapi_abi,
michael@0 25 ctypes.uintptr_t,
michael@0 26 ctypes.jschar.ptr,
michael@0 27 ctypes.jschar.ptr);
michael@0 28 }
michael@0 29 if (!this.winEventProcType) {
michael@0 30 this.winEventProcType = ctypes.FunctionType(ctypes.stdcall_abi,
michael@0 31 ctypes.void_t,
michael@0 32 [ctypes.uintptr_t,
michael@0 33 ctypes.uint32_t,
michael@0 34 ctypes.uintptr_t,
michael@0 35 ctypes.long,
michael@0 36 ctypes.long,
michael@0 37 ctypes.uint32_t,
michael@0 38 ctypes.uint32_t]).ptr;
michael@0 39 }
michael@0 40 if (!this.setWinEventHook) {
michael@0 41 this.setWinEventHook = user32.declare("SetWinEventHook",
michael@0 42 ctypes.winapi_abi,
michael@0 43 ctypes.uintptr_t,
michael@0 44 ctypes.uint32_t,
michael@0 45 ctypes.uint32_t,
michael@0 46 ctypes.uintptr_t,
michael@0 47 this.winEventProcType,
michael@0 48 ctypes.uint32_t,
michael@0 49 ctypes.uint32_t,
michael@0 50 ctypes.uint32_t);
michael@0 51 }
michael@0 52 if (!this.unhookWinEvent) {
michael@0 53 this.unhookWinEvent = user32.declare("UnhookWinEvent",
michael@0 54 ctypes.winapi_abi,
michael@0 55 ctypes.int,
michael@0 56 ctypes.uintptr_t);
michael@0 57 }
michael@0 58 if (!this.pointType) {
michael@0 59 this.pointType = ctypes.StructType("tagPOINT",
michael@0 60 [ { "x": ctypes.long },
michael@0 61 { "y": ctypes.long } ] );
michael@0 62 }
michael@0 63 if (!this.msgType) {
michael@0 64 this.msgType = ctypes.StructType("tagMSG",
michael@0 65 [ { "hwnd": ctypes.uintptr_t },
michael@0 66 { "message": ctypes.uint32_t },
michael@0 67 { "wParam": ctypes.uintptr_t },
michael@0 68 { "lParam": ctypes.intptr_t },
michael@0 69 { "time": ctypes.uint32_t },
michael@0 70 { "pt": this.pointType } ] );
michael@0 71 }
michael@0 72 if (!this.peekMessage) {
michael@0 73 this.peekMessage = user32.declare("PeekMessageW",
michael@0 74 ctypes.winapi_abi,
michael@0 75 ctypes.int,
michael@0 76 this.msgType.ptr,
michael@0 77 ctypes.uintptr_t,
michael@0 78 ctypes.uint32_t,
michael@0 79 ctypes.uint32_t,
michael@0 80 ctypes.uint32_t);
michael@0 81 }
michael@0 82 if (!this.msgWaitForMultipleObjects) {
michael@0 83 this.msgWaitForMultipleObjects = user32.declare("MsgWaitForMultipleObjects",
michael@0 84 ctypes.winapi_abi,
michael@0 85 ctypes.uint32_t,
michael@0 86 ctypes.uint32_t,
michael@0 87 ctypes.uintptr_t.ptr,
michael@0 88 ctypes.int,
michael@0 89 ctypes.uint32_t,
michael@0 90 ctypes.uint32_t);
michael@0 91 }
michael@0 92 if (!this.getWindowTextW) {
michael@0 93 this.getWindowTextW = user32.declare("GetWindowTextW",
michael@0 94 ctypes.winapi_abi,
michael@0 95 ctypes.int,
michael@0 96 ctypes.uintptr_t,
michael@0 97 ctypes.jschar.ptr,
michael@0 98 ctypes.int);
michael@0 99 }
michael@0 100 if (!this.messageBox) {
michael@0 101 // Handy for debugging this code
michael@0 102 this.messageBox = user32.declare("MessageBoxW",
michael@0 103 ctypes.winapi_abi,
michael@0 104 ctypes.int,
michael@0 105 ctypes.uintptr_t,
michael@0 106 ctypes.jschar.ptr,
michael@0 107 ctypes.jschar.ptr,
michael@0 108 ctypes.uint32_t);
michael@0 109 }
michael@0 110 };
michael@0 111
michael@0 112 DialogWatcher.prototype.getWindowText = function(hwnd) {
michael@0 113 var bufType = ctypes.ArrayType(ctypes.jschar);
michael@0 114 var buffer = new bufType(256);
michael@0 115
michael@0 116 if (this.getWindowTextW(hwnd, buffer, buffer.length)) {
michael@0 117 return buffer.readString();
michael@0 118 }
michael@0 119 };
michael@0 120
michael@0 121 DialogWatcher.prototype.processWindowEvents = function(timeout) {
michael@0 122 var onWinEvent = function(self, hook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) {
michael@0 123 var nhwnd = Number(hwnd)
michael@0 124 if (event == EVENT_OBJECT_SHOW) {
michael@0 125 if (nhwnd == self.hwnd) {
michael@0 126 // We've already picked up this event via FindWindow
michael@0 127 return;
michael@0 128 }
michael@0 129 var windowText = self.getWindowText(hwnd);
michael@0 130 if (windowText == self.titleText && self.onDialogStart) {
michael@0 131 self.hwnd = nhwnd;
michael@0 132 self.onDialogStart(nhwnd);
michael@0 133 }
michael@0 134 } else if (event == EVENT_OBJECT_HIDE && nhwnd == self.hwnd && self.onDialogEnd) {
michael@0 135 self.onDialogEnd();
michael@0 136 self.hwnd = null;
michael@0 137 }
michael@0 138 };
michael@0 139 var self = this;
michael@0 140 var callback = this.winEventProcType(function(hook, event, hwnd, idObject,
michael@0 141 idChild, dwEventThread,
michael@0 142 dwmsEventTime) {
michael@0 143 onWinEvent(self, hook, event, hwnd, idObject, idChild, dwEventThread,
michael@0 144 dwmsEventTime);
michael@0 145 } );
michael@0 146 var hook = this.setWinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_HIDE,
michael@0 147 0, callback, 0, 0,
michael@0 148 WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
michael@0 149 if (!hook) {
michael@0 150 return;
michael@0 151 }
michael@0 152 // Check if the window is already showing
michael@0 153 var hwnd = this.findWindow(null, this.titleText);
michael@0 154 if (hwnd && hwnd > 0) {
michael@0 155 this.hwnd = Number(hwnd);
michael@0 156 if (this.onDialogStart) {
michael@0 157 this.onDialogStart(this.hwnd);
michael@0 158 }
michael@0 159 }
michael@0 160
michael@0 161 if (!timeout) {
michael@0 162 timeout = INFINITE;
michael@0 163 }
michael@0 164
michael@0 165 var waitStatus = WAIT_OBJECT_0;
michael@0 166 var expectingStart = this.onDialogStart && this.hwnd === undefined;
michael@0 167 var startWaitTime = Date.now();
michael@0 168 while (this.hwnd === undefined || this.onDialogEnd && this.hwnd) {
michael@0 169 waitStatus = this.msgWaitForMultipleObjects(0, null, 0, expectingStart ?
michael@0 170 INFINITE : timeout, 0);
michael@0 171 if (waitStatus == WAIT_OBJECT_0) {
michael@0 172 var msg = new this.msgType;
michael@0 173 this.peekMessage(msg.address(), 0, 0, 0, PM_NOREMOVE);
michael@0 174 }
michael@0 175 if (waitStatus == WAIT_TIMEOUT || (Date.now() - startWaitTime) >= timeout) {
michael@0 176 break;
michael@0 177 }
michael@0 178 }
michael@0 179
michael@0 180 this.unhookWinEvent(hook);
michael@0 181 // Returns true if the hook was successful, something was found, and we never timed out
michael@0 182 return this.hwnd !== undefined && waitStatus == WAIT_OBJECT_0;
michael@0 183 };
michael@0 184

mercurial