/* This file modifies the main browser window. It does the following:
 *   Goes through the hiddenUI list and hides any UI
 *
 */

const EXPORTED_SYMBOLS = [];

const {classes: Cc, interfaces: Ci, utils: Cu} = Components;

Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/CustomizableUI.jsm");
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
Cu.import("resource://cck2/CCK2.jsm");

var configs = null;

var observer = {
  observe: function observe(subject, topic, data) {
    switch (topic) {
      case "chrome-document-global-created":
        var win = subject.QueryInterface(Components.interfaces.nsIDOMWindow);
        win.addEventListener("load", function onLoad(event) {
          win.removeEventListener("load", onLoad, false);
          var doc = event.target;
          var url = doc.location.href.split("?")[0].split("#")[0];
          switch (url) {
            case "chrome://browser/content/browser.xul":
              // Workaround https://bugzilla.mozilla.org/show_bug.cgi?id=1149617
              var origSetReportPhishingMenu = win.gSafeBrowsing.setReportPhishingMenu;
              win.gSafeBrowsing.setReportPhishingMenu = function() {
                try {
                  origSetReportPhishingMenu();
                } catch (e) {}
              }

              win.addEventListener("unload", function onUnload(event) {
                win.removeEventListener("unload", onUnload, false);
                var panelUIPopup = doc.getElementById("PanelUI-popup");
                if (panelUIPopup) {
                  E("PanelUI-popup", doc).removeEventListener("popupshowing", onPanelShowing, false);
                }
              });
              var panelUIPopup = doc.getElementById("PanelUI-popup");
              if (panelUIPopup) {
                E("PanelUI-popup", doc).addEventListener("popupshowing", onPanelShowing, false);
              }
              var appMenuPopup = doc.getElementById("appMenu-popup");
              if (appMenuPopup) {
                E("appMenu-popup", doc).addEventListener("popupshowing", onAppMenuShowing, false);
              }
              configs = CCK2.getConfigs();
              for (let id in configs) {
                config = configs[id];
                if (config.disablePrivateBrowsing &&
                    PrivateBrowsingUtils.isWindowPrivate(win)) {
                  win.setTimeout(function() {
                    Services.prompt.alert(win, "Private Browsing", "Private Browsing has been disabled by your administrator");
                    win.close();
                  }, 0, false);
                }
                if (config.disablePrivateBrowsing) {
                  disablePrivateBrowsing(doc);
                }
                if (config.disableSync) {
                  disableSync(doc);
                }
                if (config.disableAddonsManager) {
                  disableAddonsManager(doc);
                }
                if (config.removeDeveloperTools) {
                  Services.tm.mainThread.dispatch(function() {
                    removeDeveloperTools(doc);
                  }, Ci.nsIThread.DISPATCH_NORMAL);
                }
                if (config.disableErrorConsole) {
                  disableErrorConsole(doc);
                }
                if (config.disableFirefoxHealthReport) {
                  var healthReportMenu = doc.getElementById("healthReport");
                  if (healthReportMenu) {
                    healthReportMenu.parentNode.removeChild(healthReportMenu);
                  }
                }
                if (config.removeSafeModeMenu) {
                  hide(E("helpSafeMode", doc));
                }
                if (config.titlemodifier) {
                  doc.getElementById("main-window").setAttribute("titlemodifier", config.titlemodifier);
                }
                if (config.removeSetDesktopBackground) {
                  // Because this is on a context menu, we can't use "hidden"
                  if (E("context-setDesktopBackground", doc)) {
                    E("context-setDesktopBackground", doc).setAttribute("style", "display: none;");
                  }
                }
                if (config.disableWebApps) {
                  CustomizableUI.destroyWidget("web-apps-button");
                  hide(E("menu_openApps", doc));
                }
                if (config.disableHello) {
                  CustomizableUI.destroyWidget("loop-button");
                  hide(E("menu_openLoop", doc));
                }
                if (config.disablePocket) {
                  CustomizableUI.destroyWidget("pocket-button");
                }
                if (config.disableSharePage) {
                  CustomizableUI.destroyWidget("social-share-button");
                  // Because these are on a context menu, we can't use "hidden"
                  if (E("context-sharelink", doc)) {
                    E("context-sharelink", doc).setAttribute("style", "display: none;");
                  }
                  if (E("context-shareselect", doc)) {
                    E("context-shareselect", doc).setAttribute("style", "display: none;");
                  }
                  if (E("context-shareimage", doc)) {
                    E("context-shareimage", doc).setAttribute("style", "display: none;");
                  }
                  if (E("context-sharevideo", doc)) {
                    E("context-sharevideo", doc).setAttribute("style", "display: none;");
                  }
                  if (E("context-sharepage", doc)) {
                    E("context-sharepage", doc).setAttribute("style", "display: none;");
                  }
                }
                if (config.disableSocialAPI) {
                  win.SocialActivationListener = {};
                }
                if (config.disableForget) {
                  CustomizableUI.destroyWidget("panic-button");
                }
                if (config.hiddenUI) {
                  hideUIElements(doc, config.hiddenUI);
                }
                if (config.helpMenu) {
                  // We need to run this function on a delay, because we won't know
                  // if the about menu is hidden for mac until after it is run.
                  Services.tm.mainThread.dispatch(function() {
                    var helpMenuPopup = doc.getElementById("menu_HelpPopup");
                    var menuitem = doc.createElement("menuitem");
                    menuitem.setAttribute("label", config.helpMenu.label);
                    if ("accesskey" in config.helpMenu) {
                      menuitem.setAttribute("accesskey", config.helpMenu.accesskey);
                    }
                    menuitem.setAttribute("oncommand", "openUILink('" + config.helpMenu.url + "');");
                    menuitem.setAttribute("onclick", "checkForMiddleClick(this, event);");
                    if (!E("aboutName", doc) || E("aboutName", doc).hidden) {
                      // Mac
                      helpMenuPopup.appendChild(menuitem);
                    } else {
                      helpMenuPopup.insertBefore(menuitem, E("aboutName", doc));
                      helpMenuPopup.insertBefore(doc.createElement("menuseparator"),
                                                        E("aboutName", doc));
                    }
                  }, Ci.nsIThread.DISPATCH_NORMAL);
                }
                if (config.firstrun || config.upgrade) {
                  if (config.displayBookmarksToolbar || (config.bookmarks && config.bookmarks.toolbar)) {
                    CustomizableUI.setToolbarVisibility("PersonalToolbar", "true");
                  }
                  if (config.displayMenuBar) {
                    CustomizableUI.setToolbarVisibility("toolbar-menubar", "true");
                  }
                  if (config.showSearchBar) {
                    CustomizableUI.addWidgetToArea("search-container", CustomizableUI.AREA_NAVBAR,
                    CustomizableUI.getPlacementOfWidget("urlbar-container").position + 1);
                  }
                  config.firstrun = false;
                  config.upgrade = false;
                }
              }
              break;
            case "chrome://browser/content/places/places.xul":
            case "chrome://browser/content/bookmarks/bookmarksPanel.xul":
            case "chrome://browser/content/history/history-panel.xul":
              configs = CCK2.getConfigs();
              for (let id in configs) {
                var config = configs[id];       
                if (config.disablePrivateBrowsing) {
                  if (E("placesContext_open:newprivatewindow", doc)) {
                    E("placesContext_open:newprivatewindow", doc).setAttribute("style", "display: none;");
                  }
                }
                if (config.hiddenUI) {
                  hideUIElements(doc, config.hiddenUI);
                }
              }
              break;
          }
        }, false);
        break;
    }
  }
}
Services.obs.addObserver(observer, "chrome-document-global-created", false);

function disableSync(doc) {
  var win = doc.defaultView;
  if (win.gSyncUI) {
    var mySyncUI = {
      init: function() {
        return;
      },
      initUI: function() {
        return;
      },
      updateUI: function() {
        hide(E("sync-setup-state", doc));
        hide(E("sync-syncnow-state", doc));
        hide(E("sync-setup", doc));
        hide(E("sync-syncnowitem", doc));
      }
    }
    win.gSyncUI = mySyncUI;
  }
  CustomizableUI.destroyWidget("sync-button");
  CustomizableUI.removeWidgetFromArea("sync-button");
  var toolbox = doc.getElementById("navigator-toolbox");
  if (toolbox && toolbox.palette) {
    let element = toolbox.palette.querySelector("#sync-button");
    if (element) {
      element.parentNode.removeChild(element);
    }
  }
  hide(E("sync-setup-state", doc));
  hide(E("sync-syncnow-state", doc));
  hide(E("sync-setup", doc));
  hide(E("sync-syncnowitem", doc));
}

function disablePrivateBrowsing(doc) {
  disable(E("Tools:PrivateBrowsing", doc));
  hide(E("menu_newPrivateWindow", doc));
  // Because this is on a context menu, we can't use "hidden"
  if (E("context-openlinkprivate", doc))
    E("context-openlinkprivate", doc).setAttribute("style", "display: none;");
  if (E("placesContext_open:newprivatewindow", doc))
    E("placesContext_open:newprivatewindow", doc).setAttribute("style", "display: none;");
  CustomizableUI.destroyWidget("privatebrowsing-button")
}

function disableAddonsManager(doc) {
  hide(E("menu_openAddons", doc));
  disable(E("Tools:Addons", doc)); // Ctrl+Shift+A
  CustomizableUI.destroyWidget("add-ons-button")
}

function removeDeveloperTools(doc) {
  var win = doc.defaultView;
  // Need to delay this because devtools is created dynamically
  win.setTimeout(function() {
    CustomizableUI.destroyWidget("developer-button")
    hide(E("webDeveloperMenu", doc));
    var devtoolsKeyset = doc.getElementById("devtoolsKeyset");
    if (devtoolsKeyset) {
      for (var i = 0; i < devtoolsKeyset.childNodes.length; i++) {
        devtoolsKeyset.childNodes[i].removeAttribute("oncommand");
        devtoolsKeyset.childNodes[i].removeAttribute("command");
      }
    }
  }, 0);
  try {
    doc.getElementById("Tools:ResponsiveUI").removeAttribute("oncommand");
  } catch (e) {}
  try {
    doc.getElementById("Tools:Scratchpad").removeAttribute("oncommand");
  } catch (e) {}
  try {
    doc.getElementById("Tools:BrowserConsole").removeAttribute("oncommand");
  } catch (e) {}
  try {
    doc.getElementById("Tools:BrowserToolbox").removeAttribute("oncommand");
  } catch (e) {}
  try {
    doc.getElementById("Tools:DevAppsMgr").removeAttribute("oncommand");
  } catch (e) {}
  try {
    doc.getElementById("Tools:DevToolbar").removeAttribute("oncommand");
  } catch (e) {}
  try {
    doc.getElementById("Tools:DevToolbox").removeAttribute("oncommand");
  } catch (e) {}
  try {
    doc.getElementById("Tools:DevToolbarFocus").removeAttribute("oncommand");
  } catch (e) {}
  CustomizableUI.destroyWidget("developer-button")
}

function disableErrorConsole(doc) {
  doc.getElementById("Tools:ErrorConsole").removeAttribute("oncommand");
}

function onPanelShowing(event) {
  var configs = CCK2.getConfigs();
  for (let id in configs) {
    var config = configs[id];       
    if (config.disableSync) {
      hide(E("PanelUI-fxa-status", event.target.ownerDocument));
      hide(E("PanelUI-footer-fxa", event.target.ownerDocument)); // Firefox 42+
    }
  }
}

function onAppMenuShowing(event) {
  var configs = CCK2.getConfigs();
  for (let id in configs) {
    var config = configs[id];
    if (config.disableSync) {
      hide(E("appMenu-fxa-container", event.target.ownerDocument));
    }
    if (config.removeDeveloperTools) {
      hide(E("appMenu-developer-button", event.target.ownerDocument));
    }
  }
}

function E(id, context) {
  var element = context.getElementById(id);
  return element;
}

function hide(element) {
  if (element) {
    element.setAttribute("hidden", "true");
  }
}

function disable(element) {
  if (element) {
    element.disabled = true;
    element.setAttribute("disabled", "true");
  }
}

function hideUIElements(doc, hiddenUI) {
  for (var i=0; i < hiddenUI.length; i++) {
    var uiElements = doc.querySelectorAll(hiddenUI[i]);
    // Don't use .hidden since it doesn't work sometimes
    var style = doc.getElementById("cck2-hidden-style");
    if (!style) {
      style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style");
      style.setAttribute("id", "cck2-hidden-style");
      style.setAttribute("type", "text/css");
      doc.documentElement.appendChild(style);
    }
    style.textContent = style.textContent + hiddenUI[i] + "{display: none !important;}";
    if (!uiElements || uiElements.length == 0) {
      continue;
    }
    for (var j=0; j < uiElements.length; j++) {
      var uiElement = uiElements[j];
      if (uiElement.nodeName == "menuitem") {
        uiElement.removeAttribute("key");
        uiElement.removeAttribute("oncommand");
        if (uiElement.hasAttribute("command")) {
          var commandId = uiElement.getAttribute("command");
          uiElement.removeAttribute("command");
          var command = doc.getElementById(commandId);
          command.removeAttribute("oncommand");
          var keys = doc.querySelectorAll("key[command='" + commandId + "']")
          for (var k=0; k < keys.length; k++) {
            keys[k].removeAttribute("command");
          }
        }
      }
      // Horrible hack to work around the crappy Australis help menu
      // Items on the menu always show up in the Australis menu, so we have to remove them.
      if (uiElements[j].parentNode.id == "menu_HelpPopup") {
        uiElements[j].parentNode.removeChild(uiElements[j]);
      }
    }
  }
}