Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "nsWinUtils.h"
10 #include "Compatibility.h"
11 #include "DocAccessible.h"
12 #include "nsCoreUtils.h"
14 #include "mozilla/Preferences.h"
15 #include "nsArrayUtils.h"
16 #include "nsIArray.h"
17 #include "nsIDocument.h"
18 #include "nsIDocShellTreeItem.h"
19 #include "nsXULAppAPI.h"
21 using namespace mozilla;
22 using namespace mozilla::a11y;
24 // Window property used by ipc related code in identifying accessible
25 // tab windows.
26 const wchar_t* kPropNameTabContent = L"AccessibleTabWindow";
28 /**
29 * WindowProc to process WM_GETOBJECT messages, used in windows emulation mode.
30 */
31 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg,
32 WPARAM wParam, LPARAM lParam);
34 nsRefPtrHashtable<nsPtrHashKey<void>, DocAccessible>* nsWinUtils::sHWNDCache = nullptr;
36 already_AddRefed<nsIDOMCSSStyleDeclaration>
37 nsWinUtils::GetComputedStyleDeclaration(nsIContent* aContent)
38 {
39 nsIContent* elm = nsCoreUtils::GetDOMElementFor(aContent);
40 if (!elm)
41 return nullptr;
43 // Returns number of items in style declaration
44 nsCOMPtr<nsIDOMWindow> window =
45 do_QueryInterface(elm->OwnerDoc()->GetWindow());
46 if (!window)
47 return nullptr;
49 nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
50 nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(elm));
51 window->GetComputedStyle(domElement, EmptyString(), getter_AddRefs(cssDecl));
52 return cssDecl.forget();
53 }
55 bool
56 nsWinUtils::MaybeStartWindowEmulation()
57 {
58 // Register window class that'll be used for document accessibles associated
59 // with tabs.
60 if (Compatibility::IsJAWS() || Compatibility::IsWE() ||
61 Compatibility::IsDolphin() ||
62 XRE_GetProcessType() == GeckoProcessType_Content) {
63 RegisterNativeWindow(kClassNameTabContent);
64 sHWNDCache = new nsRefPtrHashtable<nsPtrHashKey<void>, DocAccessible>(4);
65 return true;
66 }
68 return false;
69 }
71 void
72 nsWinUtils::ShutdownWindowEmulation()
73 {
74 // Unregister window call that's used for document accessibles associated
75 // with tabs.
76 if (IsWindowEmulationStarted())
77 ::UnregisterClassW(kClassNameTabContent, GetModuleHandle(nullptr));
78 }
80 bool
81 nsWinUtils::IsWindowEmulationStarted()
82 {
83 return sHWNDCache != nullptr;
84 }
86 void
87 nsWinUtils::RegisterNativeWindow(LPCWSTR aWindowClass)
88 {
89 WNDCLASSW wc;
90 wc.style = CS_GLOBALCLASS;
91 wc.lpfnWndProc = WindowProc;
92 wc.cbClsExtra = 0;
93 wc.cbWndExtra = 0;
94 wc.hInstance = GetModuleHandle(nullptr);
95 wc.hIcon = nullptr;
96 wc.hCursor = nullptr;
97 wc.hbrBackground = nullptr;
98 wc.lpszMenuName = nullptr;
99 wc.lpszClassName = aWindowClass;
100 ::RegisterClassW(&wc);
101 }
103 HWND
104 nsWinUtils::CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd,
105 int aX, int aY, int aWidth, int aHeight,
106 bool aIsActive)
107 {
108 HWND hwnd = ::CreateWindowExW(WS_EX_TRANSPARENT, aWindowClass,
109 L"NetscapeDispatchWnd",
110 WS_CHILD | (aIsActive ? WS_VISIBLE : 0),
111 aX, aY, aWidth, aHeight,
112 aParentWnd,
113 nullptr,
114 GetModuleHandle(nullptr),
115 nullptr);
116 if (hwnd) {
117 // Mark this window so that ipc related code can identify it.
118 ::SetPropW(hwnd, kPropNameTabContent, (HANDLE)1);
119 }
120 return hwnd;
121 }
123 void
124 nsWinUtils::ShowNativeWindow(HWND aWnd)
125 {
126 ::ShowWindow(aWnd, SW_SHOW);
127 }
129 void
130 nsWinUtils::HideNativeWindow(HWND aWnd)
131 {
132 ::SetWindowPos(aWnd, nullptr, 0, 0, 0, 0,
133 SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
134 SWP_NOZORDER | SWP_NOACTIVATE);
135 }
137 LRESULT CALLBACK
138 WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
139 {
140 // Note, this window's message handling should not invoke any call that
141 // may result in a cross-process ipc call. Doing so may violate RPC
142 // message semantics.
144 switch (msg) {
145 case WM_GETOBJECT:
146 {
147 if (lParam == OBJID_CLIENT) {
148 DocAccessible* document =
149 nsWinUtils::sHWNDCache->GetWeak(static_cast<void*>(hWnd));
150 if (document) {
151 IAccessible* msaaAccessible = nullptr;
152 document->GetNativeInterface((void**)&msaaAccessible); // does an addref
153 if (msaaAccessible) {
154 LRESULT result = ::LresultFromObject(IID_IAccessible, wParam,
155 msaaAccessible); // does an addref
156 msaaAccessible->Release(); // release extra addref
157 return result;
158 }
159 }
160 }
161 return 0;
162 }
163 case WM_NCHITTEST:
164 {
165 LRESULT lRet = ::DefWindowProc(hWnd, msg, wParam, lParam);
166 if (HTCLIENT == lRet)
167 lRet = HTTRANSPARENT;
168 return lRet;
169 }
170 }
172 return ::DefWindowProcW(hWnd, msg, wParam, lParam);
173 }