toolkit/components/parentalcontrols/nsParentalControlsServiceWin.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:aba8e58dc64a
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "nsParentalControlsServiceWin.h"
7 #include "nsString.h"
8 #include "nsIArray.h"
9 #include "nsIWidget.h"
10 #include "nsIInterfaceRequestor.h"
11 #include "nsIInterfaceRequestorUtils.h"
12 #include "nsIFile.h"
13 #include "nsILocalFileWin.h"
14 #include "nsArrayUtils.h"
15 #include "nsIXULAppInfo.h"
16
17 static const CLSID CLSID_WinParentalControls = {0xE77CC89B,0x7401,0x4C04,{0x8C,0xED,0x14,0x9D,0xB3,0x5A,0xDD,0x04}};
18 static const IID IID_IWinParentalControls = {0x28B4D88B,0xE072,0x49E6,{0x80,0x4D,0x26,0xED,0xBE,0x21,0xA7,0xB9}};
19
20 NS_IMPL_ISUPPORTS(nsParentalControlsServiceWin, nsIParentalControlsService)
21
22 static HINSTANCE gAdvAPIDLLInst = nullptr;
23
24 decltype(EventWrite)* gEventWrite = nullptr;
25 decltype(EventRegister)* gEventRegister = nullptr;
26 decltype(EventUnregister)* gEventUnregister = nullptr;
27
28 nsParentalControlsServiceWin::nsParentalControlsServiceWin() :
29 mEnabled(false)
30 , mProvider(0)
31 , mPC(nullptr)
32 {
33 HRESULT hr;
34 CoInitialize(nullptr);
35 hr = CoCreateInstance(CLSID_WinParentalControls, nullptr, CLSCTX_INPROC,
36 IID_IWinParentalControls, (void**)&mPC);
37 if (FAILED(hr))
38 return;
39
40 nsRefPtr<IWPCSettings> wpcs;
41 if (FAILED(mPC->GetUserSettings(nullptr, getter_AddRefs(wpcs)))) {
42 // Not available on this os or not enabled for this user account or we're running as admin
43 mPC->Release();
44 mPC = nullptr;
45 return;
46 }
47
48 DWORD settings = 0;
49 wpcs->GetRestrictions(&settings);
50
51 if (settings) { // WPCFLAG_NO_RESTRICTION = 0
52 gAdvAPIDLLInst = ::LoadLibrary("Advapi32.dll");
53 if(gAdvAPIDLLInst)
54 {
55 gEventWrite = (decltype(EventWrite)*) GetProcAddress(gAdvAPIDLLInst, "EventWrite");
56 gEventRegister = (decltype(EventRegister)*) GetProcAddress(gAdvAPIDLLInst, "EventRegister");
57 gEventUnregister = (decltype(EventUnregister)*) GetProcAddress(gAdvAPIDLLInst, "EventUnregister");
58 }
59 mEnabled = true;
60 }
61 }
62
63 nsParentalControlsServiceWin::~nsParentalControlsServiceWin()
64 {
65 if (mPC)
66 mPC->Release();
67
68 if (gEventUnregister && mProvider)
69 gEventUnregister(mProvider);
70
71 if (gAdvAPIDLLInst)
72 ::FreeLibrary(gAdvAPIDLLInst);
73 }
74
75 //------------------------------------------------------------------------
76
77 NS_IMETHODIMP
78 nsParentalControlsServiceWin::GetParentalControlsEnabled(bool *aResult)
79 {
80 *aResult = false;
81
82 if (mEnabled)
83 *aResult = true;
84
85 return NS_OK;
86 }
87
88 NS_IMETHODIMP
89 nsParentalControlsServiceWin::GetBlockFileDownloadsEnabled(bool *aResult)
90 {
91 *aResult = false;
92
93 if (!mEnabled)
94 return NS_ERROR_NOT_AVAILABLE;
95
96 nsRefPtr<IWPCWebSettings> wpcws;
97 if (SUCCEEDED(mPC->GetWebSettings(nullptr, getter_AddRefs(wpcws)))) {
98 DWORD settings = 0;
99 wpcws->GetSettings(&settings);
100 if (settings == WPCFLAG_WEB_SETTING_DOWNLOADSBLOCKED)
101 *aResult = true;
102 }
103
104 return NS_OK;
105 }
106
107 NS_IMETHODIMP
108 nsParentalControlsServiceWin::GetLoggingEnabled(bool *aResult)
109 {
110 *aResult = false;
111
112 if (!mEnabled)
113 return NS_ERROR_NOT_AVAILABLE;
114
115 // Check the general purpose logging flag
116 nsRefPtr<IWPCSettings> wpcs;
117 if (SUCCEEDED(mPC->GetUserSettings(nullptr, getter_AddRefs(wpcs)))) {
118 BOOL enabled = FALSE;
119 wpcs->IsLoggingRequired(&enabled);
120 if (enabled)
121 *aResult = true;
122 }
123
124 return NS_OK;
125 }
126
127 // Post a log event to the system
128 NS_IMETHODIMP
129 nsParentalControlsServiceWin::Log(int16_t aEntryType, bool blocked, nsIURI *aSource, nsIFile *aTarget)
130 {
131 if (!mEnabled)
132 return NS_ERROR_NOT_AVAILABLE;
133
134 NS_ENSURE_ARG_POINTER(aSource);
135
136 // Confirm we should be logging
137 bool enabled;
138 GetLoggingEnabled(&enabled);
139 if (!enabled)
140 return NS_ERROR_NOT_AVAILABLE;
141
142 // Register a Vista log event provider associated with the parental controls channel.
143 if (!mProvider) {
144 if (!gEventRegister)
145 return NS_ERROR_NOT_AVAILABLE;
146 if (gEventRegister(&WPCPROV, nullptr, nullptr, &mProvider) != ERROR_SUCCESS)
147 return NS_ERROR_OUT_OF_MEMORY;
148 }
149
150 switch(aEntryType) {
151 case ePCLog_URIVisit:
152 // Not needed, Vista's web content filter handles this for us
153 break;
154 case ePCLog_FileDownload:
155 LogFileDownload(blocked, aSource, aTarget);
156 break;
157 default:
158 break;
159 }
160
161 return NS_OK;
162 }
163
164 // Override a single URI
165 NS_IMETHODIMP
166 nsParentalControlsServiceWin::RequestURIOverride(nsIURI *aTarget, nsIInterfaceRequestor *aWindowContext, bool *_retval)
167 {
168 *_retval = false;
169
170 if (!mEnabled)
171 return NS_ERROR_NOT_AVAILABLE;
172
173 NS_ENSURE_ARG_POINTER(aTarget);
174
175 nsAutoCString spec;
176 aTarget->GetSpec(spec);
177 if (spec.IsEmpty())
178 return NS_ERROR_INVALID_ARG;
179
180 HWND hWnd = nullptr;
181 // If we have a native window, use its handle instead
182 nsCOMPtr<nsIWidget> widget(do_GetInterface(aWindowContext));
183 if (widget)
184 hWnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
185 if (hWnd == nullptr)
186 hWnd = GetDesktopWindow();
187
188 BOOL ret;
189 nsRefPtr<IWPCWebSettings> wpcws;
190 if (SUCCEEDED(mPC->GetWebSettings(nullptr, getter_AddRefs(wpcws)))) {
191 wpcws->RequestURLOverride(hWnd, NS_ConvertUTF8toUTF16(spec).get(),
192 0, nullptr, &ret);
193 *_retval = ret;
194 }
195
196
197 return NS_OK;
198 }
199
200 // Override a web page
201 NS_IMETHODIMP
202 nsParentalControlsServiceWin::RequestURIOverrides(nsIArray *aTargets, nsIInterfaceRequestor *aWindowContext, bool *_retval)
203 {
204 *_retval = false;
205
206 if (!mEnabled)
207 return NS_ERROR_NOT_AVAILABLE;
208
209 NS_ENSURE_ARG_POINTER(aTargets);
210
211 uint32_t arrayLength = 0;
212 aTargets->GetLength(&arrayLength);
213 if (!arrayLength)
214 return NS_ERROR_INVALID_ARG;
215
216 if (arrayLength == 1) {
217 nsCOMPtr<nsIURI> uri = do_QueryElementAt(aTargets, 0);
218 if (!uri)
219 return NS_ERROR_INVALID_ARG;
220 return RequestURIOverride(uri, aWindowContext, _retval);
221 }
222
223 HWND hWnd = nullptr;
224 // If we have a native window, use its handle instead
225 nsCOMPtr<nsIWidget> widget(do_GetInterface(aWindowContext));
226 if (widget)
227 hWnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
228 if (hWnd == nullptr)
229 hWnd = GetDesktopWindow();
230
231 // The first entry should be the root uri
232 nsAutoCString rootSpec;
233 nsCOMPtr<nsIURI> rootURI = do_QueryElementAt(aTargets, 0);
234 if (!rootURI)
235 return NS_ERROR_INVALID_ARG;
236
237 rootURI->GetSpec(rootSpec);
238 if (rootSpec.IsEmpty())
239 return NS_ERROR_INVALID_ARG;
240
241 // Allocate an array of sub uri
242 int32_t count = arrayLength - 1;
243 nsAutoArrayPtr<LPCWSTR> arrUrls(new LPCWSTR[count]);
244 if (!arrUrls)
245 return NS_ERROR_OUT_OF_MEMORY;
246
247 uint32_t uriIdx = 0, idx;
248 for (idx = 1; idx < arrayLength; idx++)
249 {
250 nsCOMPtr<nsIURI> uri = do_QueryElementAt(aTargets, idx);
251 if (!uri)
252 continue;
253
254 nsAutoCString subURI;
255 if (NS_FAILED(uri->GetSpec(subURI)))
256 continue;
257
258 arrUrls[uriIdx] = (LPCWSTR)UTF8ToNewUnicode(subURI); // allocation
259 if (!arrUrls[uriIdx])
260 continue;
261
262 uriIdx++;
263 }
264
265 if (!uriIdx)
266 return NS_ERROR_INVALID_ARG;
267
268 BOOL ret;
269 nsRefPtr<IWPCWebSettings> wpcws;
270 if (SUCCEEDED(mPC->GetWebSettings(nullptr, getter_AddRefs(wpcws)))) {
271 wpcws->RequestURLOverride(hWnd, NS_ConvertUTF8toUTF16(rootSpec).get(),
272 uriIdx, (LPCWSTR*)arrUrls.get(), &ret);
273 *_retval = ret;
274 }
275
276 // Free up the allocated strings in our array
277 for (idx = 0; idx < uriIdx; idx++)
278 NS_Free((void*)arrUrls[idx]);
279
280 return NS_OK;
281 }
282
283 //------------------------------------------------------------------------
284
285 // Sends a file download event to the Vista Event Log
286 void
287 nsParentalControlsServiceWin::LogFileDownload(bool blocked, nsIURI *aSource, nsIFile *aTarget)
288 {
289 nsAutoCString curi;
290
291 if (!gEventWrite)
292 return;
293
294 // Note, EventDataDescCreate is a macro defined in the headers, not a function
295
296 aSource->GetSpec(curi);
297 nsAutoString uri = NS_ConvertUTF8toUTF16(curi);
298
299 // Get the name of the currently running process
300 nsCOMPtr<nsIXULAppInfo> appInfo = do_GetService("@mozilla.org/xre/app-info;1");
301 nsAutoCString asciiAppName;
302 if (appInfo)
303 appInfo->GetName(asciiAppName);
304 nsAutoString appName = NS_ConvertUTF8toUTF16(asciiAppName);
305
306 static const WCHAR fill[] = L"";
307
308 // See wpcevent.h and msdn for event formats
309 EVENT_DATA_DESCRIPTOR eventData[WPC_ARGS_FILEDOWNLOADEVENT_CARGS];
310 DWORD dwBlocked = blocked;
311
312 EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_URL], (const void*)uri.get(),
313 ((ULONG)uri.Length()+1)*sizeof(WCHAR));
314 EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_APPNAME], (const void*)appName.get(),
315 ((ULONG)appName.Length()+1)*sizeof(WCHAR));
316 EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_VERSION], (const void*)fill, sizeof(fill));
317 EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_BLOCKED], (const void*)&dwBlocked,
318 sizeof(dwBlocked));
319
320 nsCOMPtr<nsILocalFileWin> local(do_QueryInterface(aTarget)); // May be null
321 if (local) {
322 nsAutoString path;
323 local->GetCanonicalPath(path);
324 EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_PATH], (const void*)path.get(),
325 ((ULONG)path.Length()+1)*sizeof(WCHAR));
326 }
327 else {
328 EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_PATH], (const void*)fill, sizeof(fill));
329 }
330
331 gEventWrite(mProvider, &WPCEVENT_WEB_FILEDOWNLOAD, ARRAYSIZE(eventData), eventData);
332 }
333

mercurial