toolkit/components/parentalcontrols/nsParentalControlsServiceWin.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/components/parentalcontrols/nsParentalControlsServiceWin.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,333 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "nsParentalControlsServiceWin.h"
    1.10 +#include "nsString.h"
    1.11 +#include "nsIArray.h"
    1.12 +#include "nsIWidget.h"
    1.13 +#include "nsIInterfaceRequestor.h"
    1.14 +#include "nsIInterfaceRequestorUtils.h"
    1.15 +#include "nsIFile.h"
    1.16 +#include "nsILocalFileWin.h"
    1.17 +#include "nsArrayUtils.h"
    1.18 +#include "nsIXULAppInfo.h"
    1.19 +
    1.20 +static const CLSID CLSID_WinParentalControls = {0xE77CC89B,0x7401,0x4C04,{0x8C,0xED,0x14,0x9D,0xB3,0x5A,0xDD,0x04}};
    1.21 +static const IID IID_IWinParentalControls  = {0x28B4D88B,0xE072,0x49E6,{0x80,0x4D,0x26,0xED,0xBE,0x21,0xA7,0xB9}};
    1.22 +
    1.23 +NS_IMPL_ISUPPORTS(nsParentalControlsServiceWin, nsIParentalControlsService)
    1.24 +
    1.25 +static HINSTANCE gAdvAPIDLLInst = nullptr;
    1.26 +
    1.27 +decltype(EventWrite)* gEventWrite = nullptr;
    1.28 +decltype(EventRegister)* gEventRegister = nullptr;
    1.29 +decltype(EventUnregister)* gEventUnregister = nullptr;
    1.30 +
    1.31 +nsParentalControlsServiceWin::nsParentalControlsServiceWin() :
    1.32 +  mEnabled(false)
    1.33 +, mProvider(0)
    1.34 +, mPC(nullptr)
    1.35 +{
    1.36 +  HRESULT hr;
    1.37 +  CoInitialize(nullptr);
    1.38 +  hr = CoCreateInstance(CLSID_WinParentalControls, nullptr, CLSCTX_INPROC,
    1.39 +                        IID_IWinParentalControls, (void**)&mPC);
    1.40 +  if (FAILED(hr))
    1.41 +    return;
    1.42 +
    1.43 +  nsRefPtr<IWPCSettings> wpcs;
    1.44 +  if (FAILED(mPC->GetUserSettings(nullptr, getter_AddRefs(wpcs)))) {
    1.45 +    // Not available on this os or not enabled for this user account or we're running as admin
    1.46 +    mPC->Release();
    1.47 +    mPC = nullptr;
    1.48 +    return;
    1.49 +  }
    1.50 +
    1.51 +  DWORD settings = 0;
    1.52 +  wpcs->GetRestrictions(&settings);
    1.53 +  
    1.54 +  if (settings) { // WPCFLAG_NO_RESTRICTION = 0
    1.55 +    gAdvAPIDLLInst = ::LoadLibrary("Advapi32.dll");
    1.56 +    if(gAdvAPIDLLInst)
    1.57 +    {
    1.58 +      gEventWrite = (decltype(EventWrite)*) GetProcAddress(gAdvAPIDLLInst, "EventWrite");
    1.59 +      gEventRegister = (decltype(EventRegister)*) GetProcAddress(gAdvAPIDLLInst, "EventRegister");
    1.60 +      gEventUnregister = (decltype(EventUnregister)*) GetProcAddress(gAdvAPIDLLInst, "EventUnregister");
    1.61 +    }
    1.62 +    mEnabled = true;
    1.63 +  }
    1.64 +}
    1.65 +
    1.66 +nsParentalControlsServiceWin::~nsParentalControlsServiceWin()
    1.67 +{
    1.68 +  if (mPC)
    1.69 +    mPC->Release();
    1.70 +
    1.71 +  if (gEventUnregister && mProvider)
    1.72 +    gEventUnregister(mProvider);
    1.73 +
    1.74 +  if (gAdvAPIDLLInst)
    1.75 +    ::FreeLibrary(gAdvAPIDLLInst);
    1.76 +}
    1.77 +
    1.78 +//------------------------------------------------------------------------
    1.79 +
    1.80 +NS_IMETHODIMP
    1.81 +nsParentalControlsServiceWin::GetParentalControlsEnabled(bool *aResult)
    1.82 +{
    1.83 +  *aResult = false;
    1.84 +
    1.85 +  if (mEnabled)
    1.86 +    *aResult = true;
    1.87 +
    1.88 +  return NS_OK;
    1.89 +}
    1.90 +
    1.91 +NS_IMETHODIMP
    1.92 +nsParentalControlsServiceWin::GetBlockFileDownloadsEnabled(bool *aResult)
    1.93 +{
    1.94 +  *aResult = false;
    1.95 +
    1.96 +  if (!mEnabled)
    1.97 +    return NS_ERROR_NOT_AVAILABLE;
    1.98 +
    1.99 +  nsRefPtr<IWPCWebSettings> wpcws;
   1.100 +  if (SUCCEEDED(mPC->GetWebSettings(nullptr, getter_AddRefs(wpcws)))) {
   1.101 +    DWORD settings = 0;
   1.102 +    wpcws->GetSettings(&settings);
   1.103 +    if (settings == WPCFLAG_WEB_SETTING_DOWNLOADSBLOCKED)
   1.104 +      *aResult = true;
   1.105 +  }
   1.106 +
   1.107 +  return NS_OK;
   1.108 +}
   1.109 +
   1.110 +NS_IMETHODIMP
   1.111 +nsParentalControlsServiceWin::GetLoggingEnabled(bool *aResult)
   1.112 +{
   1.113 +  *aResult = false;
   1.114 +
   1.115 +  if (!mEnabled)
   1.116 +    return NS_ERROR_NOT_AVAILABLE;
   1.117 +
   1.118 +  // Check the general purpose logging flag
   1.119 +  nsRefPtr<IWPCSettings> wpcs;
   1.120 +  if (SUCCEEDED(mPC->GetUserSettings(nullptr, getter_AddRefs(wpcs)))) {
   1.121 +    BOOL enabled = FALSE;
   1.122 +    wpcs->IsLoggingRequired(&enabled);
   1.123 +    if (enabled)
   1.124 +      *aResult = true;
   1.125 +  }
   1.126 +
   1.127 +  return NS_OK;
   1.128 +}
   1.129 +
   1.130 +// Post a log event to the system
   1.131 +NS_IMETHODIMP
   1.132 +nsParentalControlsServiceWin::Log(int16_t aEntryType, bool blocked, nsIURI *aSource, nsIFile *aTarget)
   1.133 +{
   1.134 +  if (!mEnabled)
   1.135 +    return NS_ERROR_NOT_AVAILABLE;
   1.136 +
   1.137 +  NS_ENSURE_ARG_POINTER(aSource);
   1.138 +
   1.139 +  // Confirm we should be logging
   1.140 +  bool enabled;
   1.141 +  GetLoggingEnabled(&enabled);
   1.142 +  if (!enabled)
   1.143 +    return NS_ERROR_NOT_AVAILABLE;
   1.144 +
   1.145 +  // Register a Vista log event provider associated with the parental controls channel.
   1.146 +  if (!mProvider) {
   1.147 +    if (!gEventRegister)
   1.148 +      return NS_ERROR_NOT_AVAILABLE;
   1.149 +    if (gEventRegister(&WPCPROV, nullptr, nullptr, &mProvider) != ERROR_SUCCESS)
   1.150 +      return NS_ERROR_OUT_OF_MEMORY;
   1.151 +  }
   1.152 +
   1.153 +  switch(aEntryType) {
   1.154 +    case ePCLog_URIVisit:
   1.155 +      // Not needed, Vista's web content filter handles this for us
   1.156 +      break;
   1.157 +    case ePCLog_FileDownload:
   1.158 +      LogFileDownload(blocked, aSource, aTarget);
   1.159 +      break;
   1.160 +    default:
   1.161 +      break;
   1.162 +  }
   1.163 +
   1.164 +  return NS_OK;
   1.165 +}
   1.166 +
   1.167 +// Override a single URI
   1.168 +NS_IMETHODIMP
   1.169 +nsParentalControlsServiceWin::RequestURIOverride(nsIURI *aTarget, nsIInterfaceRequestor *aWindowContext, bool *_retval)
   1.170 +{
   1.171 +  *_retval = false;
   1.172 +
   1.173 +  if (!mEnabled)
   1.174 +    return NS_ERROR_NOT_AVAILABLE;
   1.175 +
   1.176 +  NS_ENSURE_ARG_POINTER(aTarget);
   1.177 +
   1.178 +  nsAutoCString spec;
   1.179 +  aTarget->GetSpec(spec);
   1.180 +  if (spec.IsEmpty())
   1.181 +    return NS_ERROR_INVALID_ARG;
   1.182 +
   1.183 +  HWND hWnd = nullptr;
   1.184 +  // If we have a native window, use its handle instead
   1.185 +  nsCOMPtr<nsIWidget> widget(do_GetInterface(aWindowContext));
   1.186 +  if (widget)
   1.187 +    hWnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
   1.188 +  if (hWnd == nullptr)
   1.189 +    hWnd = GetDesktopWindow();
   1.190 +
   1.191 +  BOOL ret;
   1.192 +  nsRefPtr<IWPCWebSettings> wpcws;
   1.193 +  if (SUCCEEDED(mPC->GetWebSettings(nullptr, getter_AddRefs(wpcws)))) {
   1.194 +    wpcws->RequestURLOverride(hWnd, NS_ConvertUTF8toUTF16(spec).get(),
   1.195 +                              0, nullptr, &ret);
   1.196 +    *_retval = ret;
   1.197 +  }
   1.198 +
   1.199 +
   1.200 +  return NS_OK;
   1.201 +}
   1.202 +
   1.203 +// Override a web page
   1.204 +NS_IMETHODIMP
   1.205 +nsParentalControlsServiceWin::RequestURIOverrides(nsIArray *aTargets, nsIInterfaceRequestor *aWindowContext, bool *_retval)
   1.206 +{
   1.207 +  *_retval = false;
   1.208 +
   1.209 +  if (!mEnabled)
   1.210 +    return NS_ERROR_NOT_AVAILABLE;
   1.211 +
   1.212 +  NS_ENSURE_ARG_POINTER(aTargets);
   1.213 +
   1.214 +  uint32_t arrayLength = 0;
   1.215 +  aTargets->GetLength(&arrayLength);
   1.216 +  if (!arrayLength)
   1.217 +    return NS_ERROR_INVALID_ARG;
   1.218 +
   1.219 +  if (arrayLength == 1) {
   1.220 +    nsCOMPtr<nsIURI> uri = do_QueryElementAt(aTargets, 0);
   1.221 +    if (!uri)
   1.222 +      return NS_ERROR_INVALID_ARG;
   1.223 +    return RequestURIOverride(uri, aWindowContext, _retval);
   1.224 +  }
   1.225 +
   1.226 +  HWND hWnd = nullptr;
   1.227 +  // If we have a native window, use its handle instead
   1.228 +  nsCOMPtr<nsIWidget> widget(do_GetInterface(aWindowContext));
   1.229 +  if (widget)
   1.230 +    hWnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
   1.231 +  if (hWnd == nullptr)
   1.232 +    hWnd = GetDesktopWindow();
   1.233 +
   1.234 +  // The first entry should be the root uri
   1.235 +  nsAutoCString rootSpec;
   1.236 +  nsCOMPtr<nsIURI> rootURI = do_QueryElementAt(aTargets, 0);
   1.237 +  if (!rootURI)
   1.238 +    return NS_ERROR_INVALID_ARG;
   1.239 +  
   1.240 +  rootURI->GetSpec(rootSpec);
   1.241 +  if (rootSpec.IsEmpty())
   1.242 +    return NS_ERROR_INVALID_ARG;
   1.243 +
   1.244 +  // Allocate an array of sub uri
   1.245 +  int32_t count = arrayLength - 1;
   1.246 +  nsAutoArrayPtr<LPCWSTR> arrUrls(new LPCWSTR[count]);
   1.247 +  if (!arrUrls)
   1.248 +    return NS_ERROR_OUT_OF_MEMORY;
   1.249 +
   1.250 +  uint32_t uriIdx = 0, idx;
   1.251 +  for (idx = 1; idx < arrayLength; idx++)
   1.252 +  {
   1.253 +    nsCOMPtr<nsIURI> uri = do_QueryElementAt(aTargets, idx);
   1.254 +    if (!uri)
   1.255 +      continue;
   1.256 +
   1.257 +    nsAutoCString subURI;
   1.258 +    if (NS_FAILED(uri->GetSpec(subURI)))
   1.259 +      continue;
   1.260 +
   1.261 +    arrUrls[uriIdx] = (LPCWSTR)UTF8ToNewUnicode(subURI); // allocation
   1.262 +    if (!arrUrls[uriIdx])
   1.263 +      continue;
   1.264 +
   1.265 +    uriIdx++;
   1.266 +  }
   1.267 +
   1.268 +  if (!uriIdx)
   1.269 +    return NS_ERROR_INVALID_ARG;
   1.270 +
   1.271 +  BOOL ret; 
   1.272 +  nsRefPtr<IWPCWebSettings> wpcws;
   1.273 +  if (SUCCEEDED(mPC->GetWebSettings(nullptr, getter_AddRefs(wpcws)))) {
   1.274 +    wpcws->RequestURLOverride(hWnd, NS_ConvertUTF8toUTF16(rootSpec).get(),
   1.275 +                             uriIdx, (LPCWSTR*)arrUrls.get(), &ret);
   1.276 +   *_retval = ret;
   1.277 +  }
   1.278 +
   1.279 +  // Free up the allocated strings in our array
   1.280 +  for (idx = 0; idx < uriIdx; idx++)
   1.281 +    NS_Free((void*)arrUrls[idx]);
   1.282 +
   1.283 +  return NS_OK;
   1.284 +}
   1.285 +
   1.286 +//------------------------------------------------------------------------
   1.287 +
   1.288 +// Sends a file download event to the Vista Event Log 
   1.289 +void
   1.290 +nsParentalControlsServiceWin::LogFileDownload(bool blocked, nsIURI *aSource, nsIFile *aTarget)
   1.291 +{
   1.292 +  nsAutoCString curi;
   1.293 +
   1.294 +  if (!gEventWrite)
   1.295 +    return;
   1.296 +
   1.297 +  // Note, EventDataDescCreate is a macro defined in the headers, not a function
   1.298 +
   1.299 +  aSource->GetSpec(curi);
   1.300 +  nsAutoString uri = NS_ConvertUTF8toUTF16(curi);
   1.301 +
   1.302 +  // Get the name of the currently running process
   1.303 +  nsCOMPtr<nsIXULAppInfo> appInfo = do_GetService("@mozilla.org/xre/app-info;1");
   1.304 +  nsAutoCString asciiAppName;
   1.305 +  if (appInfo)
   1.306 +    appInfo->GetName(asciiAppName);
   1.307 +  nsAutoString appName = NS_ConvertUTF8toUTF16(asciiAppName);
   1.308 +
   1.309 +  static const WCHAR fill[] = L"";
   1.310 +  
   1.311 +  // See wpcevent.h and msdn for event formats
   1.312 +  EVENT_DATA_DESCRIPTOR eventData[WPC_ARGS_FILEDOWNLOADEVENT_CARGS];
   1.313 +  DWORD dwBlocked = blocked;
   1.314 +
   1.315 +  EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_URL], (const void*)uri.get(),
   1.316 +                      ((ULONG)uri.Length()+1)*sizeof(WCHAR));
   1.317 +  EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_APPNAME], (const void*)appName.get(),
   1.318 +                      ((ULONG)appName.Length()+1)*sizeof(WCHAR));
   1.319 +  EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_VERSION], (const void*)fill, sizeof(fill));
   1.320 +  EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_BLOCKED], (const void*)&dwBlocked,
   1.321 +                      sizeof(dwBlocked));
   1.322 +
   1.323 +  nsCOMPtr<nsILocalFileWin> local(do_QueryInterface(aTarget)); // May be null
   1.324 +  if (local) {
   1.325 +    nsAutoString path;
   1.326 +    local->GetCanonicalPath(path);
   1.327 +    EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_PATH], (const void*)path.get(),
   1.328 +                        ((ULONG)path.Length()+1)*sizeof(WCHAR));
   1.329 +  }
   1.330 +  else {
   1.331 +    EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_PATH], (const void*)fill, sizeof(fill));
   1.332 +  }
   1.333 +
   1.334 +  gEventWrite(mProvider, &WPCEVENT_WEB_FILEDOWNLOAD, ARRAYSIZE(eventData), eventData);
   1.335 +}
   1.336 +

mercurial