Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* ***** BEGIN LICENSE BLOCK *****
2 *
3 * Copyright (c) 2008, Mozilla Corporation
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * * Neither the name of the Mozilla Corporation nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contributor(s):
30 * Josh Aas <josh@mozilla.com>
31 * Jim Mathies <jmathies@mozilla.com>
32 *
33 * ***** END LICENSE BLOCK ***** */
35 #include "nptest_platform.h"
37 #include <windows.h>
38 #include <windowsx.h>
39 #include <stdio.h>
41 #include <d3d10_1.h>
43 using namespace std;
45 void SetSubclass(HWND hWnd, InstanceData* instanceData);
46 void ClearSubclass(HWND hWnd);
47 LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
49 struct _PlatformData {
50 HWND childWindow;
51 ID3D10Device1 *device;
52 ID3D10Texture2D *frontBuffer;
53 ID3D10Texture2D *backBuffer;
54 };
56 bool
57 pluginSupportsWindowMode()
58 {
59 return true;
60 }
62 bool
63 pluginSupportsWindowlessMode()
64 {
65 return true;
66 }
68 bool
69 pluginSupportsAsyncBitmapDrawing()
70 {
71 return true;
72 }
74 NPError
75 pluginInstanceInit(InstanceData* instanceData)
76 {
77 NPP npp = instanceData->npp;
79 instanceData->platformData = static_cast<PlatformData*>
80 (NPN_MemAlloc(sizeof(PlatformData)));
81 if (!instanceData->platformData)
82 return NPERR_OUT_OF_MEMORY_ERROR;
84 instanceData->platformData->childWindow = nullptr;
85 instanceData->platformData->device = nullptr;
86 instanceData->platformData->frontBuffer = nullptr;
87 instanceData->platformData->backBuffer = nullptr;
88 return NPERR_NO_ERROR;
89 }
91 void
92 pluginInstanceShutdown(InstanceData* instanceData)
93 {
94 PlatformData *pd = instanceData->platformData;
95 if (pd->frontBuffer) {
96 pd->frontBuffer->Release();
97 }
98 if (pd->backBuffer) {
99 pd->backBuffer->Release();
100 }
101 if (pd->device) {
102 pd->device->Release();
103 }
104 NPN_MemFree(instanceData->platformData);
105 instanceData->platformData = 0;
106 }
108 static ID3D10Device1*
109 getD3D10Device()
110 {
111 ID3D10Device1 *device;
113 HMODULE d3d10module = LoadLibraryA("d3d10_1.dll");
114 decltype(D3D10CreateDevice1)* createD3DDevice =
115 (decltype(D3D10CreateDevice1)*) GetProcAddress(d3d10module,
116 "D3D10CreateDevice1");
118 if (createD3DDevice) {
119 HMODULE dxgiModule = LoadLibraryA("dxgi.dll");
120 decltype(CreateDXGIFactory1)* createDXGIFactory1 =
121 (decltype(CreateDXGIFactory1)*) GetProcAddress(dxgiModule,
122 "CreateDXGIFactory1");
124 HRESULT hr;
126 // Try to use a DXGI 1.1 adapter in order to share resources
127 // across processes.
128 IDXGIAdapter1 *adapter1;
129 if (createDXGIFactory1) {
130 IDXGIFactory1 *factory1;
131 hr = createDXGIFactory1(__uuidof(IDXGIFactory1),
132 (void**)&factory1);
134 if (FAILED(hr) || !factory1) {
135 // Uh-oh
136 return nullptr;
137 }
139 hr = factory1->EnumAdapters1(0, &adapter1);
141 if (SUCCEEDED(hr) && adapter1) {
142 hr = adapter1->CheckInterfaceSupport(__uuidof(ID3D10Device),
143 nullptr);
144 if (FAILED(hr)) {
145 adapter1 = nullptr;
146 }
147 }
148 factory1->Release();
149 }
151 hr = createD3DDevice(
152 adapter1,
153 D3D10_DRIVER_TYPE_HARDWARE,
154 nullptr,
155 D3D10_CREATE_DEVICE_BGRA_SUPPORT |
156 D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
157 D3D10_FEATURE_LEVEL_10_0,
158 D3D10_1_SDK_VERSION,
159 &device);
161 adapter1->Release();
162 }
164 return device;
165 }
167 void
168 pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow)
169 {
170 instanceData->window = *newWindow;
171 NPP npp = instanceData->npp;
173 if (instanceData->asyncDrawing == AD_DXGI) {
174 if (instanceData->frontBuffer &&
175 instanceData->frontBuffer->size.width == newWindow->width &&
176 instanceData->frontBuffer->size.height == newWindow->height) {
177 return;
178 }
179 if (instanceData->frontBuffer) {
180 instanceData->platformData->frontBuffer->Release();
181 instanceData->platformData->frontBuffer = nullptr;
182 NPN_FinalizeAsyncSurface(npp, instanceData->frontBuffer);
183 NPN_MemFree(instanceData->frontBuffer);
184 }
185 if (instanceData->backBuffer) {
186 instanceData->platformData->backBuffer->Release();
187 instanceData->platformData->backBuffer = nullptr;
188 NPN_FinalizeAsyncSurface(npp, instanceData->backBuffer);
189 NPN_MemFree(instanceData->backBuffer);
190 }
192 if (!instanceData->platformData->device) {
193 instanceData->platformData->device = getD3D10Device();
194 }
196 ID3D10Device1 *dev = instanceData->platformData->device;
198 if (!dev) {
199 return;
200 }
202 instanceData->frontBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface));
203 instanceData->backBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface));
205 NPSize size;
206 size.width = newWindow->width;
207 size.height = newWindow->height;
209 memset(instanceData->frontBuffer, 0, sizeof(NPAsyncSurface));
210 memset(instanceData->backBuffer, 0, sizeof(NPAsyncSurface));
212 NPN_InitAsyncSurface(npp, &size, NPImageFormatBGRA32, nullptr, instanceData->frontBuffer);
213 NPN_InitAsyncSurface(npp, &size, NPImageFormatBGRA32, nullptr, instanceData->backBuffer);
215 dev->OpenSharedResource(instanceData->frontBuffer->sharedHandle, __uuidof(ID3D10Texture2D), (void**)&instanceData->platformData->frontBuffer);
216 dev->OpenSharedResource(instanceData->backBuffer->sharedHandle, __uuidof(ID3D10Texture2D), (void**)&instanceData->platformData->backBuffer);
218 pluginDrawAsyncDxgiColor(instanceData);
219 }
220 }
222 #define CHILD_WIDGET_SIZE 10
224 void
225 pluginWidgetInit(InstanceData* instanceData, void* oldWindow)
226 {
227 HWND hWnd = (HWND)instanceData->window.window;
228 if (oldWindow) {
229 // chrashtests/539897-1.html excercises this code
230 HWND hWndOld = (HWND)oldWindow;
231 ClearSubclass(hWndOld);
232 if (instanceData->platformData->childWindow) {
233 ::DestroyWindow(instanceData->platformData->childWindow);
234 }
235 }
237 SetSubclass(hWnd, instanceData);
239 instanceData->platformData->childWindow =
240 ::CreateWindowW(L"SCROLLBAR", L"Dummy child window",
241 WS_CHILD, 0, 0, CHILD_WIDGET_SIZE, CHILD_WIDGET_SIZE, hWnd, nullptr,
242 nullptr, nullptr);
243 }
245 static void
246 drawToDC(InstanceData* instanceData, HDC dc,
247 int x, int y, int width, int height)
248 {
249 switch (instanceData->scriptableObject->drawMode) {
250 case DM_DEFAULT:
251 {
252 const RECT fill = { x, y, x + width, y + height };
254 int oldBkMode = ::SetBkMode(dc, TRANSPARENT);
255 HBRUSH brush = ::CreateSolidBrush(RGB(0, 0, 0));
256 if (brush) {
257 ::FillRect(dc, &fill, brush);
258 ::DeleteObject(brush);
259 }
260 if (width > 6 && height > 6) {
261 brush = ::CreateSolidBrush(RGB(192, 192, 192));
262 if (brush) {
263 RECT inset = { x + 3, y + 3, x + width - 3, y + height - 3 };
264 ::FillRect(dc, &inset, brush);
265 ::DeleteObject(brush);
266 }
267 }
269 const char* uaString = NPN_UserAgent(instanceData->npp);
270 if (uaString && width > 10 && height > 10) {
271 HFONT font =
272 ::CreateFontA(20, 0, 0, 0, 400, FALSE, FALSE, FALSE,
273 DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
274 CLIP_DEFAULT_PRECIS, 5, // CLEARTYPE_QUALITY
275 DEFAULT_PITCH, "Arial");
276 if (font) {
277 HFONT oldFont = (HFONT)::SelectObject(dc, font);
278 RECT inset = { x + 5, y + 5, x + width - 5, y + height - 5 };
279 ::DrawTextA(dc, uaString, -1, &inset,
280 DT_LEFT | DT_TOP | DT_NOPREFIX | DT_WORDBREAK);
281 ::SelectObject(dc, oldFont);
282 ::DeleteObject(font);
283 }
284 }
285 ::SetBkMode(dc, oldBkMode);
286 }
287 break;
289 case DM_SOLID_COLOR:
290 {
291 HDC offscreenDC = ::CreateCompatibleDC(dc);
292 if (!offscreenDC)
293 return;
295 const BITMAPV4HEADER bitmapheader = {
296 sizeof(BITMAPV4HEADER),
297 width,
298 height,
299 1, // planes
300 32, // bits
301 BI_BITFIELDS,
302 0, // unused size
303 0, 0, // unused metrics
304 0, 0, // unused colors used/important
305 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, // ARGB masks
306 };
307 uint32_t *pixelData;
308 HBITMAP offscreenBitmap =
309 ::CreateDIBSection(dc, reinterpret_cast<const BITMAPINFO*>(&bitmapheader),
310 0, reinterpret_cast<void**>(&pixelData), 0, 0);
311 if (!offscreenBitmap)
312 return;
314 uint32_t rgba = instanceData->scriptableObject->drawColor;
315 unsigned int alpha = ((rgba & 0xFF000000) >> 24);
316 BYTE r = ((rgba & 0xFF0000) >> 16);
317 BYTE g = ((rgba & 0xFF00) >> 8);
318 BYTE b = (rgba & 0xFF);
320 // Windows expects premultiplied
321 r = BYTE(float(alpha * r) / 0xFF);
322 g = BYTE(float(alpha * g) / 0xFF);
323 b = BYTE(float(alpha * b) / 0xFF);
324 uint32_t premultiplied =
325 (alpha << 24) + (r << 16) + (g << 8) + b;
327 for (uint32_t* lastPixel = pixelData + width * height;
328 pixelData < lastPixel;
329 ++pixelData)
330 *pixelData = premultiplied;
332 ::SelectObject(offscreenDC, offscreenBitmap);
333 BLENDFUNCTION blendFunc;
334 blendFunc.BlendOp = AC_SRC_OVER;
335 blendFunc.BlendFlags = 0;
336 blendFunc.SourceConstantAlpha = 255;
337 blendFunc.AlphaFormat = AC_SRC_ALPHA;
338 ::AlphaBlend(dc, x, y, width, height, offscreenDC, 0, 0, width, height,
339 blendFunc);
341 ::DeleteObject(offscreenDC);
342 ::DeleteObject(offscreenBitmap);
343 }
344 break;
345 }
346 }
348 void
349 pluginDraw(InstanceData* instanceData)
350 {
351 NPP npp = instanceData->npp;
352 if (!npp)
353 return;
355 HDC hdc = nullptr;
356 PAINTSTRUCT ps;
358 notifyDidPaint(instanceData);
360 if (instanceData->hasWidget)
361 hdc = ::BeginPaint((HWND)instanceData->window.window, &ps);
362 else
363 hdc = (HDC)instanceData->window.window;
365 if (hdc == nullptr)
366 return;
368 // Push the browser's hdc on the resource stack. If this test plugin is windowless,
369 // we share the drawing surface with the rest of the browser.
370 int savedDCID = SaveDC(hdc);
372 // When we have a widget, window.x/y are meaningless since our widget
373 // is always positioned correctly and we just draw into it at 0,0.
374 int x = instanceData->hasWidget ? 0 : instanceData->window.x;
375 int y = instanceData->hasWidget ? 0 : instanceData->window.y;
376 int width = instanceData->window.width;
377 int height = instanceData->window.height;
378 drawToDC(instanceData, hdc, x, y, width, height);
380 // Pop our hdc changes off the resource stack
381 RestoreDC(hdc, savedDCID);
383 if (instanceData->hasWidget)
384 ::EndPaint((HWND)instanceData->window.window, &ps);
385 }
387 /* script interface */
389 int32_t
390 pluginGetEdge(InstanceData* instanceData, RectEdge edge)
391 {
392 if (!instanceData || !instanceData->hasWidget)
393 return NPTEST_INT32_ERROR;
395 // Get the plugin client rect in screen coordinates
396 RECT rect = {0};
397 if (!::GetClientRect((HWND)instanceData->window.window, &rect))
398 return NPTEST_INT32_ERROR;
399 ::MapWindowPoints((HWND)instanceData->window.window, nullptr,
400 (LPPOINT)&rect, 2);
402 // Get the toplevel window frame rect in screen coordinates
403 HWND rootWnd = ::GetAncestor((HWND)instanceData->window.window, GA_ROOT);
404 if (!rootWnd)
405 return NPTEST_INT32_ERROR;
406 RECT rootRect;
407 if (!::GetWindowRect(rootWnd, &rootRect))
408 return NPTEST_INT32_ERROR;
410 switch (edge) {
411 case EDGE_LEFT:
412 return rect.left - rootRect.left;
413 case EDGE_TOP:
414 return rect.top - rootRect.top;
415 case EDGE_RIGHT:
416 return rect.right - rootRect.left;
417 case EDGE_BOTTOM:
418 return rect.bottom - rootRect.top;
419 }
421 return NPTEST_INT32_ERROR;
422 }
424 static BOOL
425 getWindowRegion(HWND wnd, HRGN rgn)
426 {
427 if (::GetWindowRgn(wnd, rgn) != ERROR)
428 return TRUE;
430 RECT clientRect;
431 if (!::GetClientRect(wnd, &clientRect))
432 return FALSE;
433 return ::SetRectRgn(rgn, 0, 0, clientRect.right, clientRect.bottom);
434 }
436 static RGNDATA*
437 computeClipRegion(InstanceData* instanceData)
438 {
439 HWND wnd = (HWND)instanceData->window.window;
440 HRGN rgn = ::CreateRectRgn(0, 0, 0, 0);
441 if (!rgn)
442 return nullptr;
443 HRGN ancestorRgn = ::CreateRectRgn(0, 0, 0, 0);
444 if (!ancestorRgn) {
445 ::DeleteObject(rgn);
446 return nullptr;
447 }
448 if (!getWindowRegion(wnd, rgn)) {
449 ::DeleteObject(ancestorRgn);
450 ::DeleteObject(rgn);
451 return nullptr;
452 }
454 HWND ancestor = wnd;
455 for (;;) {
456 ancestor = ::GetAncestor(ancestor, GA_PARENT);
457 if (!ancestor || ancestor == ::GetDesktopWindow()) {
458 ::DeleteObject(ancestorRgn);
460 DWORD size = ::GetRegionData(rgn, 0, nullptr);
461 if (!size) {
462 ::DeleteObject(rgn);
463 return nullptr;
464 }
466 HANDLE heap = ::GetProcessHeap();
467 RGNDATA* data = static_cast<RGNDATA*>(::HeapAlloc(heap, 0, size));
468 if (!data) {
469 ::DeleteObject(rgn);
470 return nullptr;
471 }
472 DWORD result = ::GetRegionData(rgn, size, data);
473 ::DeleteObject(rgn);
474 if (!result) {
475 ::HeapFree(heap, 0, data);
476 return nullptr;
477 }
479 return data;
480 }
482 if (!getWindowRegion(ancestor, ancestorRgn)) {
483 ::DeleteObject(ancestorRgn);
484 ::DeleteObject(rgn);
485 return 0;
486 }
488 POINT pt = { 0, 0 };
489 ::MapWindowPoints(ancestor, wnd, &pt, 1);
490 if (::OffsetRgn(ancestorRgn, pt.x, pt.y) == ERROR ||
491 ::CombineRgn(rgn, rgn, ancestorRgn, RGN_AND) == ERROR) {
492 ::DeleteObject(ancestorRgn);
493 ::DeleteObject(rgn);
494 return 0;
495 }
496 }
497 }
499 int32_t
500 pluginGetClipRegionRectCount(InstanceData* instanceData)
501 {
502 RGNDATA* data = computeClipRegion(instanceData);
503 if (!data)
504 return NPTEST_INT32_ERROR;
506 int32_t result = data->rdh.nCount;
507 ::HeapFree(::GetProcessHeap(), 0, data);
508 return result;
509 }
511 static int32_t
512 addOffset(LONG coord, int32_t offset)
513 {
514 if (offset == NPTEST_INT32_ERROR)
515 return NPTEST_INT32_ERROR;
516 return coord + offset;
517 }
519 int32_t
520 pluginGetClipRegionRectEdge(InstanceData* instanceData,
521 int32_t rectIndex, RectEdge edge)
522 {
523 RGNDATA* data = computeClipRegion(instanceData);
524 if (!data)
525 return NPTEST_INT32_ERROR;
527 HANDLE heap = ::GetProcessHeap();
528 if (rectIndex >= int32_t(data->rdh.nCount)) {
529 ::HeapFree(heap, 0, data);
530 return NPTEST_INT32_ERROR;
531 }
533 RECT rect = reinterpret_cast<RECT*>(data->Buffer)[rectIndex];
534 ::HeapFree(heap, 0, data);
536 switch (edge) {
537 case EDGE_LEFT:
538 return addOffset(rect.left, pluginGetEdge(instanceData, EDGE_LEFT));
539 case EDGE_TOP:
540 return addOffset(rect.top, pluginGetEdge(instanceData, EDGE_TOP));
541 case EDGE_RIGHT:
542 return addOffset(rect.right, pluginGetEdge(instanceData, EDGE_LEFT));
543 case EDGE_BOTTOM:
544 return addOffset(rect.bottom, pluginGetEdge(instanceData, EDGE_TOP));
545 }
547 return NPTEST_INT32_ERROR;
548 }
550 /* windowless plugin events */
552 static bool
553 handleEventInternal(InstanceData* instanceData, NPEvent* pe, LRESULT* result)
554 {
555 switch ((UINT)pe->event) {
556 case WM_PAINT:
557 pluginDraw(instanceData);
558 return true;
560 case WM_MOUSEACTIVATE:
561 if (instanceData->hasWidget) {
562 ::SetFocus((HWND)instanceData->window.window);
563 *result = MA_ACTIVATEANDEAT;
564 return true;
565 }
566 return false;
568 case WM_MOUSEWHEEL:
569 return true;
571 case WM_WINDOWPOSCHANGED: {
572 WINDOWPOS* pPos = (WINDOWPOS*)pe->lParam;
573 instanceData->winX = instanceData->winY = 0;
574 if (pPos) {
575 instanceData->winX = pPos->x;
576 instanceData->winY = pPos->y;
577 return true;
578 }
579 return false;
580 }
582 case WM_MOUSEMOVE:
583 case WM_LBUTTONDOWN:
584 case WM_LBUTTONUP:
585 case WM_MBUTTONDOWN:
586 case WM_MBUTTONUP:
587 case WM_RBUTTONDOWN:
588 case WM_RBUTTONUP: {
589 int x = instanceData->hasWidget ? 0 : instanceData->winX;
590 int y = instanceData->hasWidget ? 0 : instanceData->winY;
591 instanceData->lastMouseX = GET_X_LPARAM(pe->lParam) - x;
592 instanceData->lastMouseY = GET_Y_LPARAM(pe->lParam) - y;
593 if ((UINT)pe->event == WM_LBUTTONUP) {
594 instanceData->mouseUpEventCount++;
595 }
596 return true;
597 }
599 case WM_KEYDOWN:
600 instanceData->lastKeyText.erase();
601 *result = 0;
602 return true;
604 case WM_CHAR: {
605 *result = 0;
606 wchar_t uniChar = static_cast<wchar_t>(pe->wParam);
607 if (!uniChar) {
608 return true;
609 }
610 char utf8Char[6];
611 int len =
612 ::WideCharToMultiByte(CP_UTF8, 0, &uniChar, 1, utf8Char, 6,
613 nullptr, nullptr);
614 if (len == 0 || len > 6) {
615 return true;
616 }
617 instanceData->lastKeyText.append(utf8Char, len);
618 return true;
619 }
621 default:
622 return false;
623 }
624 }
626 int16_t
627 pluginHandleEvent(InstanceData* instanceData, void* event)
628 {
629 NPEvent* pe = (NPEvent*)event;
631 if (pe == nullptr || instanceData == nullptr ||
632 instanceData->window.type != NPWindowTypeDrawable)
633 return 0;
635 LRESULT result = 0;
636 return handleEventInternal(instanceData, pe, &result);
637 }
639 /* windowed plugin events */
641 LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
642 {
643 WNDPROC wndProc = (WNDPROC)GetProp(hWnd, "MozillaWndProc");
644 if (!wndProc)
645 return 0;
646 InstanceData* pInstance = (InstanceData*)GetProp(hWnd, "InstanceData");
647 if (!pInstance)
648 return 0;
650 NPEvent event = { static_cast<uint16_t>(uMsg), wParam, lParam };
652 LRESULT result = 0;
653 if (handleEventInternal(pInstance, &event, &result))
654 return result;
656 if (uMsg == WM_CLOSE) {
657 ClearSubclass((HWND)pInstance->window.window);
658 }
660 return CallWindowProc(wndProc, hWnd, uMsg, wParam, lParam);
661 }
663 void
664 ClearSubclass(HWND hWnd)
665 {
666 if (GetProp(hWnd, "MozillaWndProc")) {
667 ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)GetProp(hWnd, "MozillaWndProc"));
668 RemoveProp(hWnd, "MozillaWndProc");
669 RemoveProp(hWnd, "InstanceData");
670 }
671 }
673 void
674 SetSubclass(HWND hWnd, InstanceData* instanceData)
675 {
676 // Subclass the plugin window so we can handle our own windows events.
677 SetProp(hWnd, "InstanceData", (HANDLE)instanceData);
678 WNDPROC origProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)PluginWndProc);
679 SetProp(hWnd, "MozillaWndProc", (HANDLE)origProc);
680 }
682 static void checkEquals(int a, int b, const char* msg, string& error)
683 {
684 if (a == b) {
685 return;
686 }
688 error.append(msg);
689 char buf[100];
690 sprintf(buf, " (got %d, expected %d)\n", a, b);
691 error.append(buf);
692 }
694 void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error)
695 {
696 if (instanceData->platformData->childWindow) {
697 RECT childRect;
698 ::GetWindowRect(instanceData->platformData->childWindow, &childRect);
699 RECT ourRect;
700 HWND hWnd = (HWND)instanceData->window.window;
701 ::GetWindowRect(hWnd, &ourRect);
702 checkEquals(childRect.left, ourRect.left, "Child widget left", error);
703 checkEquals(childRect.top, ourRect.top, "Child widget top", error);
704 checkEquals(childRect.right, childRect.left + CHILD_WIDGET_SIZE, "Child widget width", error);
705 checkEquals(childRect.bottom, childRect.top + CHILD_WIDGET_SIZE, "Child widget height", error);
706 }
707 }
709 void
710 pluginDrawAsyncDxgiColor(InstanceData* id)
711 {
712 PlatformData *pd = id->platformData;
714 ID3D10Device1 *dev = pd->device;
716 IDXGIKeyedMutex *mutex;
717 pd->backBuffer->QueryInterface(&mutex);
719 mutex->AcquireSync(0, INFINITE);
720 ID3D10RenderTargetView *rtView;
721 dev->CreateRenderTargetView(pd->backBuffer, nullptr, &rtView);
723 uint32_t rgba = id->scriptableObject->drawColor;
725 unsigned char subpixels[4];
726 subpixels[0] = rgba & 0xFF;
727 subpixels[1] = (rgba & 0xFF00) >> 8;
728 subpixels[2] = (rgba & 0xFF0000) >> 16;
729 subpixels[3] = (rgba & 0xFF000000) >> 24;
731 float color[4];
732 color[2] = float(subpixels[3] * subpixels[0]) / 0xFE01;
733 color[1] = float(subpixels[3] * subpixels[1]) / 0xFE01;
734 color[0] = float(subpixels[3] * subpixels[2]) / 0xFE01;
735 color[3] = float(subpixels[3]) / 0xFF;
736 dev->ClearRenderTargetView(rtView, color);
737 rtView->Release();
739 mutex->ReleaseSync(0);
740 mutex->Release();
742 NPN_SetCurrentAsyncSurface(id->npp, id->backBuffer, nullptr);
743 NPAsyncSurface *oldFront = id->frontBuffer;
744 id->frontBuffer = id->backBuffer;
745 id->backBuffer = oldFront;
746 ID3D10Texture2D *oldFrontT = pd->frontBuffer;
747 pd->frontBuffer = pd->backBuffer;
748 pd->backBuffer = oldFrontT;
749 }