1 diff --git a/modules/libpref/src/Makefile.in b/modules/libpref/src/Makefile.in
2 --- a/modules/libpref/src/Makefile.in
3 +++ b/modules/libpref/src/Makefile.in
4 @@ -90,14 +90,16 @@ GREPREF_FILES = $(topsrcdir)/netwerk/bas
5 # Optimizer bug with GCC 3.2.2 on OS/2
7 nsPrefService.$(OBJ_SUFFIX): nsPrefService.cpp
10 $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS:-O2=-O1) $(_VPATH_SRCS)
13 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
16 greprefs.js: $(GREPREF_FILES)
17 $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $^ > $@
20 $(INSTALL) $^ $(DIST)/bin/
21 diff --git a/modules/libpref/src/nsPrefService.cpp b/modules/libpref/src/nsPrefService.cpp
22 --- a/modules/libpref/src/nsPrefService.cpp
23 +++ b/modules/libpref/src/nsPrefService.cpp
25 #include "nsIStringEnumerator.h"
26 #include "nsIZipReader.h"
27 #include "nsPrefBranch.h"
28 #include "nsXPIDLString.h"
30 #include "nsCOMArray.h"
31 #include "nsXPCOMCID.h"
32 #include "nsAutoPtr.h"
33 +#include "nsKDEUtils.h"
35 #include "nsQuickSort.h"
41 #include "prefapi_private_data.h"
42 @@ -758,30 +759,48 @@ pref_LoadPrefsInDir(nsIFile* aDir, char
45 static nsresult pref_LoadPrefsInDirList(const char *listId)
48 nsCOMPtr<nsIProperties> dirSvc(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
49 if (NS_FAILED(rv)) return rv;
51 + // make sure we load these special files after all the others
52 + static const char* specialFiles[] = {
58 + if (nsKDEUtils::kdeSession()) {
60 + i < NS_ARRAY_LENGTH(specialFiles);
62 + if (*specialFiles[ i ] == '\0') {
63 + specialFiles[ i ] = "kde.js";
69 nsCOMPtr<nsISimpleEnumerator> dirList;
71 NS_GET_IID(nsISimpleEnumerator),
72 getter_AddRefs(dirList));
75 while (NS_SUCCEEDED(dirList->HasMoreElements(&hasMore)) && hasMore) {
76 nsCOMPtr<nsISupports> elem;
77 dirList->GetNext(getter_AddRefs(elem));
79 nsCOMPtr<nsIFile> dir = do_QueryInterface(elem);
81 // Do we care if a file provided by this process fails to load?
82 - pref_LoadPrefsInDir(dir, nsnull, 0);
83 + pref_LoadPrefsInDir(dir, specialFiles, NS_ARRAY_LENGTH(specialFiles));
91 //----------------------------------------------------------------------------------------
92 @@ -876,24 +895,36 @@ static nsresult pref_InitInitialObjects(
93 /* these pref file names should not be used: we process them after all other application pref files for backwards compatibility */
94 static const char* specialFiles[] = {
95 #if defined(XP_MAC) || defined(XP_MACOSX)
99 #elif defined(XP_UNIX)
101 + , "" // placeholder for KDE (empty is otherwise harmless)
105 #elif defined(XP_OS2)
110 + if(nsKDEUtils::kdeSession()) { // TODO what if some setup actually requires the helper?
112 + i < NS_ARRAY_LENGTH(specialFiles);
114 + if( *specialFiles[ i ] == '\0' ) {
115 + specialFiles[ i ] = "kde.js";
121 rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, NS_ARRAY_LENGTH(specialFiles));
123 NS_WARNING("Error parsing application default preferences.");
126 rv = pref_LoadPrefsInDirList(NS_APP_PREFS_DEFAULTS_DIR_LIST);
127 NS_ENSURE_SUCCESS(rv, rv);
129 diff --git a/toolkit/components/downloads/Makefile.in b/toolkit/components/downloads/Makefile.in
130 --- a/toolkit/components/downloads/Makefile.in
131 +++ b/toolkit/components/downloads/Makefile.in
132 @@ -79,8 +79,10 @@ endif
138 include $(topsrcdir)/config/rules.mk
140 EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
142 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
143 diff --git a/toolkit/components/downloads/nsDownloadManager.cpp b/toolkit/components/downloads/nsDownloadManager.cpp
144 --- a/toolkit/components/downloads/nsDownloadManager.cpp
145 +++ b/toolkit/components/downloads/nsDownloadManager.cpp
148 #if defined(XP_WIN) && !defined(WINCE)
150 #ifdef DOWNLOAD_SCANNER
151 #include "nsDownloadScanner.h"
155 +#if defined(XP_UNIX) && !defined(XP_MACOSX)
156 +#include "nsKDEUtils.h"
160 #include <CoreFoundation/CoreFoundation.h>
164 #include "AndroidBridge.h"
167 @@ -2203,16 +2207,25 @@ nsDownload::SetState(DownloadState aStat
168 nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID));
170 // Master pref to control this function.
171 PRBool showTaskbarAlert = PR_TRUE;
173 pref->GetBoolPref(PREF_BDM_SHOWALERTONCOMPLETE, &showTaskbarAlert);
175 if (showTaskbarAlert) {
176 + if( nsKDEUtils::kdeSupport()) {
177 + nsCStringArray command;
178 + command.AppendCString( NS_LITERAL_CSTRING( "DOWNLOADFINISHED" ));
179 + nsAutoString displayName;
180 + GetDisplayName( displayName );
181 + command.AppendCString( nsCAutoString( ToNewUTF8String( displayName )));
182 + nsKDEUtils::command( command );
184 + // begin non-KDE block
185 PRInt32 alertInterval = 2000;
187 pref->GetIntPref(PREF_BDM_SHOWALERTINTERVAL, &alertInterval);
189 PRInt64 alertIntervalUSec = alertInterval * PR_USEC_PER_MSEC;
190 PRInt64 goat = PR_Now() - mStartTime;
191 showTaskbarAlert = goat > alertIntervalUSec;
193 @@ -2236,18 +2249,19 @@ nsDownload::SetState(DownloadState aStat
194 // If downloads are automatically removed per the user's
195 // retention policy, there's no reason to make the text clickable
196 // because if it is, they'll click open the download manager and
197 // the items they downloaded will have been removed.
198 alerts->ShowAlertNotification(
199 NS_LITERAL_STRING(DOWNLOAD_MANAGER_ALERT_ICON), title,
200 message, !removeWhenDone, EmptyString(), mDownloadManager,
205 + } // end non-KDE block
208 #if (defined(XP_WIN) && !defined(WINCE)) || defined(XP_MACOSX) || defined(ANDROID)
209 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mTarget);
210 nsCOMPtr<nsIFile> file;
214 diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn
215 --- a/toolkit/content/jar.mn
216 +++ b/toolkit/content/jar.mn
217 @@ -40,29 +40,33 @@ toolkit.jar:
218 *+ content/global/viewZoomOverlay.js (viewZoomOverlay.js)
219 *+ content/global/bindings/autocomplete.xml (widgets/autocomplete.xml)
220 *+ content/global/bindings/browser.xml (widgets/browser.xml)
221 *+ content/global/bindings/button.xml (widgets/button.xml)
222 *+ content/global/bindings/checkbox.xml (widgets/checkbox.xml)
223 *+ content/global/bindings/colorpicker.xml (widgets/colorpicker.xml)
224 *+ content/global/bindings/datetimepicker.xml (widgets/datetimepicker.xml)
225 *+ content/global/bindings/dialog.xml (widgets/dialog.xml)
226 +*+ content/global/bindings/dialog-kde.xml (widgets/dialog-kde.xml)
227 +% override chrome://global/content/bindings/dialog.xml chrome://global/content/bindings/dialog-kde.xml desktop=kde
228 *+ content/global/bindings/editor.xml (widgets/editor.xml)
229 * content/global/bindings/expander.xml (widgets/expander.xml)
230 * content/global/bindings/filefield.xml (widgets/filefield.xml)
231 *+ content/global/bindings/findbar.xml (widgets/findbar.xml)
232 *+ content/global/bindings/general.xml (widgets/general.xml)
233 *+ content/global/bindings/groupbox.xml (widgets/groupbox.xml)
234 *+ content/global/bindings/listbox.xml (widgets/listbox.xml)
235 *+ content/global/bindings/menu.xml (widgets/menu.xml)
236 *+ content/global/bindings/menulist.xml (widgets/menulist.xml)
237 *+ content/global/bindings/notification.xml (widgets/notification.xml)
238 *+ content/global/bindings/numberbox.xml (widgets/numberbox.xml)
239 *+ content/global/bindings/popup.xml (widgets/popup.xml)
240 *+ content/global/bindings/preferences.xml (widgets/preferences.xml)
241 +*+ content/global/bindings/preferences-kde.xml (widgets/preferences-kde.xml)
242 +% override chrome://global/content/bindings/preferences.xml chrome://global/content/bindings/preferences-kde.xml desktop=kde
243 *+ content/global/bindings/progressmeter.xml (widgets/progressmeter.xml)
244 *+ content/global/bindings/radio.xml (widgets/radio.xml)
245 *+ content/global/bindings/resizer.xml (widgets/resizer.xml)
246 *+ content/global/bindings/richlistbox.xml (widgets/richlistbox.xml)
247 *+ content/global/bindings/scale.xml (widgets/scale.xml)
248 *+ content/global/bindings/scrollbar.xml (widgets/scrollbar.xml)
249 *+ content/global/bindings/scrollbox.xml (widgets/scrollbox.xml)
250 *+ content/global/bindings/splitter.xml (widgets/splitter.xml)
251 diff --git a/toolkit/content/widgets/dialog-kde.xml b/toolkit/content/widgets/dialog-kde.xml
254 +++ b/toolkit/content/widgets/dialog-kde.xml
256 +<?xml version="1.0"?>
258 +<bindings id="dialogBindings"
259 + xmlns="http://www.mozilla.org/xbl"
260 + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
261 + xmlns:xbl="http://www.mozilla.org/xbl">
263 + <binding id="dialog" extends="chrome://global/content/bindings/general.xml#root-element">
265 + <stylesheet src="chrome://global/skin/dialog.css"/>
268 + <xul:vbox class="box-inherit dialog-content-box" flex="1">
272 + <xul:hbox class="dialog-button-box" anonid="buttons"
273 + xbl:inherits="pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient"
274 +#ifdef XP_UNIX_GNOME
276 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
277 + <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
278 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
279 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
280 + <xul:spacer anonid="spacer" flex="1"/>
281 + <xul:button dlgtype="cancel" class="dialog-button"/>
282 + <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
285 + <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
286 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
287 + <xul:spacer anonid="spacer" flex="1" hidden="true"/>
288 + <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
289 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
290 + <xul:button dlgtype="cancel" class="dialog-button"/>
291 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
294 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
295 + <xul:spacer anonid="spacer" flex="1" hidden="true"/>
296 + <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
297 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
298 + <xul:button dlgtype="cancel" class="dialog-button"/>
299 + <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
300 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
306 + <field name="_mStrBundle">null</field>
307 + <field name="_closeHandler">(function(event) {
308 + if (!document.documentElement.cancelDialog())
309 + event.preventDefault();
312 + <property name="buttons"
313 + onget="return this.getAttribute('buttons');"
314 + onset="this._configureButtons(val); return val;"/>
316 + <property name="defaultButton">
319 + if (this.hasAttribute("defaultButton"))
320 + return this.getAttribute("defaultButton");
321 + else // default to the accept button
327 + this._setDefaultButton(val);
333 + <method name="acceptDialog">
336 + return this._doButtonCommand("accept");
341 + <method name="cancelDialog">
344 + return this._doButtonCommand("cancel");
349 + <method name="getButton">
350 + <parameter name="aDlgType"/>
353 + return this._buttons[aDlgType];
358 + <method name="moveToAlertPosition">
361 + // hack. we need this so the window has something like its final size
362 + if (window.outerWidth == 1) {
363 + dump("Trying to position a sizeless window; caller should have called sizeToContent() or sizeTo(). See bug 75649.\n");
367 + var xOffset = (opener.outerWidth - window.outerWidth) / 2;
368 + var yOffset = opener.outerHeight / 5;
370 + var newX = opener.screenX + xOffset;
371 + var newY = opener.screenY + yOffset;
373 + // ensure the window is fully onscreen (if smaller than the screen)
374 + if (newX < screen.availLeft)
375 + newX = screen.availLeft + 20;
376 + if ((newX + window.outerWidth) > (screen.availLeft + screen.availWidth))
377 + newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20;
379 + if (newY < screen.availTop)
380 + newY = screen.availTop + 20;
381 + if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight))
382 + newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60;
384 + window.moveTo( newX, newY );
389 + <method name="centerWindowOnScreen">
392 + var xOffset = screen.availWidth/2 - window.outerWidth/2;
393 + var yOffset = screen.availHeight/2 - window.outerHeight/2; //(opener.outerHeight *2)/10;
395 + xOffset = xOffset > 0 ? xOffset : 0;
396 + yOffset = yOffset > 0 ? yOffset : 0;
397 + window.moveTo(xOffset, yOffset);
404 + this._configureButtons(this.buttons);
406 + // listen for when window is closed via native close buttons
407 + window.addEventListener("close", this._closeHandler, false);
409 + // for things that we need to initialize after onload fires
410 + window.addEventListener("load", this.postLoadInit, false);
412 + window.moveToAlertPosition = this.moveToAlertPosition;
413 + window.centerWindowOnScreen = this.centerWindowOnScreen;
417 + <method name="postLoadInit">
418 + <parameter name="aEvent"/>
421 + function focusInit() {
422 + const dialog = document.documentElement;
423 + const defaultButton = dialog.getButton(dialog.defaultButton);
424 + // give focus to the first focusable element in the dialog
425 + if (!document.commandDispatcher.focusedElement) {
426 + document.commandDispatcher.advanceFocusIntoSubtree(dialog);
428 + var focusedElt = document.commandDispatcher.focusedElement;
430 + var initialFocusedElt = focusedElt;
431 + while (focusedElt.localName == "tab" ||
432 + focusedElt.getAttribute("noinitialfocus") == "true") {
433 + document.commandDispatcher.advanceFocusIntoSubtree(focusedElt);
434 + focusedElt = document.commandDispatcher.focusedElement;
435 + if (focusedElt == initialFocusedElt)
439 + if (initialFocusedElt.localName == "tab") {
440 + if (focusedElt.hasAttribute("dlgtype")) {
441 + // We don't want to focus on anonymous OK, Cancel, etc. buttons,
442 + // so return focus to the tab itself
443 + initialFocusedElt.focus();
447 + else if (focusedElt.hasAttribute("dlgtype") && focusedElt != defaultButton) {
448 + defaultButton.focus();
456 + window.notifyDefaultButtonLoaded(defaultButton);
460 + // Give focus after onload completes, see bug 103197.
461 + setTimeout(focusInit, 0);
466 + <property name="mStrBundle">
469 + if (!this._mStrBundle) {
470 + // need to create string bundle manually instead of using <xul:stringbundle/>
471 + // see bug 63370 for details
472 + this._mStrBundle = Components.classes["@mozilla.org/intl/stringbundle;1"]
473 + .getService(Components.interfaces.nsIStringBundleService)
474 + .createBundle("chrome://global/locale/dialog.properties");
476 + return this._mStrBundle;
480 + <method name="_configureButtons">
481 + <parameter name="aButtons"/>
484 + // by default, get all the anonymous button elements
486 + this._buttons = buttons;
487 + buttons.accept = document.getAnonymousElementByAttribute(this, "dlgtype", "accept");
488 + buttons.cancel = document.getAnonymousElementByAttribute(this, "dlgtype", "cancel");
489 + buttons.extra1 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra1");
490 + buttons.extra2 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra2");
491 + buttons.help = document.getAnonymousElementByAttribute(this, "dlgtype", "help");
492 + buttons.disclosure = document.getAnonymousElementByAttribute(this, "dlgtype", "disclosure");
494 + // look for any overriding explicit button elements
495 + var exBtns = this.getElementsByAttribute("dlgtype", "*");
498 + for (i = 0; i < exBtns.length; ++i) {
499 + dlgtype = exBtns[i].getAttribute("dlgtype");
500 + buttons[dlgtype].hidden = true; // hide the anonymous button
501 + buttons[dlgtype] = exBtns[i];
504 + // add the label and oncommand handler to each button
505 + for (dlgtype in buttons) {
506 + var button = buttons[dlgtype];
507 + button.addEventListener("command", this._handleButtonCommand, true);
509 + // don't override custom labels with pre-defined labels on explicit buttons
510 + if (!button.hasAttribute("label")) {
511 + // dialog attributes override the default labels in dialog.properties
512 + if (this.hasAttribute("buttonlabel"+dlgtype)) {
513 + button.setAttribute("label", this.getAttribute("buttonlabel"+dlgtype));
514 + if (this.hasAttribute("buttonaccesskey"+dlgtype))
515 + button.setAttribute("accesskey", this.getAttribute("buttonaccesskey"+dlgtype));
516 + } else if (dlgtype != "extra1" && dlgtype != "extra2") {
517 + button.setAttribute("label", this.mStrBundle.GetStringFromName("button-"+dlgtype));
518 + var accessKey = this.mStrBundle.GetStringFromName("accesskey-"+dlgtype);
520 + button.setAttribute("accesskey", accessKey);
523 + // allow specifying alternate icons in the dialog header
524 + if (!button.hasAttribute("icon")) {
525 + // if there's an icon specified, use that
526 + if (this.hasAttribute("buttonicon"+dlgtype))
527 + button.setAttribute("icon", this.getAttribute("buttonicon"+dlgtype));
528 + // otherwise set defaults
532 + button.setAttribute("icon","accept");
535 + button.setAttribute("icon","cancel");
538 + button.setAttribute("icon","properties");
541 + button.setAttribute("icon","help");
549 + // ensure that hitting enter triggers the default button command
550 + this.defaultButton = this.defaultButton;
552 + // if there is a special button configuration, use it
554 + // expect a comma delimited list of dlgtype values
555 + var list = aButtons.split(",");
557 + // mark shown dlgtypes as true
558 + var shown = { accept: false, cancel: false, help: false,
559 + disclosure: false, extra1: false, extra2: false };
560 + for (i = 0; i < list.length; ++i)
561 + shown[list[i].replace(/ /g, "")] = true;
563 + // hide/show the buttons we want
564 + for (dlgtype in buttons)
565 + buttons[dlgtype].hidden = !shown[dlgtype];
568 +# show the spacer on Windows only when the extra2 button is present
569 + var spacer = document.getAnonymousElementByAttribute(this, "anonid", "spacer");
570 + spacer.removeAttribute("hidden");
571 + spacer.setAttribute("flex", shown["extra2"]?"1":"0");
579 + <method name="_setDefaultButton">
580 + <parameter name="aNewDefault"/>
583 + // remove the default attribute from the previous default button, if any
584 + var oldDefaultButton = this.getButton(this.defaultButton);
585 + if (oldDefaultButton)
586 + oldDefaultButton.removeAttribute("default");
588 + var newDefaultButton = this.getButton(aNewDefault);
589 + if (newDefaultButton) {
590 + this.setAttribute("defaultButton", aNewDefault);
591 + newDefaultButton.setAttribute("default", "true");
594 + this.setAttribute("defaultButton", "none");
595 + if (aNewDefault != "none")
596 + dump("invalid new default button: " + aNewDefault + ", assuming: none\n");
602 + <method name="_handleButtonCommand">
603 + <parameter name="aEvent"/>
606 + return document.documentElement._doButtonCommand(
607 + aEvent.target.getAttribute("dlgtype"));
612 + <method name="_doButtonCommand">
613 + <parameter name="aDlgType"/>
616 + var button = this.getButton(aDlgType);
617 + if (!button.disabled) {
618 + var noCancel = this._fireButtonEvent(aDlgType);
620 + if (aDlgType == "accept" || aDlgType == "cancel")
630 + <method name="_fireButtonEvent">
631 + <parameter name="aDlgType"/>
634 + var event = document.createEvent("Events");
635 + event.initEvent("dialog"+aDlgType, true, true);
637 + // handle dom event handlers
638 + var noCancel = this.dispatchEvent(event);
640 + // handle any xml attribute event handlers
641 + var handler = this.getAttribute("ondialog"+aDlgType);
642 + if (handler != "") {
643 + var fn = new Function("event", handler);
644 + var returned = fn(event);
645 + if (returned == false)
654 + <method name="_hitEnter">
655 + <parameter name="evt"/>
658 + if (evt.getPreventDefault())
661 + var btn = this.getButton(this.defaultButton);
663 + this._doButtonCommand(this.defaultButton);
671 + <handler event="keypress" keycode="VK_ENTER"
672 + group="system" action="this._hitEnter(event);"/>
673 + <handler event="keypress" keycode="VK_RETURN"
674 + group="system" action="this._hitEnter(event);"/>
675 + <handler event="keypress" keycode="VK_ESCAPE" group="system">
676 + if (!event.getPreventDefault())
677 + this.cancelDialog();
680 + <handler event="keypress" key="." modifiers="meta" phase="capturing" action="this.cancelDialog();"/>
682 + <handler event="focus" phase="capturing">
683 + var btn = this.getButton(this.defaultButton);
685 + btn.setAttribute("default", event.originalTarget == btn || !(event.originalTarget instanceof Components.interfaces.nsIDOMXULButtonElement));
692 + <binding id="dialogheader">
694 + <stylesheet src="chrome://global/skin/dialog.css"/>
697 + <xul:label class="dialogheader-title" xbl:inherits="value=title,crop" crop="right" flex="1"/>
698 + <xul:label class="dialogheader-description" xbl:inherits="value=description"/>
703 diff --git a/toolkit/content/widgets/preferences-kde.xml b/toolkit/content/widgets/preferences-kde.xml
706 +++ b/toolkit/content/widgets/preferences-kde.xml
708 +<?xml version="1.0"?>
710 +<!DOCTYPE bindings [
711 + <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
713 + <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
717 +<bindings id="preferencesBindings"
718 + xmlns="http://www.mozilla.org/xbl"
719 + xmlns:xbl="http://www.mozilla.org/xbl"
720 + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
723 +# = Preferences Window Framework
725 +# The syntax for use looks something like:
728 +# <prefpane id="prefPaneA">
730 +# <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/>
731 +# <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/>
733 +# <checkbox label="Preference" preference="preference1"/>
738 + <binding id="preferences">
739 + <implementation implements="nsIObserver">
740 + <method name="observe">
741 + <parameter name="aSubject"/>
742 + <parameter name="aTopic"/>
743 + <parameter name="aData"/>
746 + for (var i = 0; i < this.childNodes.length; ++i) {
747 + var preference = this.childNodes[i];
748 + if (preference.name == aData) {
749 + preference.value = preference.valueFromPreferences;
756 + <method name="fireChangedEvent">
757 + <parameter name="aPreference"/>
760 + // Value changed, synthesize an event
762 + var event = document.createEvent("Events");
763 + event.initEvent("change", true, true);
764 + aPreference.dispatchEvent(event);
767 + Components.utils.reportError(e);
773 + <field name="service">
774 + Components.classes["@mozilla.org/preferences-service;1"]
775 + .getService(Components.interfaces.nsIPrefService);
777 + <field name="rootBranch">
778 + Components.classes["@mozilla.org/preferences-service;1"]
779 + .getService(Components.interfaces.nsIPrefBranch);
781 + <field name="defaultBranch">
782 + this.service.getDefaultBranch("");
784 + <field name="rootBranchInternal">
785 + Components.classes["@mozilla.org/preferences-service;1"]
786 + .getService(Components.interfaces.nsIPrefBranchInternal);
788 + <property name="type" readonly="true">
791 + return document.documentElement.type || "";
795 + <property name="instantApply" readonly="true">
798 + var doc = document.documentElement;
799 + return this.type == "child" ? doc.instantApply
800 + : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply");
807 + <binding id="preference">
811 + // if the element has been inserted without the name attribute set,
812 + // we have nothing to do here
816 + this.preferences.rootBranchInternal
817 + .addObserver(this.name, this.preferences, false);
818 + // In non-instant apply mode, we must try and use the last saved state
819 + // from any previous opens of a child dialog instead of the value from
820 + // preferences, to pick up any edits a user may have made.
821 + if (this.preferences.type == "child" &&
822 + !this.instantApply && window.opener) {
823 + var pdoc = window.opener.document;
825 + // Try to find a preference element for the same preference.
826 + var preference = null;
827 + var parentPreferences = pdoc.getElementsByTagName("preferences");
828 + for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
829 + var parentPrefs = parentPreferences[k]
830 + .getElementsByAttribute("name", this.name);
831 + for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
832 + if (parentPrefs[l].localName == "preference")
833 + preference = parentPrefs[l];
836 + this._setValue(preference ? preference.value
837 + : this.valueFromPreferences, false);
840 + this._setValue(this.valueFromPreferences, false);
844 + this.preferences.rootBranchInternal
845 + .removeObserver(this.name, this.preferences);
848 + <property name="instantApply">
850 + return this.getAttribute("instantApply") == "true" || this.preferences.instantApply;
854 + <property name="preferences" onget="return this.parentNode"/>
855 + <property name="name" onget="return this.getAttribute('name');">
857 + if (val == this.name)
860 + this.preferences.rootBranchInternal
861 + .removeObserver(this.name, this.preferences);
862 + this.setAttribute('name', val);
863 + this.preferences.rootBranchInternal
864 + .addObserver(val, this.preferences, false);
869 + <property name="type" onget="return this.getAttribute('type');"
870 + onset="this.setAttribute('type', val); return val;"/>
871 + <property name="inverted" onget="return this.getAttribute('inverted') == 'true';"
872 + onset="this.setAttribute('inverted', val); return val;"/>
873 + <property name="readonly" onget="return this.getAttribute('readonly') == 'true';"
874 + onset="this.setAttribute('readonly', val); return val;"/>
876 + <field name="_value">null</field>
877 + <method name="_setValue">
878 + <parameter name="aValue"/>
879 + <parameter name="aUpdate"/>
882 + if (aUpdate && this.value !== aValue) {
883 + this._value = aValue;
884 + if (this.instantApply)
885 + this.valueFromPreferences = aValue;
886 + this.preferences.fireChangedEvent(this);
888 + else if (!aUpdate) {
889 + this._value = aValue;
890 + this.updateElements();
896 + <property name="value" onget="return this._value" onset="return this._setValue(val, true);"/>
898 + <property name="locked">
900 + return this.preferences.rootBranch.prefIsLocked(this.name);
904 + <property name="disabled">
906 + return this.getAttribute("disabled") == "true";
911 + this.setAttribute("disabled", "true");
913 + this.removeAttribute("disabled");
918 + var elements = document.getElementsByAttribute("preference", this.id);
919 + for (var i = 0; i < elements.length; ++i) {
920 + elements[i].disabled = val;
922 + var labels = document.getElementsByAttribute("control", elements[i].id);
923 + for (var j = 0; j < labels.length; ++j)
924 + labels[j].disabled = val;
932 + <property name="tabIndex">
934 + return parseInt(this.getAttribute("tabindex"));
939 + this.setAttribute("tabindex", val);
941 + this.removeAttribute("tabindex");
946 + var elements = document.getElementsByAttribute("preference", this.id);
947 + for (var i = 0; i < elements.length; ++i) {
948 + elements[i].tabIndex = val;
950 + var labels = document.getElementsByAttribute("control", elements[i].id);
951 + for (var j = 0; j < labels.length; ++j)
952 + labels[j].tabIndex = val;
960 + <property name="hasUserValue">
963 + return this.preferences.rootBranch.prefHasUserValue(this.name) &&
964 + this.value !== undefined;
969 + <method name="reset">
971 + // defer reset until preference update
972 + this.value = undefined;
976 + <field name="_useDefault">false</field>
977 + <property name="defaultValue">
980 + this._useDefault = true;
981 + var val = this.valueFromPreferences;
982 + this._useDefault = false;
988 + <property name="_branch">
990 + return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch;
994 + <field name="batching">false</field>
996 + <method name="_reportUnknownType">
999 + var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
1000 + .getService(Components.interfaces.nsIConsoleService);
1001 + var msg = "<preference> with id='" + this.id + "' and name='" +
1002 + this.name + "' has unknown type '" + this.type + "'.";
1003 + consoleService.logStringMessage(msg);
1008 + <property name="valueFromPreferences">
1012 + // Force a resync of value with preferences.
1013 + switch (this.type) {
1015 + return this._branch.getIntPref(this.name);
1017 + var val = this._branch.getBoolPref(this.name);
1018 + return this.inverted ? !val : val;
1020 + return this._branch
1021 + .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString)
1025 + return this._branch
1026 + .getComplexValue(this.name, Components.interfaces.nsISupportsString)
1029 + var family = this._branch
1030 + .getComplexValue(this.name, Components.interfaces.nsISupportsString)
1032 + var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
1033 + .createInstance(Components.interfaces.nsIFontEnumerator);
1034 + return fontEnumerator.getStandardFamilyName(family);
1036 + var f = this._branch
1037 + .getComplexValue(this.name, Components.interfaces.nsILocalFile);
1040 + this._reportUnknownType();
1049 + // Exit early if nothing to do.
1050 + if (this.readonly || this.valueFromPreferences == val)
1053 + // The special value undefined means 'reset preference to default'.
1054 + if (val === undefined) {
1055 + this.preferences.rootBranch.clearUserPref(this.name);
1059 + // Force a resync of preferences with value.
1060 + switch (this.type) {
1062 + this.preferences.rootBranch.setIntPref(this.name, val);
1065 + this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val);
1068 + var pls = Components.classes["@mozilla.org/pref-localizedstring;1"]
1069 + .createInstance(Components.interfaces.nsIPrefLocalizedString);
1071 + this.preferences.rootBranch
1072 + .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls);
1077 + var iss = Components.classes["@mozilla.org/supports-string;1"]
1078 + .createInstance(Components.interfaces.nsISupportsString);
1080 + this.preferences.rootBranch
1081 + .setComplexValue(this.name, Components.interfaces.nsISupportsString, iss);
1085 + if (typeof(val) == "string") {
1086 + lf = Components.classes["@mozilla.org/file/local;1"]
1087 + .createInstance(Components.interfaces.nsILocalFile);
1088 + lf.persistentDescriptor = val;
1090 + lf.initWithPath(val);
1093 + lf = val.QueryInterface(Components.interfaces.nsILocalFile);
1094 + this.preferences.rootBranch
1095 + .setComplexValue(this.name, Components.interfaces.nsILocalFile, lf);
1098 + this._reportUnknownType();
1100 + if (!this.batching)
1101 + this.preferences.service.savePrefFile(null);
1107 + <method name="setElementValue">
1108 + <parameter name="aElement"/>
1112 + aElement.disabled = true;
1114 + if (!this.isElementEditable(aElement))
1117 + var rv = undefined;
1118 + if (aElement.hasAttribute("onsyncfrompreference")) {
1119 + // Value changed, synthesize an event
1121 + var event = document.createEvent("Events");
1122 + event.initEvent("syncfrompreference", true, true);
1123 + var f = new Function ("event",
1124 + aElement.getAttribute("onsyncfrompreference"));
1125 + rv = f.call(aElement, event);
1128 + Components.utils.reportError(e);
1131 + var val = rv !== undefined ? rv : (this.instantApply ? this.valueFromPreferences : this.value);
1132 + // if the preference is marked for reset, show default value in UI
1133 + if (val === undefined)
1134 + val = this.defaultValue;
1137 + * Initialize a UI element property with a value. Handles the case
1138 + * where an element has not yet had a XBL binding attached for it and
1139 + * the property setter does not yet exist by setting the same attribute
1140 + * on the XUL element using DOM apis and assuming the element's
1141 + * constructor or property getters appropriately handle this state.
1143 + function setValue(element, attribute, value) {
1144 + if (attribute in element)
1145 + element[attribute] = value;
1147 + element.setAttribute(attribute, value);
1149 + if (aElement.localName == "checkbox" ||
1150 + aElement.localName == "listitem")
1151 + setValue(aElement, "checked", val);
1152 + else if (aElement.localName == "colorpicker")
1153 + setValue(aElement, "color", val);
1154 + else if (aElement.localName == "textbox") {
1155 + // XXXmano Bug 303998: Avoid a caret placement issue if either the
1156 + // preference observer or its setter calls updateElements as a result
1157 + // of the input event handler.
1158 + if (aElement.value !== val)
1159 + setValue(aElement, "value", val);
1162 + setValue(aElement, "value", val);
1167 + <method name="getElementValue">
1168 + <parameter name="aElement"/>
1171 + if (aElement.hasAttribute("onsynctopreference")) {
1172 + // Value changed, synthesize an event
1174 + var event = document.createEvent("Events");
1175 + event.initEvent("synctopreference", true, true);
1176 + var f = new Function ("event",
1177 + aElement.getAttribute("onsynctopreference"));
1178 + var rv = f.call(aElement, event);
1179 + if (rv !== undefined)
1183 + Components.utils.reportError(e);
1188 + * Read the value of an attribute from an element, assuming the
1189 + * attribute is a property on the element's node API. If the property
1190 + * is not present in the API, then assume its value is contained in
1191 + * an attribute, as is the case before a binding has been attached.
1193 + function getValue(element, attribute) {
1194 + if (attribute in element)
1195 + return element[attribute];
1196 + return element.getAttribute(attribute);
1198 + if (aElement.localName == "checkbox" ||
1199 + aElement.localName == "listitem")
1200 + var value = getValue(aElement, "checked");
1201 + else if (aElement.localName == "colorpicker")
1202 + value = getValue(aElement, "color");
1204 + value = getValue(aElement, "value");
1206 + switch (this.type) {
1208 + return parseInt(value, 10) || 0;
1210 + return typeof(value) == "boolean" ? value : value == "true";
1217 + <method name="isElementEditable">
1218 + <parameter name="aElement"/>
1221 + switch (aElement.localName) {
1223 + case "colorpicker":
1224 + case "radiogroup":
1231 + return aElement.getAttribute("preference-editable") == "true";
1236 + <method name="updateElements">
1242 + // This "change" event handler tracks changes made to preferences by
1243 + // sources other than the user in this window.
1244 + var elements = document.getElementsByAttribute("preference", this.id);
1245 + for (var i = 0; i < elements.length; ++i)
1246 + this.setElementValue(elements[i]);
1253 + <handler event="change">
1254 + this.updateElements();
1259 + <binding id="prefwindow"
1260 + extends="chrome://global/content/bindings/dialog.xml#dialog">
1262 + <stylesheet src="chrome://global/skin/preferences.css"/>
1264 + <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY"
1265 + closebuttonlabel="&preferencesCloseButton.label;"
1266 + closebuttonaccesskey="&preferencesCloseButton.accesskey;"
1269 + title="&preferencesDefaultTitleWin.title;">
1271 + title="&preferencesDefaultTitleMac.title;">
1273 + <xul:windowdragbox orient="vertical">
1274 + <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar"
1275 + role="listbox"/> <!-- Expose to accessibility APIs as a listbox -->
1276 + </xul:windowdragbox>
1277 + <xul:hbox flex="1" class="paneDeckContainer">
1278 + <xul:deck anonid="paneDeck" flex="1">
1279 + <children includes="prefpane"/>
1282 + <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons"
1283 +#ifdef XP_UNIX_GNOME
1285 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
1286 + <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
1287 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
1288 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
1289 + <xul:spacer anonid="spacer" flex="1"/>
1290 + <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
1291 + <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
1294 + <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
1295 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
1296 + <xul:spacer anonid="spacer" flex="1"/>
1297 + <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
1298 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
1299 + <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
1300 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
1303 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
1304 + <xul:spacer anonid="spacer" flex="1"/>
1305 + <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
1306 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
1307 + <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
1308 + <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
1309 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
1316 + <implementation implements="nsITimerCallback">
1319 + if (this.type != "child") {
1320 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1321 + .getService(Components.interfaces.nsIPrefBranch);
1322 + this.instantApply = psvc.getBoolPref("browser.preferences.instantApply");
1323 + if (this.instantApply) {
1324 + var docElt = document.documentElement;
1325 + var acceptButton = docElt.getButton("accept");
1326 + acceptButton.hidden = true;
1327 + var cancelButton = docElt.getButton("cancel");
1329 + // no buttons on Mac except Help
1330 + cancelButton.hidden = true;
1331 + // Also, don't fire onDialogAccept on enter
1332 + acceptButton.disabled = true;
1334 + // morph the Cancel button into the Close button
1335 + cancelButton.setAttribute ("icon", "close");
1336 + cancelButton.label = docElt.getAttribute("closebuttonlabel");
1337 + cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey");
1341 + this.setAttribute("animated", this._shouldAnimate ? "true" : "false");
1342 + var panes = this.preferencePanes;
1344 + var lastPane = null;
1345 + if (this.lastSelected) {
1346 + lastPane = document.getElementById(this.lastSelected);
1348 + this.lastSelected = null;
1353 + if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") {
1354 + paneToLoad = document.getElementById(window.arguments[0]);
1355 + this.lastSelected = paneToLoad.id;
1357 + else if (lastPane)
1358 + paneToLoad = lastPane;
1360 + paneToLoad = panes[0];
1362 + for (var i = 0; i < panes.length; ++i) {
1363 + this._makePaneButton(panes[i]);
1364 + if (panes[i].loaded) {
1365 + // Inline pane content, fire load event to force initialization.
1366 + this._fireEvent("paneload", panes[i]);
1369 + this.showPane(paneToLoad);
1371 + if (panes.length == 1)
1372 + this._selector.setAttribute("collapsed", "true");
1378 + // Release timers to avoid reference cycles.
1379 + if (this._animateTimer) {
1380 + this._animateTimer.cancel();
1381 + this._animateTimer = null;
1383 + if (this._fadeTimer) {
1384 + this._fadeTimer.cancel();
1385 + this._fadeTimer = null;
1390 + <field name="instantApply">false</field>
1392 + <property name="preferencePanes"
1393 + onget="return this.getElementsByTagName('prefpane');"/>
1395 + <property name="type" onget="return this.getAttribute('type');"/>
1396 + <property name="_paneDeck"
1397 + onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/>
1398 + <property name="_paneDeckContainer"
1399 + onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/>
1400 + <property name="_selector"
1401 + onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/>
1402 + <property name="lastSelected"
1403 + onget="return this.getAttribute('lastSelected');">
1405 + this.setAttribute("lastSelected", val);
1406 + document.persist(this.id, "lastSelected");
1410 + <property name="currentPane"
1411 + onset="return this._currentPane = val;">
1413 + if (!this._currentPane)
1414 + this._currentPane = this.preferencePanes[0];
1416 + return this._currentPane;
1419 + <field name="_currentPane">null</field>
1422 + <method name="_makePaneButton">
1423 + <parameter name="aPaneElement"/>
1426 + var radio = document.createElement("radio");
1427 + radio.setAttribute("pane", aPaneElement.id);
1428 + radio.setAttribute("label", aPaneElement.label);
1429 + // Expose preference group choice to accessibility APIs as an unchecked list item
1430 + // The parent group is exposed to accessibility APIs as a list
1431 + if (aPaneElement.image)
1432 + radio.setAttribute("src", aPaneElement.image);
1433 + radio.style.listStyleImage = aPaneElement.style.listStyleImage;
1434 + this._selector.appendChild(radio);
1440 + <method name="showPane">
1441 + <parameter name="aPaneElement"/>
1444 + if (!aPaneElement)
1447 + this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id);
1448 + if (!aPaneElement.loaded) {
1449 + function OverlayLoadObserver(aPane)
1451 + this._pane = aPane;
1453 + OverlayLoadObserver.prototype = {
1455 + observe: function (aSubject, aTopic, aData)
1457 + this._pane.loaded = true;
1458 + this._outer._fireEvent("paneload", this._pane);
1459 + this._outer._selectPane(this._pane);
1463 + var obs = new OverlayLoadObserver(aPaneElement);
1464 + document.loadOverlay(aPaneElement.src, obs);
1467 + this._selectPane(aPaneElement);
1472 + <method name="_fireEvent">
1473 + <parameter name="aEventName"/>
1474 + <parameter name="aTarget"/>
1477 + // Panel loaded, synthesize a load event.
1479 + var event = document.createEvent("Events");
1480 + event.initEvent(aEventName, true, true);
1481 + var cancel = !aTarget.dispatchEvent(event);
1482 + if (aTarget.hasAttribute("on" + aEventName)) {
1483 + var fn = new Function ("event", aTarget.getAttribute("on" + aEventName));
1484 + var rv = fn.call(aTarget, event);
1491 + Components.utils.reportError(e);
1498 + <field name="_initialized">false</field>
1499 + <method name="_selectPane">
1500 + <parameter name="aPaneElement"/>
1504 + var paneTitle = aPaneElement.label;
1505 + if (paneTitle != "")
1506 + document.title = paneTitle;
1508 + var helpButton = document.documentElement.getButton("help");
1509 + if (aPaneElement.helpTopic)
1510 + helpButton.hidden = false;
1512 + helpButton.hidden = true;
1514 + // Find this pane's index in the deck and set the deck's
1515 + // selectedIndex to that value to switch to it.
1516 + var prefpanes = this.preferencePanes;
1517 + for (var i = 0; i < prefpanes.length; ++i) {
1518 + if (prefpanes[i] == aPaneElement) {
1519 + this._paneDeck.selectedIndex = i;
1521 + if (this.type != "child") {
1522 + if (aPaneElement.hasAttribute("flex") && this._shouldAnimate &&
1523 + prefpanes.length > 1)
1524 + aPaneElement.removeAttribute("flex");
1525 + // Calling sizeToContent after the first prefpane is loaded
1526 + // will size the windows contents so style information is
1527 + // available to calculate correct sizing.
1528 + if (!this._initialized && prefpanes.length > 1) {
1529 + if (this._shouldAnimate)
1530 + this.style.minHeight = 0;
1531 + window.sizeToContent();
1534 + var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0];
1535 + oldPane.selected = !(aPaneElement.selected = true);
1536 + this.lastSelected = aPaneElement.id;
1537 + this.currentPane = aPaneElement;
1538 + this._initialized = true;
1540 + // Only animate if we've switched between prefpanes
1541 + if (this._shouldAnimate && oldPane.id != aPaneElement.id) {
1542 + aPaneElement.style.opacity = 0.0;
1543 + this.animate(oldPane, aPaneElement);
1545 + else if (!this._shouldAnimate && prefpanes.length > 1) {
1546 + var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer, "").height);
1547 + var verticalPadding = parseInt(window.getComputedStyle(aPaneElement, "").paddingTop);
1548 + verticalPadding += parseInt(window.getComputedStyle(aPaneElement, "").paddingBottom);
1549 + if (aPaneElement.contentHeight > targetHeight - verticalPadding) {
1550 + // To workaround the bottom border of a groupbox from being
1551 + // cutoff an hbox with a class of bottomBox may enclose it.
1552 + // This needs to include its padding to resize properly.
1554 + var bottomPadding = 0;
1555 + var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0];
1557 + bottomPadding = parseInt(window.getComputedStyle(bottomBox, "").paddingBottom);
1558 + window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight;
1561 + // XXX rstrong - extend the contents of the prefpane to
1562 + // prevent elements from being cutoff (see bug 349098).
1563 + if (aPaneElement.contentHeight + verticalPadding < targetHeight)
1564 + aPaneElement._content.style.height = targetHeight - verticalPadding + "px";
1574 + <property name="_shouldAnimate">
1577 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1578 + .getService(Components.interfaces.nsIPrefBranch);
1580 + var animate = true;
1582 + var animate = false;
1585 + animate = psvc.getBoolPref("browser.preferences.animateFadeIn");
1593 + <method name="animate">
1594 + <parameter name="aOldPane"/>
1595 + <parameter name="aNewPane"/>
1598 + // if we are already resizing, use currentHeight
1599 + var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight;
1601 + this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1;
1602 + var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight);
1603 + this._animateRemainder = sizeDelta % this._animateIncrement;
1605 + this._setUpAnimationTimer(oldHeight);
1610 + <property name="_sizeIncrement">
1613 + var lastSelectedPane = document.getElementById(this.lastSelected);
1614 + var increment = this._animateIncrement * this._multiplier;
1615 + var newHeight = this._currentHeight + increment;
1616 + if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) ||
1617 + (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight))
1620 + if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) ||
1621 + (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight))
1622 + increment = this._animateRemainder * this._multiplier;
1628 + <method name="notify">
1629 + <parameter name="aTimer"/>
1635 + if (aTimer == this._animateTimer) {
1636 + var increment = this._sizeIncrement;
1637 + if (increment != 0) {
1638 + window.innerHeight += increment;
1639 + this._currentHeight += increment;
1643 + this._setUpFadeTimer();
1645 + } else if (aTimer == this._fadeTimer) {
1646 + var elt = document.getElementById(this.lastSelected);
1647 + var newOpacity = parseFloat(window.getComputedStyle(elt, "").opacity) + this._fadeIncrement;
1648 + if (newOpacity < 1.0)
1649 + elt.style.opacity = newOpacity;
1652 + elt.style.opacity = 1.0;
1659 + <method name="_setUpAnimationTimer">
1660 + <parameter name="aStartHeight"/>
1663 + if (!this._animateTimer)
1664 + this._animateTimer = Components.classes["@mozilla.org/timer;1"]
1665 + .createInstance(Components.interfaces.nsITimer);
1667 + this._animateTimer.cancel();
1668 + this._currentHeight = aStartHeight;
1670 + this._animateTimer.initWithCallback(this, this._animateDelay,
1671 + Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
1676 + <method name="_setUpFadeTimer">
1679 + if (!this._fadeTimer)
1680 + this._fadeTimer = Components.classes["@mozilla.org/timer;1"]
1681 + .createInstance(Components.interfaces.nsITimer);
1683 + this._fadeTimer.cancel();
1685 + this._fadeTimer.initWithCallback(this, this._fadeDelay,
1686 + Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
1691 + <field name="_animateTimer">null</field>
1692 + <field name="_fadeTimer">null</field>
1693 + <field name="_animateDelay">15</field>
1694 + <field name="_animateIncrement">40</field>
1695 + <field name="_fadeDelay">5</field>
1696 + <field name="_fadeIncrement">0.40</field>
1697 + <field name="_animateRemainder">0</field>
1698 + <field name="_currentHeight">0</field>
1699 + <field name="_multiplier">0</field>
1701 + <method name="addPane">
1702 + <parameter name="aPaneElement"/>
1705 + this.appendChild(aPaneElement);
1707 + // Set up pane button
1708 + this._makePaneButton(aPaneElement);
1713 + <method name="openSubDialog">
1714 + <parameter name="aURL"/>
1715 + <parameter name="aFeatures"/>
1716 + <parameter name="aParams"/>
1718 + return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams);
1722 + <method name="openWindow">
1723 + <parameter name="aWindowType"/>
1724 + <parameter name="aURL"/>
1725 + <parameter name="aFeatures"/>
1726 + <parameter name="aParams"/>
1729 + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
1730 + .getService(Components.interfaces.nsIWindowMediator);
1731 + var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null;
1733 + if ("initWithParams" in win)
1734 + win.initWithParams(aParams);
1738 + var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : "");
1739 + var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener;
1740 + win = parentWindow.openDialog(aURL, "_blank", features, aParams);
1748 + <handler event="dialogaccept">
1750 + if (!this._fireEvent("beforeaccept", this))
1753 + if (this.type == "child" && window.opener) {
1754 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1755 + .getService(Components.interfaces.nsIPrefBranch);
1756 + var instantApply = psvc.getBoolPref("browser.preferences.instantApply");
1757 + if (instantApply) {
1758 + var panes = this.preferencePanes;
1759 + for (var i = 0; i < panes.length; ++i)
1760 + panes[i].writePreferences(true);
1763 + // Clone all the preferences elements from the child document and
1764 + // insert them into the pane collection of the parent.
1765 + var pdoc = window.opener.document;
1766 + if (pdoc.documentElement.localName == "prefwindow") {
1767 + var currentPane = pdoc.documentElement.currentPane;
1768 + var id = window.location.href + "#childprefs";
1769 + var childPrefs = pdoc.getElementById(id);
1770 + if (!childPrefs) {
1771 + var childPrefs = pdoc.createElement("preferences");
1772 + currentPane.appendChild(childPrefs);
1773 + childPrefs.id = id;
1775 + var panes = this.preferencePanes;
1776 + for (var i = 0; i < panes.length; ++i) {
1777 + var preferences = panes[i].preferences;
1778 + for (var j = 0; j < preferences.length; ++j) {
1779 + // Try to find a preference element for the same preference.
1780 + var preference = null;
1781 + var parentPreferences = pdoc.getElementsByTagName("preferences");
1782 + for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
1783 + var parentPrefs = parentPreferences[k]
1784 + .getElementsByAttribute("name", preferences[j].name);
1785 + for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
1786 + if (parentPrefs[l].localName == "preference")
1787 + preference = parentPrefs[l];
1790 + if (!preference) {
1791 + // No matching preference in the parent window.
1792 + preference = pdoc.createElement("preference");
1793 + childPrefs.appendChild(preference);
1794 + preference.name = preferences[j].name;
1795 + preference.type = preferences[j].type;
1796 + preference.inverted = preferences[j].inverted;
1797 + preference.readonly = preferences[j].readonly;
1798 + preference.disabled = preferences[j].disabled;
1800 + preference.value = preferences[j].value;
1807 + var panes = this.preferencePanes;
1808 + for (var i = 0; i < panes.length; ++i)
1809 + panes[i].writePreferences(false);
1811 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1812 + .getService(Components.interfaces.nsIPrefService);
1813 + psvc.savePrefFile(null);
1817 + <handler event="command">
1818 + if (event.originalTarget.hasAttribute("pane")) {
1819 + var pane = document.getElementById(event.originalTarget.getAttribute("pane"));
1820 + this.showPane(pane);
1824 + <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing">
1826 + if (this.instantApply)
1828 + event.stopPropagation();
1829 + event.preventDefault();
1833 + <handler event="keypress"
1835 + key="&openHelpMac.commandkey;" modifiers="accel"
1837 + keycode="&openHelp.commandkey;"
1839 + phase="capturing">
1841 + var helpButton = this.getButton("help");
1842 + if (helpButton.disabled || helpButton.hidden)
1844 + this._fireEvent("dialoghelp", this);
1845 + event.stopPropagation();
1846 + event.preventDefault();
1852 + <binding id="prefpane">
1854 + <stylesheet src="chrome://global/skin/preferences.css"/>
1857 + <xul:vbox class="content-box" xbl:inherits="flex">
1862 + <method name="writePreferences">
1863 + <parameter name="aFlushToDisk"/>
1866 + // Write all values to preferences.
1867 + var preferences = this.preferences;
1868 + for (var i = 0; i < preferences.length; ++i) {
1869 + var preference = preferences[i];
1870 + preference.batching = true;
1871 + preference.valueFromPreferences = preference.value;
1872 + preference.batching = false;
1874 + if (aFlushToDisk) {
1875 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1876 + .getService(Components.interfaces.nsIPrefService);
1877 + psvc.savePrefFile(null);
1883 + <property name="src"
1884 + onget="return this.getAttribute('src');"
1885 + onset="this.setAttribute('src', val); return val;"/>
1886 + <property name="selected"
1887 + onget="return this.getAttribute('selected') == 'true';"
1888 + onset="this.setAttribute('selected', val); return val;"/>
1889 + <property name="image"
1890 + onget="return this.getAttribute('image');"
1891 + onset="this.setAttribute('image', val); return val;"/>
1892 + <property name="label"
1893 + onget="return this.getAttribute('label');"
1894 + onset="this.setAttribute('label', val); return val;"/>
1896 + <property name="preferenceElements"
1897 + onget="return this.getElementsByAttribute('preference', '*');"/>
1898 + <property name="preferences"
1899 + onget="return this.getElementsByTagName('preference');"/>
1901 + <property name="helpTopic">
1904 + // if there are tabs, and the selected tab provides a helpTopic, return that
1905 + var box = this.getElementsByTagName("tabbox");
1907 + var tab = box[0].selectedTab;
1908 + if (tab && tab.hasAttribute("helpTopic"))
1909 + return tab.getAttribute("helpTopic");
1912 + // otherwise, return the helpTopic of the current panel
1913 + return this.getAttribute("helpTopic");
1918 + <field name="_loaded">false</field>
1919 + <property name="loaded"
1920 + onget="return !this.src ? true : this._loaded;"
1921 + onset="this._loaded = val; return val;"/>
1923 + <method name="preferenceForElement">
1924 + <parameter name="aElement"/>
1926 + return document.getElementById(aElement.getAttribute("preference"));
1930 + <method name="getPreferenceElement">
1931 + <parameter name="aStartElement"/>
1934 + var temp = aStartElement;
1935 + while (temp && temp.nodeType == Node.ELEMENT_NODE &&
1936 + !temp.hasAttribute("preference"))
1937 + temp = temp.parentNode;
1938 + return temp.nodeType == Node.ELEMENT_NODE ? temp : aStartElement;
1943 + <method name="userChangedValue">
1944 + <parameter name="aElement"/>
1947 + var element = this.getPreferenceElement(aElement);
1948 + if (element.hasAttribute("preference")) {
1949 + var preference = document.getElementById(element.getAttribute("preference"));
1950 + var prefVal = preference.getElementValue(element);
1951 + preference.value = prefVal;
1957 + <property name="contentHeight">
1959 + var targetHeight = parseInt(window.getComputedStyle(this._content, "").height);
1960 + targetHeight += parseInt(window.getComputedStyle(this._content, "").marginTop);
1961 + targetHeight += parseInt(window.getComputedStyle(this._content, "").marginBottom);
1962 + return targetHeight;
1965 + <field name="_content">
1966 + document.getAnonymousElementByAttribute(this, "class", "content-box");
1970 + <handler event="command">
1971 + // This "command" event handler tracks changes made to preferences by
1972 + // the user in this window.
1973 + this.userChangedValue(event.target);
1975 + <handler event="select">
1976 + // This "select" event handler tracks changes made to colorpicker
1977 + // preferences by the user in this window.
1978 + if (event.target.localName == "colorpicker")
1979 + this.userChangedValue(event.target);
1981 + <handler event="change">
1982 + // This "change" event handler tracks changes made to preferences by
1983 + // the user in this window.
1984 + this.userChangedValue(event.target);
1986 + <handler event="input">
1987 + // This "input" event handler tracks changes made to preferences by
1988 + // the user in this window.
1989 + this.userChangedValue(event.target);
1991 + <handler event="paneload">
1993 + // Initialize all values from preferences.
1994 + var elements = this.preferenceElements;
1995 + for (var i = 0; i < elements.length; ++i) {
1997 + var preference = this.preferenceForElement(elements[i]);
1998 + preference.setElementValue(elements[i]);
2001 + dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n");
2009 + <binding id="panebutton" extends="chrome://global/content/bindings/radio.xml#radio">
2011 + <stylesheet src="chrome://global/skin/preferences.css"/>
2014 + <xul:image class="paneButtonIcon" xbl:inherits="src"/>
2015 + <xul:label class="paneButtonLabel" xbl:inherits="value=label"/>
2017 + <implementation implements="nsIAccessible">
2018 + <property name="accessibleType" readonly="true">
2021 + return Components.interfaces.nsIAccessibleProvider.XULListitem;
2030 +# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2031 +# ***** BEGIN LICENSE BLOCK *****
2032 +# Version: MPL 1.1/GPL 2.0/LGPL 2.1
2034 +# The contents of this file are subject to the Mozilla Public License Version
2035 +# 1.1 (the "License"); you may not use this file except in compliance with
2036 +# the License. You may obtain a copy of the License at
2037 +# http://www.mozilla.org/MPL/
2039 +# Software distributed under the License is distributed on an "AS IS" basis,
2040 +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2041 +# for the specific language governing rights and limitations under the
2044 +# The Original Code is the Preferences System.
2046 +# The Initial Developer of the Original Code is
2048 +# Portions created by the Initial Developer are Copyright (C) 2005
2049 +# the Initial Developer. All Rights Reserved.
2052 +# Ben Goodger <ben@mozilla.org>
2053 +# Josh Aas <josh@mozilla.com>
2055 +# Alternatively, the contents of this file may be used under the terms of
2056 +# either the GNU General Public License Version 2 or later (the "GPL"), or
2057 +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2058 +# in which case the provisions of the GPL or the LGPL are applicable instead
2059 +# of those above. If you wish to allow use of your version of this file only
2060 +# under the terms of either the GPL or the LGPL, and not to allow others to
2061 +# use your version of this file under the terms of the MPL, indicate your
2062 +# decision by deleting the provisions above and replace them with the notice
2063 +# and other provisions required by the GPL or the LGPL. If you do not delete
2064 +# the provisions above, a recipient may use your version of this file under
2065 +# the terms of any one of the MPL, the GPL or the LGPL.
2067 +# ***** END LICENSE BLOCK *****
2070 +# This is PrefWindow 6. The Code Could Well Be Ready, Are You?
2072 +# Historical References:
2073 +# PrefWindow V (February 1, 2003)
2074 +# PrefWindow IV (April 24, 2000)
2075 +# PrefWindow III (January 6, 2000)
2076 +# PrefWindow II (???)
2077 +# PrefWindow I (June 4, 1999)
2079 diff --git a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
2080 --- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
2081 +++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
2084 #include "nsReadableUtils.h"
2085 #include "nsArrayUtils.h"
2086 #include "prnetdb.h"
2088 #include "nsPrintfCString.h"
2089 #include "nsNetUtil.h"
2090 #include "nsISupportsPrimitives.h"
2091 +#include "nsVoidArray.h"
2092 +#include "nsKDEUtils.h"
2094 class nsUnixSystemProxySettings : public nsISystemProxySettings {
2097 NS_DECL_NSISYSTEMPROXYSETTINGS
2099 nsUnixSystemProxySettings() {}
2103 ~nsUnixSystemProxySettings() {}
2105 nsCOMPtr<nsIGConfService> mGConf;
2106 PRBool IsProxyMode(const char* aMode);
2107 nsresult SetProxyResultFromGConf(const char* aKeyBase, const char* aType, nsACString& aResult);
2108 nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult);
2109 + nsresult GetProxyFromKDE(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult);
2112 NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
2115 nsUnixSystemProxySettings::Init()
2117 // If this is a GNOME session, load gconf and try to use its preferences.
2118 @@ -407,16 +410,19 @@ nsUnixSystemProxySettings::GetProxyForUR
2120 rv = aURI->GetHost(host);
2121 NS_ENSURE_SUCCESS(rv, rv);
2124 rv = aURI->GetPort(&port);
2125 NS_ENSURE_SUCCESS(rv, rv);
2127 + if( nsKDEUtils::kdeSupport())
2128 + return GetProxyFromKDE( scheme, host, port, aResult );
2131 return GetProxyFromEnvironment(scheme, host, port, aResult);
2133 return GetProxyFromGConf(scheme, host, port, aResult);
2136 #define NS_UNIXSYSTEMPROXYSERVICE_CID /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\
2137 { 0x0fa3158c, 0xd5a7, 0x43de, \
2138 diff --git a/toolkit/xre/Makefile.in b/toolkit/xre/Makefile.in
2139 --- a/toolkit/xre/Makefile.in
2140 +++ b/toolkit/xre/Makefile.in
2141 @@ -94,17 +94,18 @@ EXPORTS = nsWindowsDllInterceptor.h
2143 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
2144 CMMSRCS = nsNativeAppSupportCocoa.mm
2146 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
2147 CPPSRCS += nsNativeAppSupportOS2.cpp
2149 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
2150 -CPPSRCS += nsNativeAppSupportUnix.cpp
2151 +CPPSRCS += nsNativeAppSupportUnix.cpp nsKDEUtils.cpp
2152 +EXPORTS += nsKDEUtils.h
2154 ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
2155 CPPSRCS += nsNativeAppSupportQt.cpp
2156 CPPSRCS += nsQAppInstance.cpp
2157 EXPORTS += nsQAppInstance.h
2159 CPPSRCS += nsNativeAppSupportDefault.cpp
2161 diff --git a/toolkit/xre/nsKDEUtils.cpp b/toolkit/xre/nsKDEUtils.cpp
2162 new file mode 100644
2164 +++ b/toolkit/xre/nsKDEUtils.cpp
2166 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2167 +/* ***** BEGIN LICENSE BLOCK *****
2168 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2170 + * The contents of this file are subject to the Mozilla Public License Version
2171 + * 1.1 (the "License"); you may not use this file except in compliance with
2172 + * the License. You may obtain a copy of the License at
2173 + * http://www.mozilla.org/MPL/
2175 + * Software distributed under the License is distributed on an "AS IS" basis,
2176 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2177 + * for the specific language governing rights and limitations under the
2180 + * The Original Code is Unix Native App Support.
2182 + * The Initial Developer of the Original Code is
2183 + * Mozilla Corporation.
2184 + * Portions created by the Initial Developer are Copyright (C) 2007
2185 + * the Initial Developer. All Rights Reserved.
2189 + * Alternatively, the contents of this file may be used under the terms of
2190 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2191 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2192 + * in which case the provisions of the GPL or the LGPL are applicable instead
2193 + * of those above. If you wish to allow use of your version of this file only
2194 + * under the terms of either the GPL or the LGPL, and not to allow others to
2195 + * use your version of this file under the terms of the MPL, indicate your
2196 + * decision by deleting the provisions above and replace them with the notice
2197 + * and other provisions required by the GPL or the LGPL. If you do not delete
2198 + * the provisions above, a recipient may use your version of this file under
2199 + * the terms of any one of the MPL, the GPL or the LGPL.
2201 + * ***** END LICENSE BLOCK ***** */
2203 +#include "nsKDEUtils.h"
2204 +#include "nsIWidget.h"
2206 +#include <gtk/gtk.h>
2208 +#include <limits.h>
2210 +#include <sys/wait.h>
2211 +#include <unistd.h>
2212 +#include <X11/Xlib.h>
2214 +//#define DEBUG_KDE
2216 +#define KMOZILLAHELPER "kmozillahelper"
2218 +// not need for lib64, it's a binary
2219 +#define KMOZILLAHELPER "/usr/lib/mozilla/kmozillahelper"
2222 +#define KMOZILLAHELPER_VERSION 6
2223 +#define MAKE_STR2( n ) #n
2224 +#define MAKE_STR( n ) MAKE_STR2( n )
2226 +static bool getKdeSession()
2228 + Display* dpy = XOpenDisplay( NULL );
2231 + Atom kde_full_session = XInternAtom( dpy, "KDE_FULL_SESSION", True );
2233 + if( kde_full_session != None )
2236 + if( Atom* props = XListProperties( dpy, DefaultRootWindow( dpy ), &cnt ))
2242 + if( props[ i ] == kde_full_session )
2246 + fprintf( stderr, "KDE SESSION %d\n", kde );
2254 + XCloseDisplay( dpy );
2258 +static bool getKdeSupport()
2260 + nsCStringArray command;
2261 + command.AppendCString( NS_LITERAL_CSTRING( "CHECK" ));
2262 + command.AppendCString( NS_LITERAL_CSTRING( MAKE_STR( KMOZILLAHELPER_VERSION )));
2263 + bool kde = nsKDEUtils::command( command );
2265 + fprintf( stderr, "KDE RUNNING %d\n", kde );
2270 +nsKDEUtils::nsKDEUtils()
2271 + : commandFile( NULL )
2272 + , replyFile( NULL )
2276 +nsKDEUtils::~nsKDEUtils()
2278 +// closeHelper(); not actually useful, exiting will close the fd too
2281 +nsKDEUtils* nsKDEUtils::self()
2283 + static nsKDEUtils s;
2287 +static bool helperRunning = false;
2288 +static bool helperFailed = false;
2290 +bool nsKDEUtils::kdeSession()
2292 + static bool session = getKdeSession();
2296 +bool nsKDEUtils::kdeSupport()
2298 + static bool support = kdeSession() && getKdeSupport();
2299 + return support && helperRunning;
2302 +struct nsKDECommandData
2305 + nsCStringArray* output;
2310 +static gboolean kdeReadFunc( GIOChannel*, GIOCondition, gpointer data )
2312 + nsKDECommandData* p = static_cast< nsKDECommandData* >( data );
2313 + char buf[ 8192 ]; // TODO big enough
2314 + bool command_done = false;
2315 + bool command_failed = false;
2316 + while( !command_done && !command_failed && fgets( buf, 8192, p->file ) != NULL )
2317 + { // TODO what if the kernel splits a line into two chunks?
2319 +// fprintf( stderr, "READ: %s %d\n", buf, feof( p->file ));
2321 + if( char* eol = strchr( buf, '\n' ))
2323 + command_done = ( strcmp( buf, "\\1" ) == 0 );
2324 + command_failed = ( strcmp( buf, "\\0" ) == 0 );
2325 + nsCAutoString line( buf );
2326 + line.ReplaceSubstring( "\\n", "\n" );
2327 + line.ReplaceSubstring( "\\" "\\", "\\" ); // \\ -> \ , i.e. unescape
2328 + if( p->output && !( command_done || command_failed ))
2329 + p->output->AppendCString( nsCString( buf )); // TODO utf8?
2331 + bool quit = false;
2332 + if( feof( p->file ) || command_failed )
2335 + p->success = false;
2337 + if( command_done )
2338 + { // reading one reply finished
2340 + p->success = true;
2345 + g_main_loop_quit( p->loop );
2351 +bool nsKDEUtils::command( const nsCStringArray& command, nsCStringArray* output )
2353 + return self()->internalCommand( command, NULL, false, output );
2356 +bool nsKDEUtils::commandBlockUi( const nsCStringArray& command, const GtkWindow* parent, nsCStringArray* output )
2358 + return self()->internalCommand( command, parent, true, output );
2361 +bool nsKDEUtils::internalCommand( const nsCStringArray& command, const GtkWindow* parent, bool blockUi,
2362 + nsCStringArray* output )
2364 + if( !startHelper())
2366 + feedCommand( command );
2367 + // do not store the data in 'this' but in extra structure, just in case there
2368 + // is reentrancy (can there be? the event loop is re-entered)
2369 + nsKDECommandData data;
2370 + data.file = replyFile;
2371 + data.output = output;
2372 + data.success = false;
2375 + data.loop = g_main_loop_new( NULL, FALSE );
2376 + GtkWidget* window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
2377 + if( parent && parent->group )
2378 + gtk_window_group_add_window( parent->group, GTK_WINDOW( window ));
2379 + gtk_widget_realize( window );
2380 + gtk_widget_set_sensitive( window, TRUE );
2381 + gtk_grab_add( window );
2382 + GIOChannel* channel = g_io_channel_unix_new( fileno( data.file ));
2383 + g_io_add_watch( channel, static_cast< GIOCondition >( G_IO_IN | G_IO_ERR | G_IO_HUP ), kdeReadFunc, &data );
2384 + g_io_channel_unref( channel );
2385 + g_main_loop_run( data.loop );
2386 + g_main_loop_unref( data.loop );
2387 + gtk_grab_remove( window );
2388 + gtk_widget_destroy( window );
2393 + while( kdeReadFunc( NULL, static_cast< GIOCondition >( 0 ), &data ))
2396 + return data.success;
2399 +bool nsKDEUtils::startHelper()
2401 + if( helperRunning )
2403 + if( helperFailed )
2405 + helperFailed = true;
2406 + int fdcommand[ 2 ];
2408 + if( pipe( fdcommand ) < 0 )
2410 + if( pipe( fdreply ) < 0 )
2412 + close( fdcommand[ 0 ] );
2413 + close( fdcommand[ 1 ] );
2416 + char* args[ 2 ] = { const_cast< char* >( KMOZILLAHELPER ), NULL };
2421 + close( fdcommand[ 0 ] );
2422 + close( fdcommand[ 1 ] );
2423 + close( fdreply[ 0 ] );
2424 + close( fdreply[ 1 ] );
2429 + if( dup2( fdcommand[ 0 ], STDIN_FILENO ) < 0 )
2431 + if( dup2( fdreply[ 1 ], STDOUT_FILENO ) < 0 )
2433 + int maxfd = 1024; // close all other fds
2435 + if( getrlimit( RLIMIT_NOFILE, &rl ) == 0 )
2436 + maxfd = rl.rlim_max;
2442 + execvp( KMOZILLAHELPER, args );
2444 + execv( KMOZILLAHELPER, args );
2446 + _exit( 1 ); // failed
2448 + default: // parent
2450 + commandFile = fdopen( fdcommand[ 1 ], "w" );
2451 + replyFile = fdopen( fdreply[ 0 ], "r" );
2452 + close( fdcommand[ 0 ] );
2453 + close( fdreply[ 1 ] );
2454 + if( commandFile == NULL || replyFile == NULL )
2459 + // ok, helper ready, getKdeRunning() will check if it works
2462 + helperFailed = false;
2463 + helperRunning = true;
2467 +void nsKDEUtils::closeHelper()
2469 + if( commandFile != NULL )
2470 + fclose( commandFile ); // this will also make the helper quit
2471 + if( replyFile != NULL )
2472 + fclose( replyFile );
2473 + helperRunning = false;
2476 +void nsKDEUtils::feedCommand( const nsCStringArray& command )
2479 + i < command.Count();
2482 + nsCString line = *command[ i ];
2483 + line.ReplaceSubstring( "\\", "\\" "\\" ); // \ -> \\ , i.e. escape
2484 + line.ReplaceSubstring( "\n", "\\n" );
2486 + fprintf( stderr, "COMM: %s\n", line.get());
2488 + fputs( line.get(), commandFile );
2489 + fputs( "\n", commandFile );
2491 + fputs( "\\E\n", commandFile ); // done as \E, so it cannot happen in normal data
2492 + fflush( commandFile );
2494 diff --git a/toolkit/xre/nsKDEUtils.h b/toolkit/xre/nsKDEUtils.h
2495 new file mode 100644
2497 +++ b/toolkit/xre/nsKDEUtils.h
2499 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2501 + * ***** BEGIN LICENSE BLOCK *****
2502 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2504 + * The contents of this file are subject to the Mozilla Public License Version
2505 + * 1.1 (the "License"); you may not use this file except in compliance with
2506 + * the License. You may obtain a copy of the License at
2507 + * http://www.mozilla.org/MPL/
2509 + * Software distributed under the License is distributed on an "AS IS" basis,
2510 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2511 + * for the specific language governing rights and limitations under the
2514 + * The Original Code is Mozilla Communicator client code.
2516 + * The Initial Developer of the Original Code is
2517 + * Netscape Communications Corporation.
2518 + * Portions created by the Initial Developer are Copyright (C) 1998
2519 + * the Initial Developer. All Rights Reserved.
2523 + * Alternatively, the contents of this file may be used under the terms of
2524 + * either of the GNU General Public License Version 2 or later (the "GPL"),
2525 + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2526 + * in which case the provisions of the GPL or the LGPL are applicable instead
2527 + * of those above. If you wish to allow use of your version of this file only
2528 + * under the terms of either the GPL or the LGPL, and not to allow others to
2529 + * use your version of this file under the terms of the MPL, indicate your
2530 + * decision by deleting the provisions above and replace them with the notice
2531 + * and other provisions required by the GPL or the LGPL. If you do not delete
2532 + * the provisions above, a recipient may use your version of this file under
2533 + * the terms of any one of the MPL, the GPL or the LGPL.
2535 + * ***** END LICENSE BLOCK ***** */
2537 +#ifndef nsKDEUtils_h__
2538 +#define nsKDEUtils_h__
2540 +#include "nsStringGlue.h"
2541 +#include "nsVoidArray.h"
2544 +typedef struct _GtkWindow GtkWindow;
2546 +class NS_EXPORT nsKDEUtils
2549 + /* Returns true if running inside a KDE session (regardless of whether there is KDE
2550 + support available for Firefox). This should be used e.g. when determining
2551 + dialog button order but not for code that requires the KDE support. */
2552 + static bool kdeSession();
2553 + /* Returns true if running inside a KDE session and KDE support is available
2554 + for Firefox. This should be used everywhere where the external helper is needed. */
2555 + static bool kdeSupport();
2556 + /* Executes the given helper command, returns true if helper returned success. */
2557 + static bool command( const nsCStringArray& command, nsCStringArray* output = NULL );
2558 + /* Like command(), but additionally blocks the parent widget like if there was
2559 + a modal dialog shown and enters the event loop (i.e. there are still paint updates,
2560 + this is for commands that take long). */
2561 + static bool commandBlockUi( const nsCStringArray& command, const GtkWindow* parent, nsCStringArray* output = NULL );
2565 + static nsKDEUtils* self();
2566 + bool startHelper();
2567 + void closeHelper();
2568 + void feedCommand( const nsCStringArray& command );
2569 + bool internalCommand( const nsCStringArray& command, const GtkWindow* parent, bool isParent,
2570 + nsCStringArray* output );
2571 + FILE* commandFile;
2575 +#endif // nsKDEUtils
2576 diff --git a/uriloader/exthandler/Makefile.in b/uriloader/exthandler/Makefile.in
2577 --- a/uriloader/exthandler/Makefile.in
2578 +++ b/uriloader/exthandler/Makefile.in
2579 @@ -88,18 +88,19 @@ LOCAL_INCLUDES = -I$(srcdir)
2580 LOCAL_INCLUDES += -I$(topsrcdir)/dom/base \
2581 -I$(topsrcdir)/dom/ipc \
2582 -I$(topsrcdir)/content/base/src \
2583 -I$(topsrcdir)/content/events/src \
2584 -I$(topsrcdir)/netwerk/base/src \
2585 -I$(topsrcdir)/netwerk/protocol/http
2587 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
2588 -OSHELPER += nsGNOMERegistry.cpp
2589 +OSHELPER += nsCommonRegistry.cpp nsGNOMERegistry.cpp nsKDERegistry.cpp
2590 OSHELPER += nsMIMEInfoUnix.cpp
2591 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
2594 ifeq ($(MOZ_WIDGET_TOOLKIT),android)
2595 OSHELPER += nsMIMEInfoAndroid.cpp
2596 OSHELPER += nsAndroidHandlerApp.cpp
2597 OSHELPER += nsExternalSharingAppService.cpp
2598 EXPORTS += nsExternalSharingAppService.h
2599 OSHELPER += nsExternalURLHandlerService.cpp
2600 diff --git a/uriloader/exthandler/unix/nsCommonRegistry.cpp b/uriloader/exthandler/unix/nsCommonRegistry.cpp
2601 new file mode 100644
2603 +++ b/uriloader/exthandler/unix/nsCommonRegistry.cpp
2605 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2606 +/* ***** BEGIN LICENSE BLOCK *****
2607 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2609 + * The contents of this file are subject to the Mozilla Public License Version
2610 + * 1.1 (the "License"); you may not use this file except in compliance with
2611 + * the License. You may obtain a copy of the License at
2612 + * http://www.mozilla.org/MPL/
2614 + * Software distributed under the License is distributed on an "AS IS" basis,
2615 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2616 + * for the specific language governing rights and limitations under the
2619 + * The Original Code is the GNOME helper app implementation.
2621 + * The Initial Developer of the Original Code is
2622 + * IBM Corporation.
2623 + * Portions created by the Initial Developer are Copyright (C) 2003
2624 + * the Initial Developer. All Rights Reserved.
2627 + * Brian Ryner <bryner@brianryner.com> (Original Author)
2629 + * Alternatively, the contents of this file may be used under the terms of
2630 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2631 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2632 + * in which case the provisions of the GPL or the LGPL are applicable instead
2633 + * of those above. If you wish to allow use of your version of this file only
2634 + * under the terms of either the GPL or the LGPL, and not to allow others to
2635 + * use your version of this file under the terms of the MPL, indicate your
2636 + * decision by deleting the provisions above and replace them with the notice
2637 + * and other provisions required by the GPL or the LGPL. If you do not delete
2638 + * the provisions above, a recipient may use your version of this file under
2639 + * the terms of any one of the MPL, the GPL or the LGPL.
2641 + * ***** END LICENSE BLOCK ***** */
2643 +#include "nsCommonRegistry.h"
2645 +#include "nsGNOMERegistry.h"
2646 +#include "nsKDERegistry.h"
2647 +#include "nsString.h"
2648 +#include "nsVoidArray.h"
2649 +#include "nsKDEUtils.h"
2651 +/* static */ PRBool
2652 +nsCommonRegistry::HandlerExists(const char *aProtocolScheme)
2654 + if( nsKDEUtils::kdeSupport())
2655 + return nsKDERegistry::HandlerExists( aProtocolScheme );
2656 + return nsGNOMERegistry::HandlerExists( aProtocolScheme );
2659 +/* static */ nsresult
2660 +nsCommonRegistry::LoadURL(nsIURI *aURL)
2662 + if( nsKDEUtils::kdeSupport())
2663 + return nsKDERegistry::LoadURL( aURL );
2664 + return nsGNOMERegistry::LoadURL( aURL );
2668 +nsCommonRegistry::GetAppDescForScheme(const nsACString& aScheme,
2671 + if( nsKDEUtils::kdeSupport())
2672 + return nsKDERegistry::GetAppDescForScheme( aScheme, aDesc );
2673 + return nsGNOMERegistry::GetAppDescForScheme( aScheme, aDesc );
2677 +/* static */ already_AddRefed<nsMIMEInfoBase>
2678 +nsCommonRegistry::GetFromExtension(const nsACString& aFileExt)
2680 + if( nsKDEUtils::kdeSupport())
2681 + return nsKDERegistry::GetFromExtension( aFileExt );
2682 + return nsGNOMERegistry::GetFromExtension( aFileExt );
2685 +/* static */ already_AddRefed<nsMIMEInfoBase>
2686 +nsCommonRegistry::GetFromType(const nsACString& aMIMEType)
2688 + if( nsKDEUtils::kdeSupport())
2689 + return nsKDERegistry::GetFromType( aMIMEType );
2690 + return nsGNOMERegistry::GetFromType( aMIMEType );
2692 diff --git a/uriloader/exthandler/unix/nsCommonRegistry.h b/uriloader/exthandler/unix/nsCommonRegistry.h
2693 new file mode 100644
2695 +++ b/uriloader/exthandler/unix/nsCommonRegistry.h
2697 +/* ***** BEGIN LICENSE BLOCK *****
2698 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2700 + * The contents of this file are subject to the Mozilla Public License Version
2701 + * 1.1 (the "License"); you may not use this file except in compliance with
2702 + * the License. You may obtain a copy of the License at
2703 + * http://www.mozilla.org/MPL/
2705 + * Software distributed under the License is distributed on an "AS IS" basis,
2706 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2707 + * for the specific language governing rights and limitations under the
2710 + * The Original Code is the GNOME helper app implementation.
2712 + * The Initial Developer of the Original Code is
2713 + * IBM Corporation.
2714 + * Portions created by the Initial Developer are Copyright (C) 2003
2715 + * the Initial Developer. All Rights Reserved.
2718 + * Brian Ryner <bryner@brianryner.com> (Original Author)
2720 + * Alternatively, the contents of this file may be used under the terms of
2721 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2722 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2723 + * in which case the provisions of the GPL or the LGPL are applicable instead
2724 + * of those above. If you wish to allow use of your version of this file only
2725 + * under the terms of either the GPL or the LGPL, and not to allow others to
2726 + * use your version of this file under the terms of the MPL, indicate your
2727 + * decision by deleting the provisions above and replace them with the notice
2728 + * and other provisions required by the GPL or the LGPL. If you do not delete
2729 + * the provisions above, a recipient may use your version of this file under
2730 + * the terms of any one of the MPL, the GPL or the LGPL.
2732 + * ***** END LICENSE BLOCK ***** */
2734 +#include "nsIURI.h"
2735 +#include "nsCOMPtr.h"
2737 +class nsMIMEInfoBase;
2739 +class nsCommonRegistry
2742 + static PRBool HandlerExists(const char *aProtocolScheme);
2744 + static nsresult LoadURL(nsIURI *aURL);
2746 + static void GetAppDescForScheme(const nsACString& aScheme,
2747 + nsAString& aDesc);
2749 + static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt);
2751 + static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType);
2753 diff --git a/uriloader/exthandler/unix/nsKDERegistry.cpp b/uriloader/exthandler/unix/nsKDERegistry.cpp
2754 new file mode 100644
2756 +++ b/uriloader/exthandler/unix/nsKDERegistry.cpp
2758 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2759 +/* ***** BEGIN LICENSE BLOCK *****
2760 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2762 + * The contents of this file are subject to the Mozilla Public License Version
2763 + * 1.1 (the "License"); you may not use this file except in compliance with
2764 + * the License. You may obtain a copy of the License at
2765 + * http://www.mozilla.org/MPL/
2767 + * Software distributed under the License is distributed on an "AS IS" basis,
2768 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2769 + * for the specific language governing rights and limitations under the
2772 + * The Original Code is the GNOME helper app implementation.
2774 + * The Initial Developer of the Original Code is
2775 + * IBM Corporation.
2776 + * Portions created by the Initial Developer are Copyright (C) 2003
2777 + * the Initial Developer. All Rights Reserved.
2780 + * Brian Ryner <bryner@brianryner.com> (Original Author)
2782 + * Alternatively, the contents of this file may be used under the terms of
2783 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2784 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2785 + * in which case the provisions of the GPL or the LGPL are applicable instead
2786 + * of those above. If you wish to allow use of your version of this file only
2787 + * under the terms of either the GPL or the LGPL, and not to allow others to
2788 + * use your version of this file under the terms of the MPL, indicate your
2789 + * decision by deleting the provisions above and replace them with the notice
2790 + * and other provisions required by the GPL or the LGPL. If you do not delete
2791 + * the provisions above, a recipient may use your version of this file under
2792 + * the terms of any one of the MPL, the GPL or the LGPL.
2794 + * ***** END LICENSE BLOCK ***** */
2796 +#include "nsKDERegistry.h"
2797 +#include "prlink.h"
2799 +#include "nsString.h"
2800 +#include "nsILocalFile.h"
2801 +#include "nsMIMEInfoUnix.h"
2802 +#include "nsAutoPtr.h"
2803 +#include "nsKDEUtils.h"
2805 +/* static */ PRBool
2806 +nsKDERegistry::HandlerExists(const char *aProtocolScheme)
2808 + nsCStringArray command;
2809 + command.AppendCString( NS_LITERAL_CSTRING( "HANDLEREXISTS" ));
2810 + command.AppendCString( nsCAutoString( aProtocolScheme ));
2811 + return nsKDEUtils::command( command );
2814 +/* static */ nsresult
2815 +nsKDERegistry::LoadURL(nsIURI *aURL)
2817 + nsCStringArray command;
2818 + command.AppendCString( NS_LITERAL_CSTRING( "OPEN" ));
2820 + aURL->GetSpec( url );
2821 + command.AppendCString( url );
2822 + return nsKDEUtils::command( command );
2826 +nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme,
2829 + nsCStringArray command;
2830 + command.AppendCString( NS_LITERAL_CSTRING( "GETAPPDESCFORSCHEME" ));
2831 + command.AppendCString( aScheme );
2832 + nsCStringArray output;
2833 + if( nsKDEUtils::command( command, &output ) && output.Count() == 1 )
2834 + CopyUTF8toUTF16( *output[ 0 ], aDesc );
2838 +/* static */ already_AddRefed<nsMIMEInfoBase>
2839 +nsKDERegistry::GetFromExtension(const nsACString& aFileExt)
2841 + NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot");
2842 + nsCStringArray command;
2843 + command.AppendCString( NS_LITERAL_CSTRING( "GETFROMEXTENSION" ));
2844 + command.AppendCString( aFileExt );
2845 + return GetFromHelper( command );
2848 +/* static */ already_AddRefed<nsMIMEInfoBase>
2849 +nsKDERegistry::GetFromType(const nsACString& aMIMEType)
2851 + nsCStringArray command;
2852 + command.AppendCString( NS_LITERAL_CSTRING( "GETFROMTYPE" ));
2853 + command.AppendCString( aMIMEType );
2854 + return GetFromHelper( command );
2857 +/* static */ already_AddRefed<nsMIMEInfoBase>
2858 +nsKDERegistry::GetFromHelper(const nsCStringArray& command)
2860 + nsCStringArray output;
2861 + if( nsKDEUtils::command( command, &output ) && output.Count() == 3 )
2863 + nsCString mimetype = *output[ 0 ];
2864 + nsRefPtr<nsMIMEInfoUnix> mimeInfo = new nsMIMEInfoUnix( mimetype );
2865 + NS_ENSURE_TRUE(mimeInfo, nsnull);
2866 + nsCString description = *output[ 1 ];
2867 + mimeInfo->SetDescription(NS_ConvertUTF8toUTF16(description));
2868 + nsCString handlerAppName = *output[ 2 ];
2869 + mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUTF16(handlerAppName));
2870 + mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault);
2871 + nsMIMEInfoBase* retval;
2872 + NS_ADDREF((retval = mimeInfo));
2877 diff --git a/uriloader/exthandler/unix/nsKDERegistry.h b/uriloader/exthandler/unix/nsKDERegistry.h
2878 new file mode 100644
2880 +++ b/uriloader/exthandler/unix/nsKDERegistry.h
2882 +/* ***** BEGIN LICENSE BLOCK *****
2883 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2885 + * The contents of this file are subject to the Mozilla Public License Version
2886 + * 1.1 (the "License"); you may not use this file except in compliance with
2887 + * the License. You may obtain a copy of the License at
2888 + * http://www.mozilla.org/MPL/
2890 + * Software distributed under the License is distributed on an "AS IS" basis,
2891 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2892 + * for the specific language governing rights and limitations under the
2895 + * The Original Code is the GNOME helper app implementation.
2897 + * The Initial Developer of the Original Code is
2898 + * IBM Corporation.
2899 + * Portions created by the Initial Developer are Copyright (C) 2003
2900 + * the Initial Developer. All Rights Reserved.
2903 + * Brian Ryner <bryner@brianryner.com> (Original Author)
2905 + * Alternatively, the contents of this file may be used under the terms of
2906 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2907 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2908 + * in which case the provisions of the GPL or the LGPL are applicable instead
2909 + * of those above. If you wish to allow use of your version of this file only
2910 + * under the terms of either the GPL or the LGPL, and not to allow others to
2911 + * use your version of this file under the terms of the MPL, indicate your
2912 + * decision by deleting the provisions above and replace them with the notice
2913 + * and other provisions required by the GPL or the LGPL. If you do not delete
2914 + * the provisions above, a recipient may use your version of this file under
2915 + * the terms of any one of the MPL, the GPL or the LGPL.
2917 + * ***** END LICENSE BLOCK ***** */
2919 +#include "nsIURI.h"
2920 +#include "nsCOMPtr.h"
2922 +class nsMIMEInfoBase;
2923 +class nsCAutoString;
2924 +class nsCStringArray;
2926 +class nsKDERegistry
2929 + static PRBool HandlerExists(const char *aProtocolScheme);
2931 + static nsresult LoadURL(nsIURI *aURL);
2933 + static void GetAppDescForScheme(const nsACString& aScheme,
2934 + nsAString& aDesc);
2936 + static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt);
2938 + static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType);
2940 + static already_AddRefed<nsMIMEInfoBase> GetFromHelper(const nsCStringArray& command);
2943 diff --git a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp
2944 --- a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp
2945 +++ b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp
2948 #if (MOZ_ENABLE_CONTENTACTION)
2949 #include <contentaction/contentaction.h>
2950 #include "nsContentHandlerApp.h"
2954 #include "nsMIMEInfoUnix.h"
2955 -#include "nsGNOMERegistry.h"
2956 +#include "nsCommonRegistry.h"
2957 #include "nsIGIOService.h"
2958 #include "nsNetCID.h"
2959 #include "nsIIOService.h"
2960 #include "nsIGnomeVFSService.h"
2961 #include "nsAutoPtr.h"
2962 #ifdef MOZ_ENABLE_DBUS
2963 #include "nsDBusHandlerApp.h"
2965 +#if defined(XP_UNIX) && !defined(XP_MACOSX)
2966 +#include "nsKDEUtils.h"
2970 nsMIMEInfoUnix::LoadUriInternal(nsIURI * aURI)
2972 - nsresult rv = nsGNOMERegistry::LoadURL(aURI);
2973 + nsresult rv = nsCommonRegistry::LoadURL(aURI);
2975 #if (MOZ_PLATFORM_MAEMO == 5) && defined (MOZ_ENABLE_GNOMEVFS)
2977 HildonURIAction *action = hildon_uri_get_default_action(mSchemeOrType.get(), nsnull);
2980 aURI->GetAsciiSpec(spec);
2981 if (hildon_uri_open(spec.get(), action, nsnull))
2982 @@ -95,22 +98,22 @@ nsMIMEInfoUnix::LoadUriInternal(nsIURI *
2988 nsMIMEInfoUnix::GetHasDefaultHandler(PRBool *_retval)
2990 *_retval = PR_FALSE;
2991 - nsRefPtr<nsMIMEInfoBase> mimeInfo = nsGNOMERegistry::GetFromType(mSchemeOrType);
2992 + nsRefPtr<nsMIMEInfoBase> mimeInfo = nsCommonRegistry::GetFromType(mSchemeOrType);
2995 nsresult rv = GetPrimaryExtension(ext);
2996 if (NS_SUCCEEDED(rv)) {
2997 - mimeInfo = nsGNOMERegistry::GetFromExtension(ext);
2998 + mimeInfo = nsCommonRegistry::GetFromExtension(ext);
3007 @@ -153,16 +156,33 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(ns
3008 ContentAction::Action::defaultActionForFile(uri, QString(mSchemeOrType.get()));
3009 if (action.isValid()) {
3013 return NS_ERROR_FAILURE;
3016 + if( nsKDEUtils::kdeSupport()) {
3018 + if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) {
3019 + nsCStringArray command;
3020 + command.AppendCString( NS_LITERAL_CSTRING( "OPEN" ));
3021 + command.AppendCString( nativePath );
3022 + command.AppendCString( NS_LITERAL_CSTRING( "MIMETYPE" ));
3023 + command.AppendCString( mSchemeOrType );
3024 + if( nsKDEUtils::command( command ))
3027 + if (!mDefaultApplication)
3028 + return NS_ERROR_FILE_NOT_FOUND;
3030 + return LaunchWithIProcess(mDefaultApplication, nativePath);
3033 nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
3034 nsCAutoString uriSpec;
3036 // nsGIOMimeApp->Launch wants a URI string instead of local file
3038 nsCOMPtr<nsIIOService> ioservice = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
3039 NS_ENSURE_SUCCESS(rv, rv);
3040 nsCOMPtr<nsIURI> uri;
3041 @@ -180,17 +200,17 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(ns
3042 /* Fallback to GnomeVFS */
3043 nsCOMPtr<nsIGnomeVFSMimeApp> app;
3044 if (NS_SUCCEEDED(gnomevfs->GetAppForMimeType(mSchemeOrType, getter_AddRefs(app))) && app)
3045 return app->Launch(nativePath);
3048 // If we haven't got an app we try to get a valid one by searching for the
3049 // extension mapped type
3050 - nsRefPtr<nsMIMEInfoBase> mimeInfo = nsGNOMERegistry::GetFromExtension(nativePath);
3051 + nsRefPtr<nsMIMEInfoBase> mimeInfo = nsCommonRegistry::GetFromExtension(nativePath);
3054 mimeInfo->GetType(type);
3056 nsCOMPtr<nsIGIOMimeApp> app;
3057 if (NS_SUCCEEDED(giovfs->GetAppForMimeType(type, getter_AddRefs(app))) && app)
3058 return app->Launch(uriSpec);
3059 } else if (gnomevfs) {
3060 diff --git a/uriloader/exthandler/unix/nsOSHelperAppService.cpp b/uriloader/exthandler/unix/nsOSHelperAppService.cpp
3061 --- a/uriloader/exthandler/unix/nsOSHelperAppService.cpp
3062 +++ b/uriloader/exthandler/unix/nsOSHelperAppService.cpp
3064 #if defined(MOZ_ENABLE_CONTENTACTION)
3065 #include <contentaction/contentaction.h>
3069 #include "nsOSHelperAppService.h"
3070 #include "nsMIMEInfoUnix.h"
3071 #ifdef MOZ_WIDGET_GTK2
3072 -#include "nsGNOMERegistry.h"
3073 +#include "nsCommonRegistry.h"
3075 #include "nsISupports.h"
3076 #include "nsString.h"
3077 #include "nsReadableUtils.h"
3078 #include "nsUnicharUtils.h"
3079 #include "nsXPIDLString.h"
3081 #include "nsIFileStreams.h"
3082 @@ -1219,29 +1219,29 @@ nsresult nsOSHelperAppService::OSProtoco
3083 ContentAction::Action::defaultActionForScheme(QString(aProtocolScheme) + ':');
3085 if (action.isValid())
3086 *aHandlerExists = PR_TRUE;
3089 #ifdef MOZ_WIDGET_GTK2
3090 // Check the GConf registry for a protocol handler
3091 - *aHandlerExists = nsGNOMERegistry::HandlerExists(aProtocolScheme);
3092 + *aHandlerExists = nsCommonRegistry::HandlerExists(aProtocolScheme);
3093 #if (MOZ_PLATFORM_MAEMO == 5) && defined (MOZ_ENABLE_GNOMEVFS)
3094 *aHandlerExists = nsMIMEInfoUnix::HandlerExists(aProtocolScheme);
3101 NS_IMETHODIMP nsOSHelperAppService::GetApplicationDescription(const nsACString& aScheme, nsAString& _retval)
3103 #ifdef MOZ_WIDGET_GTK2
3104 - nsGNOMERegistry::GetAppDescForScheme(aScheme, _retval);
3105 + nsCommonRegistry::GetAppDescForScheme(aScheme, _retval);
3106 return _retval.IsEmpty() ? NS_ERROR_NOT_AVAILABLE : NS_OK;
3108 return NS_ERROR_NOT_AVAILABLE;
3112 nsresult nsOSHelperAppService::GetFileTokenForPath(const PRUnichar * platformAppPath, nsIFile ** aFile)
3114 @@ -1327,17 +1327,17 @@ nsOSHelperAppService::GetFromExtension(c
3116 mime_types_description,
3119 if (NS_FAILED(rv) || majorType.IsEmpty()) {
3121 #ifdef MOZ_WIDGET_GTK2
3122 LOG(("Looking in GNOME registry\n"));
3123 - nsMIMEInfoBase *gnomeInfo = nsGNOMERegistry::GetFromExtension(aFileExt).get();
3124 + nsMIMEInfoBase *gnomeInfo = nsCommonRegistry::GetFromExtension(aFileExt).get();
3126 LOG(("Got MIMEInfo from GNOME registry\n"));
3131 rv = LookUpTypeAndDescription(NS_ConvertUTF8toUTF16(aFileExt),
3133 @@ -1453,17 +1453,17 @@ nsOSHelperAppService::GetFromType(const
3134 #ifdef MOZ_WIDGET_GTK2
3135 nsMIMEInfoBase *gnomeInfo = nsnull;
3136 if (handler.IsEmpty()) {
3137 // No useful data yet. Check the GNOME registry. Unfortunately, newer
3138 // GNOME versions no longer have type-to-extension mappings, so we might
3139 // get back a MIMEInfo without any extensions set. In that case we'll have
3140 // to look in our mime.types files for the extensions.
3141 LOG(("Looking in GNOME registry\n"));
3142 - gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType).get();
3143 + gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType).get();
3144 if (gnomeInfo && gnomeInfo->HasExtensions()) {
3145 LOG(("Got MIMEInfo from GNOME registry, and it has extensions set\n"));
3151 // Now look up our extensions
3152 diff --git a/widget/src/gtk2/Makefile.in b/widget/src/gtk2/Makefile.in
3153 --- a/widget/src/gtk2/Makefile.in
3154 +++ b/widget/src/gtk2/Makefile.in
3155 @@ -157,11 +157,14 @@ endif
3157 DEFINES += -DCAIRO_GFX
3160 -I$(srcdir)/../xpwidgets \
3161 -I$(srcdir)/../shared \
3162 -I$(topsrcdir)/other-licenses/atk-1.0 \
3165 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
3168 INCLUDES += -I$(srcdir)/../shared/x11
3170 diff --git a/widget/src/gtk2/nsFilePicker.cpp b/widget/src/gtk2/nsFilePicker.cpp
3171 --- a/widget/src/gtk2/nsFilePicker.cpp
3172 +++ b/widget/src/gtk2/nsFilePicker.cpp
3174 * decision by deleting the provisions above and replace them with the notice
3175 * and other provisions required by the GPL or the LGPL. If you do not delete
3176 * the provisions above, a recipient may use your version of this file under
3177 * the terms of any one of the MPL, the GPL or the LGPL.
3179 * ***** END LICENSE BLOCK ***** */
3181 #include <gtk/gtk.h>
3182 +#include <gdk/gdkx.h>
3184 #include "nsIFileURL.h"
3186 #include "nsIWidget.h"
3187 #include "nsILocalFile.h"
3188 #include "nsIStringBundle.h"
3190 #include "nsArrayEnumerator.h"
3192 #include "nsReadableUtils.h"
3193 #include "mozcontainer.h"
3198 #include "nsFilePicker.h"
3199 #include "nsAccessibilityHelper.h"
3200 +#include "nsKDEUtils.h"
3202 #if (MOZ_PLATFORM_MAEMO == 5)
3203 #include <hildon-fm-2/hildon/hildon-file-chooser-dialog.h>
3206 #define MAX_PREVIEW_SIZE 180
3208 nsILocalFile *nsFilePicker::mPrevDisplayDirectory = nsnull;
3209 @@ -271,17 +273,19 @@ nsFilePicker::AppendFilters(PRInt32 aFil
3210 return nsBaseFilePicker::AppendFilters(aFilterMask);
3214 nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
3216 if (aFilter.EqualsLiteral("..apps")) {
3217 // No platform specific thing we can do here, really....
3219 + // Unless it's KDE.
3220 + if( mMode != modeOpen || !nsKDEUtils::kdeSupport())
3224 nsCAutoString filter, name;
3225 CopyUTF16toUTF8(aFilter, filter);
3226 CopyUTF16toUTF8(aTitle, name);
3228 mFilters.AppendElement(filter);
3229 mFilterNames.AppendElement(name);
3230 @@ -419,16 +423,19 @@ confirm_overwrite_file(GtkWidget *parent
3231 gtk_widget_destroy(dialog);
3237 nsFilePicker::Show(PRInt16 *aReturn)
3239 + if( nsKDEUtils::kdeSupport())
3240 + return kdeFileDialog( aReturn );
3242 NS_ENSURE_ARG_POINTER(aReturn);
3244 nsXPIDLCString title;
3245 title.Adopt(ToNewUTF8String(mTitle));
3247 GtkWindow *parent_widget = get_gtk_window_for_nsiwidget(mParentWidget);
3249 GtkFileChooserAction action = GetGtkFileChooserAction(mMode);
3250 @@ -569,8 +576,234 @@ nsFilePicker::Show(PRInt16 *aReturn)
3251 *aReturn = nsIFilePicker::returnCancel;
3255 gtk_widget_destroy(file_chooser);
3260 +nsCString nsFilePicker::kdeMakeFilter( int index )
3262 + nsCString buf = mFilters[ index ];
3263 + for( PRUint32 i = 0;
3266 + if( buf[ i ] == ';' ) // KDE separates just using spaces
3267 + buf.SetCharAt( ' ', i );
3268 + if (!mFilterNames[index].IsEmpty())
3271 + buf += mFilterNames[index].get();
3276 +static PRInt32 windowToXid( nsIWidget* widget )
3278 + GtkWindow *parent_widget = get_gtk_window_for_nsiwidget( widget );
3279 + GdkWindow* gdk_window = gtk_widget_get_window( gtk_widget_get_toplevel( GTK_WIDGET( parent_widget )));
3280 + return GDK_WINDOW_XID( gdk_window );
3283 +NS_IMETHODIMP nsFilePicker::kdeFileDialog(PRInt16 *aReturn)
3285 + NS_ENSURE_ARG_POINTER(aReturn);
3287 + if( mMode == modeOpen && mFilters.Length() == 1 && mFilters[ 0 ].EqualsLiteral( "..apps" ))
3288 + return kdeAppsDialog( aReturn );
3290 + nsXPIDLCString title;
3291 + title.Adopt(ToNewUTF8String(mTitle));
3293 + const char* arg = NULL;
3298 + case nsIFilePicker::modeOpen:
3299 + case nsIFilePicker::modeOpenMultiple:
3300 + arg = "GETOPENURL";
3302 + case nsIFilePicker::modeSave:
3303 + arg = "GETSAVEURL";
3305 + case nsIFilePicker::modeGetFolder:
3306 + arg = "GETDIRECTORYURL";
3314 + case nsIFilePicker::modeOpen:
3315 + case nsIFilePicker::modeOpenMultiple:
3316 + arg = "GETOPENFILENAME";
3318 + case nsIFilePicker::modeSave:
3319 + arg = "GETSAVEFILENAME";
3321 + case nsIFilePicker::modeGetFolder:
3322 + arg = "GETDIRECTORYFILENAME";
3327 + nsCAutoString directory;
3328 + if (mDisplayDirectory) {
3329 + mDisplayDirectory->GetNativePath(directory);
3330 + } else if (mPrevDisplayDirectory) {
3331 + mPrevDisplayDirectory->GetNativePath(directory);
3334 + nsCAutoString startdir;
3335 + if (!directory.IsEmpty()) {
3336 + startdir = directory;
3338 + if (mMode == nsIFilePicker::modeSave) {
3339 + if( !startdir.IsEmpty())
3342 + startdir += ToNewUTF8String(mDefault);
3345 + startdir = ToNewUTF8String(mDefault);
3347 + if( startdir.IsEmpty())
3350 + nsCAutoString filters;
3351 + PRInt32 count = mFilters.Length();
3352 + if( count == 0 ) //just in case
3356 + filters = kdeMakeFilter( 0 );
3357 + for (PRInt32 i = 1; i < count; ++i)
3360 + filters += kdeMakeFilter( i );
3364 + nsCStringArray command;
3365 + command.AppendCString( nsCAutoString( arg ));
3366 + command.AppendCString( startdir );
3367 + if( mMode != nsIFilePicker::modeGetFolder )
3369 + command.AppendCString( filters );
3370 + nsCAutoString selected;
3371 + selected.AppendInt( mSelectedType );
3372 + command.AppendCString( selected );
3374 + command.AppendCString( title );
3375 + if( mMode == nsIFilePicker::modeOpenMultiple )
3376 + command.AppendCString( NS_LITERAL_CSTRING( "MULTIPLE" ));
3377 + if( PRInt32 xid = windowToXid( mParentWidget ))
3379 + command.AppendCString( NS_LITERAL_CSTRING( "PARENT" ));
3380 + nsCAutoString parent;
3381 + parent.AppendInt( xid );
3382 + command.AppendCString( parent );
3385 + nsCStringArray output;
3386 + if( nsKDEUtils::commandBlockUi( command, get_gtk_window_for_nsiwidget( mParentWidget ), &output ))
3388 + *aReturn = nsIFilePicker::returnOK;
3390 + if( mMode != nsIFilePicker::modeGetFolder )
3392 + mSelectedType = atoi( output[ 0 ]->get());
3393 + output.RemoveCStringAt( 0 );
3395 + if (mMode == nsIFilePicker::modeOpenMultiple)
3397 + mFileURL.Truncate();
3398 + PRUint32 count = output.Count();
3399 + for( PRUint32 i = 0;
3403 + nsCOMPtr<nsILocalFile> localfile;
3404 + nsresult rv = NS_NewNativeLocalFile( *output[ i ],
3406 + getter_AddRefs(localfile));
3407 + if (NS_SUCCEEDED(rv))
3408 + mFiles.AppendObject(localfile);
3413 + if( output.Count() == 0 )
3414 + mFileURL = nsCString();
3415 + else if( mAllowURLs )
3416 + mFileURL = *output[ 0 ];
3417 + else // GetFile() actually requires it to be url even for local files :-/
3419 + mFileURL = nsCString( "file://" );
3420 + mFileURL.Append( *output[ 0 ] );
3423 + // Remember last used directory.
3424 + nsCOMPtr<nsILocalFile> file;
3425 + GetFile(getter_AddRefs(file));
3427 + nsCOMPtr<nsIFile> dir;
3428 + file->GetParent(getter_AddRefs(dir));
3429 + nsCOMPtr<nsILocalFile> localDir(do_QueryInterface(dir));
3431 + localDir.swap(mPrevDisplayDirectory);
3434 + if (mMode == nsIFilePicker::modeSave)
3436 + nsCOMPtr<nsILocalFile> file;
3437 + GetFile(getter_AddRefs(file));
3440 + PRBool exists = PR_FALSE;
3441 + file->Exists(&exists);
3442 + if (exists) // TODO do overwrite check in the helper app
3443 + *aReturn = nsIFilePicker::returnReplace;
3449 + *aReturn = nsIFilePicker::returnCancel;
3455 +NS_IMETHODIMP nsFilePicker::kdeAppsDialog(PRInt16 *aReturn)
3457 + NS_ENSURE_ARG_POINTER(aReturn);
3459 + nsXPIDLCString title;
3460 + title.Adopt(ToNewUTF8String(mTitle));
3462 + nsCStringArray command;
3463 + command.AppendCString( NS_LITERAL_CSTRING( "APPSDIALOG" ));
3464 + command.AppendCString( title );
3465 + if( PRInt32 xid = windowToXid( mParentWidget ))
3467 + command.AppendCString( NS_LITERAL_CSTRING( "PARENT" ));
3468 + nsCAutoString parent;
3469 + parent.AppendInt( xid );
3470 + command.AppendCString( parent );
3473 + nsCStringArray output;
3474 + if( nsKDEUtils::commandBlockUi( command, get_gtk_window_for_nsiwidget( mParentWidget ), &output ))
3476 + *aReturn = nsIFilePicker::returnOK;
3477 + mFileURL = output.Count() > 0 ? *output[ 0 ] : nsCString();
3481 + *aReturn = nsIFilePicker::returnCancel;
3485 diff --git a/widget/src/gtk2/nsFilePicker.h b/widget/src/gtk2/nsFilePicker.h
3486 --- a/widget/src/gtk2/nsFilePicker.h
3487 +++ b/widget/src/gtk2/nsFilePicker.h
3488 @@ -89,11 +89,17 @@ protected:
3490 nsString mDefaultExtension;
3492 nsTArray<nsCString> mFilters;
3493 nsTArray<nsCString> mFilterNames;
3496 static nsILocalFile *mPrevDisplayDirectory;
3498 + bool kdeRunning();
3499 + bool getKdeRunning();
3500 + NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn);
3501 + NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn);
3502 + nsCString kdeMakeFilter( int index );
3506 diff --git a/xpcom/components/Makefile.in b/xpcom/components/Makefile.in
3507 --- a/xpcom/components/Makefile.in
3508 +++ b/xpcom/components/Makefile.in
3509 @@ -94,10 +94,11 @@ FORCE_STATIC_LIB = 1
3513 include $(topsrcdir)/config/rules.mk
3515 DEFINES += -D_IMPL_NS_COM
3517 ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
3518 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
3519 CXXFLAGS += $(MOZ_GTK2_CFLAGS)
3521 diff --git a/xpcom/components/ManifestParser.cpp b/xpcom/components/ManifestParser.cpp
3522 --- a/xpcom/components/ManifestParser.cpp
3523 +++ b/xpcom/components/ManifestParser.cpp
3525 #include "nsTextFormatter.h"
3526 #include "nsVersionComparator.h"
3527 #include "nsXPCOMCIDInternal.h"
3529 #include "nsIConsoleService.h"
3530 #include "nsIScriptError.h"
3531 #include "nsIXULAppInfo.h"
3532 #include "nsIXULRuntime.h"
3533 +#include "nsKDEUtils.h"
3535 struct ManifestDirective
3537 const char* directive;
3540 // Some directives should only be delivered for NS_COMPONENT_LOCATION
3542 @@ -422,16 +423,17 @@ ParseManifestCommon(NSLocationType aType
3544 NS_NAMED_LITERAL_STRING(kPlatform, "platform");
3545 NS_NAMED_LITERAL_STRING(kContentAccessible, "contentaccessible");
3546 NS_NAMED_LITERAL_STRING(kApplication, "application");
3547 NS_NAMED_LITERAL_STRING(kAppVersion, "appversion");
3548 NS_NAMED_LITERAL_STRING(kOs, "os");
3549 NS_NAMED_LITERAL_STRING(kOsVersion, "osversion");
3550 NS_NAMED_LITERAL_STRING(kABI, "abi");
3551 + NS_NAMED_LITERAL_STRING(kDesktop, "desktop");
3554 NS_NAMED_LITERAL_STRING(kXPCNativeWrappers, "xpcnativewrappers");
3557 nsAutoString appVersion;
3558 nsAutoString osTarget;
3560 @@ -461,35 +463,39 @@ ParseManifestCommon(NSLocationType aType
3561 CopyUTF8toUTF16(s, abi);
3562 abi.Insert(PRUnichar('_'), 0);
3563 abi.Insert(osTarget, 0);
3568 nsAutoString osVersion;
3569 + nsAutoString desktop;
3571 OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
3572 if (GetVersionEx(&info)) {
3573 nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
3574 info.dwMajorVersion,
3575 info.dwMinorVersion);
3577 + desktop = NS_LITERAL_STRING("win");
3578 #elif defined(XP_MACOSX)
3579 SInt32 majorVersion, minorVersion;
3580 if ((Gestalt(gestaltSystemVersionMajor, &majorVersion) == noErr) &&
3581 (Gestalt(gestaltSystemVersionMinor, &minorVersion) == noErr)) {
3582 nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
3586 + desktop = NS_LITERAL_STRING("macosx");
3587 #elif defined(MOZ_WIDGET_GTK2)
3588 nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
3591 + desktop = nsKDEUtils::kdeSession() ? NS_LITERAL_STRING("kde") : NS_LITERAL_STRING("gnome");
3594 // Because contracts must be registered after CIDs, we save and process them
3596 nsTArray<CachedDirective> contracts;
3599 char *newline = buf;
3600 @@ -558,24 +564,26 @@ ParseManifestCommon(NSLocationType aType
3602 TriState stAppVersion = eUnspecified;
3603 TriState stApp = eUnspecified;
3604 TriState stOsVersion = eUnspecified;
3605 TriState stOs = eUnspecified;
3606 TriState stABI = eUnspecified;
3607 bool platform = false;
3608 bool contentAccessible = false;
3609 + TriState stDesktop = eUnspecified;
3611 while (NULL != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && ok) {
3613 NS_ConvertASCIItoUTF16 wtoken(token);
3615 if (CheckStringFlag(kApplication, wtoken, appID, stApp) ||
3616 CheckStringFlag(kOs, wtoken, osTarget, stOs) ||
3617 CheckStringFlag(kABI, wtoken, abi, stABI) ||
3618 + CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) ||
3619 CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) ||
3620 CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion))
3623 if (directive->contentflags &&
3624 (CheckFlag(kPlatform, wtoken, platform) ||
3625 CheckFlag(kContentAccessible, wtoken, contentAccessible)))
3627 @@ -594,16 +602,17 @@ ParseManifestCommon(NSLocationType aType
3633 stAppVersion == eBad ||
3635 stOsVersion == eBad ||
3636 + stDesktop == eBad ||
3640 if (directive->regfunc) {
3641 if (GeckoProcessType_Default != XRE_GetProcessType())
3644 if (!nsChromeRegistry::gChromeRegistry) {
3645 diff --git a/xpcom/io/Makefile.in b/xpcom/io/Makefile.in
3646 --- a/xpcom/io/Makefile.in
3647 +++ b/xpcom/io/Makefile.in
3648 @@ -192,17 +192,17 @@ include $(topsrcdir)/ipc/chromium/chromi
3649 DEFINES += -D_IMPL_NS_COM
3651 ifeq ($(OS_ARCH),Linux)
3652 ifneq (,$(findstring lib64,$(libdir)))
3653 DEFINES += -DHAVE_USR_LIB64_DIR
3657 -LOCAL_INCLUDES += -I..
3658 +LOCAL_INCLUDES += -I.. -I$(topsrcdir)/toolkit/xre
3660 ifeq ($(MOZ_PLATFORM_MAEMO),5)
3661 CFLAGS += $(MOZ_DBUS_CFLAGS)
3662 CXXFLAGS += $(MOZ_DBUS_CFLAGS)
3665 ifdef MOZ_PLATFORM_MAEMO
3666 CFLAGS += $(MOZ_PLATFORM_MAEMO_CFLAGS) $(MOZ_QT_CFLAGS)
3667 diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp
3668 --- a/xpcom/io/nsLocalFileUnix.cpp
3669 +++ b/xpcom/io/nsLocalFileUnix.cpp
3671 #include "prproces.h"
3672 #include "nsIDirectoryEnumerator.h"
3673 #include "nsISimpleEnumerator.h"
3674 #include "nsITimelineService.h"
3676 #ifdef MOZ_WIDGET_GTK2
3677 #include "nsIGIOService.h"
3678 #include "nsIGnomeVFSService.h"
3679 +#include "nsKDEUtils.h"
3683 #include <Carbon/Carbon.h>
3684 #include "CocoaFileUtils.h"
3686 #include "plbase64.h"
3688 @@ -1730,44 +1731,50 @@ nsLocalFile::SetPersistentDescriptor(con
3689 return InitWithNativePath(aPersistentDescriptor);
3694 nsLocalFile::Reveal()
3696 #ifdef MOZ_WIDGET_GTK2
3697 - nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
3698 - nsCOMPtr<nsIGnomeVFSService> gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
3699 - if (!giovfs && !gnomevfs)
3700 - return NS_ERROR_FAILURE;
3702 + nsCAutoString url;
3704 if (NS_FAILED(IsDirectory(&isDirectory)))
3705 return NS_ERROR_FAILURE;
3709 - return giovfs->ShowURIForInput(mPath);
3711 - /* Fallback to GnomeVFS */
3712 - return gnomevfs->ShowURIForInput(mPath);
3715 nsCOMPtr<nsIFile> parentDir;
3716 nsCAutoString dirPath;
3717 if (NS_FAILED(GetParent(getter_AddRefs(parentDir))))
3718 return NS_ERROR_FAILURE;
3719 if (NS_FAILED(parentDir->GetNativePath(dirPath)))
3720 return NS_ERROR_FAILURE;
3723 - return giovfs->ShowURIForInput(dirPath);
3725 - return gnomevfs->ShowURIForInput(dirPath);
3729 + if(nsKDEUtils::kdeSupport()) {
3730 + nsCStringArray command;
3731 + command.AppendCString( NS_LITERAL_CSTRING( "OPEN" ));
3732 + command.AppendCString( url );
3733 + return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE;
3736 + nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
3737 + nsCOMPtr<nsIGnomeVFSService> gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
3738 + if (!giovfs && !gnomevfs)
3739 + return NS_ERROR_FAILURE;
3742 + return giovfs->ShowURIForInput(url);
3744 + return gnomevfs->ShowURIForInput(url);
3745 #elif defined(XP_MACOSX)
3747 if (NS_SUCCEEDED(GetCFURL(&url))) {
3748 nsresult rv = CocoaFileUtils::RevealFileInFinder(url);
3752 return NS_ERROR_FAILURE;
3753 @@ -1793,16 +1800,23 @@ nsLocalFile::Launch()
3755 if (nsnull == connection)
3756 return NS_ERROR_FAILURE;
3758 if (hildon_mime_open_file(connection, mPath.get()) != kHILDON_SUCCESS)
3759 return NS_ERROR_FAILURE;
3762 + if( nsKDEUtils::kdeSupport()) {
3763 + nsCStringArray command;
3764 + command.AppendCString( NS_LITERAL_CSTRING( "OPEN" ));
3765 + command.AppendCString( mPath );
3766 + return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE;
3769 nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
3770 nsCOMPtr<nsIGnomeVFSService> gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
3772 return giovfs->ShowURIForInput(mPath);
3773 } else if (gnomevfs) {
3774 /* GnomeVFS fallback */
3775 return gnomevfs->ShowURIForInput(mPath);