toolkit/components/parentalcontrols/nsParentalControlsServiceWin.cpp

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     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/. */
     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"
    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}};
    20 NS_IMPL_ISUPPORTS(nsParentalControlsServiceWin, nsIParentalControlsService)
    22 static HINSTANCE gAdvAPIDLLInst = nullptr;
    24 decltype(EventWrite)* gEventWrite = nullptr;
    25 decltype(EventRegister)* gEventRegister = nullptr;
    26 decltype(EventUnregister)* gEventUnregister = nullptr;
    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;
    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   }
    48   DWORD settings = 0;
    49   wpcs->GetRestrictions(&settings);
    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 }
    63 nsParentalControlsServiceWin::~nsParentalControlsServiceWin()
    64 {
    65   if (mPC)
    66     mPC->Release();
    68   if (gEventUnregister && mProvider)
    69     gEventUnregister(mProvider);
    71   if (gAdvAPIDLLInst)
    72     ::FreeLibrary(gAdvAPIDLLInst);
    73 }
    75 //------------------------------------------------------------------------
    77 NS_IMETHODIMP
    78 nsParentalControlsServiceWin::GetParentalControlsEnabled(bool *aResult)
    79 {
    80   *aResult = false;
    82   if (mEnabled)
    83     *aResult = true;
    85   return NS_OK;
    86 }
    88 NS_IMETHODIMP
    89 nsParentalControlsServiceWin::GetBlockFileDownloadsEnabled(bool *aResult)
    90 {
    91   *aResult = false;
    93   if (!mEnabled)
    94     return NS_ERROR_NOT_AVAILABLE;
    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   }
   104   return NS_OK;
   105 }
   107 NS_IMETHODIMP
   108 nsParentalControlsServiceWin::GetLoggingEnabled(bool *aResult)
   109 {
   110   *aResult = false;
   112   if (!mEnabled)
   113     return NS_ERROR_NOT_AVAILABLE;
   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   }
   124   return NS_OK;
   125 }
   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;
   134   NS_ENSURE_ARG_POINTER(aSource);
   136   // Confirm we should be logging
   137   bool enabled;
   138   GetLoggingEnabled(&enabled);
   139   if (!enabled)
   140     return NS_ERROR_NOT_AVAILABLE;
   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   }
   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   }
   161   return NS_OK;
   162 }
   164 // Override a single URI
   165 NS_IMETHODIMP
   166 nsParentalControlsServiceWin::RequestURIOverride(nsIURI *aTarget, nsIInterfaceRequestor *aWindowContext, bool *_retval)
   167 {
   168   *_retval = false;
   170   if (!mEnabled)
   171     return NS_ERROR_NOT_AVAILABLE;
   173   NS_ENSURE_ARG_POINTER(aTarget);
   175   nsAutoCString spec;
   176   aTarget->GetSpec(spec);
   177   if (spec.IsEmpty())
   178     return NS_ERROR_INVALID_ARG;
   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();
   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   }
   197   return NS_OK;
   198 }
   200 // Override a web page
   201 NS_IMETHODIMP
   202 nsParentalControlsServiceWin::RequestURIOverrides(nsIArray *aTargets, nsIInterfaceRequestor *aWindowContext, bool *_retval)
   203 {
   204   *_retval = false;
   206   if (!mEnabled)
   207     return NS_ERROR_NOT_AVAILABLE;
   209   NS_ENSURE_ARG_POINTER(aTargets);
   211   uint32_t arrayLength = 0;
   212   aTargets->GetLength(&arrayLength);
   213   if (!arrayLength)
   214     return NS_ERROR_INVALID_ARG;
   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   }
   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();
   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;
   237   rootURI->GetSpec(rootSpec);
   238   if (rootSpec.IsEmpty())
   239     return NS_ERROR_INVALID_ARG;
   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;
   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;
   254     nsAutoCString subURI;
   255     if (NS_FAILED(uri->GetSpec(subURI)))
   256       continue;
   258     arrUrls[uriIdx] = (LPCWSTR)UTF8ToNewUnicode(subURI); // allocation
   259     if (!arrUrls[uriIdx])
   260       continue;
   262     uriIdx++;
   263   }
   265   if (!uriIdx)
   266     return NS_ERROR_INVALID_ARG;
   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   }
   276   // Free up the allocated strings in our array
   277   for (idx = 0; idx < uriIdx; idx++)
   278     NS_Free((void*)arrUrls[idx]);
   280   return NS_OK;
   281 }
   283 //------------------------------------------------------------------------
   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;
   291   if (!gEventWrite)
   292     return;
   294   // Note, EventDataDescCreate is a macro defined in the headers, not a function
   296   aSource->GetSpec(curi);
   297   nsAutoString uri = NS_ConvertUTF8toUTF16(curi);
   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);
   306   static const WCHAR fill[] = L"";
   308   // See wpcevent.h and msdn for event formats
   309   EVENT_DATA_DESCRIPTOR eventData[WPC_ARGS_FILEDOWNLOADEVENT_CARGS];
   310   DWORD dwBlocked = blocked;
   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));
   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   }
   331   gEventWrite(mProvider, &WPCEVENT_WEB_FILEDOWNLOAD, ARRAYSIZE(eventData), eventData);
   332 }

mercurial