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 @@ -77,14 +77,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/Preferences.cpp b/modules/libpref/src/Preferences.cpp
22 --- a/modules/libpref/src/Preferences.cpp
23 +++ b/modules/libpref/src/Preferences.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 @@ -956,30 +957,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 static nsresult pref_ReadPrefFromJar(nsZipArchive* jarReader, const char *name)
92 @@ -1072,28 +1091,40 @@ 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_MACOSX)
99 #elif defined(XP_UNIX)
101 + , "" // placeholder for KDE (empty is otherwise harmless)
107 #elif defined(XP_OS2)
109 #elif defined(XP_BEOS)
114 + if(nsKDEUtils::kdeSession()) { // TODO what if some setup actually requires the helper?
116 + i < NS_ARRAY_LENGTH(specialFiles);
118 + if( *specialFiles[ i ] == '\0' ) {
119 + specialFiles[ i ] = "kde.js";
125 rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, NS_ARRAY_LENGTH(specialFiles));
127 NS_WARNING("Error parsing application default preferences.");
129 // Load jar:$app/omni.jar!/defaults/preferences/*.js
130 nsZipArchive *appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
132 rv = appJarReader->FindInit("defaults/preferences/*.js$", &findPtr);
133 diff --git a/toolkit/components/downloads/Makefile.in b/toolkit/components/downloads/Makefile.in
134 --- a/toolkit/components/downloads/Makefile.in
135 +++ b/toolkit/components/downloads/Makefile.in
136 @@ -75,8 +75,10 @@ EXTRA_COMPONENTS = \
144 include $(topsrcdir)/config/rules.mk
146 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
147 diff --git a/toolkit/components/downloads/nsDownloadManager.cpp b/toolkit/components/downloads/nsDownloadManager.cpp
148 --- a/toolkit/components/downloads/nsDownloadManager.cpp
149 +++ b/toolkit/components/downloads/nsDownloadManager.cpp
154 #ifdef DOWNLOAD_SCANNER
155 #include "nsDownloadScanner.h"
159 +#if defined(XP_UNIX) && !defined(XP_MACOSX)
160 +#include "nsKDEUtils.h"
164 #include <CoreFoundation/CoreFoundation.h>
168 #include "AndroidBridge.h"
171 @@ -2203,16 +2207,25 @@ nsDownload::SetState(DownloadState aStat
172 nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID));
174 // Master pref to control this function.
175 PRBool showTaskbarAlert = PR_TRUE;
177 pref->GetBoolPref(PREF_BDM_SHOWALERTONCOMPLETE, &showTaskbarAlert);
179 if (showTaskbarAlert) {
180 + if( nsKDEUtils::kdeSupport()) {
181 + nsCStringArray command;
182 + command.AppendCString( NS_LITERAL_CSTRING( "DOWNLOADFINISHED" ));
183 + nsAutoString displayName;
184 + GetDisplayName( displayName );
185 + command.AppendCString( nsCAutoString( ToNewUTF8String( displayName )));
186 + nsKDEUtils::command( command );
188 + // begin non-KDE block
189 PRInt32 alertInterval = 2000;
191 pref->GetIntPref(PREF_BDM_SHOWALERTINTERVAL, &alertInterval);
193 PRInt64 alertIntervalUSec = alertInterval * PR_USEC_PER_MSEC;
194 PRInt64 goat = PR_Now() - mStartTime;
195 showTaskbarAlert = goat > alertIntervalUSec;
197 @@ -2236,19 +2249,20 @@ nsDownload::SetState(DownloadState aStat
198 // If downloads are automatically removed per the user's
199 // retention policy, there's no reason to make the text clickable
200 // because if it is, they'll click open the download manager and
201 // the items they downloaded will have been removed.
202 alerts->ShowAlertNotification(
203 NS_LITERAL_STRING(DOWNLOAD_MANAGER_ALERT_ICON), title,
204 message, !removeWhenDone, EmptyString(), mDownloadManager,
212 #if defined(XP_WIN) || defined(XP_MACOSX) || defined(ANDROID)
213 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mTarget);
214 nsCOMPtr<nsIFile> file;
218 NS_SUCCEEDED(fileURL->GetFile(getter_AddRefs(file))) &&
219 diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn
220 --- a/toolkit/content/jar.mn
221 +++ b/toolkit/content/jar.mn
222 @@ -40,29 +40,33 @@ toolkit.jar:
223 *+ content/global/viewZoomOverlay.js (viewZoomOverlay.js)
224 *+ content/global/bindings/autocomplete.xml (widgets/autocomplete.xml)
225 *+ content/global/bindings/browser.xml (widgets/browser.xml)
226 *+ content/global/bindings/button.xml (widgets/button.xml)
227 *+ content/global/bindings/checkbox.xml (widgets/checkbox.xml)
228 *+ content/global/bindings/colorpicker.xml (widgets/colorpicker.xml)
229 *+ content/global/bindings/datetimepicker.xml (widgets/datetimepicker.xml)
230 *+ content/global/bindings/dialog.xml (widgets/dialog.xml)
231 +*+ content/global/bindings/dialog-kde.xml (widgets/dialog-kde.xml)
232 +% override chrome://global/content/bindings/dialog.xml chrome://global/content/bindings/dialog-kde.xml desktop=kde
233 *+ content/global/bindings/editor.xml (widgets/editor.xml)
234 * content/global/bindings/expander.xml (widgets/expander.xml)
235 * content/global/bindings/filefield.xml (widgets/filefield.xml)
236 *+ content/global/bindings/findbar.xml (widgets/findbar.xml)
237 *+ content/global/bindings/general.xml (widgets/general.xml)
238 *+ content/global/bindings/groupbox.xml (widgets/groupbox.xml)
239 *+ content/global/bindings/listbox.xml (widgets/listbox.xml)
240 *+ content/global/bindings/menu.xml (widgets/menu.xml)
241 *+ content/global/bindings/menulist.xml (widgets/menulist.xml)
242 *+ content/global/bindings/notification.xml (widgets/notification.xml)
243 *+ content/global/bindings/numberbox.xml (widgets/numberbox.xml)
244 *+ content/global/bindings/popup.xml (widgets/popup.xml)
245 *+ content/global/bindings/preferences.xml (widgets/preferences.xml)
246 +*+ content/global/bindings/preferences-kde.xml (widgets/preferences-kde.xml)
247 +% override chrome://global/content/bindings/preferences.xml chrome://global/content/bindings/preferences-kde.xml desktop=kde
248 *+ content/global/bindings/progressmeter.xml (widgets/progressmeter.xml)
249 *+ content/global/bindings/radio.xml (widgets/radio.xml)
250 *+ content/global/bindings/resizer.xml (widgets/resizer.xml)
251 *+ content/global/bindings/richlistbox.xml (widgets/richlistbox.xml)
252 *+ content/global/bindings/scale.xml (widgets/scale.xml)
253 *+ content/global/bindings/scrollbar.xml (widgets/scrollbar.xml)
254 *+ content/global/bindings/scrollbox.xml (widgets/scrollbox.xml)
255 *+ content/global/bindings/splitter.xml (widgets/splitter.xml)
256 diff --git a/toolkit/content/widgets/dialog-kde.xml b/toolkit/content/widgets/dialog-kde.xml
259 +++ b/toolkit/content/widgets/dialog-kde.xml
261 +<?xml version="1.0"?>
263 +<bindings id="dialogBindings"
264 + xmlns="http://www.mozilla.org/xbl"
265 + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
266 + xmlns:xbl="http://www.mozilla.org/xbl">
268 + <binding id="dialog" extends="chrome://global/content/bindings/general.xml#root-element">
270 + <stylesheet src="chrome://global/skin/dialog.css"/>
273 + <xul:vbox class="box-inherit dialog-content-box" flex="1">
277 + <xul:hbox class="dialog-button-box" anonid="buttons"
278 + xbl:inherits="pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient"
279 +#ifdef XP_UNIX_GNOME
281 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
282 + <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
283 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
284 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
285 + <xul:spacer anonid="spacer" flex="1"/>
286 + <xul:button dlgtype="cancel" class="dialog-button"/>
287 + <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
290 + <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
291 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
292 + <xul:spacer anonid="spacer" flex="1" hidden="true"/>
293 + <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
294 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
295 + <xul:button dlgtype="cancel" class="dialog-button"/>
296 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
299 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
300 + <xul:spacer anonid="spacer" flex="1" hidden="true"/>
301 + <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
302 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
303 + <xul:button dlgtype="cancel" class="dialog-button"/>
304 + <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
305 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
311 + <field name="_mStrBundle">null</field>
312 + <field name="_closeHandler">(function(event) {
313 + if (!document.documentElement.cancelDialog())
314 + event.preventDefault();
317 + <property name="buttons"
318 + onget="return this.getAttribute('buttons');"
319 + onset="this._configureButtons(val); return val;"/>
321 + <property name="defaultButton">
324 + if (this.hasAttribute("defaultButton"))
325 + return this.getAttribute("defaultButton");
326 + else // default to the accept button
332 + this._setDefaultButton(val);
338 + <method name="acceptDialog">
341 + return this._doButtonCommand("accept");
346 + <method name="cancelDialog">
349 + return this._doButtonCommand("cancel");
354 + <method name="getButton">
355 + <parameter name="aDlgType"/>
358 + return this._buttons[aDlgType];
363 + <method name="moveToAlertPosition">
366 + // hack. we need this so the window has something like its final size
367 + if (window.outerWidth == 1) {
368 + dump("Trying to position a sizeless window; caller should have called sizeToContent() or sizeTo(). See bug 75649.\n");
372 + var xOffset = (opener.outerWidth - window.outerWidth) / 2;
373 + var yOffset = opener.outerHeight / 5;
375 + var newX = opener.screenX + xOffset;
376 + var newY = opener.screenY + yOffset;
378 + // ensure the window is fully onscreen (if smaller than the screen)
379 + if (newX < screen.availLeft)
380 + newX = screen.availLeft + 20;
381 + if ((newX + window.outerWidth) > (screen.availLeft + screen.availWidth))
382 + newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20;
384 + if (newY < screen.availTop)
385 + newY = screen.availTop + 20;
386 + if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight))
387 + newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60;
389 + window.moveTo( newX, newY );
394 + <method name="centerWindowOnScreen">
397 + var xOffset = screen.availWidth/2 - window.outerWidth/2;
398 + var yOffset = screen.availHeight/2 - window.outerHeight/2; //(opener.outerHeight *2)/10;
400 + xOffset = xOffset > 0 ? xOffset : 0;
401 + yOffset = yOffset > 0 ? yOffset : 0;
402 + window.moveTo(xOffset, yOffset);
409 + this._configureButtons(this.buttons);
411 + // listen for when window is closed via native close buttons
412 + window.addEventListener("close", this._closeHandler, false);
414 + // for things that we need to initialize after onload fires
415 + window.addEventListener("load", this.postLoadInit, false);
417 + window.moveToAlertPosition = this.moveToAlertPosition;
418 + window.centerWindowOnScreen = this.centerWindowOnScreen;
422 + <method name="postLoadInit">
423 + <parameter name="aEvent"/>
426 + function focusInit() {
427 + const dialog = document.documentElement;
428 + const defaultButton = dialog.getButton(dialog.defaultButton);
429 + // give focus to the first focusable element in the dialog
430 + if (!document.commandDispatcher.focusedElement) {
431 + document.commandDispatcher.advanceFocusIntoSubtree(dialog);
433 + var focusedElt = document.commandDispatcher.focusedElement;
435 + var initialFocusedElt = focusedElt;
436 + while (focusedElt.localName == "tab" ||
437 + focusedElt.getAttribute("noinitialfocus") == "true") {
438 + document.commandDispatcher.advanceFocusIntoSubtree(focusedElt);
439 + focusedElt = document.commandDispatcher.focusedElement;
440 + if (focusedElt == initialFocusedElt)
444 + if (initialFocusedElt.localName == "tab") {
445 + if (focusedElt.hasAttribute("dlgtype")) {
446 + // We don't want to focus on anonymous OK, Cancel, etc. buttons,
447 + // so return focus to the tab itself
448 + initialFocusedElt.focus();
452 + else if (focusedElt.hasAttribute("dlgtype") && focusedElt != defaultButton) {
453 + defaultButton.focus();
461 + window.notifyDefaultButtonLoaded(defaultButton);
465 + // Give focus after onload completes, see bug 103197.
466 + setTimeout(focusInit, 0);
471 + <property name="mStrBundle">
474 + if (!this._mStrBundle) {
475 + // need to create string bundle manually instead of using <xul:stringbundle/>
476 + // see bug 63370 for details
477 + this._mStrBundle = Components.classes["@mozilla.org/intl/stringbundle;1"]
478 + .getService(Components.interfaces.nsIStringBundleService)
479 + .createBundle("chrome://global/locale/dialog.properties");
481 + return this._mStrBundle;
485 + <method name="_configureButtons">
486 + <parameter name="aButtons"/>
489 + // by default, get all the anonymous button elements
491 + this._buttons = buttons;
492 + buttons.accept = document.getAnonymousElementByAttribute(this, "dlgtype", "accept");
493 + buttons.cancel = document.getAnonymousElementByAttribute(this, "dlgtype", "cancel");
494 + buttons.extra1 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra1");
495 + buttons.extra2 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra2");
496 + buttons.help = document.getAnonymousElementByAttribute(this, "dlgtype", "help");
497 + buttons.disclosure = document.getAnonymousElementByAttribute(this, "dlgtype", "disclosure");
499 + // look for any overriding explicit button elements
500 + var exBtns = this.getElementsByAttribute("dlgtype", "*");
503 + for (i = 0; i < exBtns.length; ++i) {
504 + dlgtype = exBtns[i].getAttribute("dlgtype");
505 + buttons[dlgtype].hidden = true; // hide the anonymous button
506 + buttons[dlgtype] = exBtns[i];
509 + // add the label and oncommand handler to each button
510 + for (dlgtype in buttons) {
511 + var button = buttons[dlgtype];
512 + button.addEventListener("command", this._handleButtonCommand, true);
514 + // don't override custom labels with pre-defined labels on explicit buttons
515 + if (!button.hasAttribute("label")) {
516 + // dialog attributes override the default labels in dialog.properties
517 + if (this.hasAttribute("buttonlabel"+dlgtype)) {
518 + button.setAttribute("label", this.getAttribute("buttonlabel"+dlgtype));
519 + if (this.hasAttribute("buttonaccesskey"+dlgtype))
520 + button.setAttribute("accesskey", this.getAttribute("buttonaccesskey"+dlgtype));
521 + } else if (dlgtype != "extra1" && dlgtype != "extra2") {
522 + button.setAttribute("label", this.mStrBundle.GetStringFromName("button-"+dlgtype));
523 + var accessKey = this.mStrBundle.GetStringFromName("accesskey-"+dlgtype);
525 + button.setAttribute("accesskey", accessKey);
528 + // allow specifying alternate icons in the dialog header
529 + if (!button.hasAttribute("icon")) {
530 + // if there's an icon specified, use that
531 + if (this.hasAttribute("buttonicon"+dlgtype))
532 + button.setAttribute("icon", this.getAttribute("buttonicon"+dlgtype));
533 + // otherwise set defaults
537 + button.setAttribute("icon","accept");
540 + button.setAttribute("icon","cancel");
543 + button.setAttribute("icon","properties");
546 + button.setAttribute("icon","help");
554 + // ensure that hitting enter triggers the default button command
555 + this.defaultButton = this.defaultButton;
557 + // if there is a special button configuration, use it
559 + // expect a comma delimited list of dlgtype values
560 + var list = aButtons.split(",");
562 + // mark shown dlgtypes as true
563 + var shown = { accept: false, cancel: false, help: false,
564 + disclosure: false, extra1: false, extra2: false };
565 + for (i = 0; i < list.length; ++i)
566 + shown[list[i].replace(/ /g, "")] = true;
568 + // hide/show the buttons we want
569 + for (dlgtype in buttons)
570 + buttons[dlgtype].hidden = !shown[dlgtype];
573 +# show the spacer on Windows only when the extra2 button is present
574 + var spacer = document.getAnonymousElementByAttribute(this, "anonid", "spacer");
575 + spacer.removeAttribute("hidden");
576 + spacer.setAttribute("flex", shown["extra2"]?"1":"0");
584 + <method name="_setDefaultButton">
585 + <parameter name="aNewDefault"/>
588 + // remove the default attribute from the previous default button, if any
589 + var oldDefaultButton = this.getButton(this.defaultButton);
590 + if (oldDefaultButton)
591 + oldDefaultButton.removeAttribute("default");
593 + var newDefaultButton = this.getButton(aNewDefault);
594 + if (newDefaultButton) {
595 + this.setAttribute("defaultButton", aNewDefault);
596 + newDefaultButton.setAttribute("default", "true");
599 + this.setAttribute("defaultButton", "none");
600 + if (aNewDefault != "none")
601 + dump("invalid new default button: " + aNewDefault + ", assuming: none\n");
607 + <method name="_handleButtonCommand">
608 + <parameter name="aEvent"/>
611 + return document.documentElement._doButtonCommand(
612 + aEvent.target.getAttribute("dlgtype"));
617 + <method name="_doButtonCommand">
618 + <parameter name="aDlgType"/>
621 + var button = this.getButton(aDlgType);
622 + if (!button.disabled) {
623 + var noCancel = this._fireButtonEvent(aDlgType);
625 + if (aDlgType == "accept" || aDlgType == "cancel")
635 + <method name="_fireButtonEvent">
636 + <parameter name="aDlgType"/>
639 + var event = document.createEvent("Events");
640 + event.initEvent("dialog"+aDlgType, true, true);
642 + // handle dom event handlers
643 + var noCancel = this.dispatchEvent(event);
645 + // handle any xml attribute event handlers
646 + var handler = this.getAttribute("ondialog"+aDlgType);
647 + if (handler != "") {
648 + var fn = new Function("event", handler);
649 + var returned = fn(event);
650 + if (returned == false)
659 + <method name="_hitEnter">
660 + <parameter name="evt"/>
663 + if (evt.getPreventDefault())
666 + var btn = this.getButton(this.defaultButton);
668 + this._doButtonCommand(this.defaultButton);
676 + <handler event="keypress" keycode="VK_ENTER"
677 + group="system" action="this._hitEnter(event);"/>
678 + <handler event="keypress" keycode="VK_RETURN"
679 + group="system" action="this._hitEnter(event);"/>
680 + <handler event="keypress" keycode="VK_ESCAPE" group="system">
681 + if (!event.getPreventDefault())
682 + this.cancelDialog();
685 + <handler event="keypress" key="." modifiers="meta" phase="capturing" action="this.cancelDialog();"/>
687 + <handler event="focus" phase="capturing">
688 + var btn = this.getButton(this.defaultButton);
690 + btn.setAttribute("default", event.originalTarget == btn || !(event.originalTarget instanceof Components.interfaces.nsIDOMXULButtonElement));
697 + <binding id="dialogheader">
699 + <stylesheet src="chrome://global/skin/dialog.css"/>
702 + <xul:label class="dialogheader-title" xbl:inherits="value=title,crop" crop="right" flex="1"/>
703 + <xul:label class="dialogheader-description" xbl:inherits="value=description"/>
708 diff --git a/toolkit/content/widgets/preferences-kde.xml b/toolkit/content/widgets/preferences-kde.xml
711 +++ b/toolkit/content/widgets/preferences-kde.xml
713 +<?xml version="1.0"?>
715 +<!DOCTYPE bindings [
716 + <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
718 + <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
722 +<bindings id="preferencesBindings"
723 + xmlns="http://www.mozilla.org/xbl"
724 + xmlns:xbl="http://www.mozilla.org/xbl"
725 + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
728 +# = Preferences Window Framework
730 +# The syntax for use looks something like:
733 +# <prefpane id="prefPaneA">
735 +# <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/>
736 +# <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/>
738 +# <checkbox label="Preference" preference="preference1"/>
743 + <binding id="preferences">
744 + <implementation implements="nsIObserver">
745 + <method name="observe">
746 + <parameter name="aSubject"/>
747 + <parameter name="aTopic"/>
748 + <parameter name="aData"/>
751 + for (var i = 0; i < this.childNodes.length; ++i) {
752 + var preference = this.childNodes[i];
753 + if (preference.name == aData) {
754 + preference.value = preference.valueFromPreferences;
761 + <method name="fireChangedEvent">
762 + <parameter name="aPreference"/>
765 + // Value changed, synthesize an event
767 + var event = document.createEvent("Events");
768 + event.initEvent("change", true, true);
769 + aPreference.dispatchEvent(event);
772 + Components.utils.reportError(e);
778 + <field name="service">
779 + Components.classes["@mozilla.org/preferences-service;1"]
780 + .getService(Components.interfaces.nsIPrefService);
782 + <field name="rootBranch">
783 + Components.classes["@mozilla.org/preferences-service;1"]
784 + .getService(Components.interfaces.nsIPrefBranch);
786 + <field name="defaultBranch">
787 + this.service.getDefaultBranch("");
789 + <field name="rootBranchInternal">
790 + Components.classes["@mozilla.org/preferences-service;1"]
791 + .getService(Components.interfaces.nsIPrefBranchInternal);
793 + <property name="type" readonly="true">
796 + return document.documentElement.type || "";
800 + <property name="instantApply" readonly="true">
803 + var doc = document.documentElement;
804 + return this.type == "child" ? doc.instantApply
805 + : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply");
812 + <binding id="preference">
816 + // if the element has been inserted without the name attribute set,
817 + // we have nothing to do here
821 + this.preferences.rootBranchInternal
822 + .addObserver(this.name, this.preferences, false);
823 + // In non-instant apply mode, we must try and use the last saved state
824 + // from any previous opens of a child dialog instead of the value from
825 + // preferences, to pick up any edits a user may have made.
826 + if (this.preferences.type == "child" &&
827 + !this.instantApply && window.opener) {
828 + var pdoc = window.opener.document;
830 + // Try to find a preference element for the same preference.
831 + var preference = null;
832 + var parentPreferences = pdoc.getElementsByTagName("preferences");
833 + for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
834 + var parentPrefs = parentPreferences[k]
835 + .getElementsByAttribute("name", this.name);
836 + for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
837 + if (parentPrefs[l].localName == "preference")
838 + preference = parentPrefs[l];
841 + this._setValue(preference ? preference.value
842 + : this.valueFromPreferences, false);
845 + this._setValue(this.valueFromPreferences, false);
849 + this.preferences.rootBranchInternal
850 + .removeObserver(this.name, this.preferences);
853 + <property name="instantApply">
855 + return this.getAttribute("instantApply") == "true" || this.preferences.instantApply;
859 + <property name="preferences" onget="return this.parentNode"/>
860 + <property name="name" onget="return this.getAttribute('name');">
862 + if (val == this.name)
865 + this.preferences.rootBranchInternal
866 + .removeObserver(this.name, this.preferences);
867 + this.setAttribute('name', val);
868 + this.preferences.rootBranchInternal
869 + .addObserver(val, this.preferences, false);
874 + <property name="type" onget="return this.getAttribute('type');"
875 + onset="this.setAttribute('type', val); return val;"/>
876 + <property name="inverted" onget="return this.getAttribute('inverted') == 'true';"
877 + onset="this.setAttribute('inverted', val); return val;"/>
878 + <property name="readonly" onget="return this.getAttribute('readonly') == 'true';"
879 + onset="this.setAttribute('readonly', val); return val;"/>
881 + <field name="_value">null</field>
882 + <method name="_setValue">
883 + <parameter name="aValue"/>
884 + <parameter name="aUpdate"/>
887 + if (aUpdate && this.value !== aValue) {
888 + this._value = aValue;
889 + if (this.instantApply)
890 + this.valueFromPreferences = aValue;
891 + this.preferences.fireChangedEvent(this);
893 + else if (!aUpdate) {
894 + this._value = aValue;
895 + this.updateElements();
901 + <property name="value" onget="return this._value" onset="return this._setValue(val, true);"/>
903 + <property name="locked">
905 + return this.preferences.rootBranch.prefIsLocked(this.name);
909 + <property name="disabled">
911 + return this.getAttribute("disabled") == "true";
916 + this.setAttribute("disabled", "true");
918 + this.removeAttribute("disabled");
923 + var elements = document.getElementsByAttribute("preference", this.id);
924 + for (var i = 0; i < elements.length; ++i) {
925 + elements[i].disabled = val;
927 + var labels = document.getElementsByAttribute("control", elements[i].id);
928 + for (var j = 0; j < labels.length; ++j)
929 + labels[j].disabled = val;
937 + <property name="tabIndex">
939 + return parseInt(this.getAttribute("tabindex"));
944 + this.setAttribute("tabindex", val);
946 + this.removeAttribute("tabindex");
951 + var elements = document.getElementsByAttribute("preference", this.id);
952 + for (var i = 0; i < elements.length; ++i) {
953 + elements[i].tabIndex = val;
955 + var labels = document.getElementsByAttribute("control", elements[i].id);
956 + for (var j = 0; j < labels.length; ++j)
957 + labels[j].tabIndex = val;
965 + <property name="hasUserValue">
968 + return this.preferences.rootBranch.prefHasUserValue(this.name) &&
969 + this.value !== undefined;
974 + <method name="reset">
976 + // defer reset until preference update
977 + this.value = undefined;
981 + <field name="_useDefault">false</field>
982 + <property name="defaultValue">
985 + this._useDefault = true;
986 + var val = this.valueFromPreferences;
987 + this._useDefault = false;
993 + <property name="_branch">
995 + return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch;
999 + <field name="batching">false</field>
1001 + <method name="_reportUnknownType">
1004 + var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
1005 + .getService(Components.interfaces.nsIConsoleService);
1006 + var msg = "<preference> with id='" + this.id + "' and name='" +
1007 + this.name + "' has unknown type '" + this.type + "'.";
1008 + consoleService.logStringMessage(msg);
1013 + <property name="valueFromPreferences">
1017 + // Force a resync of value with preferences.
1018 + switch (this.type) {
1020 + return this._branch.getIntPref(this.name);
1022 + var val = this._branch.getBoolPref(this.name);
1023 + return this.inverted ? !val : val;
1025 + return this._branch
1026 + .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString)
1030 + return this._branch
1031 + .getComplexValue(this.name, Components.interfaces.nsISupportsString)
1034 + var family = this._branch
1035 + .getComplexValue(this.name, Components.interfaces.nsISupportsString)
1037 + var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
1038 + .createInstance(Components.interfaces.nsIFontEnumerator);
1039 + return fontEnumerator.getStandardFamilyName(family);
1041 + var f = this._branch
1042 + .getComplexValue(this.name, Components.interfaces.nsILocalFile);
1045 + this._reportUnknownType();
1054 + // Exit early if nothing to do.
1055 + if (this.readonly || this.valueFromPreferences == val)
1058 + // The special value undefined means 'reset preference to default'.
1059 + if (val === undefined) {
1060 + this.preferences.rootBranch.clearUserPref(this.name);
1064 + // Force a resync of preferences with value.
1065 + switch (this.type) {
1067 + this.preferences.rootBranch.setIntPref(this.name, val);
1070 + this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val);
1073 + var pls = Components.classes["@mozilla.org/pref-localizedstring;1"]
1074 + .createInstance(Components.interfaces.nsIPrefLocalizedString);
1076 + this.preferences.rootBranch
1077 + .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls);
1082 + var iss = Components.classes["@mozilla.org/supports-string;1"]
1083 + .createInstance(Components.interfaces.nsISupportsString);
1085 + this.preferences.rootBranch
1086 + .setComplexValue(this.name, Components.interfaces.nsISupportsString, iss);
1090 + if (typeof(val) == "string") {
1091 + lf = Components.classes["@mozilla.org/file/local;1"]
1092 + .createInstance(Components.interfaces.nsILocalFile);
1093 + lf.persistentDescriptor = val;
1095 + lf.initWithPath(val);
1098 + lf = val.QueryInterface(Components.interfaces.nsILocalFile);
1099 + this.preferences.rootBranch
1100 + .setComplexValue(this.name, Components.interfaces.nsILocalFile, lf);
1103 + this._reportUnknownType();
1105 + if (!this.batching)
1106 + this.preferences.service.savePrefFile(null);
1112 + <method name="setElementValue">
1113 + <parameter name="aElement"/>
1117 + aElement.disabled = true;
1119 + if (!this.isElementEditable(aElement))
1122 + var rv = undefined;
1123 + if (aElement.hasAttribute("onsyncfrompreference")) {
1124 + // Value changed, synthesize an event
1126 + var event = document.createEvent("Events");
1127 + event.initEvent("syncfrompreference", true, true);
1128 + var f = new Function ("event",
1129 + aElement.getAttribute("onsyncfrompreference"));
1130 + rv = f.call(aElement, event);
1133 + Components.utils.reportError(e);
1136 + var val = rv !== undefined ? rv : (this.instantApply ? this.valueFromPreferences : this.value);
1137 + // if the preference is marked for reset, show default value in UI
1138 + if (val === undefined)
1139 + val = this.defaultValue;
1142 + * Initialize a UI element property with a value. Handles the case
1143 + * where an element has not yet had a XBL binding attached for it and
1144 + * the property setter does not yet exist by setting the same attribute
1145 + * on the XUL element using DOM apis and assuming the element's
1146 + * constructor or property getters appropriately handle this state.
1148 + function setValue(element, attribute, value) {
1149 + if (attribute in element)
1150 + element[attribute] = value;
1152 + element.setAttribute(attribute, value);
1154 + if (aElement.localName == "checkbox" ||
1155 + aElement.localName == "listitem")
1156 + setValue(aElement, "checked", val);
1157 + else if (aElement.localName == "colorpicker")
1158 + setValue(aElement, "color", val);
1159 + else if (aElement.localName == "textbox") {
1160 + // XXXmano Bug 303998: Avoid a caret placement issue if either the
1161 + // preference observer or its setter calls updateElements as a result
1162 + // of the input event handler.
1163 + if (aElement.value !== val)
1164 + setValue(aElement, "value", val);
1167 + setValue(aElement, "value", val);
1172 + <method name="getElementValue">
1173 + <parameter name="aElement"/>
1176 + if (aElement.hasAttribute("onsynctopreference")) {
1177 + // Value changed, synthesize an event
1179 + var event = document.createEvent("Events");
1180 + event.initEvent("synctopreference", true, true);
1181 + var f = new Function ("event",
1182 + aElement.getAttribute("onsynctopreference"));
1183 + var rv = f.call(aElement, event);
1184 + if (rv !== undefined)
1188 + Components.utils.reportError(e);
1193 + * Read the value of an attribute from an element, assuming the
1194 + * attribute is a property on the element's node API. If the property
1195 + * is not present in the API, then assume its value is contained in
1196 + * an attribute, as is the case before a binding has been attached.
1198 + function getValue(element, attribute) {
1199 + if (attribute in element)
1200 + return element[attribute];
1201 + return element.getAttribute(attribute);
1203 + if (aElement.localName == "checkbox" ||
1204 + aElement.localName == "listitem")
1205 + var value = getValue(aElement, "checked");
1206 + else if (aElement.localName == "colorpicker")
1207 + value = getValue(aElement, "color");
1209 + value = getValue(aElement, "value");
1211 + switch (this.type) {
1213 + return parseInt(value, 10) || 0;
1215 + return typeof(value) == "boolean" ? value : value == "true";
1222 + <method name="isElementEditable">
1223 + <parameter name="aElement"/>
1226 + switch (aElement.localName) {
1228 + case "colorpicker":
1229 + case "radiogroup":
1236 + return aElement.getAttribute("preference-editable") == "true";
1241 + <method name="updateElements">
1247 + // This "change" event handler tracks changes made to preferences by
1248 + // sources other than the user in this window.
1249 + var elements = document.getElementsByAttribute("preference", this.id);
1250 + for (var i = 0; i < elements.length; ++i)
1251 + this.setElementValue(elements[i]);
1258 + <handler event="change">
1259 + this.updateElements();
1264 + <binding id="prefwindow"
1265 + extends="chrome://global/content/bindings/dialog.xml#dialog">
1267 + <stylesheet src="chrome://global/skin/preferences.css"/>
1269 + <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY"
1270 + closebuttonlabel="&preferencesCloseButton.label;"
1271 + closebuttonaccesskey="&preferencesCloseButton.accesskey;"
1274 + title="&preferencesDefaultTitleWin.title;">
1276 + title="&preferencesDefaultTitleMac.title;">
1278 + <xul:windowdragbox orient="vertical">
1279 + <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar"
1280 + role="listbox"/> <!-- Expose to accessibility APIs as a listbox -->
1281 + </xul:windowdragbox>
1282 + <xul:hbox flex="1" class="paneDeckContainer">
1283 + <xul:deck anonid="paneDeck" flex="1">
1284 + <children includes="prefpane"/>
1287 + <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons"
1288 +#ifdef XP_UNIX_GNOME
1290 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
1291 + <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
1292 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
1293 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
1294 + <xul:spacer anonid="spacer" flex="1"/>
1295 + <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
1296 + <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
1299 + <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
1300 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
1301 + <xul:spacer anonid="spacer" flex="1"/>
1302 + <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
1303 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
1304 + <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
1305 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
1308 + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
1309 + <xul:spacer anonid="spacer" flex="1"/>
1310 + <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
1311 + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
1312 + <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
1313 + <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
1314 + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
1321 + <implementation implements="nsITimerCallback">
1324 + if (this.type != "child") {
1325 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1326 + .getService(Components.interfaces.nsIPrefBranch);
1327 + this.instantApply = psvc.getBoolPref("browser.preferences.instantApply");
1328 + if (this.instantApply) {
1329 + var docElt = document.documentElement;
1330 + var acceptButton = docElt.getButton("accept");
1331 + acceptButton.hidden = true;
1332 + var cancelButton = docElt.getButton("cancel");
1334 + // no buttons on Mac except Help
1335 + cancelButton.hidden = true;
1336 + // Also, don't fire onDialogAccept on enter
1337 + acceptButton.disabled = true;
1339 + // morph the Cancel button into the Close button
1340 + cancelButton.setAttribute ("icon", "close");
1341 + cancelButton.label = docElt.getAttribute("closebuttonlabel");
1342 + cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey");
1346 + this.setAttribute("animated", this._shouldAnimate ? "true" : "false");
1347 + var panes = this.preferencePanes;
1349 + var lastPane = null;
1350 + if (this.lastSelected) {
1351 + lastPane = document.getElementById(this.lastSelected);
1353 + this.lastSelected = null;
1358 + if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") {
1359 + paneToLoad = document.getElementById(window.arguments[0]);
1360 + this.lastSelected = paneToLoad.id;
1362 + else if (lastPane)
1363 + paneToLoad = lastPane;
1365 + paneToLoad = panes[0];
1367 + for (var i = 0; i < panes.length; ++i) {
1368 + this._makePaneButton(panes[i]);
1369 + if (panes[i].loaded) {
1370 + // Inline pane content, fire load event to force initialization.
1371 + this._fireEvent("paneload", panes[i]);
1374 + this.showPane(paneToLoad);
1376 + if (panes.length == 1)
1377 + this._selector.setAttribute("collapsed", "true");
1383 + // Release timers to avoid reference cycles.
1384 + if (this._animateTimer) {
1385 + this._animateTimer.cancel();
1386 + this._animateTimer = null;
1388 + if (this._fadeTimer) {
1389 + this._fadeTimer.cancel();
1390 + this._fadeTimer = null;
1395 + <field name="instantApply">false</field>
1397 + <property name="preferencePanes"
1398 + onget="return this.getElementsByTagName('prefpane');"/>
1400 + <property name="type" onget="return this.getAttribute('type');"/>
1401 + <property name="_paneDeck"
1402 + onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/>
1403 + <property name="_paneDeckContainer"
1404 + onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/>
1405 + <property name="_selector"
1406 + onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/>
1407 + <property name="lastSelected"
1408 + onget="return this.getAttribute('lastSelected');">
1410 + this.setAttribute("lastSelected", val);
1411 + document.persist(this.id, "lastSelected");
1415 + <property name="currentPane"
1416 + onset="return this._currentPane = val;">
1418 + if (!this._currentPane)
1419 + this._currentPane = this.preferencePanes[0];
1421 + return this._currentPane;
1424 + <field name="_currentPane">null</field>
1427 + <method name="_makePaneButton">
1428 + <parameter name="aPaneElement"/>
1431 + var radio = document.createElement("radio");
1432 + radio.setAttribute("pane", aPaneElement.id);
1433 + radio.setAttribute("label", aPaneElement.label);
1434 + // Expose preference group choice to accessibility APIs as an unchecked list item
1435 + // The parent group is exposed to accessibility APIs as a list
1436 + if (aPaneElement.image)
1437 + radio.setAttribute("src", aPaneElement.image);
1438 + radio.style.listStyleImage = aPaneElement.style.listStyleImage;
1439 + this._selector.appendChild(radio);
1445 + <method name="showPane">
1446 + <parameter name="aPaneElement"/>
1449 + if (!aPaneElement)
1452 + this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id);
1453 + if (!aPaneElement.loaded) {
1454 + function OverlayLoadObserver(aPane)
1456 + this._pane = aPane;
1458 + OverlayLoadObserver.prototype = {
1460 + observe: function (aSubject, aTopic, aData)
1462 + this._pane.loaded = true;
1463 + this._outer._fireEvent("paneload", this._pane);
1464 + this._outer._selectPane(this._pane);
1468 + var obs = new OverlayLoadObserver(aPaneElement);
1469 + document.loadOverlay(aPaneElement.src, obs);
1472 + this._selectPane(aPaneElement);
1477 + <method name="_fireEvent">
1478 + <parameter name="aEventName"/>
1479 + <parameter name="aTarget"/>
1482 + // Panel loaded, synthesize a load event.
1484 + var event = document.createEvent("Events");
1485 + event.initEvent(aEventName, true, true);
1486 + var cancel = !aTarget.dispatchEvent(event);
1487 + if (aTarget.hasAttribute("on" + aEventName)) {
1488 + var fn = new Function ("event", aTarget.getAttribute("on" + aEventName));
1489 + var rv = fn.call(aTarget, event);
1496 + Components.utils.reportError(e);
1503 + <field name="_initialized">false</field>
1504 + <method name="_selectPane">
1505 + <parameter name="aPaneElement"/>
1509 + var paneTitle = aPaneElement.label;
1510 + if (paneTitle != "")
1511 + document.title = paneTitle;
1513 + var helpButton = document.documentElement.getButton("help");
1514 + if (aPaneElement.helpTopic)
1515 + helpButton.hidden = false;
1517 + helpButton.hidden = true;
1519 + // Find this pane's index in the deck and set the deck's
1520 + // selectedIndex to that value to switch to it.
1521 + var prefpanes = this.preferencePanes;
1522 + for (var i = 0; i < prefpanes.length; ++i) {
1523 + if (prefpanes[i] == aPaneElement) {
1524 + this._paneDeck.selectedIndex = i;
1526 + if (this.type != "child") {
1527 + if (aPaneElement.hasAttribute("flex") && this._shouldAnimate &&
1528 + prefpanes.length > 1)
1529 + aPaneElement.removeAttribute("flex");
1530 + // Calling sizeToContent after the first prefpane is loaded
1531 + // will size the windows contents so style information is
1532 + // available to calculate correct sizing.
1533 + if (!this._initialized && prefpanes.length > 1) {
1534 + if (this._shouldAnimate)
1535 + this.style.minHeight = 0;
1536 + window.sizeToContent();
1539 + var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0];
1540 + oldPane.selected = !(aPaneElement.selected = true);
1541 + this.lastSelected = aPaneElement.id;
1542 + this.currentPane = aPaneElement;
1543 + this._initialized = true;
1545 + // Only animate if we've switched between prefpanes
1546 + if (this._shouldAnimate && oldPane.id != aPaneElement.id) {
1547 + aPaneElement.style.opacity = 0.0;
1548 + this.animate(oldPane, aPaneElement);
1550 + else if (!this._shouldAnimate && prefpanes.length > 1) {
1551 + var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer, "").height);
1552 + var verticalPadding = parseInt(window.getComputedStyle(aPaneElement, "").paddingTop);
1553 + verticalPadding += parseInt(window.getComputedStyle(aPaneElement, "").paddingBottom);
1554 + if (aPaneElement.contentHeight > targetHeight - verticalPadding) {
1555 + // To workaround the bottom border of a groupbox from being
1556 + // cutoff an hbox with a class of bottomBox may enclose it.
1557 + // This needs to include its padding to resize properly.
1559 + var bottomPadding = 0;
1560 + var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0];
1562 + bottomPadding = parseInt(window.getComputedStyle(bottomBox, "").paddingBottom);
1563 + window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight;
1566 + // XXX rstrong - extend the contents of the prefpane to
1567 + // prevent elements from being cutoff (see bug 349098).
1568 + if (aPaneElement.contentHeight + verticalPadding < targetHeight)
1569 + aPaneElement._content.style.height = targetHeight - verticalPadding + "px";
1579 + <property name="_shouldAnimate">
1582 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1583 + .getService(Components.interfaces.nsIPrefBranch);
1585 + var animate = true;
1587 + var animate = false;
1590 + animate = psvc.getBoolPref("browser.preferences.animateFadeIn");
1598 + <method name="animate">
1599 + <parameter name="aOldPane"/>
1600 + <parameter name="aNewPane"/>
1603 + // if we are already resizing, use currentHeight
1604 + var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight;
1606 + this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1;
1607 + var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight);
1608 + this._animateRemainder = sizeDelta % this._animateIncrement;
1610 + this._setUpAnimationTimer(oldHeight);
1615 + <property name="_sizeIncrement">
1618 + var lastSelectedPane = document.getElementById(this.lastSelected);
1619 + var increment = this._animateIncrement * this._multiplier;
1620 + var newHeight = this._currentHeight + increment;
1621 + if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) ||
1622 + (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight))
1625 + if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) ||
1626 + (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight))
1627 + increment = this._animateRemainder * this._multiplier;
1633 + <method name="notify">
1634 + <parameter name="aTimer"/>
1640 + if (aTimer == this._animateTimer) {
1641 + var increment = this._sizeIncrement;
1642 + if (increment != 0) {
1643 + window.innerHeight += increment;
1644 + this._currentHeight += increment;
1648 + this._setUpFadeTimer();
1650 + } else if (aTimer == this._fadeTimer) {
1651 + var elt = document.getElementById(this.lastSelected);
1652 + var newOpacity = parseFloat(window.getComputedStyle(elt, "").opacity) + this._fadeIncrement;
1653 + if (newOpacity < 1.0)
1654 + elt.style.opacity = newOpacity;
1657 + elt.style.opacity = 1.0;
1664 + <method name="_setUpAnimationTimer">
1665 + <parameter name="aStartHeight"/>
1668 + if (!this._animateTimer)
1669 + this._animateTimer = Components.classes["@mozilla.org/timer;1"]
1670 + .createInstance(Components.interfaces.nsITimer);
1672 + this._animateTimer.cancel();
1673 + this._currentHeight = aStartHeight;
1675 + this._animateTimer.initWithCallback(this, this._animateDelay,
1676 + Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
1681 + <method name="_setUpFadeTimer">
1684 + if (!this._fadeTimer)
1685 + this._fadeTimer = Components.classes["@mozilla.org/timer;1"]
1686 + .createInstance(Components.interfaces.nsITimer);
1688 + this._fadeTimer.cancel();
1690 + this._fadeTimer.initWithCallback(this, this._fadeDelay,
1691 + Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
1696 + <field name="_animateTimer">null</field>
1697 + <field name="_fadeTimer">null</field>
1698 + <field name="_animateDelay">15</field>
1699 + <field name="_animateIncrement">40</field>
1700 + <field name="_fadeDelay">5</field>
1701 + <field name="_fadeIncrement">0.40</field>
1702 + <field name="_animateRemainder">0</field>
1703 + <field name="_currentHeight">0</field>
1704 + <field name="_multiplier">0</field>
1706 + <method name="addPane">
1707 + <parameter name="aPaneElement"/>
1710 + this.appendChild(aPaneElement);
1712 + // Set up pane button
1713 + this._makePaneButton(aPaneElement);
1718 + <method name="openSubDialog">
1719 + <parameter name="aURL"/>
1720 + <parameter name="aFeatures"/>
1721 + <parameter name="aParams"/>
1723 + return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams);
1727 + <method name="openWindow">
1728 + <parameter name="aWindowType"/>
1729 + <parameter name="aURL"/>
1730 + <parameter name="aFeatures"/>
1731 + <parameter name="aParams"/>
1734 + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
1735 + .getService(Components.interfaces.nsIWindowMediator);
1736 + var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null;
1738 + if ("initWithParams" in win)
1739 + win.initWithParams(aParams);
1743 + var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : "");
1744 + var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener;
1745 + win = parentWindow.openDialog(aURL, "_blank", features, aParams);
1753 + <handler event="dialogaccept">
1755 + if (!this._fireEvent("beforeaccept", this))
1758 + if (this.type == "child" && window.opener) {
1759 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1760 + .getService(Components.interfaces.nsIPrefBranch);
1761 + var instantApply = psvc.getBoolPref("browser.preferences.instantApply");
1762 + if (instantApply) {
1763 + var panes = this.preferencePanes;
1764 + for (var i = 0; i < panes.length; ++i)
1765 + panes[i].writePreferences(true);
1768 + // Clone all the preferences elements from the child document and
1769 + // insert them into the pane collection of the parent.
1770 + var pdoc = window.opener.document;
1771 + if (pdoc.documentElement.localName == "prefwindow") {
1772 + var currentPane = pdoc.documentElement.currentPane;
1773 + var id = window.location.href + "#childprefs";
1774 + var childPrefs = pdoc.getElementById(id);
1775 + if (!childPrefs) {
1776 + var childPrefs = pdoc.createElement("preferences");
1777 + currentPane.appendChild(childPrefs);
1778 + childPrefs.id = id;
1780 + var panes = this.preferencePanes;
1781 + for (var i = 0; i < panes.length; ++i) {
1782 + var preferences = panes[i].preferences;
1783 + for (var j = 0; j < preferences.length; ++j) {
1784 + // Try to find a preference element for the same preference.
1785 + var preference = null;
1786 + var parentPreferences = pdoc.getElementsByTagName("preferences");
1787 + for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
1788 + var parentPrefs = parentPreferences[k]
1789 + .getElementsByAttribute("name", preferences[j].name);
1790 + for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
1791 + if (parentPrefs[l].localName == "preference")
1792 + preference = parentPrefs[l];
1795 + if (!preference) {
1796 + // No matching preference in the parent window.
1797 + preference = pdoc.createElement("preference");
1798 + childPrefs.appendChild(preference);
1799 + preference.name = preferences[j].name;
1800 + preference.type = preferences[j].type;
1801 + preference.inverted = preferences[j].inverted;
1802 + preference.readonly = preferences[j].readonly;
1803 + preference.disabled = preferences[j].disabled;
1805 + preference.value = preferences[j].value;
1812 + var panes = this.preferencePanes;
1813 + for (var i = 0; i < panes.length; ++i)
1814 + panes[i].writePreferences(false);
1816 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1817 + .getService(Components.interfaces.nsIPrefService);
1818 + psvc.savePrefFile(null);
1822 + <handler event="command">
1823 + if (event.originalTarget.hasAttribute("pane")) {
1824 + var pane = document.getElementById(event.originalTarget.getAttribute("pane"));
1825 + this.showPane(pane);
1829 + <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing">
1831 + if (this.instantApply)
1833 + event.stopPropagation();
1834 + event.preventDefault();
1838 + <handler event="keypress"
1840 + key="&openHelpMac.commandkey;" modifiers="accel"
1842 + keycode="&openHelp.commandkey;"
1844 + phase="capturing">
1846 + var helpButton = this.getButton("help");
1847 + if (helpButton.disabled || helpButton.hidden)
1849 + this._fireEvent("dialoghelp", this);
1850 + event.stopPropagation();
1851 + event.preventDefault();
1857 + <binding id="prefpane">
1859 + <stylesheet src="chrome://global/skin/preferences.css"/>
1862 + <xul:vbox class="content-box" xbl:inherits="flex">
1867 + <method name="writePreferences">
1868 + <parameter name="aFlushToDisk"/>
1871 + // Write all values to preferences.
1872 + var preferences = this.preferences;
1873 + for (var i = 0; i < preferences.length; ++i) {
1874 + var preference = preferences[i];
1875 + preference.batching = true;
1876 + preference.valueFromPreferences = preference.value;
1877 + preference.batching = false;
1879 + if (aFlushToDisk) {
1880 + var psvc = Components.classes["@mozilla.org/preferences-service;1"]
1881 + .getService(Components.interfaces.nsIPrefService);
1882 + psvc.savePrefFile(null);
1888 + <property name="src"
1889 + onget="return this.getAttribute('src');"
1890 + onset="this.setAttribute('src', val); return val;"/>
1891 + <property name="selected"
1892 + onget="return this.getAttribute('selected') == 'true';"
1893 + onset="this.setAttribute('selected', val); return val;"/>
1894 + <property name="image"
1895 + onget="return this.getAttribute('image');"
1896 + onset="this.setAttribute('image', val); return val;"/>
1897 + <property name="label"
1898 + onget="return this.getAttribute('label');"
1899 + onset="this.setAttribute('label', val); return val;"/>
1901 + <property name="preferenceElements"
1902 + onget="return this.getElementsByAttribute('preference', '*');"/>
1903 + <property name="preferences"
1904 + onget="return this.getElementsByTagName('preference');"/>
1906 + <property name="helpTopic">
1909 + // if there are tabs, and the selected tab provides a helpTopic, return that
1910 + var box = this.getElementsByTagName("tabbox");
1912 + var tab = box[0].selectedTab;
1913 + if (tab && tab.hasAttribute("helpTopic"))
1914 + return tab.getAttribute("helpTopic");
1917 + // otherwise, return the helpTopic of the current panel
1918 + return this.getAttribute("helpTopic");
1923 + <field name="_loaded">false</field>
1924 + <property name="loaded"
1925 + onget="return !this.src ? true : this._loaded;"
1926 + onset="this._loaded = val; return val;"/>
1928 + <method name="preferenceForElement">
1929 + <parameter name="aElement"/>
1931 + return document.getElementById(aElement.getAttribute("preference"));
1935 + <method name="getPreferenceElement">
1936 + <parameter name="aStartElement"/>
1939 + var temp = aStartElement;
1940 + while (temp && temp.nodeType == Node.ELEMENT_NODE &&
1941 + !temp.hasAttribute("preference"))
1942 + temp = temp.parentNode;
1943 + return temp.nodeType == Node.ELEMENT_NODE ? temp : aStartElement;
1948 + <method name="userChangedValue">
1949 + <parameter name="aElement"/>
1952 + var element = this.getPreferenceElement(aElement);
1953 + if (element.hasAttribute("preference")) {
1954 + var preference = document.getElementById(element.getAttribute("preference"));
1955 + var prefVal = preference.getElementValue(element);
1956 + preference.value = prefVal;
1962 + <property name="contentHeight">
1964 + var targetHeight = parseInt(window.getComputedStyle(this._content, "").height);
1965 + targetHeight += parseInt(window.getComputedStyle(this._content, "").marginTop);
1966 + targetHeight += parseInt(window.getComputedStyle(this._content, "").marginBottom);
1967 + return targetHeight;
1970 + <field name="_content">
1971 + document.getAnonymousElementByAttribute(this, "class", "content-box");
1975 + <handler event="command">
1976 + // This "command" event handler tracks changes made to preferences by
1977 + // the user in this window.
1978 + if (event.sourceEvent)
1979 + event = event.sourceEvent;
1980 + this.userChangedValue(event.target);
1982 + <handler event="select">
1983 + // This "select" event handler tracks changes made to colorpicker
1984 + // preferences by the user in this window.
1985 + if (event.target.localName == "colorpicker")
1986 + this.userChangedValue(event.target);
1988 + <handler event="change">
1989 + // This "change" event handler tracks changes made to preferences by
1990 + // the user in this window.
1991 + this.userChangedValue(event.target);
1993 + <handler event="input">
1994 + // This "input" event handler tracks changes made to preferences by
1995 + // the user in this window.
1996 + this.userChangedValue(event.target);
1998 + <handler event="paneload">
2000 + // Initialize all values from preferences.
2001 + var elements = this.preferenceElements;
2002 + for (var i = 0; i < elements.length; ++i) {
2004 + var preference = this.preferenceForElement(elements[i]);
2005 + preference.setElementValue(elements[i]);
2008 + dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n");
2016 + <binding id="panebutton" extends="chrome://global/content/bindings/radio.xml#radio">
2018 + <stylesheet src="chrome://global/skin/preferences.css"/>
2021 + <xul:image class="paneButtonIcon" xbl:inherits="src"/>
2022 + <xul:label class="paneButtonLabel" xbl:inherits="value=label"/>
2024 + <implementation implements="nsIAccessible">
2025 + <property name="accessibleType" readonly="true">
2028 + return Components.interfaces.nsIAccessibleProvider.XULListitem;
2037 +# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2038 +# ***** BEGIN LICENSE BLOCK *****
2039 +# Version: MPL 1.1/GPL 2.0/LGPL 2.1
2041 +# The contents of this file are subject to the Mozilla Public License Version
2042 +# 1.1 (the "License"); you may not use this file except in compliance with
2043 +# the License. You may obtain a copy of the License at
2044 +# http://www.mozilla.org/MPL/
2046 +# Software distributed under the License is distributed on an "AS IS" basis,
2047 +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2048 +# for the specific language governing rights and limitations under the
2051 +# The Original Code is the Preferences System.
2053 +# The Initial Developer of the Original Code is
2055 +# Portions created by the Initial Developer are Copyright (C) 2005
2056 +# the Initial Developer. All Rights Reserved.
2059 +# Ben Goodger <ben@mozilla.org>
2060 +# Josh Aas <josh@mozilla.com>
2062 +# Alternatively, the contents of this file may be used under the terms of
2063 +# either the GNU General Public License Version 2 or later (the "GPL"), or
2064 +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2065 +# in which case the provisions of the GPL or the LGPL are applicable instead
2066 +# of those above. If you wish to allow use of your version of this file only
2067 +# under the terms of either the GPL or the LGPL, and not to allow others to
2068 +# use your version of this file under the terms of the MPL, indicate your
2069 +# decision by deleting the provisions above and replace them with the notice
2070 +# and other provisions required by the GPL or the LGPL. If you do not delete
2071 +# the provisions above, a recipient may use your version of this file under
2072 +# the terms of any one of the MPL, the GPL or the LGPL.
2074 +# ***** END LICENSE BLOCK *****
2077 +# This is PrefWindow 6. The Code Could Well Be Ready, Are You?
2079 +# Historical References:
2080 +# PrefWindow V (February 1, 2003)
2081 +# PrefWindow IV (April 24, 2000)
2082 +# PrefWindow III (January 6, 2000)
2083 +# PrefWindow II (???)
2084 +# PrefWindow I (June 4, 1999)
2086 diff --git a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
2087 --- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
2088 +++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
2091 #include "nsReadableUtils.h"
2092 #include "nsArrayUtils.h"
2093 #include "prnetdb.h"
2095 #include "nsPrintfCString.h"
2096 #include "nsNetUtil.h"
2097 #include "nsISupportsPrimitives.h"
2098 +#include "nsVoidArray.h"
2099 +#include "nsKDEUtils.h"
2101 class nsUnixSystemProxySettings : public nsISystemProxySettings {
2104 NS_DECL_NSISYSTEMPROXYSETTINGS
2106 nsUnixSystemProxySettings() {}
2110 ~nsUnixSystemProxySettings() {}
2112 nsCOMPtr<nsIGConfService> mGConf;
2113 PRBool IsProxyMode(const char* aMode);
2114 nsresult SetProxyResultFromGConf(const char* aKeyBase, const char* aType, nsACString& aResult);
2115 nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult);
2116 + nsresult GetProxyFromKDE(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult);
2119 NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
2122 nsUnixSystemProxySettings::Init()
2124 // If this is a GNOME session, load gconf and try to use its preferences.
2125 @@ -407,16 +410,19 @@ nsUnixSystemProxySettings::GetProxyForUR
2127 rv = aURI->GetHost(host);
2128 NS_ENSURE_SUCCESS(rv, rv);
2131 rv = aURI->GetPort(&port);
2132 NS_ENSURE_SUCCESS(rv, rv);
2134 + if( nsKDEUtils::kdeSupport())
2135 + return GetProxyFromKDE( scheme, host, port, aResult );
2138 return GetProxyFromEnvironment(scheme, host, port, aResult);
2140 return GetProxyFromGConf(scheme, host, port, aResult);
2143 #define NS_UNIXSYSTEMPROXYSERVICE_CID /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\
2144 { 0x0fa3158c, 0xd5a7, 0x43de, \
2145 @@ -437,8 +443,34 @@ static const mozilla::Module::ContractID
2147 static const mozilla::Module kUnixProxyModule = {
2148 mozilla::Module::kVersion,
2153 NSMODULE_DEFN(nsUnixProxyModule) = &kUnixProxyModule;
2156 +nsUnixSystemProxySettings::GetProxyFromKDE(const nsACString& aScheme,
2157 + const nsACString& aHost,
2159 + nsACString& aResult)
2161 + nsCAutoString url;
2168 + url += nsPrintfCString("%d", aPort);
2170 + nsCStringArray command;
2171 + command.AppendCString( NS_LITERAL_CSTRING( "GETPROXY" ));
2172 + command.AppendCString( url );
2173 + nsCStringArray result;
2174 + if( !nsKDEUtils::command( command, &result ) || result.Count() != 1 )
2175 + return NS_ERROR_FAILURE;
2176 + aResult = *result[ 0 ];
2180 diff --git a/toolkit/xre/Makefile.in b/toolkit/xre/Makefile.in
2181 --- a/toolkit/xre/Makefile.in
2182 +++ b/toolkit/xre/Makefile.in
2183 @@ -94,17 +94,18 @@ EXPORTS = nsWindowsDllInterceptor.h
2185 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
2186 CMMSRCS = nsNativeAppSupportCocoa.mm
2188 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
2189 CPPSRCS += nsNativeAppSupportOS2.cpp
2191 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
2192 -CPPSRCS += nsNativeAppSupportUnix.cpp
2193 +CPPSRCS += nsNativeAppSupportUnix.cpp nsKDEUtils.cpp
2194 +EXPORTS += nsKDEUtils.h
2196 ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
2197 MOCSRCS += moc_nsNativeAppSupportQt.cpp
2199 CPPSRCS += $(MOCSRCS)
2200 CPPSRCS += nsNativeAppSupportQt.cpp
2201 CPPSRCS += nsQAppInstance.cpp
2202 EXPORTS += nsQAppInstance.h
2203 diff --git a/toolkit/xre/nsKDEUtils.cpp b/toolkit/xre/nsKDEUtils.cpp
2204 new file mode 100644
2206 +++ b/toolkit/xre/nsKDEUtils.cpp
2208 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2209 +/* ***** BEGIN LICENSE BLOCK *****
2210 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2212 + * The contents of this file are subject to the Mozilla Public License Version
2213 + * 1.1 (the "License"); you may not use this file except in compliance with
2214 + * the License. You may obtain a copy of the License at
2215 + * http://www.mozilla.org/MPL/
2217 + * Software distributed under the License is distributed on an "AS IS" basis,
2218 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2219 + * for the specific language governing rights and limitations under the
2222 + * The Original Code is Unix Native App Support.
2224 + * The Initial Developer of the Original Code is
2225 + * Mozilla Corporation.
2226 + * Portions created by the Initial Developer are Copyright (C) 2007
2227 + * the Initial Developer. All Rights Reserved.
2231 + * Alternatively, the contents of this file may be used under the terms of
2232 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2233 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2234 + * in which case the provisions of the GPL or the LGPL are applicable instead
2235 + * of those above. If you wish to allow use of your version of this file only
2236 + * under the terms of either the GPL or the LGPL, and not to allow others to
2237 + * use your version of this file under the terms of the MPL, indicate your
2238 + * decision by deleting the provisions above and replace them with the notice
2239 + * and other provisions required by the GPL or the LGPL. If you do not delete
2240 + * the provisions above, a recipient may use your version of this file under
2241 + * the terms of any one of the MPL, the GPL or the LGPL.
2243 + * ***** END LICENSE BLOCK ***** */
2245 +#include "nsKDEUtils.h"
2246 +#include "nsIWidget.h"
2248 +#include <gtk/gtk.h>
2250 +#include <limits.h>
2252 +#include <sys/wait.h>
2253 +#include <unistd.h>
2254 +#include <X11/Xlib.h>
2256 +//#define DEBUG_KDE
2258 +#define KMOZILLAHELPER "kmozillahelper"
2260 +// not need for lib64, it's a binary
2261 +#define KMOZILLAHELPER "/usr/lib/mozilla/kmozillahelper"
2264 +#define KMOZILLAHELPER_VERSION 6
2265 +#define MAKE_STR2( n ) #n
2266 +#define MAKE_STR( n ) MAKE_STR2( n )
2268 +static bool getKdeSession()
2270 + Display* dpy = XOpenDisplay( NULL );
2273 + Atom kde_full_session = XInternAtom( dpy, "KDE_FULL_SESSION", True );
2275 + if( kde_full_session != None )
2278 + if( Atom* props = XListProperties( dpy, DefaultRootWindow( dpy ), &cnt ))
2284 + if( props[ i ] == kde_full_session )
2288 + fprintf( stderr, "KDE SESSION %d\n", kde );
2296 + XCloseDisplay( dpy );
2300 +static bool getKdeSupport()
2302 + nsCStringArray command;
2303 + command.AppendCString( NS_LITERAL_CSTRING( "CHECK" ));
2304 + command.AppendCString( NS_LITERAL_CSTRING( MAKE_STR( KMOZILLAHELPER_VERSION )));
2305 + bool kde = nsKDEUtils::command( command );
2307 + fprintf( stderr, "KDE RUNNING %d\n", kde );
2312 +nsKDEUtils::nsKDEUtils()
2313 + : commandFile( NULL )
2314 + , replyFile( NULL )
2318 +nsKDEUtils::~nsKDEUtils()
2320 +// closeHelper(); not actually useful, exiting will close the fd too
2323 +nsKDEUtils* nsKDEUtils::self()
2325 + static nsKDEUtils s;
2329 +static bool helperRunning = false;
2330 +static bool helperFailed = false;
2332 +bool nsKDEUtils::kdeSession()
2334 + static bool session = getKdeSession();
2338 +bool nsKDEUtils::kdeSupport()
2340 + static bool support = kdeSession() && getKdeSupport();
2341 + return support && helperRunning;
2344 +struct nsKDECommandData
2347 + nsCStringArray* output;
2352 +static gboolean kdeReadFunc( GIOChannel*, GIOCondition, gpointer data )
2354 + nsKDECommandData* p = static_cast< nsKDECommandData* >( data );
2355 + char buf[ 8192 ]; // TODO big enough
2356 + bool command_done = false;
2357 + bool command_failed = false;
2358 + while( !command_done && !command_failed && fgets( buf, 8192, p->file ) != NULL )
2359 + { // TODO what if the kernel splits a line into two chunks?
2361 +// fprintf( stderr, "READ: %s %d\n", buf, feof( p->file ));
2363 + if( char* eol = strchr( buf, '\n' ))
2365 + command_done = ( strcmp( buf, "\\1" ) == 0 );
2366 + command_failed = ( strcmp( buf, "\\0" ) == 0 );
2367 + nsCAutoString line( buf );
2368 + line.ReplaceSubstring( "\\n", "\n" );
2369 + line.ReplaceSubstring( "\\" "\\", "\\" ); // \\ -> \ , i.e. unescape
2370 + if( p->output && !( command_done || command_failed ))
2371 + p->output->AppendCString( nsCString( buf )); // TODO utf8?
2373 + bool quit = false;
2374 + if( feof( p->file ) || command_failed )
2377 + p->success = false;
2379 + if( command_done )
2380 + { // reading one reply finished
2382 + p->success = true;
2387 + g_main_loop_quit( p->loop );
2393 +bool nsKDEUtils::command( const nsCStringArray& command, nsCStringArray* output )
2395 + return self()->internalCommand( command, NULL, false, output );
2398 +bool nsKDEUtils::commandBlockUi( const nsCStringArray& command, const GtkWindow* parent, nsCStringArray* output )
2400 + return self()->internalCommand( command, parent, true, output );
2403 +bool nsKDEUtils::internalCommand( const nsCStringArray& command, const GtkWindow* parent, bool blockUi,
2404 + nsCStringArray* output )
2406 + if( !startHelper())
2408 + feedCommand( command );
2409 + // do not store the data in 'this' but in extra structure, just in case there
2410 + // is reentrancy (can there be? the event loop is re-entered)
2411 + nsKDECommandData data;
2412 + data.file = replyFile;
2413 + data.output = output;
2414 + data.success = false;
2417 + data.loop = g_main_loop_new( NULL, FALSE );
2418 + GtkWidget* window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
2419 + if( parent && parent->group )
2420 + gtk_window_group_add_window( parent->group, GTK_WINDOW( window ));
2421 + gtk_widget_realize( window );
2422 + gtk_widget_set_sensitive( window, TRUE );
2423 + gtk_grab_add( window );
2424 + GIOChannel* channel = g_io_channel_unix_new( fileno( data.file ));
2425 + g_io_add_watch( channel, static_cast< GIOCondition >( G_IO_IN | G_IO_ERR | G_IO_HUP ), kdeReadFunc, &data );
2426 + g_io_channel_unref( channel );
2427 + g_main_loop_run( data.loop );
2428 + g_main_loop_unref( data.loop );
2429 + gtk_grab_remove( window );
2430 + gtk_widget_destroy( window );
2435 + while( kdeReadFunc( NULL, static_cast< GIOCondition >( 0 ), &data ))
2438 + return data.success;
2441 +bool nsKDEUtils::startHelper()
2443 + if( helperRunning )
2445 + if( helperFailed )
2447 + helperFailed = true;
2448 + int fdcommand[ 2 ];
2450 + if( pipe( fdcommand ) < 0 )
2452 + if( pipe( fdreply ) < 0 )
2454 + close( fdcommand[ 0 ] );
2455 + close( fdcommand[ 1 ] );
2458 + char* args[ 2 ] = { const_cast< char* >( KMOZILLAHELPER ), NULL };
2463 + close( fdcommand[ 0 ] );
2464 + close( fdcommand[ 1 ] );
2465 + close( fdreply[ 0 ] );
2466 + close( fdreply[ 1 ] );
2471 + if( dup2( fdcommand[ 0 ], STDIN_FILENO ) < 0 )
2473 + if( dup2( fdreply[ 1 ], STDOUT_FILENO ) < 0 )
2475 + int maxfd = 1024; // close all other fds
2477 + if( getrlimit( RLIMIT_NOFILE, &rl ) == 0 )
2478 + maxfd = rl.rlim_max;
2484 + execvp( KMOZILLAHELPER, args );
2486 + execv( KMOZILLAHELPER, args );
2488 + _exit( 1 ); // failed
2490 + default: // parent
2492 + commandFile = fdopen( fdcommand[ 1 ], "w" );
2493 + replyFile = fdopen( fdreply[ 0 ], "r" );
2494 + close( fdcommand[ 0 ] );
2495 + close( fdreply[ 1 ] );
2496 + if( commandFile == NULL || replyFile == NULL )
2501 + // ok, helper ready, getKdeRunning() will check if it works
2504 + helperFailed = false;
2505 + helperRunning = true;
2509 +void nsKDEUtils::closeHelper()
2511 + if( commandFile != NULL )
2512 + fclose( commandFile ); // this will also make the helper quit
2513 + if( replyFile != NULL )
2514 + fclose( replyFile );
2515 + helperRunning = false;
2518 +void nsKDEUtils::feedCommand( const nsCStringArray& command )
2521 + i < command.Count();
2524 + nsCString line = *command[ i ];
2525 + line.ReplaceSubstring( "\\", "\\" "\\" ); // \ -> \\ , i.e. escape
2526 + line.ReplaceSubstring( "\n", "\\n" );
2528 + fprintf( stderr, "COMM: %s\n", line.get());
2530 + fputs( line.get(), commandFile );
2531 + fputs( "\n", commandFile );
2533 + fputs( "\\E\n", commandFile ); // done as \E, so it cannot happen in normal data
2534 + fflush( commandFile );
2536 diff --git a/toolkit/xre/nsKDEUtils.h b/toolkit/xre/nsKDEUtils.h
2537 new file mode 100644
2539 +++ b/toolkit/xre/nsKDEUtils.h
2541 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2543 + * ***** BEGIN LICENSE BLOCK *****
2544 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2546 + * The contents of this file are subject to the Mozilla Public License Version
2547 + * 1.1 (the "License"); you may not use this file except in compliance with
2548 + * the License. You may obtain a copy of the License at
2549 + * http://www.mozilla.org/MPL/
2551 + * Software distributed under the License is distributed on an "AS IS" basis,
2552 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2553 + * for the specific language governing rights and limitations under the
2556 + * The Original Code is Mozilla Communicator client code.
2558 + * The Initial Developer of the Original Code is
2559 + * Netscape Communications Corporation.
2560 + * Portions created by the Initial Developer are Copyright (C) 1998
2561 + * the Initial Developer. All Rights Reserved.
2565 + * Alternatively, the contents of this file may be used under the terms of
2566 + * either of the GNU General Public License Version 2 or later (the "GPL"),
2567 + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2568 + * in which case the provisions of the GPL or the LGPL are applicable instead
2569 + * of those above. If you wish to allow use of your version of this file only
2570 + * under the terms of either the GPL or the LGPL, and not to allow others to
2571 + * use your version of this file under the terms of the MPL, indicate your
2572 + * decision by deleting the provisions above and replace them with the notice
2573 + * and other provisions required by the GPL or the LGPL. If you do not delete
2574 + * the provisions above, a recipient may use your version of this file under
2575 + * the terms of any one of the MPL, the GPL or the LGPL.
2577 + * ***** END LICENSE BLOCK ***** */
2579 +#ifndef nsKDEUtils_h__
2580 +#define nsKDEUtils_h__
2582 +#include "nsStringGlue.h"
2583 +#include "nsVoidArray.h"
2586 +typedef struct _GtkWindow GtkWindow;
2588 +class NS_EXPORT nsKDEUtils
2591 + /* Returns true if running inside a KDE session (regardless of whether there is KDE
2592 + support available for Firefox). This should be used e.g. when determining
2593 + dialog button order but not for code that requires the KDE support. */
2594 + static bool kdeSession();
2595 + /* Returns true if running inside a KDE session and KDE support is available
2596 + for Firefox. This should be used everywhere where the external helper is needed. */
2597 + static bool kdeSupport();
2598 + /* Executes the given helper command, returns true if helper returned success. */
2599 + static bool command( const nsCStringArray& command, nsCStringArray* output = NULL );
2600 + /* Like command(), but additionally blocks the parent widget like if there was
2601 + a modal dialog shown and enters the event loop (i.e. there are still paint updates,
2602 + this is for commands that take long). */
2603 + static bool commandBlockUi( const nsCStringArray& command, const GtkWindow* parent, nsCStringArray* output = NULL );
2607 + static nsKDEUtils* self();
2608 + bool startHelper();
2609 + void closeHelper();
2610 + void feedCommand( const nsCStringArray& command );
2611 + bool internalCommand( const nsCStringArray& command, const GtkWindow* parent, bool isParent,
2612 + nsCStringArray* output );
2613 + FILE* commandFile;
2617 +#endif // nsKDEUtils
2618 diff --git a/uriloader/exthandler/Makefile.in b/uriloader/exthandler/Makefile.in
2619 --- a/uriloader/exthandler/Makefile.in
2620 +++ b/uriloader/exthandler/Makefile.in
2621 @@ -88,18 +88,19 @@ LOCAL_INCLUDES = -I$(srcdir)
2622 LOCAL_INCLUDES += -I$(topsrcdir)/dom/base \
2623 -I$(topsrcdir)/dom/ipc \
2624 -I$(topsrcdir)/content/base/src \
2625 -I$(topsrcdir)/content/events/src \
2626 -I$(topsrcdir)/netwerk/base/src \
2627 -I$(topsrcdir)/netwerk/protocol/http
2629 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
2630 -OSHELPER += nsGNOMERegistry.cpp
2631 +OSHELPER += nsCommonRegistry.cpp nsGNOMERegistry.cpp nsKDERegistry.cpp
2632 OSHELPER += nsMIMEInfoUnix.cpp
2633 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
2636 ifeq ($(MOZ_WIDGET_TOOLKIT),android)
2637 OSHELPER += nsMIMEInfoAndroid.cpp
2638 OSHELPER += nsAndroidHandlerApp.cpp
2639 OSHELPER += nsExternalSharingAppService.cpp
2640 EXPORTS += nsExternalSharingAppService.h
2641 OSHELPER += nsExternalURLHandlerService.cpp
2642 diff --git a/uriloader/exthandler/unix/nsCommonRegistry.cpp b/uriloader/exthandler/unix/nsCommonRegistry.cpp
2643 new file mode 100644
2645 +++ b/uriloader/exthandler/unix/nsCommonRegistry.cpp
2647 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2648 +/* ***** BEGIN LICENSE BLOCK *****
2649 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2651 + * The contents of this file are subject to the Mozilla Public License Version
2652 + * 1.1 (the "License"); you may not use this file except in compliance with
2653 + * the License. You may obtain a copy of the License at
2654 + * http://www.mozilla.org/MPL/
2656 + * Software distributed under the License is distributed on an "AS IS" basis,
2657 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2658 + * for the specific language governing rights and limitations under the
2661 + * The Original Code is the GNOME helper app implementation.
2663 + * The Initial Developer of the Original Code is
2664 + * IBM Corporation.
2665 + * Portions created by the Initial Developer are Copyright (C) 2003
2666 + * the Initial Developer. All Rights Reserved.
2669 + * Brian Ryner <bryner@brianryner.com> (Original Author)
2671 + * Alternatively, the contents of this file may be used under the terms of
2672 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2673 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2674 + * in which case the provisions of the GPL or the LGPL are applicable instead
2675 + * of those above. If you wish to allow use of your version of this file only
2676 + * under the terms of either the GPL or the LGPL, and not to allow others to
2677 + * use your version of this file under the terms of the MPL, indicate your
2678 + * decision by deleting the provisions above and replace them with the notice
2679 + * and other provisions required by the GPL or the LGPL. If you do not delete
2680 + * the provisions above, a recipient may use your version of this file under
2681 + * the terms of any one of the MPL, the GPL or the LGPL.
2683 + * ***** END LICENSE BLOCK ***** */
2685 +#include "nsCommonRegistry.h"
2687 +#include "nsGNOMERegistry.h"
2688 +#include "nsKDERegistry.h"
2689 +#include "nsString.h"
2690 +#include "nsVoidArray.h"
2691 +#include "nsKDEUtils.h"
2693 +/* static */ PRBool
2694 +nsCommonRegistry::HandlerExists(const char *aProtocolScheme)
2696 + if( nsKDEUtils::kdeSupport())
2697 + return nsKDERegistry::HandlerExists( aProtocolScheme );
2698 + return nsGNOMERegistry::HandlerExists( aProtocolScheme );
2701 +/* static */ nsresult
2702 +nsCommonRegistry::LoadURL(nsIURI *aURL)
2704 + if( nsKDEUtils::kdeSupport())
2705 + return nsKDERegistry::LoadURL( aURL );
2706 + return nsGNOMERegistry::LoadURL( aURL );
2710 +nsCommonRegistry::GetAppDescForScheme(const nsACString& aScheme,
2713 + if( nsKDEUtils::kdeSupport())
2714 + return nsKDERegistry::GetAppDescForScheme( aScheme, aDesc );
2715 + return nsGNOMERegistry::GetAppDescForScheme( aScheme, aDesc );
2719 +/* static */ already_AddRefed<nsMIMEInfoBase>
2720 +nsCommonRegistry::GetFromExtension(const nsACString& aFileExt)
2722 + if( nsKDEUtils::kdeSupport())
2723 + return nsKDERegistry::GetFromExtension( aFileExt );
2724 + return nsGNOMERegistry::GetFromExtension( aFileExt );
2727 +/* static */ already_AddRefed<nsMIMEInfoBase>
2728 +nsCommonRegistry::GetFromType(const nsACString& aMIMEType)
2730 + if( nsKDEUtils::kdeSupport())
2731 + return nsKDERegistry::GetFromType( aMIMEType );
2732 + return nsGNOMERegistry::GetFromType( aMIMEType );
2734 diff --git a/uriloader/exthandler/unix/nsCommonRegistry.h b/uriloader/exthandler/unix/nsCommonRegistry.h
2735 new file mode 100644
2737 +++ b/uriloader/exthandler/unix/nsCommonRegistry.h
2739 +/* ***** BEGIN LICENSE BLOCK *****
2740 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2742 + * The contents of this file are subject to the Mozilla Public License Version
2743 + * 1.1 (the "License"); you may not use this file except in compliance with
2744 + * the License. You may obtain a copy of the License at
2745 + * http://www.mozilla.org/MPL/
2747 + * Software distributed under the License is distributed on an "AS IS" basis,
2748 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2749 + * for the specific language governing rights and limitations under the
2752 + * The Original Code is the GNOME helper app implementation.
2754 + * The Initial Developer of the Original Code is
2755 + * IBM Corporation.
2756 + * Portions created by the Initial Developer are Copyright (C) 2003
2757 + * the Initial Developer. All Rights Reserved.
2760 + * Brian Ryner <bryner@brianryner.com> (Original Author)
2762 + * Alternatively, the contents of this file may be used under the terms of
2763 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2764 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2765 + * in which case the provisions of the GPL or the LGPL are applicable instead
2766 + * of those above. If you wish to allow use of your version of this file only
2767 + * under the terms of either the GPL or the LGPL, and not to allow others to
2768 + * use your version of this file under the terms of the MPL, indicate your
2769 + * decision by deleting the provisions above and replace them with the notice
2770 + * and other provisions required by the GPL or the LGPL. If you do not delete
2771 + * the provisions above, a recipient may use your version of this file under
2772 + * the terms of any one of the MPL, the GPL or the LGPL.
2774 + * ***** END LICENSE BLOCK ***** */
2776 +#include "nsIURI.h"
2777 +#include "nsCOMPtr.h"
2779 +class nsMIMEInfoBase;
2781 +class nsCommonRegistry
2784 + static PRBool HandlerExists(const char *aProtocolScheme);
2786 + static nsresult LoadURL(nsIURI *aURL);
2788 + static void GetAppDescForScheme(const nsACString& aScheme,
2789 + nsAString& aDesc);
2791 + static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt);
2793 + static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType);
2795 diff --git a/uriloader/exthandler/unix/nsKDERegistry.cpp b/uriloader/exthandler/unix/nsKDERegistry.cpp
2796 new file mode 100644
2798 +++ b/uriloader/exthandler/unix/nsKDERegistry.cpp
2800 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2801 +/* ***** BEGIN LICENSE BLOCK *****
2802 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2804 + * The contents of this file are subject to the Mozilla Public License Version
2805 + * 1.1 (the "License"); you may not use this file except in compliance with
2806 + * the License. You may obtain a copy of the License at
2807 + * http://www.mozilla.org/MPL/
2809 + * Software distributed under the License is distributed on an "AS IS" basis,
2810 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2811 + * for the specific language governing rights and limitations under the
2814 + * The Original Code is the GNOME helper app implementation.
2816 + * The Initial Developer of the Original Code is
2817 + * IBM Corporation.
2818 + * Portions created by the Initial Developer are Copyright (C) 2003
2819 + * the Initial Developer. All Rights Reserved.
2822 + * Brian Ryner <bryner@brianryner.com> (Original Author)
2824 + * Alternatively, the contents of this file may be used under the terms of
2825 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2826 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2827 + * in which case the provisions of the GPL or the LGPL are applicable instead
2828 + * of those above. If you wish to allow use of your version of this file only
2829 + * under the terms of either the GPL or the LGPL, and not to allow others to
2830 + * use your version of this file under the terms of the MPL, indicate your
2831 + * decision by deleting the provisions above and replace them with the notice
2832 + * and other provisions required by the GPL or the LGPL. If you do not delete
2833 + * the provisions above, a recipient may use your version of this file under
2834 + * the terms of any one of the MPL, the GPL or the LGPL.
2836 + * ***** END LICENSE BLOCK ***** */
2838 +#include "nsKDERegistry.h"
2839 +#include "prlink.h"
2841 +#include "nsString.h"
2842 +#include "nsILocalFile.h"
2843 +#include "nsMIMEInfoUnix.h"
2844 +#include "nsAutoPtr.h"
2845 +#include "nsKDEUtils.h"
2847 +/* static */ PRBool
2848 +nsKDERegistry::HandlerExists(const char *aProtocolScheme)
2850 + nsCStringArray command;
2851 + command.AppendCString( NS_LITERAL_CSTRING( "HANDLEREXISTS" ));
2852 + command.AppendCString( nsCAutoString( aProtocolScheme ));
2853 + return nsKDEUtils::command( command );
2856 +/* static */ nsresult
2857 +nsKDERegistry::LoadURL(nsIURI *aURL)
2859 + nsCStringArray command;
2860 + command.AppendCString( NS_LITERAL_CSTRING( "OPEN" ));
2862 + aURL->GetSpec( url );
2863 + command.AppendCString( url );
2864 + return nsKDEUtils::command( command );
2868 +nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme,
2871 + nsCStringArray command;
2872 + command.AppendCString( NS_LITERAL_CSTRING( "GETAPPDESCFORSCHEME" ));
2873 + command.AppendCString( aScheme );
2874 + nsCStringArray output;
2875 + if( nsKDEUtils::command( command, &output ) && output.Count() == 1 )
2876 + CopyUTF8toUTF16( *output[ 0 ], aDesc );
2880 +/* static */ already_AddRefed<nsMIMEInfoBase>
2881 +nsKDERegistry::GetFromExtension(const nsACString& aFileExt)
2883 + NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot");
2884 + nsCStringArray command;
2885 + command.AppendCString( NS_LITERAL_CSTRING( "GETFROMEXTENSION" ));
2886 + command.AppendCString( aFileExt );
2887 + return GetFromHelper( command );
2890 +/* static */ already_AddRefed<nsMIMEInfoBase>
2891 +nsKDERegistry::GetFromType(const nsACString& aMIMEType)
2893 + nsCStringArray command;
2894 + command.AppendCString( NS_LITERAL_CSTRING( "GETFROMTYPE" ));
2895 + command.AppendCString( aMIMEType );
2896 + return GetFromHelper( command );
2899 +/* static */ already_AddRefed<nsMIMEInfoBase>
2900 +nsKDERegistry::GetFromHelper(const nsCStringArray& command)
2902 + nsCStringArray output;
2903 + if( nsKDEUtils::command( command, &output ) && output.Count() == 3 )
2905 + nsCString mimetype = *output[ 0 ];
2906 + nsRefPtr<nsMIMEInfoUnix> mimeInfo = new nsMIMEInfoUnix( mimetype );
2907 + NS_ENSURE_TRUE(mimeInfo, nsnull);
2908 + nsCString description = *output[ 1 ];
2909 + mimeInfo->SetDescription(NS_ConvertUTF8toUTF16(description));
2910 + nsCString handlerAppName = *output[ 2 ];
2911 + mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUTF16(handlerAppName));
2912 + mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault);
2913 + nsMIMEInfoBase* retval;
2914 + NS_ADDREF((retval = mimeInfo));
2919 diff --git a/uriloader/exthandler/unix/nsKDERegistry.h b/uriloader/exthandler/unix/nsKDERegistry.h
2920 new file mode 100644
2922 +++ b/uriloader/exthandler/unix/nsKDERegistry.h
2924 +/* ***** BEGIN LICENSE BLOCK *****
2925 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2927 + * The contents of this file are subject to the Mozilla Public License Version
2928 + * 1.1 (the "License"); you may not use this file except in compliance with
2929 + * the License. You may obtain a copy of the License at
2930 + * http://www.mozilla.org/MPL/
2932 + * Software distributed under the License is distributed on an "AS IS" basis,
2933 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2934 + * for the specific language governing rights and limitations under the
2937 + * The Original Code is the GNOME helper app implementation.
2939 + * The Initial Developer of the Original Code is
2940 + * IBM Corporation.
2941 + * Portions created by the Initial Developer are Copyright (C) 2003
2942 + * the Initial Developer. All Rights Reserved.
2945 + * Brian Ryner <bryner@brianryner.com> (Original Author)
2947 + * Alternatively, the contents of this file may be used under the terms of
2948 + * either the GNU General Public License Version 2 or later (the "GPL"), or
2949 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2950 + * in which case the provisions of the GPL or the LGPL are applicable instead
2951 + * of those above. If you wish to allow use of your version of this file only
2952 + * under the terms of either the GPL or the LGPL, and not to allow others to
2953 + * use your version of this file under the terms of the MPL, indicate your
2954 + * decision by deleting the provisions above and replace them with the notice
2955 + * and other provisions required by the GPL or the LGPL. If you do not delete
2956 + * the provisions above, a recipient may use your version of this file under
2957 + * the terms of any one of the MPL, the GPL or the LGPL.
2959 + * ***** END LICENSE BLOCK ***** */
2961 +#include "nsIURI.h"
2962 +#include "nsCOMPtr.h"
2964 +class nsMIMEInfoBase;
2965 +class nsCAutoString;
2966 +class nsCStringArray;
2968 +class nsKDERegistry
2971 + static PRBool HandlerExists(const char *aProtocolScheme);
2973 + static nsresult LoadURL(nsIURI *aURL);
2975 + static void GetAppDescForScheme(const nsACString& aScheme,
2976 + nsAString& aDesc);
2978 + static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt);
2980 + static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType);
2982 + static already_AddRefed<nsMIMEInfoBase> GetFromHelper(const nsCStringArray& command);
2985 diff --git a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp
2986 --- a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp
2987 +++ b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp
2990 #if (MOZ_ENABLE_CONTENTACTION)
2991 #include <contentaction/contentaction.h>
2992 #include "nsContentHandlerApp.h"
2996 #include "nsMIMEInfoUnix.h"
2997 -#include "nsGNOMERegistry.h"
2998 +#include "nsCommonRegistry.h"
2999 #include "nsIGIOService.h"
3000 #include "nsNetCID.h"
3001 #include "nsIIOService.h"
3002 #include "nsIGnomeVFSService.h"
3003 #include "nsAutoPtr.h"
3004 #ifdef MOZ_ENABLE_DBUS
3005 #include "nsDBusHandlerApp.h"
3007 +#if defined(XP_UNIX) && !defined(XP_MACOSX)
3008 +#include "nsKDEUtils.h"
3012 nsMIMEInfoUnix::LoadUriInternal(nsIURI * aURI)
3014 - nsresult rv = nsGNOMERegistry::LoadURL(aURI);
3015 + nsresult rv = nsCommonRegistry::LoadURL(aURI);
3017 #if (MOZ_PLATFORM_MAEMO == 5) && defined (MOZ_ENABLE_GNOMEVFS)
3019 HildonURIAction *action = hildon_uri_get_default_action(mSchemeOrType.get(), nsnull);
3022 aURI->GetAsciiSpec(spec);
3023 if (hildon_uri_open(spec.get(), action, nsnull))
3024 @@ -95,22 +98,22 @@ nsMIMEInfoUnix::LoadUriInternal(nsIURI *
3030 nsMIMEInfoUnix::GetHasDefaultHandler(PRBool *_retval)
3032 *_retval = PR_FALSE;
3033 - nsRefPtr<nsMIMEInfoBase> mimeInfo = nsGNOMERegistry::GetFromType(mSchemeOrType);
3034 + nsRefPtr<nsMIMEInfoBase> mimeInfo = nsCommonRegistry::GetFromType(mSchemeOrType);
3037 nsresult rv = GetPrimaryExtension(ext);
3038 if (NS_SUCCEEDED(rv)) {
3039 - mimeInfo = nsGNOMERegistry::GetFromExtension(ext);
3040 + mimeInfo = nsCommonRegistry::GetFromExtension(ext);
3049 @@ -153,16 +156,33 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(ns
3050 ContentAction::Action::defaultActionForFile(uri, QString(mSchemeOrType.get()));
3051 if (action.isValid()) {
3055 return NS_ERROR_FAILURE;
3058 + if( nsKDEUtils::kdeSupport()) {
3060 + if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) {
3061 + nsCStringArray command;
3062 + command.AppendCString( NS_LITERAL_CSTRING( "OPEN" ));
3063 + command.AppendCString( nativePath );
3064 + command.AppendCString( NS_LITERAL_CSTRING( "MIMETYPE" ));
3065 + command.AppendCString( mSchemeOrType );
3066 + if( nsKDEUtils::command( command ))
3069 + if (!mDefaultApplication)
3070 + return NS_ERROR_FILE_NOT_FOUND;
3072 + return LaunchWithIProcess(mDefaultApplication, nativePath);
3075 nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
3076 nsCAutoString uriSpec;
3078 // nsGIOMimeApp->Launch wants a URI string instead of local file
3080 nsCOMPtr<nsIIOService> ioservice = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
3081 NS_ENSURE_SUCCESS(rv, rv);
3082 nsCOMPtr<nsIURI> uri;
3083 @@ -180,17 +200,17 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(ns
3084 /* Fallback to GnomeVFS */
3085 nsCOMPtr<nsIGnomeVFSMimeApp> app;
3086 if (NS_SUCCEEDED(gnomevfs->GetAppForMimeType(mSchemeOrType, getter_AddRefs(app))) && app)
3087 return app->Launch(nativePath);
3090 // If we haven't got an app we try to get a valid one by searching for the
3091 // extension mapped type
3092 - nsRefPtr<nsMIMEInfoBase> mimeInfo = nsGNOMERegistry::GetFromExtension(nativePath);
3093 + nsRefPtr<nsMIMEInfoBase> mimeInfo = nsCommonRegistry::GetFromExtension(nativePath);
3096 mimeInfo->GetType(type);
3098 nsCOMPtr<nsIGIOMimeApp> app;
3099 if (NS_SUCCEEDED(giovfs->GetAppForMimeType(type, getter_AddRefs(app))) && app)
3100 return app->Launch(uriSpec);
3101 } else if (gnomevfs) {
3102 diff --git a/uriloader/exthandler/unix/nsOSHelperAppService.cpp b/uriloader/exthandler/unix/nsOSHelperAppService.cpp
3103 --- a/uriloader/exthandler/unix/nsOSHelperAppService.cpp
3104 +++ b/uriloader/exthandler/unix/nsOSHelperAppService.cpp
3106 #if defined(MOZ_ENABLE_CONTENTACTION)
3107 #include <contentaction/contentaction.h>
3111 #include "nsOSHelperAppService.h"
3112 #include "nsMIMEInfoUnix.h"
3113 #ifdef MOZ_WIDGET_GTK2
3114 -#include "nsGNOMERegistry.h"
3115 +#include "nsCommonRegistry.h"
3117 #include "nsISupports.h"
3118 #include "nsString.h"
3119 #include "nsReadableUtils.h"
3120 #include "nsUnicharUtils.h"
3121 #include "nsXPIDLString.h"
3123 #include "nsIFileStreams.h"
3124 @@ -1191,29 +1191,29 @@ nsresult nsOSHelperAppService::OSProtoco
3125 ContentAction::Action::defaultActionForScheme(QString(aProtocolScheme) + ':');
3127 if (action.isValid())
3128 *aHandlerExists = PR_TRUE;
3131 #ifdef MOZ_WIDGET_GTK2
3132 // Check the GConf registry for a protocol handler
3133 - *aHandlerExists = nsGNOMERegistry::HandlerExists(aProtocolScheme);
3134 + *aHandlerExists = nsCommonRegistry::HandlerExists(aProtocolScheme);
3135 #if (MOZ_PLATFORM_MAEMO == 5) && defined (MOZ_ENABLE_GNOMEVFS)
3136 *aHandlerExists = nsMIMEInfoUnix::HandlerExists(aProtocolScheme);
3143 NS_IMETHODIMP nsOSHelperAppService::GetApplicationDescription(const nsACString& aScheme, nsAString& _retval)
3145 #ifdef MOZ_WIDGET_GTK2
3146 - nsGNOMERegistry::GetAppDescForScheme(aScheme, _retval);
3147 + nsCommonRegistry::GetAppDescForScheme(aScheme, _retval);
3148 return _retval.IsEmpty() ? NS_ERROR_NOT_AVAILABLE : NS_OK;
3150 return NS_ERROR_NOT_AVAILABLE;
3154 nsresult nsOSHelperAppService::GetFileTokenForPath(const PRUnichar * platformAppPath, nsIFile ** aFile)
3156 @@ -1299,17 +1299,17 @@ nsOSHelperAppService::GetFromExtension(c
3158 mime_types_description,
3161 if (NS_FAILED(rv) || majorType.IsEmpty()) {
3163 #ifdef MOZ_WIDGET_GTK2
3164 LOG(("Looking in GNOME registry\n"));
3165 - nsMIMEInfoBase *gnomeInfo = nsGNOMERegistry::GetFromExtension(aFileExt).get();
3166 + nsMIMEInfoBase *gnomeInfo = nsCommonRegistry::GetFromExtension(aFileExt).get();
3168 LOG(("Got MIMEInfo from GNOME registry\n"));
3173 rv = LookUpTypeAndDescription(NS_ConvertUTF8toUTF16(aFileExt),
3175 @@ -1425,17 +1425,17 @@ nsOSHelperAppService::GetFromType(const
3176 #ifdef MOZ_WIDGET_GTK2
3177 nsMIMEInfoBase *gnomeInfo = nsnull;
3178 if (handler.IsEmpty()) {
3179 // No useful data yet. Check the GNOME registry. Unfortunately, newer
3180 // GNOME versions no longer have type-to-extension mappings, so we might
3181 // get back a MIMEInfo without any extensions set. In that case we'll have
3182 // to look in our mime.types files for the extensions.
3183 LOG(("Looking in GNOME registry\n"));
3184 - gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType).get();
3185 + gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType).get();
3186 if (gnomeInfo && gnomeInfo->HasExtensions()) {
3187 LOG(("Got MIMEInfo from GNOME registry, and it has extensions set\n"));
3193 // Now look up our extensions
3194 diff --git a/widget/src/gtk2/Makefile.in b/widget/src/gtk2/Makefile.in
3195 --- a/widget/src/gtk2/Makefile.in
3196 +++ b/widget/src/gtk2/Makefile.in
3197 @@ -135,11 +135,14 @@ DEFINES += -DCAIRO_GFX
3200 -I$(srcdir)/../xpwidgets \
3201 -I$(srcdir)/../shared \
3202 -I$(topsrcdir)/layout/generic \
3203 -I$(topsrcdir)/layout/xul/base/src \
3204 -I$(topsrcdir)/other-licenses/atk-1.0 \
3207 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
3210 INCLUDES += -I$(srcdir)/../shared/x11
3212 diff --git a/widget/src/gtk2/nsFilePicker.cpp b/widget/src/gtk2/nsFilePicker.cpp
3213 --- a/widget/src/gtk2/nsFilePicker.cpp
3214 +++ b/widget/src/gtk2/nsFilePicker.cpp
3216 * decision by deleting the provisions above and replace them with the notice
3217 * and other provisions required by the GPL or the LGPL. If you do not delete
3218 * the provisions above, a recipient may use your version of this file under
3219 * the terms of any one of the MPL, the GPL or the LGPL.
3221 * ***** END LICENSE BLOCK ***** */
3223 #include <gtk/gtk.h>
3224 +#include <gdk/gdkx.h>
3226 #include "nsIFileURL.h"
3228 #include "nsIWidget.h"
3229 #include "nsILocalFile.h"
3230 #include "nsIStringBundle.h"
3232 #include "nsArrayEnumerator.h"
3234 #include "nsNetUtil.h"
3235 #include "nsReadableUtils.h"
3236 #include "mozcontainer.h"
3241 #include "nsFilePicker.h"
3242 +#include "nsKDEUtils.h"
3244 #if (MOZ_PLATFORM_MAEMO == 5)
3245 #include <hildon-fm-2/hildon/hildon-file-chooser-dialog.h>
3248 #define MAX_PREVIEW_SIZE 180
3250 nsILocalFile *nsFilePicker::mPrevDisplayDirectory = nsnull;
3251 @@ -281,17 +283,19 @@ nsFilePicker::AppendFilters(PRInt32 aFil
3252 return nsBaseFilePicker::AppendFilters(aFilterMask);
3256 nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
3258 if (aFilter.EqualsLiteral("..apps")) {
3259 // No platform specific thing we can do here, really....
3261 + // Unless it's KDE.
3262 + if( mMode != modeOpen || !nsKDEUtils::kdeSupport())
3266 nsCAutoString filter, name;
3267 CopyUTF16toUTF8(aFilter, filter);
3268 CopyUTF16toUTF8(aTitle, name);
3270 mFilters.AppendElement(filter);
3271 mFilterNames.AppendElement(name);
3272 @@ -429,16 +433,19 @@ confirm_overwrite_file(GtkWidget *parent
3273 gtk_widget_destroy(dialog);
3279 nsFilePicker::Show(PRInt16 *aReturn)
3281 + if( nsKDEUtils::kdeSupport())
3282 + return kdeFileDialog( aReturn );
3284 NS_ENSURE_ARG_POINTER(aReturn);
3286 nsXPIDLCString title;
3287 title.Adopt(ToNewUTF8String(mTitle));
3289 GtkWindow *parent_widget = get_gtk_window_for_nsiwidget(mParentWidget);
3291 GtkFileChooserAction action = GetGtkFileChooserAction(mMode);
3292 @@ -579,8 +586,234 @@ nsFilePicker::Show(PRInt16 *aReturn)
3293 *aReturn = nsIFilePicker::returnCancel;
3297 gtk_widget_destroy(file_chooser);
3302 +nsCString nsFilePicker::kdeMakeFilter( int index )
3304 + nsCString buf = mFilters[ index ];
3305 + for( PRUint32 i = 0;
3308 + if( buf[ i ] == ';' ) // KDE separates just using spaces
3309 + buf.SetCharAt( ' ', i );
3310 + if (!mFilterNames[index].IsEmpty())
3313 + buf += mFilterNames[index].get();
3318 +static PRInt32 windowToXid( nsIWidget* widget )
3320 + GtkWindow *parent_widget = get_gtk_window_for_nsiwidget( widget );
3321 + GdkWindow* gdk_window = gtk_widget_get_window( gtk_widget_get_toplevel( GTK_WIDGET( parent_widget )));
3322 + return GDK_WINDOW_XID( gdk_window );
3325 +NS_IMETHODIMP nsFilePicker::kdeFileDialog(PRInt16 *aReturn)
3327 + NS_ENSURE_ARG_POINTER(aReturn);
3329 + if( mMode == modeOpen && mFilters.Length() == 1 && mFilters[ 0 ].EqualsLiteral( "..apps" ))
3330 + return kdeAppsDialog( aReturn );
3332 + nsXPIDLCString title;
3333 + title.Adopt(ToNewUTF8String(mTitle));
3335 + const char* arg = NULL;
3340 + case nsIFilePicker::modeOpen:
3341 + case nsIFilePicker::modeOpenMultiple:
3342 + arg = "GETOPENURL";
3344 + case nsIFilePicker::modeSave:
3345 + arg = "GETSAVEURL";
3347 + case nsIFilePicker::modeGetFolder:
3348 + arg = "GETDIRECTORYURL";
3356 + case nsIFilePicker::modeOpen:
3357 + case nsIFilePicker::modeOpenMultiple:
3358 + arg = "GETOPENFILENAME";
3360 + case nsIFilePicker::modeSave:
3361 + arg = "GETSAVEFILENAME";
3363 + case nsIFilePicker::modeGetFolder:
3364 + arg = "GETDIRECTORYFILENAME";
3369 + nsCAutoString directory;
3370 + if (mDisplayDirectory) {
3371 + mDisplayDirectory->GetNativePath(directory);
3372 + } else if (mPrevDisplayDirectory) {
3373 + mPrevDisplayDirectory->GetNativePath(directory);
3376 + nsCAutoString startdir;
3377 + if (!directory.IsEmpty()) {
3378 + startdir = directory;
3380 + if (mMode == nsIFilePicker::modeSave) {
3381 + if( !startdir.IsEmpty())
3384 + startdir += ToNewUTF8String(mDefault);
3387 + startdir = ToNewUTF8String(mDefault);
3389 + if( startdir.IsEmpty())
3392 + nsCAutoString filters;
3393 + PRInt32 count = mFilters.Length();
3394 + if( count == 0 ) //just in case
3398 + filters = kdeMakeFilter( 0 );
3399 + for (PRInt32 i = 1; i < count; ++i)
3402 + filters += kdeMakeFilter( i );
3406 + nsCStringArray command;
3407 + command.AppendCString( nsCAutoString( arg ));
3408 + command.AppendCString( startdir );
3409 + if( mMode != nsIFilePicker::modeGetFolder )
3411 + command.AppendCString( filters );
3412 + nsCAutoString selected;
3413 + selected.AppendInt( mSelectedType );
3414 + command.AppendCString( selected );
3416 + command.AppendCString( title );
3417 + if( mMode == nsIFilePicker::modeOpenMultiple )
3418 + command.AppendCString( NS_LITERAL_CSTRING( "MULTIPLE" ));
3419 + if( PRInt32 xid = windowToXid( mParentWidget ))
3421 + command.AppendCString( NS_LITERAL_CSTRING( "PARENT" ));
3422 + nsCAutoString parent;
3423 + parent.AppendInt( xid );
3424 + command.AppendCString( parent );
3427 + nsCStringArray output;
3428 + if( nsKDEUtils::commandBlockUi( command, get_gtk_window_for_nsiwidget( mParentWidget ), &output ))
3430 + *aReturn = nsIFilePicker::returnOK;
3432 + if( mMode != nsIFilePicker::modeGetFolder )
3434 + mSelectedType = atoi( output[ 0 ]->get());
3435 + output.RemoveCStringAt( 0 );
3437 + if (mMode == nsIFilePicker::modeOpenMultiple)
3439 + mFileURL.Truncate();
3440 + PRUint32 count = output.Count();
3441 + for( PRUint32 i = 0;
3445 + nsCOMPtr<nsILocalFile> localfile;
3446 + nsresult rv = NS_NewNativeLocalFile( *output[ i ],
3448 + getter_AddRefs(localfile));
3449 + if (NS_SUCCEEDED(rv))
3450 + mFiles.AppendObject(localfile);
3455 + if( output.Count() == 0 )
3456 + mFileURL = nsCString();
3457 + else if( mAllowURLs )
3458 + mFileURL = *output[ 0 ];
3459 + else // GetFile() actually requires it to be url even for local files :-/
3461 + mFileURL = nsCString( "file://" );
3462 + mFileURL.Append( *output[ 0 ] );
3465 + // Remember last used directory.
3466 + nsCOMPtr<nsILocalFile> file;
3467 + GetFile(getter_AddRefs(file));
3469 + nsCOMPtr<nsIFile> dir;
3470 + file->GetParent(getter_AddRefs(dir));
3471 + nsCOMPtr<nsILocalFile> localDir(do_QueryInterface(dir));
3473 + localDir.swap(mPrevDisplayDirectory);
3476 + if (mMode == nsIFilePicker::modeSave)
3478 + nsCOMPtr<nsILocalFile> file;
3479 + GetFile(getter_AddRefs(file));
3482 + PRBool exists = PR_FALSE;
3483 + file->Exists(&exists);
3484 + if (exists) // TODO do overwrite check in the helper app
3485 + *aReturn = nsIFilePicker::returnReplace;
3491 + *aReturn = nsIFilePicker::returnCancel;
3497 +NS_IMETHODIMP nsFilePicker::kdeAppsDialog(PRInt16 *aReturn)
3499 + NS_ENSURE_ARG_POINTER(aReturn);
3501 + nsXPIDLCString title;
3502 + title.Adopt(ToNewUTF8String(mTitle));
3504 + nsCStringArray command;
3505 + command.AppendCString( NS_LITERAL_CSTRING( "APPSDIALOG" ));
3506 + command.AppendCString( title );
3507 + if( PRInt32 xid = windowToXid( mParentWidget ))
3509 + command.AppendCString( NS_LITERAL_CSTRING( "PARENT" ));
3510 + nsCAutoString parent;
3511 + parent.AppendInt( xid );
3512 + command.AppendCString( parent );
3515 + nsCStringArray output;
3516 + if( nsKDEUtils::commandBlockUi( command, get_gtk_window_for_nsiwidget( mParentWidget ), &output ))
3518 + *aReturn = nsIFilePicker::returnOK;
3519 + mFileURL = output.Count() > 0 ? *output[ 0 ] : nsCString();
3523 + *aReturn = nsIFilePicker::returnCancel;
3527 diff --git a/widget/src/gtk2/nsFilePicker.h b/widget/src/gtk2/nsFilePicker.h
3528 --- a/widget/src/gtk2/nsFilePicker.h
3529 +++ b/widget/src/gtk2/nsFilePicker.h
3530 @@ -89,11 +89,17 @@ protected:
3532 nsString mDefaultExtension;
3534 nsTArray<nsCString> mFilters;
3535 nsTArray<nsCString> mFilterNames;
3538 static nsILocalFile *mPrevDisplayDirectory;
3540 + bool kdeRunning();
3541 + bool getKdeRunning();
3542 + NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn);
3543 + NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn);
3544 + nsCString kdeMakeFilter( int index );
3548 diff --git a/xpcom/components/Makefile.in b/xpcom/components/Makefile.in
3549 --- a/xpcom/components/Makefile.in
3550 +++ b/xpcom/components/Makefile.in
3551 @@ -94,10 +94,11 @@ FORCE_STATIC_LIB = 1
3555 include $(topsrcdir)/config/rules.mk
3557 DEFINES += -D_IMPL_NS_COM
3559 ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
3560 +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
3561 CXXFLAGS += $(MOZ_GTK2_CFLAGS)
3563 diff --git a/xpcom/components/ManifestParser.cpp b/xpcom/components/ManifestParser.cpp
3564 --- a/xpcom/components/ManifestParser.cpp
3565 +++ b/xpcom/components/ManifestParser.cpp
3567 #include "nsTextFormatter.h"
3568 #include "nsVersionComparator.h"
3569 #include "nsXPCOMCIDInternal.h"
3571 #include "nsIConsoleService.h"
3572 #include "nsIScriptError.h"
3573 #include "nsIXULAppInfo.h"
3574 #include "nsIXULRuntime.h"
3575 +#include "nsKDEUtils.h"
3577 struct ManifestDirective
3579 const char* directive;
3582 // Some directives should only be delivered for NS_COMPONENT_LOCATION
3584 @@ -430,16 +431,17 @@ ParseManifestCommon(NSLocationType aType
3585 NS_NAMED_LITERAL_STRING(kPlatform, "platform");
3586 NS_NAMED_LITERAL_STRING(kContentAccessible, "contentaccessible");
3587 NS_NAMED_LITERAL_STRING(kApplication, "application");
3588 NS_NAMED_LITERAL_STRING(kAppVersion, "appversion");
3589 NS_NAMED_LITERAL_STRING(kGeckoVersion, "platformversion");
3590 NS_NAMED_LITERAL_STRING(kOs, "os");
3591 NS_NAMED_LITERAL_STRING(kOsVersion, "osversion");
3592 NS_NAMED_LITERAL_STRING(kABI, "abi");
3593 + NS_NAMED_LITERAL_STRING(kDesktop, "desktop");
3596 NS_NAMED_LITERAL_STRING(kXPCNativeWrappers, "xpcnativewrappers");
3599 nsAutoString appVersion;
3600 nsAutoString geckoVersion;
3601 nsAutoString osTarget;
3602 @@ -474,39 +476,44 @@ ParseManifestCommon(NSLocationType aType
3603 CopyUTF8toUTF16(s, abi);
3604 abi.Insert(PRUnichar('_'), 0);
3605 abi.Insert(osTarget, 0);
3610 nsAutoString osVersion;
3611 + nsAutoString desktop;
3613 OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
3614 if (GetVersionEx(&info)) {
3615 nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
3616 info.dwMajorVersion,
3617 info.dwMinorVersion);
3619 + desktop = NS_LITERAL_STRING("win");
3620 #elif defined(MOZ_WIDGET_COCOA)
3621 SInt32 majorVersion, minorVersion;
3622 if ((Gestalt(gestaltSystemVersionMajor, &majorVersion) == noErr) &&
3623 (Gestalt(gestaltSystemVersionMinor, &minorVersion) == noErr)) {
3624 nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
3628 + desktop = NS_LITERAL_STRING("macosx");
3629 #elif defined(MOZ_WIDGET_GTK2)
3630 nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
3633 + desktop = nsKDEUtils::kdeSession() ? NS_LITERAL_STRING("kde") : NS_LITERAL_STRING("gnome");
3634 #elif defined(ANDROID)
3635 if (mozilla::AndroidBridge::Bridge()) {
3636 mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", osVersion);
3638 + desktop = NS_LITERAL_STRING("android");
3641 // Because contracts must be registered after CIDs, we save and process them
3643 nsTArray<CachedDirective> contracts;
3646 char *newline = buf;
3647 @@ -585,24 +592,26 @@ ParseManifestCommon(NSLocationType aType
3648 TriState stAppVersion = eUnspecified;
3649 TriState stGeckoVersion = eUnspecified;
3650 TriState stApp = eUnspecified;
3651 TriState stOsVersion = eUnspecified;
3652 TriState stOs = eUnspecified;
3653 TriState stABI = eUnspecified;
3654 bool platform = false;
3655 bool contentAccessible = false;
3656 + TriState stDesktop = eUnspecified;
3658 while (NULL != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && ok) {
3660 NS_ConvertASCIItoUTF16 wtoken(token);
3662 if (CheckStringFlag(kApplication, wtoken, appID, stApp) ||
3663 CheckStringFlag(kOs, wtoken, osTarget, stOs) ||
3664 CheckStringFlag(kABI, wtoken, abi, stABI) ||
3665 + CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) ||
3666 CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) ||
3667 CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) ||
3668 CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, stGeckoVersion))
3671 if (directive->contentflags &&
3672 (CheckFlag(kPlatform, wtoken, platform) ||
3673 CheckFlag(kContentAccessible, wtoken, contentAccessible)))
3674 @@ -623,16 +632,17 @@ ParseManifestCommon(NSLocationType aType
3679 stAppVersion == eBad ||
3680 stGeckoVersion == eBad ||
3682 stOsVersion == eBad ||
3683 + stDesktop == eBad ||
3687 if (directive->regfunc) {
3688 if (GeckoProcessType_Default != XRE_GetProcessType())
3691 if (!nsChromeRegistry::gChromeRegistry) {
3692 diff --git a/xpcom/io/Makefile.in b/xpcom/io/Makefile.in
3693 --- a/xpcom/io/Makefile.in
3694 +++ b/xpcom/io/Makefile.in
3695 @@ -190,17 +190,17 @@ include $(topsrcdir)/ipc/chromium/chromi
3696 DEFINES += -D_IMPL_NS_COM
3698 ifeq ($(OS_ARCH),Linux)
3699 ifneq (,$(findstring lib64,$(libdir)))
3700 DEFINES += -DHAVE_USR_LIB64_DIR
3704 -LOCAL_INCLUDES += -I..
3705 +LOCAL_INCLUDES += -I.. -I$(topsrcdir)/toolkit/xre
3707 ifeq ($(MOZ_PLATFORM_MAEMO),5)
3708 CFLAGS += $(MOZ_DBUS_CFLAGS)
3709 CXXFLAGS += $(MOZ_DBUS_CFLAGS)
3712 ifdef MOZ_PLATFORM_MAEMO
3713 CFLAGS += $(MOZ_PLATFORM_MAEMO_CFLAGS) $(MOZ_QT_CFLAGS)
3714 diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp
3715 --- a/xpcom/io/nsLocalFileUnix.cpp
3716 +++ b/xpcom/io/nsLocalFileUnix.cpp
3718 #include "nsXPIDLString.h"
3719 #include "prproces.h"
3720 #include "nsIDirectoryEnumerator.h"
3721 #include "nsISimpleEnumerator.h"
3723 #ifdef MOZ_WIDGET_GTK2
3724 #include "nsIGIOService.h"
3725 #include "nsIGnomeVFSService.h"
3726 +#include "nsKDEUtils.h"
3730 #include <Carbon/Carbon.h>
3731 #include "CocoaFileUtils.h"
3733 #include "plbase64.h"
3735 @@ -1785,44 +1786,50 @@ nsLocalFile::SetPersistentDescriptor(con
3736 return InitWithNativePath(aPersistentDescriptor);
3741 nsLocalFile::Reveal()
3743 #ifdef MOZ_WIDGET_GTK2
3744 - nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
3745 - nsCOMPtr<nsIGnomeVFSService> gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
3746 - if (!giovfs && !gnomevfs)
3747 - return NS_ERROR_FAILURE;
3749 + nsCAutoString url;
3751 if (NS_FAILED(IsDirectory(&isDirectory)))
3752 return NS_ERROR_FAILURE;
3756 - return giovfs->ShowURIForInput(mPath);
3758 - /* Fallback to GnomeVFS */
3759 - return gnomevfs->ShowURIForInput(mPath);
3762 nsCOMPtr<nsIFile> parentDir;
3763 nsCAutoString dirPath;
3764 if (NS_FAILED(GetParent(getter_AddRefs(parentDir))))
3765 return NS_ERROR_FAILURE;
3766 if (NS_FAILED(parentDir->GetNativePath(dirPath)))
3767 return NS_ERROR_FAILURE;
3770 - return giovfs->ShowURIForInput(dirPath);
3772 - return gnomevfs->ShowURIForInput(dirPath);
3776 + if(nsKDEUtils::kdeSupport()) {
3777 + nsCStringArray command;
3778 + command.AppendCString( NS_LITERAL_CSTRING( "OPEN" ));
3779 + command.AppendCString( url );
3780 + return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE;
3783 + nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
3784 + nsCOMPtr<nsIGnomeVFSService> gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
3785 + if (!giovfs && !gnomevfs)
3786 + return NS_ERROR_FAILURE;
3789 + return giovfs->ShowURIForInput(url);
3791 + return gnomevfs->ShowURIForInput(url);
3792 #elif defined(XP_MACOSX)
3794 if (NS_SUCCEEDED(GetCFURL(&url))) {
3795 nsresult rv = CocoaFileUtils::RevealFileInFinder(url);
3799 return NS_ERROR_FAILURE;
3800 @@ -1848,16 +1855,23 @@ nsLocalFile::Launch()
3802 if (nsnull == connection)
3803 return NS_ERROR_FAILURE;
3805 if (hildon_mime_open_file(connection, mPath.get()) != kHILDON_SUCCESS)
3806 return NS_ERROR_FAILURE;
3809 + if( nsKDEUtils::kdeSupport()) {
3810 + nsCStringArray command;
3811 + command.AppendCString( NS_LITERAL_CSTRING( "OPEN" ));
3812 + command.AppendCString( mPath );
3813 + return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE;
3816 nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
3817 nsCOMPtr<nsIGnomeVFSService> gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
3819 return giovfs->ShowURIForInput(mPath);
3820 } else if (gnomevfs) {
3821 /* GnomeVFS fallback */
3822 return gnomevfs->ShowURIForInput(mPath);