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