diff --git a/browser/base/content/browser-context.inc b/browser/base/content/browser-context.inc
index 72fd054..ea364fe 100644
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -206,7 +206,8 @@
                     accesskey="&saveFrameCmd.accesskey;"
                     oncommand="saveDocument(gContextMenu.target.ownerDocument);"/>
           <menuseparator/>
-          <menuitem label="&viewFrameSourceCmd.label;"
+          <menuitem id="context-frame-viewFrameSourceCmd"
+                    label="&viewFrameSourceCmd.label;"
                     accesskey="&viewFrameSourceCmd.accesskey;"
                     oncommand="gContextMenu.viewFrameSource();"/>
           <menuitem label="&viewFrameInfoCmd.label;"
diff --git a/browser/base/content/browser-menubar.inc b/browser/base/content/browser-menubar.inc
index bcf9109..0cc6740 100644
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -55,9 +55,9 @@
                 <menuitem id="menu_saveFrame" label="&saveFrameCmd.label;" accesskey="&saveFrameCmd.accesskey;" command="Browser:SaveFrame" hidden="true"/>
                 <menuitem id="menu_sendLink"  label="&sendPageCmd.label;"  accesskey="&sendPageCmd.accesskey;"  command="Browser:SendLink"/>
                 <menuseparator/>
-                <menuitem label="&printSetupCmd.label;" accesskey="&printSetupCmd.accesskey;" command="cmd_pageSetup"/>
+                <menuitem id="menu_printSetup" label="&printSetupCmd.label;" accesskey="&printSetupCmd.accesskey;" command="cmd_pageSetup"/>
 #ifndef XP_MACOSX
-                <menuitem label="&printPreviewCmd.label;" accesskey="&printPreviewCmd.accesskey;" command="cmd_printPreview"/>
+                <menuitem id="menu_printPreview" label="&printPreviewCmd.label;" accesskey="&printPreviewCmd.accesskey;" oncommand="PrintUtils.printPreview(onEnterPrintPreview, onExitPrintPreview);"/>
 #endif
                 <menuitem label="&printCmd.label;" accesskey="&printCmd.accesskey;" key="printKb" command="cmd_print"/>
                 <menuseparator/>
@@ -458,7 +458,7 @@
 #endif
                           label="&bookmarkAllCmd.label;"
                           command="Browser:BookmarkAllTabs"/>
-                <menuitem key="manBookmarkKb" 
+                <menuitem id="manBookmark" key="manBookmarkKb" 
                           label="&manBookmarksCmd.label;"
                           oncommand="toOpenWindowByType('bookmarks:manager', 'chrome://browser/content/bookmarks/bookmarksManager.xul');"/>
                 <menuseparator/>
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 0dcabc8..bcad885 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -179,6 +179,12 @@ function UpdateBackForwardButtons()
   var backBroadcaster = document.getElementById("Browser:Back");
   var forwardBroadcaster = document.getElementById("Browser:Forward");
 
+  if (gPrefService.getBoolPref("config.lockdown.history")) {
+    backBroadcaster.setAttribute("disabled", true);
+    forwardBroadcaster.setAttribute("disabled", true);
+    return;
+  }
+
   var webNavigation = gBrowser.webNavigation;
 
   // Avoid setting attributes on broadcasters if the value hasn't changed!
@@ -934,6 +940,112 @@ function prepareForStartup()
   BrowserSearch.init();
 }
 
+function lockdownElement(ident, disable)
+{
+  var e = document.getElementById(ident);
+  if (disable) {
+    e.setAttribute("disabled", "true");
+  } else {
+    e.removeAttribute("disabled");
+  }
+}
+
+function applyLockdown(isStartup)
+{
+  // It is important to check that Firefox code does not change the
+  // "disabled" state of these UI elements. Fortunately it mostly hides
+  // elements rather than disables them.
+  var disablePrinting = gPrefService.getBoolPref("config.lockdown.printing");
+  var disablePrintSetup = gPrefService.getBoolPref("config.lockdown.printsetup");
+  if (!isStartup || disablePrintSetup || disablePrintSetup) {
+    lockdownElement("menu_printSetup", disablePrinting || disablePrintSetup);
+    lockdownElement("menu_printPreview", disablePrinting || disablePrintSetup);
+    lockdownElement("cmd_print", disablePrinting);
+  }
+
+  var disableSave = gPrefService.getBoolPref("config.lockdown.savepage");
+  if (!isStartup || disableSave) {
+    lockdownElement("Browser:SavePage", disableSave);
+    lockdownElement("menu_saveFrame", disableSave);
+    lockdownElement("context-savepage", disableSave);
+    lockdownElement("context-savelink", disableSave);
+    lockdownElement("context-saveimage", disableSave);
+    lockdownElement("View:PageSource", disableSave);
+    lockdownElement("context-viewpartialsource-selection", disableSave);
+    lockdownElement("context-viewpartialsource-mathml", disableSave);
+    lockdownElement("context-viewsource", disableSave);
+    lockdownElement("context-frame-viewFrameSourceCmd", disableSave);
+  }
+
+  var disableBookmarks = gPrefService.getBoolPref("config.lockdown.hidebookmark");
+  var disableBookmarkEditing = gPrefService.getBoolPref("config.lockdown.bookmark");
+  if (!isStartup || disableBookmarks || disableBookmarkEditing) {
+    lockdownElement("viewBookmarksSidebar", disableBookmarks);
+    lockdownElement("PersonalToolbar", disableBookmarks); // XXX check
+    lockdownElement("Browser:AddBookmarkAs", disableBookmarks || disableBookmarkEditing);
+    lockdownElement("manBookmark", disableBookmarks || disableBookmarkEditing);
+    lockdownElement("context-bookmarkpage", disableBookmarks || disableBookmarkEditing);
+    lockdownElement("context-bookmarklink", disableBookmarks || disableBookmarkEditing);
+
+    // hide the personal bookmarks toolbar if necessary
+    if (disableBookmarks) {
+      document.getElementById("PersonalToolbar").setAttribute("collapsed", "true");
+    }
+  }
+
+  var disableHistory = gPrefService.getBoolPref("config.lockdown.history");
+  if (!isStartup || disableHistory) {
+    lockdownElement("viewHistorySidebar", disableHistory);
+    UpdateBackForwardButtons();
+    var urlBar = document.getElementById("urlbar");
+    urlBar.setAttribute("enablehistory", disableHistory ? "false" : "true");
+  }
+
+  var disableURLBar = gPrefService.getBoolPref("config.lockdown.urlbar");
+  if (!isStartup || disableURLBar) {
+    lockdownElement("urlbar", disableURLBar);
+    lockdownElement("Browser:OpenLocation", disableURLBar);
+    lockdownElement("Browser:OpenFile", disableURLBar);
+  }
+
+  var disableSearchBar = gPrefService.getBoolPref("config.lockdown.searchbar");
+  if (!isStartup || disableSearchBar) {
+    lockdownElement("searchbar-textfield", disableSearchBar);
+    lockdownElement("searchbar-dropmarker", disableSearchBar);
+  }
+
+  var disableToolbarEditing = gPrefService.getBoolPref("config.lockdown.toolbarediting");
+  if (!isStartup || disableToolbarEditing) {
+    var e = document.getElementById("cmd_CustomizeToolbars");
+    if (!e.getAttribute("inCustomization")) {
+      lockdownElement("cmd_CustomizeToolbars", disableToolbarEditing);
+    }
+  }
+
+  // Close sidebar if we disabled the command that's currently in use
+  var sidebarBox = document.getElementById("sidebar-box");
+  var cmd = sidebarBox.getAttribute("sidebarcommand");
+  if (cmd) {
+    var elt = document.getElementById(cmd);
+    if (elt && elt.getAttribute("disabled") == "true") {
+      toggleSidebar(cmd, false);
+      gMustLoadSidebar = false;
+    }
+  }
+}
+
+var lockdownObserver = {
+  observe: function(aSubject, aTopic, aPrefName)
+  {
+    try {
+      applyLockdown(false);
+    } catch (ex) {
+      dump("Failed lockdown: " + ex + "\n");
+    }
+  }
+};
+
+
 function delayedStartup()
 {
   var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
@@ -942,7 +1054,15 @@ function delayedStartup()
 
   if (!gPrefService)
     gPrefService = Components.classes["@mozilla.org/preferences-service;1"]
-                             .getService(Components.interfaces.nsIPrefBranch);
+                           .getService(Components.interfaces.nsIPrefBranchInternal);
+  try {
+    // do lockdown stuff in an exception handler so that if it fails
+    // catastrophically, the browser should still come up and function
+    applyLockdown(true);
+    gPrefService.addObserver("config.lockdown.", lockdownObserver, false);
+  } catch (ex) {
+    dump("Failed lockdown: " + ex + "\n");
+  }
   BrowserOffline.init();
   
   if (gURLBar && document.documentElement.getAttribute("chromehidden").indexOf("toolbar") != -1) {
@@ -961,8 +1081,8 @@ function delayedStartup()
   window.addEventListener("keypress", ctrlNumberTabSelection, false);
 
   if (gMustLoadSidebar) {
-    var sidebar = document.getElementById("sidebar");
     var sidebarBox = document.getElementById("sidebar-box");
+    var sidebar = document.getElementById("sidebar");
     sidebar.setAttribute("src", sidebarBox.getAttribute("src"));
   }
 
@@ -1130,6 +1250,8 @@ function BrowserShutdown()
   os.removeObserver(gSessionHistoryObserver, "browser:purge-session-history");
   os.removeObserver(gXPInstallObserver, "xpinstall-install-blocked");
 
+  gPrefService.removeObserver("config.lockdown.", lockdownObserver);
+
   try {
     gBrowser.removeProgressListener(window.XULBrowserWindow);
   } catch (ex) {
@@ -1687,6 +1809,9 @@ function updateGoMenu(aEvent, goMenu)
 
   var history = document.getElementById("hiddenHistoryTree");
 
+  if (gPrefService.getBoolPref("config.lockdown.history"))
+    return;
+
   if (history.hidden) {
     history.hidden = false;
     var globalHistory = Components.classes["@mozilla.org/browser/global-history;2"]
@@ -3355,6 +3480,7 @@ function BrowserCustomizeToolbar()
 
   var cmd = document.getElementById("cmd_CustomizeToolbars");
   cmd.setAttribute("disabled", "true");
+  cmd.setAttribute("inCustomization", "true");
 
 #ifdef TOOLBAR_CUSTOMIZATION_SHEET
   document.getElementById("customizeToolbarSheetBox").hidden = false;
@@ -3382,6 +3508,15 @@ function BrowserCustomizeToolbar()
 #endif
 }
 
+function BrowserRestoreCustomizationDisabledState()
+{
+  var cmd = document.getElementById("cmd_CustomizeToolbars");
+  if (!gPrefService.getBoolPref("config.lockdown.toolbarediting")) {
+    cmd.removeAttribute("disabled", "true");
+  }
+  cmd.removeAttribute("inCustomization");
+}
+
 function BrowserToolboxCustomizeDone(aToolboxChanged)
 {
 #ifdef TOOLBAR_CUSTOMIZATION_SHEET
@@ -3414,8 +3549,7 @@ function BrowserToolboxCustomizeDone(aToolboxChanged)
   var menubar = document.getElementById("main-menubar");
   for (var i = 0; i < menubar.childNodes.length; ++i)
     menubar.childNodes[i].setAttribute("disabled", false);
-  var cmd = document.getElementById("cmd_CustomizeToolbars");
-  cmd.removeAttribute("disabled");
+  BrowserRestoreCustomizationDisabledState();
 
   // XXXmano bug 287105: wallpaper to bug 309953,
   // the reload button isn't in sync with the reload command.
@@ -4176,6 +4310,9 @@ function onViewToolbarsPopupShowing(aEvent)
       menuItem.setAttribute("toolbarindex", i);
       menuItem.setAttribute("type", "checkbox");
       menuItem.setAttribute("label", toolbarName);
+      if (toolbar.getAttribute("disabled") == "true") {
+        menuItem.setAttribute("disabled", "true");
+      }
       menuItem.setAttribute("accesskey", toolbar.getAttribute("accesskey"));
       menuItem.setAttribute("checked", toolbar.getAttribute("collapsed") != "true");
       popup.insertBefore(menuItem, firstMenuItem);
@@ -4417,7 +4554,8 @@ nsContextMenu.prototype = {
 #endif
         this.showItem( "context-setDesktopBackground", haveSetDesktopBackground && this.onLoadedImage );
 
-        if ( haveSetDesktopBackground && this.onLoadedImage )
+        var lockedSetDesktopBackground = gPrefService.getBoolPref("config.lockdown.setwallpaper");
+        if ( haveSetDesktopBackground && this.onLoadedImage && !lockedSetDesktopBackground )
             this.setItemAttr( "context-setDesktopBackground", "disabled", this.disableSetDesktopBackground());
 
         // View Image depends on whether an image was clicked on.
diff --git a/browser/base/content/pageInfo.js b/browser/base/content/pageInfo.js
index 289aad6..e9c1f34 100644
--- a/browser/base/content/pageInfo.js
+++ b/browser/base/content/pageInfo.js
@@ -757,8 +757,11 @@ function onImageSelect()
 {
   var tree = document.getElementById("imagetree");
   var saveAsButton = document.getElementById("imagesaveasbutton");
+  var saveLocked = Components.classes["@mozilla.org/preferences-service;1"]
+    .getService(Components.interfaces.nsIPrefBranch)
+    .getBoolPref("config.lockdown.savepage");
 
-  if (tree.view.selection.count == 1)
+  if (tree.view.selection.count == 1 && !saveLocked)
   {
     makePreview(tree.view.selection.currentIndex);
     saveAsButton.setAttribute("disabled", "false");
diff --git a/browser/components/bookmarks/content/bookmarksProperties.js b/browser/components/bookmarks/content/bookmarksProperties.js
index fddef1d..dc2beec 100644
--- a/browser/components/bookmarks/content/bookmarksProperties.js
+++ b/browser/components/bookmarks/content/bookmarksProperties.js
@@ -138,6 +138,15 @@ function Init()
   // set initial focus
   nameNode.focus();
   nameNode.select();
+
+  // I don't know why doing this is a good idea. If bookmark editing
+  // is disabled we shouldn't let the user into the preferences
+  // dialog.
+  var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+                           .getService(Components.interfaces.nsIPrefBranch);
+  if (prefs.getBoolPref("config.lockdown.bookmark")) {
+    document.getElementById("url").setAttribute("disabled", "true");
+  }
 }
 
 
diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js
index 16991ac..b3f5920 100644
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1018,6 +1018,21 @@ pref("config.use_system_prefs", false);
 // if the system has enabled accessibility
 pref("config.use_system_prefs.accessibility", false);
 
+// UI lockdown settings
+pref("config.lockdown.printing", false);
+pref("config.lockdown.printsetup", false);
+pref("config.lockdown.savepage", false);
+pref("config.lockdown.history",false);
+pref("config.lockdown.toolbarediting",false);
+pref("config.lockdown.urlbar",false);
+pref("config.lockdown.bookmark",false);
+pref("config.lockdown.disable_themes",false);
+pref("config.lockdown.disable_extensions",false);
+pref("config.lockdown.searchbar",false);
+pref("config.lockdown.hidebookmark",false);
+pref("config.lockdown.setwallpaper",false);
+pref("config.lockdown.showsavedpasswords", false);
+
 /*
  * What are the entities that you want Mozilla to save using mnemonic
  * names rather than numeric codes? E.g. If set, we'll output &nbsp;
diff --git a/toolkit/components/help/content/toolbarCustomization.js b/toolkit/components/help/content/toolbarCustomization.js
index 67a037b..c553e70 100644
--- a/toolkit/components/help/content/toolbarCustomization.js
+++ b/toolkit/components/help/content/toolbarCustomization.js
@@ -42,11 +42,23 @@ function CustomizeToolbar(id)
 {
   var customizePopup = document.getElementById("cmd_CustomizeToolbars");
   customizePopup.setAttribute("disabled", "true");
+  customizePopup.setAttribute("inEdit", "true");
 
   window.openDialog("chrome://help/content/customizeToolbar.xul", "CustomizeToolbar",
                     "chrome,all,dependent", document.getElementById(id));
 }
 
+function RestoreCustomizationDisabledState()
+{
+  var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+    .getService(Components.interfaces.nsIPrefBranchInternal);
+  var customizePopup = document.getElementById("cmd_CustomizeToolbars");
+  if (!prefs.getBoolPref("config.lockdown.toolbarediting")) {
+    customizePopup.removeAttribute("disabled");
+  } 
+  customizePopup.removeAttribute("inEdit");
+}
+
 # ToolboxCustomizeDone() - Resets the toolbar back to its default state. Reenables
 #	toolbar buttons and the "Customize Toolbar" command.
 #
@@ -54,8 +66,7 @@ function CustomizeToolbar(id)
 function ToolboxCustomizeDone(aToolboxChanged)
 {
 # Update global UI elements that may have been added or removed
-  var customizePopup = document.getElementById("cmd_CustomizeToolbars");
-  customizePopup.removeAttribute("disabled");
+  RestoreCustomizationDisabledState();
 
 # make sure our toolbar buttons have the correct enabled state restored to them...
   if (this.UpdateToolbar != undefined)
@@ -77,8 +88,7 @@ function UpdateToolbar(caller)
   document.commandDispatcher.updateCommands('help-toolbar');
 
 # re-enable toolbar customization command
-  var customizePopup = document.getElementById("cmd_CustomizeToolbars");
-  customizePopup.removeAttribute("disabled");
+  RestoreCustomizationDisabledState();
 
 # hook for extra toolbar items
   var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
diff --git a/toolkit/components/passwordmgr/resources/content/passwordManager.js b/toolkit/components/passwordmgr/resources/content/passwordManager.js
index d128253..e4d7e70 100644
--- a/toolkit/components/passwordmgr/resources/content/passwordManager.js
+++ b/toolkit/components/passwordmgr/resources/content/passwordManager.js
@@ -137,7 +137,10 @@ function LoadSignons() {
   // disable "remove all signons" button if there are no signons
   var element = document.getElementById("removeAllSignons");
   var toggle = document.getElementById("togglePasswords");
-  if (signons.length == 0 || gSelectUserInUse) {
+  var viewLocked = Components.classes["@mozilla.org/preferences-service;1"]
+    .getService(Components.interfaces.nsIPrefBranch)
+    .getBoolPref("config.lockdown.showsavedpasswords");
+  if (signons.length == 0 || gSelectUserInUse || viewLocked) {
     element.setAttribute("disabled","true");
     toggle.setAttribute("disabled","true");
   } else {
diff --git a/toolkit/components/printing/content/printdialog.js b/toolkit/components/printing/content/printdialog.js
index 4584a8a..b0c1e3d 100644
--- a/toolkit/components/printing/content/printdialog.js
+++ b/toolkit/components/printing/content/printdialog.js
@@ -51,6 +51,7 @@ var gPrintSettings     = null;
 var gWebBrowserPrint   = null;
 var gPrintSetInterface = Components.interfaces.nsIPrintSettings;
 var doDebug            = false;
+var gPrefService       = null;
 
 //---------------------------------------------------
 function initDialog()
@@ -88,11 +89,23 @@ function initDialog()
   dialog.fpDialog        = document.getElementById("fpDialog");
 
   dialog.enabled         = false;
+
+  gPrefService = Components.classes["@mozilla.org/preferences-service;1"]
+      .getService(Components.interfaces.nsIPrefService).getBranch(null);
+  if (gPrefService.getBoolPref("config.lockdown.savepage")) {
+    dialog.fileCheck.setAttribute("disabled", "true");
+  }    
+  if (gPrefService.getBoolPref("config.lockdown.printing")) {
+    dialog.printButton.setAttribute("disabled", "true");
+  }
 }
 
 //---------------------------------------------------
 function checkInteger(element)
 {
+  if (gPrefService.getBoolPref("config.lockdown.printing"))
+    return;
+
   var value = element.value;
   if (value && value.length > 0) {
     value = value.replace(/[^0-9]/g,"");
