Bug 412374 - "Parental Controls can be easily bypassed by going back to the download source" [p=jmathies@mozilla.com (Jim Mathies) r=sdwilsh sr=bsmedberg a=blocking-firefox3+]
authorreed@reedloden.com
Wed, 19 Mar 2008 23:01:26 -0700
changeset 13367 971b9a7deb6714f6a2a04670b562c429c6fb8c8a
parent 13366 074ebfba009c6fc45103074534181e4742a12d23
child 13368 944d3a3993046dfd940e6e37308beda84ba15c71
push idunknown
push userunknown
push dateunknown
reviewerssdwilsh, bsmedberg, blocking-firefox3
bugs412374
milestone1.9b5pre
Bug 412374 - "Parental Controls can be easily bypassed by going back to the download source" [p=jmathies@mozilla.com (Jim Mathies) r=sdwilsh sr=bsmedberg a=blocking-firefox3+]
toolkit/components/Makefile.in
toolkit/components/build/Makefile.in
toolkit/components/build/nsToolkitCompsCID.h
toolkit/components/build/nsToolkitCompsModule.cpp
toolkit/components/downloads/src/Makefile.in
toolkit/components/downloads/src/nsDownloadManager.cpp
toolkit/components/parentalcontrols/Makefile.in
toolkit/components/parentalcontrols/public/Makefile.in
toolkit/components/parentalcontrols/public/nsIParentalControlsService.idl
toolkit/components/parentalcontrols/src/Makefile.in
toolkit/components/parentalcontrols/src/nsParentalControlsServiceWin.cpp
toolkit/components/parentalcontrols/src/nsParentalControlsServiceWin.h
--- a/toolkit/components/Makefile.in
+++ b/toolkit/components/Makefile.in
@@ -58,16 +58,17 @@ DIRS += \
 
 ifdef MOZ_XUL_APP
 DIRS += \
 	apppicker \
 	filepicker \
 	console \
 	viewconfig \
 	typeaheadfind \
+	parentalcontrols \
 	$(NULL)
 
 ifneq (,$(filter cocoa, $(MOZ_WIDGET_TOOLKIT)))
 TOOL_DIRS += alerts
 else
 DIRS += alerts
 endif
 
--- a/toolkit/components/build/Makefile.in
+++ b/toolkit/components/build/Makefile.in
@@ -105,16 +105,24 @@ LOCAL_INCLUDES += \
 	-I$(srcdir)/../alerts/src \
 	$(NULL)
 endif
 
 SHARED_LIBRARY_LIBS = \
 	../startup/src/$(LIB_PREFIX)appstartup_s.$(LIB_SUFFIX) \
 	$(NULL)
 
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+SHARED_LIBRARY_LIBS += ../parentalcontrols/src/$(LIB_PREFIX)parentalcontrols_s.$(LIB_SUFFIX)
+LOCAL_INCLUDES += \
+	-I$(srcdir)/../parentalcontrols/src \
+	$(NULL)
+REQUIRES += parentalcontrols
+endif
+
 ifndef MOZ_SUITE
 # XXX Suite isn't ready to build this just yet
 ifdef MOZ_RDF
 SHARED_LIBRARY_LIBS += ../downloads/src/$(LIB_PREFIX)download_s.$(LIB_SUFFIX)
 endif
 endif
 
 ifdef ALERTS_SERVICE
--- a/toolkit/components/build/nsToolkitCompsCID.h
+++ b/toolkit/components/build/nsToolkitCompsCID.h
@@ -69,16 +69,19 @@
   "@mozilla.org/rdf/datasource;1?name=history"
 
 #define NS_GLOBALHISTORY_AUTOCOMPLETE_CONTRACTID \
     "@mozilla.org/autocomplete/search;1?name=history"
 
 #define NS_TYPEAHEADFIND_CONTRACTID \
     "@mozilla.org/typeaheadfind;1"
 
+#define NS_PARENTALCONTROLSSERVICE_CONTRACTID \
+    "@mozilla.org/parental-controls-service;1"
+
 #define NS_URLCLASSIFIERDBSERVICE_CONTRACTID \
     "@mozilla.org/url-classifier/dbservice;1"
 
 #define NS_URLCLASSIFIERSTREAMUPDATER_CONTRACTID \
     "@mozilla.org/url-classifier/streamupdater;1"
 
 #define NS_URLCLASSIFIERUTILS_CONTRACTID \
     "@mozilla.org/url-classifier/utils;1"
@@ -138,16 +141,20 @@
 // {db340cc2-7f50-4ea3-8427-f529daf6dc87}
 #define NS_FORMHISTORYIMPORTER_CID \
 { 0xdb340cc2, 0x7f50, 0x4ea3, { 0x84, 0x27, 0xf5, 0x29, 0xda, 0xf6, 0xdc, 0x87 } }
 
 // {59648a91-5a60-4122-8ff2-54b839c84aed}
 #define NS_GLOBALHISTORY_CID \
 { 0x59648a91, 0x5a60, 0x4122, { 0x8f, 0xf2, 0x54, 0xb8, 0x39, 0xc8, 0x4a, 0xed} }
 
+// {59648a91-5a60-4122-8ff2-54b839c84aed}
+#define NS_PARENTALCONTROLSSERVICE_CID \
+{ 0x580530e5, 0x118c, 0x4bc7, { 0xab, 0x88, 0xbc, 0x2c, 0xd2, 0xb9, 0x72, 0x23 } }
+
 // {e7f70966-9a37-48d7-8aeb-35998f31090e}
 #define NS_TYPEAHEADFIND_CID \
 { 0xe7f70966, 0x9a37, 0x48d7, { 0x8a, 0xeb, 0x35, 0x99, 0x8f, 0x31, 0x09, 0x0e} }
   
 // {5eb7c3c1-ec1f-4007-87cc-eefb37d68ce6}
 #define NS_URLCLASSIFIERDBSERVICE_CID \
 { 0x5eb7c3c1, 0xec1f, 0x4007, { 0x87, 0xcc, 0xee, 0xfb, 0x37, 0xd6, 0x8c, 0xe6} }
 
--- a/toolkit/components/build/nsToolkitCompsModule.cpp
+++ b/toolkit/components/build/nsToolkitCompsModule.cpp
@@ -35,16 +35,21 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIGenericFactory.h"
 #include "nsAppStartup.h"
 #include "nsUserInfo.h"
 #include "nsXPFEComponentsCID.h"
 #include "nsToolkitCompsCID.h"
+
+#ifdef XP_WIN
+#include "nsParentalControlsServiceWin.h"
+#endif
+
 #ifdef ALERTS_SERVICE
 #include "nsAlertsService.h"
 #endif
 
 #ifndef MOZ_SUITE
 // XXX Suite isn't ready to include this just yet
 #ifdef MOZ_RDF
 #include "nsDownloadManager.h"
@@ -66,16 +71,20 @@
 #include "nsScriptableUnescapeHTML.h"
 #endif
 
 /////////////////////////////////////////////////////////////////////////////
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsAppStartup, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsUserInfo)
 
+#ifdef XP_WIN
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsParentalControlsServiceWin)
+#endif
+
 #ifdef ALERTS_SERVICE
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsAlertsService)
 #endif
 
 #ifndef MOZ_SUITE
 // XXX Suite isn't ready to include this just yet
 #ifdef MOZ_RDF
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDownloadManager,
@@ -129,16 +138,22 @@ static const nsModuleComponentInfo compo
     NS_USERINFO_CONTRACTID,
     nsUserInfoConstructor },
 #ifdef ALERTS_SERVICE
   { "Alerts Service",
     NS_ALERTSSERVICE_CID, 
     NS_ALERTSERVICE_CONTRACTID,
     nsAlertsServiceConstructor },
 #endif
+#ifdef XP_WIN
+  { "Parental Controls Service",
+    NS_PARENTALCONTROLSSERVICE_CID,
+    NS_PARENTALCONTROLSSERVICE_CONTRACTID,
+    nsParentalControlsServiceWinConstructor },
+#endif
 #ifndef MOZ_SUITE
 // XXX Suite isn't ready to include this just yet
 #ifdef MOZ_RDF
   { "Download Manager",
     NS_DOWNLOADMANAGER_CID,
     NS_DOWNLOADMANAGER_CONTRACTID,
     nsDownloadManagerConstructor },
   { "Download",
--- a/toolkit/components/downloads/src/Makefile.in
+++ b/toolkit/components/downloads/src/Makefile.in
@@ -58,19 +58,21 @@ REQUIRES  = xpcom \
             pref \
             intl \
             windowwatcher \
             webbrowserpersist \
             appshell \
             dom \
             embed_base \
             alerts \
+            parentalcontrols \
             storage \
             exthandler \
             docshell \
+            toolkitcomps \
             $(NULL)
 
 CPPSRCS   = \
     nsDownloadManager.cpp \
     $(NULL)
 
 ifndef GNU_CXX
 ifeq ($(OS_ARCH),WINNT)
--- a/toolkit/components/downloads/src/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/src/nsDownloadManager.cpp
@@ -72,17 +72,18 @@
 #include "nsIAlertsService.h"
 #include "nsIPropertyBag2.h"
 #include "nsIHttpChannel.h"
 #include "nsIDownloadManagerUI.h"
 #include "nsIResumableChannel.h"
 #include "nsCExternalHandlerService.h"
 #include "nsIExternalHelperAppService.h"
 #include "nsIMIMEService.h"
-
+#include "nsIParentalControlsService.h"
+#include "nsToolkitCompsCID.h"
 #include "nsIDownloadHistory.h"
 #include "nsDocShellCID.h"
 
 #if defined(XP_WIN) && !defined(WINCE) 
 #include <shlobj.h>
 #ifndef __MINGW32__
 #include "nsDownloadScanner.h"
 #endif
@@ -1378,16 +1379,40 @@ nsDownloadManager::AddDownload(DownloadT
                                mimeType, persistentDescriptor, action);
   NS_ENSURE_TRUE(id, NS_ERROR_FAILURE);
   dl->mID = id;
 
   rv = AddToCurrentDownloads(dl);
   (void)dl->SetState(nsIDownloadManager::DOWNLOAD_QUEUED);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // Check with parental controls to see if file downloads
+  // are allowed for this user. If not allowed, cancel the
+  // download and mark its state as being blocked.
+  nsCOMPtr<nsIParentalControlsService> pc =
+    do_CreateInstance(NS_PARENTALCONTROLSSERVICE_CONTRACTID);
+  if (pc) {
+    PRBool enabled = PR_FALSE;
+    (void)pc->GetBlockFileDownloadsEnabled(&enabled);
+    if (enabled) {
+      (void)CancelDownload(id);
+      (void)dl->SetState(nsIDownloadManager::DOWNLOAD_BLOCKED);
+    }
+
+    // Log the event if required by pc settings. 
+    PRBool logEnabled = PR_FALSE;
+    (void)pc->GetLoggingEnabled(&logEnabled);
+    if (logEnabled) {
+      (void)pc->Log(nsIParentalControlsService::ePCLog_FileDownload,
+                    enabled,
+                    aSource,
+                    nsnull);
+    }
+  }
+
   NS_ADDREF(*aDownload = dl);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDownloadManager::GetDownload(PRUint32 aID, nsIDownload **aDownloadItem)
 {
new file mode 100644
--- /dev/null
+++ b/toolkit/components/parentalcontrols/Makefile.in
@@ -0,0 +1,53 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+
+DEPTH     = ../../..
+topsrcdir = @top_srcdir@
+srcdir    = @srcdir@
+VPATH     = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS = public
+
+ifeq (WINNT,$(OS_ARCH))
+DIRS += src
+endif
+
+include $(topsrcdir)/config/rules.mk
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/parentalcontrols/public/Makefile.in
@@ -0,0 +1,51 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE        = parentalcontrols
+XPIDL_MODULE  = parentalcontrols
+
+XPIDLSRCS = \
+		nsIParentalControlsService.idl \
+		$(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/toolkit/components/parentalcontrols/public/nsIParentalControlsService.idl
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jim Mathies <jmathies@mozilla.com>.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsISupports.idl"
+
+interface nsIURI;
+interface nsIFile;
+interface nsIInterfaceRequestor;
+interface nsIArray;
+
+[scriptable, uuid(871cf229-2b21-4f04-b24d-e08061f14815)]
+interface nsIParentalControlsService : nsISupports
+{
+  /**
+   * @returns true if the current user account has parental controls
+   * restrictions enabled.
+   */ 
+  readonly attribute boolean parentalControlsEnabled;
+
+  /**
+   * @returns true if the current user account parental controls
+   * restrictions include the blocking of all file downloads.
+   */ 
+  readonly attribute boolean blockFileDownloadsEnabled;
+
+  /**
+   * Request that blocked URI(s) be allowed through parental
+   * control filters. Returns true if the URI was successfully
+   * overriden. Note, may block while native UI is shown.
+   *
+   * @param aTarget(s)          URI to be overridden. In the case of
+   *                            multiple URI, the first URI in the array
+   *                            should be the root URI of the site.
+   * @param window              Window that generates the event.
+   */
+  boolean requestURIOverride(in nsIURI aTarget, [optional] in nsIInterfaceRequestor aWindowContext);
+  boolean requestURIOverrides(in nsIArray aTargets, [optional] in nsIInterfaceRequestor aWindowContext);
+
+  /**
+   * @returns true if the current user account has parental controls
+   * logging enabled. If true, applications should log relevent events
+   * using 'log'.
+   */ 
+  readonly attribute boolean loggingEnabled;
+
+  /**
+   * Log entry types. Additional types can be defined and implemented
+   * as needed. Other possible event types might include email events,
+   * media related events, and IM events. 
+   */
+  const short ePCLog_URIVisit = 1;    /* Web content */
+  const short ePCLog_FileDownload = 2;  /* File downloads */
+
+  /**
+   * Log an application specific parental controls
+   * event.
+   *
+   * @param aEntryType       Constant defining the type of event.
+   * @param aFlag            A flag indicating if the subject content
+   *                         was blocked.
+   * @param aSource          The URI source of the subject content.
+   * @param aTarget          The location the content was saved to if
+   *                         no blocking occured.
+   */
+  void log(in short aEntryType, in boolean aFlag, in nsIURI aSource, [optional] in nsIFile aTarget);
+};
new file mode 100644
--- /dev/null
+++ b/toolkit/components/parentalcontrols/src/Makefile.in
@@ -0,0 +1,63 @@
+#! gmake
+# 
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH   = ../../../..
+topsrcdir = @top_srcdir@
+srcdir    = @srcdir@
+
+VPATH   = $(srcdir)
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE    = parentalcontrols
+LIBRARY_NAME = parentalcontrols_s
+FORCE_STATIC_LIB = 1
+LIBXUL_LIBRARY = 1
+
+REQUIRES  = xpcom \
+  string \
+  pref \
+  gfx \
+  widget \
+  $(NULL)
+
+CPPSRCS   = \
+  nsParentalControlsServiceWin.cpp \
+  $(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/toolkit/components/parentalcontrols/src/nsParentalControlsServiceWin.cpp
@@ -0,0 +1,333 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jim Mathies <jmathies@mozilla.com>.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsParentalControlsServiceWin.h"
+#include "nsString.h"
+#include "nsIArray.h"
+#include "nsIWidget.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsIFile.h"
+#include "nsILocalFileWin.h"
+#include "nsArrayUtils.h"
+#include "nsIXULAppInfo.h"
+
+static const CLSID CLSID_WinParentalControls = {0xE77CC89B,0x7401,0x4C04,{0x8C,0xED,0x14,0x9D,0xB3,0x5A,0xDD,0x04}};
+static const IID IID_IWinParentalControls  = {0x28B4D88B,0xE072,0x49E6,{0x80,0x4D,0x26,0xED,0xBE,0x21,0xA7,0xB9}};
+
+NS_IMPL_ISUPPORTS1(nsParentalControlsServiceWin, nsIParentalControlsService)
+
+nsParentalControlsServiceWin::nsParentalControlsServiceWin() :
+  mPC(nsnull)
+, mEnabled(PR_FALSE)
+, mProvider(nsnull)
+{
+  HRESULT hr;
+  CoInitialize(NULL);
+  hr = CoCreateInstance(CLSID_WinParentalControls, NULL, CLSCTX_INPROC,
+                        IID_IWinParentalControls, (void**)&mPC);
+  if (FAILED(hr))
+    return;
+
+  nsRefPtr<IWPCSettings> wpcs;
+  if (FAILED(mPC->GetUserSettings(NULL, getter_AddRefs(wpcs)))) {
+    // Not available on this os or not enabled for this user account or we're running as admin
+    mPC->Release();
+    mPC = nsnull;
+    return;
+  }
+
+  DWORD settings = 0;
+  wpcs->GetRestrictions(&settings);
+  
+  if (settings)  // WPCFLAG_NO_RESTRICTION = 0
+    mEnabled = PR_TRUE;
+}
+
+nsParentalControlsServiceWin::~nsParentalControlsServiceWin()
+{
+  if (mPC)
+    mPC->Release();
+  if (mProvider)
+    EventUnregister(mProvider);
+}
+
+//------------------------------------------------------------------------
+
+NS_IMETHODIMP
+nsParentalControlsServiceWin::GetParentalControlsEnabled(PRBool *aResult)
+{
+  *aResult = PR_FALSE;
+
+  if (mEnabled)
+    *aResult = PR_TRUE;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsParentalControlsServiceWin::GetBlockFileDownloadsEnabled(PRBool *aResult)
+{
+  *aResult = PR_FALSE;
+
+  if (!mEnabled)
+    return NS_ERROR_NOT_AVAILABLE;
+
+  nsRefPtr<IWPCWebSettings> wpcws;
+  if (SUCCEEDED(mPC->GetWebSettings(NULL, getter_AddRefs(wpcws)))) {
+    DWORD settings = 0;
+    wpcws->GetSettings(&settings);
+    if (settings == WPCFLAG_WEB_SETTING_DOWNLOADSBLOCKED)
+      *aResult = PR_TRUE;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsParentalControlsServiceWin::GetLoggingEnabled(PRBool *aResult)
+{
+  *aResult = PR_FALSE;
+
+  if (!mEnabled)
+    return NS_ERROR_NOT_AVAILABLE;
+
+  // Check the general purpose logging flag
+  nsRefPtr<IWPCSettings> wpcs;
+  if (SUCCEEDED(mPC->GetUserSettings(NULL, getter_AddRefs(wpcs)))) {
+    BOOL enabled = FALSE;
+    wpcs->IsLoggingRequired(&enabled);
+    if (enabled)
+      *aResult = PR_TRUE;
+  }
+
+  return NS_OK;
+}
+
+// Post a log event to the system
+NS_IMETHODIMP
+nsParentalControlsServiceWin::Log(PRInt16 aEntryType, PRBool blocked, nsIURI *aSource, nsIFile *aTarget)
+{
+  if (!mEnabled)
+    return NS_ERROR_NOT_AVAILABLE;
+
+  NS_ENSURE_ARG_POINTER(aSource);
+
+  // Confirm we should be logging
+  PRBool enabled;
+  GetLoggingEnabled(&enabled);
+  if (!enabled)
+    return NS_ERROR_NOT_AVAILABLE;
+
+  // Register a windows log event provider associated with the parental controls channel.
+  if (!mProvider) {
+    if (EventRegister(&WPCPROV, NULL, NULL, &mProvider) != ERROR_SUCCESS)
+      return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  switch(aEntryType) {
+    case ePCLog_URIVisit:
+      // Not needed, Vista's web content filter handles this for us
+      break;
+    case ePCLog_FileDownload:
+      LogFileDownload(blocked, aSource, aTarget);
+      break;
+    default:
+      break;
+  }
+
+  return NS_OK;
+}
+
+// Override a single URI
+NS_IMETHODIMP
+nsParentalControlsServiceWin::RequestURIOverride(nsIURI *aTarget, nsIInterfaceRequestor *aWindowContext, PRBool *_retval)
+{
+  *_retval = PR_FALSE;
+
+  if (!mEnabled)
+    return NS_ERROR_NOT_AVAILABLE;
+
+  NS_ENSURE_ARG_POINTER(aTarget);
+
+  nsCAutoString spec;
+  aTarget->GetSpec(spec);
+  if (spec.IsEmpty())
+    return NS_ERROR_INVALID_ARG;
+
+  HWND hWnd = nsnull;
+  // If we have a native window, use it's handle instead
+  nsCOMPtr<nsIWidget> widget(do_GetInterface(aWindowContext));
+  if (widget)
+    hWnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
+  if (hWnd == nsnull)
+    hWnd = GetDesktopWindow();
+
+  nsRefPtr<IWPCWebSettings> wpcws;
+  if (SUCCEEDED(mPC->GetWebSettings(NULL, getter_AddRefs(wpcws))))
+    wpcws->RequestURLOverride(hWnd, NS_ConvertUTF8toUTF16(spec).get(),
+                              0, NULL, _retval);
+
+  return NS_OK;
+}
+
+// Override a web page
+NS_IMETHODIMP
+nsParentalControlsServiceWin::RequestURIOverrides(nsIArray *aTargets, nsIInterfaceRequestor *aWindowContext, PRBool *_retval)
+{
+  *_retval = PR_FALSE;
+
+  if (!mEnabled)
+    return NS_ERROR_NOT_AVAILABLE;
+
+  NS_ENSURE_ARG_POINTER(aTargets);
+
+  PRUint32 arrayLength = 0;
+  aTargets->GetLength(&arrayLength);
+  if (!arrayLength)
+    return NS_ERROR_INVALID_ARG;
+
+  if (arrayLength == 1) {
+    nsCOMPtr<nsIURI> uri = do_QueryElementAt(aTargets, 0);
+    if (!uri)
+      return NS_ERROR_INVALID_ARG;
+    return RequestURIOverride(uri, aWindowContext, _retval);
+  }
+
+  HWND hWnd = nsnull;
+  // If we have a native window, use it's handle instead
+  nsCOMPtr<nsIWidget> widget(do_GetInterface(aWindowContext));
+  if (widget)
+    hWnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
+  if (hWnd == nsnull)
+    hWnd = GetDesktopWindow();
+
+  // The first entry should be the root uri
+  nsCAutoString rootSpec;
+  nsCOMPtr<nsIURI> rootURI = do_QueryElementAt(aTargets, 0);
+  if (!rootURI)
+    return NS_ERROR_INVALID_ARG;
+  
+  rootURI->GetSpec(rootSpec);
+  if (rootSpec.IsEmpty())
+    return NS_ERROR_INVALID_ARG;
+
+  // Allocate an array of sub uri
+  PRInt32 count = arrayLength - 1;
+  nsAutoArrayPtr<LPCWSTR> arrUrls(new LPCWSTR[count]);
+  if (!arrUrls)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  PRUint32 uriIdx = 0, idx;
+  for (idx = 1; idx < arrayLength; idx++)
+  {
+    nsCOMPtr<nsIURI> uri = do_QueryElementAt(aTargets, idx);
+    if (!uri)
+      continue;
+
+    nsCAutoString subURI;
+    if (NS_FAILED(uri->GetSpec(subURI)))
+      continue;
+
+    arrUrls[uriIdx] = (LPCWSTR)UTF8ToNewUnicode(subURI); // allocation
+    if (!arrUrls[uriIdx])
+      continue;
+
+    uriIdx++;
+  }
+
+  if (!uriIdx)
+    return NS_ERROR_INVALID_ARG;
+ 
+  nsRefPtr<IWPCWebSettings> wpcws;
+  if (SUCCEEDED(mPC->GetWebSettings(NULL, getter_AddRefs(wpcws))))
+    wpcws->RequestURLOverride(hWnd, NS_ConvertUTF8toUTF16(rootSpec).get(),
+                             uriIdx, (LPCWSTR*)arrUrls.get(), _retval);
+
+  // Free up the allocated strings in our array
+  for (idx = 0; idx < uriIdx; idx++)
+    NS_Free((void*)arrUrls[idx]);
+
+  return NS_OK;
+}
+
+//------------------------------------------------------------------------
+
+// Sends a file download event to the Windows Event Log 
+void
+nsParentalControlsServiceWin::LogFileDownload(PRBool blocked, nsIURI *aSource, nsIFile *aTarget)
+{
+  nsCAutoString curi;
+  aSource->GetSpec(curi);
+  nsAutoString uri = NS_ConvertUTF8toUTF16(curi);
+
+  // Get the name of the currently running process
+  nsCOMPtr<nsIXULAppInfo> appInfo = do_GetService("@mozilla.org/xre/app-info;1");
+  nsCAutoString asciiAppName;
+  if (appInfo)
+    appInfo->GetName(asciiAppName);
+  nsAutoString appName = NS_ConvertUTF8toUTF16(asciiAppName);
+
+  static const WCHAR fill[] = L"";
+  
+  // See wpcevent.h and msdn for event formats
+  EVENT_DATA_DESCRIPTOR eventData[WPC_ARGS_FILEDOWNLOADEVENT_CARGS];
+  DWORD dwBlocked = blocked;
+
+  EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_URL], (const void*)uri.get(),
+                      ((ULONG)uri.Length()+1)*sizeof(WCHAR));
+  EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_APPNAME], (const void*)appName.get(),
+                      ((ULONG)appName.Length()+1)*sizeof(WCHAR));
+  EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_VERSION], (const void*)fill, sizeof(fill));
+  EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_BLOCKED], (const void*)&dwBlocked,
+                      sizeof(dwBlocked));
+
+  nsCOMPtr<nsILocalFileWin> local(do_QueryInterface(aTarget)); // May be null
+  if (local) {
+    nsAutoString path;
+    local->GetCanonicalPath(path);
+    EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_PATH], (const void*)path.get(),
+                        ((ULONG)path.Length()+1)*sizeof(WCHAR));
+  }
+  else {
+    EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_PATH], (const void*)fill, sizeof(fill));
+  }
+
+  EventWrite(mProvider, &WPCEVENT_WEB_FILEDOWNLOAD, ARRAYSIZE(eventData), eventData);
+}
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/parentalcontrols/src/nsParentalControlsServiceWin.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jim Mathies <jmathies@mozilla.com>.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsParentalControlsServiceWin_h__
+#define nsParentalControlsServiceWin_h__
+
+#include "nsIParentalControlsService.h"
+#include "nsCOMPtr.h"
+#include "nsAutoPtr.h"
+#include "nsIURI.h"
+
+// wpcevents.h requires this be elevated
+#if (WINVER < 0x0600)
+# undef WINVER
+# define WINVER 0x0600
+#endif
+
+#include <wpcapi.h>
+#include <wpcevent.h>
+
+class nsParentalControlsServiceWin : public nsIParentalControlsService
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPARENTALCONTROLSSERVICE
+
+  nsParentalControlsServiceWin();
+  virtual ~nsParentalControlsServiceWin();
+
+private:
+  PRBool mEnabled;
+  REGHANDLE mProvider;
+  IWindowsParentalControls * mPC;
+
+  void LogFileDownload(PRBool blocked, nsIURI *aSource, nsIFile *aTarget);
+};
+
+#endif /* nsParentalControlsServiceWin_h__ */