toolkit/components/parentalcontrols/nsParentalControlsServiceWin.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial