diff --git a/helpers/DATA/firefox/firefox-kde.patch b/helpers/DATA/firefox/firefox-kde.patch deleted file mode 100644 index 403021449e54cf24cc6c083874c5902ae28f9130..0000000000000000000000000000000000000000 --- a/helpers/DATA/firefox/firefox-kde.patch +++ /dev/null @@ -1,1815 +0,0 @@ -# HG changeset patch -# Parent 77c3bdc27160dfa96aa4b3288c7f12a72f273967 - -diff --git a/browser/base/content/browser-kde.xul b/browser/base/content/browser-kde.xul -new file mode 100644 ---- /dev/null -+++ b/browser/base/content/browser-kde.xul -@@ -0,0 +1,1250 @@ -+#filter substitution -+<?xml version="1.0"?> -+# -*- Mode: HTML -*- -+# -+# This Source Code Form is subject to the terms of the Mozilla Public -+# License, v. 2.0. If a copy of the MPL was not distributed with this -+# file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ -+<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?> -+<?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?> -+<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?> -+<?xml-stylesheet href="chrome://browser/skin/controlcenter/panel.css" type="text/css"?> -+<?xml-stylesheet href="chrome://browser/skin/customizableui/panelUIOverlay.css" type="text/css"?> -+<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?> -+<?xml-stylesheet href="chrome://browser/skin/browser-lightweightTheme.css" type="text/css"?> -+ -+<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?> -+<?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?> -+<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?> -+ -+# All DTD information is stored in a separate file so that it can be shared by -+# hiddenWindow.xul. -+#include browser-doctype.inc -+ -+<window id="main-window" -+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" -+ xmlns:svg="http://www.w3.org/2000/svg" -+ xmlns:html="http://www.w3.org/1999/xhtml" -+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" -+ onload="gBrowserInit.onLoad()" onunload="gBrowserInit.onUnload()" onclose="return WindowIsClosing();" -+ title="&mainWindow.title;" -+ title_normal="&mainWindow.title;" -+#ifdef XP_MACOSX -+ title_privatebrowsing="&mainWindow.title;&mainWindow.titlemodifiermenuseparator;&mainWindow.titlePrivateBrowsingSuffix;" -+ titledefault="&mainWindow.title;" -+ titlemodifier="" -+ titlemodifier_normal="" -+ titlemodifier_privatebrowsing="&mainWindow.titlePrivateBrowsingSuffix;" -+#else -+ title_privatebrowsing="&mainWindow.titlemodifier; &mainWindow.titlePrivateBrowsingSuffix;" -+ titlemodifier="&mainWindow.titlemodifier;" -+ titlemodifier_normal="&mainWindow.titlemodifier;" -+ titlemodifier_privatebrowsing="&mainWindow.titlemodifier; &mainWindow.titlePrivateBrowsingSuffix;" -+#endif -+#ifdef CAN_DRAW_IN_TITLEBAR -+#ifdef XP_WIN -+ chromemargin="0,2,2,2" -+#else -+ chromemargin="0,-1,-1,-1" -+#endif -+ tabsintitlebar="true" -+#endif -+ titlemenuseparator="&mainWindow.titlemodifiermenuseparator;" -+ lightweightthemes="true" -+ lightweightthemesfooter="browser-bottombox" -+ windowtype="navigator:browser" -+ macanimationtype="document" -+ screenX="4" screenY="4" -+ fullscreenbutton="true" -+ sizemode="normal" -+ retargetdocumentfocus="urlbar" -+ persist="screenX screenY width height sizemode"> -+ -+# All JS files which are not content (only) dependent that browser.xul -+# wishes to include *must* go into the global-scripts.inc file -+# so that they can be shared by macBrowserOverlay.xul. -+#include global-scripts.inc -+<script type="application/javascript" src="chrome://browser/content/nsContextMenu.js"/> -+ -+<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/> -+ -+<script type="application/javascript" src="chrome://browser/content/places/editBookmarkOverlay.js"/> -+ -+# All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the -+# browser-sets.inc file for sharing with hiddenWindow.xul. -+#define FULL_BROWSER_WINDOW -+#include browser-sets.inc -+#undef FULL_BROWSER_WINDOW -+ -+ <popupset id="mainPopupSet"> -+ <menupopup id="tabContextMenu" -+ onpopupshowing="if (event.target == this) TabContextMenu.updateContextMenu(this);" -+ onpopuphidden="if (event.target == this) TabContextMenu.contextTab = null;"> -+ <menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;" -+ oncommand="gBrowser.reloadTab(TabContextMenu.contextTab);"/> -+ <menuitem id="context_toggleMuteTab" oncommand="TabContextMenu.contextTab.toggleMuteAudio();"/> -+ <menuseparator/> -+ <menuitem id="context_pinTab" label="&pinTab.label;" -+ accesskey="&pinTab.accesskey;" -+ oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/> -+ <menuitem id="context_unpinTab" label="&unpinTab.label;" hidden="true" -+ accesskey="&unpinTab.accesskey;" -+ oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/> -+ <menu id="context_tabViewMenu" label="&moveToGroup.label;" -+ accesskey="&moveToGroup.accesskey;"> -+ <menupopup id="context_tabViewMenuPopup" -+ onpopupshowing="if (event.target == this) TabView.moveToGroupPopupShowing(event);"> -+ <menuseparator id="context_tabViewNamedGroups" hidden="true"/> -+ <menuitem id="context_tabViewNewGroup" label="&moveToNewGroup.label;" -+ oncommand="TabView.moveTabTo(TabContextMenu.contextTab, null);"/> -+ </menupopup> -+ </menu> -+ <menuitem id="context_openTabInWindow" label="&moveToNewWindow.label;" -+ accesskey="&moveToNewWindow.accesskey;" -+ tbattr="tabbrowser-multiple" -+ oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/> -+#ifdef E10S_TESTING_ONLY -+ <menuitem id="context_openNonRemoteWindow" label="Open in new non-e10s window" -+ tbattr="tabbrowser-remote" -+ hidden="true" -+ oncommand="gBrowser.openNonRemoteWindow(TabContextMenu.contextTab);"/> -+#endif -+ <menuseparator/> -+ <menuitem id="context_reloadAllTabs" label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;" -+ tbattr="tabbrowser-multiple-visible" -+ oncommand="gBrowser.reloadAllTabs();"/> -+ <menuitem id="context_bookmarkAllTabs" -+ label="&bookmarkAllTabs.label;" -+ accesskey="&bookmarkAllTabs.accesskey;" -+ command="Browser:BookmarkAllTabs"/> -+ <menuitem id="context_closeTabsToTheEnd" label="&closeTabsToTheEnd.label;" accesskey="&closeTabsToTheEnd.accesskey;" -+ oncommand="gBrowser.removeTabsToTheEndFrom(TabContextMenu.contextTab);"/> -+ <menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;" -+ oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/> -+ <menuseparator/> -+ <menuitem id="context_undoCloseTab" -+ label="&undoCloseTab.label;" -+ accesskey="&undoCloseTab.accesskey;" -+ observes="History:UndoCloseTab"/> -+ <menuitem id="context_closeTab" label="&closeTab.label;" accesskey="&closeTab.accesskey;" -+ oncommand="gBrowser.removeTab(TabContextMenu.contextTab, { animate: true });"/> -+ </menupopup> -+ -+ <!-- bug 415444/582485: event.stopPropagation is here for the cloned version -+ of this menupopup --> -+ <menupopup id="backForwardMenu" -+ onpopupshowing="return FillHistoryMenu(event.target);" -+ oncommand="gotoHistoryIndex(event); event.stopPropagation();" -+ onclick="checkForMiddleClick(this, event);"/> -+ <tooltip id="aHTMLTooltip" page="true"/> -+ <tooltip id="remoteBrowserTooltip"/> -+ -+ <!-- for search and content formfill/pw manager --> -+ <panel type="autocomplete" id="PopupAutoComplete" noautofocus="true" hidden="true"/> -+ -+ <!-- for search with one-off buttons --> -+ <panel type="autocomplete" id="PopupSearchAutoComplete" noautofocus="true" hidden="true"/> -+ -+ <!-- for url bar autocomplete --> -+ <panel type="autocomplete-richlistbox" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"> -+#ifdef NIGHTLY_BUILD -+ <hbox id="urlbar-search-footer" flex="1" align="stretch" pack="end"> -+ <button id="urlbar-search-settings" label="&changeSearchSettings.button;" -+ oncommand="BrowserUITelemetry.countSearchSettingsEvent('urlbar'); openPreferences('paneSearch')"/> -+ </hbox> -+#endif -+ </panel> -+ -+ <!-- for select dropdowns. The menupopup is what shows the list of options, -+ and the popuponly menulist makes things like the menuactive attributes -+ work correctly on the menupopup. ContentSelectDropdown expects the -+ popuponly menulist to be its immediate parent. --> -+ <menulist popuponly="true" id="ContentSelectDropdown" hidden="true"> -+ <menupopup rolluponmousewheel="true" -+ activateontab="true" -+#ifdef XP_WIN -+ consumeoutsideclicks="false" ignorekeys="handled" -+#endif -+ /> -+ </menulist> -+ -+ <!-- for invalid form error message --> -+ <panel id="invalid-form-popup" type="arrow" orient="vertical" noautofocus="true" hidden="true" level="parent"> -+ <description/> -+ </panel> -+ -+ <panel id="editBookmarkPanel" -+ type="arrow" -+ footertype="promobox" -+ orient="vertical" -+ ignorekeys="true" -+ hidden="true" -+ onpopupshown="StarUI.panelShown(event);" -+ aria-labelledby="editBookmarkPanelTitle"> -+ <row id="editBookmarkPanelHeader" align="center" hidden="true"> -+ <vbox align="center"> -+ <image id="editBookmarkPanelStarIcon"/> -+ </vbox> -+ <vbox> -+ <label id="editBookmarkPanelTitle"/> -+ <description id="editBookmarkPanelDescription"/> -+ <hbox> -+ <button id="editBookmarkPanelRemoveButton" -+ class="editBookmarkPanelHeaderButton" -+ oncommand="StarUI.removeBookmarkButtonCommand();" -+ accesskey="&editBookmark.removeBookmark.accessKey;"/> -+ </hbox> -+ </vbox> -+ </row> -+ <vbox id="editBookmarkPanelContent" flex="1" hidden="true"/> -+ <hbox id="editBookmarkPanelBottomButtons" pack="end"> -+#ifdef XP_UNIX -+ <button id="editBookmarkPanelDoneButton" -+ class="editBookmarkPanelBottomButton" -+ label="&editBookmark.done.label;" -+ default="true" -+ oncommand="StarUI.panel.hidePopup();"/> -+ <button id="editBookmarkPanelDeleteButton" -+ class="editBookmarkPanelBottomButton" -+ label="&editBookmark.cancel.label;" -+ oncommand="StarUI.cancelButtonOnCommand();"/> -+#else -+ <button id="editBookmarkPanelDeleteButton" -+ class="editBookmarkPanelBottomButton" -+ label="&editBookmark.cancel.label;" -+ oncommand="StarUI.cancelButtonOnCommand();"/> -+ <button id="editBookmarkPanelDoneButton" -+ class="editBookmarkPanelBottomButton" -+ label="&editBookmark.done.label;" -+ default="true" -+ oncommand="StarUI.panel.hidePopup();"/> -+#endif -+ </hbox> -+ </panel> -+ -+ <!-- UI tour experience --> -+ <panel id="UITourTooltip" -+ type="arrow" -+ hidden="true" -+ noautofocus="true" -+ noautohide="true" -+ align="start" -+ orient="vertical" -+ role="alert"> -+ <vbox> -+ <hbox pack="end"> -+ <toolbarbutton id="UITourTooltipClose" class="close-icon" -+ tooltiptext="&uiTour.infoPanel.close;"/> -+ </hbox> -+ <hbox id="UITourTooltipBody"> -+ <vbox id="UITourTooltipIconContainer"> -+ <image id="UITourTooltipIcon"/> -+ </vbox> -+ <vbox flex="1"> -+ <label id="UITourTooltipTitle" flex="1"/> -+ <description id="UITourTooltipDescription" flex="1"/> -+ </vbox> -+ </hbox> -+ <hbox id="UITourTooltipButtons" flex="1" align="center"/> -+ </vbox> -+ </panel> -+ <!-- type="default" forces frames to be created so that the panel's size can be determined --> -+ <panel id="UITourHighlightContainer" -+ type="default" -+ hidden="true" -+ noautofocus="true" -+ noautohide="true" -+ flip="none" -+ consumeoutsideclicks="false" -+ mousethrough="always"> -+ <box id="UITourHighlight"></box> -+ </panel> -+ -+ <panel id="abouthome-search-panel" orient="vertical" type="arrow" hidden="true" -+ onclick="this.hidePopup()"> -+ <hbox id="abouthome-search-panel-manage" -+ onclick="openPreferences('paneSearch')"> -+ <label>&changeSearchSettings.button;</label> -+ </hbox> -+ </panel> -+ -+ <panel id="social-share-panel" -+ class="social-panel" -+ type="arrow" -+ orient="vertical" -+ onpopupshowing="SocialShare.onShowing()" -+ onpopuphidden="SocialShare.onHidden()" -+ hidden="true"> -+ <hbox class="social-share-toolbar"> -+ <toolbarbutton id="manage-share-providers" class="toolbarbutton share-provider-button" -+ tooltiptext="&social.addons.label;" -+ oncommand="BrowserOpenAddonsMgr('addons://list/service'); -+ this.parentNode.parentNode.hidePopup();"/> -+ <arrowscrollbox id="social-share-provider-buttons" orient="horizontal" flex="1" pack="end"> -+ <toolbarbutton id="add-share-provider" class="toolbarbutton share-provider-button" type="radio" -+ group="share-providers" tooltiptext="&findShareServices.label;" -+ oncommand="SocialShare.showDirectory()"/> -+ </arrowscrollbox> -+ </hbox> -+ <hbox id="share-container" flex="1"/> -+ </panel> -+ -+ <panel id="social-notification-panel" -+ class="social-panel" -+ type="arrow" -+ hidden="true" -+ noautofocus="true"/> -+ <panel id="social-flyout-panel" -+ class="social-panel" -+ onpopupshown="SocialFlyout.onShown()" -+ onpopuphidden="SocialFlyout.onHidden()" -+ side="right" -+ type="arrow" -+ hidden="true" -+ flip="slide" -+ rolluponmousewheel="true" -+ noautofocus="true" -+ position="topcenter topright"/> -+ -+ <panel id="loop-notification-panel" -+ class="loop-panel social-panel" -+ type="arrow" -+ hidden="true" -+ noautofocus="true"/> -+ -+ <panel id="loop-panel" -+ class="loop-panel social-panel" -+ type="arrow" -+ orient="horizontal" -+ hidden="true"/> -+ -+ <menupopup id="processHangOptions" -+ onpopupshowing="ProcessHangMonitor.refreshMenu(window);"> -+ <menuitem id="processHangTerminateScript" -+ oncommand="ProcessHangMonitor.terminateScript(window)" -+ accesskey="&processHang.terminateScript.accessKey;" -+ label="&processHang.terminateScript.label;"/> -+ <menuitem id="processHangDebugScript" -+ oncommand="ProcessHangMonitor.debugScript(window)" -+ accesskey="&processHang.debugScript.accessKey;" -+ label="&processHang.debugScript.label;"/> -+ <menuitem id="processHangTerminatePlugin" -+ oncommand="ProcessHangMonitor.terminatePlugin(window)" -+ accesskey="&processHang.terminatePlugin.accessKey;" -+ label="&processHang.terminatePlugin.label;"/> -+ <menuitem id="processHangTerminateProcess" -+ oncommand="ProcessHangMonitor.terminateProcess(window)" -+ accesskey="&processHang.terminateProcess.accessKey;" -+ label="&processHang.terminateProcess.label;"/> -+ </menupopup> -+ -+ <menupopup id="toolbar-context-menu" -+ onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('viewToolbarsMenuSeparator'));"> -+ <menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)" -+ accesskey="&customizeMenu.moveToPanel.accesskey;" -+ label="&customizeMenu.moveToPanel.label;" -+ contexttype="toolbaritem" -+ class="customize-context-moveToPanel"/> -+ <menuitem oncommand="gCustomizeMode.removeFromArea(document.popupNode)" -+ accesskey="&customizeMenu.removeFromToolbar.accesskey;" -+ label="&customizeMenu.removeFromToolbar.label;" -+ contexttype="toolbaritem" -+ class="customize-context-removeFromToolbar"/> -+ <menuitem id="toolbar-context-reloadAllTabs" -+ class="toolbaritem-tabsmenu" -+ contexttype="tabbar" -+ oncommand="gBrowser.reloadAllTabs();" -+ label="&toolbarContextMenu.reloadAllTabs.label;" -+ accesskey="&toolbarContextMenu.reloadAllTabs.accesskey;"/> -+ <menuitem id="toolbar-context-bookmarkAllTabs" -+ class="toolbaritem-tabsmenu" -+ contexttype="tabbar" -+ command="Browser:BookmarkAllTabs" -+ label="&toolbarContextMenu.bookmarkAllTabs.label;" -+ accesskey="&toolbarContextMenu.bookmarkAllTabs.accesskey;"/> -+ <menuitem id="toolbar-context-undoCloseTab" -+ class="toolbaritem-tabsmenu" -+ contexttype="tabbar" -+ label="&toolbarContextMenu.undoCloseTab.label;" -+ accesskey="&toolbarContextMenu.undoCloseTab.accesskey;" -+ observes="History:UndoCloseTab"/> -+ <menuseparator/> -+ <menuseparator id="viewToolbarsMenuSeparator"/> -+ <!-- XXXgijs: we're using oncommand handler here to avoid the event being -+ redirected to the command element, thus preventing -+ listeners on the menupopup or further up the tree from -+ seeing the command event pass by. The observes attribute is -+ here so that the menuitem is still disabled and re-enabled -+ correctly. --> -+ <menuitem oncommand="BrowserCustomizeToolbar()" -+ observes="cmd_CustomizeToolbars" -+ class="viewCustomizeToolbar" -+ label="&viewCustomizeToolbar.label;" -+ accesskey="&viewCustomizeToolbar.accesskey;"/> -+ </menupopup> -+ -+ <menupopup id="blockedPopupOptions" -+ onpopupshowing="gPopupBlockerObserver.fillPopupList(event);" -+ onpopuphiding="gPopupBlockerObserver.onPopupHiding(event);"> -+ <menuitem observes="blockedPopupAllowSite"/> -+ <menuitem observes="blockedPopupEditSettings"/> -+ <menuitem observes="blockedPopupDontShowMessage"/> -+ <menuseparator observes="blockedPopupsSeparator"/> -+ </menupopup> -+ -+ <menupopup id="autohide-context" -+ onpopupshowing="FullScreen.getAutohide(this.firstChild);"> -+ <menuitem type="checkbox" label="&fullScreenAutohide.label;" -+ accesskey="&fullScreenAutohide.accesskey;" -+ oncommand="FullScreen.setAutohide();"/> -+ <menuseparator/> -+ <menuitem label="&fullScreenExit.label;" -+ accesskey="&fullScreenExit.accesskey;" -+ oncommand="BrowserFullScreen();"/> -+ </menupopup> -+ -+ <menupopup id="contentAreaContextMenu" pagemenu="#page-menu-separator" -+ onpopupshowing="if (event.target != this) -+ return true; -+ gContextMenu = new nsContextMenu(this, event.shiftKey); -+ if (gContextMenu.shouldDisplay) -+ updateEditUIVisibility(); -+ return gContextMenu.shouldDisplay;" -+ onpopuphiding="if (event.target != this) -+ return; -+ gContextMenu.hiding(); -+ gContextMenu = null; -+ updateEditUIVisibility();"> -+#include browser-context.inc -+ </menupopup> -+ -+ <menupopup id="placesContext"/> -+ -+ <panel id="ctrlTab-panel" class="KUI-panel" hidden="true" norestorefocus="true" level="top"> -+ <hbox> -+ <button class="ctrlTab-preview" flex="1"/> -+ <button class="ctrlTab-preview" flex="1"/> -+ <button class="ctrlTab-preview" flex="1"/> -+ <button class="ctrlTab-preview" flex="1"/> -+ <button class="ctrlTab-preview" flex="1"/> -+ <button class="ctrlTab-preview" flex="1"/> -+ </hbox> -+ <hbox pack="center"> -+ <button id="ctrlTab-showAll" class="ctrlTab-preview" noicon="true"/> -+ </hbox> -+ </panel> -+ -+ <!-- Sync Panel --> -+ <panel id="sync-start-panel" class="sync-panel" type="arrow" hidden="true" -+ noautofocus="true" onclick="this.hidePopup();" -+ flip="slide"> -+ <hbox class="sync-panel-outer"> -+ <image class="sync-panel-icon"/> -+ <vbox class="sync-panel-inner"> -+ <description id="sync-start-panel-title" -+ value="&syncStartPanel2.heading;"/> -+ <description id="sync-start-panel-subtitle" -+ value="&syncStartPanel2.subTitle;"/> -+ </vbox> -+ </hbox> -+ </panel> -+ -+ <!-- Bookmarks and history tooltip --> -+ <tooltip id="bhTooltip"/> -+ -+ <tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/> -+ -+ <tooltip id="back-button-tooltip"> -+ <label class="tooltip-label" value="&backButton.tooltip;"/> -+#ifdef XP_MACOSX -+ <label class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/> -+#else -+ <label class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/> -+#endif -+ </tooltip> -+ -+ <tooltip id="forward-button-tooltip"> -+ <label class="tooltip-label" value="&forwardButton.tooltip;"/> -+#ifdef XP_MACOSX -+ <label class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/> -+#else -+ <label class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/> -+#endif -+ </tooltip> -+ -+ <tooltip id="share-button-tooltip" onpopupshowing="SocialShare.createTooltip(event);"> -+ <label class="tooltip-label"/> -+ <label class="tooltip-label"/> -+ </tooltip> -+ -+#include popup-notifications.inc -+ -+#include ../../components/customizableui/content/panelUI.inc.xul -+#include ../../components/controlcenter/content/panel.inc.xul -+ -+ <hbox id="downloads-animation-container" mousethrough="always"> -+ <vbox id="downloads-notification-anchor"> -+ <vbox id="downloads-indicator-notification"/> -+ </vbox> -+ </hbox> -+ -+ <hbox id="bookmarked-notification-container" mousethrough="always"> -+ <vbox id="bookmarked-notification-anchor"> -+ <vbox id="bookmarked-notification"/> -+ </vbox> -+ <vbox id="bookmarked-notification-dropmarker-anchor"> -+ <image id="bookmarked-notification-dropmarker-icon"/> -+ </vbox> -+ </hbox> -+ -+ <tooltip id="dynamic-shortcut-tooltip" -+ onpopupshowing="UpdateDynamicShortcutTooltipText(this);"/> -+ -+ <menupopup id="emeNotificationsPopup"> -+ <menuitem id="emeNotificationsNotNow" -+ label="&emeNotificationsNotNow.label;" -+ acceskey="&emeNotificationsNotNow.accesskey;" -+ oncommand="gEMEHandler.onNotNow(this);"/> -+ <menuitem id="emeNotificationsDontAskAgain" -+ label="&emeNotificationsDontAskAgain.label;" -+ acceskey="&emeNotificationsDontAskAgain.accesskey;" -+ oncommand="gEMEHandler.onDontAskAgain(this);"/> -+ </menupopup> -+ </popupset> -+ -+#ifdef CAN_DRAW_IN_TITLEBAR -+<vbox id="titlebar"> -+ <hbox id="titlebar-content"> -+ <spacer id="titlebar-spacer" flex="1"/> -+ <hbox id="titlebar-buttonbox-container"> -+#ifdef XP_WIN -+ <hbox id="private-browsing-indicator-titlebar"> -+ <hbox class="private-browsing-indicator"/> -+ </hbox> -+#endif -+ <hbox id="titlebar-buttonbox"> -+ <toolbarbutton class="titlebar-button" id="titlebar-min" oncommand="window.minimize();"/> -+ <toolbarbutton class="titlebar-button" id="titlebar-max" oncommand="onTitlebarMaxClick();"/> -+ <toolbarbutton class="titlebar-button" id="titlebar-close" command="cmd_closeWindow"/> -+ </hbox> -+ </hbox> -+#ifdef XP_MACOSX -+ <!-- OS X does not natively support RTL for its titlebar items, so we prevent this secondary -+ buttonbox from reversing order in RTL by forcing an LTR direction. --> -+ <hbox id="titlebar-secondary-buttonbox" dir="ltr"> -+ <hbox class="private-browsing-indicator"/> -+ <hbox id="titlebar-fullscreen-button"/> -+ </hbox> -+#endif -+ </hbox> -+</vbox> -+#endif -+ -+<deck flex="1" id="tab-view-deck"> -+<vbox flex="1" id="browser-panel"> -+ -+ <toolbox id="navigator-toolbox" mode="icons"> -+ <!-- Menu --> -+ <toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true" -+ defaultset="menubar-items" -+ mode="icons" iconsize="small" -+#ifdef MENUBAR_CAN_AUTOHIDE -+ toolbarname="&menubarCmd.label;" -+ accesskey="&menubarCmd.accesskey;" -+#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT) -+ autohide="true" -+#endif -+#endif -+ context="toolbar-context-menu"> -+ <toolbaritem id="menubar-items" align="center"> -+# The entire main menubar is placed into browser-menubar.inc, so that it can be shared by -+# hiddenWindow.xul. -+#include browser-menubar.inc -+ </toolbaritem> -+ -+#ifdef CAN_DRAW_IN_TITLEBAR -+#ifndef XP_MACOSX -+ <hbox class="titlebar-placeholder" type="caption-buttons" ordinal="1000" -+ id="titlebar-placeholder-on-menubar-for-caption-buttons" persist="width" -+ skipintoolbarset="true"/> -+#endif -+#endif -+ </toolbar> -+ -+ <toolbar id="TabsToolbar" -+ fullscreentoolbar="true" -+ customizable="true" -+ mode="icons" -+ iconsize="small" -+ aria-label="&tabsToolbar.label;" -+ context="toolbar-context-menu" -+ defaultset="tabbrowser-tabs,new-tab-button,alltabs-button" -+ collapsed="true"> -+ -+#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT) -+ <hbox id="private-browsing-indicator" -+ skipintoolbarset="true"/> -+#endif -+ -+ <tabs id="tabbrowser-tabs" -+ class="tabbrowser-tabs" -+ tabbrowser="content" -+ flex="1" -+ setfocus="false" -+ tooltip="tabbrowser-tab-tooltip" -+ stopwatchid="FX_TAB_CLICK_MS"> -+ <tab class="tabbrowser-tab" selected="true" visuallyselected="true" fadein="true"/> -+ </tabs> -+ -+ <toolbarbutton id="new-tab-button" -+ class="toolbarbutton-1 chromeclass-toolbar-additional" -+ label="&tabCmd.label;" -+ command="cmd_newNavigatorTab" -+ onclick="checkForMiddleClick(this, event);" -+ tooltip="dynamic-shortcut-tooltip" -+ ondrop="newTabButtonObserver.onDrop(event)" -+ ondragover="newTabButtonObserver.onDragOver(event)" -+ ondragenter="newTabButtonObserver.onDragOver(event)" -+ ondragexit="newTabButtonObserver.onDragExit(event)" -+ cui-areatype="toolbar" -+ removable="true"/> -+ -+ <toolbarbutton id="alltabs-button" -+ class="toolbarbutton-1 chromeclass-toolbar-additional tabs-alltabs-button" -+ type="menu" -+ label="&listAllTabs.label;" -+ tooltiptext="&listAllTabs.label;" -+ removable="false"> -+ <menupopup id="alltabs-popup" -+ position="after_end"> -+ <menuitem id="menu_tabview" -+ class="menuitem-iconic" -+ key="key_tabview" -+ label="&viewTabGroups.label;" -+ command="Browser:ToggleTabView" -+ observes="tabviewGroupsNumber"/> -+ <menuitem id="alltabs_undoCloseTab" -+ class="menuitem-iconic" -+ key="key_undoCloseTab" -+ label="&undoCloseTab.label;" -+ observes="History:UndoCloseTab"/> -+ <menuseparator id="alltabs-popup-separator"/> -+ </menupopup> -+ </toolbarbutton> -+ -+#if !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_QT) -+ <hbox class="private-browsing-indicator" skipintoolbarset="true"/> -+#endif -+#ifdef CAN_DRAW_IN_TITLEBAR -+ <hbox class="titlebar-placeholder" type="caption-buttons" -+ id="titlebar-placeholder-on-TabsToolbar-for-captions-buttons" persist="width" -+#ifndef XP_MACOSX -+ ordinal="1000" -+#endif -+ skipintoolbarset="true"/> -+ -+#ifdef XP_MACOSX -+ <hbox class="titlebar-placeholder" type="fullscreen-button" -+ id="titlebar-placeholder-on-TabsToolbar-for-fullscreen-button" persist="width" -+ skipintoolbarset="true"/> -+#endif -+#endif -+ </toolbar> -+ -+ <!-- -+ CAVEAT EMPTOR -+ Should you need to add items to the toolbar here, make sure to also add them -+ to the default placements of buttons in CustomizableUI.jsm, so the -+ customization code doesn't get confused. -+ --> -+ <toolbar id="nav-bar" -+ aria-label="&navbarCmd.label;" -+ fullscreentoolbar="true" mode="icons" customizable="true" -+ iconsize="small" -+#ifdef MOZ_DEV_EDITION -+ defaultset="urlbar-container,search-container,developer-button,bookmarks-menu-button,pocket-button,downloads-button,home-button,loop-button" -+#else -+ defaultset="urlbar-container,search-container,bookmarks-menu-button,pocket-button,downloads-button,home-button,loop-button" -+#endif -+ customizationtarget="nav-bar-customization-target" -+ overflowable="true" -+ overflowbutton="nav-bar-overflow-button" -+ overflowtarget="widget-overflow-list" -+ overflowpanel="widget-overflow" -+ context="toolbar-context-menu"> -+ -+ <hbox id="nav-bar-customization-target" flex="1"> -+ <toolbaritem id="urlbar-container" flex="400" persist="width" -+ removable="false" -+ class="chromeclass-location" overflows="false"> -+ <toolbarbutton id="back-button" class="toolbarbutton-1 chromeclass-toolbar-additional" -+ label="&backCmd.label;" -+ command="Browser:BackOrBackDuplicate" -+ onclick="checkForMiddleClick(this, event);" -+ tooltip="back-button-tooltip" -+ context="backForwardMenu"/> -+ <hbox id="urlbar-wrapper" flex="1"> -+ <toolbarbutton id="forward-button" class="toolbarbutton-1 chromeclass-toolbar-additional" -+ label="&forwardCmd.label;" -+ command="Browser:ForwardOrForwardDuplicate" -+ onclick="checkForMiddleClick(this, event);" -+ tooltip="forward-button-tooltip" -+ context="backForwardMenu"/> -+ <textbox id="urlbar" flex="1" -+ placeholder="&urlbar.placeholder2;" -+ type="autocomplete" -+ autocompletesearch="urlinline history" -+ autocompletesearchparam="enable-actions" -+ autocompletepopup="PopupAutoCompleteRichResult" -+ completeselectedindex="true" -+ shrinkdelay="250" -+ tabscrolling="true" -+ showcommentcolumn="true" -+ showimagecolumn="true" -+ enablehistory="true" -+ maxrows="6" -+ newlines="stripsurroundingwhitespace" -+ ontextentered="this.handleCommand(param);" -+ ontextreverted="return this.handleRevert();" -+ pageproxystate="invalid" -+ onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'" -+ onblur="setTimeout(() => { document.getElementById('identity-box').style.MozUserFocus = ''; }, 0);"> -+ <box id="notification-popup-box" hidden="true" align="center"> -+ <image id="default-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.defaultNotificationAnchor.label;"/> -+ <!-- NB: the identity-notification-icon is used for persona-based auth and preffed -+ off by default. It hasn't been updated for some time and liable to being -+ removed.--> -+ <image id="identity-notification-icon" class="notification-anchor-icon" role="button"/> -+ <image id="geo-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.geolocationNotificationAnchor.label;"/> -+ <image id="addons-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.addonsNotificationAnchor.label;"/> -+ <image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.indexedDBNotificationAnchor.label;"/> -+ <image id="login-fill-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.loginFillNotificationAnchor.label;"/> -+ <image id="password-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.passwordNotificationAnchor.label;"/> -+ <image id="webapps-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.webappsNotificationAnchor.label;"/> -+ <image id="plugins-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.pluginsNotificationAnchor.label;"/> -+ <image id="web-notifications-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.webNotsNotificationAnchor.label;"/> -+ <image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.webRTCShareDevicesNotificationAnchor.label;"/> -+ <image id="webRTC-sharingDevices-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.webRTCSharingDevicesNotificationAnchor.label;"/> -+ <image id="webRTC-shareMicrophone-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.webRTCShareMicrophoneNotificationAnchor.label;"/> -+ <image id="webRTC-sharingMicrophone-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.webRTCSharingMicrophoneNotificationAnchor.label;"/> -+ <image id="webRTC-shareScreen-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.webRTCShareScreenNotificationAnchor.label;"/> -+ <image id="webRTC-sharingScreen-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.webRTCSharingScreenNotificationAnchor.label;"/> -+ <image id="pointerLock-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.pointerLockNotificationAnchor.label;"/> -+ <image id="servicesInstall-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.servicesNotificationAnchor.label;"/> -+ <image id="translate-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.translateNotificationAnchor.label;"/> -+ <image id="translated-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.translatedNotificationAnchor.label;"/> -+ <image id="eme-notification-icon" class="notification-anchor-icon" role="button" -+ aria-label="&urlbar.emeNotificationAnchor.label;"/> -+ </box> -+ <!-- Use onclick instead of normal popup= syntax since the popup -+ code fires onmousedown, and hence eats our favicon drag events. -+ We only add the identity-box button to the tab order when the location bar -+ has focus, otherwise pressing F6 focuses it instead of the location bar --> -+ <box id="identity-box" role="button" -+ align="center" -+ aria-label="&urlbar.viewSiteInfo.label;" -+ onclick="gIdentityHandler.handleIdentityButtonEvent(event);" -+ onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);" -+ ondragstart="gIdentityHandler.onDragStart(event);"> -+ <hbox id="identity-icons" -+ consumeanchor="identity-box"> -+ <image id="tracking-protection-icon"/> -+ <image id="page-proxy-favicon" -+ onclick="PageProxyClickHandler(event);" -+ pageproxystate="invalid"/> -+ </hbox> -+ <hbox id="identity-icon-labels"> -+ <label id="identity-icon-label" class="plain" flex="1"/> -+ <label id="identity-icon-country-label" class="plain"/> -+ </hbox> -+ </box> -+ <box id="urlbar-display-box" align="center"> -+ <label class="urlbar-display urlbar-display-switchtab" value="&urlbar.switchToTab.label;"/> -+ </box> -+ <hbox id="urlbar-icons"> -+ <image id="page-report-button" -+ class="urlbar-icon" -+ hidden="true" -+ tooltiptext="&pageReportIcon.tooltip;" -+ onclick="gPopupBlockerObserver.onReportButtonClick(event);"/> -+ <image id="reader-mode-button" -+ class="urlbar-icon" -+ hidden="true" -+ onclick="ReaderParent.buttonClick(event);"/> -+ </hbox> -+ <hbox id="userContext-icons"> -+ <label id="userContext-label"/> -+ <image id="userContext-indicator"/> -+ </hbox> -+ <toolbarbutton id="urlbar-go-button" -+ class="chromeclass-toolbar-additional" -+ onclick="gURLBar.handleCommand(event);" -+ tooltiptext="&goEndCap.tooltip;"/> -+ <toolbarbutton id="urlbar-reload-button" -+ class="chromeclass-toolbar-additional" -+ command="Browser:ReloadOrDuplicate" -+ onclick="checkForMiddleClick(this, event);" -+ tooltiptext="&reloadButton.tooltip;"/> -+ <toolbarbutton id="urlbar-stop-button" -+ class="chromeclass-toolbar-additional" -+ command="Browser:Stop" -+ tooltiptext="&stopButton.tooltip;"/> -+ </textbox> -+ </hbox> -+ </toolbaritem> -+ -+ <toolbaritem id="search-container" title="&searchItem.title;" -+ align="center" class="chromeclass-toolbar-additional panel-wide-item" -+ cui-areatype="toolbar" -+ flex="100" persist="width" removable="true"> -+ <searchbar id="searchbar" flex="1"/> -+ </toolbaritem> -+ -+ <toolbarbutton id="bookmarks-menu-button" -+ class="toolbarbutton-1 chromeclass-toolbar-additional" -+ removable="true" -+ type="menu-button" -+ label="&bookmarksMenuButton.label;" -+ tooltip="dynamic-shortcut-tooltip" -+ anchor="dropmarker" -+ ondragenter="PlacesMenuDNDHandler.onDragEnter(event);" -+ ondragover="PlacesMenuDNDHandler.onDragOver(event);" -+ ondragleave="PlacesMenuDNDHandler.onDragLeave(event);" -+ ondrop="PlacesMenuDNDHandler.onDrop(event);" -+ cui-areatype="toolbar" -+ oncommand="BookmarkingUI.onCommand(event);"> -+ <observes element="bookmarkThisPageBroadcaster" attribute="starred"/> -+ <observes element="bookmarkThisPageBroadcaster" attribute="buttontooltiptext"/> -+ <menupopup id="BMB_bookmarksPopup" -+ class="cui-widget-panel cui-widget-panelview cui-widget-panelWithFooter PanelUI-subView" -+ placespopup="true" -+ context="placesContext" -+ openInTabs="children" -+ oncommand="BookmarksEventHandler.onCommand(event, this.parentNode._placesView);" -+ onclick="BookmarksEventHandler.onClick(event, this.parentNode._placesView);" -+ onpopupshowing="BookmarkingUI.onPopupShowing(event); -+ BookmarkingUI.updatePocketItemVisibility('BMB_'); -+ BookmarkingUI.attachPlacesView(event, this);" -+ tooltip="bhTooltip" popupsinherittooltip="true"> -+ <menuitem id="BMB_viewBookmarksSidebar" -+ class="subviewbutton" -+ label="&viewBookmarksSidebar2.label;" -+ type="checkbox" -+ oncommand="SidebarUI.toggle('viewBookmarksSidebar');"> -+ <observes element="viewBookmarksSidebar" attribute="checked"/> -+ </menuitem> -+ <!-- NB: temporary solution for bug 985024, this should go away soon. --> -+ <menuitem id="BMB_bookmarksShowAllTop" -+ class="menuitem-iconic subviewbutton" -+ label="&showAllBookmarks2.label;" -+ command="Browser:ShowAllBookmarks" -+ key="manBookmarkKb"/> -+ <menuseparator/> -+ <menuitem id="BMB_pocket" -+ class="menuitem-iconic bookmark-item subviewbutton" -+ label="&pocketMenuitem.label;" -+ oncommand="openUILink(Pocket.listURL, event);"/> -+ <menuseparator id="BMB_pocketSeparator"/> -+ <menuitem id="BMB_subscribeToPageMenuitem" -+#ifndef XP_MACOSX -+ class="menuitem-iconic subviewbutton" -+#else -+ class="subviewbutton" -+#endif -+ label="&subscribeToPageMenuitem.label;" -+ oncommand="return FeedHandler.subscribeToFeed(null, event);" -+ onclick="checkForMiddleClick(this, event);" -+ observes="singleFeedMenuitemState"/> -+ <menu id="BMB_subscribeToPageMenupopup" -+#ifndef XP_MACOSX -+ class="menu-iconic subviewbutton" -+#else -+ class="subviewbutton" -+#endif -+ label="&subscribeToPageMenupopup.label;" -+ observes="multipleFeedsMenuState"> -+ <menupopup id="BMB_subscribeToPageSubmenuMenupopup" -+ onpopupshowing="return FeedHandler.buildFeedList(event.target);" -+ oncommand="return FeedHandler.subscribeToFeed(null, event);" -+ onclick="checkForMiddleClick(this, event);"/> -+ </menu> -+ <menuseparator/> -+ <menu id="BMB_bookmarksToolbar" -+ class="menu-iconic bookmark-item subviewbutton" -+ label="&personalbarCmd.label;" -+ container="true"> -+ <menupopup id="BMB_bookmarksToolbarPopup" -+ placespopup="true" -+ context="placesContext" -+ onpopupshowing="if (!this.parentNode._placesView) -+ new PlacesMenu(event, 'place:folder=TOOLBAR', -+ PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);"> -+ <menuitem id="BMB_viewBookmarksToolbar" -+ placesanonid="view-toolbar" -+ toolbarId="PersonalToolbar" -+ type="checkbox" -+ oncommand="onViewToolbarCommand(event)" -+ label="&viewBookmarksToolbar.label;"/> -+ <menuseparator/> -+ <!-- Bookmarks toolbar items --> -+ </menupopup> -+ </menu> -+ <menu id="BMB_unsortedBookmarks" -+ class="menu-iconic bookmark-item subviewbutton" -+ label="&bookmarksMenuButton.unsorted.label;" -+ container="true"> -+ <menupopup id="BMB_unsortedBookmarksPopup" -+ placespopup="true" -+ context="placesContext" -+ onpopupshowing="if (!this.parentNode._placesView) -+ new PlacesMenu(event, 'place:folder=UNFILED_BOOKMARKS', -+ PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);"/> -+ </menu> -+ <menuseparator/> -+ <!-- Bookmarks menu items will go here --> -+ <menuitem id="BMB_bookmarksShowAll" -+ class="subviewbutton panel-subview-footer" -+ label="&showAllBookmarks2.label;" -+ command="Browser:ShowAllBookmarks" -+ key="manBookmarkKb"/> -+ </menupopup> -+ </toolbarbutton> -+ -+ <!-- This is a placeholder for the Downloads Indicator. It is visible -+ during the customization of the toolbar, in the palette, and before -+ the Downloads Indicator overlay is loaded. --> -+ <toolbarbutton id="downloads-button" class="toolbarbutton-1 chromeclass-toolbar-additional" -+ key="key_openDownloads" -+ oncommand="DownloadsIndicatorView.onCommand(event);" -+ ondrop="DownloadsIndicatorView.onDrop(event);" -+ ondragover="DownloadsIndicatorView.onDragOver(event);" -+ ondragenter="DownloadsIndicatorView.onDragOver(event);" -+ label="&downloads.label;" -+ removable="true" -+ cui-areatype="toolbar" -+ tooltip="dynamic-shortcut-tooltip"/> -+ -+ <toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional" -+ removable="true" -+ label="&homeButton.label;" -+ ondragover="homeButtonObserver.onDragOver(event)" -+ ondragenter="homeButtonObserver.onDragOver(event)" -+ ondrop="homeButtonObserver.onDrop(event)" -+ ondragexit="homeButtonObserver.onDragExit(event)" -+ key="goHome" -+ onclick="BrowserGoHome(event);" -+ cui-areatype="toolbar" -+ aboutHomeOverrideTooltip="&abouthome.pageTitle;"/> -+ </hbox> -+ -+ <toolbarbutton id="nav-bar-overflow-button" -+ class="toolbarbutton-1 chromeclass-toolbar-additional overflow-button" -+ skipintoolbarset="true" -+ tooltiptext="&navbarOverflow.label;"/> -+ -+ <toolbaritem id="PanelUI-button" -+ class="chromeclass-toolbar-additional" -+ removable="false"> -+ <toolbarbutton id="PanelUI-menu-button" -+ class="toolbarbutton-1 badged-button" -+ consumeanchor="PanelUI-button" -+ label="&brandShortName;" -+ tooltiptext="&appmenu.tooltip;"/> -+ </toolbaritem> -+ -+ <hbox id="window-controls" hidden="true" pack="end" skipintoolbarset="true" -+ ordinal="1000"> -+ <toolbarbutton id="minimize-button" -+ tooltiptext="&fullScreenMinimize.tooltip;" -+ oncommand="window.minimize();"/> -+ -+ <toolbarbutton id="restore-button" -+#ifdef XP_MACOSX -+# Prior to 10.7 there wasn't a native fullscreen button so we use #restore-button -+# to exit fullscreen and want it to behave like other toolbar buttons. -+ class="toolbarbutton-1" -+#endif -+ tooltiptext="&fullScreenRestore.tooltip;" -+ oncommand="BrowserFullScreen();"/> -+ -+ <toolbarbutton id="close-button" -+ tooltiptext="&fullScreenClose.tooltip;" -+ oncommand="BrowserTryToCloseWindow();"/> -+ </hbox> -+ </toolbar> -+ -+ <toolbarset id="customToolbars" context="toolbar-context-menu"/> -+ -+ <toolbar id="PersonalToolbar" -+ mode="icons" iconsize="small" -+ class="chromeclass-directories" -+ context="toolbar-context-menu" -+ defaultset="personal-bookmarks" -+ toolbarname="&personalbarCmd.label;" accesskey="&personalbarCmd.accesskey;" -+ collapsed="true" -+ customizable="true"> -+ <toolbaritem id="personal-bookmarks" -+ title="&bookmarksToolbarItem.label;" -+ cui-areatype="toolbar" -+ removable="true"> -+ <toolbarbutton id="bookmarks-toolbar-placeholder" -+ class="toolbarbutton-1" -+ mousethrough="never" -+ label="&bookmarksToolbarItem.label;" -+ oncommand="PlacesToolbarHelper.onPlaceholderCommand();"/> -+ <hbox flex="1" -+ id="PlacesToolbar" -+ context="placesContext" -+ onclick="BookmarksEventHandler.onClick(event, this._placesView);" -+ oncommand="BookmarksEventHandler.onCommand(event, this._placesView);" -+ tooltip="bhTooltip" -+ popupsinherittooltip="true"> -+ <hbox flex="1"> -+ <hbox id="PlacesToolbarDropIndicatorHolder" align="center" collapsed="true"> -+ <image id="PlacesToolbarDropIndicator" -+ mousethrough="always" -+ collapsed="true"/> -+ </hbox> -+ <scrollbox orient="horizontal" -+ id="PlacesToolbarItems" -+ flex="1"/> -+ <toolbarbutton type="menu" -+ id="PlacesChevron" -+ class="chevron" -+ mousethrough="never" -+ collapsed="true" -+ tooltiptext="&bookmarksToolbarChevron.tooltip;" -+ onpopupshowing="document.getElementById('PlacesToolbar') -+ ._placesView._onChevronPopupShowing(event);"> -+ <menupopup id="PlacesChevronPopup" -+ placespopup="true" -+ tooltip="bhTooltip" popupsinherittooltip="true" -+ context="placesContext"/> -+ </toolbarbutton> -+ </hbox> -+ </hbox> -+ </toolbaritem> -+ </toolbar> -+ -+ <!-- This is a shim which will go away ASAP. See bug 749804 for details --> -+ <toolbar id="addon-bar" toolbar-delegate="nav-bar" mode="icons" iconsize="small" -+ customizable="true"> -+ <hbox id="addonbar-closebutton"/> -+ <statusbar id="status-bar"/> -+ </toolbar> -+ -+ <toolbarpalette id="BrowserToolbarPalette"> -+ -+# Update primaryToolbarButtons in browser/themes/shared/browser.inc when adding -+# or removing default items with the toolbarbutton-1 class. -+ -+ <toolbarbutton id="print-button" class="toolbarbutton-1 chromeclass-toolbar-additional" -+#ifdef XP_MACOSX -+ command="cmd_print" -+ tooltip="dynamic-shortcut-tooltip" -+#else -+ command="cmd_printPreview" -+ tooltiptext="&printButton.tooltip;" -+#endif -+ label="&printButton.label;"/> -+ -+ -+ <toolbarbutton id="new-window-button" class="toolbarbutton-1 chromeclass-toolbar-additional" -+ label="&newNavigatorCmd.label;" -+ command="key_newNavigator" -+ tooltip="dynamic-shortcut-tooltip" -+ ondrop="newWindowButtonObserver.onDrop(event)" -+ ondragover="newWindowButtonObserver.onDragOver(event)" -+ ondragenter="newWindowButtonObserver.onDragOver(event)" -+ ondragexit="newWindowButtonObserver.onDragExit(event)"/> -+ -+ <toolbarbutton id="fullscreen-button" class="toolbarbutton-1 chromeclass-toolbar-additional" -+ observes="View:FullScreen" -+ type="checkbox" -+ label="&fullScreenCmd.label;" -+ tooltip="dynamic-shortcut-tooltip"/> -+ -+#ifdef MOZ_SERVICES_SYNC -+ <toolbarbutton id="sync-button" -+ class="toolbarbutton-1 chromeclass-toolbar-additional" -+ label="&syncToolbarButton.label;" -+ oncommand="gSyncUI.handleToolbarButton()"/> -+#endif -+ -+ <toolbarbutton id="tabview-button" class="toolbarbutton-1 chromeclass-toolbar-additional" -+ label="&tabGroupsButton.label;" -+ command="Browser:ToggleTabView" -+ tooltip="dynamic-shortcut-tooltip" -+ observes="tabviewGroupsNumber"/> -+ </toolbarpalette> -+ </toolbox> -+ -+ <hbox id="fullscr-toggler" hidden="true"/> -+ -+ <deck id="content-deck" flex="1"> -+ <hbox flex="1" id="browser"> -+ <vbox id="browser-border-start" hidden="true" layer="true"/> -+ <vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome"> -+ <sidebarheader id="sidebar-header" align="center"> -+ <label id="sidebar-title" persist="value" flex="1" crop="end" control="sidebar"/> -+ <image id="sidebar-throbber"/> -+ <toolbarbutton class="close-icon tabbable" tooltiptext="&sidebarCloseButton.tooltip;" oncommand="SidebarUI.hide();"/> -+ </sidebarheader> -+ <browser id="sidebar" flex="1" autoscroll="false" disablehistory="true" -+ style="min-width: 14em; width: 18em; max-width: 36em;" tooltip="aHTMLTooltip"/> -+ </vbox> -+ -+ <splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" hidden="true"/> -+ <vbox id="appcontent" flex="1"> -+ <notificationbox id="high-priority-global-notificationbox" notificationside="top"/> -+ <tabbrowser id="content" -+ flex="1" contenttooltip="aHTMLTooltip" -+ tabcontainer="tabbrowser-tabs" -+ contentcontextmenu="contentAreaContextMenu" -+ autocompletepopup="PopupAutoComplete" -+ selectmenulist="ContentSelectDropdown"/> -+ <chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/> -+ </vbox> -+ <splitter id="social-sidebar-splitter" -+ class="chromeclass-extrachrome sidebar-splitter" -+ observes="socialSidebarBroadcaster"/> -+ <vbox id="social-sidebar-box" -+ class="chromeclass-extrachrome" -+ observes="socialSidebarBroadcaster" -+ persist="width"> -+ -+ <sidebarheader id="social-sidebar-header" class="sidebar-header" align="center"> -+ <image id="social-sidebar-favico"/> -+ <label id="social-sidebar-title" class="sidebar-title" persist="value" flex="1" crop="end" control="sidebar"/> -+ <toolbarbutton id="social-sidebar-button" -+ class="toolbarbutton-1" -+ type="menu"> -+ <menupopup id="social-statusarea-popup" position="after_end"> -+ <menuitem class="social-toggle-sidebar-menuitem" -+ type="checkbox" -+ autocheck="false" -+ command="Social:ToggleSidebar" -+ label="&social.toggleSidebar.label;" -+ accesskey="&social.toggleSidebar.accesskey;"/> -+ <menuitem class="social-toggle-notifications-menuitem" -+ type="checkbox" -+ autocheck="false" -+ command="Social:ToggleNotifications" -+ label="&social.toggleNotifications.label;" -+ accesskey="&social.toggleNotifications.accesskey;"/> -+ <menuseparator/> -+ <menuseparator class="social-provider-menu" hidden="true"/> -+ <menuitem class="social-addons-menuitem" command="Social:Addons" -+ label="&social.addons.label;"/> -+ <menuitem label="&social.learnMore.label;" -+ accesskey="&social.learnMore.accesskey;" -+ oncommand="SocialUI.showLearnMore();"/> -+ </menupopup> -+ </toolbarbutton> -+ </sidebarheader> -+ -+ <browser id="social-sidebar-browser" -+ type="content" -+ context="contentAreaContextMenu" -+ message="true" -+ messagemanagergroup="social" -+ disableglobalhistory="true" -+ tooltip="aHTMLTooltip" -+ popupnotificationanchor="social-sidebar-favico" -+ flex="1" -+ style="min-width: 14em; width: 18em; max-width: 36em;"/> -+ </vbox> -+ <vbox id="browser-border-end" hidden="true" layer="true"/> -+ </hbox> -+#include ../../components/customizableui/content/customizeMode.inc.xul -+ </deck> -+ -+ <html:div id="fullscreen-warning" hidden="true"> -+ <html:div id="fullscreen-domain-text"> -+ &fullscreenWarning.beforeDomain.label; -+ <html:span id="fullscreen-domain"/> -+ &fullscreenWarning.afterDomain.label; -+ </html:div> -+ <html:div id="fullscreen-generic-text"> -+ &fullscreenWarning.generic.label; -+ </html:div> -+ <html:button id="fullscreen-exit-button" -+ onclick="FullScreen.exitDomFullScreen();"> -+#ifdef XP_MACOSX -+ &exitDOMFullscreenMac.button; -+#else -+ &exitDOMFullscreen.button; -+#endif -+ </html:button> -+ </html:div> -+ -+ <vbox id="browser-bottombox" layer="true"> -+ <notificationbox id="global-notificationbox" notificationside="bottom"/> -+ <toolbar id="developer-toolbar" -+ hidden="true"> -+#ifdef XP_MACOSX -+ <toolbarbutton id="developer-toolbar-closebutton" -+ class="devtools-closebutton" -+ oncommand="DeveloperToolbar.hide();" -+ tooltiptext="&devToolbarCloseButton.tooltiptext;"/> -+#endif -+ <stack class="gclitoolbar-stack-node" flex="1"> -+ <textbox class="gclitoolbar-input-node" rows="1"/> -+ <hbox class="gclitoolbar-complete-node"/> -+ </stack> -+ <toolbarbutton id="developer-toolbar-toolbox-button" -+ class="developer-toolbar-button" -+ observes="devtoolsMenuBroadcaster_DevToolbox" -+ tooltiptext="&devToolbarToolsButton.tooltip;"/> -+#ifndef XP_MACOSX -+ <toolbarbutton id="developer-toolbar-closebutton" -+ class="devtools-closebutton" -+ oncommand="DeveloperToolbar.hide();" -+ tooltiptext="&devToolbarCloseButton.tooltiptext;"/> -+#endif -+ </toolbar> -+ </vbox> -+ -+ <svg:svg height="0"> -+#include tab-shape.inc.svg -+ <svg:clipPath id="urlbar-back-button-clip-path"> -+#ifndef XP_MACOSX -+ <svg:path d="M -9,-4 l 0,1 a 15 15 0 0,1 0,30 l 0,1 l 10000,0 l 0,-32 l -10000,0 z" /> -+#else -+ <svg:path d="M -11,-5 a 16 16 0 0 1 0,34 l 10000,0 l 0,-34 l -10000,0 z"/> -+#endif -+ </svg:clipPath> -+#ifdef XP_WIN -+ <svg:clipPath id="urlbar-back-button-clip-path-win10"> -+ <svg:path d="M -6,-2 l 0,1 a 15 15 0 0,1 0,30 l 0,1 l 10000,0 l 0,-32 l -10000,0 z" /> -+ </svg:clipPath> -+#endif -+ </svg:svg> -+ -+</vbox> -+# <iframe id="tab-view"> is dynamically appended as the 2nd child of #tab-view-deck. -+# Introducing the iframe dynamically, as needed, was found to be better than -+# starting with an empty iframe here in browser.xul from a Ts standpoint. -+</deck> -+ -+</window> -diff --git a/browser/base/jar.mn b/browser/base/jar.mn ---- a/browser/base/jar.mn -+++ b/browser/base/jar.mn -@@ -70,16 +70,18 @@ browser.jar: - content/browser/aboutSocialError.xhtml (content/aboutSocialError.xhtml) - content/browser/aboutProviderDirectory.xhtml (content/aboutProviderDirectory.xhtml) - content/browser/aboutTabCrashed.css (content/aboutTabCrashed.css) - content/browser/aboutTabCrashed.js (content/aboutTabCrashed.js) - content/browser/aboutTabCrashed.xhtml (content/aboutTabCrashed.xhtml) - * content/browser/browser.css (content/browser.css) - * content/browser/browser.js (content/browser.js) - * content/browser/browser.xul (content/browser.xul) -+* content/browser/browser-kde.xul (content/browser-kde.xul) -+% override chrome://browser/content/browser.xul chrome://browser/content/browser-kde.xul desktop=kde - * content/browser/browser-tabPreviews.xml (content/browser-tabPreviews.xml) - * content/browser/chatWindow.xul (content/chatWindow.xul) - content/browser/tab-content.js (content/tab-content.js) - content/browser/content.js (content/content.js) - content/browser/social-content.js (content/social-content.js) - content/browser/defaultthemes/1.footer.jpg (content/defaultthemes/1.footer.jpg) - content/browser/defaultthemes/1.header.jpg (content/defaultthemes/1.header.jpg) - content/browser/defaultthemes/1.icon.jpg (content/defaultthemes/1.icon.jpg) -diff --git a/browser/components/build/nsModule.cpp b/browser/components/build/nsModule.cpp ---- a/browser/components/build/nsModule.cpp -+++ b/browser/components/build/nsModule.cpp -@@ -8,17 +8,17 @@ - #include "nsBrowserCompsCID.h" - #include "DirectoryProvider.h" - - #if defined(XP_WIN) - #include "nsWindowsShellService.h" - #elif defined(XP_MACOSX) - #include "nsMacShellService.h" - #elif defined(MOZ_WIDGET_GTK) --#include "nsGNOMEShellService.h" -+#include "nsUnixShellService.h" - #endif - - #if defined(XP_WIN) - #include "nsIEHistoryEnumerator.h" - #include "nsEdgeReadingListExtractor.h" - #endif - - #include "rdf.h" -@@ -32,18 +32,16 @@ using namespace mozilla::browser; - - ///////////////////////////////////////////////////////////////////////////// - - NS_GENERIC_FACTORY_CONSTRUCTOR(DirectoryProvider) - #if defined(XP_WIN) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindowsShellService) - #elif defined(XP_MACOSX) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShellService) --#elif defined(MOZ_WIDGET_GTK) --NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init) - #endif - - #if defined(XP_WIN) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEHistoryEnumerator) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsEdgeReadingListExtractor) - #endif - - NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer) -@@ -63,17 +61,17 @@ NS_DEFINE_NAMED_CID(NS_EDGEREADINGLISTEX - NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID); - #endif - - static const mozilla::Module::CIDEntry kBrowserCIDs[] = { - { &kNS_BROWSERDIRECTORYPROVIDER_CID, false, nullptr, DirectoryProviderConstructor }, - #if defined(XP_WIN) - { &kNS_SHELLSERVICE_CID, false, nullptr, nsWindowsShellServiceConstructor }, - #elif defined(MOZ_WIDGET_GTK) -- { &kNS_SHELLSERVICE_CID, false, nullptr, nsGNOMEShellServiceConstructor }, -+ { &kNS_SHELLSERVICE_CID, false, nullptr, nsUnixShellServiceConstructor }, - #endif - { &kNS_FEEDSNIFFER_CID, false, nullptr, nsFeedSnifferConstructor }, - { &kNS_BROWSER_ABOUT_REDIRECTOR_CID, false, nullptr, AboutRedirector::Create }, - #if defined(XP_WIN) - { &kNS_WINIEHISTORYENUMERATOR_CID, false, nullptr, nsIEHistoryEnumeratorConstructor }, - { &kNS_EDGEREADINGLISTEXTRACTOR_CID, false, nullptr, nsEdgeReadingListExtractorConstructor }, - #elif defined(XP_MACOSX) - { &kNS_SHELLSERVICE_CID, false, nullptr, nsMacShellServiceConstructor }, -diff --git a/browser/components/preferences/in-content/main.js b/browser/components/preferences/in-content/main.js ---- a/browser/components/preferences/in-content/main.js -+++ b/browser/components/preferences/in-content/main.js -@@ -14,16 +14,22 @@ var gMainPane = { - init: function () - { - function setEventListener(aId, aEventType, aCallback) - { - document.getElementById(aId) - .addEventListener(aEventType, aCallback.bind(gMainPane)); - } - -+ var env = Components.classes["@mozilla.org/process/environment;1"] -+ .getService(Components.interfaces.nsIEnvironment); -+ var kde_session = 0; -+ if (env.get('KDE_FULL_SESSION') == "true") -+ kde_session = 1; -+ - #ifdef HAVE_SHELL_SERVICE - this.updateSetDefaultBrowser(); - #ifdef XP_WIN - // In Windows 8 we launch the control panel since it's the only - // way to get all file type association prefs. So we don't know - // when the user will select the default. We refresh here periodically - // in case the default changes. On other Windows OS's defaults can also - // be set while the prefs are open. -@@ -711,16 +717,27 @@ var gMainPane = { - */ - setDefaultBrowser: function() - { - let shellSvc = getShellService(); - if (!shellSvc) - return; - try { - shellSvc.setDefaultBrowser(true, false); -+ if (kde_session == 1) { -+ var shellObj = Components.classes["@mozilla.org/file/local;1"] -+ .createInstance(Components.interfaces.nsILocalFile); -+ shellObj.initWithPath("/usr/bin/kwriteconfig"); -+ var process = Components.classes["@mozilla.org/process/util;1"] -+ .createInstance(Components.interfaces.nsIProcess); -+ process.init(shellObj); -+ var args = ["--file", "kdeglobals", "--group", "General", "--key", -+ "BrowserApplication", "firefox"]; -+ process.run(false, args, args.length); -+ } - } catch (ex) { - Cu.reportError(ex); - return; - } - let selectedIndex = - shellSvc.isDefaultBrowser(false, true) ? 1 : 0; - document.getElementById("setDefaultPane").selectedIndex = selectedIndex; - } -diff --git a/browser/components/shell/moz.build b/browser/components/shell/moz.build ---- a/browser/components/shell/moz.build -+++ b/browser/components/shell/moz.build -@@ -30,16 +30,18 @@ if CONFIG['OS_ARCH'] == 'WINNT': - ] - elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': - SOURCES += [ - 'nsMacShellService.cpp', - ] - elif CONFIG['MOZ_WIDGET_GTK']: - SOURCES += [ - 'nsGNOMEShellService.cpp', -+ 'nsKDEShellService.cpp', -+ 'nsUnixShellService.cpp', - ] - - if SOURCES: - FINAL_LIBRARY = 'browsercomps' - - EXTRA_COMPONENTS += [ - 'nsSetDefaultBrowser.js', - 'nsSetDefaultBrowser.manifest', -diff --git a/browser/components/shell/nsKDEShellService.cpp b/browser/components/shell/nsKDEShellService.cpp -new file mode 100644 ---- /dev/null -+++ b/browser/components/shell/nsKDEShellService.cpp -@@ -0,0 +1,292 @@ -+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#include "mozilla/ArrayUtils.h" -+ -+#include "nsCOMPtr.h" -+#include "nsKDEShellService.h" -+#include "nsShellService.h" -+#include "nsKDEUtils.h" -+#include "nsIPrefService.h" -+#include "nsIProcess.h" -+#include "nsIFile.h" -+#include "nsServiceManagerUtils.h" -+#include "nsComponentManagerUtils.h" -+#include "nsIMutableArray.h" -+#include "nsISupportsPrimitives.h" -+#include "nsArrayUtils.h" -+ -+using namespace mozilla; -+ -+nsresult -+nsKDEShellService::Init() -+{ -+ if( !nsKDEUtils::kdeSupport()) -+ return NS_ERROR_NOT_AVAILABLE; -+ return NS_OK; -+} -+ -+NS_IMPL_ISUPPORTS(nsKDEShellService, nsIShellService) -+ -+NS_IMETHODIMP -+nsKDEShellService::IsDefaultBrowser(bool aStartupCheck, -+ bool aForAllTypes, -+ bool* aIsDefaultBrowser) -+{ -+ *aIsDefaultBrowser = false; -+ if (aStartupCheck) -+ mCheckedThisSession = true; -+ -+ nsCOMPtr<nsIMutableArray> command = do_CreateInstance( NS_ARRAY_CONTRACTID ); -+ if (!command) -+ return NS_ERROR_FAILURE; -+ -+ nsCOMPtr<nsISupportsCString> str = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); -+ if (!str) -+ return NS_ERROR_FAILURE; -+ -+ str->SetData( NS_LITERAL_CSTRING( "ISDEFAULTBROWSER" )); -+ command->AppendElement( str, false ); -+ -+ if( nsKDEUtils::command( command )) -+ *aIsDefaultBrowser = true; -+ return NS_OK; -+} -+ -+NS_IMETHODIMP -+nsKDEShellService::SetDefaultBrowser(bool aClaimAllTypes, -+ bool aForAllUsers) -+{ -+ nsCOMPtr<nsIMutableArray> command = do_CreateInstance( NS_ARRAY_CONTRACTID ); -+ if (!command) -+ return NS_ERROR_FAILURE; -+ -+ nsCOMPtr<nsISupportsCString> cmdstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); -+ nsCOMPtr<nsISupportsCString> paramstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); -+ if (!cmdstr || !paramstr) -+ return NS_ERROR_FAILURE; -+ -+ cmdstr->SetData( NS_LITERAL_CSTRING( "SETDEFAULTBROWSER" )); -+ command->AppendElement( cmdstr, false ); -+ -+ paramstr->SetData( aClaimAllTypes ? NS_LITERAL_CSTRING( "ALLTYPES" ) : NS_LITERAL_CSTRING( "NORMAL" )); -+ command->AppendElement( paramstr, false ); -+ -+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; -+} -+ -+NS_IMETHODIMP -+nsKDEShellService::GetShouldSkipCheckDefaultBrowser(bool* aResult) -+{ -+ NS_ENSURE_ARG_POINTER(aResult); -+ -+ nsresult rv; -+ nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); -+ if (NS_FAILED(rv)) { -+ return rv; -+ } -+ -+ rv = prefs->GetBoolPref(PREF_SKIPDEFAULTBROWSERCHECK, aResult); -+ if (NS_FAILED(rv)) { -+ return rv; -+ } -+ if (*aResult) { -+ // Only skip the default browser check once. The next attempt in -+ // a new session should proceed. -+ return prefs->SetBoolPref(PREF_SKIPDEFAULTBROWSERCHECK, false); -+ } -+ -+ int32_t defaultBrowserCheckCount; -+ rv = prefs->GetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, -+ &defaultBrowserCheckCount); -+ if (NS_FAILED(rv)) { -+ return rv; -+ } -+ if (defaultBrowserCheckCount < 4) { -+ *aResult = false; -+ return prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, -+ defaultBrowserCheckCount + 1); -+ } -+ -+ // Disable the default browser check after three attempts. -+ // Don't modify PREF_CHECKDEFAULTBROWSER since that is a -+ // user-initiated action and it shouldn't get re-enabled -+ // if it has been user disabled. -+ *aResult = true; -+ return rv; -+} -+ -+NS_IMETHODIMP -+nsKDEShellService::GetShouldCheckDefaultBrowser(bool* aResult) -+{ -+ // If we've already checked, the browser has been started and this is a -+ // new window open, and we don't want to check again. -+ if (mCheckedThisSession) { -+ *aResult = false; -+ return NS_OK; -+ } -+ -+ nsresult rv; -+#ifndef RELEASE_BUILD -+ bool skipDefaultBrowserCheck; -+ rv = GetShouldSkipCheckDefaultBrowser(&skipDefaultBrowserCheck); -+ if (NS_FAILED(rv)) { -+ return rv; -+ } -+ if (skipDefaultBrowserCheck) { -+ *aResult = false; -+ return rv; -+ } -+#endif -+ -+ nsCOMPtr<nsIPrefBranch> prefs; -+ nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID)); -+ if (pserve) -+ pserve->GetBranch("", getter_AddRefs(prefs)); -+ -+ if (prefs) -+ prefs->GetBoolPref(PREF_CHECKDEFAULTBROWSER, aResult); -+ -+ return NS_OK; -+} -+ -+NS_IMETHODIMP -+nsKDEShellService::SetShouldCheckDefaultBrowser(bool aShouldCheck) -+{ -+ nsCOMPtr<nsIPrefBranch> prefs; -+ nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID)); -+ if (pserve) -+ pserve->GetBranch("", getter_AddRefs(prefs)); -+ -+ if (prefs) -+ prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck); -+ -+ return NS_OK; -+} -+ -+NS_IMETHODIMP -+nsKDEShellService::GetCanSetDesktopBackground(bool* aResult) -+{ -+ *aResult = true; -+ return NS_OK; -+} -+ -+NS_IMETHODIMP -+nsKDEShellService::SetDesktopBackground(nsIDOMElement* aElement, -+ PRInt32 aPosition) -+{ -+ return NS_ERROR_NOT_IMPLEMENTED; -+} -+ -+NS_IMETHODIMP -+nsKDEShellService::GetDesktopBackgroundColor(PRUint32 *aColor) -+{ -+ return NS_ERROR_NOT_IMPLEMENTED; -+} -+ -+NS_IMETHODIMP -+nsKDEShellService::SetDesktopBackgroundColor(PRUint32 aColor) -+{ -+ return NS_ERROR_NOT_IMPLEMENTED; -+} -+ -+NS_IMETHODIMP -+nsKDEShellService::OpenApplication(PRInt32 aApplication) -+{ -+ nsCOMPtr<nsIMutableArray> command = do_CreateInstance( NS_ARRAY_CONTRACTID ); -+ if (!command) -+ return NS_ERROR_FAILURE; -+ -+ nsCOMPtr<nsISupportsCString> str = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); -+ if (!str) -+ return NS_ERROR_FAILURE; -+ -+ if( aApplication == APPLICATION_MAIL ) -+ str->SetData( NS_LITERAL_CSTRING( "OPENMAIL" )); -+ else if( aApplication == APPLICATION_NEWS ) -+ str->SetData( NS_LITERAL_CSTRING( "OPENNEWS" )); -+ else -+ return NS_ERROR_NOT_IMPLEMENTED; -+ -+ command->AppendElement( str, false ); -+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; -+} -+ -+NS_IMETHODIMP -+nsKDEShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACString& aURI) -+{ -+ nsCOMPtr<nsIMutableArray> command = do_CreateInstance( NS_ARRAY_CONTRACTID ); -+ if (!command) -+ return NS_ERROR_FAILURE; -+ -+ nsCOMPtr<nsISupportsCString> cmdstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); -+ nsCOMPtr<nsISupportsCString> appstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); -+ nsCOMPtr<nsISupportsCString> uristr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); -+ if (!cmdstr || !appstr || !uristr) -+ return NS_ERROR_FAILURE; -+ -+ cmdstr->SetData( NS_LITERAL_CSTRING( "RUN" )); -+ command->AppendElement( cmdstr, false ); -+ nsAutoCString app; -+ nsresult rv = aApplication->GetNativePath( app ); -+ NS_ENSURE_SUCCESS( rv, rv ); -+ appstr->SetData( app ); -+ command->AppendElement( appstr, false ); -+ uristr->SetData( aURI ); -+ command->AppendElement( uristr, false ); -+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; -+} -+ -+NS_IMETHODIMP -+nsKDEShellService::GetDefaultFeedReader(nsIFile** _retval) -+{ -+ *_retval = nullptr; -+ -+ nsCOMPtr<nsIMutableArray> command = do_CreateInstance( NS_ARRAY_CONTRACTID ); -+ if( !command ) -+ return NS_ERROR_FAILURE; -+ -+ nsCOMPtr<nsISupportsCString> str = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); -+ if( !str ) -+ return NS_ERROR_FAILURE; -+ -+ str->SetData( NS_LITERAL_CSTRING( "GETDEFAULTFEEDREADER" )); -+ command->AppendElement( str, false ); -+ -+ nsCOMPtr<nsIArray> output; -+ if( !nsKDEUtils::command( command, getter_AddRefs( output ) ) ) -+ return NS_ERROR_FAILURE; -+ -+ PRUint32 length; -+ output->GetLength( &length ); -+ if( length != 1 ) -+ return NS_ERROR_FAILURE; -+ -+ nsCOMPtr<nsISupportsCString> resstr = do_QueryElementAt( output, 0 ); -+ if( !resstr ) -+ return NS_ERROR_FAILURE; -+ -+ nsAutoCString path; -+ resstr->GetData( path ); -+ if (path.IsEmpty()) -+ return NS_ERROR_FAILURE; -+ -+ nsresult rv; -+ nsCOMPtr<nsIFile> defaultReader = -+ do_CreateInstance("@mozilla.org/file/local;1", &rv); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ rv = defaultReader->InitWithNativePath(path); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ bool exists; -+ rv = defaultReader->Exists(&exists); -+ NS_ENSURE_SUCCESS(rv, rv); -+ if (!exists) -+ return NS_ERROR_FAILURE; -+ -+ NS_ADDREF(*_retval = defaultReader); -+ return NS_OK; -+} -diff --git a/browser/components/shell/nsKDEShellService.h b/browser/components/shell/nsKDEShellService.h -new file mode 100644 ---- /dev/null -+++ b/browser/components/shell/nsKDEShellService.h -@@ -0,0 +1,29 @@ -+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#ifndef nskdeshellservice_h____ -+#define nskdeshellservice_h____ -+ -+#include "nsIShellService.h" -+#include "nsStringAPI.h" -+#include "mozilla/Attributes.h" -+ -+class nsKDEShellService final : public nsIShellService -+{ -+public: -+ nsKDEShellService() : mCheckedThisSession(false) { } -+ -+ NS_DECL_ISUPPORTS -+ NS_DECL_NSISHELLSERVICE -+ -+ nsresult Init(); -+ -+private: -+ ~nsKDEShellService() {} -+ -+ bool mCheckedThisSession; -+}; -+ -+#endif // nskdeshellservice_h____ -diff --git a/browser/components/shell/nsUnixShellService.cpp b/browser/components/shell/nsUnixShellService.cpp -new file mode 100644 ---- /dev/null -+++ b/browser/components/shell/nsUnixShellService.cpp -@@ -0,0 +1,22 @@ -+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+ -+#include "nsUnixShellService.h" -+#include "nsGNOMEShellService.h" -+#include "nsKDEShellService.h" -+#include "nsKDEUtils.h" -+#include "mozilla/ModuleUtils.h" -+ -+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init) -+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsKDEShellService, Init) -+ -+NS_METHOD -+nsUnixShellServiceConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult) -+{ -+ if( nsKDEUtils::kdeSupport()) -+ return nsKDEShellServiceConstructor( aOuter, aIID, aResult ); -+ return nsGNOMEShellServiceConstructor( aOuter, aIID, aResult ); -+} -diff --git a/browser/components/shell/nsUnixShellService.h b/browser/components/shell/nsUnixShellService.h -new file mode 100644 ---- /dev/null -+++ b/browser/components/shell/nsUnixShellService.h -@@ -0,0 +1,15 @@ -+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+ -+#ifndef nsunixshellservice_h____ -+#define nsunixshellservice_h____ -+ -+#include "nsIShellService.h" -+ -+NS_METHOD -+nsUnixShellServiceConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult); -+ -+#endif // nsunixshellservice_h____ -diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in ---- a/browser/installer/package-manifest.in -+++ b/browser/installer/package-manifest.in -@@ -709,16 +709,17 @@ - @RESPATH@/defaults/autoconfig/prefcalls.js - @RESPATH@/browser/defaults/profile/prefs.js - @RESPATH@/browser/defaults/permissions - - ; Warning: changing the path to channel-prefs.js can cause bugs (Bug 756325) - ; Technically this is an app pref file, but we are keeping it in the original - ; gre location for now. - @RESPATH@/defaults/pref/channel-prefs.js -+@BINPATH@/defaults/pref/kde.js - - ; Services (gre) prefs - #ifdef MOZ_SERVICES_NOTIFICATIONS - @RESPATH@/defaults/pref/services-notifications.js - #endif - #ifdef MOZ_SERVICES_SYNC - @RESPATH@/defaults/pref/services-sync.js - #endif diff --git a/helpers/DATA/firefox/mozilla-kde.patch b/helpers/DATA/firefox/mozilla-kde.patch deleted file mode 100644 index 6816da49c375e6613103437215fb471f4a1cf125..0000000000000000000000000000000000000000 --- a/helpers/DATA/firefox/mozilla-kde.patch +++ /dev/null @@ -1,3780 +0,0 @@ -# HG changeset patch -# Parent d9c9ae52f0338a60d1626d9209248341815e597a -Description: Add KDE integration to Firefox (toolkit parts) -Author: Wolfgang Rosenauer <wolfgang@rosenauer.org> -Author: Lubos Lunak <lunak@suse.com> -Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=140751 - https://bugzilla.novell.com/show_bug.cgi?id=170055 - -diff --git a/modules/libpref/Makefile.in b/modules/libpref/Makefile.in ---- a/modules/libpref/Makefile.in -+++ b/modules/libpref/Makefile.in -@@ -21,13 +21,15 @@ endif - ifdef MOZ_SERVICES_HEALTHREPORT - ifneq (android,$(MOZ_WIDGET_TOOLKIT)) - grepref_files += $(topsrcdir)/services/healthreport/healthreport-prefs.js - else - grepref_files += $(topsrcdir)/mobile/android/chrome/content/healthreport-prefs.js - endif - endif - -+LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre -+ - greprefs.js: $(grepref_files) - $(call py_action,preprocessor,$(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(MOZ_DEBUG_DEFINES) $^ -o $@) - - libs:: greprefs.js - $(INSTALL) $^ $(DIST)/bin/ -diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp ---- a/modules/libpref/Preferences.cpp -+++ b/modules/libpref/Preferences.cpp -@@ -30,16 +30,17 @@ - #include "nsIZipReader.h" - #include "nsPrefBranch.h" - #include "nsXPIDLString.h" - #include "nsCRT.h" - #include "nsCOMArray.h" - #include "nsXPCOMCID.h" - #include "nsAutoPtr.h" - #include "nsPrintfCString.h" -+#include "nsKDEUtils.h" - - #include "nsQuickSort.h" - #include "PLDHashTable.h" - - #include "prefapi.h" - #include "prefread.h" - #include "prefapi_private_data.h" - -@@ -1148,16 +1149,34 @@ pref_LoadPrefsInDir(nsIFile* aDir, char - - static nsresult pref_LoadPrefsInDirList(const char *listId) - { - nsresult rv; - nsCOMPtr<nsIProperties> dirSvc(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv)); - if (NS_FAILED(rv)) - return rv; - -+ // make sure we load these special files after all the others -+ static const char* specialFiles[] = { -+#if defined(XP_UNIX) -+ "" -+#endif -+ }; -+ -+ if (nsKDEUtils::kdeSession()) { -+ for(int i = 0; -+ i < MOZ_ARRAY_LENGTH(specialFiles); -+ ++i ) { -+ if (*specialFiles[ i ] == '\0') { -+ specialFiles[ i ] = "kde.js"; -+ break; -+ } -+ } -+ } -+ - nsCOMPtr<nsISimpleEnumerator> list; - dirSvc->Get(listId, - NS_GET_IID(nsISimpleEnumerator), - getter_AddRefs(list)); - if (!list) - return NS_OK; - - bool hasMore; -@@ -1173,17 +1192,17 @@ static nsresult pref_LoadPrefsInDirList( - - nsAutoCString leaf; - path->GetNativeLeafName(leaf); - - // Do we care if a file provided by this process fails to load? - if (Substring(leaf, leaf.Length() - 4).EqualsLiteral(".xpi")) - ReadExtensionPrefs(path); - else -- pref_LoadPrefsInDir(path, nullptr, 0); -+ pref_LoadPrefsInDir(path, specialFiles, MOZ_ARRAY_LENGTH(specialFiles)); - } - return NS_OK; - } - - static nsresult pref_ReadPrefFromJar(nsZipArchive* jarReader, const char *name) - { - nsZipItemPtr<char> manifest(jarReader, name, true); - NS_ENSURE_TRUE(manifest.Buffer(), NS_ERROR_NOT_AVAILABLE); -@@ -1277,26 +1296,38 @@ static nsresult pref_InitInitialObjects( - /* these pref file names should not be used: we process them after all other application pref files for backwards compatibility */ - static const char* specialFiles[] = { - #if defined(XP_MACOSX) - "macprefs.js" - #elif defined(XP_WIN) - "winpref.js" - #elif defined(XP_UNIX) - "unix.js" -+ , "" // placeholder for KDE (empty is otherwise harmless) - #if defined(VMS) - , "openvms.js" - #elif defined(_AIX) - , "aix.js" - #endif - #elif defined(XP_BEOS) - "beos.js" - #endif - }; - -+ if(nsKDEUtils::kdeSession()) { // TODO what if some setup actually requires the helper? -+ for(int i = 0; -+ i < MOZ_ARRAY_LENGTH(specialFiles); -+ ++i ) { -+ if( *specialFiles[ i ] == '\0' ) { -+ specialFiles[ i ] = "kde.js"; -+ break; -+ } -+ } -+ } -+ - rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, ArrayLength(specialFiles)); - if (NS_FAILED(rv)) - NS_WARNING("Error parsing application default preferences."); - - // Load jar:$app/omni.jar!/defaults/preferences/*.js - // or jar:$gre/omni.jar!/defaults/preferences/*.js. - RefPtr<nsZipArchive> appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP); - // GetReader(mozilla::Omnijar::APP) returns null when $app == $gre, in which -diff --git a/python/mozbuild/mozpack/chrome/flags.py b/python/mozbuild/mozpack/chrome/flags.py ---- a/python/mozbuild/mozpack/chrome/flags.py -+++ b/python/mozbuild/mozpack/chrome/flags.py -@@ -211,16 +211,17 @@ class Flags(OrderedDict): - 'contentaccessible': Flag, - 'os': StringFlag, - 'osversion': VersionFlag, - 'abi': StringFlag, - 'platform': Flag, - 'xpcnativewrappers': Flag, - 'tablet': Flag, - 'process': StringFlag, -+ 'desktop': StringFlag, - } - RE = re.compile(r'([!<>=]+)') - - def __init__(self, *flags): - ''' - Initialize a set of flags given in string form. - flags = Flags('contentaccessible=yes', 'appversion>=3.5') - ''' -diff --git a/python/mozbuild/mozpack/chrome/manifest.py b/python/mozbuild/mozpack/chrome/manifest.py ---- a/python/mozbuild/mozpack/chrome/manifest.py -+++ b/python/mozbuild/mozpack/chrome/manifest.py -@@ -33,16 +33,17 @@ class ManifestEntry(object): - 'application', - 'platformversion', - 'os', - 'osversion', - 'abi', - 'xpcnativewrappers', - 'tablet', - 'process', -+ 'desktop', - ] - - def __init__(self, base, *flags): - ''' - Initialize a manifest entry with the given base path and flags. - ''' - self.base = base - self.flags = Flags(*flags) -diff --git a/toolkit/components/downloads/moz.build b/toolkit/components/downloads/moz.build ---- a/toolkit/components/downloads/moz.build -+++ b/toolkit/components/downloads/moz.build -@@ -65,15 +65,16 @@ if not CONFIG['MOZ_SUITE']: - 'nsDownloadManagerUI.js', - 'nsDownloadManagerUI.manifest', - ] - - FINAL_LIBRARY = 'xul' - - LOCAL_INCLUDES += [ - '../protobuf', -- '/ipc/chromium/src' -+ '/ipc/chromium/src', -+ '/toolkit/xre' - ] - - DEFINES['GOOGLE_PROTOBUF_NO_RTTI'] = True - DEFINES['GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER'] = True - - CXXFLAGS += CONFIG['TK_CFLAGS'] -diff --git a/toolkit/components/downloads/nsDownloadManager.cpp b/toolkit/components/downloads/nsDownloadManager.cpp ---- a/toolkit/components/downloads/nsDownloadManager.cpp -+++ b/toolkit/components/downloads/nsDownloadManager.cpp -@@ -51,16 +51,20 @@ - #ifdef XP_WIN - #include <shlobj.h> - #include "nsWindowsHelpers.h" - #ifdef DOWNLOAD_SCANNER - #include "nsDownloadScanner.h" - #endif - #endif - -+#if defined(XP_UNIX) && !defined(XP_MACOSX) -+#include "nsKDEUtils.h" -+#endif -+ - #ifdef XP_MACOSX - #include <CoreFoundation/CoreFoundation.h> - #endif - - #ifdef MOZ_WIDGET_ANDROID - #include "AndroidBridge.h" - #endif - -@@ -2714,16 +2718,25 @@ nsDownload::SetState(DownloadState aStat - nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID)); - - // Master pref to control this function. - bool showTaskbarAlert = true; - if (pref) - pref->GetBoolPref(PREF_BDM_SHOWALERTONCOMPLETE, &showTaskbarAlert); - - if (showTaskbarAlert) { -+ if( nsKDEUtils::kdeSupport()) { -+ nsTArray<nsCString> command; -+ command.AppendElement( NS_LITERAL_CSTRING( "DOWNLOADFINISHED" )); -+ nsAutoString displayName; -+ GetDisplayName( displayName ); -+ command.AppendElement( nsAutoCString( ToNewUTF8String( displayName ))); -+ nsKDEUtils::command( command ); -+ } else { -+ // begin non-KDE block - int32_t alertInterval = 2000; - if (pref) - pref->GetIntPref(PREF_BDM_SHOWALERTINTERVAL, &alertInterval); - - int64_t alertIntervalUSec = alertInterval * PR_USEC_PER_MSEC; - int64_t goat = PR_Now() - mStartTime; - showTaskbarAlert = goat > alertIntervalUSec; - -@@ -2754,16 +2767,17 @@ nsDownload::SetState(DownloadState aStat - NS_LITERAL_STRING(DOWNLOAD_MANAGER_ALERT_ICON), title, - message, !removeWhenDone, - mPrivate ? NS_LITERAL_STRING("private") : NS_LITERAL_STRING("non-private"), - mDownloadManager, EmptyString(), NS_LITERAL_STRING("auto"), - EmptyString(), EmptyString(), nullptr, mPrivate); - } - } - } -+ } - - #if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK) - nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mTarget); - nsCOMPtr<nsIFile> file; - nsAutoString path; - - if (fileURL && - NS_SUCCEEDED(fileURL->GetFile(getter_AddRefs(file))) && -diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn ---- a/toolkit/content/jar.mn -+++ b/toolkit/content/jar.mn -@@ -64,29 +64,33 @@ toolkit.jar: - content/global/viewZoomOverlay.js - *+ content/global/bindings/autocomplete.xml (widgets/autocomplete.xml) - content/global/bindings/browser.xml (widgets/browser.xml) - content/global/bindings/button.xml (widgets/button.xml) - content/global/bindings/checkbox.xml (widgets/checkbox.xml) - content/global/bindings/colorpicker.xml (widgets/colorpicker.xml) - content/global/bindings/datetimepicker.xml (widgets/datetimepicker.xml) - *+ content/global/bindings/dialog.xml (widgets/dialog.xml) -+*+ content/global/bindings/dialog-kde.xml (widgets/dialog-kde.xml) -+% override chrome://global/content/bindings/dialog.xml chrome://global/content/bindings/dialog-kde.xml desktop=kde - content/global/bindings/editor.xml (widgets/editor.xml) - content/global/bindings/expander.xml (widgets/expander.xml) - * content/global/bindings/filefield.xml (widgets/filefield.xml) - *+ content/global/bindings/findbar.xml (widgets/findbar.xml) - content/global/bindings/general.xml (widgets/general.xml) - content/global/bindings/groupbox.xml (widgets/groupbox.xml) - *+ content/global/bindings/listbox.xml (widgets/listbox.xml) - content/global/bindings/menu.xml (widgets/menu.xml) - content/global/bindings/menulist.xml (widgets/menulist.xml) - content/global/bindings/notification.xml (widgets/notification.xml) - content/global/bindings/numberbox.xml (widgets/numberbox.xml) - content/global/bindings/popup.xml (widgets/popup.xml) - *+ content/global/bindings/preferences.xml (widgets/preferences.xml) -+*+ content/global/bindings/preferences-kde.xml (widgets/preferences-kde.xml) -+% override chrome://global/content/bindings/preferences.xml chrome://global/content/bindings/preferences-kde.xml desktop=kde - content/global/bindings/progressmeter.xml (widgets/progressmeter.xml) - content/global/bindings/radio.xml (widgets/radio.xml) - content/global/bindings/remote-browser.xml (widgets/remote-browser.xml) - content/global/bindings/resizer.xml (widgets/resizer.xml) - content/global/bindings/richlistbox.xml (widgets/richlistbox.xml) - content/global/bindings/scale.xml (widgets/scale.xml) - content/global/bindings/scrollbar.xml (widgets/scrollbar.xml) - content/global/bindings/scrollbox.xml (widgets/scrollbox.xml) -diff --git a/toolkit/content/widgets/dialog-kde.xml b/toolkit/content/widgets/dialog-kde.xml -new file mode 100644 ---- /dev/null -+++ b/toolkit/content/widgets/dialog-kde.xml -@@ -0,0 +1,460 @@ -+<?xml version="1.0"?> -+<!-- This Source Code Form is subject to the terms of the Mozilla Public -+ - License, v. 2.0. If a copy of the MPL was not distributed with this -+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> -+ -+ -+<bindings id="dialogBindings" -+ xmlns="http://www.mozilla.org/xbl" -+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" -+ xmlns:xbl="http://www.mozilla.org/xbl"> -+ -+ <binding id="dialog" extends="chrome://global/content/bindings/general.xml#root-element"> -+ <resources> -+ <stylesheet src="chrome://global/skin/dialog.css"/> -+ </resources> -+ <content> -+ <xul:vbox class="box-inherit dialog-content-box" flex="1"> -+ <children/> -+ </xul:vbox> -+ -+ <xul:hbox class="dialog-button-box" anonid="buttons" -+ xbl:inherits="pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient" -+#ifdef XP_UNIX_GNOME -+ > -+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> -+ <xul:button dlgtype="help" class="dialog-button" hidden="true"/> -+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> -+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> -+ <xul:spacer anonid="spacer" flex="1"/> -+ <xul:button dlgtype="cancel" class="dialog-button"/> -+ <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/> -+#elif XP_UNIX -+ > -+ <xul:button dlgtype="help" class="dialog-button" hidden="true"/> -+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> -+ <xul:spacer anonid="spacer" flex="1"/> -+ <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/> -+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> -+ <xul:button dlgtype="cancel" class="dialog-button"/> -+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> -+#else -+ pack="end"> -+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> -+ <xul:spacer anonid="spacer" flex="1" hidden="true"/> -+ <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/> -+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> -+ <xul:button dlgtype="cancel" class="dialog-button"/> -+ <xul:button dlgtype="help" class="dialog-button" hidden="true"/> -+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> -+#endif -+ </xul:hbox> -+ </content> -+ -+ <implementation> -+ <field name="_mStrBundle">null</field> -+ <field name="_closeHandler">(function(event) { -+ if (!document.documentElement.cancelDialog()) -+ event.preventDefault(); -+ })</field> -+ -+ <property name="buttons" -+ onget="return this.getAttribute('buttons');" -+ onset="this._configureButtons(val); return val;"/> -+ -+ <property name="defaultButton"> -+ <getter> -+ <![CDATA[ -+ if (this.hasAttribute("defaultButton")) -+ return this.getAttribute("defaultButton"); -+ else // default to the accept button -+ return "accept"; -+ ]]> -+ </getter> -+ <setter> -+ <![CDATA[ -+ this._setDefaultButton(val); -+ return val; -+ ]]> -+ </setter> -+ </property> -+ -+ <method name="acceptDialog"> -+ <body> -+ <![CDATA[ -+ return this._doButtonCommand("accept"); -+ ]]> -+ </body> -+ </method> -+ -+ <method name="cancelDialog"> -+ <body> -+ <![CDATA[ -+ return this._doButtonCommand("cancel"); -+ ]]> -+ </body> -+ </method> -+ -+ <method name="getButton"> -+ <parameter name="aDlgType"/> -+ <body> -+ <![CDATA[ -+ return this._buttons[aDlgType]; -+ ]]> -+ </body> -+ </method> -+ -+ <method name="moveToAlertPosition"> -+ <body> -+ <![CDATA[ -+ // hack. we need this so the window has something like its final size -+ if (window.outerWidth == 1) { -+ dump("Trying to position a sizeless window; caller should have called sizeToContent() or sizeTo(). See bug 75649.\n"); -+ sizeToContent(); -+ } -+ -+ if (opener) { -+ var xOffset = (opener.outerWidth - window.outerWidth) / 2; -+ var yOffset = opener.outerHeight / 5; -+ -+ var newX = opener.screenX + xOffset; -+ var newY = opener.screenY + yOffset; -+ } else { -+ newX = (screen.availWidth - window.outerWidth) / 2; -+ newY = (screen.availHeight - window.outerHeight) / 2; -+ } -+ -+ // ensure the window is fully onscreen (if smaller than the screen) -+ if (newX < screen.availLeft) -+ newX = screen.availLeft + 20; -+ if ((newX + window.outerWidth) > (screen.availLeft + screen.availWidth)) -+ newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20; -+ -+ if (newY < screen.availTop) -+ newY = screen.availTop + 20; -+ if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight)) -+ newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60; -+ -+ window.moveTo( newX, newY ); -+ ]]> -+ </body> -+ </method> -+ -+ <method name="centerWindowOnScreen"> -+ <body> -+ <![CDATA[ -+ var xOffset = screen.availWidth/2 - window.outerWidth/2; -+ var yOffset = screen.availHeight/2 - window.outerHeight/2; //(opener.outerHeight *2)/10; -+ -+ xOffset = xOffset > 0 ? xOffset : 0; -+ yOffset = yOffset > 0 ? yOffset : 0; -+ window.moveTo(xOffset, yOffset); -+ ]]> -+ </body> -+ </method> -+ -+ <constructor> -+ <![CDATA[ -+ this._configureButtons(this.buttons); -+ -+ // listen for when window is closed via native close buttons -+ window.addEventListener("close", this._closeHandler, false); -+ -+ // for things that we need to initialize after onload fires -+ window.addEventListener("load", this.postLoadInit, false); -+ -+ window.moveToAlertPosition = this.moveToAlertPosition; -+ window.centerWindowOnScreen = this.centerWindowOnScreen; -+ ]]> -+ </constructor> -+ -+ <method name="postLoadInit"> -+ <parameter name="aEvent"/> -+ <body> -+ <![CDATA[ -+ function focusInit() { -+ const dialog = document.documentElement; -+ const defaultButton = dialog.getButton(dialog.defaultButton); -+ // give focus to the first focusable element in the dialog -+ if (!document.commandDispatcher.focusedElement) { -+ document.commandDispatcher.advanceFocusIntoSubtree(dialog); -+ -+ var focusedElt = document.commandDispatcher.focusedElement; -+ if (focusedElt) { -+ var initialFocusedElt = focusedElt; -+ while (focusedElt.localName == "tab" || -+ focusedElt.getAttribute("noinitialfocus") == "true") { -+ document.commandDispatcher.advanceFocusIntoSubtree(focusedElt); -+ focusedElt = document.commandDispatcher.focusedElement; -+ if (focusedElt == initialFocusedElt) -+ break; -+ } -+ -+ if (initialFocusedElt.localName == "tab") { -+ if (focusedElt.hasAttribute("dlgtype")) { -+ // We don't want to focus on anonymous OK, Cancel, etc. buttons, -+ // so return focus to the tab itself -+ initialFocusedElt.focus(); -+ } -+ } -+#ifndef XP_MACOSX -+ else if (focusedElt.hasAttribute("dlgtype") && focusedElt != defaultButton) { -+ defaultButton.focus(); -+ } -+#endif -+ } -+ } -+ -+ try { -+ if (defaultButton) -+ window.notifyDefaultButtonLoaded(defaultButton); -+ } catch (e) { } -+ } -+ -+ // Give focus after onload completes, see bug 103197. -+ setTimeout(focusInit, 0); -+ ]]> -+ </body> -+ </method> -+ -+ <property name="mStrBundle"> -+ <getter> -+ <![CDATA[ -+ if (!this._mStrBundle) { -+ // need to create string bundle manually instead of using <xul:stringbundle/> -+ // see bug 63370 for details -+ this._mStrBundle = Components.classes["@mozilla.org/intl/stringbundle;1"] -+ .getService(Components.interfaces.nsIStringBundleService) -+ .createBundle("chrome://global/locale/dialog.properties"); -+ } -+ return this._mStrBundle; -+ ]]></getter> -+ </property> -+ -+ <method name="_configureButtons"> -+ <parameter name="aButtons"/> -+ <body> -+ <![CDATA[ -+ // by default, get all the anonymous button elements -+ var buttons = {}; -+ this._buttons = buttons; -+ buttons.accept = document.getAnonymousElementByAttribute(this, "dlgtype", "accept"); -+ buttons.cancel = document.getAnonymousElementByAttribute(this, "dlgtype", "cancel"); -+ buttons.extra1 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra1"); -+ buttons.extra2 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra2"); -+ buttons.help = document.getAnonymousElementByAttribute(this, "dlgtype", "help"); -+ buttons.disclosure = document.getAnonymousElementByAttribute(this, "dlgtype", "disclosure"); -+ -+ // look for any overriding explicit button elements -+ var exBtns = this.getElementsByAttribute("dlgtype", "*"); -+ var dlgtype; -+ var i; -+ for (i = 0; i < exBtns.length; ++i) { -+ dlgtype = exBtns[i].getAttribute("dlgtype"); -+ buttons[dlgtype].hidden = true; // hide the anonymous button -+ buttons[dlgtype] = exBtns[i]; -+ } -+ -+ // add the label and oncommand handler to each button -+ for (dlgtype in buttons) { -+ var button = buttons[dlgtype]; -+ button.addEventListener("command", this._handleButtonCommand, true); -+ -+ // don't override custom labels with pre-defined labels on explicit buttons -+ if (!button.hasAttribute("label")) { -+ // dialog attributes override the default labels in dialog.properties -+ if (this.hasAttribute("buttonlabel"+dlgtype)) { -+ button.setAttribute("label", this.getAttribute("buttonlabel"+dlgtype)); -+ if (this.hasAttribute("buttonaccesskey"+dlgtype)) -+ button.setAttribute("accesskey", this.getAttribute("buttonaccesskey"+dlgtype)); -+ } else if (dlgtype != "extra1" && dlgtype != "extra2") { -+ button.setAttribute("label", this.mStrBundle.GetStringFromName("button-"+dlgtype)); -+ var accessKey = this.mStrBundle.GetStringFromName("accesskey-"+dlgtype); -+ if (accessKey) -+ button.setAttribute("accesskey", accessKey); -+ } -+ } -+ // allow specifying alternate icons in the dialog header -+ if (!button.hasAttribute("icon")) { -+ // if there's an icon specified, use that -+ if (this.hasAttribute("buttonicon"+dlgtype)) -+ button.setAttribute("icon", this.getAttribute("buttonicon"+dlgtype)); -+ // otherwise set defaults -+ else -+ switch (dlgtype) { -+ case "accept": -+ button.setAttribute("icon","accept"); -+ break; -+ case "cancel": -+ button.setAttribute("icon","cancel"); -+ break; -+ case "disclosure": -+ button.setAttribute("icon","properties"); -+ break; -+ case "help": -+ button.setAttribute("icon","help"); -+ break; -+ default: -+ break; -+ } -+ } -+ } -+ -+ // ensure that hitting enter triggers the default button command -+ this.defaultButton = this.defaultButton; -+ -+ // if there is a special button configuration, use it -+ if (aButtons) { -+ // expect a comma delimited list of dlgtype values -+ var list = aButtons.split(","); -+ -+ // mark shown dlgtypes as true -+ var shown = { accept: false, cancel: false, help: false, -+ disclosure: false, extra1: false, extra2: false }; -+ for (i = 0; i < list.length; ++i) -+ shown[list[i].replace(/ /g, "")] = true; -+ -+ // hide/show the buttons we want -+ for (dlgtype in buttons) -+ buttons[dlgtype].hidden = !shown[dlgtype]; -+ -+#ifdef XP_WIN -+# show the spacer on Windows only when the extra2 button is present -+ var spacer = document.getAnonymousElementByAttribute(this, "anonid", "spacer"); -+ spacer.removeAttribute("hidden"); -+ spacer.setAttribute("flex", shown["extra2"]?"1":"0"); -+#endif -+ -+ } -+ ]]> -+ </body> -+ </method> -+ -+ <method name="_setDefaultButton"> -+ <parameter name="aNewDefault"/> -+ <body> -+ <![CDATA[ -+ // remove the default attribute from the previous default button, if any -+ var oldDefaultButton = this.getButton(this.defaultButton); -+ if (oldDefaultButton) -+ oldDefaultButton.removeAttribute("default"); -+ -+ var newDefaultButton = this.getButton(aNewDefault); -+ if (newDefaultButton) { -+ this.setAttribute("defaultButton", aNewDefault); -+ newDefaultButton.setAttribute("default", "true"); -+ } -+ else { -+ this.setAttribute("defaultButton", "none"); -+ if (aNewDefault != "none") -+ dump("invalid new default button: " + aNewDefault + ", assuming: none\n"); -+ } -+ ]]> -+ </body> -+ </method> -+ -+ <method name="_handleButtonCommand"> -+ <parameter name="aEvent"/> -+ <body> -+ <![CDATA[ -+ return document.documentElement._doButtonCommand( -+ aEvent.target.getAttribute("dlgtype")); -+ ]]> -+ </body> -+ </method> -+ -+ <method name="_doButtonCommand"> -+ <parameter name="aDlgType"/> -+ <body> -+ <![CDATA[ -+ var button = this.getButton(aDlgType); -+ if (!button.disabled) { -+ var noCancel = this._fireButtonEvent(aDlgType); -+ if (noCancel) { -+ if (aDlgType == "accept" || aDlgType == "cancel") { -+ var closingEvent = new CustomEvent("dialogclosing", { -+ bubbles: true, -+ detail: { button: aDlgType }, -+ }); -+ this.dispatchEvent(closingEvent); -+ window.close(); -+ } -+ } -+ return noCancel; -+ } -+ return true; -+ ]]> -+ </body> -+ </method> -+ -+ <method name="_fireButtonEvent"> -+ <parameter name="aDlgType"/> -+ <body> -+ <![CDATA[ -+ var event = document.createEvent("Events"); -+ event.initEvent("dialog"+aDlgType, true, true); -+ -+ // handle dom event handlers -+ var noCancel = this.dispatchEvent(event); -+ -+ // handle any xml attribute event handlers -+ var handler = this.getAttribute("ondialog"+aDlgType); -+ if (handler != "") { -+ var fn = new Function("event", handler); -+ var returned = fn(event); -+ if (returned == false) -+ noCancel = false; -+ } -+ -+ return noCancel; -+ ]]> -+ </body> -+ </method> -+ -+ <method name="_hitEnter"> -+ <parameter name="evt"/> -+ <body> -+ <![CDATA[ -+ if (evt.defaultPrevented) -+ return; -+ -+ var btn = this.getButton(this.defaultButton); -+ if (btn) -+ this._doButtonCommand(this.defaultButton); -+ ]]> -+ </body> -+ </method> -+ -+ </implementation> -+ -+ <handlers> -+ <handler event="keypress" keycode="VK_RETURN" -+ group="system" action="this._hitEnter(event);"/> -+ <handler event="keypress" keycode="VK_ESCAPE" group="system"> -+ if (!event.defaultPrevented) -+ this.cancelDialog(); -+ </handler> -+#ifdef XP_MACOSX -+ <handler event="keypress" key="." modifiers="meta" phase="capturing" action="this.cancelDialog();"/> -+#else -+ <handler event="focus" phase="capturing"> -+ var btn = this.getButton(this.defaultButton); -+ if (btn) -+ btn.setAttribute("default", event.originalTarget == btn || !(event.originalTarget instanceof Components.interfaces.nsIDOMXULButtonElement)); -+ </handler> -+#endif -+ </handlers> -+ -+ </binding> -+ -+ <binding id="dialogheader"> -+ <resources> -+ <stylesheet src="chrome://global/skin/dialog.css"/> -+ </resources> -+ <content> -+ <xul:label class="dialogheader-title" xbl:inherits="value=title,crop" crop="right" flex="1"/> -+ <xul:label class="dialogheader-description" xbl:inherits="value=description"/> -+ </content> -+ </binding> -+ -+</bindings> -diff --git a/toolkit/content/widgets/preferences-kde.xml b/toolkit/content/widgets/preferences-kde.xml -new file mode 100644 ---- /dev/null -+++ b/toolkit/content/widgets/preferences-kde.xml -@@ -0,0 +1,1403 @@ -+<?xml version="1.0"?> -+ -+<!DOCTYPE bindings [ -+ <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd"> -+ %preferencesDTD; -+ <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd"> -+ %globalKeysDTD; -+]> -+ -+<bindings id="preferencesBindings" -+ xmlns="http://www.mozilla.org/xbl" -+ xmlns:xbl="http://www.mozilla.org/xbl" -+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> -+ -+# -+# = Preferences Window Framework -+# -+# The syntax for use looks something like: -+# -+# <prefwindow> -+# <prefpane id="prefPaneA"> -+# <preferences> -+# <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/> -+# <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/> -+# </preferences> -+# <checkbox label="Preference" preference="preference1"/> -+# </prefpane> -+# </prefwindow> -+# -+ -+ <binding id="preferences"> -+ <implementation implements="nsIObserver"> -+ <method name="_constructAfterChildren"> -+ <body> -+ <![CDATA[ -+ // This method will be called after each one of the child -+ // <preference> elements is constructed. Its purpose is to propagate -+ // the values to the associated form elements -+ -+ var elements = this.getElementsByTagName("preference"); -+ for (let element of elements) { -+ if (!element._constructed) { -+ return; -+ } -+ } -+ for (let element of elements) { -+ element.updateElements(); -+ } -+ ]]> -+ </body> -+ </method> -+ <method name="observe"> -+ <parameter name="aSubject"/> -+ <parameter name="aTopic"/> -+ <parameter name="aData"/> -+ <body> -+ <![CDATA[ -+ for (var i = 0; i < this.childNodes.length; ++i) { -+ var preference = this.childNodes[i]; -+ if (preference.name == aData) { -+ preference.value = preference.valueFromPreferences; -+ } -+ } -+ ]]> -+ </body> -+ </method> -+ -+ <method name="fireChangedEvent"> -+ <parameter name="aPreference"/> -+ <body> -+ <![CDATA[ -+ // Value changed, synthesize an event -+ try { -+ var event = document.createEvent("Events"); -+ event.initEvent("change", true, true); -+ aPreference.dispatchEvent(event); -+ } -+ catch (e) { -+ Components.utils.reportError(e); -+ } -+ ]]> -+ </body> -+ </method> -+ -+ <field name="service"> -+ Components.classes["@mozilla.org/preferences-service;1"] -+ .getService(Components.interfaces.nsIPrefService); -+ </field> -+ <field name="rootBranch"> -+ Components.classes["@mozilla.org/preferences-service;1"] -+ .getService(Components.interfaces.nsIPrefBranch); -+ </field> -+ <field name="defaultBranch"> -+ this.service.getDefaultBranch(""); -+ </field> -+ <field name="rootBranchInternal"> -+ Components.classes["@mozilla.org/preferences-service;1"] -+ .getService(Components.interfaces.nsIPrefBranchInternal); -+ </field> -+ <property name="type" readonly="true"> -+ <getter> -+ <![CDATA[ -+ return document.documentElement.type || ""; -+ ]]> -+ </getter> -+ </property> -+ <property name="instantApply" readonly="true"> -+ <getter> -+ <![CDATA[ -+ var doc = document.documentElement; -+ return this.type == "child" ? doc.instantApply -+ : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply"); -+ ]]> -+ </getter> -+ </property> -+ </implementation> -+ </binding> -+ -+ <binding id="preference"> -+ <implementation> -+ <constructor> -+ <![CDATA[ -+ this._constructed = true; -+ -+ // if the element has been inserted without the name attribute set, -+ // we have nothing to do here -+ if (!this.name) -+ return; -+ -+ this.preferences.rootBranchInternal -+ .addObserver(this.name, this.preferences, false); -+ // In non-instant apply mode, we must try and use the last saved state -+ // from any previous opens of a child dialog instead of the value from -+ // preferences, to pick up any edits a user may have made. -+ -+ var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"] -+ .getService(Components.interfaces.nsIScriptSecurityManager); -+ if (this.preferences.type == "child" && -+ !this.instantApply && window.opener && -+ secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) { -+ var pdoc = window.opener.document; -+ -+ // Try to find a preference element for the same preference. -+ var preference = null; -+ var parentPreferences = pdoc.getElementsByTagName("preferences"); -+ for (var k = 0; (k < parentPreferences.length && !preference); ++k) { -+ var parentPrefs = parentPreferences[k] -+ .getElementsByAttribute("name", this.name); -+ for (var l = 0; (l < parentPrefs.length && !preference); ++l) { -+ if (parentPrefs[l].localName == "preference") -+ preference = parentPrefs[l]; -+ } -+ } -+ -+ // Don't use the value setter here, we don't want updateElements to be prematurely fired. -+ this._value = preference ? preference.value : this.valueFromPreferences; -+ } -+ else -+ this._value = this.valueFromPreferences; -+ this.preferences._constructAfterChildren(); -+ ]]> -+ </constructor> -+ <destructor> -+ this.preferences.rootBranchInternal -+ .removeObserver(this.name, this.preferences); -+ </destructor> -+ <field name="_constructed">false</field> -+ <property name="instantApply"> -+ <getter> -+ return this.getAttribute("instantApply") == "true" || this.preferences.instantApply; -+ </getter> -+ </property> -+ -+ <property name="preferences" onget="return this.parentNode"/> -+ <property name="name" onget="return this.getAttribute('name');"> -+ <setter> -+ if (val == this.name) -+ return val; -+ -+ this.preferences.rootBranchInternal -+ .removeObserver(this.name, this.preferences); -+ this.setAttribute('name', val); -+ this.preferences.rootBranchInternal -+ .addObserver(val, this.preferences, false); -+ -+ return val; -+ </setter> -+ </property> -+ <property name="type" onget="return this.getAttribute('type');" -+ onset="this.setAttribute('type', val); return val;"/> -+ <property name="inverted" onget="return this.getAttribute('inverted') == 'true';" -+ onset="this.setAttribute('inverted', val); return val;"/> -+ <property name="readonly" onget="return this.getAttribute('readonly') == 'true';" -+ onset="this.setAttribute('readonly', val); return val;"/> -+ -+ <field name="_value">null</field> -+ <method name="_setValue"> -+ <parameter name="aValue"/> -+ <body> -+ <![CDATA[ -+ if (this.value !== aValue) { -+ this._value = aValue; -+ if (this.instantApply) -+ this.valueFromPreferences = aValue; -+ this.preferences.fireChangedEvent(this); -+ } -+ return aValue; -+ ]]> -+ </body> -+ </method> -+ <property name="value" onget="return this._value" onset="return this._setValue(val);"/> -+ -+ <property name="locked"> -+ <getter> -+ return this.preferences.rootBranch.prefIsLocked(this.name); -+ </getter> -+ </property> -+ -+ <property name="disabled"> -+ <getter> -+ return this.getAttribute("disabled") == "true"; -+ </getter> -+ <setter> -+ <![CDATA[ -+ if (val) -+ this.setAttribute("disabled", "true"); -+ else -+ this.removeAttribute("disabled"); -+ -+ if (!this.id) -+ return val; -+ -+ var elements = document.getElementsByAttribute("preference", this.id); -+ for (var i = 0; i < elements.length; ++i) { -+ elements[i].disabled = val; -+ -+ var labels = document.getElementsByAttribute("control", elements[i].id); -+ for (var j = 0; j < labels.length; ++j) -+ labels[j].disabled = val; -+ } -+ -+ return val; -+ ]]> -+ </setter> -+ </property> -+ -+ <property name="tabIndex"> -+ <getter> -+ return parseInt(this.getAttribute("tabindex")); -+ </getter> -+ <setter> -+ <![CDATA[ -+ if (val) -+ this.setAttribute("tabindex", val); -+ else -+ this.removeAttribute("tabindex"); -+ -+ if (!this.id) -+ return val; -+ -+ var elements = document.getElementsByAttribute("preference", this.id); -+ for (var i = 0; i < elements.length; ++i) { -+ elements[i].tabIndex = val; -+ -+ var labels = document.getElementsByAttribute("control", elements[i].id); -+ for (var j = 0; j < labels.length; ++j) -+ labels[j].tabIndex = val; -+ } -+ -+ return val; -+ ]]> -+ </setter> -+ </property> -+ -+ <property name="hasUserValue"> -+ <getter> -+ <![CDATA[ -+ return this.preferences.rootBranch.prefHasUserValue(this.name) && -+ this.value !== undefined; -+ ]]> -+ </getter> -+ </property> -+ -+ <method name="reset"> -+ <body> -+ // defer reset until preference update -+ this.value = undefined; -+ </body> -+ </method> -+ -+ <field name="_useDefault">false</field> -+ <property name="defaultValue"> -+ <getter> -+ <![CDATA[ -+ this._useDefault = true; -+ var val = this.valueFromPreferences; -+ this._useDefault = false; -+ return val; -+ ]]> -+ </getter> -+ </property> -+ -+ <property name="_branch"> -+ <getter> -+ return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch; -+ </getter> -+ </property> -+ -+ <field name="batching">false</field> -+ -+ <method name="_reportUnknownType"> -+ <body> -+ <![CDATA[ -+ var consoleService = Components.classes["@mozilla.org/consoleservice;1"] -+ .getService(Components.interfaces.nsIConsoleService); -+ var msg = "<preference> with id='" + this.id + "' and name='" + -+ this.name + "' has unknown type '" + this.type + "'."; -+ consoleService.logStringMessage(msg); -+ ]]> -+ </body> -+ </method> -+ -+ <property name="valueFromPreferences"> -+ <getter> -+ <![CDATA[ -+ try { -+ // Force a resync of value with preferences. -+ switch (this.type) { -+ case "int": -+ return this._branch.getIntPref(this.name); -+ case "bool": -+ var val = this._branch.getBoolPref(this.name); -+ return this.inverted ? !val : val; -+ case "wstring": -+ return this._branch -+ .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString) -+ .data; -+ case "string": -+ case "unichar": -+ return this._branch -+ .getComplexValue(this.name, Components.interfaces.nsISupportsString) -+ .data; -+ case "fontname": -+ var family = this._branch -+ .getComplexValue(this.name, Components.interfaces.nsISupportsString) -+ .data; -+ var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"] -+ .createInstance(Components.interfaces.nsIFontEnumerator); -+ return fontEnumerator.getStandardFamilyName(family); -+ case "file": -+ var f = this._branch -+ .getComplexValue(this.name, Components.interfaces.nsILocalFile); -+ return f; -+ default: -+ this._reportUnknownType(); -+ } -+ } -+ catch (e) { } -+ return null; -+ ]]> -+ </getter> -+ <setter> -+ <![CDATA[ -+ // Exit early if nothing to do. -+ if (this.readonly || this.valueFromPreferences == val) -+ return val; -+ -+ // The special value undefined means 'reset preference to default'. -+ if (val === undefined) { -+ this.preferences.rootBranch.clearUserPref(this.name); -+ return val; -+ } -+ -+ // Force a resync of preferences with value. -+ switch (this.type) { -+ case "int": -+ this.preferences.rootBranch.setIntPref(this.name, val); -+ break; -+ case "bool": -+ this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val); -+ break; -+ case "wstring": -+ var pls = Components.classes["@mozilla.org/pref-localizedstring;1"] -+ .createInstance(Components.interfaces.nsIPrefLocalizedString); -+ pls.data = val; -+ this.preferences.rootBranch -+ .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls); -+ break; -+ case "string": -+ case "unichar": -+ case "fontname": -+ var iss = Components.classes["@mozilla.org/supports-string;1"] -+ .createInstance(Components.interfaces.nsISupportsString); -+ iss.data = val; -+ this.preferences.rootBranch -+ .setComplexValue(this.name, Components.interfaces.nsISupportsString, iss); -+ break; -+ case "file": -+ var lf; -+ if (typeof(val) == "string") { -+ lf = Components.classes["@mozilla.org/file/local;1"] -+ .createInstance(Components.interfaces.nsILocalFile); -+ lf.persistentDescriptor = val; -+ if (!lf.exists()) -+ lf.initWithPath(val); -+ } -+ else -+ lf = val.QueryInterface(Components.interfaces.nsILocalFile); -+ this.preferences.rootBranch -+ .setComplexValue(this.name, Components.interfaces.nsILocalFile, lf); -+ break; -+ default: -+ this._reportUnknownType(); -+ } -+ if (!this.batching) -+ this.preferences.service.savePrefFile(null); -+ return val; -+ ]]> -+ </setter> -+ </property> -+ -+ <method name="setElementValue"> -+ <parameter name="aElement"/> -+ <body> -+ <![CDATA[ -+ if (this.locked) -+ aElement.disabled = true; -+ -+ if (!this.isElementEditable(aElement)) -+ return; -+ -+ var rv = undefined; -+ if (aElement.hasAttribute("onsyncfrompreference")) { -+ // Value changed, synthesize an event -+ try { -+ var event = document.createEvent("Events"); -+ event.initEvent("syncfrompreference", true, true); -+ var f = new Function ("event", -+ aElement.getAttribute("onsyncfrompreference")); -+ rv = f.call(aElement, event); -+ } -+ catch (e) { -+ Components.utils.reportError(e); -+ } -+ } -+ var val = rv !== undefined ? rv : (this.instantApply ? this.valueFromPreferences : this.value); -+ // if the preference is marked for reset, show default value in UI -+ if (val === undefined) -+ val = this.defaultValue; -+ -+ /** -+ * Initialize a UI element property with a value. Handles the case -+ * where an element has not yet had a XBL binding attached for it and -+ * the property setter does not yet exist by setting the same attribute -+ * on the XUL element using DOM apis and assuming the element's -+ * constructor or property getters appropriately handle this state. -+ */ -+ function setValue(element, attribute, value) { -+ if (attribute in element) -+ element[attribute] = value; -+ else -+ element.setAttribute(attribute, value); -+ } -+ if (aElement.localName == "checkbox" || -+ aElement.localName == "listitem") -+ setValue(aElement, "checked", val); -+ else if (aElement.localName == "colorpicker") -+ setValue(aElement, "color", val); -+ else if (aElement.localName == "textbox") { -+ // XXXmano Bug 303998: Avoid a caret placement issue if either the -+ // preference observer or its setter calls updateElements as a result -+ // of the input event handler. -+ if (aElement.value !== val) -+ setValue(aElement, "value", val); -+ } -+ else -+ setValue(aElement, "value", val); -+ ]]> -+ </body> -+ </method> -+ -+ <method name="getElementValue"> -+ <parameter name="aElement"/> -+ <body> -+ <![CDATA[ -+ if (aElement.hasAttribute("onsynctopreference")) { -+ // Value changed, synthesize an event -+ try { -+ var event = document.createEvent("Events"); -+ event.initEvent("synctopreference", true, true); -+ var f = new Function ("event", -+ aElement.getAttribute("onsynctopreference")); -+ var rv = f.call(aElement, event); -+ if (rv !== undefined) -+ return rv; -+ } -+ catch (e) { -+ Components.utils.reportError(e); -+ } -+ } -+ -+ /** -+ * Read the value of an attribute from an element, assuming the -+ * attribute is a property on the element's node API. If the property -+ * is not present in the API, then assume its value is contained in -+ * an attribute, as is the case before a binding has been attached. -+ */ -+ function getValue(element, attribute) { -+ if (attribute in element) -+ return element[attribute]; -+ return element.getAttribute(attribute); -+ } -+ if (aElement.localName == "checkbox" || -+ aElement.localName == "listitem") -+ var value = getValue(aElement, "checked"); -+ else if (aElement.localName == "colorpicker") -+ value = getValue(aElement, "color"); -+ else -+ value = getValue(aElement, "value"); -+ -+ switch (this.type) { -+ case "int": -+ return parseInt(value, 10) || 0; -+ case "bool": -+ return typeof(value) == "boolean" ? value : value == "true"; -+ } -+ return value; -+ ]]> -+ </body> -+ </method> -+ -+ <method name="isElementEditable"> -+ <parameter name="aElement"/> -+ <body> -+ <![CDATA[ -+ switch (aElement.localName) { -+ case "checkbox": -+ case "colorpicker": -+ case "radiogroup": -+ case "textbox": -+ case "listitem": -+ case "listbox": -+ case "menulist": -+ return true; -+ } -+ return aElement.getAttribute("preference-editable") == "true"; -+ ]]> -+ </body> -+ </method> -+ -+ <method name="updateElements"> -+ <body> -+ <![CDATA[ -+ if (!this.id) -+ return; -+ -+ // This "change" event handler tracks changes made to preferences by -+ // sources other than the user in this window. -+ var elements = document.getElementsByAttribute("preference", this.id); -+ for (var i = 0; i < elements.length; ++i) -+ this.setElementValue(elements[i]); -+ ]]> -+ </body> -+ </method> -+ </implementation> -+ -+ <handlers> -+ <handler event="change"> -+ this.updateElements(); -+ </handler> -+ </handlers> -+ </binding> -+ -+ <binding id="prefwindow" -+ extends="chrome://global/content/bindings/dialog.xml#dialog"> -+ <resources> -+ <stylesheet src="chrome://global/skin/preferences.css"/> -+ </resources> -+ <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY" -+ closebuttonlabel="&preferencesCloseButton.label;" -+ closebuttonaccesskey="&preferencesCloseButton.accesskey;" -+ role="dialog" -+#ifdef XP_WIN -+ title="&preferencesDefaultTitleWin.title;"> -+#else -+ title="&preferencesDefaultTitleMac.title;"> -+#endif -+ <xul:windowdragbox orient="vertical"> -+ <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar" -+ role="listbox"/> <!-- Expose to accessibility APIs as a listbox --> -+ </xul:windowdragbox> -+ <xul:hbox flex="1" class="paneDeckContainer"> -+ <xul:deck anonid="paneDeck" flex="1"> -+ <children includes="prefpane"/> -+ </xul:deck> -+ </xul:hbox> -+ <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons" pack="end"> -+#ifndef XP_UNIX -+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> -+ <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/> -+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> -+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> -+ <xul:spacer anonid="spacer" flex="1"/> -+ <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/> -+ <xul:button dlgtype="accept" class="dialog-button" icon="accept"/> -+#else -+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> -+ <xul:spacer anonid="spacer" flex="1"/> -+ <xul:button dlgtype="accept" class="dialog-button" icon="accept"/> -+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> -+ <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/> -+ <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/> -+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> -+#endif -+ </xul:hbox> -+ <xul:hbox> -+ <children/> -+ </xul:hbox> -+ </content> -+ <implementation implements="nsITimerCallback"> -+ <constructor> -+ <![CDATA[ -+ if (this.type != "child") { -+ if (!this._instantApplyInitialized) { -+ let psvc = Components.classes["@mozilla.org/preferences-service;1"] -+ .getService(Components.interfaces.nsIPrefBranch); -+ this.instantApply = psvc.getBoolPref("browser.preferences.instantApply"); -+ } -+ if (this.instantApply) { -+ var docElt = document.documentElement; -+ var acceptButton = docElt.getButton("accept"); -+ acceptButton.hidden = true; -+ var cancelButton = docElt.getButton("cancel"); -+#ifdef XP_MACOSX -+ // no buttons on Mac except Help -+ cancelButton.hidden = true; -+ // Move Help button to the end -+ document.getAnonymousElementByAttribute(this, "anonid", "spacer").hidden = true; -+ // Also, don't fire onDialogAccept on enter -+ acceptButton.disabled = true; -+#else -+ // morph the Cancel button into the Close button -+ cancelButton.setAttribute ("icon", "close"); -+ cancelButton.label = docElt.getAttribute("closebuttonlabel"); -+ cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey"); -+#endif -+ } -+ } -+ this.setAttribute("animated", this._shouldAnimate ? "true" : "false"); -+ var panes = this.preferencePanes; -+ -+ var lastPane = null; -+ if (this.lastSelected) { -+ lastPane = document.getElementById(this.lastSelected); -+ if (!lastPane) { -+ this.lastSelected = ""; -+ } -+ } -+ -+ var paneToLoad; -+ if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") { -+ paneToLoad = document.getElementById(window.arguments[0]); -+ this.lastSelected = paneToLoad.id; -+ } -+ else if (lastPane) -+ paneToLoad = lastPane; -+ else -+ paneToLoad = panes[0]; -+ -+ for (var i = 0; i < panes.length; ++i) { -+ this._makePaneButton(panes[i]); -+ if (panes[i].loaded) { -+ // Inline pane content, fire load event to force initialization. -+ this._fireEvent("paneload", panes[i]); -+ } -+ } -+ this.showPane(paneToLoad); -+ -+ if (panes.length == 1) -+ this._selector.setAttribute("collapsed", "true"); -+ ]]> -+ </constructor> -+ -+ <destructor> -+ <![CDATA[ -+ // Release timers to avoid reference cycles. -+ if (this._animateTimer) { -+ this._animateTimer.cancel(); -+ this._animateTimer = null; -+ } -+ if (this._fadeTimer) { -+ this._fadeTimer.cancel(); -+ this._fadeTimer = null; -+ } -+ ]]> -+ </destructor> -+ -+ <!-- Derived bindings can set this to true to cause us to skip -+ reading the browser.preferences.instantApply pref in the constructor. -+ Then they can set instantApply to their wished value. --> -+ <field name="_instantApplyInitialized">false</field> -+ <!-- Controls whether changed pref values take effect immediately. --> -+ <field name="instantApply">false</field> -+ -+ <property name="preferencePanes" -+ onget="return this.getElementsByTagName('prefpane');"/> -+ -+ <property name="type" onget="return this.getAttribute('type');"/> -+ <property name="_paneDeck" -+ onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/> -+ <property name="_paneDeckContainer" -+ onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/> -+ <property name="_selector" -+ onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/> -+ <property name="lastSelected" -+ onget="return this.getAttribute('lastSelected');"> -+ <setter> -+ this.setAttribute("lastSelected", val); -+ document.persist(this.id, "lastSelected"); -+ return val; -+ </setter> -+ </property> -+ <property name="currentPane" -+ onset="return this._currentPane = val;"> -+ <getter> -+ if (!this._currentPane) -+ this._currentPane = this.preferencePanes[0]; -+ -+ return this._currentPane; -+ </getter> -+ </property> -+ <field name="_currentPane">null</field> -+ -+ -+ <method name="_makePaneButton"> -+ <parameter name="aPaneElement"/> -+ <body> -+ <![CDATA[ -+ var radio = document.createElement("radio"); -+ radio.setAttribute("pane", aPaneElement.id); -+ radio.setAttribute("label", aPaneElement.label); -+ // Expose preference group choice to accessibility APIs as an unchecked list item -+ // The parent group is exposed to accessibility APIs as a list -+ if (aPaneElement.image) -+ radio.setAttribute("src", aPaneElement.image); -+ radio.style.listStyleImage = aPaneElement.style.listStyleImage; -+ this._selector.appendChild(radio); -+ return radio; -+ ]]> -+ </body> -+ </method> -+ -+ <method name="showPane"> -+ <parameter name="aPaneElement"/> -+ <body> -+ <![CDATA[ -+ if (!aPaneElement) -+ return; -+ -+ this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id); -+ if (!aPaneElement.loaded) { -+ let OverlayLoadObserver = function(aPane) -+ { -+ this._pane = aPane; -+ } -+ OverlayLoadObserver.prototype = { -+ _outer: this, -+ observe: function (aSubject, aTopic, aData) -+ { -+ this._pane.loaded = true; -+ this._outer._fireEvent("paneload", this._pane); -+ this._outer._selectPane(this._pane); -+ } -+ }; -+ -+ var obs = new OverlayLoadObserver(aPaneElement); -+ document.loadOverlay(aPaneElement.src, obs); -+ } -+ else -+ this._selectPane(aPaneElement); -+ ]]> -+ </body> -+ </method> -+ -+ <method name="_fireEvent"> -+ <parameter name="aEventName"/> -+ <parameter name="aTarget"/> -+ <body> -+ <![CDATA[ -+ // Panel loaded, synthesize a load event. -+ try { -+ var event = document.createEvent("Events"); -+ event.initEvent(aEventName, true, true); -+ var cancel = !aTarget.dispatchEvent(event); -+ if (aTarget.hasAttribute("on" + aEventName)) { -+ var fn = new Function ("event", aTarget.getAttribute("on" + aEventName)); -+ var rv = fn.call(aTarget, event); -+ if (rv == false) -+ cancel = true; -+ } -+ return !cancel; -+ } -+ catch (e) { -+ Components.utils.reportError(e); -+ } -+ return false; -+ ]]> -+ </body> -+ </method> -+ -+ <field name="_initialized">false</field> -+ <method name="_selectPane"> -+ <parameter name="aPaneElement"/> -+ <body> -+ <![CDATA[ -+#ifdef XP_MACOSX -+ var paneTitle = aPaneElement.label; -+ if (paneTitle != "") -+ document.title = paneTitle; -+#endif -+ var helpButton = document.documentElement.getButton("help"); -+ if (aPaneElement.helpTopic) -+ helpButton.hidden = false; -+ else -+ helpButton.hidden = true; -+ -+ // Find this pane's index in the deck and set the deck's -+ // selectedIndex to that value to switch to it. -+ var prefpanes = this.preferencePanes; -+ for (var i = 0; i < prefpanes.length; ++i) { -+ if (prefpanes[i] == aPaneElement) { -+ this._paneDeck.selectedIndex = i; -+ -+ if (this.type != "child") { -+ if (aPaneElement.hasAttribute("flex") && this._shouldAnimate && -+ prefpanes.length > 1) -+ aPaneElement.removeAttribute("flex"); -+ // Calling sizeToContent after the first prefpane is loaded -+ // will size the windows contents so style information is -+ // available to calculate correct sizing. -+ if (!this._initialized && prefpanes.length > 1) { -+ if (this._shouldAnimate) -+ this.style.minHeight = 0; -+ window.sizeToContent(); -+ } -+ -+ var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0]; -+ oldPane.selected = !(aPaneElement.selected = true); -+ this.lastSelected = aPaneElement.id; -+ this.currentPane = aPaneElement; -+ this._initialized = true; -+ -+ // Only animate if we've switched between prefpanes -+ if (this._shouldAnimate && oldPane.id != aPaneElement.id) { -+ aPaneElement.style.opacity = 0.0; -+ this.animate(oldPane, aPaneElement); -+ } -+ else if (!this._shouldAnimate && prefpanes.length > 1) { -+ var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer, "").height); -+ var verticalPadding = parseInt(window.getComputedStyle(aPaneElement, "").paddingTop); -+ verticalPadding += parseInt(window.getComputedStyle(aPaneElement, "").paddingBottom); -+ if (aPaneElement.contentHeight > targetHeight - verticalPadding) { -+ // To workaround the bottom border of a groupbox from being -+ // cutoff an hbox with a class of bottomBox may enclose it. -+ // This needs to include its padding to resize properly. -+ // See bug 394433 -+ var bottomPadding = 0; -+ var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0]; -+ if (bottomBox) -+ bottomPadding = parseInt(window.getComputedStyle(bottomBox, "").paddingBottom); -+ window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight; -+ } -+ -+ // XXX rstrong - extend the contents of the prefpane to -+ // prevent elements from being cutoff (see bug 349098). -+ if (aPaneElement.contentHeight + verticalPadding < targetHeight) -+ aPaneElement._content.style.height = targetHeight - verticalPadding + "px"; -+ } -+ } -+ break; -+ } -+ } -+ ]]> -+ </body> -+ </method> -+ -+ <property name="_shouldAnimate"> -+ <getter> -+ <![CDATA[ -+ var psvc = Components.classes["@mozilla.org/preferences-service;1"] -+ .getService(Components.interfaces.nsIPrefBranch); -+#ifdef XP_MACOSX -+ var animate = true; -+#else -+ var animate = false; -+#endif -+ try { -+ animate = psvc.getBoolPref("browser.preferences.animateFadeIn"); -+ } -+ catch (e) { } -+ return animate; -+ ]]> -+ </getter> -+ </property> -+ -+ <method name="animate"> -+ <parameter name="aOldPane"/> -+ <parameter name="aNewPane"/> -+ <body> -+ <![CDATA[ -+ // if we are already resizing, use currentHeight -+ var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight; -+ -+ this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1; -+ var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight); -+ this._animateRemainder = sizeDelta % this._animateIncrement; -+ -+ this._setUpAnimationTimer(oldHeight); -+ ]]> -+ </body> -+ </method> -+ -+ <property name="_sizeIncrement"> -+ <getter> -+ <![CDATA[ -+ var lastSelectedPane = document.getElementById(this.lastSelected); -+ var increment = this._animateIncrement * this._multiplier; -+ var newHeight = this._currentHeight + increment; -+ if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) || -+ (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight)) -+ return 0; -+ -+ if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) || -+ (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight)) -+ increment = this._animateRemainder * this._multiplier; -+ return increment; -+ ]]> -+ </getter> -+ </property> -+ -+ <method name="notify"> -+ <parameter name="aTimer"/> -+ <body> -+ <![CDATA[ -+ if (!document) -+ aTimer.cancel(); -+ -+ if (aTimer == this._animateTimer) { -+ var increment = this._sizeIncrement; -+ if (increment != 0) { -+ window.innerHeight += increment; -+ this._currentHeight += increment; -+ } -+ else { -+ aTimer.cancel(); -+ this._setUpFadeTimer(); -+ } -+ } else if (aTimer == this._fadeTimer) { -+ var elt = document.getElementById(this.lastSelected); -+ var newOpacity = parseFloat(window.getComputedStyle(elt, "").opacity) + this._fadeIncrement; -+ if (newOpacity < 1.0) -+ elt.style.opacity = newOpacity; -+ else { -+ aTimer.cancel(); -+ elt.style.opacity = 1.0; -+ } -+ } -+ ]]> -+ </body> -+ </method> -+ -+ <method name="_setUpAnimationTimer"> -+ <parameter name="aStartHeight"/> -+ <body> -+ <![CDATA[ -+ if (!this._animateTimer) -+ this._animateTimer = Components.classes["@mozilla.org/timer;1"] -+ .createInstance(Components.interfaces.nsITimer); -+ else -+ this._animateTimer.cancel(); -+ this._currentHeight = aStartHeight; -+ -+ this._animateTimer.initWithCallback(this, this._animateDelay, -+ Components.interfaces.nsITimer.TYPE_REPEATING_SLACK); -+ ]]> -+ </body> -+ </method> -+ -+ <method name="_setUpFadeTimer"> -+ <body> -+ <![CDATA[ -+ if (!this._fadeTimer) -+ this._fadeTimer = Components.classes["@mozilla.org/timer;1"] -+ .createInstance(Components.interfaces.nsITimer); -+ else -+ this._fadeTimer.cancel(); -+ -+ this._fadeTimer.initWithCallback(this, this._fadeDelay, -+ Components.interfaces.nsITimer.TYPE_REPEATING_SLACK); -+ ]]> -+ </body> -+ </method> -+ -+ <field name="_animateTimer">null</field> -+ <field name="_fadeTimer">null</field> -+ <field name="_animateDelay">15</field> -+ <field name="_animateIncrement">40</field> -+ <field name="_fadeDelay">5</field> -+ <field name="_fadeIncrement">0.40</field> -+ <field name="_animateRemainder">0</field> -+ <field name="_currentHeight">0</field> -+ <field name="_multiplier">0</field> -+ -+ <method name="addPane"> -+ <parameter name="aPaneElement"/> -+ <body> -+ <![CDATA[ -+ this.appendChild(aPaneElement); -+ -+ // Set up pane button -+ this._makePaneButton(aPaneElement); -+ ]]> -+ </body> -+ </method> -+ -+ <method name="openSubDialog"> -+ <parameter name="aURL"/> -+ <parameter name="aFeatures"/> -+ <parameter name="aParams"/> -+ <body> -+ return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams); -+ </body> -+ </method> -+ -+ <method name="openWindow"> -+ <parameter name="aWindowType"/> -+ <parameter name="aURL"/> -+ <parameter name="aFeatures"/> -+ <parameter name="aParams"/> -+ <body> -+ <![CDATA[ -+ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] -+ .getService(Components.interfaces.nsIWindowMediator); -+ var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null; -+ if (win) { -+ if ("initWithParams" in win) -+ win.initWithParams(aParams); -+ win.focus(); -+ } -+ else { -+ var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : ""); -+ var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener; -+ win = parentWindow.openDialog(aURL, "_blank", features, aParams); -+ } -+ return win; -+ ]]> -+ </body> -+ </method> -+ </implementation> -+ <handlers> -+ <handler event="dialogaccept"> -+ <![CDATA[ -+ if (!this._fireEvent("beforeaccept", this)){ -+ return false; -+ } -+ -+ var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"] -+ .getService(Components.interfaces.nsIScriptSecurityManager); -+ if (this.type == "child" && window.opener && -+ secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) { -+ var psvc = Components.classes["@mozilla.org/preferences-service;1"] -+ .getService(Components.interfaces.nsIPrefBranch); -+ var pdocEl = window.opener.document.documentElement; -+ if (pdocEl.instantApply) { -+ var panes = this.preferencePanes; -+ for (var i = 0; i < panes.length; ++i) -+ panes[i].writePreferences(true); -+ } -+ else { -+ // Clone all the preferences elements from the child document and -+ // insert them into the pane collection of the parent. -+ var pdoc = window.opener.document; -+ if (pdoc.documentElement.localName == "prefwindow") { -+ var currentPane = pdoc.documentElement.currentPane; -+ var id = window.location.href + "#childprefs"; -+ var childPrefs = pdoc.getElementById(id); -+ if (!childPrefs) { -+ var childPrefs = pdoc.createElement("preferences"); -+ currentPane.appendChild(childPrefs); -+ childPrefs.id = id; -+ } -+ var panes = this.preferencePanes; -+ for (var i = 0; i < panes.length; ++i) { -+ var preferences = panes[i].preferences; -+ for (var j = 0; j < preferences.length; ++j) { -+ // Try to find a preference element for the same preference. -+ var preference = null; -+ var parentPreferences = pdoc.getElementsByTagName("preferences"); -+ for (var k = 0; (k < parentPreferences.length && !preference); ++k) { -+ var parentPrefs = parentPreferences[k] -+ .getElementsByAttribute("name", preferences[j].name); -+ for (var l = 0; (l < parentPrefs.length && !preference); ++l) { -+ if (parentPrefs[l].localName == "preference") -+ preference = parentPrefs[l]; -+ } -+ } -+ if (!preference) { -+ // No matching preference in the parent window. -+ preference = pdoc.createElement("preference"); -+ childPrefs.appendChild(preference); -+ preference.name = preferences[j].name; -+ preference.type = preferences[j].type; -+ preference.inverted = preferences[j].inverted; -+ preference.readonly = preferences[j].readonly; -+ preference.disabled = preferences[j].disabled; -+ } -+ preference.value = preferences[j].value; -+ } -+ } -+ } -+ } -+ } -+ else { -+ var panes = this.preferencePanes; -+ for (var i = 0; i < panes.length; ++i) -+ panes[i].writePreferences(false); -+ -+ var psvc = Components.classes["@mozilla.org/preferences-service;1"] -+ .getService(Components.interfaces.nsIPrefService); -+ psvc.savePrefFile(null); -+ } -+ -+ return true; -+ ]]> -+ </handler> -+ <handler event="command"> -+ if (event.originalTarget.hasAttribute("pane")) { -+ var pane = document.getElementById(event.originalTarget.getAttribute("pane")); -+ this.showPane(pane); -+ } -+ </handler> -+ -+ <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing"> -+ <![CDATA[ -+ if (this.instantApply) -+ window.close(); -+ event.stopPropagation(); -+ event.preventDefault(); -+ ]]> -+ </handler> -+ -+ <handler event="keypress" -+#ifdef XP_MACOSX -+ key="&openHelpMac.commandkey;" modifiers="accel" -+#else -+ keycode="&openHelp.commandkey;" -+#endif -+ phase="capturing"> -+ <![CDATA[ -+ var helpButton = this.getButton("help"); -+ if (helpButton.disabled || helpButton.hidden) -+ return; -+ this._fireEvent("dialoghelp", this); -+ event.stopPropagation(); -+ event.preventDefault(); -+ ]]> -+ </handler> -+ </handlers> -+ </binding> -+ -+ <binding id="prefpane"> -+ <resources> -+ <stylesheet src="chrome://global/skin/preferences.css"/> -+ </resources> -+ <content> -+ <xul:vbox class="content-box" xbl:inherits="flex"> -+ <children/> -+ </xul:vbox> -+ </content> -+ <implementation> -+ <method name="writePreferences"> -+ <parameter name="aFlushToDisk"/> -+ <body> -+ <![CDATA[ -+ // Write all values to preferences. -+ if (this._deferredValueUpdateElements.size) { -+ this._finalizeDeferredElements(); -+ } -+ -+ var preferences = this.preferences; -+ for (var i = 0; i < preferences.length; ++i) { -+ var preference = preferences[i]; -+ preference.batching = true; -+ preference.valueFromPreferences = preference.value; -+ preference.batching = false; -+ } -+ if (aFlushToDisk) { -+ var psvc = Components.classes["@mozilla.org/preferences-service;1"] -+ .getService(Components.interfaces.nsIPrefService); -+ psvc.savePrefFile(null); -+ } -+ ]]> -+ </body> -+ </method> -+ -+ <property name="src" -+ onget="return this.getAttribute('src');" -+ onset="this.setAttribute('src', val); return val;"/> -+ <property name="selected" -+ onget="return this.getAttribute('selected') == 'true';" -+ onset="this.setAttribute('selected', val); return val;"/> -+ <property name="image" -+ onget="return this.getAttribute('image');" -+ onset="this.setAttribute('image', val); return val;"/> -+ <property name="label" -+ onget="return this.getAttribute('label');" -+ onset="this.setAttribute('label', val); return val;"/> -+ -+ <property name="preferenceElements" -+ onget="return this.getElementsByAttribute('preference', '*');"/> -+ <property name="preferences" -+ onget="return this.getElementsByTagName('preference');"/> -+ -+ <property name="helpTopic"> -+ <getter> -+ <![CDATA[ -+ // if there are tabs, and the selected tab provides a helpTopic, return that -+ var box = this.getElementsByTagName("tabbox"); -+ if (box[0]) { -+ var tab = box[0].selectedTab; -+ if (tab && tab.hasAttribute("helpTopic")) -+ return tab.getAttribute("helpTopic"); -+ } -+ -+ // otherwise, return the helpTopic of the current panel -+ return this.getAttribute("helpTopic"); -+ ]]> -+ </getter> -+ </property> -+ -+ <field name="_loaded">false</field> -+ <property name="loaded" -+ onget="return !this.src ? true : this._loaded;" -+ onset="this._loaded = val; return val;"/> -+ -+ <method name="preferenceForElement"> -+ <parameter name="aElement"/> -+ <body> -+ return document.getElementById(aElement.getAttribute("preference")); -+ </body> -+ </method> -+ -+ <method name="getPreferenceElement"> -+ <parameter name="aStartElement"/> -+ <body> -+ <![CDATA[ -+ var temp = aStartElement; -+ while (temp && temp.nodeType == Node.ELEMENT_NODE && -+ !temp.hasAttribute("preference")) -+ temp = temp.parentNode; -+ return temp.nodeType == Node.ELEMENT_NODE ? temp : aStartElement; -+ ]]> -+ </body> -+ </method> -+ -+ <field name="DeferredTask" readonly="true"> -+ let targetObj = {}; -+ Components.utils.import("resource://gre/modules/DeferredTask.jsm", targetObj); -+ targetObj.DeferredTask; -+ </field> -+ <method name="_deferredValueUpdate"> -+ <parameter name="aElement"/> -+ <body> -+ <![CDATA[ -+ delete aElement._deferredValueUpdateTask; -+ let preference = document.getElementById(aElement.getAttribute("preference")); -+ let prefVal = preference.getElementValue(aElement); -+ preference.value = prefVal; -+ this._deferredValueUpdateElements.delete(aElement); -+ ]]> -+ </body> -+ </method> -+ <field name="_deferredValueUpdateElements"> -+ new Set(); -+ </field> -+ <method name="_finalizeDeferredElements"> -+ <body> -+ <![CDATA[ -+ for (let el of this._deferredValueUpdateElements) { -+ if (el._deferredValueUpdateTask) { -+ el._deferredValueUpdateTask.finalize(); -+ } -+ } -+ ]]> -+ </body> -+ </method> -+ <method name="userChangedValue"> -+ <parameter name="aElement"/> -+ <body> -+ <![CDATA[ -+ let element = this.getPreferenceElement(aElement); -+ if (element.hasAttribute("preference")) { -+ if (element.getAttribute("delayprefsave") != "true") { -+ var preference = document.getElementById(element.getAttribute("preference")); -+ var prefVal = preference.getElementValue(element); -+ preference.value = prefVal; -+ } else { -+ if (!element._deferredValueUpdateTask) { -+ element._deferredValueUpdateTask = new this.DeferredTask(this._deferredValueUpdate.bind(this, element), 1000); -+ this._deferredValueUpdateElements.add(element); -+ } else { -+ // Each time the preference is changed, restart the delay. -+ element._deferredValueUpdateTask.disarm(); -+ } -+ element._deferredValueUpdateTask.arm(); -+ } -+ } -+ ]]> -+ </body> -+ </method> -+ -+ <property name="contentHeight"> -+ <getter> -+ var targetHeight = parseInt(window.getComputedStyle(this._content, "").height); -+ targetHeight += parseInt(window.getComputedStyle(this._content, "").marginTop); -+ targetHeight += parseInt(window.getComputedStyle(this._content, "").marginBottom); -+ return targetHeight; -+ </getter> -+ </property> -+ <field name="_content"> -+ document.getAnonymousElementByAttribute(this, "class", "content-box"); -+ </field> -+ </implementation> -+ <handlers> -+ <handler event="command"> -+ // This "command" event handler tracks changes made to preferences by -+ // the user in this window. -+ if (event.sourceEvent) -+ event = event.sourceEvent; -+ this.userChangedValue(event.target); -+ </handler> -+ <handler event="select"> -+ // This "select" event handler tracks changes made to colorpicker -+ // preferences by the user in this window. -+ if (event.target.localName == "colorpicker") -+ this.userChangedValue(event.target); -+ </handler> -+ <handler event="change"> -+ // This "change" event handler tracks changes made to preferences by -+ // the user in this window. -+ this.userChangedValue(event.target); -+ </handler> -+ <handler event="input"> -+ // This "input" event handler tracks changes made to preferences by -+ // the user in this window. -+ this.userChangedValue(event.target); -+ </handler> -+ <handler event="paneload"> -+ <![CDATA[ -+ // Initialize all values from preferences. -+ var elements = this.preferenceElements; -+ for (var i = 0; i < elements.length; ++i) { -+ try { -+ var preference = this.preferenceForElement(elements[i]); -+ preference.setElementValue(elements[i]); -+ } -+ catch (e) { -+ dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n"); -+ } -+ } -+ ]]> -+ </handler> -+ </handlers> -+ </binding> -+ -+ <binding id="panebutton" role="xul:listitem" -+ extends="chrome://global/content/bindings/radio.xml#radio"> -+ <resources> -+ <stylesheet src="chrome://global/skin/preferences.css"/> -+ </resources> -+ <content> -+ <xul:image class="paneButtonIcon" xbl:inherits="src"/> -+ <xul:label class="paneButtonLabel" xbl:inherits="value=label"/> -+ </content> -+ </binding> -+ -+</bindings> -+ -+# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -+# This Source Code Form is subject to the terms of the Mozilla Public -+# License, v. 2.0. If a copy of the MPL was not distributed with this -+# file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ -+# -+# This is PrefWindow 6. The Code Could Well Be Ready, Are You? -+# -+# Historical References: -+# PrefWindow V (February 1, 2003) -+# PrefWindow IV (April 24, 2000) -+# PrefWindow III (January 6, 2000) -+# PrefWindow II (???) -+# PrefWindow I (June 4, 1999) -+# -diff --git a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp ---- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp -+++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp -@@ -15,16 +15,17 @@ - #include "nsPrintfCString.h" - #include "nsNetCID.h" - #include "nsNetUtil.h" - #include "nsISupportsPrimitives.h" - #include "nsIGSettingsService.h" - #include "nsInterfaceHashtable.h" - #include "mozilla/Attributes.h" - #include "nsIURI.h" -+#include "nsKDEUtils.h" - - class nsUnixSystemProxySettings final : public nsISystemProxySettings { - public: - NS_DECL_ISUPPORTS - NS_DECL_NSISYSTEMPROXYSETTINGS - - nsUnixSystemProxySettings() - : mSchemeProxySettings(4) -@@ -39,16 +40,17 @@ private: - nsCOMPtr<nsIGSettingsService> mGSettings; - nsCOMPtr<nsIGSettingsCollection> mProxySettings; - nsInterfaceHashtable<nsCStringHashKey, nsIGSettingsCollection> mSchemeProxySettings; - bool IsProxyMode(const char* aMode); - nsresult SetProxyResultFromGConf(const char* aKeyBase, const char* aType, nsACString& aResult); - nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, int32_t aPort, nsACString& aResult); - nsresult GetProxyFromGSettings(const nsACString& aScheme, const nsACString& aHost, int32_t aPort, nsACString& aResult); - nsresult SetProxyResultFromGSettings(const char* aKeyBase, const char* aType, nsACString& aResult); -+ nsresult GetProxyFromKDE(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult); - }; - - NS_IMPL_ISUPPORTS(nsUnixSystemProxySettings, nsISystemProxySettings) - - NS_IMETHODIMP - nsUnixSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly) - { - // dbus prevents us from being threadsafe, but this routine should not block anyhow -@@ -505,16 +507,19 @@ nsUnixSystemProxySettings::GetProxyFromG - - nsresult - nsUnixSystemProxySettings::GetProxyForURI(const nsACString & aSpec, - const nsACString & aScheme, - const nsACString & aHost, - const int32_t aPort, - nsACString & aResult) - { -+ if (nsKDEUtils::kdeSupport()) -+ return GetProxyFromKDE(aScheme, aHost, aPort, aResult); -+ - if (mProxySettings) { - nsresult rv = GetProxyFromGSettings(aScheme, aHost, aPort, aResult); - if (NS_SUCCEEDED(rv)) - return rv; - } - if (mGConf) - return GetProxyFromGConf(aScheme, aHost, aPort, aResult); - -@@ -540,8 +545,34 @@ static const mozilla::Module::ContractID - - static const mozilla::Module kUnixProxyModule = { - mozilla::Module::kVersion, - kUnixProxyCIDs, - kUnixProxyContracts - }; - - NSMODULE_DEFN(nsUnixProxyModule) = &kUnixProxyModule; -+ -+nsresult -+nsUnixSystemProxySettings::GetProxyFromKDE(const nsACString& aScheme, -+ const nsACString& aHost, -+ PRInt32 aPort, -+ nsACString& aResult) -+{ -+ nsAutoCString url; -+ url = aScheme; -+ url += "://"; -+ url += aHost; -+ if( aPort >= 0 ) -+ { -+ url += ":"; -+ url += nsPrintfCString("%d", aPort); -+ } -+ nsTArray<nsCString> command; -+ command.AppendElement( NS_LITERAL_CSTRING( "GETPROXY" )); -+ command.AppendElement( url ); -+ nsTArray<nsCString> result; -+ if( !nsKDEUtils::command( command, &result ) || result.Length() != 1 ) -+ return NS_ERROR_FAILURE; -+ aResult = result[0]; -+ return NS_OK; -+} -+ -diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build ---- a/toolkit/xre/moz.build -+++ b/toolkit/xre/moz.build -@@ -48,17 +48,19 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'ui - elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt': - EXPORTS += ['nsQAppInstance.h'] - SOURCES += [ - '!moc_nsNativeAppSupportQt.cpp', - 'nsNativeAppSupportQt.cpp', - 'nsQAppInstance.cpp', - ] - elif CONFIG['MOZ_ENABLE_GTK']: -+ EXPORTS += ['nsKDEUtils.h'] - UNIFIED_SOURCES += [ -+ 'nsKDEUtils.cpp', - 'nsNativeAppSupportUnix.cpp', - ] - else: - UNIFIED_SOURCES += [ - 'nsNativeAppSupportDefault.cpp', - ] - - if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3': -diff --git a/toolkit/xre/nsKDEUtils.cpp b/toolkit/xre/nsKDEUtils.cpp -new file mode 100644 ---- /dev/null -+++ b/toolkit/xre/nsKDEUtils.cpp -@@ -0,0 +1,339 @@ -+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#include "nsKDEUtils.h" -+#include "nsIWidget.h" -+#include "nsISupportsPrimitives.h" -+#include "nsIMutableArray.h" -+#include "nsComponentManagerUtils.h" -+#include "nsArrayUtils.h" -+ -+#include <gtk/gtk.h> -+ -+#include <limits.h> -+#include <stdio.h> -+#include <sys/wait.h> -+#include <sys/resource.h> -+#include <unistd.h> -+#include <X11/Xlib.h> -+ -+//#define DEBUG_KDE -+#ifdef DEBUG_KDE -+#define KMOZILLAHELPER "kmozillahelper" -+#else -+// not need for lib64, it's a binary -+#define KMOZILLAHELPER "/usr/lib/mozilla/kmozillahelper" -+#endif -+ -+#define KMOZILLAHELPER_VERSION 6 -+#define MAKE_STR2( n ) #n -+#define MAKE_STR( n ) MAKE_STR2( n ) -+ -+static bool getKdeSession() -+ { -+ Display* dpy = XOpenDisplay( NULL ); -+ if( dpy == NULL ) -+ return false; -+ Atom kde_full_session = XInternAtom( dpy, "KDE_FULL_SESSION", True ); -+ bool kde = false; -+ if( kde_full_session != None ) -+ { -+ int cnt; -+ if( Atom* props = XListProperties( dpy, DefaultRootWindow( dpy ), &cnt )) -+ { -+ for( int i = 0; -+ i < cnt; -+ ++i ) -+ { -+ if( props[ i ] == kde_full_session ) -+ { -+ kde = true; -+#ifdef DEBUG_KDE -+ fprintf( stderr, "KDE SESSION %d\n", kde ); -+#endif -+ break; -+ } -+ } -+ XFree( props ); -+ } -+ } -+ XCloseDisplay( dpy ); -+ return kde; -+ } -+ -+static bool getKdeSupport() -+ { -+ nsTArray<nsCString> command; -+ command.AppendElement( NS_LITERAL_CSTRING( "CHECK" )); -+ command.AppendElement( NS_LITERAL_CSTRING( MAKE_STR( KMOZILLAHELPER_VERSION ))); -+ bool kde = nsKDEUtils::command( command ); -+#ifdef DEBUG_KDE -+ fprintf( stderr, "KDE RUNNING %d\n", kde ); -+#endif -+ return kde; -+ } -+ -+nsKDEUtils::nsKDEUtils() -+ : commandFile( NULL ) -+ , replyFile( NULL ) -+ { -+ } -+ -+nsKDEUtils::~nsKDEUtils() -+ { -+// closeHelper(); not actually useful, exiting will close the fd too -+ } -+ -+nsKDEUtils* nsKDEUtils::self() -+ { -+ static nsKDEUtils s; -+ return &s; -+ } -+ -+static bool helperRunning = false; -+static bool helperFailed = false; -+ -+bool nsKDEUtils::kdeSession() -+ { -+ static bool session = getKdeSession(); -+ return session; -+ } -+ -+bool nsKDEUtils::kdeSupport() -+ { -+ static bool support = kdeSession() && getKdeSupport(); -+ return support && helperRunning; -+ } -+ -+struct nsKDECommandData -+ { -+ FILE* file; -+ nsTArray<nsCString>* output; -+ GMainLoop* loop; -+ bool success; -+ }; -+ -+static gboolean kdeReadFunc( GIOChannel*, GIOCondition, gpointer data ) -+ { -+ nsKDECommandData* p = static_cast< nsKDECommandData* >( data ); -+ char buf[ 8192 ]; // TODO big enough -+ bool command_done = false; -+ bool command_failed = false; -+ while( !command_done && !command_failed && fgets( buf, 8192, p->file ) != NULL ) -+ { // TODO what if the kernel splits a line into two chunks? -+//#ifdef DEBUG_KDE -+// fprintf( stderr, "READ: %s %d\n", buf, feof( p->file )); -+//#endif -+ if( char* eol = strchr( buf, '\n' )) -+ *eol = '\0'; -+ command_done = ( strcmp( buf, "\\1" ) == 0 ); -+ command_failed = ( strcmp( buf, "\\0" ) == 0 ); -+ nsAutoCString line( buf ); -+ line.ReplaceSubstring( "\\n", "\n" ); -+ line.ReplaceSubstring( "\\" "\\", "\\" ); // \\ -> \ , i.e. unescape -+ if( p->output && !( command_done || command_failed )) -+ p->output->AppendElement( nsCString( buf )); // TODO utf8? -+ } -+ bool quit = false; -+ if( feof( p->file ) || command_failed ) -+ { -+ quit = true; -+ p->success = false; -+ } -+ if( command_done ) -+ { // reading one reply finished -+ quit = true; -+ p->success = true; -+ } -+ if( quit ) -+ { -+ if( p->loop ) -+ g_main_loop_quit( p->loop ); -+ return FALSE; -+ } -+ return TRUE; -+ } -+ -+bool nsKDEUtils::command( const nsTArray<nsCString>& command, nsTArray<nsCString>* output ) -+ { -+ return self()->internalCommand( command, NULL, false, output ); -+ } -+ -+bool nsKDEUtils::command( nsIArray* command, nsIArray** output) -+ { -+ nsTArray<nsCString> in; -+ PRUint32 length; -+ command->GetLength( &length ); -+ for ( PRUint32 i = 0; i < length; i++ ) -+ { -+ nsCOMPtr<nsISupportsCString> str = do_QueryElementAt( command, i ); -+ if( str ) -+ { -+ nsAutoCString s; -+ str->GetData( s ); -+ in.AppendElement( s ); -+ } -+ } -+ -+ nsTArray<nsCString> out; -+ bool ret = self()->internalCommand( in, NULL, false, &out ); -+ -+ if ( !output ) return ret; -+ -+ nsCOMPtr<nsIMutableArray> result = do_CreateInstance( NS_ARRAY_CONTRACTID ); -+ if ( !result ) return false; -+ -+ for ( PRUint32 i = 0; i < out.Length(); i++ ) -+ { -+ nsCOMPtr<nsISupportsCString> rstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); -+ if ( !rstr ) return false; -+ -+ rstr->SetData( out[i] ); -+ result->AppendElement( rstr, false ); -+ } -+ -+ NS_ADDREF( *output = result); -+ return ret; -+ } -+ -+ -+bool nsKDEUtils::commandBlockUi( const nsTArray<nsCString>& command, GtkWindow* parent, nsTArray<nsCString>* output ) -+ { -+ return self()->internalCommand( command, parent, true, output ); -+ } -+ -+bool nsKDEUtils::internalCommand( const nsTArray<nsCString>& command, GtkWindow* parent, bool blockUi, -+ nsTArray<nsCString>* output ) -+ { -+ if( !startHelper()) -+ return false; -+ feedCommand( command ); -+ // do not store the data in 'this' but in extra structure, just in case there -+ // is reentrancy (can there be? the event loop is re-entered) -+ nsKDECommandData data; -+ data.file = replyFile; -+ data.output = output; -+ data.success = false; -+ if( blockUi ) -+ { -+ data.loop = g_main_loop_new( NULL, FALSE ); -+ GtkWidget* window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); -+ if( parent && gtk_window_get_group(parent) ) -+ gtk_window_group_add_window( gtk_window_get_group(parent), GTK_WINDOW( window )); -+ gtk_widget_realize( window ); -+ gtk_widget_set_sensitive( window, TRUE ); -+ gtk_grab_add( window ); -+ GIOChannel* channel = g_io_channel_unix_new( fileno( data.file )); -+ g_io_add_watch( channel, static_cast< GIOCondition >( G_IO_IN | G_IO_ERR | G_IO_HUP ), kdeReadFunc, &data ); -+ g_io_channel_unref( channel ); -+ g_main_loop_run( data.loop ); -+ g_main_loop_unref( data.loop ); -+ gtk_grab_remove( window ); -+ gtk_widget_destroy( window ); -+ } -+ else -+ { -+ data.loop = NULL; -+ while( kdeReadFunc( NULL, static_cast< GIOCondition >( 0 ), &data )) -+ ; -+ } -+ return data.success; -+ } -+ -+bool nsKDEUtils::startHelper() -+ { -+ if( helperRunning ) -+ return true; -+ if( helperFailed ) -+ return false; -+ helperFailed = true; -+ int fdcommand[ 2 ]; -+ int fdreply[ 2 ]; -+ if( pipe( fdcommand ) < 0 ) -+ return false; -+ if( pipe( fdreply ) < 0 ) -+ { -+ close( fdcommand[ 0 ] ); -+ close( fdcommand[ 1 ] ); -+ return false; -+ } -+ char* args[ 2 ] = { const_cast< char* >( KMOZILLAHELPER ), NULL }; -+ switch( fork()) -+ { -+ case -1: -+ { -+ close( fdcommand[ 0 ] ); -+ close( fdcommand[ 1 ] ); -+ close( fdreply[ 0 ] ); -+ close( fdreply[ 1 ] ); -+ return false; -+ } -+ case 0: // child -+ { -+ if( dup2( fdcommand[ 0 ], STDIN_FILENO ) < 0 ) -+ _exit( 1 ); -+ if( dup2( fdreply[ 1 ], STDOUT_FILENO ) < 0 ) -+ _exit( 1 ); -+ int maxfd = 1024; // close all other fds -+ struct rlimit rl; -+ if( getrlimit( RLIMIT_NOFILE, &rl ) == 0 ) -+ maxfd = rl.rlim_max; -+ for( int i = 3; -+ i < maxfd; -+ ++i ) -+ close( i ); -+#ifdef DEBUG_KDE -+ execvp( KMOZILLAHELPER, args ); -+#else -+ execv( KMOZILLAHELPER, args ); -+#endif -+ _exit( 1 ); // failed -+ } -+ default: // parent -+ { -+ commandFile = fdopen( fdcommand[ 1 ], "w" ); -+ replyFile = fdopen( fdreply[ 0 ], "r" ); -+ close( fdcommand[ 0 ] ); -+ close( fdreply[ 1 ] ); -+ if( commandFile == NULL || replyFile == NULL ) -+ { -+ closeHelper(); -+ return false; -+ } -+ // ok, helper ready, getKdeRunning() will check if it works -+ } -+ } -+ helperFailed = false; -+ helperRunning = true; -+ return true; -+ } -+ -+void nsKDEUtils::closeHelper() -+ { -+ if( commandFile != NULL ) -+ fclose( commandFile ); // this will also make the helper quit -+ if( replyFile != NULL ) -+ fclose( replyFile ); -+ helperRunning = false; -+ } -+ -+void nsKDEUtils::feedCommand( const nsTArray<nsCString>& command ) -+ { -+ for( int i = 0; -+ i < command.Length(); -+ ++i ) -+ { -+ nsCString line = command[ i ]; -+ line.ReplaceSubstring( "\\", "\\" "\\" ); // \ -> \\ , i.e. escape -+ line.ReplaceSubstring( "\n", "\\n" ); -+#ifdef DEBUG_KDE -+ fprintf( stderr, "COMM: %s\n", line.get()); -+#endif -+ fputs( line.get(), commandFile ); -+ fputs( "\n", commandFile ); -+ } -+ fputs( "\\E\n", commandFile ); // done as \E, so it cannot happen in normal data -+ fflush( commandFile ); -+ } -diff --git a/toolkit/xre/nsKDEUtils.h b/toolkit/xre/nsKDEUtils.h -new file mode 100644 ---- /dev/null -+++ b/toolkit/xre/nsKDEUtils.h -@@ -0,0 +1,48 @@ -+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#ifndef nsKDEUtils_h__ -+#define nsKDEUtils_h__ -+ -+#include "nsStringGlue.h" -+#include "nsTArray.h" -+#include <stdio.h> -+ -+typedef struct _GtkWindow GtkWindow; -+ -+class nsIArray; -+ -+class NS_EXPORT nsKDEUtils -+ { -+ public: -+ /* Returns true if running inside a KDE session (regardless of whether there is KDE -+ support available for Firefox). This should be used e.g. when determining -+ dialog button order but not for code that requires the KDE support. */ -+ static bool kdeSession(); -+ /* Returns true if running inside a KDE session and KDE support is available -+ for Firefox. This should be used everywhere where the external helper is needed. */ -+ static bool kdeSupport(); -+ /* Executes the given helper command, returns true if helper returned success. */ -+ static bool command( const nsTArray<nsCString>& command, nsTArray<nsCString>* output = NULL ); -+ static bool command( nsIArray* command, nsIArray** output = NULL ); -+ /* Like command(), but additionally blocks the parent widget like if there was -+ a modal dialog shown and enters the event loop (i.e. there are still paint updates, -+ this is for commands that take long). */ -+ static bool commandBlockUi( const nsTArray<nsCString>& command, GtkWindow* parent, nsTArray<nsCString>* output = NULL ); -+ -+ private: -+ nsKDEUtils(); -+ ~nsKDEUtils(); -+ static nsKDEUtils* self(); -+ bool startHelper(); -+ void closeHelper(); -+ void feedCommand( const nsTArray<nsCString>& command ); -+ bool internalCommand( const nsTArray<nsCString>& command, GtkWindow* parent, bool isParent, -+ nsTArray<nsCString>* output ); -+ FILE* commandFile; -+ FILE* replyFile; -+ }; -+ -+#endif // nsKDEUtils -diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build ---- a/uriloader/exthandler/moz.build -+++ b/uriloader/exthandler/moz.build -@@ -72,17 +72,19 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'ui - else: - # These files can't be built in unified mode because they redefine LOG. - SOURCES += [ - osdir + '/nsOSHelperAppService.cpp', - ] - - if CONFIG['MOZ_ENABLE_GTK']: - UNIFIED_SOURCES += [ -+ 'unix/nsCommonRegistry.cpp', - 'unix/nsGNOMERegistry.cpp', -+ 'unix/nsKDERegistry.cpp', - 'unix/nsMIMEInfoUnix.cpp', - ] - elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': - UNIFIED_SOURCES += [ - 'android/nsAndroidHandlerApp.cpp', - 'android/nsExternalSharingAppService.cpp', - 'android/nsExternalURLHandlerService.cpp', - 'android/nsMIMEInfoAndroid.cpp', -@@ -125,16 +127,17 @@ include('/ipc/chromium/chromium-config.m - - FINAL_LIBRARY = 'xul' - - LOCAL_INCLUDES += [ - '/dom/base', - '/dom/ipc', - '/netwerk/base', - '/netwerk/protocol/http', -+ '/toolkit/xre', - ] - - if CONFIG['MOZ_ENABLE_DBUS']: - CXXFLAGS += CONFIG['TK_CFLAGS'] - CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS'] - - if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('qt', 'gtk2', 'gtk3'): - CXXFLAGS += CONFIG['TK_CFLAGS'] -diff --git a/uriloader/exthandler/unix/nsCommonRegistry.cpp b/uriloader/exthandler/unix/nsCommonRegistry.cpp -new file mode 100644 ---- /dev/null -+++ b/uriloader/exthandler/unix/nsCommonRegistry.cpp -@@ -0,0 +1,53 @@ -+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#include "nsCommonRegistry.h" -+ -+#include "nsGNOMERegistry.h" -+#include "nsKDERegistry.h" -+#include "nsString.h" -+#include "nsKDEUtils.h" -+ -+/* static */ bool -+nsCommonRegistry::HandlerExists(const char *aProtocolScheme) -+{ -+ if( nsKDEUtils::kdeSupport()) -+ return nsKDERegistry::HandlerExists( aProtocolScheme ); -+ return nsGNOMERegistry::HandlerExists( aProtocolScheme ); -+} -+ -+/* static */ nsresult -+nsCommonRegistry::LoadURL(nsIURI *aURL) -+{ -+ if( nsKDEUtils::kdeSupport()) -+ return nsKDERegistry::LoadURL( aURL ); -+ return nsGNOMERegistry::LoadURL( aURL ); -+} -+ -+/* static */ void -+nsCommonRegistry::GetAppDescForScheme(const nsACString& aScheme, -+ nsAString& aDesc) -+{ -+ if( nsKDEUtils::kdeSupport()) -+ return nsKDERegistry::GetAppDescForScheme( aScheme, aDesc ); -+ return nsGNOMERegistry::GetAppDescForScheme( aScheme, aDesc ); -+} -+ -+ -+/* static */ already_AddRefed<nsMIMEInfoBase> -+nsCommonRegistry::GetFromExtension(const nsACString& aFileExt) -+{ -+ if( nsKDEUtils::kdeSupport()) -+ return nsKDERegistry::GetFromExtension( aFileExt ); -+ return nsGNOMERegistry::GetFromExtension( aFileExt ); -+} -+ -+/* static */ already_AddRefed<nsMIMEInfoBase> -+nsCommonRegistry::GetFromType(const nsACString& aMIMEType) -+{ -+ if( nsKDEUtils::kdeSupport()) -+ return nsKDERegistry::GetFromType( aMIMEType ); -+ return nsGNOMERegistry::GetFromType( aMIMEType ); -+} -diff --git a/uriloader/exthandler/unix/nsCommonRegistry.h b/uriloader/exthandler/unix/nsCommonRegistry.h -new file mode 100644 ---- /dev/null -+++ b/uriloader/exthandler/unix/nsCommonRegistry.h -@@ -0,0 +1,28 @@ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#ifndef nsCommonRegistry_h__ -+#define nsCommonRegistry_h__ -+ -+#include "nsIURI.h" -+#include "nsCOMPtr.h" -+ -+class nsMIMEInfoBase; -+ -+class nsCommonRegistry -+{ -+ public: -+ static bool HandlerExists(const char *aProtocolScheme); -+ -+ static nsresult LoadURL(nsIURI *aURL); -+ -+ static void GetAppDescForScheme(const nsACString& aScheme, -+ nsAString& aDesc); -+ -+ static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt); -+ -+ static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType); -+}; -+ -+#endif -diff --git a/uriloader/exthandler/unix/nsKDERegistry.cpp b/uriloader/exthandler/unix/nsKDERegistry.cpp -new file mode 100644 ---- /dev/null -+++ b/uriloader/exthandler/unix/nsKDERegistry.cpp -@@ -0,0 +1,88 @@ -+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#include "nsKDERegistry.h" -+#include "prlink.h" -+#include "prmem.h" -+#include "nsString.h" -+#include "nsILocalFile.h" -+#include "nsMIMEInfoUnix.h" -+#include "nsAutoPtr.h" -+#include "nsKDEUtils.h" -+ -+/* static */ bool -+nsKDERegistry::HandlerExists(const char *aProtocolScheme) -+{ -+ nsTArray<nsCString> command; -+ command.AppendElement( NS_LITERAL_CSTRING( "HANDLEREXISTS" )); -+ command.AppendElement( nsAutoCString( aProtocolScheme )); -+ return nsKDEUtils::command( command ); -+} -+ -+/* static */ nsresult -+nsKDERegistry::LoadURL(nsIURI *aURL) -+{ -+ nsTArray<nsCString> command; -+ command.AppendElement( NS_LITERAL_CSTRING( "OPEN" )); -+ nsCString url; -+ aURL->GetSpec( url ); -+ command.AppendElement( url ); -+ bool rv = nsKDEUtils::command( command ); -+ if (!rv) -+ return NS_ERROR_FAILURE; -+ -+ return NS_OK; -+} -+ -+/* static */ void -+nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme, -+ nsAString& aDesc) -+{ -+ nsTArray<nsCString> command; -+ command.AppendElement( NS_LITERAL_CSTRING( "GETAPPDESCFORSCHEME" )); -+ command.AppendElement( aScheme ); -+ nsTArray<nsCString> output; -+ if( nsKDEUtils::command( command, &output ) && output.Length() == 1 ) -+ CopyUTF8toUTF16( output[ 0 ], aDesc ); -+} -+ -+ -+/* static */ already_AddRefed<nsMIMEInfoBase> -+nsKDERegistry::GetFromExtension(const nsACString& aFileExt) -+{ -+ NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot"); -+ nsTArray<nsCString> command; -+ command.AppendElement( NS_LITERAL_CSTRING( "GETFROMEXTENSION" )); -+ command.AppendElement( aFileExt ); -+ return GetFromHelper( command ); -+} -+ -+/* static */ already_AddRefed<nsMIMEInfoBase> -+nsKDERegistry::GetFromType(const nsACString& aMIMEType) -+{ -+ nsTArray<nsCString> command; -+ command.AppendElement( NS_LITERAL_CSTRING( "GETFROMTYPE" )); -+ command.AppendElement( aMIMEType ); -+ return GetFromHelper( command ); -+} -+ -+/* static */ already_AddRefed<nsMIMEInfoBase> -+nsKDERegistry::GetFromHelper(const nsTArray<nsCString>& command) -+{ -+ nsTArray<nsCString> output; -+ if( nsKDEUtils::command( command, &output ) && output.Length() == 3 ) -+ { -+ nsCString mimetype = output[ 0 ]; -+ RefPtr<nsMIMEInfoUnix> mimeInfo = new nsMIMEInfoUnix( mimetype ); -+ NS_ENSURE_TRUE(mimeInfo, nullptr); -+ nsCString description = output[ 1 ]; -+ mimeInfo->SetDescription(NS_ConvertUTF8toUTF16(description)); -+ nsCString handlerAppName = output[ 2 ]; -+ mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUTF16(handlerAppName)); -+ mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault); -+ return mimeInfo.forget(); -+ } -+ return nullptr; -+} -diff --git a/uriloader/exthandler/unix/nsKDERegistry.h b/uriloader/exthandler/unix/nsKDERegistry.h -new file mode 100644 ---- /dev/null -+++ b/uriloader/exthandler/unix/nsKDERegistry.h -@@ -0,0 +1,34 @@ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#ifndef nsKDERegistry_h__ -+#define nsKDERegistry_h__ -+ -+#include "nsIURI.h" -+#include "nsCOMPtr.h" -+#include "nsTArray.h" -+ -+class nsMIMEInfoBase; -+class nsAutoCString; -+class nsCString; -+ -+class nsKDERegistry -+{ -+ public: -+ static bool HandlerExists(const char *aProtocolScheme); -+ -+ static nsresult LoadURL(nsIURI *aURL); -+ -+ static void GetAppDescForScheme(const nsACString& aScheme, -+ nsAString& aDesc); -+ -+ static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt); -+ -+ static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType); -+ private: -+ static already_AddRefed<nsMIMEInfoBase> GetFromHelper(const nsTArray<nsCString>& command); -+ -+}; -+ -+#endif //nsKDERegistry_h__ -diff --git a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp ---- a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp -+++ b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp -@@ -7,32 +7,35 @@ - #ifdef MOZ_WIDGET_QT - #if (MOZ_ENABLE_CONTENTACTION) - #include <contentaction/contentaction.h> - #include "nsContentHandlerApp.h" - #endif - #endif - - #include "nsMIMEInfoUnix.h" --#include "nsGNOMERegistry.h" -+#include "nsCommonRegistry.h" - #include "nsIGIOService.h" - #include "nsNetCID.h" - #include "nsIIOService.h" - #include "nsAutoPtr.h" - #ifdef MOZ_ENABLE_DBUS - #include "nsDBusHandlerApp.h" - #endif - #ifdef MOZ_WIDGET_QT - #include "nsMIMEInfoQt.h" - #endif -+#if defined(XP_UNIX) && !defined(XP_MACOSX) -+#include "nsKDEUtils.h" -+#endif - - nsresult - nsMIMEInfoUnix::LoadUriInternal(nsIURI * aURI) - { -- nsresult rv = nsGNOMERegistry::LoadURL(aURI); -+ nsresult rv = nsCommonRegistry::LoadURL(aURI); - - #ifdef MOZ_WIDGET_QT - if (NS_FAILED(rv)) { - rv = nsMIMEInfoQt::LoadUriInternal(aURI); - } - #endif - - return rv; -@@ -45,24 +48,24 @@ nsMIMEInfoUnix::GetHasDefaultHandler(boo - // either /etc/mailcap or ${HOME}/.mailcap, in which case we don't want to - // give the GNOME answer. - if (mDefaultApplication) - return nsMIMEInfoImpl::GetHasDefaultHandler(_retval); - - *_retval = false; - - if (mClass == eProtocolInfo) { -- *_retval = nsGNOMERegistry::HandlerExists(mSchemeOrType.get()); -+ *_retval = nsCommonRegistry::HandlerExists(mSchemeOrType.get()); - } else { -- RefPtr<nsMIMEInfoBase> mimeInfo = nsGNOMERegistry::GetFromType(mSchemeOrType); -+ RefPtr<nsMIMEInfoBase> mimeInfo = nsCommonRegistry::GetFromType(mSchemeOrType); - if (!mimeInfo) { - nsAutoCString ext; - nsresult rv = GetPrimaryExtension(ext); - if (NS_SUCCEEDED(rv)) { -- mimeInfo = nsGNOMERegistry::GetFromExtension(ext); -+ mimeInfo = nsCommonRegistry::GetFromExtension(ext); - } - } - if (mimeInfo) - *_retval = true; - } - - if (*_retval) - return NS_OK; -@@ -97,16 +100,33 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(ns - ContentAction::Action::defaultActionForFile(uri, QString(mSchemeOrType.get())); - if (action.isValid()) { - action.trigger(); - return NS_OK; - } - return NS_ERROR_FAILURE; - #endif - -+ if( nsKDEUtils::kdeSupport()) { -+ bool supports; -+ if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) { -+ nsTArray<nsCString> command; -+ command.AppendElement( NS_LITERAL_CSTRING( "OPEN" )); -+ command.AppendElement( nativePath ); -+ command.AppendElement( NS_LITERAL_CSTRING( "MIMETYPE" )); -+ command.AppendElement( mSchemeOrType ); -+ if( nsKDEUtils::command( command )) -+ return NS_OK; -+ } -+ if (!mDefaultApplication) -+ return NS_ERROR_FILE_NOT_FOUND; -+ -+ return LaunchWithIProcess(mDefaultApplication, nativePath); -+ } -+ - nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); - if (!giovfs) { - return NS_ERROR_FAILURE; - } - - // nsGIOMimeApp->Launch wants a URI string instead of local file - nsresult rv; - nsCOMPtr<nsIIOService> ioservice = do_GetService(NS_IOSERVICE_CONTRACTID, &rv); -diff --git a/uriloader/exthandler/unix/nsOSHelperAppService.cpp b/uriloader/exthandler/unix/nsOSHelperAppService.cpp ---- a/uriloader/exthandler/unix/nsOSHelperAppService.cpp -+++ b/uriloader/exthandler/unix/nsOSHelperAppService.cpp -@@ -10,17 +10,17 @@ - #if defined(MOZ_ENABLE_CONTENTACTION) - #include <contentaction/contentaction.h> - #include <QString> - #endif - - #include "nsOSHelperAppService.h" - #include "nsMIMEInfoUnix.h" - #ifdef MOZ_WIDGET_GTK --#include "nsGNOMERegistry.h" -+#include "nsCommonRegistry.h" - #endif - #include "nsISupports.h" - #include "nsString.h" - #include "nsReadableUtils.h" - #include "nsUnicharUtils.h" - #include "nsXPIDLString.h" - #include "nsIURL.h" - #include "nsIFileStreams.h" -@@ -1146,26 +1146,26 @@ nsresult nsOSHelperAppService::OSProtoco - ContentAction::Action::defaultActionForScheme(QString(aProtocolScheme) + ':'); - - if (action.isValid()) - *aHandlerExists = true; - #endif - - #ifdef MOZ_WIDGET_GTK - // Check the GNOME registry for a protocol handler -- *aHandlerExists = nsGNOMERegistry::HandlerExists(aProtocolScheme); -+ *aHandlerExists = nsCommonRegistry::HandlerExists(aProtocolScheme); - #endif - - return NS_OK; - } - - NS_IMETHODIMP nsOSHelperAppService::GetApplicationDescription(const nsACString& aScheme, nsAString& _retval) - { - #ifdef MOZ_WIDGET_GTK -- nsGNOMERegistry::GetAppDescForScheme(aScheme, _retval); -+ nsCommonRegistry::GetAppDescForScheme(aScheme, _retval); - return _retval.IsEmpty() ? NS_ERROR_NOT_AVAILABLE : NS_OK; - #else - return NS_ERROR_NOT_AVAILABLE; - #endif - } - - nsresult nsOSHelperAppService::GetFileTokenForPath(const char16_t * platformAppPath, nsIFile ** aFile) - { -@@ -1252,17 +1252,17 @@ nsOSHelperAppService::GetFromExtension(c - mime_types_description, - true); - - if (NS_FAILED(rv) || majorType.IsEmpty()) { - - #ifdef MOZ_WIDGET_GTK - LOG(("Looking in GNOME registry\n")); - RefPtr<nsMIMEInfoBase> gnomeInfo = -- nsGNOMERegistry::GetFromExtension(aFileExt); -+ nsCommonRegistry::GetFromExtension(aFileExt); - if (gnomeInfo) { - LOG(("Got MIMEInfo from GNOME registry\n")); - return gnomeInfo.forget(); - } - #endif - - rv = LookUpTypeAndDescription(NS_ConvertUTF8toUTF16(aFileExt), - majorType, -@@ -1373,17 +1373,17 @@ nsOSHelperAppService::GetFromType(const - nsAutoString extensions, mime_types_description; - LookUpExtensionsAndDescription(majorType, - minorType, - extensions, - mime_types_description); - - #ifdef MOZ_WIDGET_GTK - if (handler.IsEmpty()) { -- RefPtr<nsMIMEInfoBase> gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType); -+ RefPtr<nsMIMEInfoBase> gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType); - if (gnomeInfo) { - LOG(("Got MIMEInfo from GNOME registry without extensions; setting them " - "to %s\n", NS_LossyConvertUTF16toASCII(extensions).get())); - - NS_ASSERTION(!gnomeInfo->HasExtensions(), "How'd that happen?"); - gnomeInfo->SetFileExtensions(NS_ConvertUTF16toUTF8(extensions)); - return gnomeInfo.forget(); - } -diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build ---- a/widget/gtk/moz.build -+++ b/widget/gtk/moz.build -@@ -86,16 +86,17 @@ else: - include('/ipc/chromium/chromium-config.mozbuild') - - FINAL_LIBRARY = 'xul' - - LOCAL_INCLUDES += [ - '/layout/generic', - '/layout/xul', - '/other-licenses/atk-1.0', -+ '/toolkit/xre', - '/widget', - ] - - if CONFIG['MOZ_X11']: - LOCAL_INCLUDES += [ - '/widget/x11', - ] - -diff --git a/widget/gtk/nsFilePicker.cpp b/widget/gtk/nsFilePicker.cpp ---- a/widget/gtk/nsFilePicker.cpp -+++ b/widget/gtk/nsFilePicker.cpp -@@ -4,32 +4,34 @@ - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - #include "mozilla/Types.h" - #include <sys/types.h> - #include <sys/stat.h> - #include <unistd.h> - - #include <gtk/gtk.h> -+#include <gdk/gdkx.h> - - #include "nsGtkUtils.h" - #include "nsIFileURL.h" - #include "nsIURI.h" - #include "nsIWidget.h" - #include "nsIFile.h" - #include "nsIStringBundle.h" - - #include "nsArrayEnumerator.h" - #include "nsMemory.h" - #include "nsEnumeratorUtils.h" - #include "nsNetUtil.h" - #include "nsReadableUtils.h" - #include "mozcontainer.h" - - #include "nsFilePicker.h" -+#include "nsKDEUtils.h" - - using namespace mozilla; - - #define MAX_PREVIEW_SIZE 180 - // bug 1184009 - #define MAX_PREVIEW_SOURCE_SIZE 4096 - - nsIFile *nsFilePicker::mPrevDisplayDirectory = nullptr; -@@ -246,17 +248,19 @@ nsFilePicker::AppendFilters(int32_t aFil - return nsBaseFilePicker::AppendFilters(aFilterMask); - } - - NS_IMETHODIMP - nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter) - { - if (aFilter.EqualsLiteral("..apps")) { - // No platform specific thing we can do here, really.... -- return NS_OK; -+ // Unless it's KDE. -+ if( mMode != modeOpen || !nsKDEUtils::kdeSupport()) -+ return NS_OK; - } - - nsAutoCString filter, name; - CopyUTF16toUTF8(aFilter, filter); - CopyUTF16toUTF8(aTitle, name); - - mFilters.AppendElement(filter); - mFilterNames.AppendElement(name); -@@ -371,16 +375,32 @@ nsFilePicker::Show(int16_t *aReturn) - - NS_IMETHODIMP - nsFilePicker::Open(nsIFilePickerShownCallback *aCallback) - { - // Can't show two dialogs concurrently with the same filepicker - if (mRunning) - return NS_ERROR_NOT_AVAILABLE; - -+ // KDE file picker is not handled via callback -+ if( nsKDEUtils::kdeSupport()) { -+ int16_t result; -+ mCallback = aCallback; -+ mRunning = true; -+ kdeFileDialog(&result); -+ if (mCallback) { -+ mCallback->Done(result); -+ mCallback = nullptr; -+ } else { -+ mResult = result; -+ } -+ mRunning = false; -+ return NS_OK; -+ } -+ - nsXPIDLCString title; - title.Adopt(ToNewUTF8String(mTitle)); - - GtkWindow *parent_widget = - GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)); - - GtkFileChooserAction action = GetGtkFileChooserAction(mMode); - const gchar *accept_button = (action == GTK_FILE_CHOOSER_ACTION_SAVE) -@@ -595,8 +615,235 @@ nsFilePicker::Done(GtkWidget* file_choos - if (mCallback) { - mCallback->Done(result); - mCallback = nullptr; - } else { - mResult = result; - } - NS_RELEASE_THIS(); - } -+ -+nsCString nsFilePicker::kdeMakeFilter( int index ) -+ { -+ nsCString buf = mFilters[ index ]; -+ for( PRUint32 i = 0; -+ i < buf.Length(); -+ ++i ) -+ if( buf[ i ] == ';' ) // KDE separates just using spaces -+ buf.SetCharAt( ' ', i ); -+ if (!mFilterNames[index].IsEmpty()) -+ { -+ buf += "|"; -+ buf += mFilterNames[index].get(); -+ } -+ return buf; -+ } -+ -+static PRInt32 windowToXid( nsIWidget* widget ) -+ { -+ GtkWindow *parent_widget = GTK_WINDOW(widget->GetNativeData(NS_NATIVE_SHELLWIDGET)); -+ GdkWindow* gdk_window = gtk_widget_get_window( gtk_widget_get_toplevel( GTK_WIDGET( parent_widget ))); -+ return GDK_WINDOW_XID( gdk_window ); -+ } -+ -+NS_IMETHODIMP nsFilePicker::kdeFileDialog(PRInt16 *aReturn) -+ { -+ NS_ENSURE_ARG_POINTER(aReturn); -+ -+ if( mMode == modeOpen && mFilters.Length() == 1 && mFilters[ 0 ].EqualsLiteral( "..apps" )) -+ return kdeAppsDialog( aReturn ); -+ -+ nsXPIDLCString title; -+ title.Adopt(ToNewUTF8String(mTitle)); -+ -+ const char* arg = NULL; -+ if( mAllowURLs ) -+ { -+ switch( mMode ) -+ { -+ case nsIFilePicker::modeOpen: -+ case nsIFilePicker::modeOpenMultiple: -+ arg = "GETOPENURL"; -+ break; -+ case nsIFilePicker::modeSave: -+ arg = "GETSAVEURL"; -+ break; -+ case nsIFilePicker::modeGetFolder: -+ arg = "GETDIRECTORYURL"; -+ break; -+ } -+ } -+ else -+ { -+ switch( mMode ) -+ { -+ case nsIFilePicker::modeOpen: -+ case nsIFilePicker::modeOpenMultiple: -+ arg = "GETOPENFILENAME"; -+ break; -+ case nsIFilePicker::modeSave: -+ arg = "GETSAVEFILENAME"; -+ break; -+ case nsIFilePicker::modeGetFolder: -+ arg = "GETDIRECTORYFILENAME"; -+ break; -+ } -+ } -+ -+ nsAutoCString directory; -+ if (mDisplayDirectory) { -+ mDisplayDirectory->GetNativePath(directory); -+ } else if (mPrevDisplayDirectory) { -+ mPrevDisplayDirectory->GetNativePath(directory); -+ } -+ -+ nsAutoCString startdir; -+ if (!directory.IsEmpty()) { -+ startdir = directory; -+ } -+ if (mMode == nsIFilePicker::modeSave) { -+ if( !startdir.IsEmpty()) -+ { -+ startdir += "/"; -+ startdir += ToNewUTF8String(mDefault); -+ } -+ else -+ startdir = ToNewUTF8String(mDefault); -+ } -+ if( startdir.IsEmpty()) -+ startdir = "."; -+ -+ nsAutoCString filters; -+ PRInt32 count = mFilters.Length(); -+ if( count == 0 ) //just in case -+ filters = "*"; -+ else -+ { -+ filters = kdeMakeFilter( 0 ); -+ for (PRInt32 i = 1; i < count; ++i) -+ { -+ filters += "\n"; -+ filters += kdeMakeFilter( i ); -+ } -+ } -+ -+ nsTArray<nsCString> command; -+ command.AppendElement( nsAutoCString( arg )); -+ command.AppendElement( startdir ); -+ if( mMode != nsIFilePicker::modeGetFolder ) -+ { -+ command.AppendElement( filters ); -+ nsAutoCString selected; -+ selected.AppendInt( mSelectedType ); -+ command.AppendElement( selected ); -+ } -+ command.AppendElement( title ); -+ if( mMode == nsIFilePicker::modeOpenMultiple ) -+ command.AppendElement( NS_LITERAL_CSTRING( "MULTIPLE" )); -+ if( PRInt32 xid = windowToXid( mParentWidget )) -+ { -+ command.AppendElement( NS_LITERAL_CSTRING( "PARENT" )); -+ nsAutoCString parent; -+ parent.AppendInt( xid ); -+ command.AppendElement( parent ); -+ } -+ -+ nsTArray<nsCString> output; -+ if( nsKDEUtils::commandBlockUi( command, GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)), &output )) -+ { -+ *aReturn = nsIFilePicker::returnOK; -+ mFiles.Clear(); -+ if( mMode != nsIFilePicker::modeGetFolder ) -+ { -+ mSelectedType = atoi( output[ 0 ].get()); -+ output.RemoveElementAt( 0 ); -+ } -+ if (mMode == nsIFilePicker::modeOpenMultiple) -+ { -+ mFileURL.Truncate(); -+ PRUint32 count = output.Length(); -+ for( PRUint32 i = 0; -+ i < count; -+ ++i ) -+ { -+ nsCOMPtr<nsIFile> localfile; -+ nsresult rv = NS_NewNativeLocalFile( output[ i ], -+ PR_FALSE, -+ getter_AddRefs(localfile)); -+ if (NS_SUCCEEDED(rv)) -+ mFiles.AppendObject(localfile); -+ } -+ } -+ else -+ { -+ if( output.Length() == 0 ) -+ mFileURL = nsCString(); -+ else if( mAllowURLs ) -+ mFileURL = output[ 0 ]; -+ else // GetFile() actually requires it to be url even for local files :-/ -+ { -+ mFileURL = nsCString( "file://" ); -+ mFileURL.Append( output[ 0 ] ); -+ } -+ } -+ // Remember last used directory. -+ nsCOMPtr<nsIFile> file; -+ GetFile(getter_AddRefs(file)); -+ if (file) { -+ nsCOMPtr<nsIFile> dir; -+ file->GetParent(getter_AddRefs(dir)); -+ nsCOMPtr<nsIFile> localDir(do_QueryInterface(dir)); -+ if (localDir) { -+ localDir.swap(mPrevDisplayDirectory); -+ } -+ } -+ if (mMode == nsIFilePicker::modeSave) -+ { -+ nsCOMPtr<nsIFile> file; -+ GetFile(getter_AddRefs(file)); -+ if (file) -+ { -+ bool exists = false; -+ file->Exists(&exists); -+ if (exists) // TODO do overwrite check in the helper app -+ *aReturn = nsIFilePicker::returnReplace; -+ } -+ } -+ } -+ else -+ { -+ *aReturn = nsIFilePicker::returnCancel; -+ } -+ return NS_OK; -+ } -+ -+ -+NS_IMETHODIMP nsFilePicker::kdeAppsDialog(PRInt16 *aReturn) -+ { -+ NS_ENSURE_ARG_POINTER(aReturn); -+ -+ nsXPIDLCString title; -+ title.Adopt(ToNewUTF8String(mTitle)); -+ -+ nsTArray<nsCString> command; -+ command.AppendElement( NS_LITERAL_CSTRING( "APPSDIALOG" )); -+ command.AppendElement( title ); -+ if( PRInt32 xid = windowToXid( mParentWidget )) -+ { -+ command.AppendElement( NS_LITERAL_CSTRING( "PARENT" )); -+ nsAutoCString parent; -+ parent.AppendInt( xid ); -+ command.AppendElement( parent ); -+ } -+ -+ nsTArray<nsCString> output; -+ if( nsKDEUtils::commandBlockUi( command, GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)), &output )) -+ { -+ *aReturn = nsIFilePicker::returnOK; -+ mFileURL = output.Length() > 0 ? output[ 0 ] : nsCString(); -+ } -+ else -+ { -+ *aReturn = nsIFilePicker::returnCancel; -+ } -+ return NS_OK; -+ } -+ -diff --git a/widget/gtk/nsFilePicker.h b/widget/gtk/nsFilePicker.h ---- a/widget/gtk/nsFilePicker.h -+++ b/widget/gtk/nsFilePicker.h -@@ -69,14 +69,20 @@ protected: - nsString mDefaultExtension; - - nsTArray<nsCString> mFilters; - nsTArray<nsCString> mFilterNames; - - private: - static nsIFile *mPrevDisplayDirectory; - -+ bool kdeRunning(); -+ bool getKdeRunning(); -+ NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn); -+ NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn); -+ nsCString kdeMakeFilter( int index ); -+ - #if (MOZ_WIDGET_GTK == 3) - GtkFileChooserWidget *mFileChooserDelegate; - #endif - }; - - #endif -diff --git a/xpcom/components/ManifestParser.cpp b/xpcom/components/ManifestParser.cpp ---- a/xpcom/components/ManifestParser.cpp -+++ b/xpcom/components/ManifestParser.cpp -@@ -35,16 +35,17 @@ - - #include "nsIConsoleService.h" - #include "nsIScriptError.h" - #include "nsIXULAppInfo.h" - #include "nsIXULRuntime.h" - #ifdef MOZ_B2G_LOADER - #include "mozilla/XPTInterfaceInfoManager.h" - #endif -+#include "nsKDEUtils.h" - - #ifdef MOZ_B2G_LOADER - #define XPTONLY_MANIFEST &nsComponentManagerImpl::XPTOnlyManifestManifest - #define XPTONLY_XPT &nsComponentManagerImpl::XPTOnlyManifestXPT - #else - #define XPTONLY_MANIFEST nullptr - #define XPTONLY_XPT nullptr - #endif -@@ -494,16 +495,17 @@ ParseManifest(NSLocationType aType, File - NS_NAMED_LITERAL_STRING(kRemoteEnabled, "remoteenabled"); - NS_NAMED_LITERAL_STRING(kRemoteRequired, "remoterequired"); - NS_NAMED_LITERAL_STRING(kApplication, "application"); - NS_NAMED_LITERAL_STRING(kAppVersion, "appversion"); - NS_NAMED_LITERAL_STRING(kGeckoVersion, "platformversion"); - NS_NAMED_LITERAL_STRING(kOs, "os"); - NS_NAMED_LITERAL_STRING(kOsVersion, "osversion"); - NS_NAMED_LITERAL_STRING(kABI, "abi"); -+ NS_NAMED_LITERAL_STRING(kDesktop, "desktop"); - NS_NAMED_LITERAL_STRING(kProcess, "process"); - #if defined(MOZ_WIDGET_ANDROID) - NS_NAMED_LITERAL_STRING(kTablet, "tablet"); - #endif - - NS_NAMED_LITERAL_STRING(kMain, "main"); - NS_NAMED_LITERAL_STRING(kContent, "content"); - -@@ -554,44 +556,49 @@ ParseManifest(NSLocationType aType, File - CopyUTF8toUTF16(s, abi); - abi.Insert(char16_t('_'), 0); - abi.Insert(osTarget, 0); - } - } - } - - nsAutoString osVersion; -+ nsAutoString desktop; - #if defined(XP_WIN) - #pragma warning(push) - #pragma warning(disable:4996) // VC12+ deprecates GetVersionEx - OSVERSIONINFO info = { sizeof(OSVERSIONINFO) }; - if (GetVersionEx(&info)) { - nsTextFormatter::ssprintf(osVersion, MOZ_UTF16("%ld.%ld"), - info.dwMajorVersion, - info.dwMinorVersion); - } -+ desktop = NS_LITERAL_STRING("win"); - #pragma warning(pop) - #elif defined(MOZ_WIDGET_COCOA) - SInt32 majorVersion = nsCocoaFeatures::OSXVersionMajor(); - SInt32 minorVersion = nsCocoaFeatures::OSXVersionMinor(); - nsTextFormatter::ssprintf(osVersion, MOZ_UTF16("%ld.%ld"), - majorVersion, - minorVersion); -+ desktop = NS_LITERAL_STRING("macosx"); - #elif defined(MOZ_WIDGET_GTK) - nsTextFormatter::ssprintf(osVersion, MOZ_UTF16("%ld.%ld"), - gtk_major_version, - gtk_minor_version); -+ desktop = nsKDEUtils::kdeSession() ? NS_LITERAL_STRING("kde") : NS_LITERAL_STRING("gnome"); - #elif defined(MOZ_WIDGET_ANDROID) - bool isTablet = false; - if (mozilla::AndroidBridge::Bridge()) { - mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", - "RELEASE", - osVersion); - isTablet = mozilla::widget::GeckoAppShell::IsTablet(); - } -+ desktop = NS_LITERAL_STRING("android"); - #endif - - if (XRE_IsContentProcess()) { - process = kContent; - } else { - process = kMain; - } - -@@ -694,25 +701,27 @@ ParseManifest(NSLocationType aType, File - TriState stOsVersion = eUnspecified; - TriState stOs = eUnspecified; - TriState stABI = eUnspecified; - TriState stProcess = eUnspecified; - #if defined(MOZ_WIDGET_ANDROID) - TriState stTablet = eUnspecified; - #endif - int flags = 0; -+ TriState stDesktop = eUnspecified; - - while ((token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && - ok) { - ToLowerCase(token); - NS_ConvertASCIItoUTF16 wtoken(token); - - if (CheckStringFlag(kApplication, wtoken, appID, stApp) || - CheckStringFlag(kOs, wtoken, osTarget, stOs) || - CheckStringFlag(kABI, wtoken, abi, stABI) || -+ CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) || - CheckStringFlag(kProcess, wtoken, process, stProcess) || - CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) || - CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) || - CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, stGeckoVersion)) { - continue; - } - - #if defined(MOZ_WIDGET_ANDROID) -@@ -762,16 +771,17 @@ ParseManifest(NSLocationType aType, File - } - - if (!ok || - stApp == eBad || - stAppVersion == eBad || - stGeckoVersion == eBad || - stOs == eBad || - stOsVersion == eBad || -+ stDesktop == eBad || - #ifdef MOZ_WIDGET_ANDROID - stTablet == eBad || - #endif - stABI == eBad || - stProcess == eBad) { - continue; - } - -diff --git a/xpcom/components/moz.build b/xpcom/components/moz.build ---- a/xpcom/components/moz.build -+++ b/xpcom/components/moz.build -@@ -47,12 +47,13 @@ FINAL_LIBRARY = 'xul' - GENERATED_INCLUDES += ['..'] - LOCAL_INCLUDES += [ - '../base', - '../build', - '../ds', - '../reflect/xptinfo', - '/chrome', - '/modules/libjar', -+ '/toolkit/xre' - ] - - if CONFIG['MOZ_WIDGET_GTK']: - CXXFLAGS += CONFIG['TK_CFLAGS'] -diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp ---- a/xpcom/io/nsLocalFileUnix.cpp -+++ b/xpcom/io/nsLocalFileUnix.cpp -@@ -47,16 +47,17 @@ - #include "prproces.h" - #include "nsIDirectoryEnumerator.h" - #include "nsISimpleEnumerator.h" - #include "private/pprio.h" - #include "prlink.h" - - #ifdef MOZ_WIDGET_GTK - #include "nsIGIOService.h" -+#include "nsKDEUtils.h" - #endif - - #ifdef MOZ_WIDGET_COCOA - #include <Carbon/Carbon.h> - #include "CocoaFileUtils.h" - #include "prmem.h" - #include "plbase64.h" - -@@ -1963,42 +1964,52 @@ nsLocalFile::SetPersistentDescriptor(con - return InitWithNativePath(aPersistentDescriptor); - #endif - } - - NS_IMETHODIMP - nsLocalFile::Reveal() - { - #ifdef MOZ_WIDGET_GTK -- nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); -- if (!giovfs) { -- return NS_ERROR_FAILURE; -- } -+ nsAutoCString url; - - bool isDirectory; - if (NS_FAILED(IsDirectory(&isDirectory))) { - return NS_ERROR_FAILURE; - } - -+ nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); - if (isDirectory) { -- return giovfs->ShowURIForInput(mPath); -+ url = mPath; - } else if (NS_SUCCEEDED(giovfs->OrgFreedesktopFileManager1ShowItems(mPath))) { - return NS_OK; - } else { - nsCOMPtr<nsIFile> parentDir; - nsAutoCString dirPath; - if (NS_FAILED(GetParent(getter_AddRefs(parentDir)))) { - return NS_ERROR_FAILURE; - } - if (NS_FAILED(parentDir->GetNativePath(dirPath))) { - return NS_ERROR_FAILURE; - } - -- return giovfs->ShowURIForInput(dirPath); -+ url = dirPath; - } -+ -+ if(nsKDEUtils::kdeSupport()) { -+ nsTArray<nsCString> command; -+ command.AppendElement( NS_LITERAL_CSTRING("REVEAL") ); -+ command.AppendElement( mPath ); -+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; -+ } -+ -+ if (!giovfs) -+ return NS_ERROR_FAILURE; -+ -+ return giovfs->ShowURIForInput(url); - #elif defined(MOZ_WIDGET_COCOA) - CFURLRef url; - if (NS_SUCCEEDED(GetCFURL(&url))) { - nsresult rv = CocoaFileUtils::RevealFileInFinder(url); - ::CFRelease(url); - return rv; - } - return NS_ERROR_FAILURE; -@@ -2006,16 +2017,22 @@ nsLocalFile::Reveal() - return NS_ERROR_FAILURE; - #endif - } - - NS_IMETHODIMP - nsLocalFile::Launch() - { - #ifdef MOZ_WIDGET_GTK -+ if( nsKDEUtils::kdeSupport()) { -+ nsTArray<nsCString> command; -+ command.AppendElement( NS_LITERAL_CSTRING("OPEN") ); -+ command.AppendElement( mPath ); -+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; -+ } - nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); - if (!giovfs) { - return NS_ERROR_FAILURE; - } - - return giovfs->ShowURIForInput(mPath); - #elif defined(MOZ_ENABLE_CONTENTACTION) - QUrl uri = QUrl::fromLocalFile(QString::fromUtf8(mPath.get()));